After a successful photometry run, Node v1 can write a science-ready copy of the FITS file enriched with observatory, detector, and processing metadata. The export preserves the original Seestar file untouched — a byte-for-byte copy is made first withDocumentation Index
Fetch the complete documentation index at: https://mintlify.com/skyrobot804/node_v1/llms.txt
Use this file to discover all available pages before exploring further.
shutil.copy2, and all additional keywords are written only into the copy. This gives downstream users and archives a self-describing file that carries its own provenance without any risk of corrupting the source data.
Configuration
FITS export is controlled by two keys nested underphotometry.fits_export in config.yaml:
config.yaml
enabled: true, export_enhanced_fits() is called automatically after every successful pipeline run. The export_dir path is relative to the working directory. An optional export_dir argument to the function itself overrides the config value (useful for tests or scripted batch processing).
Exported files are written to <export_dir>/YYYY-MM-DD/<original_basename>, where the date is derived from the result’s bjd field (converted to UTC via astropy.time.Time) or from DATE-OBS in the source FITS header, falling back to today’s date if neither is available.
Headers Added
The following FITS header keywords are set on the exported copy. All keywords pass through_set_if_absent(), which means they are only written if the keyword does not already exist in the source file. Existing Seestar headers are never overwritten.
_set_if_absent() is defined as a single conditional check: if keyword not in hdr: hdr[keyword] = value. Original Seestar metadata — including its own TELESCOP, INSTRUME, or AIRMASS — is always preserved exactly as the camera wrote it.Observatory Block
Telescope name, from
observatory.telescope in config. Default: ZWO Seestar S50.Instrument/detector name, from
observatory.instrument in config. Default: ZWO Seestar S50 IMX462.Observer name or code, from
observatory.observer in config. Falls back to aavso.observer_code if observatory.observer is not set. Omitted if neither is configured.Human-readable site name, from
observatory.name in config. Omitted if not configured.Observer latitude in decimal degrees (north positive), from
observatory.latitude or safety.observer.latitude. Both keywords are set to the same value for maximum compatibility with analysis tools.Observer longitude in decimal degrees (east positive, negative for west), from
observatory.longitude or safety.observer.longitude. Both keywords are set to the same value.Observer altitude above sea level in metres, from
observatory.elevation in config. Default: 0.0.Detector Block
Detector gain in e⁻/ADU, from
photometry.gain in config. Default: 1.0.Read noise in ADU, from
photometry.read_noise in config. Default: 5.0.Always set to
LIGHT. The pipeline only processes light frames; calibration frames are rejected in Step 1.Always set to
ICRS. The coordinate reference system used by the WCS solution and all sky coordinates in the file.Always set to
2000.0.Science Block
Airmass at time of observation, copied from the photometry result dict. Only set if the result contains a non-null
airmass value.Barycentric Julian Date (TCB) of the observation midpoint, copied from the photometry result dict. Only set if the result contains a non-null
bjd value. Comment: Barycentric Julian Date (TCB).Always set to
TCB when BJD-OBS is written, identifying the time scale of the barycentric correction.Processing Block
Software identification string:
Boundless Skies Node <node_id>. The node_id is taken from photometry.node_id in config.UTC timestamp of when the header enrichment was applied, in ISO 8601 format (
YYYY-MM-DDTHH:MM:SSZ). Comment: UTC timestamp of header enrichment.Multiple
HISTORY lines are always appended (never overwritten, since HISTORY is an additive FITS keyword):Processed by Boundless Skies Node v1 (<node_id>)Differential photometry: mag=<mag>+/-<err> snr=<snr> quality=<flag>(if photometry succeeded)BJD-OBS computed via astropy barycentric correction (TCB)(if BJD is present)Comparison stars used: <n>(if comparison star count is present)Zero point: <zp>+/-<zp_scatter> mag(if zero point is present)Astrometric solution: WCS present (Seestar or ASTAP)(ifCD1_1orCDELT1is in the header)
Public API
fits_export.py
export_enhanced_fits() returns the full path to the enriched copy on success, or None if the copy could not be written or the header enrichment raised an exception. All failures are logged at ERROR level.
Function Signature
Absolute or relative path to the source FITS file to be copied and enriched. The file must be readable by
astropy.io.fits. The source file is never modified.The measurement dict returned by
run_pipeline(). Science keywords (AIRMASS, BJD-OBS) and all HISTORY lines are derived from this dict. Pass an empty dict to export with observatory/detector headers only.The full application config dict (loaded from
config.yaml). Observatory, detector, and processing keyword values are all drawn from config["observatory"] and config["photometry"].Optional override for the export root directory. When provided, this value takes precedence over
config["photometry"]["fits_export"]["export_dir"]. The date sub-directory (YYYY-MM-DD) is still appended automatically.