pypeit.spectrographs.p200_ngps module

Module for P200/NGPS specific methods.

NGPS raw FITS files store each channel (‘U’, ‘G’, ‘R’, ‘I’) in its own image extension labelled by EXTNAME. The order of the image extensions is not stable across files, and frames where only some channels were read out (e.g. U+G dome flats) drop the unused extensions entirely. Per-channel subclasses below resolve their image extension by scanning EXTNAME, never by hardcoded HDU index.

Per-channel CCD readout orientation is expressed through PypeIt’s stock specaxis/specflip/spatflip detector parameters, so the raw image is reoriented by orient_image() exactly as for every other spectrograph (and the Instrument-Specific Data table reports the true orientation):

  • R, I: dispersion along NAXIS1 -> specaxis=1.

  • G: dispersion along NAXIS1 but flipped left-right relative to R/I

    -> specaxis=1, specflip=True.

  • U: dispersion along NAXIS2 (read out rotated 90 deg) and flipped

    -> specaxis=0, specflip=True.

DATASEC/OSCANSEC are read from each frame’s own image-extension header in the native readout frame and reoriented alongside the image. The U channel ships malformed DATASEC cards, so it falls back to the full native frame.

For operational use at the telescope (whole-night ingestion, per-channel setup/reduction orchestration, and real-time quicklook products), see the separately maintained wrapper around these classes: https://github.com/cfremling/ngps_pipeline

class pypeit.spectrographs.p200_ngps.P200NGPSSpectrograph[source]

Bases: Spectrograph

Common base for P200/NGPS per-channel subclasses.

Each per-channel subclass sets _extname to the EXTNAME of its image extension in the raw FITS file (‘U’, ‘G’, ‘R’, or ‘I’) and, where its CCD readout orientation differs from R/I, sets _specaxis/_specflip so that PypeIt’s stock orient_image() reorients the raw frame the same way for every channel (dispersion along the spectral axis, slices in a uniform spatial order).

_arc_idnames = ('THAR',)
_bpm_usebias = False

Whether to use the master bias to build the bad-pixel mask.

_datasec_fallback = None

Hardcoded fallback DATASEC (FITS-style [NAXIS1, NAXIS2]) used only when the per-frame extension header has no usable DATASEC card (e.g. the U channel ships malformed [-1:1097,...]). When None, the per-frame raw header DATASEC card is used as-is (native readout frame).

_datasec_string(ext_hdr)[source]

Resolve the native-frame DATASEC for this extension.

Default (R/I/G): use the per-frame raw DATASEC card (this picks up the binning-correct section the instrument writes out); fall back to _datasec_fallback if the raw section is missing or malformed. orient_image reorients the resulting pixel map alongside the image, so the section is given in the native readout frame. Subclasses (e.g. U, where every raw DATASEC is malformed) can override this method.

_extname = None

EXTNAME of this channel in the raw FITS HDU list.

_extname_cache: dict = {}
_extname_index(hdulist_or_headarr)[source]

Return the HDU/header index whose EXTNAME equals self._extname, or None if the channel is not present in this file (e.g. a U+G-only calibration drops the R and I extensions).

classmethod _file_extnames(path)[source]

Cached EXTNAME set of the image HDUs in this raw FITS.

Return type:

frozenset[str]

_fit_min_spec_length = 0.6

Minimum unmasked spectral length of a slit edge as a fraction of the detector size. PypeIt’s default 0.6 is too aggressive for the U channel where dome flat illumination only spans part of the spectral range.

_flatfield_overrides = {}

Per-channel overrides for par['calibrations']['flatfield']. Each subclass can tune b-spline knot spacing / median-filter width independently, since each NGPS channel has different optics, slit-edge sharpness and dome-flat illumination characteristics. Empty by default; subclasses fill in.

_flexure_overrides = {}

Per-channel overrides for par['flexure']; default spec_method='skip'.

_gain = 1.0

Per-channel detector gain (electrons / ADU); set by each subclass.

_match_toler_pixels = 0.3

