Ejemplo n.º 1
0
def test_step_by_step(master_dir):
    # Masters
    spectrograph = load_spectrograph('shane_kast_blue')
    msarc, tslits_dict, mstrace = load_kast_blue_masters(aimg=True, tslits=True)
    # Instantiate
    master_key = 'A_1_01'
    parset = spectrograph.default_pypeit_par()
    par = parset['calibrations']['tilts']
    wavepar = parset['calibrations']['wavelengths']
    waveTilts = wavetilts.WaveTilts(msarc, tslits_dict, spectrograph, par, wavepar,
                                    det=1, master_key=master_key,
                                    master_dir=master_dir,reuse_masters=True)
    # Extract arcs
    arccen, maskslits = waveTilts.extract_arcs(waveTilts.slitcen, waveTilts.slitmask, msarc, waveTilts.inmask)
    assert arccen.shape == (2048,1)
    # Tilts in the slit
    slit = 0
    waveTilts.slitmask = pixels.tslits2mask(waveTilts.tslits_dict)
    thismask = waveTilts.slitmask == slit
    waveTilts.lines_spec, waveTilts.lines_spat = waveTilts.find_lines(arccen[:, slit], waveTilts.slitcen[:, slit], slit)

    trcdict = waveTilts.trace_tilts(waveTilts.msarc, waveTilts.lines_spec, waveTilts.lines_spat, thismask, slit)
    assert isinstance(trcdict, dict)
    # 2D Fit
    spat_order = waveTilts._parse_param(waveTilts.par, 'spat_order', slit)
    spec_order = waveTilts._parse_param(waveTilts.par, 'spec_order', slit)
    coeffs = waveTilts.fit_tilts(trcdict, thismask, waveTilts.slitcen[:, slit], spat_order, spec_order,slit, doqa=False)
    tilts = tracewave.fit2tilts(waveTilts.slitmask_science.shape, coeffs, waveTilts.par['func2d'])
    assert np.max(tilts) < 1.01
Ejemplo n.º 2
0
    def __init__(self,
                 tslits_dict,
                 tilts,
                 wv_calib,
                 spectrograph,
                 maskslits,
                 master_key=None,
                 master_dir=None,
                 reuse_masters=False):

        # MasterFrame
        masterframe.MasterFrame.__init__(self,
                                         self.frametype,
                                         master_key,
                                         master_dir,
                                         reuse_masters=reuse_masters)

        # Required parameters (but can be None)
        self.tslits_dict = tslits_dict
        self.tilts = tilts
        self.wv_calib = wv_calib
        self.spectrograph = spectrograph
        self.slitmask = pixels.tslits2mask(
            self.tslits_dict) if tslits_dict is not None else None
        self.par = wv_calib['par'] if wv_calib is not None else None

        # Optional parameters
        self.maskslits = maskslits

        # Attributes
        self.steps = [
        ]  # List to hold ouptut from inspect about what module create the image?

        # Main output
        self.wave = None
Ejemplo n.º 3
0
    def __init__(self, msarc, tslits_dict, spectrograph, par, binspectral=None, det=1,
                 master_key=None, master_dir=None, reuse_masters=False, redux_path=None, msbpm=None):

        # MasterFrame
        masterframe.MasterFrame.__init__(self, self.frametype, master_key,
                                         master_dir, reuse_masters=reuse_masters)

        # Required parameters (but can be None)
        self.msarc = msarc
        self.tslits_dict = tslits_dict
        self.spectrograph = spectrograph
        self.par = par

        # Optional parameters
        self.bpm = msbpm
        self.binspectral = binspectral
        self.redux_path = redux_path
        self.det = det
        self.master_key = master_key

        # Attributes
        self.steps = []    # steps executed
        self.wv_calib = {} # main output
        self.arccen = None # central arc spectrum

        # TODO this code is duplicated verbatim in wavetilts. Should it be a function
        if self.spectrograph is not None:
            if self.spectrograph.detector is not None:
                self.nonlinear_counts = self.spectrograph.detector[self.det-1]['saturation']*self.spectrograph.detector[self.det-1]['nonlinear']
            else:
                self.nonlinear_counts=1e10
        # Set the slitmask and slit boundary related attributes that the code needs for execution. This also deals with
        # arcimages that have a different binning then the trace images used to defined the slits
        if self.tslits_dict is not None and self.msarc is not None:
            self.slitmask_science = pixels.tslits2mask(self.tslits_dict)
            inmask = (self.bpm == 0) if self.bpm is not None else np.ones_like(self.slitmask_science, dtype=bool)
            self.shape_science = self.slitmask_science.shape
            self.shape_arc = self.msarc.shape
            self.nslits = self.tslits_dict['slit_left'].shape[1]
            self.slit_left = arc.resize_slits2arc(self.shape_arc, self.shape_science, self.tslits_dict['slit_left'])
            self.slit_righ = arc.resize_slits2arc(self.shape_arc, self.shape_science, self.tslits_dict['slit_righ'])
            self.slitcen   = arc.resize_slits2arc(self.shape_arc, self.shape_science, self.tslits_dict['slitcen'])
            self.slitmask  = arc.resize_mask2arc(self.shape_arc, self.slitmask_science)
            self.inmask = arc.resize_mask2arc(self.shape_arc,inmask)
            # TODO -- Remove the following two lines if deemed ok
            if self.par['method'] != 'full_template':
                self.inmask &= self.msarc < self.nonlinear_counts
        else:
            self.slitmask_science = None
            self.shape_science = None
            self.shape_arc = None
            self.nslits = 0
            self.slit_left = None
            self.slit_righ = None
            self.slitcen = None
            self.slitmask = None
            self.inmask = None
Ejemplo n.º 4
0
    def __init__(self, msarc, tslits_dict, spectrograph, par, wavepar, det=1,
                 master_key=None, master_dir=None, reuse_masters=False, redux_path=None, bpm=None):

        self.spectrograph = spectrograph
        self.par = par # pypeitpar.WaveTiltsPar() if par is None else par
        self.wavepar = wavepar # pypeitpar.WavelengthSolutionPar() if wavepar is None else wavepar
        # MasterFrame
        masterframe.MasterFrame.__init__(self, self.frametype, master_key,
                                         master_dir, reuse_masters=reuse_masters)

        # Parameters (but can be None)
        self.msarc = msarc
        self.tslits_dict = tslits_dict
        self.bpm = bpm
        # Optional parameters
        self.det = det
        self.redux_path = redux_path
        #
        if self.spectrograph is not None:
            self.nonlinear_counts = self.spectrograph.detector[self.det-1]['saturation']*self.spectrograph.detector[self.det-1]['nonlinear']
        else:
            self.nonlinear_counts=1e10
        # Set the slitmask and slit boundary related attributes that the code needs for execution. This also deals with
        # arcimages that have a different binning then the trace images used to defined the slits
        if self.tslits_dict is not None and self.msarc is not None:
            self.slitmask_science = pixels.tslits2mask(self.tslits_dict)
            inmask = (self.bpm == 0) if self.bpm is not None else np.ones_like(self.slitmask_science, dtype=bool)
            self.shape_science = self.slitmask_science.shape
            self.shape_arc = self.msarc.shape
            self.nslits = self.tslits_dict['slit_left'].shape[1]
            self.slit_left = arc.resize_slits2arc(self.shape_arc, self.shape_science, self.tslits_dict['slit_left'])
            self.slit_righ = arc.resize_slits2arc(self.shape_arc, self.shape_science, self.tslits_dict['slit_righ'])
            self.slitcen   = arc.resize_slits2arc(self.shape_arc, self.shape_science, self.tslits_dict['slitcen'])
            self.slitmask  = arc.resize_mask2arc(self.shape_arc, self.slitmask_science)
            self.inmask = (arc.resize_mask2arc(self.shape_arc, inmask)) & (self.msarc < self.nonlinear_counts)
        else:
            self.slitmask_science = None
            self.shape_science = None
            self.shape_arc = None
            self.nslits = 0
            self.slit_left = None
            self.slit_righ = None
            self.slitcen = None
            self.slitmask = None
            self.inmask = None

        # Key Internals
        self.mask = None
        self.all_trace_dict = [None]*self.nslits
        self.tilts = None
        # 2D fits are stored as a dictionary rather than list because we will jsonify the dict
        self.all_fit_dict = [None]*self.nslits
        self.steps = []
        # Main outputs
        self.final_tilts = None
        self.fit_dict = None
        self.trace_dict = None
