Skip to content

vis133m.py API

bh_molecule.instruments.vis133m

Attributes

Classes

FCPShape

Bases: NamedTuple

Attributes
C: int instance-attribute
F: int instance-attribute
P: int instance-attribute

Vis133M

Minimal loader/processor for VIS-1.33 m data with per-channel wavecal.

This class wraps a FITS data cube produced by the VIS-1.33 m instrument and a per-channel wavelength calibration (CSV or analytic formula). It provides convenient accessors and plotting helpers for frames, channels and pixels, plus simple dark subtraction and time-axis helpers.

Parameters:

Name Type Description Default
fits_path str

Path to a FITS file containing a 3D data cube with shape (F, C, P) (frames, channels, pixels).

required
wavecal str | None

Path to a CSV file containing per-channel wavelength calibration, or None if using explicit formula (slopes, intercepts). The first column must contain channel indices (0-based preferred, 1-based accepted). Remaining columns are wavelength values [nm] per pixel.

None
wavecal_mode (formula, csv)

"formula" (default): compute wavelength from λ(x) = a*x + b + Δλ per channel. If wavecal is a path, load CSV and convert to formulas. "csv": use CSV table directly for pixel→wavelength lookup (legacy).

"formula"
scale float

Multiplicative scale factor applied to the cube data (default 1.0).

1.0
slopes ndarray | None

Per-channel slopes [nm/pixel] for formula mode. Required when wavecal=None and wavecal_mode="formula".

None
intercepts ndarray | None

Per-channel intercepts [nm] for formula mode. Required when wavecal=None and wavecal_mode="formula".

None

Attributes:

Name Type Description
cube ndarray

The data cube of shape (F, C, P).

wl_nm ndarray

Per-channel wavelength array with shape (C, P) in nanometres.

wavecal_shift float

Global wavelength shift Δλ [nm] applied in formula mode.

header dict

FITS header converted to a dict.

exptime float | None

Exposure time read from the FITS header when available.

time_s ndarray | None

Optional time vector in seconds of length F. If unset, frame indices are used for plotting/time axes.

Attributes
axis_legend: dict[str, str] property

Mapping of axis short names to human-readable descriptions.

Returns:

Type Description
dict

Mapping with keys 'F', 'C', 'P' describing the axes.

cube = cube instance-attribute
exptime = self.header.get('EXPTIME') or self.header.get('EXPOSURE') instance-attribute
filename = fits_path instance-attribute
header = dict(hdu.header) instance-attribute
scale = float(scale) instance-attribute
shape property

Return the shape of the internal data cube.

Returns:

Type Description
tuple

Shape (F, C, P) where F is frames, C is channels and P is pixels (wavelength samples).

shape_fcp: FCPShape property

Named shape with axis meanings.

Returns:

Type Description
FCPShape

Named tuple containing F, C and P describing the number of frames, channels and pixels respectively.

time_s = None instance-attribute
wavecal_shift = 0.0 instance-attribute
wl_nm = wl_csv instance-attribute
Functions
apply_cw(cw_nm: float, *, line_name: str | None = None, line_wavelength: float | None = None, peak_pixel: int | None = None, frame_used: int | None = None) -> None

Apply central wavelength and update the wavelength axis.

Regenerates the wavelength calibration from the stored polynomial and the given CW. Updates calibration metadata. Optionally store line info (e.g. from :meth:estimate_cw_from_line) for the report.

Parameters:

Name Type Description Default
cw_nm float

Central wavelength in nm.

required
line_name str | None

Name of the reference line (e.g. "H_gamma") for the report.

None
line_wavelength float | None

Wavelength of the line in nm for the report.

None
peak_pixel int | None

Pixel index used for the estimate (for the report).

None
frame_used int | None

Frame index used (for the report).

None
band(nm_range: tuple[float, float], subtract_dark: bool = True) -> np.ndarray

Sum signal within a wavelength band (per-channel) returning an image of shape (F, C).

Parameters:

Name Type Description Default
nm_range tuple of float

(lo, hi) wavelength range in nanometres (inclusive).

required
subtract_dark bool

If True and a dark is configured via set_dark, subtract the dark from the resulting image (default True).

True

Returns:

Type Description
ndarray

Summed image of shape (F, C) in the same units as the cube multiplied by the current scale.

calibration_report() -> None

Print the wavelength calibration report (for instances from from_files).

channel_stack(channel: int, *, zero_min: bool | None = None) -> np.ndarray

Return the time×pixel stack for a single channel.

