def __init__(self, mstilt, slits, spectrograph, par, wavepar, det=1, qa_path=None, master_key=None, spat_flexure=None): # TODO: Perform type checking self.spectrograph = spectrograph self.par = par self.wavepar = wavepar self.mstilt = mstilt self.slits = slits self.det = det self.qa_path = qa_path self.master_key = master_key self.spat_flexure = spat_flexure # -------------------------------------------------------------- # TODO: Build another base class that does these things for both # WaveTilts and WaveCalib? # Get the non-linear count level self.nonlinear_counts = 1e10 if self.spectrograph is None \ else self.spectrograph.nonlinear_counts(self.mstilt.detector) # Set the slitmask and slit boundary related attributes that the # code needs for execution. This also deals with arcimages that # have a different binning then the trace images used to defined # the slits # TODO -- Tidy this up into one or two methods? # Load up all slits # TODO -- Discuss further with JFH all_left, all_right, mask = self.slits.select_edges(initial=True, flexure=self.spat_flexure) # Grabs all, initial slits self.tilt_bpm = np.invert(mask == 0) self.tilt_bpm_init = self.tilt_bpm.copy() # Slitmask # TODO -- Discuss further with JFH self.slitmask_science = self.slits.slit_img(initial=True, flexure=self.spat_flexure) # All unmasked slits # Resize gpm = (self.mstilt.bpm == 0) if self.mstilt.bpm is not None \ else np.ones_like(self.slitmask_science, dtype=bool) self.shape_science = self.slitmask_science.shape self.shape_tilt = self.mstilt.image.shape self.slitcen = arc.resize_slits2arc(self.shape_tilt, self.shape_science, (all_left+all_right)/2) self.slitmask = arc.resize_mask2arc(self.shape_tilt, self.slitmask_science) self.gpm = (arc.resize_mask2arc(self.shape_tilt, gpm)) & (self.mstilt.image < self.nonlinear_counts) # -------------------------------------------------------------- # Key Internals self.mask = None self.all_trace_dict = [None]*self.slits.nslits self.tilts = None # 2D fits are stored as a dictionary rather than list because we will jsonify the dict self.all_fit_dict = [None]*self.slits.nslits self.steps = [] # Main outputs self.final_tilts = None self.fit_dict = None self.trace_dict = None
def __init__(self, msarc, tslits_dict, spectrograph, par, binspectral=None, det=1, master_key=None, master_dir=None, reuse_masters=False, redux_path=None, msbpm=None): # MasterFrame masterframe.MasterFrame.__init__(self, self.frametype, master_key, master_dir, reuse_masters=reuse_masters) # Required parameters (but can be None) self.msarc = msarc self.tslits_dict = tslits_dict self.spectrograph = spectrograph self.par = par # Optional parameters self.bpm = msbpm self.binspectral = binspectral self.redux_path = redux_path self.det = det self.master_key = master_key # Attributes self.steps = [] # steps executed self.wv_calib = {} # main output self.arccen = None # central arc spectrum # TODO this code is duplicated verbatim in wavetilts. Should it be a function if self.spectrograph is not None: if self.spectrograph.detector is not None: self.nonlinear_counts = self.spectrograph.detector[self.det-1]['saturation']*self.spectrograph.detector[self.det-1]['nonlinear'] else: self.nonlinear_counts=1e10 # Set the slitmask and slit boundary related attributes that the code needs for execution. This also deals with # arcimages that have a different binning then the trace images used to defined the slits if self.tslits_dict is not None and self.msarc is not None: self.slitmask_science = pixels.tslits2mask(self.tslits_dict) inmask = (self.bpm == 0) if self.bpm is not None else np.ones_like(self.slitmask_science, dtype=bool) self.shape_science = self.slitmask_science.shape self.shape_arc = self.msarc.shape self.nslits = self.tslits_dict['slit_left'].shape[1] self.slit_left = arc.resize_slits2arc(self.shape_arc, self.shape_science, self.tslits_dict['slit_left']) self.slit_righ = arc.resize_slits2arc(self.shape_arc, self.shape_science, self.tslits_dict['slit_righ']) self.slitcen = arc.resize_slits2arc(self.shape_arc, self.shape_science, self.tslits_dict['slitcen']) self.slitmask = arc.resize_mask2arc(self.shape_arc, self.slitmask_science) self.inmask = arc.resize_mask2arc(self.shape_arc,inmask) # TODO -- Remove the following two lines if deemed ok if self.par['method'] != 'full_template': self.inmask &= self.msarc < self.nonlinear_counts else: self.slitmask_science = None self.shape_science = None self.shape_arc = None self.nslits = 0 self.slit_left = None self.slit_righ = None self.slitcen = None self.slitmask = None self.inmask = None
def __init__(self, msarc, tslits_dict, spectrograph, par, wavepar, det=1, master_key=None, master_dir=None, reuse_masters=False, redux_path=None, bpm=None): self.spectrograph = spectrograph self.par = par # pypeitpar.WaveTiltsPar() if par is None else par self.wavepar = wavepar # pypeitpar.WavelengthSolutionPar() if wavepar is None else wavepar # MasterFrame masterframe.MasterFrame.__init__(self, self.frametype, master_key, master_dir, reuse_masters=reuse_masters) # Parameters (but can be None) self.msarc = msarc self.tslits_dict = tslits_dict self.bpm = bpm # Optional parameters self.det = det self.redux_path = redux_path # if self.spectrograph is not None: self.nonlinear_counts = self.spectrograph.detector[self.det-1]['saturation']*self.spectrograph.detector[self.det-1]['nonlinear'] else: self.nonlinear_counts=1e10 # Set the slitmask and slit boundary related attributes that the code needs for execution. This also deals with # arcimages that have a different binning then the trace images used to defined the slits if self.tslits_dict is not None and self.msarc is not None: self.slitmask_science = pixels.tslits2mask(self.tslits_dict) inmask = (self.bpm == 0) if self.bpm is not None else np.ones_like(self.slitmask_science, dtype=bool) self.shape_science = self.slitmask_science.shape self.shape_arc = self.msarc.shape self.nslits = self.tslits_dict['slit_left'].shape[1] self.slit_left = arc.resize_slits2arc(self.shape_arc, self.shape_science, self.tslits_dict['slit_left']) self.slit_righ = arc.resize_slits2arc(self.shape_arc, self.shape_science, self.tslits_dict['slit_righ']) self.slitcen = arc.resize_slits2arc(self.shape_arc, self.shape_science, self.tslits_dict['slitcen']) self.slitmask = arc.resize_mask2arc(self.shape_arc, self.slitmask_science) self.inmask = (arc.resize_mask2arc(self.shape_arc, inmask)) & (self.msarc < self.nonlinear_counts) else: self.slitmask_science = None self.shape_science = None self.shape_arc = None self.nslits = 0 self.slit_left = None self.slit_righ = None self.slitcen = None self.slitmask = None self.inmask = None # Key Internals self.mask = None self.all_trace_dict = [None]*self.nslits self.tilts = None # 2D fits are stored as a dictionary rather than list because we will jsonify the dict self.all_fit_dict = [None]*self.nslits self.steps = [] # Main outputs self.final_tilts = None self.fit_dict = None self.trace_dict = None
def __init__(self, msarc, tslits_dict, spectrograph, par, binspectral=None, det=1, master_key=None, master_dir=None, reuse_masters=False, qa_path=None, msbpm=None): # MasterFrame masterframe.MasterFrame.__init__(self, self.master_type, master_dir=master_dir, master_key=master_key, file_format='json', reuse_masters=reuse_masters) # Required parameters (but can be None) self.msarc = msarc self.tslits_dict = tslits_dict self.spectrograph = spectrograph self.par = par # Optional parameters self.bpm = msbpm self.binspectral = binspectral self.qa_path = qa_path self.det = det self.master_key = master_key # Attributes self.steps = [] # steps executed self.wv_calib = {} # main output self.arccen = None # central arc spectrum # -------------------------------------------------------------- # TODO: Build another base class that does these things for both # WaveTilts and WaveCalib? # Get the non-linear count level self.nonlinear_counts = 1e10 if self.spectrograph is None \ else self.spectrograph.nonlinear_counts(det=self.det) # Set the slitmask and slit boundary related attributes that the # code needs for execution. This also deals with arcimages that # have a different binning then the trace images used to defined # the slits if self.tslits_dict is not None and self.msarc is not None: self.slitmask_science = pixels.tslits2mask(self.tslits_dict) inmask = self.bpm == 0 if self.bpm is not None \ else np.ones_like(self.slitmask_science, dtype=bool) self.shape_science = self.slitmask_science.shape self.shape_arc = self.msarc.shape self.nslits = self.tslits_dict['slit_left'].shape[1] self.slit_left = arc.resize_slits2arc( self.shape_arc, self.shape_science, self.tslits_dict['slit_left']) self.slit_righ = arc.resize_slits2arc( self.shape_arc, self.shape_science, self.tslits_dict['slit_righ']) self.slitcen = arc.resize_slits2arc(self.shape_arc, self.shape_science, self.tslits_dict['slitcen']) self.slitmask = arc.resize_mask2arc(self.shape_arc, self.slitmask_science) self.inmask = arc.resize_mask2arc(self.shape_arc, inmask) # TODO: Remove the following two lines if deemed ok if self.par['method'] != 'full_template': self.inmask &= self.msarc < self.nonlinear_counts self.slit_spat_pos = trace_slits.slit_spat_pos(self.tslits_dict) else: self.slitmask_science = None self.shape_science = None self.shape_arc = None self.nslits = 0 self.slit_left = None self.slit_righ = None self.slitcen = None self.slitmask = None self.inmask = None
def __init__(self, msarc, tslits_dict, spectrograph, par, wavepar, det=1, master_key=None, master_dir=None, reuse_masters=False, qa_path=None, msbpm=None): self.spectrograph = spectrograph self.par = par self.wavepar = wavepar # MasterFrame masterframe.MasterFrame.__init__(self, self.master_type, master_dir=master_dir, master_key=master_key, reuse_masters=reuse_masters) self.msarc = msarc self.tslits_dict = tslits_dict self.msbpm = msbpm self.det = det self.qa_path = qa_path # -------------------------------------------------------------- # TODO: Build another base class that does these things for both # WaveTilts and WaveCalib? # Get the non-linear count level self.nonlinear_counts = 1e10 if self.spectrograph is None \ else self.spectrograph.nonlinear_counts(det=self.det) # Set the slitmask and slit boundary related attributes that the # code needs for execution. This also deals with arcimages that # have a different binning then the trace images used to defined # the slits if self.tslits_dict is not None and self.msarc is not None: self.slitmask_science = pixels.tslits2mask(self.tslits_dict) inmask = (self.msbpm == 0) if self.msbpm is not None \ else np.ones_like(self.slitmask_science, dtype=bool) self.shape_science = self.slitmask_science.shape self.shape_arc = self.msarc.shape self.nslits = self.tslits_dict['slit_left'].shape[1] self.slit_left = arc.resize_slits2arc( self.shape_arc, self.shape_science, self.tslits_dict['slit_left']) self.slit_righ = arc.resize_slits2arc( self.shape_arc, self.shape_science, self.tslits_dict['slit_righ']) self.slitcen = arc.resize_slits2arc(self.shape_arc, self.shape_science, self.tslits_dict['slitcen']) self.slitmask = arc.resize_mask2arc(self.shape_arc, self.slitmask_science) self.inmask = (arc.resize_mask2arc( self.shape_arc, inmask)) & (self.msarc < self.nonlinear_counts) else: self.slitmask_science = None self.shape_science = None self.shape_arc = None self.nslits = 0 self.slit_left = None self.slit_righ = None self.slitcen = None self.slitmask = None self.inmask = None # -------------------------------------------------------------- # Key Internals self.mask = None self.all_trace_dict = [None] * self.nslits self.tilts = None # 2D fits are stored as a dictionary rather than list because we will jsonify the dict self.all_fit_dict = [None] * self.nslits self.steps = [] # Main outputs self.final_tilts = None self.fit_dict = None self.trace_dict = None
def __init__(self, msarc, slits, spectrograph, par, binspectral=None, det=1, qa_path=None, msbpm=None, master_key=None): # Required parameters (but can be None) self.msarc = msarc self.slits = slits self.spectrograph = spectrograph self.par = par # Optional parameters self.bpm = msbpm if self.bpm is None: if msarc is not None: # Can be None for load; will remove this for DataContainer self.bpm = msarc.bpm self.binspectral = binspectral self.qa_path = qa_path self.det = det self.master_key = master_key # Attributes self.steps = [] # steps executed self.wv_calib = {} # main output self.arccen = None # central arc spectrum # Get the non-linear count level self.nonlinear_counts = 1e10 if self.spectrograph is None \ else self.spectrograph.nonlinear_counts(self.msarc.detector) #else self.spectrograph.nonlinear_counts(self.det) # -------------------------------------------------------------- # TODO: Build another base class that does these things for both # WaveTilts and WaveCalib? # Set the slitmask and slit boundary related attributes that the # code needs for execution. This also deals with arcimages that # have a different binning then the trace images used to defined # the slits if self.slits is not None and self.msarc is not None: # Load up slits # TODO -- Allow for flexure all_left, all_right, mask = self.slits.select_edges( initial=True, flexure=None) # Grabs all, init slits + flexure self.orders = self.slits.ech_order # Can be None # self.spat_coo = self.slits.spatial_coordinates() # All slits, even masked # Internal mask for failed wv_calib analysis # TODO -- Allow for an option to re-attempt those previously flagged as BADWVCALIB? self.wvc_bpm = np.invert(mask == 0) self.wvc_bpm_init = self.wvc_bpm.copy() # Slitmask -- Grabs only unmasked, initial slits self.slitmask_science = self.slits.slit_img(initial=True, flexure=None) # Resize self.shape_science = self.slitmask_science.shape self.shape_arc = self.msarc.image.shape # slitcen is padded to include slits that may be masked, for convenience in coding downstream self.slitcen = arc.resize_slits2arc(self.shape_arc, self.shape_science, (all_left + all_right) / 2) self.slitmask = arc.resize_mask2arc(self.shape_arc, self.slitmask_science) # Mask gpm = self.bpm == 0 if self.bpm is not None \ else np.ones_like(self.slitmask_science, dtype=bool) self.gpm = arc.resize_mask2arc(self.shape_arc, gpm) # We want even the saturated lines in full_template for the cross-correlation # They will be excised in the detect_lines() method on the extracted arc if self.par['method'] != 'full_template': self.gpm &= self.msarc.image < self.nonlinear_counts else: self.orders = None self.wvc_bpm = None self.wvc_bpm_init = None self.slitmask_science = None self.shape_science = None self.shape_arc = None self.slitcen = None self.slitmask = None self.gpm = None
def __init__(self, mstilt, slits, spectrograph, par, wavepar, det=1, qa_path=None, master_key=None, spat_flexure=None): # TODO: Perform type checking self.spectrograph = spectrograph self.par = par self.wavepar = wavepar self.mstilt = mstilt self.slits = slits self.det = det self.qa_path = qa_path self.master_key = master_key self.spat_flexure = spat_flexure # Get the non-linear count level # TODO: This is currently hacked to deal with Mosaics try: self.nonlinear_counts = self.mstilt.detector.nonlinear_counts() except: self.nonlinear_counts = 1e10 # # Get the non-linear count level # self.nonlinear_counts = 1e10 if self.spectrograph is None \ # else self.mstilt.detector.nonlinear_counts() ## else self.spectrograph.nonlinear_counts(self.mstilt.detector) # Set the slitmask and slit boundary related attributes that the # code needs for execution. This also deals with arcimages that # have a different binning then the trace images used to defined # the slits # TODO -- Tidy this up into one or two methods? # Load up all slits # TODO -- Discuss further with JFH all_left, all_right, mask = self.slits.select_edges( initial=True, flexure=self.spat_flexure) # Grabs all, initial slits # self.tilt_bpm = np.invert(mask == 0) # At this point of the reduction the only bitmask flags that may have been generated are 'USERIGNORE', # 'SHORTSLIT', 'BOXSLIT' and 'BADWVCALIB'. Here we use only 'USERIGNORE' and 'SHORTSLIT' to create the bpm mask self.tilt_bpm = self.slits.bitmask.flagged( mask, flag=['SHORTSLIT', 'USERIGNORE']) self.tilt_bpm_init = self.tilt_bpm.copy() # Slitmask # TODO -- Discuss further with JFH self.slitmask_science = self.slits.slit_img( initial=True, flexure=self.spat_flexure, exclude_flag=['BOXSLIT']) # All unmasked slits # Resize gpm = (self.mstilt.bpm == 0) if self.mstilt.bpm is not None \ else np.ones_like(self.slitmask_science, dtype=bool) self.shape_science = self.slitmask_science.shape self.shape_tilt = self.mstilt.image.shape self.slitcen = arc.resize_slits2arc(self.shape_tilt, self.shape_science, (all_left + all_right) / 2) self.slitmask = arc.resize_mask2arc(self.shape_tilt, self.slitmask_science) self.gpm = (arc.resize_mask2arc(self.shape_tilt, gpm)) & ( self.mstilt.image < self.nonlinear_counts) # -------------------------------------------------------------- # Key Internals self.mask = None self.all_trace_dict = [None] * self.slits.nslits self.tilts = None # 2D fits are stored as a dictionary rather than list because we will jsonify the dict self.all_fit_dict = [None] * self.slits.nslits self.steps = [] # Main outputs self.final_tilts = None self.fit_dict = None self.trace_dict = None
def __init__(self, msarc, slits, spectrograph, par, lamps, binspectral=None, det=1, qa_path=None, msbpm=None, master_key=None): # TODO: This should be a stop-gap to avoid instantiation of this with # any Nones. if None in [msarc, slits, spectrograph, par, lamps]: msgs.error( 'CODING ERROR: Cannot instantiate BuildWaveCalib with Nones.') # Required parameters self.msarc = msarc self.slits = slits self.spectrograph = spectrograph self.par = par self.lamps = lamps # Optional parameters self.bpm = self.msarc.select_flag( flag='BPM') if msbpm is None else msbpm.astype(bool) if self.bpm.shape != self.msarc.shape: msgs.error( 'Bad-pixel mask is not the same shape as the arc image.') # self.bpm = msbpm # if self.bpm is None and msarc is not None: # # msarc can be None for load; will remove this for DataContainer # self.bpm = msarc.bpm self.binspectral = binspectral self.qa_path = qa_path self.det = det self.master_key = master_key # Attributes self.steps = [] # steps executed self.wv_calib = {} # main output self.arccen = None # central arc spectrum # Get the non-linear count level # TODO: This is currently hacked to deal with Mosaics try: self.nonlinear_counts = self.msarc.detector.nonlinear_counts() except: self.nonlinear_counts = 1e10 # self.nonlinear_counts = 1e10 if self.spectrograph is None \ # else self.spectrograph.nonlinear_counts(self.msarc.detector) #else self.spectrograph.nonlinear_counts(self.det) # -------------------------------------------------------------- # TODO: Build another base class that does these things for both # WaveTilts and WaveCalib? # Set the slitmask and slit boundary related attributes that the # code needs for execution. This also deals with arcimages that # have a different binning then the trace images used to defined # the slits if self.slits is not None and self.msarc is not None: # Load up slits # TODO -- Allow for flexure all_left, all_right, mask = self.slits.select_edges( initial=True, flexure=None) # Grabs all, init slits + flexure self.orders = self.slits.ech_order # Can be None # self.spat_coo = self.slits.spatial_coordinates() # All slits, even masked # Internal mask for failed wv_calib analysis # TODO -- Allow for an option to re-attempt those previously flagged as BADWVCALIB? self.wvc_bpm = np.invert(mask == 0) ## We want to keep the 'BOXSLIT', which mask value is 2. But we don't want to keep 'BOXSLIT' ## with other bad flag (for which the mask value would be > 2) #self.wvc_bpm = mask > 2 self.wvc_bpm_init = self.wvc_bpm.copy() # Slitmask -- Grabs only unmasked, initial slits #self.slitmask_science = self.slits.slit_img(initial=True, flexure=None, exclude_flag=['BOXSLIT']) self.slitmask_science = self.slits.slit_img(initial=True, flexure=None) # Resize self.shape_science = self.slitmask_science.shape self.shape_arc = self.msarc.image.shape # slitcen is padded to include slits that may be masked, for convenience in coding downstream self.slitcen = arc.resize_slits2arc(self.shape_arc, self.shape_science, (all_left + all_right) / 2) self.slitmask = arc.resize_mask2arc(self.shape_arc, self.slitmask_science) # Mask gpm = self.bpm == 0 if self.bpm is not None \ else np.ones_like(self.slitmask_science, dtype=bool) self.gpm = arc.resize_mask2arc(self.shape_arc, gpm) # We want even the saturated lines in full_template for the cross-correlation # They will be excised in the detect_lines() method on the extracted arc if self.par['method'] != 'full_template': self.gpm &= self.msarc.image < self.nonlinear_counts else: self.orders = None self.wvc_bpm = None self.wvc_bpm_init = None self.slitmask_science = None self.shape_science = None self.shape_arc = None self.slitcen = None self.slitmask = None self.gpm = None
def spat_flexure_shift(sciimg, slits, debug=False, maxlag=20): """ Calculate a rigid flexure shift in the spatial dimension between the slitmask and the science image. It is *important* to use original=True when defining the slitmask as everything should be relative to the initial slits Otherwise, the WaveTilts could get out of sync with science images Args: sciimg (`numpy.ndarray`_): slits (:class:`pypeit.slittrace.SlitTraceSet`): maxlag (:obj:`int`, optional): Maximum flexure searched for Returns: float: The spatial flexure shift relative to the initial slits """ # Mask -- Includes short slits and those excluded by the user (e.g. ['rdx']['slitspatnum']) slitmask = slits.slit_img(initial=True, exclude_flag=slits.bitmask.exclude_for_flexure) _sciimg = sciimg if slitmask.shape == sciimg.shape \ else arc.resize_mask2arc(slitmask.shape, sciimg) onslits = slitmask > -1 corr_slits = onslits.astype(float).flatten() # Compute mean_sci, med_sci, stddev_sci = stats.sigma_clipped_stats(_sciimg[onslits]) thresh = med_sci + 5.0 * stddev_sci corr_sci = np.fmin(_sciimg.flatten(), thresh) lags, xcorr = utils.cross_correlate(corr_sci, corr_slits, maxlag) xcorr_denom = np.sqrt( np.sum(corr_sci * corr_sci) * np.sum(corr_slits * corr_slits)) xcorr_norm = xcorr / xcorr_denom # TODO -- Generate a QA plot tampl_true, tampl, pix_max, twid, centerr, ww, arc_cont, nsig \ = arc.detect_lines(xcorr_norm, sigdetect=3.0, fit_frac_fwhm=1.5, fwhm=5.0, cont_frac_fwhm=1.0, cont_samp=30, nfind=1, debug=debug) # No peak? -- e.g. data fills the entire detector if len(tampl) == 0: msgs.warn( 'No peak found in spatial flexure. Assuming there is none..') if debug: embed(header='68 of flexure') return 0. # Find the peak xcorr_max = np.interp(pix_max, np.arange(lags.shape[0]), xcorr_norm) lag_max = np.interp(pix_max, np.arange(lags.shape[0]), lags) msgs.info('Spatial flexure measured: {}'.format(lag_max[0])) if debug: plt.figure(figsize=(14, 6)) plt.plot(lags, xcorr_norm, color='black', drawstyle='steps-mid', lw=3, label='x-corr', linewidth=1.0) plt.plot(lag_max[0], xcorr_max[0], 'g+', markersize=6.0, label='peak') plt.title('Best shift = {:5.3f}'.format(lag_max[0]) + ', corr_max = {:5.3f}'.format(xcorr_max[0])) plt.legend() plt.show() #tslits_shift = trace_slits.shift_slits(tslits_dict, lag_max) # Now translate the tilts #slitmask_shift = pixels.tslits2mask(tslits_shift) #slitmask_shift = slits.slit_img(flexure=lag_max[0]) if debug: # Now translate the slits in the tslits_dict all_left_flexure, all_right_flexure, mask = slits.select_edges( flexure=lag_max[0]) gpm = mask == 0 viewer, ch = display.show_image(_sciimg) #display.show_slits(viewer, ch, left_flexure[:,gpm], right_flexure)[:,gpm]#, slits.id) #, args.det) embed(header='83 of flexure.py') return lag_max[0]
def __init__(self, msalign, tslits_dict, spectrograph, par, det=1, binning=None, qa_path=None, msbpm=None): # MasterFrame #masterframe.MasterFrame.__init__(self, self.master_type, master_dir=master_dir, # master_key=master_key, file_format='fits', # reuse_masters=reuse_masters) # Required parameters (but can be None) self.msalign = msalign self.tslits_dict = tslits_dict self.spectrograph = spectrograph self.par = par self.binning = binning # Optional parameters self.bpm = msalign.mask if msbpm is None else msbpm self.qa_path = qa_path self.det = det #self.master_key = master_key # Attributes self.viewer, self.channel = None, None self.steps = [] # steps executed # Get the non-linear count level self.nonlinear_counts = 1e10 if self.spectrograph is None \ else self.spectrograph.nonlinear_counts(self.det) # -------------------------------------------------------------- # Set the slitmask and slit boundary related attributes that the # code needs for execution. This also deals with alignframes that # have a different binning then the images used to defined # the slits if self.tslits_dict is not None and self.msalign is not None: self.slitmask_science = pixels.tslits2mask(self.tslits_dict) gpm = self.bpm == 0 if self.bpm is not None \ else np.ones_like(self.slitmask_science, dtype=bool) self.shape_science = self.slitmask_science.shape self.shape_align = self.msalign.image.shape self.nslits = self.tslits_dict['slit_left'].shape[1] self.slit_left = arc.resize_slits2arc( self.shape_align, self.shape_science, self.tslits_dict['slit_left']) self.slit_righ = arc.resize_slits2arc( self.shape_align, self.shape_science, self.tslits_dict['slit_righ']) self.slitcen = arc.resize_slits2arc(self.shape_align, self.shape_science, self.tslits_dict['slitcen']) self.slitmask = arc.resize_mask2arc(self.shape_align, self.slitmask_science) self.gpm = arc.resize_mask2arc(self.shape_align, gpm) self.gpm &= self.msalign.image < self.nonlinear_counts self.slit_spat_pos = edgetrace.slit_spat_pos( self.tslits_dict['slit_left'], self.tslits_dict['slit_righ'], self.tslits_dict['nspec'], self.tslits_dict['nspat']) else: self.slitmask_science = None self.shape_science = None self.shape_align = None self.nslits = 0 self.slit_left = None self.slit_righ = None self.slitcen = None self.slitmask = None self.gpm = None self.nonlinear_counts = None