PypeIt’s full_template drops detected arc peaks whose nearest catalog line is more than match_toler pixels away. 0.3 binned pixels at NGPS’ binspec=3 corresponds to a ~0.5-0.6 A window across u/g/r/i.

_oscansec_fallback = None

Hardcoded fallback OSCANSEC (bias) for the same case.

_oscansec_string(ext_hdr)[source]

Same as _datasec_string() but for OSCANSEC/BIASSEC.

static _parse_section(sec_str)[source]

Parse a FITS section string into (x_lo, x_hi, y_lo, y_hi), 1-indexed inclusive. Returns None if the section is malformed (e.g. the U channel’s [-1:1097,...]).

_require_ug_only_cals = False
_ronoise = 8.5

Per-channel readnoise (electrons).

_saturation_adu = 40000.0

Detector saturation level (ADU). Set conservatively to 40k for NGPS – the CCDs nominally hold ~57 kADU but flats start to deviate from linearity well before that, and dome lamps occasionally drive bright slit regions past the conservative threshold. Pypeit masks pixels above this value as saturated; nonlinear then sets the soft warning threshold as a fraction of saturation.

_sensfunc_overrides = {'UVIS': {'polycorrect': False, 'resolution': 4000}, 'extr': 'OPT'}

Per-channel overrides for par['sensfunc']. Top-level keys go in par['sensfunc']; nested UVIS/IR dicts go in par['sensfunc']['UVIS']/['IR'].

Why resolution = 4000 is constant rather than slit-aware:

_sigdetect = 5.0

Per-channel arc-line detection SNR threshold for the wavecal. PypeIt’s default is 5.0. We use 5.0 to keep only clean, well-isolated peaks – the previous 1.0 was letting noise spikes / blended low-SNR features into the reidentify pool which then mis-matched against the catalog and biased the polynomial.

_skysub_overrides = {'bspline_spacing': 0.5, 'no_local_sky': True}

Per-channel overrides for par['reduce']['skysub'].

  • bspline_spacing = 0.5 (vs PypeIt default 0.6): tighter knot spacing along the spectral axis.

  • no_local_sky = True: skip the local-window sky re-fit so the spec2d’s sky-subtracted image is continuous.

_spatflip = False
_specaxis = 1

Native CCD readout orientation, applied by PypeIt’s stock orient_image(). R/I read out dispersion-along-NAXIS1 (specaxis=1); G is the same but left-right flipped (specflip=True); U reads out dispersion-along-NAXIS2 (specaxis=0) and flipped. Subclasses override these as needed.

_specflip = False
_use_overscan = True

Whether to use the bias overscan region in raw images.

_wave_lamps = ['ThAr']

Default wavelength-calibration lamps and raw IMGTYPE values used for arc/tilt frame typing. All four NGPS channels use ThAr; FeAr was investigated and rejected because pypeit’s FeAr line list is too sparse on g/r/i (only 7-31 cataloged lines vs 2000-7000 ThAr lines), and pypeit’s reidentify second-pass rejection makes the sparse-list fits unreliable.

_wavecal_method = 'full_template'

PypeIt wavelength-solution method. ‘full_template’ uses the single-slice central-slit ThAr archive and a global cross-correlation shift to anchor the per-slit polynomial fit.

_wvarxiv = None

Per-channel arc-line wavelength reidentification template (reid_arxiv). Lives in pypeit/data/arc_lines/reid_arxiv/.

check_frame_type(ftype, fitstbl, exprng=None)[source]

Frame-typing rule, shared by all four channels. IMGTYPE values in the raw header drive the baseline classification: SCI is science / standard, BIAS is bias, DOMEFLAT and CONT are flats, and the channel-specific arc IMGTYPE values define the arc/tilt frames. Discrimination between science and standard is left to PypeIt’s downstream coordinate-matching against the archived flux-standard registry.

compound_meta(headarr, meta_key)[source]

Compound metadata. Shared across all four channels; binning is read from the channel’s own image extension (resolved by EXTNAME), so frames where the channel is absent return None and are filtered out of the configuration.

configuration_keys()[source]