Ejemplo n.º 5
0
    def __init__(self,
                 sciImg,
                 spectrograph,
                 tslits_dict,
                 par,
                 tilts,
                 ir_redux=False,
                 det=1,
                 objtype='science',
                 binning=None,
                 setup=None,
                 maskslits=None):

        # Setup the parameters sets for this object. NOTE: This uses objtype, not frametype!
        self.objtype = objtype
        self.par = par
        # TODO -- I find it very confusing to break apart the main parset
        self.proc_par = self.par['scienceframe']['process']
        # TODO Rename the scienceimage arset to reduce.
        self.redux_par = self.par['scienceimage']
        self.wave_par = self.par['calibrations']['wavelengths']
        self.flex_par = self.par['flexure']

        # Instantiation attributes for this object
        self.sciImg = sciImg
        self.spectrograph = spectrograph
        self.tslits_dict = tslits_dict
        self.slitmask = pixels.tslits2mask(self.tslits_dict)
        # Now add the slitmask to the mask (i.e. post CR rejection in proc)
        self.sciImg.update_mask_slitmask(self.slitmask)
        self.maskslits = self._get_goodslits(maskslits)
        self.ir_redux = ir_redux
        self.det = det
        self.tilts = tilts
        self.binning = binning
        self.setup = setup
        self.pypeline = spectrograph.pypeline

        self.steps = []

        # Other attributes that will be set later during object finding,
        # sky-subtraction, and extraction
        self.waveimage = None  # used by extract

        # Key outputs images for extraction
        self.ivarmodel = None
        self.objimage = None
        self.skyimage = None
        self.global_sky = None
        self.skymask = None
        self.outmask = None
        self.extractmask = None
        # SpecObjs object
        self.sobjs_obj = None  # Only object finding but no extraction
        self.sobjs = None  # Final extracted object list with trace corrections applied
Ejemplo n.º 6
0
    def __init__(self,
                 sciImg,
                 spectrograph,
                 par,
                 caliBrate,
                 ir_redux=False,
                 det=1,
                 std_redux=False,
                 show=False,
                 objtype='science',
                 binning=None,
                 setup=None,
                 maskslits=None):

        # Setup the parameters sets for this object. NOTE: This uses objtype, not frametype!

        # Instantiation attributes for this object
        self.sciImg = sciImg
        self.spectrograph = spectrograph
        self.objtype = objtype
        self.par = par
        #self.extraction_par = self.par['scienceimage']['extraction']
        #self.wave_par = self.par['calibrations']['wavelengths']
        #self.flex_par = self.par['flexure']
        # Parse
        self.caliBrate = caliBrate
        self.tslits_dict = self.caliBrate.tslits_dict
        self.tilts = self.caliBrate.tilts_dict['tilts']
        # Now add the slitmask to the mask (i.e. post CR rejection in proc)
        self.slitmask = pixels.tslits2mask(self.tslits_dict)
        self.sciImg.update_mask_slitmask(self.slitmask)
        self.maskslits = self._get_goodslits(maskslits)
        # Load up other input items
        self.ir_redux = ir_redux
        self.std_redux = std_redux
        self.det = det
        self.binning = binning
        self.setup = setup
        self.pypeline = spectrograph.pypeline
        self.reduce_show = show

        self.steps = []

        # Key outputs images for extraction
        self.ivarmodel = None
        self.objimage = None
        self.skyimage = None
        self.initial_sky = None
        self.global_sky = None
        self.skymask = None
        self.outmask = None
        self.extractmask = None
        # SpecObjs object
        self.sobjs_obj = None  # Only object finding but no extraction
        self.sobjs = None  # Final extracted object list with trace corrections applied
Ejemplo n.º 7
0
    def _qa(self, use_slitid=True):
        """
        QA
          Wrapper to trace_slits.slit_trace_qa()

        Returns
        -------

        """
        slitmask = pixels.tslits2mask(self.tslits_dict)
        trace_slits.slit_trace_qa(self.mstrace, self.slit_left,
                                   self.slit_righ, slitmask, self.extrapord, self.master_key,
                                   desc="Trace of the slit edges D{:02d}".format(self.det),
                                   use_slitid=use_slitid, out_dir=self.redux_path)
Ejemplo n.º 8
0
    def __init__(self,
                 tslits_dict,
                 tilts,
                 wv_calib,
                 spectrograph,
                 det,
                 maskslits,
                 master_key=None,
                 master_dir=None,
                 reuse_masters=False):

        # Image
        pypeitimage.PypeItImage.__init__(self, spectrograph, det)

        # MasterFrame
        MasterFrame.__init__(self,
                             self.master_type,
                             master_dir=master_dir,
                             master_key=master_key,
                             reuse_masters=reuse_masters)

        # Required parameters
        self.spectrograph = spectrograph

        self.tslits_dict = tslits_dict
        self.tilts = tilts
        self.wv_calib = wv_calib
        if tslits_dict is not None:
            self.slitmask = pixels.tslits2mask(self.tslits_dict)
            self.slit_spat_pos = trace_slits.slit_spat_pos(self.tslits_dict)
        else:
            self.slitmask = None
            self.slit_spat_pos = None

        # TODO: only echelle is ever used.  Do we need to keep the whole
        # thing?
        self.par = wv_calib['par'] if wv_calib is not None else None

        self.maskslits = maskslits

        # For echelle order, primarily

        # List to hold ouptut from inspect about what module create the image?
        self.steps = []

        # Main output
        self.image = None
Ejemplo n.º 9
0
    def __init__(self,
                 tslits_dict,
                 tilts,
                 wv_calib,
                 spectrograph,
                 det,
                 maskslits,
                 master_key=None,
                 master_dir=None,
                 reuse_masters=False):

        # MasterFrame
        masterframe.MasterFrame.__init__(self,
                                         self.master_type,
                                         master_dir=master_dir,
                                         master_key=master_key,
                                         reuse_masters=reuse_masters)
        # Required parameters
        self.spectrograph = spectrograph
        self.det = det

        self.tslits_dict = tslits_dict
        self.tilts = tilts
        self.wv_calib = wv_calib
        if tslits_dict is not None:
            self.slitmask = pixels.tslits2mask(self.tslits_dict)
            self.slit_spat_pos = edgetrace.slit_spat_pos(self.tslits_dict)
        else:
            self.slitmask = None
            self.slit_spat_pos = None

        self.maskslits = maskslits

        # For echelle order, primarily
        # TODO: only echelle is ever used.  Do we need to keep the whole
        # thing?
        self.par = wv_calib['par'] if wv_calib is not None else None

        # Main output
        self.image = None
        self.steps = []
Ejemplo n.º 10
0
    def __init__(self,
                 tslits_dict,
                 tilts,
                 wv_calib,
                 spectrograph,
                 maskslits,
                 master_key=None,
                 master_dir=None,
                 reuse_masters=False):

        #    def __init__(self, spectrograph, tslits_dict, tilts, wv_calib, maskslits,
        #                 master_key=None, master_dir=None, reuse_masters=False):

        # MasterFrame
        MasterFrame.__init__(self,
                             self.master_type,
                             master_dir=master_dir,
                             master_key=master_key,
                             reuse_masters=reuse_masters)

        # Required parameters
        self.spectrograph = spectrograph

        self.tslits_dict = tslits_dict
        self.tilts = tilts
        self.wv_calib = wv_calib
        self.slitmask = pixels.tslits2mask(
            self.tslits_dict) if tslits_dict is not None else None
        # TODO: only echelle is ever used.  Do we need to keep the whole
        # thing?
        self.par = wv_calib['par'] if wv_calib is not None else None

        self.maskslits = maskslits

        # List to hold ouptut from inspect about what module create the image?
        self.steps = []

        # Main output
        self.mswave = None
