class MosaicRecipe(EmirRecipe): """ The effect of recording a series of stare images, with the same acquisition parameters, and taken by pointing to a number of sky positions, with separations of the order of the EMIR FOV. This command is designed to fully cover a given area on the sky, but can also be used to point to a number of sky positions on which acquisition is only made at the beginning. Supersky frame(s) can be built from the image series. **Observing modes:** * Mosaic images """ obresult = ObservationResultRequirement() # FIXME: this parameter is optional sources = Parameter([], 'List of x, y coordinates to measure FWHM') frame = Product(DataFrameType) catalog = Product(SourcesCatalog) def run(self, ri): return self.create_result(frame=DataFrame(None), catalog=SourcesCatalog())
class OffsetSpectraRecipe(EmirRecipe): """ Observing mode: Offset spectra beyond the slit """ obresult = ObservationResultRequirement() master_bpm = MasterBadPixelMaskRequirement() master_bias = MasterBiasRequirement() master_dark = MasterDarkRequirement() master_flat = MasterIntensityFlatFieldRequirement() master_spectral_ff = Requirement(prods.MasterSpectralFlat, 'Master spectral flatfield') st_calibration = Requirement(prods.SlitTransmissionCalibration, 'Slit tranmision calibration') w_calibration = Requirement(prods.WavelengthCalibration, 'Wavelength calibration') lines = Parameter('lines', None, 'List of x-lambda pairs of line coordinates') spectra = Product(prods.Spectra) catalog = Product(prods.LinesCatalog) def run(self, rinput): return self.create_result(spectra=prods.Spectra(), catalog=prods.LinesCatalog())
class CSUSpectraExtractionRecipe(EmirRecipe): """Extract spectra in image taken with the CSU configured""" # Recipe Requirements obresult = ObservationResultRequirement() master_bias = MasterBiasRequirement() master_dark = MasterDarkRequirement() master_flat = MasterIntensityFlatFieldRequirement() master_sky = MasterSkyRequirement() nrows_side = Parameter(5, 'Number of rows to extract around the center') slits_positions = Requirement(ArrayType, 'Positions and widths of the slits') # Recipe products frame = Product(DataFrameType) rss = Product(DataFrameType) def run(self, rinput): _logger.info('starting extraction') flow = self.init_filters(rinput) hdulist = basic_processing_with_combination(rinput, flow=flow) hdr = hdulist[0].header self.set_base_headers(hdr) data1 = hdulist[0].data _logger.info('Create output images') rssdata = numpy.zeros( (rinput.slits_positions.shape[0], data1.shape[1]), dtype='float32') nrows = rinput.nrows_side # Loop over slits for idx, slit_coords in enumerate(rinput.slits_positions): x, y, ax, ay = slit_coords # Coords in FITS coordinates ref_col = wc_to_pix(x - 1) ref_row = wc_to_pix(y - 1) _logger.info('Processing slit in column %i, row=%i', ref_col, ref_row) # Simple extraction _logger.info('Extract %i rows around center', nrows) region = data1[ref_row - nrows:ref_row + nrows + 1, :] rssdata[idx, :] = region.mean(axis=0) hdurss = fits.PrimaryHDU(rssdata) result = self.create_result(frame=hdulist, rss=hdurss) return result
class ImageSkyRecipe(BaseRecipe): obresult = Requirement(ObservationResultType, "Observation Result") master_bias = Requirement(MasterBias, "Master Bias") master_flat = Requirement(MasterFlat, "Master Flat") # This field can be disabled via # query_options: sky_image: False # in drp.yaml sky_image = Requirement( SkyImage, description="Previous Sky Image", query_opts=ResultOf('sky.sky_image', node='prev'), default=None # This value is used only if the query is disabled ) final = Product(DataFrameType) def run(self, rinput): query_sky_image = self.query_options.get('sky_image', True) if query_sky_image: self.logger.debug('using sky, value=%s', rinput.sky_image) else: self.logger.debug('not using sky, value=%s', rinput.sky_image) # Here the raw images are processed # and a final image myframe is created myframe = produce_image(rinput.obresult) result = self.create_result(final=myframe) return result
class ArcCalibrationRecipe(EmirRecipe): obresult = ObservationResultRequirement() master_bpm = MasterBadPixelMaskRequirement() master_bias = MasterBiasRequirement() master_dark = MasterDarkRequirement() lines_catalog = Requirement(LinesCatalog, "Catalog of lines") polynomial_degree = Parameter(2, 'Polynomial degree of the arc calibration') polynomial_coeffs = Product(ArrayType) def run(self, rinput): _logger.info('starting arc calibration') flow = self.init_filters(rinput) hdulist = basic_processing_with_combination(rinput, flow=flow) nslits = len(rinput.slits_catalog) coeff_table = numpy.zeros((nslits, rinput.polynomial_degree + 1)) result = self.create_result(polynomial_coeffs=coeff_table) return result
class StareSpectraRecipe(EmirRecipe): """Process images in Stare spectra mode""" obresult = ObservationResultRequirement() master_bpm = reqs.MasterBadPixelMaskRequirement() master_bias = reqs.MasterBiasRequirement() master_dark = reqs.MasterDarkRequirement() master_flat = reqs.MasterSpectralFlatFieldRequirement() master_sky = reqs.SpectralSkyRequirement(optional=True) stare = Product(prods.DataFrameType) @emirdrp.decorators.loginfo def run(self, rinput): self.logger.info('starting stare spectra reduction') flow = self.init_filters(rinput) hdulist = basic_processing_with_combination(rinput, flow, method=median) hdr = hdulist[0].header self.set_base_headers(hdr) # Update SEC to 0 hdr['SEC'] = 0 self.logger.info('end stare spectra reduction') result = self.create_result(stare=hdulist) return result
class TargetAcquisitionRecipe(EmirRecipe): """ Acquire a target. Recipe for the processing of target acquisition images. **Observing modes:** * Target acquisition """ # Requirements obresult = ObservationResultRequirement() master_bpm = MasterBadPixelMaskRequirement() master_bias = MasterBiasRequirement() master_dark = MasterDarkRequirement() master_flat = MasterIntensityFlatFieldRequirement() # Products telescope_offset = Product(TelescopeOffset) def run(self, rinput): return self.create_result(telescope_offset=TelescopeOffset())
class WavelengthCalibrationRecipe(EmirRecipe): """Recipe to calibrate the spectral response. **Observing modes:** * Wavelength calibration (4.5) **Inputs:** * List of line positions * Calibrations up to spectral flatfielding **Outputs:** * Wavelength calibration structure **Procedure:** * TBD """ master_bpm = MasterBadPixelMaskRequirement() master_bias = MasterBiasRequirement() master_dark = MasterDarkRequirement() master_flat = MasterIntensityFlatFieldRequirement() master_spectral_ff = MasterSpectralFlatFieldRequirement() cal = Product(WavelengthCalibration) def run(self, rinput): return self.create_result(cal=WavelengthCalibration())
class TestSkyCorrectRecipe(EmirRecipe): obresult = ObservationResultRequirement() master_bpm = MasterBadPixelMaskRequirement() master_bias = MasterBiasRequirement() master_dark = MasterDarkRequirement() master_flat = MasterIntensityFlatFieldRequirement() master_sky = Requirement(MasterIntensityFlat, 'Master Sky calibration') frame = Product(DataFrameType) def run(self, rinput): _logger.info('starting simple sky reduction') flow = self.init_filters(rinput) hdulist = basic_processing_with_combination(rinput, flow, method=median) hdr = hdulist[0].header self.set_base_headers(hdr) # Update SEC to 0 hdr['SEC'] = 0 result = self.create_result(frame=hdulist) return result
class DitherSkyRecipe(EmirRecipe): """Recipe to process data taken in dither sky mode. """ obresult = ObservationResultRequirement() master_bpm = MasterBadPixelMaskRequirement() master_bias = MasterBiasRequirement() master_dark = MasterDarkRequirement() master_flat = MasterIntensityFlatFieldRequirement() skyframe = Product(MasterIntensityFlat) def run(self, rinput): _logger.debug('instrument %s, mode %s', rinput.obresult.instrument, rinput.obresult.mode) _logger.info('starting sky reduction with dither') flow = self.init_filters(rinput) hdulist = basic_processing_with_segmentation(rinput, flow, method=median, errors=True) hdr = hdulist[0].header self.set_base_headers(hdr) _logger.info('end sky reduction with dither') result = self.create_result(skyframe=hdulist) return result
class SimpleSkyRecipe(EmirRecipe): """Recipe to process data taken in intensity flat-field mode. """ master_bpm = MasterBadPixelMaskRequirement() obresult = ObservationResultRequirement() master_bias = MasterBiasRequirement() master_dark = MasterDarkRequirement() master_flat = MasterIntensityFlatFieldRequirement() skyframe = Product(MasterIntensityFlat) def run(self, rinput): _logger.info('starting sky reduction') flow = self.init_filters(rinput) hdulist = basic_processing_with_combination(rinput, flow, method=median, errors=True) hdr = hdulist[0].header self.set_base_headers(hdr) result = self.create_result(skyframe=hdulist) return result
class SkySpecRecipe(EmirRecipe): """Recipe to process data taken in spectral sky mode. """ obresult = ObservationResultRequirement() master_bpm = reqs.MasterBadPixelMaskRequirement() master_bias = reqs.MasterBiasRequirement() master_dark = reqs.MasterDarkRequirement() master_flat = reqs.MasterSpectralFlatFieldRequirement() skyspec = Product(prods.SkySpectrum) def run(self, rinput): self.logger.info('starting spectral sky reduction') flow = self.init_filters(rinput) hdulist = basic_processing_with_combination(rinput, flow, method=median, errors=True) hdr = hdulist[0].header self.set_base_headers(hdr) self.logger.info('end sky spectral reduction') result = self.create_result(skyspec=hdulist) return result
class TelescopeFineFocusRecipe(EmirRecipe): """ Recipe to compute the telescope focus. **Observing modes:** * Telescope fine focus **Inputs:** * A list of images * A list of sky images * Bias, dark, flat * A model of the detector * List of focii **Outputs:** * Best focus """ master_bpm = reqs.MasterBadPixelMaskRequirement() master_bias = reqs.MasterBiasRequirement() master_dark = reqs.MasterDarkRequirement() master_flat = reqs.MasterIntensityFlatFieldRequirement() objects = Parameter([], 'List of x-y pair of object coordinates'), focus = Product(TelescopeFocus) def run(self, rinput): return self.create_result(focus=TelescopeFocus())
class DTUFocusRecipe(EmirRecipe): """ Recipe to compute the DTU focus. **Observing modes:** * EMIR focus control **Inputs:** * A list of images * A list of sky images * Bias, dark, flat * A model of the detector * List of focii **Outputs:** * Best focus """ master_bpm = reqs.MasterBadPixelMaskRequirement() master_bias = reqs.MasterBiasRequirement() master_dark = reqs.MasterDarkRequirement() master_flat = reqs.MasterIntensityFlatFieldRequirement() objects = Parameter([], 'List of x-y pair of object coordinates'), msm_pattern = Parameter([], 'List of x-y pair of slit coordinates'), dtu_focus_range = Parameter( 'dtu_focus_range', [], 'Focus range of the DTU: begin, end and step') focus = Product(DTUFocus) def run(self, rinput): return self.create_result(focus=DTUFocus())
class SlitTransmissionRecipe(EmirRecipe): """Recipe to calibrate the slit transmission. **Observing modes:** * Slit transmission calibration (4.4) **Inputs:** * A list of uniformly illuminated images of MSM **Outputs:** * A list of slit transmission functions **Procedure:** * TBD """ master_bpm = MasterBadPixelMaskRequirement() master_bias = MasterBiasRequirement() master_dark = MasterDarkRequirement() slit = Product(SlitTransmissionCalibration) def run(self, rinput): return self.create_result(slit=SlitTransmissionCalibration())
class BiasRecipe(EmirRecipe): """ Recipe to process data taken in Bias image Mode. Bias images only appear in Simple Readout mode. **Observing modes:** * Bias Image (3.1) **Inputs:** **Outputs:** * A combined bias frame, with variance extension. * Statistics of the final image per channel (mean, median, variance) **Procedure:** The list of images can be readly processed by combining them with a median algorithm. """ master_bpm = MasterBadPixelMaskRequirement() obresult = ObservationResultRequirement() biasframe = Product(MasterBias) def run(self, rinput): _logger.info('starting bias reduction') iinfo = gather_info_frames(rinput.obresult.frames) if iinfo: mode = iinfo[0]['readmode'] if mode.lower() not in EMIR_BIAS_MODES: msg = 'readmode %s, is not a bias mode' % mode _logger.error(msg) raise RecipeError(msg) flow = lambda x: x hdulist = basic_processing_with_combination(rinput, flow, method=median, errors=False) pdata = hdulist[0].data # update hdu header with # reduction keywords hdr = hdulist[0].header self.set_base_headers(hdr) hdr['CCDMEAN'] = pdata.mean() _logger.info('bias reduction ended') result = self.create_result(biasframe=DataFrame(hdulist)) return result
class IntensityFlatRecipe(EmirRecipe): """Recipe to process data taken in intensity flat-field mode. Recipe to process intensity flat-fields. The flat-on and flat-off images are combined (method?) separately and the subtracted to obtain a thermal subtracted flat-field. **Observing modes:** * Intensity Flat-Field **Inputs:** * A master dark frame * Non linearity * A model of the detector. **Outputs:** * TBD **Procedure:** * A combined thermal subtracted flat field, normalized to median 1, with with variance extension and quality flag. """ master_bpm = MasterBadPixelMaskRequirement() obresult = ObservationResultRequirement() master_bias = MasterBiasRequirement() master_dark = MasterDarkRequirement() flatframe = Product(MasterIntensityFlat) def run(self, rinput): _logger.info('starting flat reduction') errors = True flow = self.init_filters(rinput) hdulist = basic_processing_with_combination(rinput, flow, method=median, errors=errors) hdr = hdulist[0].header self.set_base_headers(hdr) mm = hdulist[0].data.mean() hdr['CCDMEAN'] = mm hdulist[0].data /= mm if errors: hdulist['variance'].data /= (mm * mm) result = self.create_result(flatframe=hdulist) return result
class CoaddRecipe(EmirRecipe): """Generic Coadd Recipe""" obresult = ObservationResultRequirement() result_coadd = Product(prods.DataFrameType) @classmethod def build_recipe_input(cls, obsres, dal, pipeline='default'): return cls.build_recipe_input_gtc(obsres, dal, pipeline=pipeline) @classmethod def build_recipe_input_gtc(cls, obsres, dal, pipeline='default'): cls.logger.debug('start recipe input builder') # This depends on the RecipeResult result_field = 'spec_abba' stareImagesIds = obsres.stareSpectraIds cls.logger.debug('Coadd images IDS %s: ', stareImagesIds) stareImages = [] for subresId in stareImagesIds: subres = dal.getRecipeResult(subresId) stareImages.append(subres['elements'][result_field]) newOR = numina.core.ObservationResult() newOR.frames = stareImages newRI = cls.create_input(obresult=newOR) cls.logger.debug('end recipe input builder') return newRI def run(self, rinput): self.logger.info('starting coadd reduction') flow = self.init_filters(rinput) nimages = len(rinput.obresult.frames) self.logger.info('we receive %d images', nimages) if nimages == 0: msg = 'Received %d images' % nimages raise numina.exceptions.RecipeError(msg) hdulist = basic_processing_with_combination( rinput, flow, method=combine.mean, prolog="Process Generic Coadd" ) hdr = hdulist[0].header self.set_base_headers(hdr) # Update SEC to 0 # hdr['SEC'] = 0 result = self.create_result(spec_coadd_abba=hdulist) self.logger.info('end coadd reduction') return result
class DarkRecipe(EmirRecipe): """Recipe to process data taken in Dark current image Mode. Recipe to process dark images. The dark images will be combined using the median. They do have to be of the same exposure time t. **Observing mode:** * Dark current Image (3.2) **Inputs:** **Outputs:** * A combined dark frame, with variance extension. """ master_bpm = MasterBadPixelMaskRequirement() obresult = ObservationResultRequirement() master_bias = MasterBiasRequirement() darkframe = Product(MasterDark) def run(self, rinput): _logger.info('starting dark reduction') flow = self.init_filters(rinput) iinfo = gather_info_frames(rinput.obresult.frames) ref_exptime = 0.0 for el in iinfo[1:]: if abs(el['texp'] - ref_exptime) > 1e-4: _logger.error('image with wrong exposure time') raise RecipeError('image with wrong exposure time') hdulist = basic_processing_with_combination(rinput, flow, method=median, errors=True) pdata = hdulist[0].data # update hdu header with # reduction keywords hdr = hdulist[0].header self.set_base_headers(hdr) hdr['CCDMEAN'] = pdata.mean() _logger.info('dark reduction ended') result = self.create_result(darkframe=hdulist) return result
class SpectralFlatRecipe(EmirRecipe): master_bpm = MasterBadPixelMaskRequirement() obresult = ObservationResultRequirement() master_bias = MasterBiasRequirement() master_dark = MasterDarkRequirement() master_flat = MasterIntensityFlatFieldRequirement() flatframe = Product(MasterSpectralFlat) def run(self, rinput): return self.create_result(flatframe=MasterSpectralFlat())
class StareImageBaseRecipe(EmirRecipe): """Process images in Stare Image Mode""" obresult = ObservationResultRequirement() master_bpm = reqs.MasterBadPixelMaskRequirement() master_bias = reqs.MasterBiasRequirement() master_dark = reqs.MasterDarkRequirement() master_flat = reqs.MasterIntensityFlatFieldRequirement() master_sky = reqs.MasterSkyRequirement(optional=True) frame = Product(DataFrameType) def __init__(self, *args, **kwargs): super(StareImageBaseRecipe, self).__init__(*args, **kwargs) if False: self.query_options['master_sky'] = Ignore() @emirdrp.decorators.loginfo @emirdrp.decorators.timeit def run(self, rinput): self.logger.info('starting stare image reduction') flow = self.init_filters(rinput) hdulist = basic_processing_with_combination( rinput, flow, method=combine.median ) hdr = hdulist[0].header self.set_base_headers(hdr) if rinput.master_bpm: hdul_bpm = rinput.master_bpm.open() hdu_bpm = generate_bpm_hdu(hdul_bpm[0]) else: hdu_bpm = generate_empty_bpm_hdu(hdulist[0]) # Append the BPM to the result hdulist.append(hdu_bpm) self.logger.info('end stare image reduction') result = self.create_result(frame=hdulist) return result def set_base_headers(self, hdr): """Set metadata in FITS headers.""" hdr = super(StareImageBaseRecipe, self).set_base_headers(hdr) # Update SEC to 0 hdr['SEC'] = 0 return hdr
class DTUFlexureRecipe(EmirRecipe): """ **Observing modes:** * DTU Flexure compensation """ obresult = ObservationResultRequirement() calibration = Product(DTUFlexureCalibration) def run(self, rinput): return self.create_result(calibration=DTUFlexureCalibration())
class AstrometricCalibrationRecipe(EmirRecipe): """ **Observing modes:** * Astrometric calibration """ obresult = ObservationResultRequirement() calibration = Product(DataFrameType) def run(self, rinput): return self.create_result(calibration=None)
class RotationCenterRecipe(EmirRecipe): """ **Observing modes:** * Centre of rotation """ obresult = ObservationResultRequirement() calibration = Product(PointingOriginCalibration) def run(self, rinput): return self.create_result(calibration=PointingOriginCalibration())
class SpectralCharacterizationRecipe(EmirRecipe): """ **Observing modes:** * Spectral characterization """ obresult = ObservationResultRequirement() calibration = Product(WavelengthCalibration) def run(self, rinput): return self.create_result(calibration=WavelengthCalibration())
class DTU_Z_CalibrationRecipe(EmirRecipe): """ **Observing modes:** * DTU Z calibration """ obresult = ObservationResultRequirement() dtu_range = Parameter([], 'DTU range: begin, end and step') calibration = Product(DTU_Z_Calibration) def run(self, rinput): return self.create_result(calibration=DTU_Z_Calibration())
class ImageRecipe(BaseRecipe): obresult = Requirement(ObservationResultType, "Observation Result") master_bias = Requirement(MasterBias, "Master Bias") master_flat = Requirement(MasterFlat, "Master Flat") final = Product(DataFrameType) def run(self, rinput): # Here the raw images are processed # and a final image myframe is created myframe = produce_image(rinput.obresult) result = self.create_result(final=myframe) return result
class SpectroPhotometricCalibrationRecipe(EmirRecipe): """ **Observing modes:** * Spectrophotometric calibration """ obresult = ObservationResultRequirement() sphot = Parameter([], 'Information about standard stars') calibration = Product(SpectroPhotometricCalibration) def run(self, rinput): return self.create_result(calibration=SpectroPhotometricCalibration())
class FocalPlaneCalibrationRecipe(EmirRecipe): """ **Observing modes:** * Lateral color """ obresult = ObservationResultRequirement() calibration = Product(PointingOriginCalibration) def run(self, rinput): return self.create_result(calibration=PointingOriginCalibration())
class TestBiasCorrectRecipe(EmirRecipe): obresult = ObservationResultRequirement() master_bpm = MasterBadPixelMaskRequirement() master_bias = MasterBiasRequirement() frame = Product(DataFrameType) def run(self, rinput): _logger.info('starting simple bias reduction') flow = self.init_filters(rinput) hdu = basic_processing_with_combination(rinput, flow, method=median) hdr = hdu.header hdr['NUMRNAM'] = (self.__class__.__name__, 'Numina recipe name') hdr['NUMRVER'] = (self.__version__, 'Numina recipe version') hdulist = fits.HDUList([hdu]) result = self.create_result(frame=hdulist) return result