Return the metadata keys that define a unique instrument configuration.

This list is used by PypeItMetaData to identify the unique configurations among the list of frames read for a given reduction.

Returns:

List of keywords of data pulled from file headers and used to construct the PypeItMetaData object.

Return type:

list

classmethod default_pypeit_par()[source]

Default reduction parameters. Per-channel overrides (_use_overscan, _bpm_usebias, _wvarxiv) are pulled from class attributes so subclasses only need to set those.

classmethod find_raw_files(root, extension=None)[source]

Same as base class, but only returns FITS files that carry this channel’s image extension (_extname). An NGPS raw directory contains a mix of long getcalib_ug exposures (only G+U image HDUs) and short 4-channel exposures (G+I+R+U), and only one subset is meaningful for any given per-channel spectrograph. Filtering here means pypeit never attempts to read this channel’s BINSPEC/BINSPAT from a file where that extension doesn’t exist.

get_detector_par(det, hdu=None)[source]

Build the detector container.

When hdu is supplied, dataext is set to the index of the per-channel extension in this file (looked up by EXTNAME), and DATASEC/OSCANSEC are read from the per-frame raw extension header (so they match the actual on-chip binning for this exposure). The sections are given in the native readout frame and reoriented alongside the image by orient_image(). If the raw section is malformed (e.g. U ships [-1:1097,...]), _datasec_fallback / _oscansec_fallback are used instead.

get_rawimage(raw_file, det)[source]

Read a raw NGPS image, find the channel by EXTNAME, and return the native-frame image plus the DATASEC/OSCANSEC pixel maps. The geometric reorientation into the PypeIt frame is left to the stock orient_image() via the channel’s specaxis/specflip/spatflip.

This is a custom drop-in replacement for the base class pypeit.spectrographs.spectrograph.Spectrograph.get_rawimage() method, needed only because the channel is located by EXTNAME (not a fixed HDU index). The DATASEC/OSCANSEC strings carried by the DetectorContainer already include the on-chip binning, so we set the per-amplifier section binning to None when converting the strings to slices (mirroring sec_includes_binning=True in the base flow).

init_meta()[source]

Define how metadata are derived from the spectrograph files.

ndet = 1

Number of detectors for this instrument.

pypeit_file_keys()[source]

Define the list of keys to be output into a standard PypeIt file.

Returns:

The list of keywords in the relevant PypeItMetaData instance to print to the PypeIt Reduction File.

Return type:

list

raw_header_cards()[source]

Return additional raw header cards to be propagated in downstream output files for configuration identification.

This list is used by subheader_for_spec() to include additional FITS keywords in downstream output files.

Returns:

List of keywords from the raw data files that should be propagated in output files.

Return type:

list

telescope = Parameter     Value                Default  Type        Callable ---------------------------------------------------------------- name          P200                 KECK     str         False    longitude     -116.86300000000003  None     int, float  False    latitude      33.35600000000001    None     int, float  False    elevation     1705.999999999058    None     int, float  False    fratio        None                 None     int, float  False    diameter      5.1                  None     int, float  False    eff_aperture  None                 None     int, float  False   

Instance of TelescopePar providing telescope-specific metadata.

class pypeit.spectrographs.p200_ngps.P200NGPSSpectrograph_g[source]

Bases: P200NGPSSpectrograph

P200/NGPS g-channel. Read out dispersion-along-NAXIS1 like R/I but left-right flipped, i.e. specaxis=1, specflip=True.

_bpm_usebias = False

Whether to use the master bias to build the bad-pixel mask.

_extname = 'G'

EXTNAME of this channel in the raw FITS HDU list.

_flatfield_overrides = {'slit_illum_finecorr': False, 'spec_samp_coarse': 1.0}

Per-channel overrides for par['calibrations']['flatfield']. Each subclass can tune b-spline knot spacing / median-filter width independently, since each NGPS channel has different optics, slit-edge sharpness and dome-flat illumination characteristics. Empty by default; subclasses fill in.

_gain = 2.88

Per-channel detector gain (electrons / ADU); set by each subclass.