Ejemplo n.º 11
0
    def generate_mask(self):
        """Generate the mask of sky regions

        Returns:
            ndarray : Boolean mask containing sky regions
        """
        nreg = 0
        left_edg, righ_edg = np.zeros((self.nspec, 0)), np.zeros(
            (self.nspec, 0))
        spec_min, spec_max = np.array([]), np.array([])
        for sl in range(self._nslits):
            diff = self.tslits_dict['slit_righ'][:, sl] - self.tslits_dict[
                'slit_left'][:, sl]
            tmp = np.zeros(self._resolution + 2)
            tmp[1:-1] = self._skyreg[sl]
            wl = np.where(tmp[1:] > tmp[:-1])[0]
            wr = np.where(tmp[1:] < tmp[:-1])[0]
            for rr in range(wl.size):
                left = self.tslits_dict['slit_left'][:, sl] + wl[rr] * diff / (
                    self._resolution - 1.0)
                righ = self.tslits_dict['slit_left'][:, sl] + wr[rr] * diff / (
                    self._resolution - 1.0)
                left_edg = np.append(left_edg, left[:, np.newaxis], axis=1)
                righ_edg = np.append(righ_edg, righ[:, np.newaxis], axis=1)
                nreg += 1
                spec_min = np.append(spec_min,
                                     self.tslits_dict['spec_min'][sl])
                spec_max = np.append(spec_max,
                                     self.tslits_dict['spec_max'][sl])
        reg_dict = dict(pad=0,
                        slit_left=left_edg,
                        slit_righ=righ_edg,
                        nslits=nreg,
                        nspec=self.nspec,
                        nspat=self.nspat,
                        spec_min=spec_min,
                        spec_max=spec_max)
        return (pixels.tslits2mask(reg_dict) >= 0).astype(np.int)
Ejemplo n.º 12
0
    def __init__(self,
                 msarc,
                 tslits_dict,
                 spectrograph,
                 par,
                 binspectral=None,
                 det=1,
                 master_key=None,
                 master_dir=None,
                 reuse_masters=False,
                 qa_path=None,
                 msbpm=None):

        # MasterFrame
        masterframe.MasterFrame.__init__(self,
                                         self.master_type,
                                         master_dir=master_dir,
                                         master_key=master_key,
                                         file_format='json',
                                         reuse_masters=reuse_masters)

        # Required parameters (but can be None)
        self.msarc = msarc
        self.tslits_dict = tslits_dict
        self.spectrograph = spectrograph
        self.par = par

        # Optional parameters
        self.bpm = msbpm
        self.binspectral = binspectral
        self.qa_path = qa_path
        self.det = det
        self.master_key = master_key

        # Attributes
        self.steps = []  # steps executed
        self.wv_calib = {}  # main output
        self.arccen = None  # central arc spectrum

        # --------------------------------------------------------------
        # TODO: Build another base class that does these things for both
        # WaveTilts and WaveCalib?

        # Get the non-linear count level
        self.nonlinear_counts = 1e10 if self.spectrograph is None \
                                    else self.spectrograph.nonlinear_counts(det=self.det)

        # Set the slitmask and slit boundary related attributes that the
        # code needs for execution. This also deals with arcimages that
        # have a different binning then the trace images used to defined
        # the slits
        if self.tslits_dict is not None and self.msarc is not None:
            self.slitmask_science = pixels.tslits2mask(self.tslits_dict)
            inmask = self.bpm == 0 if self.bpm is not None \
                                    else np.ones_like(self.slitmask_science, dtype=bool)
            self.shape_science = self.slitmask_science.shape
            self.shape_arc = self.msarc.shape
            self.nslits = self.tslits_dict['slit_left'].shape[1]
            self.slit_left = arc.resize_slits2arc(
                self.shape_arc, self.shape_science,
                self.tslits_dict['slit_left'])
            self.slit_righ = arc.resize_slits2arc(
                self.shape_arc, self.shape_science,
                self.tslits_dict['slit_righ'])
            self.slitcen = arc.resize_slits2arc(self.shape_arc,
                                                self.shape_science,
                                                self.tslits_dict['slitcen'])
            self.slitmask = arc.resize_mask2arc(self.shape_arc,
                                                self.slitmask_science)
            self.inmask = arc.resize_mask2arc(self.shape_arc, inmask)
            # TODO: Remove the following two lines if deemed ok
            if self.par['method'] != 'full_template':
                self.inmask &= self.msarc < self.nonlinear_counts
            self.slit_spat_pos = trace_slits.slit_spat_pos(self.tslits_dict)
        else:
            self.slitmask_science = None
            self.shape_science = None
            self.shape_arc = None
            self.nslits = 0
            self.slit_left = None
            self.slit_righ = None
            self.slitcen = None
            self.slitmask = None
            self.inmask = None
Ejemplo n.º 13
0
    def __init__(self,
                 msarc,
                 tslits_dict,
                 spectrograph,
                 par,
                 wavepar,
                 det=1,
                 master_key=None,
                 master_dir=None,
                 reuse_masters=False,
                 qa_path=None,
                 msbpm=None):

        self.spectrograph = spectrograph
        self.par = par
        self.wavepar = wavepar

        # MasterFrame
        masterframe.MasterFrame.__init__(self,
                                         self.master_type,
                                         master_dir=master_dir,
                                         master_key=master_key,
                                         reuse_masters=reuse_masters)

        self.msarc = msarc
        self.tslits_dict = tslits_dict
        self.msbpm = msbpm
        self.det = det
        self.qa_path = qa_path

        # --------------------------------------------------------------
        # TODO: Build another base class that does these things for both
        # WaveTilts and WaveCalib?

        # Get the non-linear count level
        self.nonlinear_counts = 1e10 if self.spectrograph is None \
                                    else self.spectrograph.nonlinear_counts(det=self.det)

        # Set the slitmask and slit boundary related attributes that the
        # code needs for execution. This also deals with arcimages that
        # have a different binning then the trace images used to defined
        # the slits
        if self.tslits_dict is not None and self.msarc is not None:
            self.slitmask_science = pixels.tslits2mask(self.tslits_dict)
            inmask = (self.msbpm == 0) if self.msbpm is not None \
                                        else np.ones_like(self.slitmask_science, dtype=bool)
            self.shape_science = self.slitmask_science.shape
            self.shape_arc = self.msarc.shape
            self.nslits = self.tslits_dict['slit_left'].shape[1]
            self.slit_left = arc.resize_slits2arc(
                self.shape_arc, self.shape_science,
                self.tslits_dict['slit_left'])
            self.slit_righ = arc.resize_slits2arc(
                self.shape_arc, self.shape_science,
                self.tslits_dict['slit_righ'])
            self.slitcen = arc.resize_slits2arc(self.shape_arc,
                                                self.shape_science,
                                                self.tslits_dict['slitcen'])
            self.slitmask = arc.resize_mask2arc(self.shape_arc,
                                                self.slitmask_science)
            self.inmask = (arc.resize_mask2arc(
                self.shape_arc, inmask)) & (self.msarc < self.nonlinear_counts)
        else:
            self.slitmask_science = None
            self.shape_science = None
            self.shape_arc = None
            self.nslits = 0
            self.slit_left = None
            self.slit_righ = None
            self.slitcen = None
            self.slitmask = None
            self.inmask = None
        # --------------------------------------------------------------

        # Key Internals
        self.mask = None
        self.all_trace_dict = [None] * self.nslits
        self.tilts = None
        # 2D fits are stored as a dictionary rather than list because we will jsonify the dict
        self.all_fit_dict = [None] * self.nslits
        self.steps = []
        # Main outputs
        self.final_tilts = None
        self.fit_dict = None
        self.trace_dict = None
