コード例 #1
0
ファイル: test_spec2dobj.py プロジェクト: tbowers7/PypeIt
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)
コード例 #2
0
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)
コード例 #3
0
ファイル: test_spec2dobj.py プロジェクト: tbowers7/PypeIt
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)
コード例 #4
0
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)
コード例 #5
0
ファイル: test_spec2dobj.py プロジェクト: tbowers7/PypeIt
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)
コード例 #6
0
ファイル: test_spec2dobj.py プロジェクト: tbowers7/PypeIt
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)
コード例 #7
0
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'
コード例 #8
0
ファイル: test_spec2dobj.py プロジェクト: tbowers7/PypeIt
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'
コード例 #9
0
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)
コード例 #10
0
ファイル: test_spec2dobj.py プロジェクト: tbowers7/PypeIt
def test_init(init_dict):
    init_dict['detector'] = tstutils.get_kastb_detector()
    spec2DObj = spec2dobj.Spec2DObj(**init_dict)
    # Check
    assert spec2DObj.hdu_prefix == 'DET01-'
コード例 #11
0
ファイル: coadd_2dspec.py プロジェクト: ninoc/PypeIt
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)
コード例 #12
0
ファイル: pypeit.py プロジェクト: tbowers7/PypeIt
    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
コード例 #13
0
ファイル: ql_keck_mosfire.py プロジェクト: tbowers7/PypeIt
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
コード例 #14
0
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
コード例 #15
0
ファイル: pypeit.py プロジェクト: ninoc/PypeIt
    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
コード例 #16
0
def test_init(init_dict):
    spec2DObj = spec2dobj.Spec2DObj(**init_dict)
    # Check
    assert spec2DObj.hdu_prefix == 'DET01-'
コード例 #17
0
ファイル: coadd_2dspec.py プロジェクト: tbowers7/PypeIt
    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)
コード例 #18
0
ファイル: ql_keck_mosfire.py プロジェクト: Tang-SL/PypeIt
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