def compound_meta(self, headarr: List[fits.Header], meta_key: str): """ Methods to generate metadata requiring interpretation of the header data, instead of simply reading the value of a header card. Args: headarr (:obj:`list`): List of `astropy.io.fits.Header`_ objects. meta_key (:obj:`str`): Metadata keyword to construct. Returns: object: Metadata value read from the header(s). """ # Handle dispangle and mjd from superclass method retval = super().compound_meta(headarr, meta_key) # If superclass could not handle the meta key if retval is not None: return retval if meta_key == 'binning': binspec, binspatial = headarr[0]['CCDSUM'].split(' ') return parse.binning2string(binspec, binspatial) else: msgs.error("Not ready for this compound meta")
def compound_meta(self, headarr, meta_key): """ Methods to generate metadata requiring interpretation of the header data, instead of simply reading the value of a header card. Args: headarr (:obj:`list`): List of `astropy.io.fits.Header`_ objects. meta_key (:obj:`str`): Metadata keyword to construct. Returns: object: Metadata value read from the header(s). """ if meta_key == 'binning': # PypeIt frame binspatial = headarr[0]['DETXBIN'] binspec = headarr[0]['DETYBIN'] return parse.binning2string(binspec, binspatial) elif meta_key == 'mjd': time = headarr[0]['DATE-AVG'] ttime = Time(time, format='isot') return ttime.mjd elif meta_key == 'ra': objra = headarr[0]['OBJRA'] # Given in hours, not deg return objra * 15. msgs.error("Not ready for this compound meta")
def compound_meta(self, headarr, meta_key): """ Args: headarr: list meta_key: str Returns: value """ if meta_key == 'binning': binspatial, binspec = parse.parse_binning(headarr[0]['BINNING']) binning = parse.binning2string(binspec, binspatial) return binning elif meta_key == 'dispangle': if headarr[0]['GRATEPOS'] == 3: return headarr[0]['G3TLTWAV'] elif headarr[0]['GRATEPOS'] == 4: return headarr[0]['G4TLTWAV'] else: msgs.warn( 'This is probably a problem. Non-standard DEIMOS GRATEPOS={0}.' .format(headarr[0]['GRATEPOS'])) else: msgs.error("Not ready for this compound meta")
def compound_meta(self, headarr, meta_key): if meta_key == 'binning': binspatial, binspec = parse.parse_binning(headarr[0]['BINNING']) binning = parse.binning2string(binspec, binspatial) return binning else: msgs.error("Not ready for this compound meta")
def compound_meta(self, headarr, meta_key): """ Methods to generate metadata requiring interpretation of the header data, instead of simply reading the value of a header card. Args: headarr (:obj:`list`): List of `astropy.io.fits.Header`_ objects. meta_key (:obj:`str`): Metadata keyword to construct. Returns: object: Metadata value read from the header(s). """ if meta_key == 'binning': # binning in the raw frames ccdsum = headarr[1].get('CCDSUM') if ccdsum is not None: binspatial, binspec = parse.parse_binning(ccdsum) binning = parse.binning2string(binspec, binspatial) else: # binning in the spec2d file binning = headarr[0].get('BINNING') if binning is None: msgs.error('Binning not found') return binning
def compound_meta(self, headarr, meta_key): """ Methods to generate metadata requiring interpretation of the header data, instead of simply reading the value of a header card. Args: headarr (:obj:`list`): List of `astropy.io.fits.Header`_ objects. meta_key (:obj:`str`): Metadata keyword to construct. Returns: object: Metadata value read from the header(s). """ if meta_key == 'binning': binspatial = headarr[0]['HIERARCH ESO DET WIN1 BINX'] binspec = headarr[0]['HIERARCH ESO DET WIN1 BINY'] binning = parse.binning2string(binspec, binspatial) return binning elif meta_key == 'decker': try: # Science decker = headarr[0]['HIERARCH ESO INS SLIT NAME'] except KeyError: # Standard! try: decker = headarr[0]['HIERARCH ESO SEQ SPEC TARG'] except KeyError: return None return decker else: msgs.error("Not ready for this compound meta")
def compound_meta(self, headarr, meta_key): """ Methods to generate metadata requiring interpretation of the header data, instead of simply reading the value of a header card. Args: headarr (:obj:`list`): List of `astropy.io.fits.Header`_ objects. meta_key (:obj:`str`): Metadata keyword to construct. Returns: object: Metadata value read from the header(s). """ if meta_key == 'binning': if 'HIERARCH ESO DET WIN1 BINX' in headarr[0]: binspatial = headarr[0]['HIERARCH ESO DET WIN1 BINX'] else: binspatial = 1 if 'HIERARCH ESO DET WIN1 BINY' in headarr[0]: binspec = headarr[0]['HIERARCH ESO DET WIN1 BINY'] else: binspec = 1 return parse.binning2string(binspec, binspatial) msgs.error("Not ready for this compound meta")
def compound_meta(self, headarr, meta_key): if meta_key == 'binning': if 'HIERARCH ESO DET WIN1 BINX' in headarr[0]: binspatial = headarr[0]['HIERARCH ESO DET WIN1 BINX'] else: binspatial = 1 if 'HIERARCH ESO DET WIN1 BINY' in headarr[0]: binspec = headarr[0]['HIERARCH ESO DET WIN1 BINY'] else: binspec = 1 binning = parse.binning2string(binspec, binspatial) return binning elif meta_key in ['ra', 'dec']: try: # Calibs do not have RA values coord = SkyCoord(ra=headarr[0]['RA'], dec=headarr[0]['DEC'], unit='deg') except: return None if meta_key == 'ra': return coord.ra.to_string(unit=units.hour, sep=':', pad=True, precision=2) else: return coord.dec.to_string(sep=':', pad=True, alwayssign=True, precision=1) else: msgs.error("Not ready for this compound meta")
def compound_meta(self, headarr, meta_key): if meta_key == 'binning': binspatial = headarr[0]['HIERARCH ESO DET WIN1 BINX'] binspec = headarr[0]['HIERARCH ESO DET WIN1 BINY'] binning = parse.binning2string(binspec, binspatial) return binning elif meta_key in ['ra', 'dec']: try: # Calibs do not have RA values coord = SkyCoord(ra=headarr[0]['RA'], dec=headarr[0]['DEC'], unit='deg') except: return None if meta_key == 'ra': return coord.ra.to_string(unit=units.hour, sep=':', pad=True, precision=2) else: return coord.dec.to_string(sep=':', pad=True, alwayssign=True, precision=1) elif meta_key == 'decker': try: # Science decker = headarr[0]['HIERARCH ESO INS SLIT NAME'] except KeyError: # Standard! try: decker = headarr[0]['HIERARCH ESO SEQ SPEC TARG'] except KeyError: return None return decker else: msgs.error("Not ready for this compound meta")
def compound_meta(self, headarr: List[fits.Header], meta_key: str): """ Methods to generate meta in a more complex manner than simply reading from the header. Super method handles mjd and dispangle binning is parsed from CCDSUM header Args: headarr: List[fits.Header] List of headers meta_key: str Returns: value: """ # Handle dispangle and mjd from superclass method retval = super(P200DBSPRedSpectrograph, self).compound_meta(headarr, meta_key) # If superclass could not handle the meta key if retval is not None: return retval if meta_key == 'binning': binspec, binspatial = headarr[0]['CCDSUM'].split(' ') return parse.binning2string(binspec, binspatial) else: msgs.error("Not ready for this compound meta")
def compound_meta(self, headarr, meta_key): if meta_key == 'binning': binspatial = headarr[0]['CCDXBIN'] binspec = headarr[0]['CCDYBIN'] return parse.binning2string(binspec, binspatial) else: msgs.error("Not ready for this compound meta")
def compound_meta(self, headarr, meta_key): if meta_key == 'binning': # PypeIt frame binspatial = headarr[0]['DETXBIN'] binspec = headarr[0]['DETYBIN'] return parse.binning2string(binspec, binspatial) elif meta_key == 'mjd': time = headarr[0]['DATE-AVG'] ttime = Time(time, format='isot') return ttime.mjd else: msgs.error("Not ready for this compound meta")
def compound_meta(self, headarr, meta_key): if meta_key == 'binning': if 'HIERARCH ESO DET WIN1 BINX' in headarr[0]: binspatial = headarr[0]['HIERARCH ESO DET WIN1 BINX'] else: binspatial = 1 if 'HIERARCH ESO DET WIN1 BINY' in headarr[0]: binspec = headarr[0]['HIERARCH ESO DET WIN1 BINY'] else: binspec = 1 binning = parse.binning2string(binspec, binspatial) return binning else: msgs.error("Not ready for this compound meta")
def compound_meta(self, headarr, meta_key): """ Args: headarr: list meta_key: str Returns: value """ if meta_key == 'binning': binspatial, binspec = parse.parse_binning(headarr[0]['BINNING']) return parse.binning2string(binspec, binspatial)
def compound_meta(self, headarr, meta_key): """ Methods to generate metadata requiring interpretation of the header data, instead of simply reading the value of a header card. Args: headarr (:obj:`list`): List of `astropy.io.fits.Header`_ objects. meta_key (:obj:`str`): Metadata keyword to construct. Returns: object: Metadata value read from the header(s). """ if meta_key == 'binning': binspatial, binspec = parse.parse_binning(headarr[0]['BINNING']) binning = parse.binning2string(binspec, binspatial) return binning elif meta_key == 'slitwid': # Get the slice scale slicescale = 0.00037718 # Degrees per 'large slicer' slice ifunum = headarr[0]['IFUNUM'] if ifunum == 2: slicescale /= 2.0 elif ifunum == 3: slicescale /= 4.0 return slicescale elif meta_key == 'ra' or meta_key == 'dec': try: if self.is_nasmask(headarr[0]): hdrstr = 'RABASE' if meta_key == 'ra' else 'DECBASE' else: hdrstr = 'RA' if meta_key == 'ra' else 'DEC' except KeyError: try: hdrstr = 'TARGRA' if meta_key == 'ra' else 'TARGDEC' except KeyError: hdrstr = '' return headarr[0][hdrstr] elif meta_key == 'pressure': return headarr[0]['WXPRESS'] * 0.001 * units.bar elif meta_key == 'temperature': return headarr[0]['WXOUTTMP'] * units.deg_C elif meta_key == 'humidity': return headarr[0]['WXOUTHUM'] / 100.0 elif meta_key == 'obstime': return Time(headarr[0]['DATE-END']) else: msgs.error("Not ready for this compound meta")
def compound_meta(self, headarr, meta_key): """ Args: headarr: list meta_key: str Returns: value """ if meta_key == 'binning': binspatial, binspec = parse.parse_binning(np.array([headarr[0]['CCDXBIN'], headarr[0]['CCDYBIN']])) binning = parse.binning2string(binspatial, binspec) return binning msgs.error("Not ready for this compound meta")
def compound_meta(self, headarr, meta_key): if meta_key == 'binning': binspatial = headarr[0]['HIERARCH ESO DET WIN1 BINX'] binspec = headarr[0]['HIERARCH ESO DET WIN1 BINY'] binning = parse.binning2string(binspec, binspatial) return binning elif meta_key == 'decker': try: # Science decker = headarr[0]['HIERARCH ESO INS SLIT NAME'] except KeyError: # Standard! try: decker = headarr[0]['HIERARCH ESO SEQ SPEC TARG'] except KeyError: return None return decker else: msgs.error("Not ready for this compound meta")
def compound_meta(self, headarr, meta_key): """ Methods to generate metadata requiring interpretation of the header data, instead of simply reading the value of a header card. Args: headarr (:obj:`list`): List of `astropy.io.fits.Header`_ objects. meta_key (:obj:`str`): Metadata keyword to construct. Returns: object: Metadata value read from the header(s). """ if meta_key == 'binning': binspatial, binspec = parse.parse_binning(headarr[0]['CCDSUM']) binning = parse.binning2string(binspec, binspatial) return binning
def compound_meta(self, headarr, meta_key): """ Methods to generate metadata requiring interpretation of the header data, instead of simply reading the value of a header card. Args: headarr (:obj:`list`): List of `astropy.io.fits.Header`_ objects. meta_key (:obj:`str`): Metadata keyword to construct. Returns: object: Metadata value read from the header(s). """ if meta_key == 'binning': """ Binning in blue channel headers is space-separated rather than comma-separated. """ binspec, binspatial = headarr[0]['CCDSUM'].split() binning = parse.binning2string(binspec, binspatial) return binning elif meta_key == 'mjd': """ Need to combine 'DATE-OBS' and 'UT' headers and then use astropy to make an mjd. """ date = headarr[0]['DATE-OBS'] ut = headarr[0]['UT'] ttime = Time(f"{date}T{ut}", format='isot') return ttime.mjd elif meta_key == 'lampstat01': """ If the comparison mirror is in, there will be a 'COMPLAMP' header entry containing the lamps that are turned on. However, if the comparison mirror is out, then this header entry doesn't exist. So need to test for it and set to 'Off' if it's not there. """ if 'COMPLAMP' in headarr[0]: return headarr[0]['COMPLAMP'] else: return 'off' msgs.error( f"Not ready for compound meta, {meta_key}, for MMT Blue Channel.")
def compound_meta(self, headarr, meta_key): """ Args: headarr: list meta_key: str Returns: value """ if meta_key == 'binning': binspatial, binspec = parse.parse_binning(headarr[0]['BINNING']) return parse.binning2string(binspec, binspatial) elif meta_key == 'mjd': time = '{:s}T{:s}'.format(headarr[0]['UT-DATE'], headarr[0]['UT-TIME']) ttime = Time(time, format='isot') return ttime.mjd else: msgs.error("Not ready for this compound meta")
def compound_meta(self, headarr, meta_key): if meta_key == 'binning': binspatial, binspec = parse.parse_binning(headarr[0]['BINNING']) binning = parse.binning2string(binspec, binspatial) return binning elif 'lampstat' in meta_key: idx = int(meta_key[-2:]) curr_date = time.Time(headarr[0]['MJD-OBS'], format='mjd') # Modern -- Assuming the change occurred with the new red detector t_newlamp = time.Time("2014-02-15", format='isot') # LAMPS changed in Header if curr_date > t_newlamp: lamp_names = [ 'MERCURY', 'NEON', 'ARGON', 'CADMIUM', 'ZINC', 'KRYPTON', 'XENON', 'FEARGON', 'DEUTERI', 'FLAMP1', 'FLAMP2', 'HALOGEN' ] return headarr[0][lamp_names[ idx - 1]] # Use this index is offset by 1 else: # Original lamps plamps = headarr[0]['LAMPS'].split(',') # https: // www2.keck.hawaii.edu / inst / lris / instrument_key_list.html old_lamp_names = [ 'MERCURY', 'NEON', 'ARGON', 'CADMIUM', 'ZINC', 'HALOGEN' ] if idx <= 5: # Arcs return ('off' if plamps[idx - 1] == '0' else 'on') elif idx == 10: # Current FLAMP1 return headarr[0]['FLIMAGIN'].strip() elif idx == 11: # Current FLAMP2 return headarr[0]['FLSPECTR'].strip() elif idx == 12: # Current Halogen slot return ('off' if plamps[len(old_lamp_names) - 1] == '0' else 'on') else: # Lamp didn't exist. Set to None return 'None' else: msgs.error("Not ready for this compound meta")
def compound_meta(self, headarr, meta_key): """ Methods to generate metadata requiring interpretation of the header data, instead of simply reading the value of a header card. Args: headarr (:obj:`list`): List of `astropy.io.fits.Header`_ objects. meta_key (:obj:`str`): Metadata keyword to construct. Returns: object: Metadata value read from the header(s). """ if meta_key == 'binning': binspatial, binspec = parse.parse_binning(headarr[0]['BINNING']) return parse.binning2string(binspec, binspatial) elif meta_key == 'mjd': time = '{:s}T{:s}'.format(headarr[0]['UT-DATE'], headarr[0]['UT-TIME']) ttime = Time(time, format='isot') return ttime.mjd else: msgs.error("Not ready for this compound meta")
def compound_meta(self, headarr, meta_key): """ Methods to generate metadata requiring interpretation of the header data, instead of simply reading the value of a header card. Args: headarr (:obj:`list`): List of `astropy.io.fits.Header`_ objects. meta_key (:obj:`str`): Metadata keyword to construct. Returns: object: Metadata value read from the header(s). """ if meta_key == 'binning': binspec, binspatial = [ int(item) for item in headarr[1]['CCDSUM'].split(' ') ] return parse.binning2string(binspec, binspatial) elif meta_key == 'mjd': ttime = Time(headarr[1]['DATE-OBS'], format='isot') return ttime.mjd else: msgs.error("Not ready for this compound meta")
def compound_meta(self, headarr, meta_key): if meta_key == 'binning': binspatial, binspec = parse.parse_binning(headarr[0]['BINNING']) binning = parse.binning2string(binspec, binspatial) return binning elif meta_key == 'slitwid': # Get the slice scale slicescale = 0.00037718 # Degrees per 'large slicer' slice ifunum = headarr[0]['IFUNUM'] if ifunum == 2: slicescale /= 2.0 elif ifunum == 3: slicescale /= 4.0 return slicescale elif meta_key == 'ra' or meta_key == 'dec': try: if self.is_nasmask(headarr[0]): hdrstr = 'RABASE' if meta_key == 'ra' else 'DECBASE' else: hdrstr = 'RA' if meta_key == 'ra' else 'DEC' except KeyError: try: hdrstr = 'TARGRA' if meta_key == 'ra' else 'TARGDEC' except KeyError: hdrstr = '' return headarr[0][hdrstr] elif meta_key == 'pressure': return headarr[0]['WXPRESS'] * 0.001 * units.bar elif meta_key == 'temperature': return headarr[0]['WXOUTTMP'] * units.deg_C elif meta_key == 'humidity': return headarr[0]['WXOUTHUM'] / 100.0 elif meta_key == 'obstime': return Time(headarr[0]['DATE-END']) else: msgs.error("Not ready for this compound meta")
def compound_meta(self, headarr, meta_key): """ Args: headarr: list meta_key: str Returns: value """ if meta_key == 'binning': binspatial, binspec = parse.parse_binning(headarr[0]['BINNING']) binning = parse.binning2string(binspec, binspatial) return binning elif meta_key == 'dispangle': if headarr[0]['GRATEPOS'] == 3: return headarr[0]['G3TLTWAV'] elif headarr[0]['GRATEPOS'] == 4: return headarr[0]['G4TLTWAV'] else: debugger.set_trace() else: msgs.error("Not ready for this compound meta")
def compound_meta(self, headarr, meta_key): """ Methods to generate metadata requiring interpretation of the header data, instead of simply reading the value of a header card. Args: headarr (:obj:`list`): List of `astropy.io.fits.Header`_ objects. meta_key (:obj:`str`): Metadata keyword to construct. Returns: object: Metadata value read from the header(s). """ if meta_key == 'binning': # Binning in lois headers is space-separated (like Gemini). binspec, binspatial = parse.parse_binning(headarr[0]['CCDSUM']) return parse.binning2string(binspec, binspatial) if meta_key == 'mjd': # Use astropy to convert 'DATE-OBS' into a mjd. ttime = Time(headarr[0]['DATE-OBS'], format='isot') return ttime.mjd if meta_key == 'lampstat01': # The spectral comparison lamps turned on are listed in `LAMPCAL`, but # if no lamps are on, then this string is blank. Return either the # populated `LAMPCAL` string, or 'off' to ensure a positive entry for # `lampstat01`. lampcal = headarr[0]['LAMPCAL'].strip() return 'off' if lampcal == '' else lampcal if meta_key == 'dispname': # Convert older FITS keyword GRATING (gpmm/blaze) into the newer # Grating ID names (DVx) for easier identification of disperser. gratings = { "150/5000": "DV1", "300/4000": "DV2", "300/6750": "DV3", "400/8500": "DV4", "500/5500": "DV5", "600/4900": "DV6", "600/6750": "DV7", "831/8000": "DV8", "1200/5000": "DV9", "2160/5000": "DV10", "UNKNOWN": "DVxx" } if headarr[0]['GRATING'] not in gratings: raise ValueError( f"Grating value {headarr[0]['GRATING']} not recognized.") return f"{gratings[headarr[0]['GRATING']]} ({headarr[0]['GRATING']})" if meta_key == 'decker': # Provide a stub for future inclusion of a decker on LDT/DeVeny. return headarr[0]['DECKER'] if 'DECKER' in headarr[0].keys( ) else 'None' if meta_key == 'filter1': # Remove the parenthetical knob position to leave just the filter name return headarr[0]['FILTREAR'].split()[0].upper() if meta_key == 'cenwave': # The central wavelength is more descriptive of the grating angle position # than just the angle value. Use the DeVeny grating angle formula to # return the central wavelength of the configuration. # Extract lines/mm, catch 'UNKNOWN' grating lpmm = (np.inf if headarr[0]["GRATING"] == "UNKNOWN" else float( headarr[0]["GRATING"].split("/")[0])) # DeVeny Fixed Optical Angles in radians CAMCOL = np.deg2rad(55.00) # Camera-to-Collimator Angle COLL = np.deg2rad(10.00) # Collimator-to-Grating Angle # Grating angle in radians theta = np.deg2rad(float(headarr[0]['GRANGLE'])) # Wavelength in Angstroms wavelen = ((np.sin(COLL + theta) + np.sin(COLL + theta - CAMCOL) ) # Angles * 1.0e7 # Angstroms/mm / lpmm # lines / mm ) # Round the wavelength to the nearest 5A return np.around(wavelen / 5, decimals=0) * 5 msgs.error(f"Not ready for compound meta {meta_key} for LDT/DeVeny")