Ejemplo n.º 14
0
    def run(self, debug=False, show=False, maskslits=None):
        """
        Generate normalized pixel and illumination flats

        Code flow::
           1.  Generate the pixelflat image (if necessary)
           2.  Prepare b-spline knot spacing
           3.  Loop on slits/orders
               a. Calculate the slit profile
               b. Normalize
               c. Save

        Args:
            debug (:obj:`bool`, optional):
                Run in debug mode.
            show (:obj:`bool`, optional):
                Show the results in the ginga viewer.
            maskslits (np.ndarray, optional):
               Array specifying whether a slit is good.
               True = bad

        Returns:
            `numpy.ndarray`_: Two arrays are returned, the normalized
            pixel flat data and the slit illumination correction data.
        """
        # Mask
        if maskslits is None:
            maskslits = np.zeros(self.nslits, dtype=bool)

        # Build the pixel flat (as needed)
        self.build_pixflat()

        # Prep tck (sets self.ntckx, self.ntcky)
        #self._prep_tck()

        # Setup
        self.mspixelflat = np.ones_like(self.rawflatimg.image)
        self.msillumflat = np.ones_like(self.rawflatimg.image)
        self.flat_model = np.zeros_like(self.rawflatimg.image)
        self.slitmask = pixels.tslits2mask(self.tslits_dict)

        final_tilts = np.zeros_like(self.rawflatimg.image)

        # If we are tweaking slits allocate the new aray to hold tweaked slit boundaries
        if self.flatpar['tweak_slits']:
            self.tslits_dict['slit_left_tweak'] = np.zeros_like(
                self.tslits_dict['slit_left'])
            self.tslits_dict['slit_righ_tweak'] = np.zeros_like(
                self.tslits_dict['slit_righ'])

        # Loop on slits
        for slit in range(self.nslits):
            # Is this a good slit??
            if maskslits[slit]:
                msgs.info('Skipping bad slit: {}'.format(slit))
                continue
            #
            msgs.info('Computing flat field image for slit: {:d}/{:d}'.format(
                slit, self.nslits - 1))
            if self.msbpm is not None:
                inmask = np.invert(self.msbpm)
            else:
                inmask = np.ones_like(self.rawflatimg.image, dtype=bool)

            # Fit flats for a single slit
            this_tilts_dict = {
                'tilts': self.tilts_dict['tilts'],
                'coeffs': self.tilts_dict['coeffs'][:, :, slit].copy(),
                'slitcen': self.tilts_dict['slitcen'][:, slit].copy(),
                'func2d': self.tilts_dict['func2d']
            }
            nonlinear_counts = self.spectrograph.nonlinear_counts(det=self.det)

            pixelflat, illumflat, flat_model, tilts_out, thismask_out, slit_left_out, \
                    slit_righ_out \
                            = flat.fit_flat(self.rawflatimg.image, this_tilts_dict, self.tslits_dict,
                                           slit, inmask=inmask, nonlinear_counts=nonlinear_counts,
                                           spec_samp_fine=self.flatpar['spec_samp_fine'],
                                           spec_samp_coarse=self.flatpar['spec_samp_coarse'],
                                           spat_samp=self.flatpar['spat_samp'],
                                           tweak_slits=self.flatpar['tweak_slits'],
                                           tweak_slits_thresh=self.flatpar['tweak_slits_thresh'],
                                           tweak_slits_maxfrac=self.flatpar['tweak_slits_maxfrac'],
                                           debug=debug)

            self.mspixelflat[thismask_out] = pixelflat[thismask_out]
            self.msillumflat[thismask_out] = illumflat[thismask_out]
            self.flat_model[thismask_out] = flat_model[thismask_out]

            # Did we tweak slit boundaries? If so, update the tslits_dict and the tilts_dict
            if self.flatpar['tweak_slits']:
                self.tslits_dict['slit_left'][:, slit] = slit_left_out
                self.tslits_dict['slit_righ'][:, slit] = slit_righ_out
                self.tslits_dict['slit_left_tweak'][:, slit] = slit_left_out
                self.tslits_dict['slit_righ_tweak'][:, slit] = slit_righ_out
                final_tilts[thismask_out] = tilts_out[thismask_out]

        # If we tweaked the slits update the tilts_dict
        if self.flatpar['tweak_slits']:
            self.tilts_dict['tilts'] = final_tilts

        if show:
            # Global skysub is the first step in a new extraction so clear the channels here
            self.show(slits=True, wcs_match=True)

        # If illumination flat fielding is turned off, set the illumflat to be None.
        if not self.flatpar['illumflatten']:
            msgs.warn(
                'No illumination flat will be applied to your data (illumflatten=False).'
            )
            self.msillumflat = None

        # Return
        return self.mspixelflat, self.msillumflat
Ejemplo n.º 15
0
    def run(self, debug=False, show=False):
        """
        Main driver to generate normalized flat field and illumination flats

        Code flow --
           1.  Generate the pixelflat image (if necessary)
           2.  Prepare b-spline knot spacing
           3.  Loop on slits/orders
               a. Calculate the slit profile
               b. Normalize
               c. Save

        Args:
            debug (bool, optional):
            show (bool, optional):

        Returns:
            ndarray, ndarray: self.mspixelflatnrm and self.slit_profiles

        """

        # Build the pixel flat (as needed)
        if self.rawflatimg is None:
            self.rawflatimg = self.build_pixflat()

        # Prep tck (sets self.ntckx, self.ntcky)
        #self._prep_tck()

        # Setup
        self.mspixelflat = np.ones_like(self.rawflatimg)
        self.msillumflat = np.ones_like(self.rawflatimg)
        self.flat_model = np.zeros_like(self.rawflatimg)
        self.slitmask = pixels.tslits2mask(self.tslits_dict)

        final_tilts = np.zeros_like(self.rawflatimg)

        # If we are tweaking slits allocate the new aray to hold tweaked slit boundaries
        if self.flatpar['tweak_slits']:
            self.tslits_dict['slit_left_tweak'] = np.zeros_like(
                self.tslits_dict['slit_left'])
            self.tslits_dict['slit_righ_tweak'] = np.zeros_like(
                self.tslits_dict['slit_righ'])

        # Loop on slits
        for slit in range(self.nslits):
            msgs.info('Computing flat field image for slit: {:d}/{:d}'.format(
                slit, self.nslits - 1))
            if self.msbpm is not None:
                inmask = np.invert(self.msbpm)
            else:
                inmask = np.ones_like(self.rawflatimg, dtype=bool)

            # Fit flats for a single slit
            this_tilts_dict = {
                'tilts': self.tilts_dict['tilts'],
                'coeffs': self.tilts_dict['coeffs'][:, :, slit].copy(),
                'slitcen': self.tilts_dict['slitcen'][:, slit].copy(),
                'func2d': self.tilts_dict['func2d']
            }
            nonlinear_counts = self.spectrograph.detector[self.det - 1]['nonlinear']*\
                               self.spectrograph.detector[self.det - 1]['saturation']
            pixelflat, illumflat, flat_model, tilts_out, thismask_out, slit_left_out, slit_righ_out = \
                flat.fit_flat(self.rawflatimg, this_tilts_dict, self.tslits_dict, slit,
                              inmask=inmask,
                              nonlinear_counts=nonlinear_counts,
                              spec_samp_fine=self.flatpar['spec_samp_fine'], spec_samp_coarse=self.flatpar['spec_samp_coarse'],
                              spat_samp=self.flatpar['spat_samp'], tweak_slits=self.flatpar['tweak_slits'],
                              tweak_slits_thresh=self.flatpar['tweak_slits_thresh'],
                              tweak_slits_maxfrac=self.flatpar['tweak_slits_maxfrac'],debug=debug)
            self.mspixelflat[thismask_out] = pixelflat[thismask_out]
            self.msillumflat[thismask_out] = illumflat[thismask_out]
            self.flat_model[thismask_out] = flat_model[thismask_out]
            # Did we tweak slit boundaries? If so, update the tslits_dict and the tilts_dict
            if self.flatpar['tweak_slits']:
                self.tslits_dict['slit_left'][:, slit] = slit_left_out
                self.tslits_dict['slit_righ'][:, slit] = slit_righ_out
                self.tslits_dict['slit_left_tweak'][:, slit] = slit_left_out
                self.tslits_dict['slit_righ_tweak'][:, slit] = slit_righ_out
                final_tilts[thismask_out] = tilts_out[thismask_out]

        # If we tweaked the slits update the tilts_dict
        if self.flatpar['tweak_slits']:
            self.tilts_dict['tilts'] = final_tilts

        if show:
            # Global skysub is the first step in a new extraction so clear the channels here
            self.show(slits=True, wcs_match=True)

        # If illumination flat fielding is turned off, set the illumflat to be None.
        if not self.flatpar['illumflatten']:
            msgs.warn(
                'You have set illumflatten=False. No illumination flat will be applied to your data.'
            )
            self.msillumflat = None

        # Return
        return self.mspixelflat, self.msillumflat