Parameters:

Name Type Description Default
channel int

Channel index (0-based).

required

Returns:

Type Description
ndarray

Array of shape (F, P) containing the stack for the channel.

compare_calibration_csv_vs_formula(channel: int) -> tuple[float, float]

Compare CSV and formula calibration for a channel.

Requires that calibration was loaded from CSV. When in csv mode, formula is computed from the same CSV for comparison. Compares only over the pixel range present in the CSV (cube may have more).

Returns:

Name Type Description
max_abs_delta float

max |λ_csv - λ_formula| over pixels.

rmse float

Root-mean-square error between CSV and formula.

compute_wavelength_shift_from_peaks(peak_pixel_old: float, peak_pixel_new: float, channel: int = 0) -> float

Compute wavelength shift Δλ from pixel shifts and channel dispersion.

Δλ = a_c * (peak_pixel_new - peak_pixel_old)

Parameters:

Name Type Description Default
peak_pixel_old float

Peak pixel in reference (old) dataset.

required
peak_pixel_new float

Peak pixel in new dataset.

required
channel int

Channel index for slope (default 0).

0

Returns:

Name Type Description
delta_lambda float

Wavelength shift in nm.

estimate_cw_from_line(peak_pixel: int, *, wavelength: float | None = None, line: str | None = None) -> float

Estimate central wavelength from a known line at a given pixel.

Does not modify the instance. Use :meth:apply_cw to apply the result.

Parameters:

Name Type Description Default
peak_pixel int

Pixel index (data coordinates) where the line is observed.

required
wavelength float | None

Wavelength of the line in nm. One of wavelength or line must be provided.

None
line str | None

Name of the line (e.g. "H_gamma") looked up in :data:bh_molecule.constants.BALMER_LINES_NM. One of wavelength or line must be provided.

None

Returns:

Type Description
float

Estimated CW in nm.

explain() -> None

Print a short human-readable description of the data axes.

This helper is convenient in interactive sessions or notebooks.

frame_image(frame: int, *, zero_min: bool | None = None) -> np.ndarray

Return the channel×pixel image for a single frame.

Parameters:

Name Type Description Default
frame int

Frame index (0-based).

required

Returns:

Type Description
ndarray

Array of shape (C, P) corresponding to the requested frame.

from_files(fits_path: str, *, cw: float | None = None, line: str | float | None = None, scale: float = 1.0, verbose: bool = False) -> Vis133M classmethod

Create a Vis133M instance with polynomial wavelength calibration from JSON.

Loads the FITS cube and the wavecal JSON from package resources. CW must be set explicitly: pass cw (nm) to use a value directly, or pass line (name or wavelength) to record the reference line for later use with :meth:estimate_cw_from_line and :meth:apply_cw. If neither is provided, data are loaded with dispersion only; call :meth:apply_cw after estimating CW.

Parameters:

Name Type Description Default
fits_path str

Path to a FITS file containing a 3D data cube (F, C, P).

required
cw float | None

Central wavelength in nm. If provided, calibration is applied immediately. Mutually exclusive with line.

None
line str | float | None

Reference line: string (e.g. "H_gamma") looked up in :data:bh_molecule.constants.BALMER_LINES_NM, or float (wavelength in nm). Stored for use with :meth:estimate_cw_from_line; does not apply CW by itself.

None
scale float

Multiplicative scale factor (default 1.0).

1.0
verbose bool

If True, print the calibration report after loading (default False).

False

Returns:

Type Description
Vis133M

Instance. If cw was provided, wavelength axis is calibrated.

map_band(nm_range: tuple[float, float], *, subtract_dark: bool = True) -> np.ndarray

Sum signal within a wavelength band (per-channel) returning (F, C).

Parameters:

Name Type Description Default
nm_range tuple of float

(lo, hi) wavelength range in nanometres (inclusive).

required
subtract_dark bool

If True subtract a configured dark (default True).

True

Returns:

Type Description
ndarray

Summed image of shape (F, C).

map_pixel_range(start: int, stop: int, *, subtract_dark: bool = True) -> np.ndarray

Sum over a pixel window returning an (F, C) image.

Parameters:

Name Type Description Default
start int

Start pixel index (inclusive).

required
stop int

Stop pixel index (exclusive).

required
subtract_dark bool

If True subtract a configured dark (default True).

True

Returns:

Type Description
ndarray

Summed image of shape (F, C).

measure_peak(channel: int, pixel_window: tuple[int, int] | None = None, average_frames: bool = True) -> tuple[float, float, float] | None

