def test_all2dobj_update_image(init_dict): allspec2D = spec2dobj.AllSpec2DObj() allspec2D['meta']['bkg_redux'] = False allspec2D['meta']['find_negative'] = False for i in range(2): d = load_spectrograph('keck_deimos').get_detector_par(i + 1) allspec2D[d.name] = spec2dobj.Spec2DObj(detector=d, **init_dict) # Write ofile = tstutils.data_path('tst_allspec2d.fits') if os.path.isfile(ofile): os.remove(ofile) allspec2D.write_to_fits(ofile) _allspec2D = spec2dobj.AllSpec2DObj() _allspec2D['meta']['bkg_redux'] = False _allspec2D['meta']['find_negative'] = False d = load_spectrograph('keck_deimos').get_detector_par(2) detname = d.name init_dict['sciimg'] = allspec2D[detname].sciimg.copy() * 2 _allspec2D[detname] = spec2dobj.Spec2DObj(detector=d, **init_dict) _allspec2D.write_to_fits(ofile, update_det=_allspec2D.detectors, overwrite=True) # Check allspec2D_2 = spec2dobj.AllSpec2DObj.from_fits(ofile) assert np.array_equal(allspec2D_2[detname].sciimg, _allspec2D[detname].sciimg), 'Bad update' assert np.array_equal(allspec2D_2[detname].sciimg, allspec2D[detname].sciimg * 2), 'Bad update' os.remove(ofile)
def test_all2dobj_update_image(init_dict): # Build two spec2DObj1 = spec2dobj.Spec2DObj(**init_dict) spec2DObj2 = spec2dobj.Spec2DObj(**init_dict) spec2DObj2.det = 2 # allspec2D = spec2dobj.AllSpec2DObj() allspec2D['meta']['ir_redux'] = False allspec2D[1] = spec2DObj1 allspec2D[2] = spec2DObj2 # Write ofile = data_path('tst_allspec2d.fits') if os.path.isfile(ofile): os.remove(ofile) allspec2D.write_to_fits(ofile) # Update _allspec2D = spec2dobj.AllSpec2DObj() spec2DObj1.sciimg = spec2DObj1.sciimg.copy() * 2. _allspec2D['meta']['ir_redux'] = False _allspec2D[1] = spec2DObj1 _allspec2D.write_to_fits(ofile, update_det=1, overwrite=True) # Check allspec2D_2 = spec2dobj.AllSpec2DObj.from_fits(ofile) assert np.array_equal(allspec2D_2[1].sciimg, spec2DObj1.sciimg) os.remove(ofile)
def test_all2dobj_write(init_dict): # Build one init_dict['detector'] = tstutils.get_kastb_detector() spec2DObj = spec2dobj.Spec2DObj(**init_dict) allspec2D = spec2dobj.AllSpec2DObj() allspec2D['meta']['bkg_redux'] = False allspec2D['meta']['find_negative'] = False detname = spec2DObj.detname allspec2D[detname] = spec2DObj # Write ofile = tstutils.data_path('tst_allspec2d.fits') if os.path.isfile(ofile): os.remove(ofile) allspec2D.write_to_fits(ofile) # Read _allspec2D = spec2dobj.AllSpec2DObj.from_fits(ofile) # Check assert allspec2D.detectors == _allspec2D.detectors, 'Bad read: detector mismatch' assert allspec2D['meta'] == _allspec2D['meta'], 'Bad read: meta mismatch' # Try to update it _allspec2D['meta']['bkg_redux'] = True _allspec2D[detname].vel_corr = 2. _allspec2D.write_to_fits(ofile, update_det='DET01') __allspec2D = spec2dobj.AllSpec2DObj.from_fits(ofile) assert __allspec2D['meta'] == _allspec2D['meta'], 'Bad read: meta mismatch' assert __allspec2D['meta'] != allspec2D['meta'], 'Bad read: meta mismatch' assert __allspec2D[detname].vel_corr == 2., 'Bad update' os.remove(ofile)
def test_spec2dobj_update_slit(init_dict): # Build two spec2DObj1 = spec2dobj.Spec2DObj(**init_dict) spec2DObj2 = spec2dobj.Spec2DObj(**init_dict) # Checks spec2DObj2.det = 2 with pytest.raises(pypmsgs.PypeItError): spec2DObj1.update_slits(spec2DObj2) # Update spec2DObj2.det = 1 spec2DObj2.sciimg = spec2DObj1.sciimg.copy() * 2. spec2DObj2.slits.mask[1:] = 1 spec2DObj1.update_slits(spec2DObj2)
def test_spec2dobj_update_slit(init_dict): # Build two spec2DObj1 = spec2dobj.Spec2DObj(**init_dict, detector=load_spectrograph( 'keck_deimos').get_detector_par(1)) spec2DObj2 = spec2dobj.Spec2DObj(**init_dict, detector=load_spectrograph( 'keck_deimos').get_detector_par(2)) # Checks with pytest.raises(pypmsgs.PypeItError): spec2DObj1.update_slits(spec2DObj2) # Update spec2DObj2.detector = load_spectrograph('keck_deimos').get_detector_par(1) spec2DObj2.sciimg = spec2DObj1.sciimg.copy() * 2. spec2DObj2.slits.mask[1:] = 1 spec2DObj1.update_slits(spec2DObj2)
def test_spec2dobj_io(init_dict): init_dict['detector'] = tstutils.get_kastb_detector() spec2DObj = spec2dobj.Spec2DObj(**init_dict) # Write ofile = tstutils.data_path('tst_spec2d.fits') if os.path.isfile(ofile): os.remove(ofile) spec2DObj.to_file(ofile) # Read _spec2DObj = spec2dobj.Spec2DObj.from_file(ofile, spec2DObj.detname) os.remove(ofile)
def test_all2dobj_hdr(init_dict): # Build one spec2DObj = spec2dobj.Spec2DObj(**init_dict) allspec2D = spec2dobj.AllSpec2DObj() allspec2D['meta']['ir_redux'] = False allspec2D[1] = spec2DObj # kast_file = data_path('b1.fits.gz') header = fits.getheader(kast_file) spectrograph = load_spectrograph('shane_kast_blue') # Do it hdr = allspec2D.build_primary_hdr(header, spectrograph, master_dir=data_path('')) # Test it assert hdr['SKYSUB'] == 'MODEL'
def test_all2dobj_hdr(init_dict): # Build one init_dict['detector'] = tstutils.get_kastb_detector() spec2DObj = spec2dobj.Spec2DObj(**init_dict) allspec2D = spec2dobj.AllSpec2DObj() allspec2D['meta']['bkg_redux'] = False allspec2D['meta']['find_negative'] = False allspec2D[spec2DObj.detname] = spec2DObj # kast_file = tstutils.data_path('b1.fits.gz') header = fits.getheader(kast_file) spectrograph = load_spectrograph('shane_kast_blue') # Do it hdr = allspec2D.build_primary_hdr(header, spectrograph, master_dir=tstutils.data_path('')) # Test it assert hdr['SKYSUB'] == 'MODEL'
def test_all2dobj_write(init_dict): # Build one spec2DObj = spec2dobj.Spec2DObj(**init_dict) allspec2D = spec2dobj.AllSpec2DObj() allspec2D['meta']['ir_redux'] = False allspec2D[1] = spec2DObj allspec2D[1].detector = tstutils.get_kastb_detector() # Write ofile = data_path('tst_allspec2d.fits') if os.path.isfile(ofile): os.remove(ofile) allspec2D.write_to_fits(ofile) # Read _allspec2D = spec2dobj.AllSpec2DObj.from_fits(ofile) # Write again os.remove(ofile) _allspec2D.write_to_fits(ofile) os.remove(ofile)
def test_init(init_dict): init_dict['detector'] = tstutils.get_kastb_detector() spec2DObj = spec2dobj.Spec2DObj(**init_dict) # Check assert spec2DObj.hdu_prefix == 'DET01-'
def main(args): """ Executes 2d coadding """ msgs.warn('PATH =' + os.getcwd()) # Load the file if args.file is not None: spectrograph_name, config_lines, spec2d_files = io.read_spec2d_file( args.file, filetype="coadd2d") spectrograph = load_spectrograph(spectrograph_name) # Parameters # TODO: Shouldn't this reinstantiate the same parameters used in # the PypeIt run that extracted the objects? Why are we not # just passing the pypeit file? # JFH: The reason is that the coadd2dfile may want different reduction parameters spectrograph_def_par = spectrograph.default_pypeit_par() parset = par.PypeItPar.from_cfg_lines( cfg_lines=spectrograph_def_par.to_config(), merge_with=config_lines) elif args.obj is not None: # TODO: We should probably be reading the pypeit file and using those parameters here rather than using the # default parset. # TODO: This needs to define the science path spec2d_files = glob.glob('./Science/spec2d_*' + args.obj + '*') head0 = fits.getheader(spec2d_files[0]) spectrograph_name = head0['PYP_SPEC'] spectrograph = load_spectrograph(spectrograph_name) parset = spectrograph.default_pypeit_par() else: msgs.error( 'You must either input a coadd2d file with --file or an object name with --obj' ) # Update with configuration specific parameters (which requires science file) and initialize spectrograph spectrograph_cfg_lines = spectrograph.config_specific_par( spec2d_files[0]).to_config() parset = par.PypeItPar.from_cfg_lines(cfg_lines=spectrograph_cfg_lines, merge_with=parset.to_config()) # If detector was passed as an argument override whatever was in the coadd2d_file if args.det is not None: msgs.info("Restricting reductions to detector={}".format(args.det)) parset['rdx']['detnum'] = int(args.det) # Get headers (if possible) and base names spec1d_files = [ files.replace('spec2d', 'spec1d') for files in spec2d_files ] head1d = None for spec1d_file in spec1d_files: if os.path.isfile(spec1d_file): head1d = fits.getheader(spec1d_file) break if head1d is None: msgs.warn("No 1D spectra so am generating a dummy header for output") head1d = io.initialize_header() head2d = fits.getheader(spec2d_files[0]) if args.basename is None: filename = os.path.basename(spec2d_files[0]) basename = filename.split('_')[2] else: basename = args.basename # Write the par to disk par_outfile = basename + '_coadd2d.par' print("Writing the parameters to {}".format(par_outfile)) parset.to_config(par_outfile) # Now run the coadds skysub_mode = head2d['SKYSUB'] ir_redux = True if 'DIFF' in skysub_mode else False # Print status message msgs_string = 'Reducing target {:s}'.format(basename) + msgs.newline() msgs_string += 'Performing coadd of frames reduce with {:s} imaging'.format( skysub_mode) msgs_string += msgs.newline( ) + 'Combining frames in 2d coadd:' + msgs.newline() for file in spec2d_files: msgs_string += '{0:s}'.format(os.path.basename(file)) + msgs.newline() msgs.info(msgs_string) # TODO: This needs to be added to the parameter list for rdx redux_path = os.getcwd() master_dirname = os.path.basename(head2d['PYPMFDIR']) + '_coadd' master_dir = os.path.join(redux_path, master_dirname) # Make the new Master dir if not os.path.isdir(master_dir): msgs.info( 'Creating directory for Master output: {0}'.format(master_dir)) os.makedirs(master_dir) # Instantiate the sci_dict sci_dict = OrderedDict() # This needs to be ordered sci_dict['meta'] = {} sci_dict['meta']['vel_corr'] = 0. sci_dict['meta']['ir_redux'] = ir_redux # Find the detectors to reduce detectors = PypeIt.select_detectors(detnum=parset['rdx']['detnum'], ndet=spectrograph.ndet) if len(detectors) != spectrograph.ndet: msgs.warn('Not reducing detectors: {0}'.format(' '.join([ str(d) for d in set(np.arange(spectrograph.ndet) + 1) - set(detectors) ]))) # Loop on detectors for det in detectors: msgs.info("Working on detector {0}".format(det)) sci_dict[det] = {} # Instantiate Coadd2d coadd = coadd2d.CoAdd2D.get_instance( spec2d_files, spectrograph, parset, det=det, offsets=parset['coadd2d']['offsets'], weights=parset['coadd2d']['weights'], ir_redux=ir_redux, debug_offsets=args.debug_offsets, debug=args.debug, samp_fact=args.samp_fact) # Coadd the slits coadd_dict_list = coadd.coadd( only_slits=None) # TODO implement only_slits later # Create the pseudo images pseudo_dict = coadd.create_pseudo_image(coadd_dict_list) # Reduce msgs.info('Running the extraction') # TODO -- This should mirror what is in pypeit.extract_one # TODO -- JFH :: This ought to return a Spec2DObj and SpecObjs which would be slurped into # AllSpec2DObj and all_specobsj, as below. # TODO -- JFH -- Check that the slits we are using are correct sci_dict[det]['sciimg'], sci_dict[det]['sciivar'], sci_dict[det]['skymodel'], sci_dict[det]['objmodel'], \ sci_dict[det]['ivarmodel'], sci_dict[det]['outmask'], sci_dict[det]['specobjs'], sci_dict[det]['detector'], \ sci_dict[det]['slits'], sci_dict[det]['tilts'], sci_dict[det]['waveimg'] = coadd.reduce( pseudo_dict, show = args.show, show_peaks = args.peaks) # Save pseudo image master files #coadd.save_masters() # Make the new Science dir # TODO: This needs to be defined by the user scipath = os.path.join(redux_path, 'Science_coadd') if not os.path.isdir(scipath): msgs.info('Creating directory for Science output: {0}'.format(scipath)) os.makedirs(scipath) # THE FOLLOWING MIMICS THE CODE IN pypeit.save_exposure() # TODO -- These lines should be above once reduce() passes back something sensible all_specobjs = specobjs.SpecObjs() for det in detectors: all_specobjs.add_sobj(sci_dict[det]['specobjs']) # Write outfile1d = os.path.join(scipath, 'spec1d_{:s}.fits'.format(basename)) subheader = spectrograph.subheader_for_spec(head2d, head2d) all_specobjs.write_to_fits(subheader, outfile1d) # 2D spectra # TODO -- These lines should be above once reduce() passes back something sensible all_spec2d = spec2dobj.AllSpec2DObj() all_spec2d['meta']['ir_redux'] = ir_redux for det in detectors: all_spec2d[det] = spec2dobj.Spec2DObj( det=det, sciimg=sci_dict[det]['sciimg'], ivarraw=sci_dict[det]['sciivar'], skymodel=sci_dict[det]['skymodel'], objmodel=sci_dict[det]['objmodel'], ivarmodel=sci_dict[det]['ivarmodel'], scaleimg=np.array([1.0], dtype=np.float), bpmmask=sci_dict[det]['outmask'], detector=sci_dict[det]['detector'], slits=sci_dict[det]['slits'], waveimg=sci_dict[det]['waveimg'], tilts=sci_dict[det]['tilts'], sci_spat_flexure=None, sci_spec_flexure=None, vel_corr=None, vel_type=None) # Build header outfile2d = os.path.join(scipath, 'spec2d_{:s}.fits'.format(basename)) pri_hdr = all_spec2d.build_primary_hdr( head2d, spectrograph, subheader=subheader, # TODO -- JFH :: Decide if we need any of these redux_path=None, master_key_dict=None, master_dir=None) # Write all_spec2d.write_to_fits(outfile2d, pri_hdr=pri_hdr)
def extract_one(self, frames, det, sciImg, objFind, initial_sky, sobjs_obj): """ Extract Objects in a single exposure/detector pair sci_ID and det need to have been set internally prior to calling this method Args: frames (:obj:`list`): List of frames to extract; stacked if more than one is provided det (:obj:`int`): Detector number (1-indexed) sciImg (:class:`PypeItImage`): Data container that holds a single image from a single detector its related images (e.g. ivar, mask) objFind : :class:`~pypeit.find_objects.FindObjects` Object finding object initial_sky (`numpy.ndarray`_): Initial global sky model sobjs_obj (:class:`pypeit.specobjs.SpecObjs`): List of objects found during `run_objfind` Returns: tuple: Returns six `numpy.ndarray`_ objects and a :class:`pypeit.specobjs.SpecObjs` object with the extracted spectra from this exposure/detector pair. The six `numpy.ndarray`_ objects are (1) the science image, (2) its inverse variance, (3) the sky model, (4) the object model, (5) the model inverse variance, and (6) the mask. """ # Grab some meta-data needed for the reduction from the fitstbl self.objtype, self.setup, self.obstime, self.basename, self.binning \ = self.get_sci_metadata(frames[0], det) # Is this a standard star? self.std_redux = 'standard' in self.objtype # Update the skymask skymask = objFind.create_skymask(sobjs_obj) # Update the global sky if 'standard' in self.fitstbl['frametype'][frames[0]] or \ self.par['reduce']['findobj']['skip_final_global'] or \ self.par['reduce']['skysub']['load_mask'] or \ self.par['reduce']['skysub']['user_regions'] is not None: final_global_sky = initial_sky else: final_global_sky = objFind.global_skysub(previous_sky=initial_sky, skymask=skymask, show=self.show) scaleImg = objFind.scaleimg # update here slits.mask since global_skysub modify reduce_bpm and we need to propagate it into extraction flagged_slits = np.where(objFind.reduce_bpm)[0] if len(flagged_slits) > 0: self.caliBrate.slits.mask[flagged_slits] = \ self.caliBrate.slits.bitmask.turn_on(self.caliBrate.slits.mask[flagged_slits], 'BADREDUCE') msgs.info("Extraction begins for {} on det={}".format( self.basename, det)) # Instantiate Reduce object # Required for pypeline specific object # At instantiaton, the fullmask in self.sciImg is modified # TODO Are we repeating steps in the init for FindObjects and Extract?? self.exTract = extraction.Extract.get_instance( sciImg, sobjs_obj, self.spectrograph, self.par, self.caliBrate, self.objtype, bkg_redux=self.bkg_redux, return_negative=self.par['reduce']['extraction'] ['return_negative'], std_redux=self.std_redux, show=self.show, basename=self.basename) if not self.par['reduce']['extraction']['skip_extraction']: skymodel, objmodel, ivarmodel, outmask, sobjs, waveImg, \ tilts = self.exTract.run(final_global_sky, ra=self.fitstbl["ra"][frames[0]], dec=self.fitstbl["dec"][frames[0]], obstime=self.obstime) else: # Although exrtaction is not performed, still need to prepare some masks and the tilts self.exTract.prepare_extraction() # Since the extraction was not performed, fill the arrays with the best available information skymodel = final_global_sky objmodel = np.zeros_like(self.exTract.sciImg.image) ivarmodel = np.copy(self.exTract.sciImg.ivar) outmask = self.exTract.sciImg.fullmask waveImg = self.exTract.waveimg tilts = self.exTract.tilts sobjs = sobjs_obj # TODO -- Do this upstream # Tack on detector and wavelength RMS for sobj in sobjs: sobj.DETECTOR = sciImg.detector iwv = np.where( self.caliBrate.wv_calib.spat_ids == sobj.SLITID)[0][0] sobj.WAVE_RMS = self.caliBrate.wv_calib.wv_fits[iwv].rms # Construct table of spectral flexure spec_flex_table = Table() spec_flex_table['spat_id'] = self.caliBrate.slits.spat_id spec_flex_table['sci_spec_flexure'] = self.exTract.slitshift # pull out maskdef_designtab from caliBrate.slits maskdef_designtab = self.caliBrate.slits.maskdef_designtab slits = copy.deepcopy(self.caliBrate.slits) slits.maskdef_designtab = None # Construct the Spec2DObj spec2DObj = spec2dobj.Spec2DObj( sciimg=sciImg.image, ivarraw=sciImg.ivar, skymodel=skymodel, objmodel=objmodel, ivarmodel=ivarmodel, scaleimg=scaleImg, waveimg=waveImg, bpmmask=outmask, detector=sciImg.detector, sci_spat_flexure=sciImg.spat_flexure, sci_spec_flexure=spec_flex_table, vel_corr=self.exTract.vel_corr, vel_type=self.par['calibrations']['wavelengths']['refframe'], tilts=tilts, slits=slits, maskdef_designtab=maskdef_designtab) spec2DObj.process_steps = sciImg.process_steps # QA spec2DObj.gen_qa() # Return return spec2DObj, sobjs
def reduce_IR(A_files, B_files, caliBrate, spectrograph, det, parset, show=False, std_trace=None): """ Peform 2d extraction for a set of files at the same unique A-B offset location. Parameters ---------- A_files (list of strings): Files at A position for this offset B_files (list of strings) Files at B position for this offeset caliBrate (object): CaliBrate object spectrograph (object): spectrograph object det (int): Detector number parset (parsect object) Parset show (bool, optional): Show 2d reduction outputs. Default=False std_trace (string, optional) Trace for standard star. Default=None Returns ------- spec2DObj_A, spec2DObj_B spec2DObj_A (object, Spec2D): Spec2d Object for extraction at A position spec2DObj_B (object, Spec2D) Spec2d Object for extraction at B position """ # Build Science image sciImg = buildimage.buildimage_fromlist(spectrograph, det, parset['scienceframe'], list(A_files), bpm=caliBrate.msbpm, slits=caliBrate.slits, ignore_saturation=False) # Background Image? sciImg = sciImg.sub( buildimage.buildimage_fromlist(spectrograph, det, parset['scienceframe'], list(B_files), bpm=caliBrate.msbpm, slits=caliBrate.slits, ignore_saturation=False), parset['scienceframe']['process']) # Instantiate FindObjects object # Required for pypeline specific object # At instantiaton, the fullmask in self.sciImg is modified # DP: Should find_negative be True here? JFH: For quicklook yes! objFind = find_objects.FindObjects.get_instance(sciImg, spectrograph, parset, caliBrate, 'science', bkg_redux=True, find_negative=True, show=show) global_sky, sobjs_obj = objFind.run(std_trace=std_trace, show_peaks=show) # Instantiate Extract object extract = extraction.Extract.get_instance(sciImg, sobjs_obj, spectrograph, parset, caliBrate, 'science', bkg_redux=True, return_negative=True, show=show) skymodel, objmodel, ivarmodel, \ outmask, sobjs, waveimg, tilts = extract.run(global_sky, sobjs_obj) scaleimg = np.array([1.0], dtype=np.float) # np.array([1]) applies no scale # TODO -- Do this upstream # Tack on detector for sobj in sobjs: sobj.DETECTOR = sciImg.detector # Construct table of spectral flexure spec_flex_table = Table() spec_flex_table['spat_id'] = caliBrate.slits.spat_id spec_flex_table['sci_spec_flexure'] = extract.slitshift # Construct the Spec2DObj with the positive image spec2DObj_A = spec2dobj.Spec2DObj( sciimg=sciImg.image, ivarraw=sciImg.ivar, skymodel=skymodel, objmodel=objmodel, ivarmodel=ivarmodel, scaleimg=scaleimg, waveimg=waveimg, bpmmask=outmask, detector=sciImg.detector, sci_spat_flexure=sciImg.spat_flexure, sci_spec_flexure=spec_flex_table, vel_corr=None, vel_type=parset['calibrations']['wavelengths']['refframe'], tilts=tilts, slits=copy.deepcopy(caliBrate.slits), maskdef_designtab=None) spec2DObj_A.process_steps = sciImg.process_steps all_spec2d = spec2dobj.AllSpec2DObj() all_spec2d['meta']['bkg_redux'] = True all_spec2d[spec2DObj_A.detname] = spec2DObj_A # Construct the Spec2DObj with the negative image spec2DObj_B = spec2dobj.Spec2DObj( sciimg=-sciImg.image, ivarraw=sciImg.ivar, skymodel=-skymodel, objmodel=-objmodel, ivarmodel=ivarmodel, scaleimg=scaleimg, waveimg=waveimg, bpmmask=outmask, detector=sciImg.detector, sci_spat_flexure=sciImg.spat_flexure, sci_spec_flexure=spec_flex_table, vel_corr=None, vel_type=parset['calibrations']['wavelengths']['refframe'], tilts=tilts, slits=copy.deepcopy(caliBrate.slits), maskdef_designtab=None) return spec2DObj_A, spec2DObj_B
def run(files, caliBrate, spectrograph, det, parset, show=False, std_trace=None): """ Peform 2d extraction for a set of files at the same unique A-B offset location. Parameters ---------- A_files (list of strings): Files at A position for this offset B_files (list of strings) Files at B position for this offeset caliBrate (object): CaliBrate object spectrograph (object): spectrograph object det (int): Detector number parset (parsect object) Parset show (bool, optional): Show 2d reduction outputs. Default=False std_trace (string, optional) Trace for standard star. Default=None Returns ------- spec2DObj_A, spec2DObj_B spec2DObj_A (object, Spec2D): Spec2d Object for extraction at A position spec2DObj_B (object, Spec2D) Spec2d Object for extraction at B position """ # Build Science image sciImg = buildimage.buildimage_fromlist( spectrograph, det, parset['scienceframe'], list(files), bias=caliBrate.msbias, bpm=caliBrate.msbpm, slits=caliBrate.slits, ignore_saturation=False) # Instantiate Reduce object # Required for pypeline specific object # At instantiaton, the fullmask in self.sciImg is modified redux = reduce.Reduce.get_instance(sciImg, spectrograph, parset, caliBrate, 'science', ir_redux=True, show=show, det=det) # skymodel, objmodel, ivarmodel, outmask, sobjs, scaleimg, waveimg, tilts = redux.run( # std_trace=std_trace, return_negative=True, show_peaks=show) global_sky, sobjs_obj, skymask = redux.run_objfind(std_trace=std_trace, show_peaks=show) skymodel, objmodel, ivarmodel, outmask, sobjs, scaleimg, waveimg, tilts = redux.run_extraction( global_sky, sobjs_obj, skymask) # TODO -- Do this upstream # Tack on detector for sobj in sobjs: sobj.DETECTOR = sciImg.detector # Construct table of spectral flexure spec_flex_table = Table() spec_flex_table['spat_id'] = caliBrate.slits.spat_id spec_flex_table['sci_spec_flexure'] = redux.slitshift # Construct the Spec2DObj with the positive image spec2DObj = spec2dobj.Spec2DObj(sciimg=sciImg.image, ivarraw=sciImg.ivar, skymodel=skymodel, objmodel=objmodel, ivarmodel=ivarmodel, scaleimg=scaleimg, waveimg=waveimg, bpmmask=outmask, detector=sciImg.detector, sci_spat_flexure=sciImg.spat_flexure, sci_spec_flexure=spec_flex_table, vel_corr=None, vel_type=parset['calibrations']['wavelengths']['refframe'], tilts=tilts, slits=copy.deepcopy(caliBrate.slits)) spec2DObj.process_steps = sciImg.process_steps return spec2DObj
def reduce_one(self, frames, det, bg_frames, std_outfile=None): """ Reduce + Extract a single exposure/detector pair sci_ID and det need to have been set internally prior to calling this method Args: frames (:obj:`list`): List of frames to extract; stacked if more than one is provided det (:obj:`int`): Detector number (1-indexed) bg_frames (:obj:`list`): List of frames to use as the background. Can be empty. std_outfile (:obj:`str`, optional): Filename for the standard star spec1d file. Passed directly to :func:`get_std_trace`. Returns: tuple: Returns six `numpy.ndarray`_ objects and a :class:`pypeit.specobjs.SpecObjs` object with the extracted spectra from this exposure/detector pair. The six `numpy.ndarray`_ objects are (1) the science image, (2) its inverse variance, (3) the sky model, (4) the object model, (5) the model inverse variance, and (6) the mask. """ # Grab some meta-data needed for the reduction from the fitstbl self.objtype, self.setup, self.obstime, self.basename, self.binning \ = self.get_sci_metadata(frames[0], det) msgs.info("Extraction begins for {} on det={}".format( self.basename, det)) # Is this a standard star? self.std_redux = 'standard' in self.objtype if self.std_redux: frame_par = self.par['calibrations']['standardframe'] else: frame_par = self.par['scienceframe'] # Get the standard trace if need be std_trace = self.get_std_trace(self.std_redux, det, std_outfile) # Build Science image sci_files = self.fitstbl.frame_paths(frames) sciImg = buildimage.buildimage_fromlist( self.spectrograph, det, frame_par, sci_files, bias=self.caliBrate.msbias, bpm=self.caliBrate.msbpm, dark=self.caliBrate.msdark, flatimages=self.caliBrate.flatimages, slits=self.caliBrate.slits, # For flexure correction ignore_saturation=False) # Background Image? if len(bg_frames) > 0: bg_file_list = self.fitstbl.frame_paths(bg_frames) sciImg = sciImg.sub( buildimage.buildimage_fromlist( self.spectrograph, det, frame_par, bg_file_list, bpm=self.caliBrate.msbpm, bias=self.caliBrate.msbias, dark=self.caliBrate.msdark, flatimages=self.caliBrate.flatimages, slits=self.caliBrate.slits, # For flexure correction ignore_saturation=False), frame_par['process']) # Instantiate Reduce object # Required for pypeline specific object # At instantiaton, the fullmask in self.sciImg is modified self.redux = reduce.Reduce.get_instance(sciImg, self.spectrograph, self.par, self.caliBrate, self.objtype, ir_redux=self.ir_redux, std_redux=self.std_redux, setup=self.setup, show=self.show, det=det, binning=self.binning, std_outfile=std_outfile, basename=self.basename) # Show? if self.show: self.redux.show('image', image=sciImg.image, chname='processed', slits=True, clear=True) # Do it skymodel, objmodel, ivarmodel, outmask, sobjs, scaleImg, waveImg, tilts = self.redux.run( std_trace=std_trace, show_peaks=self.show, ra=self.fitstbl["ra"][frames[0]], dec=self.fitstbl["dec"][frames[0]], obstime=self.obstime) # TODO -- Save the slits yet again? # TODO -- Do this upstream # Tack on detector for sobj in sobjs: sobj.DETECTOR = sciImg.detector # Construct table of spectral flexure spec_flex_table = Table() spec_flex_table['spat_id'] = self.caliBrate.slits.spat_id spec_flex_table['sci_spec_flexure'] = self.redux.slitshift # Construct the Spec2DObj spec2DObj = spec2dobj.Spec2DObj( det=self.det, sciimg=sciImg.image, ivarraw=sciImg.ivar, skymodel=skymodel, objmodel=objmodel, ivarmodel=ivarmodel, scaleimg=scaleImg, waveimg=waveImg, bpmmask=outmask, detector=sciImg.detector, sci_spat_flexure=sciImg.spat_flexure, sci_spec_flexure=spec_flex_table, vel_corr=self.redux.vel_corr, vel_type=self.par['calibrations']['wavelengths']['refframe'], tilts=tilts, slits=copy.deepcopy(self.caliBrate.slits)) spec2DObj.process_steps = sciImg.process_steps # Return return spec2DObj, sobjs
def test_init(init_dict): spec2DObj = spec2dobj.Spec2DObj(**init_dict) # Check assert spec2DObj.hdu_prefix == 'DET01-'
def main(args): """ Executes 2d coadding """ msgs.info('PATH =' + os.getcwd()) # Load the file if args.file is not None: spectrograph_name, config_lines, spec2d_files \ = io.read_spec2d_file(args.file, filetype="coadd2d") spectrograph = load_spectrograph(spectrograph_name) # Parameters # TODO: Shouldn't this reinstantiate the same parameters used in # the PypeIt run that extracted the objects? Why are we not # just passing the pypeit file? # JFH: The reason is that the coadd2dfile may want different reduction parameters # DP: I think config_specific_par() is more appropriate here. default_pypeit_par() # is included in config_specific_par() # NOTE `config_specific_par` works with the spec2d files because we construct the header # of those files to include all the relevant keywords from the raw file. spectrograph_cfg_lines = spectrograph.config_specific_par( spec2d_files[0]).to_config() parset = par.PypeItPar.from_cfg_lines( cfg_lines=spectrograph_cfg_lines, merge_with=config_lines) elif args.obj is not None: # TODO: We should probably be reading the pypeit file and using # those parameters here rather than using the default parset. # TODO: This needs to define the science path spec2d_files = glob.glob('./Science/spec2d_*' + args.obj + '*') head0 = fits.getheader(spec2d_files[0]) spectrograph_name = head0['PYP_SPEC'] spectrograph = load_spectrograph(spectrograph_name) # NOTE `config_specific_par` works with the spec2d files because we construct the header # of those files to include all the relevant keywords from the raw file. spectrograph_cfg_lines = spectrograph.config_specific_par( spec2d_files[0]).to_config() parset = par.PypeItPar.from_cfg_lines( cfg_lines=spectrograph_cfg_lines) else: return msgs.error( 'You must provide either a coadd2d file (--file) or an object name (--obj)' ) # If detector was passed as an argument override whatever was in the coadd2d_file if args.det is not None: msgs.info("Restricting reductions to detector={}".format(args.det)) # parset['rdx']['detnum'] = par.util.eval_tuple(args.det.split(',')) # TODO this needs to be adjusted if we want to pass (as inline command) mosaic detectors parset['rdx']['detnum'] = [int(d) for d in args.det.split(',')] # Get headers (if possible) and base names spec1d_files = [ files.replace('spec2d', 'spec1d') for files in spec2d_files ] head1d = None for spec1d_file in spec1d_files: if os.path.isfile(spec1d_file): head1d = fits.getheader(spec1d_file) break if head1d is None: msgs.warn( "No 1D spectra so am generating a dummy header for output") head1d = io.initialize_header() head2d = fits.getheader(spec2d_files[0]) if args.basename is None: #TODO Fix this, currently does not work if target names have - or _ filename_first = os.path.basename(spec2d_files[0]) filename_last = os.path.basename(spec2d_files[-1]) prefix_first = (filename_first.split('_')[1]).split('-')[0] prefix_last = (filename_last.split('_')[1]).split('-')[0] objname = (filename_first.split('-')[1]).split('_')[0] basename = '{:s}-{:s}-{:s}'.format(prefix_first, prefix_last, objname) else: basename = args.basename # TODO Heliocentric for coadd2d needs to be thought through. Currently turning it off. parset['calibrations']['wavelengths']['refframe'] = 'observed' # TODO Flexure correction for coadd2d needs to be thought through. Currently turning it off. parset['flexure']['spec_method'] = 'skip' # Write the par to disk par_outfile = basename + '_coadd2d.par' print("Writing the parameters to {}".format(par_outfile)) parset.to_config(par_outfile, exclude_defaults=True, include_descr=False) # Now run the coadds skysub_mode = head2d['SKYSUB'] findobj_mode = head2d['FINDOBJ'] bkg_redux = True if 'DIFF' in skysub_mode else False find_negative = True if 'NEG' in findobj_mode else False # Print status message msgs_string = 'Reducing target {:s}'.format(basename) + msgs.newline() msgs_string += 'Coadding frame sky-subtraced with {:s}'.format( skysub_mode) msgs_string += 'Searching for objects that are {:s}'.format( findobj_mode) msgs_string += msgs.newline( ) + 'Combining frames in 2d coadd:' + msgs.newline() for f, file in enumerate(spec2d_files): msgs_string += 'Exp {0}: {1:s}'.format( f, os.path.basename(file)) + msgs.newline() msgs.info(msgs_string) # TODO: This needs to be added to the parameter list for rdx redux_path = os.getcwd() master_dirname = os.path.basename(head2d['PYPMFDIR']) + '_coadd' master_dir = os.path.join(redux_path, master_dirname) # Make the new Master dir if not os.path.isdir(master_dir): msgs.info( 'Creating directory for Master output: {0}'.format(master_dir)) os.makedirs(master_dir) # Instantiate the sci_dict sci_dict = OrderedDict() # This needs to be ordered sci_dict['meta'] = {} sci_dict['meta']['vel_corr'] = 0. sci_dict['meta']['bkg_redux'] = bkg_redux sci_dict['meta']['find_negative'] = find_negative # Make QA coadd directory parset['rdx']['qadir'] += '_coadd' qa_path = os.path.join(parset['rdx']['redux_path'], parset['rdx']['qadir'], 'PNGs') if not os.path.isdir(qa_path): os.makedirs(qa_path) # Find the detectors to reduce # detectors = PypeIt.select_detectors(detnum=parset['rdx']['detnum'], ndet=spectrograph.ndet) detectors = spectrograph.select_detectors( subset=parset['rdx']['detnum']) # if len(detectors) != spectrograph.ndet: # msgs.warn('Not reducing detectors: {0}'.format(' '.join([str(d) for d in # set(np.arange(spectrograph.ndet) + 1) - set(detectors)]))) msgs.info(f'Detectors to work on: {detectors}') # Only_slits? if args.only_slits: parset['coadd2d']['only_slits'] = [ int(item) for item in args.only_slits.split(',') ] # container for specobjs all_specobjs = specobjs.SpecObjs() # container for spec2dobj all_spec2d = spec2dobj.AllSpec2DObj() # set some meta all_spec2d['meta']['bkg_redux'] = bkg_redux all_spec2d['meta']['find_negative'] = find_negative # Loop on detectors for det in detectors: msgs.info("Working on detector {0}".format(det)) # Instantiate Coadd2d coadd = coadd2d.CoAdd2D.get_instance( spec2d_files, spectrograph, parset, det=det, offsets=parset['coadd2d']['offsets'], weights=parset['coadd2d']['weights'], spec_samp_fact=args.spec_samp_fact, spat_samp_fact=args.spat_samp_fact, bkg_redux=bkg_redux, find_negative=find_negative, debug_offsets=args.debug_offsets, debug=args.debug) # TODO Add this stuff to a run method in coadd2d # Coadd the slits coadd_dict_list = coadd.coadd( only_slits=parset['coadd2d']['only_slits']) # Create the pseudo images pseudo_dict = coadd.create_pseudo_image(coadd_dict_list) # Reduce msgs.info('Running the extraction') # TODO -- This should mirror what is in pypeit.extract_one # TODO -- JFH :: This ought to return a Spec2DObj and SpecObjs which # would be slurped into AllSpec2DObj and all_specobsj, as below. # TODO -- JFH -- Check that the slits we are using are correct sci_dict[coadd.detname] = {} sci_dict[coadd.detname]['sciimg'], sci_dict[coadd.detname]['sciivar'], \ sci_dict[coadd.detname]['skymodel'], sci_dict[coadd.detname]['objmodel'], \ sci_dict[coadd.detname]['ivarmodel'], sci_dict[coadd.detname]['outmask'], \ sci_dict[coadd.detname]['specobjs'], sci_dict[coadd.detname]['detector'], \ sci_dict[coadd.detname]['slits'], sci_dict[coadd.detname]['tilts'], \ sci_dict[coadd.detname]['waveimg'] \ = coadd.reduce(pseudo_dict, show=args.show, show_peaks=args.peaks, basename=basename) # Tack on detector (similarly to pypeit.extract_one) for sobj in sci_dict[coadd.detname]['specobjs']: sobj.DETECTOR = sci_dict[coadd.detname]['detector'] # fill the specobjs container all_specobjs.add_sobj(sci_dict[coadd.detname]['specobjs']) # fill the spec2dobj container but first ... # pull out maskdef_designtab from sci_dict[det]['slits'] maskdef_designtab = sci_dict[ coadd.detname]['slits'].maskdef_designtab slits = copy.deepcopy(sci_dict[coadd.detname]['slits']) slits.maskdef_designtab = None # fill up all_spec2d[coadd.detname] = spec2dobj.Spec2DObj( sciimg=sci_dict[coadd.detname]['sciimg'], ivarraw=sci_dict[coadd.detname]['sciivar'], skymodel=sci_dict[coadd.detname]['skymodel'], objmodel=sci_dict[coadd.detname]['objmodel'], ivarmodel=sci_dict[coadd.detname]['ivarmodel'], scaleimg=np.array([1.0], dtype=np.float), bpmmask=sci_dict[coadd.detname]['outmask'], detector=sci_dict[coadd.detname]['detector'], slits=slits, waveimg=sci_dict[coadd.detname]['waveimg'], tilts=sci_dict[coadd.detname]['tilts'], sci_spat_flexure=None, sci_spec_flexure=None, vel_corr=None, vel_type=None, maskdef_designtab=maskdef_designtab) # Save pseudo image master files #coadd.save_masters() # SAVE TO DISK # Make the new Science dir # TODO: This needs to be defined by the user scipath = os.path.join(redux_path, 'Science_coadd') if not os.path.isdir(scipath): msgs.info( 'Creating directory for Science output: {0}'.format(scipath)) os.makedirs(scipath) # THE FOLLOWING MIMICS THE CODE IN pypeit.save_exposure() subheader = spectrograph.subheader_for_spec(head2d, head2d) # Write spec1D if all_specobjs.nobj > 0: outfile1d = os.path.join(scipath, 'spec1d_{:s}.fits'.format(basename)) all_specobjs.write_to_fits(subheader, outfile1d) # Info outfiletxt = os.path.join(scipath, 'spec1d_{:s}.txt'.format(basename)) sobjs = specobjs.SpecObjs.from_fitsfile(outfile1d, chk_version=False) sobjs.write_info(outfiletxt, spectrograph.pypeline) # Build header for spec2d outfile2d = os.path.join(scipath, 'spec2d_{:s}.fits'.format(basename)) pri_hdr = all_spec2d.build_primary_hdr( head2d, spectrograph, subheader=subheader, # TODO -- JFH :: Decide if we need any of these redux_path=None, master_key_dict=None, master_dir=None) # Write spec2d all_spec2d.write_to_fits(outfile2d, pri_hdr=pri_hdr)
def main(args): # Build the fitstable since we currently need it for output. This should not be the case! A_files = [os.path.join(args.full_rawpath, file) for file in args.Afiles] B_files = [os.path.join(args.full_rawpath, file) for file in args.Bfiles] data_files = A_files + B_files ps = pypeitsetup.PypeItSetup(A_files, path='./', spectrograph_name='keck_mosfire') ps.build_fitstbl() fitstbl = ps.fitstbl # Read in the spectrograph, config the parset spectrograph = load_spectrograph('keck_mosfire') spectrograph_def_par = spectrograph.default_pypeit_par() parset = par.PypeItPar.from_cfg_lines( cfg_lines=spectrograph_def_par.to_config(), merge_with=config_lines(args)) science_path = os.path.join(parset['rdx']['redux_path'], parset['rdx']['scidir']) # Calibration Master directory if args.master_dir is None: msgs.error( "You need to set an Environmental variable MOSFIRE_MASTERS that points at the Master Calibs" ) # Define some hard wired master files here to be later parsed out of the directory slit_masterframe_name = os.path.join(args.master_dir, 'MasterSlits_E_15_01.fits.gz') tilts_masterframe_name = os.path.join(args.master_dir, 'MasterTilts_E_1_01.fits') wvcalib_masterframe_name = os.path.join(args.master_dir, 'MasterWaveCalib_E_1_01.fits') # For now don't require a standard std_outfile = None #std_outfile = os.path.join('/Users/joe/Dropbox/PypeIt_Redux/MOSFIRE/Nov19/quicklook/Science/', # 'spec1d_m191118_0064-GD71_MOSFIRE_2019Nov18T104704.507.fits') # make the get_std from pypeit a utility function or class method det = 1 # MOSFIRE has a single detector if std_outfile is not None: # Get the standard trace if need be sobjs = specobjs.SpecObjs.from_fitsfile(std_outfile) this_det = sobjs.DET == det if np.any(this_det): sobjs_det = sobjs[this_det] sobjs_std = sobjs_det.get_std() std_trace = None if sobjs_std is None else sobjs_std.TRACE_SPAT.flatten( ) else: std_trace = None else: std_trace = None # Read in the msbpm sdet = get_dnum(det, prefix=False) msbpm = spectrograph.bpm(A_files[0], det) # Read in the slits slits = slittrace.SlitTraceSet.from_file(slit_masterframe_name) # Reset the bitmask slits.mask = slits.mask_init.copy() # Read in the wv_calib wv_calib = wavecalib.WaveCalib.from_file(wvcalib_masterframe_name) wv_calib.is_synced(slits) slits.mask_wvcalib(wv_calib) # Read in the tilts tilts_obj = wavetilts.WaveTilts.from_file(tilts_masterframe_name) tilts_obj.is_synced(slits) slits.mask_wavetilts(tilts_obj) # Build Science image sciImg = buildimage.buildimage_fromlist(spectrograph, det, parset['scienceframe'], A_files, bpm=msbpm, slits=slits, ignore_saturation=False) # Background Image? sciImg = sciImg.sub( buildimage.buildimage_fromlist(spectrograph, det, parset['scienceframe'], B_files, bpm=msbpm, slits=slits, ignore_saturation=False), parset['scienceframe']['process']) # Build the Calibrate object caliBrate = calibrations.Calibrations(None, parset['calibrations'], spectrograph, None) caliBrate.slits = slits caliBrate.wavetilts = tilts_obj caliBrate.wv_calib = wv_calib # Instantiate Reduce object # Required for pypeline specific object # At instantiaton, the fullmask in self.sciImg is modified redux = reduce.Reduce.get_instance(sciImg, spectrograph, parset, caliBrate, 'science', ir_redux=True, show=args.show, det=det, std_outfile=std_outfile) manual_extract_dict = None skymodel, objmodel, ivarmodel, outmask, sobjs, waveImg, tilts = redux.run( std_trace=std_trace, return_negative=True, manual_extract_dict=manual_extract_dict, show_peaks=args.show) # TODO -- Do this upstream # Tack on detector for sobj in sobjs: sobj.DETECTOR = sciImg.detector # Construct the Spec2DObj with the positive image spec2DObj_A = spec2dobj.Spec2DObj(det=det, sciimg=sciImg.image, ivarraw=sciImg.ivar, skymodel=skymodel, objmodel=objmodel, ivarmodel=ivarmodel, waveimg=waveImg, bpmmask=outmask, detector=sciImg.detector, sci_spat_flexure=sciImg.spat_flexure, tilts=tilts, slits=copy.deepcopy(caliBrate.slits)) spec2DObj_A.process_steps = sciImg.process_steps all_spec2d = spec2dobj.AllSpec2DObj() all_spec2d['meta']['ir_redux'] = True all_spec2d[det] = spec2DObj_A # Save image A but with all the objects extracted, i.e. positive and negative #outfile2d, outfile1d = save_exposure(fitstbl, 0, spectrograph, science_path, parset, caliBrate, all_spec2d, sobjs) # Construct the Spec2DObj with the negative image spec2DObj_B = spec2dobj.Spec2DObj(det=det, sciimg=-sciImg.image, ivarraw=sciImg.ivar, skymodel=-skymodel, objmodel=-objmodel, ivarmodel=ivarmodel, waveimg=waveImg, bpmmask=outmask, detector=sciImg.detector, sci_spat_flexure=sciImg.spat_flexure, tilts=tilts, slits=copy.deepcopy(caliBrate.slits)) # Parse the offset information out of the headers. TODO in the future get this out of fitstable dither_pattern_A, dither_id_A, offset_arcsec_A = parse_dither_pattern( A_files, spectrograph.primary_hdrext) dither_pattern_B, dither_id_B, offset_arcsec_B = parse_dither_pattern( B_files, spectrograph.primary_hdrext) # Print out a report on the offsets msg_string = msgs.newline( ) + '****************************************************' msg_string += msgs.newline( ) + ' Summary of offsets for dither pattern: {:s}'.format( dither_pattern_A[0]) msg_string += msgs.newline( ) + '****************************************************' msg_string += msgs.newline( ) + 'Position filename arcsec pixels ' msg_string += msgs.newline( ) + '----------------------------------------------------' for iexp, file in enumerate(A_files): msg_string += msgs.newline( ) + ' A {:s} {:6.2f} {:6.2f}'.format( os.path.basename(file), offset_arcsec_A[iexp], offset_arcsec_A[iexp] / sciImg.detector.platescale) for iexp, file in enumerate(B_files): msg_string += msgs.newline( ) + ' B {:s} {:6.2f} {:6.2f}'.format( os.path.basename(file), offset_arcsec_B[iexp], offset_arcsec_B[iexp] / sciImg.detector.platescale) msg_string += msgs.newline( ) + '****************************************************' msgs.info(msg_string) #offset_dith_pix = offset_dith_pix = offset_arcsec_A[0]/sciImg.detector.platescale offsets_dith_pix = (np.array([ 0.0, np.mean(offset_arcsec_B) - np.mean(offset_arcsec_A) ])) / sciImg.detector.platescale if args.offset is not None: offsets_pixels = np.array([0.0, args.offset]) msgs.info('Using user specified offsets instead: {:5.2f}'.format( args.offset)) else: offsets_pixels = offsets_dith_pix spec2d_list = [spec2DObj_A, spec2DObj_B] # Instantiate Coadd2d coadd = coadd2d.CoAdd2D.get_instance(spec2d_list, spectrograph, parset, det=det, offsets=offsets_pixels, weights='uniform', ir_redux=True, debug=args.show, samp_fact=args.samp_fact) # Coadd the slits coadd_dict_list = coadd.coadd( only_slits=None, interp_dspat=False) # TODO implement only_slits later # Create the pseudo images pseudo_dict = coadd.create_pseudo_image(coadd_dict_list) ########################## # Now display the images # ########################## display.display.connect_to_ginga(raise_err=True, allow_new=True) # Bug in ginga prevents me from using cuts here for some reason #mean, med, sigma = sigma_clipped_stats(pseudo_dict['imgminsky'][pseudo_dict['inmask']], sigma_lower=5.0,sigma_upper=5.0) #cut_min = mean - 4.0 * sigma #cut_max = mean + 4.0 * sigma chname_skysub = 'skysub-det{:s}'.format(sdet) # Clear all channels at the beginning # TODO: JFH For some reason Ginga crashes when I try to put cuts in here. viewer, ch = ginga.show_image(pseudo_dict['imgminsky'], chname=chname_skysub, waveimg=pseudo_dict['waveimg'], clear=True) # cuts=(cut_min, cut_max), slit_left, slit_righ, _ = pseudo_dict['slits'].select_edges() slit_id = slits.slitord_id[0] ginga.show_slits(viewer, ch, slit_left, slit_righ, slit_ids=slit_id) # SKRESIDS chname_skyresids = 'sky_resid-det{:s}'.format(sdet) image = pseudo_dict['imgminsky'] * np.sqrt( pseudo_dict['sciivar']) * pseudo_dict['inmask'] # sky residual map viewer, ch = ginga.show_image( image, chname_skyresids, waveimg=pseudo_dict['waveimg'], cuts=(-5.0, 5.0), ) ginga.show_slits(viewer, ch, slit_left, slit_righ, slit_ids=slits.slitord_id[0]) shell = viewer.shell() out = shell.start_global_plugin('WCSMatch') out = shell.call_global_plugin_method('WCSMatch', 'set_reference_channel', [chname_skyresids], {}) if args.embed: embed() return 0