Ejemplo n.º 16
0
def main(args):

    # List only?
    hdu = fits.open(args.file)
    head0 = hdu[0].header
    if args.list:
        hdu.info()
        return

    # Setup for PYPIT imports
    msgs.reset(verbosity=2)

    # Init
    sdet = get_dnum(args.det, prefix=False)

    # One detector, sky sub for now
    names = [hdu[i].name for i in range(len(hdu))]

    try:
        exten = names.index('DET{:s}-PROCESSED'.format(sdet))
    except:  # Backwards compatability
        msgs.error(
            'Requested detector {:s} was not processed.\n'
            'Maybe you chose the wrong one to view?\n'
            'Set with --det= or check file contents with --list'.format(sdet))
    sciimg = hdu[exten].data
    try:
        exten = names.index('DET{:s}-SKY'.format(sdet))
    except:  # Backwards compatability
        msgs.error(
            'Requested detector {:s} has no sky model.\n'
            'Maybe you chose the wrong one to view?\n'
            'Set with --det= or check file contents with --list'.format(sdet))
    skymodel = hdu[exten].data
    try:
        exten = names.index('DET{:s}-MASK'.format(sdet))
    except ValueError:  # Backwards compatability
        msgs.error(
            'Requested detector {:s} has no bit mask.\n'
            'Maybe you chose the wrong one to view?\n'
            'Set with --det= or check file contents with --list'.format(sdet))
    mask = hdu[exten].data
    try:
        exten = names.index('DET{:s}-IVARMODEL'.format(sdet))
    except ValueError:  # Backwards compatability
        msgs.error(
            'Requested detector {:s} has no IVARMODEL.\n'
            'Maybe you chose the wrong one to view?\n' +
            'Set with --det= or check file contents with --list'.format(sdet))
    ivarmodel = hdu[exten].data
    # Read in the object model for residual map
    try:
        exten = names.index('DET{:s}-OBJ'.format(sdet))
    except ValueError:  # Backwards compatability
        msgs.error(
            'Requested detector {:s} has no object model.\n'
            'Maybe you chose the wrong one to view?\n' +
            'Set with --det= or check file contents with --list'.format(sdet))
    objmodel = hdu[exten].data
    # Get waveimg
    mdir = head0['PYPMFDIR'] + '/'
    if not os.path.exists(mdir):
        mdir_base = os.path.basename(os.path.dirname(mdir)) + '/'
        msgs.warn('Master file dir: {0} does not exist. Using ./{1}'.format(
            mdir, mdir_base))
        mdir = mdir_base

    trace_key = '{0}_{1:02d}'.format(head0['TRACMKEY'], args.det)
    trc_file = os.path.join(
        mdir, MasterFrame.construct_file_name('Trace', trace_key))

    wave_key = '{0}_{1:02d}'.format(head0['ARCMKEY'], args.det)
    waveimg = os.path.join(mdir,
                           MasterFrame.construct_file_name('Wave', wave_key))

    tslits_dict = TraceSlits.load_from_file(trc_file)[0]
    slitmask = pixels.tslits2mask(tslits_dict)
    shape = (tslits_dict['nspec'], tslits_dict['nspat'])
    slit_ids = [
        trace_slits.get_slitid(shape, tslits_dict['slit_left'],
                               tslits_dict['slit_righ'], ii)[0]
        for ii in range(tslits_dict['slit_left'].shape[1])
    ]
    # Show the bitmask?
    mask_in = mask if args.showmask else None

    # Object traces
    spec1d_file = args.file.replace('spec2d', 'spec1d')

    det_nm = 'DET{:s}'.format(sdet)
    if os.path.isfile(spec1d_file):
        hdulist_1d = fits.open(spec1d_file)
    else:
        hdulist_1d = []
        msgs.warn('Could not find spec1d file: {:s}'.format(spec1d_file) +
                  msgs.newline() +
                  '                          No objects were extracted.')

    # Unpack the bitmask
    bitMask = bitmask()
    bpm, crmask, satmask, minmask, offslitmask, nanmask, ivar0mask, ivarnanmask, extractmask \
            = bitMask.unpack(mask)

    # Now show each image to a separate channel

    # SCIIMG
    image = sciimg  # Raw science image
    (mean, med, sigma) = sigma_clipped_stats(image[mask == 0],
                                             sigma_lower=5.0,
                                             sigma_upper=5.0)
    cut_min = mean - 1.0 * sigma
    cut_max = mean + 4.0 * sigma
    chname_skysub = 'sciimg-det{:s}'.format(sdet)
    # Clear all channels at the beginning
    viewer, ch = ginga.show_image(image,
                                  chname=chname_skysub,
                                  waveimg=waveimg,
                                  bitmask=mask_in,
                                  clear=True)
    #, cuts=(cut_min, cut_max), wcs_match=True)
    ginga.show_slits(viewer, ch, tslits_dict['slit_left'],
                     tslits_dict['slit_righ'], slit_ids)
    #, args.det)

    # SKYSUB
    image = (sciimg - skymodel) * (mask == 0)  # sky subtracted image
    (mean, med, sigma) = sigma_clipped_stats(image[mask == 0],
                                             sigma_lower=5.0,
                                             sigma_upper=5.0)
    cut_min = mean - 1.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(
        image, chname=chname_skysub, waveimg=waveimg,
        bitmask=mask_in)  #, cuts=(cut_min, cut_max),wcs_match=True)
    show_trace(hdulist_1d, det_nm, viewer, ch)
    ginga.show_slits(viewer, ch, tslits_dict['slit_left'],
                     tslits_dict['slit_righ'], slit_ids)
    #, args.det)

    # SKRESIDS
    chname_skyresids = 'sky_resid-det{:s}'.format(sdet)
    image = (sciimg - skymodel) * np.sqrt(ivarmodel) * (mask == 0
                                                        )  # sky residual map
    viewer, ch = ginga.show_image(image,
                                  chname_skyresids,
                                  waveimg=waveimg,
                                  cuts=(-5.0, 5.0),
                                  bitmask=mask_in)  #,wcs_match=True)
    show_trace(hdulist_1d, det_nm, viewer, ch)
    ginga.show_slits(viewer, ch, tslits_dict['slit_left'],
                     tslits_dict['slit_righ'], slit_ids)
    #, args.det)

    # RESIDS
    chname_resids = 'resid-det{:s}'.format(sdet)
    # full model residual map
    image = (sciimg - skymodel - objmodel) * np.sqrt(ivarmodel) * (mask == 0)
    viewer, ch = ginga.show_image(image,
                                  chname=chname_resids,
                                  waveimg=waveimg,
                                  cuts=(-5.0, 5.0),
                                  bitmask=mask_in)  #,wcs_match=True)
    show_trace(hdulist_1d, det_nm, viewer, ch)
    ginga.show_slits(viewer, ch, tslits_dict['slit_left'],
                     tslits_dict['slit_righ'], slit_ids)
    #, args.det)

    # After displaying all the images sync up the images with WCS_MATCH
    shell = viewer.shell()
    out = shell.start_global_plugin('WCSMatch')
    out = shell.call_global_plugin_method('WCSMatch', 'set_reference_channel',
                                          [chname_resids], {})

    if args.embed:
        IPython.embed()