Fit strongest peak (e.g. H-γ) in a channel spectrum.

Parameters:

Name Type Description Default
channel int

Channel index.

required
pixel_window tuple of int

(start, stop) pixel indices. If None, use full spectrum.

None
average_frames bool

If True, average over frames before fitting (default True).

True

Returns:

Name Type Description
result tuple or None

(peak_pixel, peak_amplitude, sigma) if fit succeeds.

pick_frame(method: str = 'max') -> int

Return the frame index with strongest total signal.

Parameters:

Name Type Description Default
method str

Only "max" is supported: frame with maximum sum over (channel, pixel).

'max'

Returns:

Type Description
int

Frame index (0-based).

pixel_map(pixel: int) -> np.ndarray

Return the frame×channel map at a fixed detector pixel.

Parameters:

Name Type Description Default
pixel int

Pixel index (0-based).

required

Returns:

Type Description
ndarray

Array of shape (F, C) containing values at the given pixel.

plot_band_map(nm_range: tuple[float, float], *, ax=None, cmap=None, cbar_label='intensity', channel_line: int | None = None, require_time: bool = False, subtract_dark: bool = True, log_scale: bool = False, vmin: float | None = None, vmax: float | None = None, colorbar: bool = True)

Plot the result of map_band(nm_range).

Parameters:

Name Type Description Default
nm_range tuple of float

(lo, hi) wavelength range in nanometres.

required

Returns:

Type Description
Axes

The axes containing the image.

See Also map_band, _plot_fc
plot_channel_stack(channel: int, *, ax=None, cmap=None, cbar_label='intensity', time_line: float | None = None, require_time: bool = False, log_scale: bool = False, vmin: float | None = None, vmax: float | None = None)

Plot a channel stack (time × wavelength) as an image.

Parameters:

Name Type Description Default
channel int

Channel index (0-based) to plot.

required
ax Axes | None

Axes to plot into. If None the current axes are used.

None
cmap str | Colormap | None

Colormap to use for the image.

None
cbar_label str

Label for the colorbar (default "intensity").

'intensity'
time_line float | None

Optional vertical line (x coordinate in time units) to indicate a time-of-interest.

None
require_time bool

If True require an explicit time vector (raise if unset).

False

Returns:

Type Description
Axes

The axes containing the image.

plot_pixel_map(pixel: int, *, ax=None, cmap=None, cbar_label='intensity', channel_line: int | None = None, require_time: bool = False, log_scale: bool = False, vmin: float | None = None, vmax: float | None = None)

Plot a frame×channel image for a fixed pixel index.

Parameters:

Name Type Description Default
pixel int

Pixel index (0-based).

required
ax Axes | None

Axes to plot into. If None the current axes are used.

None
cmap str | Colormap | None

Colormap to use for the image.

None
cbar_label str

Label for the colorbar (default "intensity").

'intensity'
channel_line int | None

Optional horizontal line indicating a channel of interest.

None
require_time bool

If True require an explicit time vector (raise if unset).

False

Returns:

Type Description
Axes

The axes containing the image.

plot_pixel_range(start: int, stop: int, *, ax=None, cmap=None, cbar_label='intensity', channel_line: int | None = None, require_time: bool = False, subtract_dark: bool = True, log_scale: bool = False, vmin: float | None = None, vmax: float | None = None)

Plot the result of map_pixel_range(start, stop).

Parameters:

Name Type Description Default
start int

Start pixel index (inclusive).

required
stop int

Stop pixel index (exclusive).

required

Returns:

Type Description
Axes

The axes containing the image.

plot_spectrum(frame: int, channel: int, ax=None, *, zero_min: bool | None = None)

Plot the spectrum at a given frame and channel using Matplotlib.

Parameters:

Name Type Description Default
frame int

Frame index (0-based).

required
channel int

Channel index (0-based).

required
ax Axes | None

Axes to plot into. If None the current axes are used.

None

Returns:

Type Description
Axes

The axes containing the plot.

plot_spectrum_pixels(frame: int, channel: int | None = None, *, reduce: str = 'sum_channels', show_peaks: bool = True)

Plot spectrum with pixel index on the x-axis (for CW inspection).

Uses Plotly. Optionally marks detected peaks.

Parameters:

Name Type Description Default
frame int

Frame index.

required
channel int | None

If provided, plot that channel; otherwise use reduce.

None
reduce str

When channel is None, "sum_channels" (default) sums channels.

'sum_channels'
show_peaks bool

