data_models.base
KPF-specific base data model.
Thin layer on top of RVDataModel that adds KPF-specific attributes and the
behaviour shared by every KPF data model: fits.Header storage, the DRPSTATU
receipt stamp, alias-aware set_data/set_header, and lossless PRIMARY
serialization. All four KPF models inherit it — L0/L1 directly, and L2/L4 via
multiple inheritance alongside rvdata’s RV2/RV4 (KPFDataModel listed first so
its overrides win while RV2/RV4 remain reachable through super()).
- class kpfpipe.data_models.base.KPFDataModel
Bases:
RVDataModelShared base for every KPF data model (L0, L1, and — multiply-inherited with RV2/RV4 — L2, L4).
- static as_fits_header(src)
Return
srcas anastropy.io.fits.Header, preserving comments.KPF stores every extension header as a
fits.Headerso reads and writes go through astropy natively, with no value-vs-(value, comment)ambiguity. This is the single bridge from the two legacy in-memory forms:a
fits.Header(e.g. fromfrom_fits) is returned as a copy, so a caller can rebuild an HDU without aliasing the stored header;a plain mapping (RVData seeds PRIMARY defaults as an
OrderedDictwhose entries are(value, comment)tuples) is rebuilt card by card —head[kw] = (value, comment)sets the value and comment together.
- check_filename_convention(filename)
Abstract: every concrete KPF model declares its own filename convention.
KPFDataModel is never instantiated directly — only inherited — so reaching this means a subclass failed to define the method.
- create_extension(ext_name, ext_type, header=None, data=None)
Create an extension, storing its header as a
fits.Header.rvdata initializes a new header as a plain
OrderedDict; KPF keeps every header as afits.Headerso all reads/writes are native astropy.
- classmethod from_fits(fn, instrument=None, **kwargs)
Read a data product from FITS, logging the file read (DRP-RUN-08).
The single read chokepoint for every KPF data model: one INFO record per FITS read, naming the concrete class and the path, then delegate to the inherited reader (rvdata’s for L2/L4 via RV2/RV4 in the MRO).
Ensures
obs_idis carried in memory after the read. L0 (and any product whose filename embeds the obs_id) resolves it duringread; L1/L2/L4 filenames are timestamp-based, so a read there recovers the obs_id from the ORIGID provenance card instead (see_obs_id_from_receipt). Theto_kpfNconverters setobs_iddirectly, so this only fills the from_fits path.
- generate_standard_filename()
Abstract: every concrete KPF model builds its own standard filename.
KPFDataModel is never instantiated directly — only inherited — so reaching this means a subclass failed to define the method.
- keyword_registry = <kpfpipe.data_models.keyword_registry.KeywordRegistry object>
- receipt_add_entry(function, args, status)
Record a processing step, and update DRPSTATU for pipeline modules.
Signature matches rvdata >=0.4.0:
functionnames the step,argsis a key=value provenance string (""when not applicable),statusis"PASS"/"FAIL".
- set_data(ext_name, data)
Set extension data, resolving KPF aliases first.
For aliased models (KPF2/KPF4) this resolves chip-prefix keys (e.g. ‘GREEN_SCI2_FLUX’, routed through the data dict’s
__setitem__) and extension aliases before the base class.keys()check. Thehasattrguards make it a no-op passthrough for non-aliased L0/L1.
- set_header(ext_name, header)
Set an extension header, resolving KPF aliases before the base class
.keys()check (a no-op for non-aliased L0/L1).
- set_keyword(key, value, ext=None)
Write a registered keyword to its home extension header.
Looks
keyup in the merged KPF + EPRV keyword registry (config/L{0,1,2,4}-headers.csvplus the EPRV PRIMARY keywords) and writesvalueto the extension named there, with the registry Description as the FITS comment. This is the single write path for registered keywords, so a keyword always lands on the same extension with the same comment — callers never name a comment.exttargets a specific extension for EPRV per-extension cards that have no single routed home because they recur on every orderlet’s extension (e.g.VELSTARTonCCF1..5,RVMETHODonRV1..5). The keyword must be registered for that extension; the comment still comes from the registry. Aliases (e.g.SCI2_CCF) resolve first. Whenextis None the keyword routes to its registered home as usual.- Raises:
KeyError – If
keyis registered nowhere (default), or not registered forext(targeted); register it in the appropriateconfig/L{level}-headers.csvbefore writing it.ValueError – If the target extension does not exist on this object (a config error — the extension must be created before the write).