Ejemplo n.º 17
0
def extract_coadd2d(stack_dict, master_dir, samp_fact = 1.0,ir_redux=False, par=None, std=False, show=False, show_peaks=False):
    """
    Main routine to run the extraction for 2d coadds.

    Algorithm steps are as follows:
        - Fill this in.

    This performs 2d coadd specific tasks, and then also performs some
    of the tasks analogous to the pypeit.extract_one method. Docs coming
    soon....

    Args:
        stack_dict:
        master_dir:
        samp_fact: float
           sampling factor to make the wavelength grid finer or coarser.  samp_fact > 1.0 oversamples (finer),
           samp_fact < 1.0 undersamples (coarser)
        ir_redux:
        par:
        show:
        show_peaks:

    Returns:

    """

    # Find the objid of the brighest object, and the average snr across all orders
    nslits = stack_dict['tslits_dict']['slit_left'].shape[1]
    objid, snr_bar = get_brightest_obj(stack_dict['specobjs_list'], echelle=True)
    # TODO Print out a report here on the image stack, i.e. S/N of each image

    spectrograph = util.load_spectrograph(stack_dict['spectrograph'])
    par = spectrograph.default_pypeit_par() if par is None else par

    binning = np.array([stack_dict['tslits_dict']['binspectral'],stack_dict['tslits_dict']['binspatial']])
    # Grab the wavelength grid that we will rectify onto
    wave_grid = spectrograph.wavegrid(binning=binning,samp_fact=samp_fact)
    wave_grid_mid = spectrograph.wavegrid(midpoint=True,binning=binning,samp_fact=samp_fact)

    coadd_list = []
    nspec_vec = np.zeros(nslits,dtype=int)
    nspat_vec = np.zeros(nslits,dtype=int)

    # TODO: Generalize this to be a loop over detectors, such tha the
    # coadd_list is an ordered dict (perhaps) with all the slits on all
    # detectors
    for islit in range(nslits):
        msgs.info('Performing 2d coadd for slit: {:d}/{:d}'.format(islit,nslits-1))
        # Determine the wavelength dependent optimal weights and grab the reference trace
        rms_sn, weights, trace_stack, wave_stack = optimal_weights(stack_dict['specobjs_list'],
                                                                   islit, objid)
        thismask_stack = stack_dict['slitmask_stack'] == islit

        # Perform the 2d coadd
        coadd_dict = coadd2d(trace_stack, stack_dict['sciimg_stack'], stack_dict['sciivar_stack'],
                             stack_dict['skymodel_stack'], stack_dict['mask_stack'] == 0,
                             stack_dict['tilts_stack'], stack_dict['waveimg_stack'],
                             thismask_stack, weights=weights, wave_grid=wave_grid)
        coadd_list.append(coadd_dict)
        nspec_vec[islit]=coadd_dict['nspec']
        nspat_vec[islit]=coadd_dict['nspat']

    # Determine the size of the psuedo image
    nspat_pad = 10
    nspec_psuedo = nspec_vec.max()
    nspat_psuedo = np.sum(nspat_vec) + (nslits + 1)*nspat_pad
    spec_vec_psuedo = np.arange(nspec_psuedo)
    shape_psuedo = (nspec_psuedo, nspat_psuedo)
    imgminsky_psuedo = np.zeros(shape_psuedo)
    sciivar_psuedo = np.zeros(shape_psuedo)
    waveimg_psuedo = np.zeros(shape_psuedo)
    tilts_psuedo = np.zeros(shape_psuedo)
    spat_psuedo = np.zeros(shape_psuedo)
    nused_psuedo = np.zeros(shape_psuedo, dtype=int)
    inmask_psuedo = np.zeros(shape_psuedo, dtype=bool)
    wave_mid = np.zeros((nspec_psuedo, nslits))
    wave_mask = np.zeros((nspec_psuedo, nslits),dtype=bool)
    wave_min = np.zeros((nspec_psuedo, nslits))
    wave_max = np.zeros((nspec_psuedo, nslits))
    dspat_mid = np.zeros((nspat_psuedo, nslits))

    spat_left = nspat_pad
    slit_left = np.zeros((nspec_psuedo, nslits))
    slit_righ = np.zeros((nspec_psuedo, nslits))
    spec_min1 = np.zeros(nslits)
    spec_max1 = np.zeros(nslits)



    for islit, coadd_dict in enumerate(coadd_list):
        spat_righ = spat_left + nspat_vec[islit]
        ispec = slice(0,nspec_vec[islit])
        ispat = slice(spat_left,spat_righ)
        imgminsky_psuedo[ispec, ispat] = coadd_dict['imgminsky']
        sciivar_psuedo[ispec, ispat] = coadd_dict['sciivar']
        waveimg_psuedo[ispec, ispat] = coadd_dict['waveimg']
        tilts_psuedo[ispec, ispat] = coadd_dict['tilts']
        # spat_psuedo is the sub-pixel image position on the rebinned psuedo image
        inmask_psuedo[ispec, ispat] = coadd_dict['outmask']
        image_temp = (coadd_dict['dspat'] -  coadd_dict['dspat_mid'][0] + spat_left)*coadd_dict['outmask']
        spat_psuedo[ispec, ispat] = image_temp
        nused_psuedo[ispec, ispat] = coadd_dict['nused']
        wave_min[ispec, islit] = coadd_dict['wave_min']
        wave_max[ispec, islit] = coadd_dict['wave_max']
        wave_mid[ispec, islit] = coadd_dict['wave_mid']
        wave_mask[ispec, islit] = True
        # Fill in the rest of the wave_mid with the corresponding points in the wave_grid
        wave_this = wave_mid[wave_mask[:,islit], islit]
        ind_upper = np.argmin(np.abs(wave_grid_mid - np.max(wave_this.max()))) + 1
        if nspec_vec[islit] != nspec_psuedo:
            wave_mid[nspec_vec[islit]:, islit] = wave_grid_mid[ind_upper:ind_upper + (nspec_psuedo-nspec_vec[islit])]

        dspat_mid[ispat, islit] = coadd_dict['dspat_mid']
        slit_left[:,islit] = np.full(nspec_psuedo, spat_left)
        slit_righ[:,islit] = np.full(nspec_psuedo, spat_righ)
        spec_max1[islit] = nspec_vec[islit]-1
        spat_left = spat_righ + nspat_pad


    slitcen = (slit_left + slit_righ)/2.0
    tslits_dict_psuedo = dict(slit_left=slit_left, slit_righ=slit_righ, slitcen=slitcen,
                              nspec=nspec_psuedo, nspat=nspat_psuedo, pad=0,
                              nslits = nslits, binspectral=1, binspatial=1, spectrograph=spectrograph.spectrograph,
                              spec_min=spec_min1, spec_max=spec_max1)

    slitmask_psuedo = pixels.tslits2mask(tslits_dict_psuedo)
    # This is a kludge to deal with cases where bad wavelengths result in large regions where the slit is poorly sampled,
    # which wreaks havoc on the local sky-subtraction
    min_slit_frac = 0.70
    spec_min = np.zeros(nslits)
    spec_max = np.zeros(nslits)
    for islit in range(nslits):
        slit_width = np.sum(inmask_psuedo*(slitmask_psuedo == islit),axis=1)
        slit_width_img = np.outer(slit_width, np.ones(nspat_psuedo))
        med_slit_width = np.median(slit_width_img[slitmask_psuedo==islit])
        nspec_eff = np.sum(slit_width > min_slit_frac*med_slit_width)
        nsmooth = int(np.fmax(np.ceil(nspec_eff*0.02),10))
        slit_width_sm = scipy.ndimage.filters.median_filter(slit_width, size=nsmooth, mode='reflect')
        igood = (slit_width_sm > min_slit_frac*med_slit_width)
        spec_min[islit] = spec_vec_psuedo[igood].min()
        spec_max[islit] = spec_vec_psuedo[igood].max()
        bad_pix = (slit_width_img < min_slit_frac*med_slit_width) & (slitmask_psuedo == islit)
        inmask_psuedo[bad_pix] = False

    # Update with tslits_dict_psuedo
    tslits_dict_psuedo['spec_min'] = spec_min
    tslits_dict_psuedo['spec_max'] = spec_max
    slitmask_psuedo = pixels.tslits2mask(tslits_dict_psuedo)

    # Make a fake bitmask from the outmask. We are kludging the crmask to be the outmask_psuedo here, and setting the bpm to
    # be good everywhere
    mask = processimages.ProcessImages.build_mask(imgminsky_psuedo, sciivar_psuedo, np.invert(inmask_psuedo),
                                                  np.zeros_like(inmask_psuedo), slitmask=slitmask_psuedo)

    redux = reduce.instantiate_me(spectrograph, tslits_dict_psuedo, mask, ir_redux=ir_redux, par=par,
                                  objtype = 'science', binning=binning)

    if show:
        redux.show('image', image=imgminsky_psuedo*(mask == 0), chname = 'imgminsky', slits=True, clear=True)
    # Object finding
    sobjs_obj, nobj, skymask_init = redux.find_objects(imgminsky_psuedo, sciivar_psuedo, ir_redux=ir_redux, std=std,
                                                       show_peaks=show_peaks, show=show)
    # Local sky-subtraction
    global_sky_psuedo = np.zeros_like(imgminsky_psuedo) # No global sky for co-adds since we go straight to local
    rn2img_psuedo = global_sky_psuedo # No rn2img for co-adds since we go do not model noise
    skymodel_psuedo, objmodel_psuedo, ivarmodel_psuedo, outmask_psuedo, sobjs = \
        redux.local_skysub_extract(imgminsky_psuedo, sciivar_psuedo, tilts_psuedo, waveimg_psuedo, global_sky_psuedo,
                                   rn2img_psuedo, sobjs_obj, spat_pix=spat_psuedo, std=std,
                                   model_noise=False, show_profile=show, show=show)

    if ir_redux:
        sobjs.purge_neg()

    # Add the information about the fixed wavelength grid to the sobjs
    for spec in sobjs:
        spec.boxcar['WAVE_GRID_MASK'] = wave_mask[:,spec.slitid]
        spec.boxcar['WAVE_GRID'] = wave_mid[:,spec.slitid]
        spec.boxcar['WAVE_GRID_MIN'] = wave_min[:,spec.slitid]
        spec.boxcar['WAVE_GRID_MAX'] = wave_max[:,spec.slitid]

        spec.optimal['WAVE_GRID_MASK'] = wave_mask[:,spec.slitid]
        spec.optimal['WAVE_GRID'] = wave_mid[:,spec.slitid]
        spec.optimal['WAVE_GRID_MIN'] = wave_min[:,spec.slitid]
        spec.optimal['WAVE_GRID_MAX'] = wave_max[:,spec.slitid]


    # TODO Implement flexure and heliocentric corrections on the single exposure 1d reductions and apply them to the
    # waveimage. Change the data model to accomodate a wavelength model for each image.
    # Using the same implementation as in core/pypeit

    # Write out the psuedo master files to disk
    master_key_dict = stack_dict['master_key_dict']

    # TODO: These saving operations are a temporary kludge
    waveImage = WaveImage(None, None, None, None, None, master_key=master_key_dict['arc'],
                          master_dir=master_dir)
    waveImage.save(mswave=waveimg_psuedo)

    traceSlits = TraceSlits(None, None, master_key=master_key_dict['trace'], master_dir=master_dir)
    traceSlits.save(tslits_dict=tslits_dict_psuedo)

    return imgminsky_psuedo, sciivar_psuedo, skymodel_psuedo, objmodel_psuedo, ivarmodel_psuedo, outmask_psuedo, sobjs