_require_ug_only_cals = True
_specflip = True
_use_overscan = False

Whether to use the bias overscan region in raw images.

_wvarxiv = 'wvarxiv_p200_ngps_g_thar_central.fits'

Per-channel arc-line wavelength reidentification template (reid_arxiv). Lives in pypeit/data/arc_lines/reid_arxiv/.

camera = 'NGPS_g'

Name of the spectrograph camera or arm. This is used by specdb, so use that naming convention

comment = 'g-Channel'

A brief comment or description regarding PypeIt usage with this spectrograph.

header_name = 'NGPS_g'

Name of the spectrograph camera or arm from the Header. Usually the INSTRUME card.

name = 'p200_ngps_g'

The name of the spectrograph. See Spectrographs for the currently supported spectrographs.

supported = True

Flag that PypeIt code base has been sufficiently tested with data from this spectrograph that it is officially supported by the development team.

class pypeit.spectrographs.p200_ngps.P200NGPSSpectrograph_i[source]

Bases: P200NGPSSpectrograph

P200/NGPS i-channel.

_bpm_usebias = False

Whether to use the master bias to build the bad-pixel mask.

_extname = 'I'

EXTNAME of this channel in the raw FITS HDU list.

_flatfield_overrides = {'pixelflat_max_wave': 10100.0, 'pixelflat_min_wave': 7800.0}

Per-channel overrides for par['calibrations']['flatfield']. Each subclass can tune b-spline knot spacing / median-filter width independently, since each NGPS channel has different optics, slit-edge sharpness and dome-flat illumination characteristics. Empty by default; subclasses fill in.

_gain = 0.86

Per-channel detector gain (electrons / ADU); set by each subclass.

_use_overscan = False

Whether to use the bias overscan region in raw images.

_wvarxiv = 'wvarxiv_p200_ngps_i_thar_central.fits'

Per-channel arc-line wavelength reidentification template (reid_arxiv). Lives in pypeit/data/arc_lines/reid_arxiv/.

camera = 'NGPS_i'

Name of the spectrograph camera or arm. This is used by specdb, so use that naming convention

comment = 'i-Channel'

A brief comment or description regarding PypeIt usage with this spectrograph.

header_name = 'NGPS_i'

Name of the spectrograph camera or arm from the Header. Usually the INSTRUME card.

name = 'p200_ngps_i'

The name of the spectrograph. See Spectrographs for the currently supported spectrographs.

supported = True

Flag that PypeIt code base has been sufficiently tested with data from this spectrograph that it is officially supported by the development team.

class pypeit.spectrographs.p200_ngps.P200NGPSSpectrograph_r[source]

Bases: P200NGPSSpectrograph

P200/NGPS r-channel.

_bpm_usebias = True

Whether to use the master bias to build the bad-pixel mask.

_extname = 'R'

EXTNAME of this channel in the raw FITS HDU list.

_flatfield_overrides = {'pixelflat_max_wave': 7800.0, 'pixelflat_min_wave': 5850.0}

Per-channel overrides for par['calibrations']['flatfield']. Each subclass can tune b-spline knot spacing / median-filter width independently, since each NGPS channel has different optics, slit-edge sharpness and dome-flat illumination characteristics. Empty by default; subclasses fill in.

_gain = 0.9

Per-channel detector gain (electrons / ADU); set by each subclass.

_use_overscan = False

Whether to use the bias overscan region in raw images.

_wvarxiv = 'wvarxiv_p200_ngps_r_thar_central.fits'

Per-channel arc-line wavelength reidentification template (reid_arxiv). Lives in pypeit/data/arc_lines/reid_arxiv/.

camera = 'NGPS_r'

Name of the spectrograph camera or arm. This is used by specdb, so use that naming convention

comment = 'r-Channel'

A brief comment or description regarding PypeIt usage with this spectrograph.

header_name = 'NGPS_r'

Name of the spectrograph camera or arm from the Header. Usually the INSTRUME card.

name = 'p200_ngps_r'

The name of the spectrograph. See Spectrographs for the currently supported spectrographs.

