pypeit.dashboard.model module
Headless (Qt-free) data/logic layer for the PypeIt Dashboard.
This module holds the dashboard’s PypeIt-facing logic so it can be unit
tested with plain pytest (no display required), keeping the Qt views
thin. It provides the cheap reduction metadata used by the header banner
and the full reduction-state layer (loading or deriving a
RunPypeItState).
- class pypeit.dashboard.model.DashboardModel(pypeit_file, redux_path=None, derive=True)[source]
Bases:
objectHeadless (Qt-free) model for one PypeIt reduction.
It acquires a
RunPypeItStateby source priority (load<root>_state.jsonif present; otherwise derive it from the on-disk calibration products, the same waypypeit_statusdoes), and exposes a clean, normalized API the Qt views consume — a status table, the(calib_id, det)pairs, the pipeline-aware step order, and graceful edge states. It never raises for a missing/empty/malformed state: such cases are reported viaload_status.- Parameters:
pypeit_file (
str,pathlib.Path) – Path to the.pypeitreduction file.redux_path (
str, optional) – Reduction directory (where the state file lives). Defaults to the directory containingpypeit_file.derive (
bool, optional) – If True (default) and no state file is present, derive the state viaPypeIt(requires the raw data). Set False to skip deriving (e.g. CI tests without RAW_DATA): the model then reportsnot_startedwhen no state file exists.
- Variables:
pypeit_file (
pathlib.Path) – The.pypeitpath.redux_dir (
pathlib.Path) – The reduction directory.state_path (
pathlib.Path) – The expected<root>_state.jsonpath.header_info (
HeaderInfo) – Header metadata, orNone.run_state (
RunPypeItState) – The state, orNonewhen unavailable.load_status (
str) – One of theLOAD_*class attributes.error (
str) – An error message when relevant, elseNone.
- LOAD_DERIVED = 'derived'
The state was derived from the on-disk products (no state file).
- LOAD_ERROR = 'error'
Deriving the state raised an error.
- LOAD_FILE_NOT_FOUND = 'file_not_found'
The named
.pypeitfile is missing.
- LOAD_MALFORMED = 'malformed'
A state file is present but could not be read/validated.
- LOAD_NOT_STARTED = 'not_started'
No state file exists and the state was not derived.
- LOAD_STATE_FILE = 'state_file'
The state was loaded from an existing
<root>_state.jsonfile.
- SCIENCE_COLUMNS = ['frame', 'detector', 'calib', 'objtype', 'process', 'findobj', 'skysub', 'extract', 'nobj', 'spec2d', 'spec1d']
The per-frame science-status columns consumed by the Science view (mirrors
get_science_status()).
- STATUS_COLUMNS = ['calibration_group', 'detector', 'step', 'in_pipeline', 'required', 'status', 'output_file']
The normalized status-table columns the views consume.
- _ABSENT = 'absent'
Status value used for an entry that is not present in the state (
get_status()reports these with a"--"sentinel).
- _CALIB_CLASS_BY_PYPELINE = {'Echelle': <class 'pypeit.calibrations.MultiSlitCalibrations'>, 'MultiSlit': <class 'pypeit.calibrations.MultiSlitCalibrations'>, 'SlicerIFU': <class 'pypeit.calibrations.IFUCalibrations'>}
The
Calibrationssubclass that defines the calibration-step order, keyed on the spectrographpypelinevalue. New pipeline types should be added here explicitly; an unknown pypeline falls back to the full set of known steps (seedefault_steps()).
- _PLANNED_SCIENCE_CACHE = {}
Per-
.pypeitcache (class-level, so it spans model reloads within a session) of the planned science/standard frames, keyed by the.pypeitpath. Computing the planned frames requires building the reduction metadata, which is expensive; caching it means the build happens at most once per session, so re-seeding planned frames on every state reload (live monitoring, post-(re)build) is cheap.
- _acquire_state(derive)[source]
Acquire the reduction state by source priority: an existing state file first, otherwise (optionally) derive it from the on-disk products. Sets
run_stateandload_status.- Parameters:
derive (
bool) – Whether to derive the state when no state file is present.
- _derive_state()[source]
Derive the reduction state from the on-disk calibration and science products (used when no state file exists). Failures are reported via
load_status, never raised.
- _load_state_file(derive)[source]
Load and validate the
<root>_state.jsonstate file, reporting a malformed/unreadable file viaload_statusinstead of raising.- Parameters:
derive (
bool) – Whether a one-time metadata build is permitted when seeding the planned science frames (see_seed_planned_science()).
- _planned_science_frames(allow_build=False)[source]
Return the cached list of planned science/standard frames for this
.pypeitfile. On a cache miss, build the metadata to compute it only whenallow_buildis True (so live-monitoring reloads and CI loads never trigger a heavy, possibly-failing build).- Parameters:
allow_build (
bool, optional) – Permit a one-time metadata build on a cache miss (True at launch; False on refresh/CI).- Returns:
Planned-frame dicts (see
planned_science_from_fitstbl()); empty when uncached and a build is not permitted/possible.- Return type:
- _seed_planned_science(allow_build=False)[source]
Seed the planned science/standard frames into
run_state(from the cache, or a one-time build whenallow_build), keyed to the calibration(group, det)pairs in the current state. Best-effort: never raises into the load/derive path.- Parameters:
allow_build (
bool, optional) – Permit a one-time metadata build on a cache miss.
- _set_malformed(error)[source]
Record a malformed/partial/schema-mismatched state file.
- Parameters:
error (Exception) – The error raised while reading/validating the state file.
- calib_det_pairs()[source]
Enumerate the
(calibration_group, detector)pairs present in the state, in sorted order, for the scope drop-downs/selectors.
- property calib_dir
The reduction’s
Calibrations/directory (where output files live).- Returns:
<redux_dir>/Calibrations.- Return type:
- calib_file_path(prefix, group, det, ext='fits')[source]
Construct the path to a calibration file by naming convention (
<prefix>_<setup>_<group>_<detname>.<ext>) — used when the viewer needs a different file than a step’soutput_file(e.g. theEdges_*file for theslitsstep, or theSlits_*file required bypypeit_chk_scattlight).- Parameters:
- Returns:
The constructed path (
Noneif the setup is unknown).- Return type:
pathlib.Pathor None
- calibrations_ready(group, det)[source]
Whether the required calibrations for one
(group, det)are all built successfully — the precondition for a science (Re)Build: until the calibrations a science frame depends on exist, its (Re)Build is disabled.- Parameters:
- Returns:
True only if at least one required, in-pipeline calibration step exists for
(group, det)and all such steps have asuccess/completestatus; False otherwise (including when no matching calibration entries are known).- Return type:
- default_steps()[source]
Return the active spectrograph’s calibration steps, in pipeline order (specific to the
pypeline; see_CALIB_CLASS_BY_PYPELINE), includingbpm.A pypeline without an entry in
_CALIB_CLASS_BY_PYPELINE(e.g. a newly added pipeline type) falls back to the full set of known calibration steps, so the dashboard remains usable until the new pipeline’s order is registered.- Returns:
The ordered step names, or
[]if the pipeline is unknown (e.g. the.pypeitfile was not found).- Return type:
- det_name(det)[source]
Return a human-readable name for a detector or mosaic, for display in the views (drop-downs, navigator).
- has_science()[source]
Whether any science-frame state is available.
- Returns:
True if the state has at least one science entry.
- Return type:
- is_stale()[source]
Whether the loaded
*_state.jsonlooks out of date relative to the.pypeitfile or the calibration outputs.- Returns:
True if the state file’s mtime is older than the
.pypeitfile or the newest file inCalibrations/; False if there is no state file or nothing newer.- Return type:
- is_started()[source]
Whether the reduction has any calibration-state entries.
- Returns:
True if a state with at least one entry is available.
- Return type:
- property log_path
The reduction
.logfile thatrun_pypeit/pypeit_run_to_calibstepwrite to (used by the single-run lock to detect an active run via the log’s modification time).- Returns:
<pypeit_root>.log(next to the.pypeitfile, matchingpypeit_run_to_calibstep’s default log path).- Return type:
- science_frame_entry(frame, det)[source]
Return the raw
ScienceFrameStatefor one(frame, det), orNone.
- science_object_qa_files(frame, det, slitid)[source]
Return all per-object QA PNGs for one object’s slit, so the per-object table can open them. The science QA PNGs encode the slit as
S{spat_id:04d}, matchingScienceObj.slitid.Discovery is purely by the QA file-naming convention (no fixed list of QA types), so newly added per-object QA figures are picked up with no dashboard change.
- science_object_table(frame, det)[source]
Return the per-object science rows for one frame (
ScienceObj).
- science_qa_files(frame, det)[source]
Return all on-disk QA PNGs for one science
(frame, det): the per-objectobj_prof/obj_tracefigures and the frame-levelspec_flex_*flexure figures.Derived at view time by globbing
<redux>/QA/PNGs/for files whose name starts with the frame basename and contains the detector name — so no science-state change is needed and it works for both live and derived state.
- science_slit_table(frame, det)[source]
Return the per-slit science rows for one frame (
ScienceSlit).
- science_table()[source]
Return the normalized per-frame science-status table the Science view renders (one row per
(frame, detector)).- Returns:
Columns
SCIENCE_COLUMNS; empty when there are no science entries.- Return type:
- slit_table(step, group, det)[source]
Return the per-slit/order rows for a step that tracks them (
slits/wv_calib/tilts/flats).- Parameters:
- Returns:
One dict per slit (sorted by slit id), with keys
slit,status, and step-specific metrics:center/slitord_id(slits),rms(wv_calib/tilts), orcorrections(flats — a dictname → {'mean':…, 'rms':…}). Empty if the step has no per-slit data.- Return type:
- status_table()[source]
Return the normalized calibration-status table the views consume.
Built on
get_status()but normalized:requiredbecomes a realbool(orNone), the"--"sentinels becomeNone/"absent", anin_pipelinecolumn is added (membership indefault_steps()), and an empty/unavailable state yields an empty table.- Returns:
Columns
STATUS_COLUMNS; empty when the reduction has not started or the state is unavailable.- Return type:
- step_entry(step, group, det)[source]
Return the raw
RunPypeItStateentry for one(step, group, det), orNoneif absent.
- step_metrics(step, group, det)[source]
Return the entry-level metrics for a step, as a plain dict for the detail panel (per-slit metrics come from
slit_table()).- Parameters:
- Returns:
Metric name → value (empty if the entry is absent or has no entry-level metrics).
bias→ mean/std;slits→ nslits;flats→ corrections/pixelflat_source.- Return type:
- step_order(include_bpm=False)[source]
Return the pipeline-aware step order for the calibration button row.
- step_output_files(step, group, det)[source]
The existing
Calibrations/file(s) a (re)build of this step would overwrite — named explicitly in the clobber confirmation dialog.Most steps write a single
output_file;slitswrites bothSlits_*(itsoutput_file) and the companionEdges_*. Only files that currently exist on disk are returned (a step with no output yet is a fresh build, nothing to overwrite).
- class pypeit.dashboard.model.HeaderInfo(pypeit_file, spectrograph, setup, path, redux_dir)[source]
Bases:
objectCheap, no-reduction metadata describing a reduction, used to populate the dashboard’s shared header banner.
- Variables:
pypeit_file (
str) – Name of the.pypeitfile (basename, for display).spectrograph (
str) – The spectrograph name (PYP_SPEC), e.g.shane_kast_blue.setup (
str) – The setup/configuration identifier, e.g.A. May beNoneif the.pypeitfile does not define one.path (
str) – The reduction path: the spectrographpypelinevalue, shown verbatim (e.g.MultiSlit,Echelle,SlicerIFU).redux_dir (
str) – The reduction directory (absolute path).
- pypeit.dashboard.model._parse_pypeit(pypeit_file, redux_path=None)[source]
Parse a
.pypeitfile once, returning both the header metadata and the instantiated spectrograph (the latter is reused for, e.g., detector-name formatting).- Parameters:
pypeit_file (
str,pathlib.Path) – Path to the.pypeitreduction file.redux_path (
str, optional) – Reduction directory. IfNone, the directory containingpypeit_fileis used.
- Returns:
header_info (
HeaderInfo) – The parsed header metadata.spec (
Spectrograph) – The instantiated spectrograph.
- Raises:
FileNotFoundError – If
pypeit_filedoes not exist.
- pypeit.dashboard.model.read_header_info(pypeit_file, redux_path=None)[source]
Parse a
.pypeitfile and return the cheap metadata needed by the header banner, performing no reduction.- Parameters:
pypeit_file (
str,pathlib.Path) – Path to the.pypeitreduction file.redux_path (
str, optional) – Reduction directory. IfNone, the directory containingpypeit_fileis used.
- Returns:
The parsed header metadata.
- Return type:
- Raises:
FileNotFoundError – If
pypeit_filedoes not exist.