Ejemplo n.º 18
0
def load_coadd2d_stacks(spec2d_files, det):
    """

    Args:
        spec2d_files: list
           List of spec2d filenames
        det: int
           detector in question

    Returns:
        stack_dict: dict
           Dictionary containing all the images and keys required for perfomring 2d coadds.

    """

    # Get the detector string
    sdet = parse.get_dnum(det, prefix=False)

    # Get the master dir
    head0 = fits.getheader(spec2d_files[0])
    master_dir = os.path.basename(head0['PYPMFDIR'])
    redux_path =  os.getcwd()
    master_path = os.path.join(redux_path, master_dir)

    # Grab the files
    head2d_list=[]
    tracefiles = []
    waveimgfiles = []
    tiltfiles = []
    spec1d_files = []
    for f in spec2d_files:
        head = fits.getheader(f)
        trace_key = '{0}_{1:02d}'.format(head['TRACMKEY'], det)
        wave_key = '{0}_{1:02d}'.format(head['ARCMKEY'], det)

        head2d_list.append(head)
        spec1d_files.append(f.replace('spec2d', 'spec1d'))
        tracefiles.append(os.path.join(master_path,
                                       MasterFrame.construct_file_name('Trace', trace_key)))
        waveimgfiles.append(os.path.join(master_path,
                                         MasterFrame.construct_file_name('Wave', wave_key)))
        tiltfiles.append(os.path.join(master_path,
                                      MasterFrame.construct_file_name('Tilts', wave_key)))

    nfiles = len(spec2d_files)

    specobjs_list = []
    head1d_list=[]
    # TODO Sort this out with the correct detector extensions etc.
    # Read in the image stacks
    for ifile in range(nfiles):
        waveimg = WaveImage.load_from_file(waveimgfiles[ifile])
        tilts = WaveTilts.load_from_file(tiltfiles[ifile])
        hdu = fits.open(spec2d_files[ifile])
        # One detector, sky sub for now
        names = [hdu[i].name for i in range(len(hdu))]
        # science image
        try:
            exten = names.index('DET{:s}-PROCESSED'.format(sdet))
        except:  # Backwards compatability
            det_error_msg(exten, sdet)
        sciimg = hdu[exten].data
        # skymodel
        try:
            exten = names.index('DET{:s}-SKY'.format(sdet))
        except:  # Backwards compatability
            det_error_msg(exten, sdet)
        skymodel = hdu[exten].data
        # Inverse variance model
        try:
            exten = names.index('DET{:s}-IVARMODEL'.format(sdet))
        except ValueError:  # Backwards compatability
            det_error_msg(exten, sdet)
        sciivar = hdu[exten].data
        # Mask
        try:
            exten = names.index('DET{:s}-MASK'.format(sdet))
        except ValueError:  # Backwards compatability
            det_error_msg(exten, sdet)
        mask = hdu[exten].data
        if ifile == 0:
            # the two shapes accomodate the possibility that waveimg and tilts are binned differently
            shape_wave = (nfiles,waveimg.shape[0],waveimg.shape[1])
            shape_sci = (nfiles,sciimg.shape[0],sciimg.shape[1])
            waveimg_stack = np.zeros(shape_wave,dtype=float)
            tilts_stack = np.zeros(shape_wave,dtype=float)
            sciimg_stack = np.zeros(shape_sci,dtype=float)
            skymodel_stack = np.zeros(shape_sci,dtype=float)
            sciivar_stack = np.zeros(shape_sci,dtype=float)
            mask_stack = np.zeros(shape_sci,dtype=float)

        waveimg_stack[ifile,:,:] = waveimg
        tilts_stack[ifile,:,:] = tilts['tilts']
        sciimg_stack[ifile,:,:] = sciimg
        sciivar_stack[ifile,:,:] = sciivar
        mask_stack[ifile,:,:] = mask
        skymodel_stack[ifile,:,:] = skymodel

        sobjs, head = load.load_specobjs(spec1d_files[ifile])
        head1d_list.append(head)
        specobjs_list.append(sobjs)

    # Right now we assume there is a single tslits_dict for all images and read in the first one
    # TODO this needs to become a tslits_dict for each file to accomodate slits defined by flats taken on different
    # nights
    tslits_dict, _ = TraceSlits.load_from_file(tracefiles[0])
    spectrograph = util.load_spectrograph(tslits_dict['spectrograph'])
    slitmask = pixels.tslits2mask(tslits_dict)
    slitmask_stack = np.einsum('i,jk->ijk', np.ones(nfiles), slitmask)

    # Fill the master key dict
    head2d = head2d_list[0]
    master_key_dict = {}
    master_key_dict['frame'] = head2d['FRAMMKEY']  + '_{:02d}'.format(det)
    master_key_dict['bpm']   = head2d['BPMMKEY']   + '_{:02d}'.format(det)
    master_key_dict['bias']  = head2d['BIASMKEY']  + '_{:02d}'.format(det)
    master_key_dict['arc']   = head2d['ARCMKEY']   + '_{:02d}'.format(det)
    master_key_dict['trace'] = head2d['TRACMKEY']  + '_{:02d}'.format(det)
    master_key_dict['flat']  = head2d['FLATMKEY']  + '_{:02d}'.format(det)
    stack_dict = dict(specobjs_list=specobjs_list, tslits_dict=tslits_dict,
                      slitmask_stack=slitmask_stack,
                      sciimg_stack=sciimg_stack, sciivar_stack=sciivar_stack,
                      skymodel_stack=skymodel_stack, mask_stack=mask_stack,
                      tilts_stack=tilts_stack, waveimg_stack=waveimg_stack,
                      head1d_list = head1d_list, head2d_list=head2d_list,
                      redux_path=redux_path, master_path=master_path, master_dir=master_dir,
                      master_key_dict=master_key_dict,
                      spectrograph = tslits_dict['spectrograph'])

    return stack_dict