supported = True

Flag that PypeIt code base has been sufficiently tested with data from this spectrograph that it is officially supported by the development team.

class pypeit.spectrographs.p200_ngps.P200NGPSSpectrograph_u[source]

Bases: P200NGPSSpectrograph

P200/NGPS u-channel. Read out with the dispersion axis along NAXIS2 (rotated 90 deg relative to the other channels) and flipped, i.e. specaxis=0, specflip=True. The raw FITS header ships malformed DATASEC/BIASSEC cards (e.g. [-1:1097,1:4302]), so we use the full native frame as the data section and leave _use_overscan=False since the bias strip is only 2 pixels wide.

_arc_idnames = ('THAR',)
_bpm_usebias = False

Whether to use the master bias to build the bad-pixel mask.

_datasec_fallback = None

Hardcoded fallback DATASEC (FITS-style [NAXIS1, NAXIS2]) used only when the per-frame extension header has no usable DATASEC card (e.g. the U channel ships malformed [-1:1097,...]). When None, the per-frame raw header DATASEC card is used as-is (native readout frame).

_datasec_string(ext_hdr)[source]

U’s raw DATASEC is malformed at every binning (negative low bounds), so we ignore it and use the entire native image ([1:NAXIS1,1:NAXIS2]); orient_image reorients it.

_extname = 'U'

EXTNAME of this channel in the raw FITS HDU list.

_fit_min_spec_length = 0.2

Minimum unmasked spectral length of a slit edge as a fraction of the detector size. PypeIt’s default 0.6 is too aggressive for the U channel where dome flat illumination only spans part of the spectral range.

_flatfield_overrides = {'pixelflat_min_wave': 3400.0, 'slit_illum_finecorr': False, 'spec_samp_coarse': 2.0}

Per-channel overrides for par['calibrations']['flatfield']. Each subclass can tune b-spline knot spacing / median-filter width independently, since each NGPS channel has different optics, slit-edge sharpness and dome-flat illumination characteristics. Empty by default; subclasses fill in.

_gain = 0.755

Per-channel detector gain (electrons / ADU); set by each subclass.

_oscansec_fallback = None

Hardcoded fallback OSCANSEC (bias) for the same case.

_oscansec_string(ext_hdr)[source]

No usable overscan strip for U (the bias region is only 2 binned pixels wide and the raw card is malformed). We rely on the master bias frame instead.

_require_ug_only_cals = True
_specaxis = 0

Native CCD readout orientation, applied by PypeIt’s stock orient_image(). R/I read out dispersion-along-NAXIS1 (specaxis=1); G is the same but left-right flipped (specflip=True); U reads out dispersion-along-NAXIS2 (specaxis=0) and flipped. Subclasses override these as needed.

_specflip = True
_use_overscan = False

Whether to use the bias overscan region in raw images.

_wave_lamps = ['ThAr']

Default wavelength-calibration lamps and raw IMGTYPE values used for arc/tilt frame typing. All four NGPS channels use ThAr; FeAr was investigated and rejected because pypeit’s FeAr line list is too sparse on g/r/i (only 7-31 cataloged lines vs 2000-7000 ThAr lines), and pypeit’s reidentify second-pass rejection makes the sparse-list fits unreliable.

_wvarxiv = 'wvarxiv_p200_ngps_u_thar_central.fits'

Per-channel arc-line wavelength reidentification template (reid_arxiv). Lives in pypeit/data/arc_lines/reid_arxiv/.

camera = 'NGPS_u'

Name of the spectrograph camera or arm. This is used by specdb, so use that naming convention

comment = 'u-Channel (read out rotated 90 deg)'

A brief comment or description regarding PypeIt usage with this spectrograph.

header_name = 'NGPS_u'

Name of the spectrograph camera or arm from the Header. Usually the INSTRUME card.

name = 'p200_ngps_u'

The name of the spectrograph. See Spectrographs for the currently supported spectrographs.

supported = True

Flag that PypeIt code base has been sufficiently tested with data from this spectrograph that it is officially supported by the development team.