If True, detect peaks with scipy.signal.find_peaks and mark them.

True

Returns:

Type Description
Figure
plot_spectrum_plotly(frame: int, channel: int, *, sort_wavelength: bool = True, line_shape: str = 'linear', zero_min: bool | None = None, theme: str | None = None, bg: str = '#44423e', fg: str = '#eaeaea')

Return an interactive Plotly figure for a spectrum.

Parameters:

Name Type Description Default
frame int

Frame index (0-based).

required
channel int

Channel index (0-based).

required
sort_wavelength bool

If True, sort the wavelength vector to be monotonic for better interactive behaviour (default True).

True
line_shape str

Plotly line shape (e.g. 'linear', 'spline').

'linear'
theme (dark, light, None)

If "dark", apply a dark layout to the figure. If None, inherit Plotly's default.

"dark","light",None
bg str

Background color for dark theme.

'#44423e'
fg str

Foreground color for dark theme.

'#eaeaea'

Returns:

Type Description
Figure

Interactive figure containing the spectrum.

Raises:

Type Description
ImportError

If Plotly is not available.

Example

fig = s26.plot_spectrum_plotly(38, 36) fig.show()

print_header()

Print all FITS header fields.

set_baseline_zero(enable: bool = True) -> None

Enable/disable per-spectrum minimum subtraction.

When enabled, each spectrum row (across pixels) will be shifted so its minimum is zero in methods that return spectra-like arrays.

Parameters:

Name Type Description Default
enable bool

If True, subtract per-row minima from spectra results. If False, disable this behaviour.

True
set_dark(*, frame: int | None = None, channel: int | None = None, vector=None, value: float | None = None)

Configure dark subtraction behaviour.

Dark can be specified in several ways: - vector: an array-like that will be used directly as the dark correction (broadcasting rules apply). - value: a scalar dark value subtracted from all pixels. - frame and channel: record a reference index; subtraction will subtract the value found at that (frame, channel) location when applied.

Parameters:

Name Type Description Default
frame int | None

Frame index used for index-based dark (with channel).

None
channel int | None

Channel index used for index-based dark (with frame).

None
vector array - like | None

Direct dark vector/array to use for subtraction.

None
value float | None

Scalar dark value to subtract.

None
set_scale(scale: float)

Set the global multiplicative scale applied to the cube.

Parameters:

Name Type Description Default
scale float

New scale factor.

required
set_time(t)

Set an explicit time vector for the frames.

Parameters:

Name Type Description Default
t array - like

Time vector (seconds) of length F where F is the number of frames in the cube. Must be non-decreasing and contain finite values.

required

Raises:

Type Description
ValueError

If the vector length does not match F, contains non-finite values, or is not non-decreasing.

set_time_linspace(start_s: float, stop_s: float)

Set time_s to a linearly spaced vector between two times.

Parameters:

Name Type Description Default
start_s float

Start time in seconds.

required
stop_s float

Stop time in seconds.

required
set_time_period(period_s: float, start_s: float = 0.0)

Set time_s assuming a constant frame period.

Parameters:

Name Type Description Default
period_s float

Time between successive frames in seconds.

required
start_s float

Time of the first frame (default 0.0 s).

0.0
set_wavecal_shift(delta_lambda_nm: float) -> None

Set the global wavelength shift applied in formula mode.

λ'(x) = a*x + b + Δλ

Parameters:

Name Type Description Default
delta_lambda_nm float

Shift in nanometres.

required
spectrum(frame: int, channel: int | None = None, *, reduce: str = 'sum_channels', zero_min: bool | None = None) -> tuple[np.ndarray, np.ndarray]

Return (x-axis, intensity) for a frame.

Parameters:

Name Type Description Default
frame int

Frame index (0-based).

required
channel int | None

If provided, return that channel's spectrum. If None, combine channels according to reduce.

None
reduce str

When channel is None, how to combine channels: "sum_channels" (default) sums across channels.

'sum_channels'
zero_min bool | None

If True, subtract per-row minimum. If None, use set_baseline_zero setting.

None

Returns:

Type Description
tuple of ndarray

If channel is provided: (wavelengths, signal) in nm and scaled counts. If channel is None: (pixels, intensity) with pixel indices and combined intensity (for inspection).

summary()

Print a compact summary of the acquisition.

Functions

parse_vis133m_header(header: dict) -> dict

Extract useful acquisition metadata from a Vis133M FITS header.

Loader and processor for VIS-1.33 m FITS data cubes with per-channel wavelength calibration.