Ejemplo n.º 19
0
    def __init__(self,
                 msalign,
                 tslits_dict,
                 spectrograph,
                 par,
                 det=1,
                 binning=None,
                 qa_path=None,
                 msbpm=None):

        # MasterFrame
        #masterframe.MasterFrame.__init__(self, self.master_type, master_dir=master_dir,
        #                                 master_key=master_key, file_format='fits',
        #                                 reuse_masters=reuse_masters)

        # Required parameters (but can be None)
        self.msalign = msalign
        self.tslits_dict = tslits_dict
        self.spectrograph = spectrograph
        self.par = par
        self.binning = binning

        # Optional parameters
        self.bpm = msalign.mask if msbpm is None else msbpm
        self.qa_path = qa_path
        self.det = det
        #self.master_key = master_key

        # Attributes
        self.viewer, self.channel = None, None
        self.steps = []  # steps executed

        # Get the non-linear count level
        self.nonlinear_counts = 1e10 if self.spectrograph is None \
            else self.spectrograph.nonlinear_counts(self.det)

        # --------------------------------------------------------------
        # Set the slitmask and slit boundary related attributes that the
        # code needs for execution. This also deals with alignframes that
        # have a different binning then the images used to defined
        # the slits
        if self.tslits_dict is not None and self.msalign is not None:
            self.slitmask_science = pixels.tslits2mask(self.tslits_dict)
            gpm = self.bpm == 0 if self.bpm is not None \
                else np.ones_like(self.slitmask_science, dtype=bool)
            self.shape_science = self.slitmask_science.shape
            self.shape_align = self.msalign.image.shape
            self.nslits = self.tslits_dict['slit_left'].shape[1]
            self.slit_left = arc.resize_slits2arc(
                self.shape_align, self.shape_science,
                self.tslits_dict['slit_left'])
            self.slit_righ = arc.resize_slits2arc(
                self.shape_align, self.shape_science,
                self.tslits_dict['slit_righ'])
            self.slitcen = arc.resize_slits2arc(self.shape_align,
                                                self.shape_science,
                                                self.tslits_dict['slitcen'])
            self.slitmask = arc.resize_mask2arc(self.shape_align,
                                                self.slitmask_science)
            self.gpm = arc.resize_mask2arc(self.shape_align, gpm)
            self.gpm &= self.msalign.image < self.nonlinear_counts
            self.slit_spat_pos = edgetrace.slit_spat_pos(
                self.tslits_dict['slit_left'], self.tslits_dict['slit_righ'],
                self.tslits_dict['nspec'], self.tslits_dict['nspat'])
        else:
            self.slitmask_science = None
            self.shape_science = None
            self.shape_align = None
            self.nslits = 0
            self.slit_left = None
            self.slit_righ = None
            self.slitcen = None
            self.slitmask = None
            self.gpm = None
            self.nonlinear_counts = None
Ejemplo n.º 20
0
    def extract_one(self, frames, det, bg_frames, std_outfile=None):
        """
        Extract a single exposure/detector pair

        sci_ID and det need to have been set internally prior to calling this method

        Args:
            frames (list):
                List of frames to extract;  stacked if more than one is provided
            det (int):
            bg_frames (list):
                List of frames to use as the background
                Can be empty
            std_outfile (str, optional):

        Returns:
            seven objects are returned::
                - ndarray: Science image
                - ndarray: Science inverse variance image
                - ndarray: Model of the sky
                - ndarray: Model of the object
                - ndarray: Model of inverse variance
                - ndarray: Mask
                - :obj:`pypeit.specobjs.SpecObjs`: spectra

        """
        # 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
        # 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)
        self.sciImg = scienceimage.build_from_file_list(
            self.spectrograph,
            det,
            self.par['scienceframe']['process'],
            self.caliBrate.msbpm,
            sci_files,
            self.caliBrate.msbias,
            self.caliBrate.mspixelflat,
            illum_flat=self.caliBrate.msillumflat)

        # Background Image?
        if len(bg_frames) > 0:
            bg_file_list = self.fitstbl.frame_paths(bg_frames)
            self.sciImg = self.sciImg - scienceimage.build_from_file_list(
                self.spectrograph,
                det,
                self.par['scienceframe']['process'],
                self.caliBrate.msbpm,
                bg_file_list,
                self.caliBrate.msbias,
                self.caliBrate.mspixelflat,
                illum_flat=self.caliBrate.msillumflat)

        # Update mask for slitmask
        slitmask = pixels.tslits2mask(self.caliBrate.tslits_dict)
        self.sciImg.update_mask_slitmask(slitmask)

        # For QA on crash
        msgs.sciexp = self.sciImg

        # Instantiate Reduce object
        self.maskslits = self.caliBrate.tslits_dict['maskslits'].copy()
        # Required for pypeline specific object
        # TODO -- caliBrate should be replaced by the ~3 primary Objects needed
        #   once we have the data models in place.
        self.redux = reduce.instantiate_me(self.sciImg,
                                           self.spectrograph,
                                           self.par,
                                           self.caliBrate,
                                           maskslits=self.maskslits,
                                           ir_redux=self.ir_redux,
                                           std_redux=self.std_redux,
                                           objtype=self.objtype,
                                           setup=self.setup,
                                           show=self.show,
                                           det=det,
                                           binning=self.binning)
        # Show?
        if self.show:
            self.redux.show('image',
                            image=self.sciImg.image,
                            chname='processed',
                            slits=True,
                            clear=True)

        # Prep for manual extraction (if requested)
        manual_extract_dict = self.fitstbl.get_manual_extract(frames, det)

        self.skymodel, self.objmodel, self.ivarmodel, self.outmask, self.sobjs = self.redux.run(
            std_trace=std_trace,
            manual_extract_dict=manual_extract_dict,
            show_peaks=self.show,
            basename=self.basename,
            ra=self.fitstbl["ra"][frames[0]],
            dec=self.fitstbl["dec"][frames[0]],
            obstime=self.obstime)

        # Return
        return self.sciImg.image, self.sciImg.ivar, self.skymodel, self.objmodel, self.ivarmodel, self.outmask, self.sobjs