예제 #1
0
    def __init__(self, mstilt, slits, spectrograph, par, wavepar, det=1, qa_path=None,
                 master_key=None, spat_flexure=None):

        # TODO: Perform type checking
        self.spectrograph = spectrograph
        self.par = par
        self.wavepar = wavepar

        self.mstilt = mstilt
        self.slits = slits
        self.det = det
        self.qa_path = qa_path
        self.master_key = master_key
        self.spat_flexure = spat_flexure

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

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

        # Set the slitmask and slit boundary related attributes that the
        # code needs for execution. This also deals with arcimages that
        # have a different binning then the trace images used to defined
        # the slits

        # TODO -- Tidy this up into one or two methods?
        # Load up all slits
        # TODO -- Discuss further with JFH
        all_left, all_right, mask = self.slits.select_edges(initial=True, flexure=self.spat_flexure)  # Grabs all, initial slits
        self.tilt_bpm = np.invert(mask == 0)
        self.tilt_bpm_init = self.tilt_bpm.copy()
        # Slitmask
        # TODO -- Discuss further with JFH
        self.slitmask_science = self.slits.slit_img(initial=True, flexure=self.spat_flexure)  # All unmasked slits
        # Resize
        gpm = (self.mstilt.bpm == 0) if self.mstilt.bpm is not None \
            else np.ones_like(self.slitmask_science, dtype=bool)
        self.shape_science = self.slitmask_science.shape
        self.shape_tilt = self.mstilt.image.shape
        self.slitcen = arc.resize_slits2arc(self.shape_tilt, self.shape_science, (all_left+all_right)/2)
        self.slitmask = arc.resize_mask2arc(self.shape_tilt, self.slitmask_science)
        self.gpm = (arc.resize_mask2arc(self.shape_tilt, gpm)) & (self.mstilt.image < self.nonlinear_counts)
    # --------------------------------------------------------------

        # Key Internals
        self.mask = None
        self.all_trace_dict = [None]*self.slits.nslits
        self.tilts = None
        # 2D fits are stored as a dictionary rather than list because we will jsonify the dict
        self.all_fit_dict = [None]*self.slits.nslits
        self.steps = []
        # Main outputs
        self.final_tilts = None
        self.fit_dict = None
        self.trace_dict = None
예제 #2
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
예제 #3
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
예제 #4
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
예제 #5
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
예제 #6
0
파일: wavecalib.py 프로젝트: Tuo-Ji/PypeIt
    def __init__(self,
                 msarc,
                 slits,
                 spectrograph,
                 par,
                 binspectral=None,
                 det=1,
                 qa_path=None,
                 msbpm=None,
                 master_key=None):

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

        # Optional parameters
        self.bpm = msbpm
        if self.bpm is None:
            if msarc is not None:  # Can be None for load;  will remove this for DataContainer
                self.bpm = msarc.bpm
        self.binspectral = binspectral
        self.qa_path = qa_path
        self.det = det
        self.master_key = master_key

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

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

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

        # Set the slitmask and slit boundary related attributes that the
        # code needs for execution. This also deals with arcimages that
        # have a different binning then the trace images used to defined
        # the slits
        if self.slits is not None and self.msarc is not None:
            # Load up slits
            # TODO -- Allow for flexure
            all_left, all_right, mask = self.slits.select_edges(
                initial=True, flexure=None)  # Grabs all, init slits + flexure
            self.orders = self.slits.ech_order  # Can be None
            #            self.spat_coo = self.slits.spatial_coordinates()  # All slits, even masked
            # Internal mask for failed wv_calib analysis
            # TODO -- Allow for an option to re-attempt those previously flagged as BADWVCALIB?
            self.wvc_bpm = np.invert(mask == 0)
            self.wvc_bpm_init = self.wvc_bpm.copy()
            # Slitmask -- Grabs only unmasked, initial slits
            self.slitmask_science = self.slits.slit_img(initial=True,
                                                        flexure=None)
            # Resize
            self.shape_science = self.slitmask_science.shape
            self.shape_arc = self.msarc.image.shape
            # slitcen is padded to include slits that may be masked, for convenience in coding downstream
            self.slitcen = arc.resize_slits2arc(self.shape_arc,
                                                self.shape_science,
                                                (all_left + all_right) / 2)
            self.slitmask = arc.resize_mask2arc(self.shape_arc,
                                                self.slitmask_science)
            # Mask
            gpm = self.bpm == 0 if self.bpm is not None \
                else np.ones_like(self.slitmask_science, dtype=bool)
            self.gpm = arc.resize_mask2arc(self.shape_arc, gpm)
            # We want even the saturated lines in full_template for the cross-correlation
            #   They will be excised in the detect_lines() method on the extracted arc
            if self.par['method'] != 'full_template':
                self.gpm &= self.msarc.image < self.nonlinear_counts

        else:
            self.orders = None
            self.wvc_bpm = None
            self.wvc_bpm_init = None
            self.slitmask_science = None
            self.shape_science = None
            self.shape_arc = None
            self.slitcen = None
            self.slitmask = None
            self.gpm = None
예제 #7
0
    def __init__(self,
                 mstilt,
                 slits,
                 spectrograph,
                 par,
                 wavepar,
                 det=1,
                 qa_path=None,
                 master_key=None,
                 spat_flexure=None):

        # TODO: Perform type checking
        self.spectrograph = spectrograph
        self.par = par
        self.wavepar = wavepar

        self.mstilt = mstilt
        self.slits = slits
        self.det = det
        self.qa_path = qa_path
        self.master_key = master_key
        self.spat_flexure = spat_flexure

        # Get the non-linear count level
        # TODO: This is currently hacked to deal with Mosaics
        try:
            self.nonlinear_counts = self.mstilt.detector.nonlinear_counts()
        except:
            self.nonlinear_counts = 1e10

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

# Set the slitmask and slit boundary related attributes that the
# code needs for execution. This also deals with arcimages that
# have a different binning then the trace images used to defined
# the slits

# TODO -- Tidy this up into one or two methods?
# Load up all slits
# TODO -- Discuss further with JFH
        all_left, all_right, mask = self.slits.select_edges(
            initial=True,
            flexure=self.spat_flexure)  # Grabs all, initial slits
        # self.tilt_bpm = np.invert(mask == 0)
        # At this point of the reduction the only bitmask flags that may have been generated are 'USERIGNORE',
        # 'SHORTSLIT', 'BOXSLIT' and 'BADWVCALIB'. Here we use only 'USERIGNORE' and 'SHORTSLIT' to create the bpm mask
        self.tilt_bpm = self.slits.bitmask.flagged(
            mask, flag=['SHORTSLIT', 'USERIGNORE'])
        self.tilt_bpm_init = self.tilt_bpm.copy()
        # Slitmask
        # TODO -- Discuss further with JFH
        self.slitmask_science = self.slits.slit_img(
            initial=True, flexure=self.spat_flexure,
            exclude_flag=['BOXSLIT'])  # All unmasked slits
        # Resize
        gpm = (self.mstilt.bpm == 0) if self.mstilt.bpm is not None \
            else np.ones_like(self.slitmask_science, dtype=bool)
        self.shape_science = self.slitmask_science.shape
        self.shape_tilt = self.mstilt.image.shape
        self.slitcen = arc.resize_slits2arc(self.shape_tilt,
                                            self.shape_science,
                                            (all_left + all_right) / 2)
        self.slitmask = arc.resize_mask2arc(self.shape_tilt,
                                            self.slitmask_science)
        self.gpm = (arc.resize_mask2arc(self.shape_tilt, gpm)) & (
            self.mstilt.image < self.nonlinear_counts)
        # --------------------------------------------------------------

        # Key Internals
        self.mask = None
        self.all_trace_dict = [None] * self.slits.nslits
        self.tilts = None
        # 2D fits are stored as a dictionary rather than list because we will jsonify the dict
        self.all_fit_dict = [None] * self.slits.nslits
        self.steps = []
        # Main outputs
        self.final_tilts = None
        self.fit_dict = None
        self.trace_dict = None
예제 #8
0
    def __init__(self,
                 msarc,
                 slits,
                 spectrograph,
                 par,
                 lamps,
                 binspectral=None,
                 det=1,
                 qa_path=None,
                 msbpm=None,
                 master_key=None):

        # TODO: This should be a stop-gap to avoid instantiation of this with
        # any Nones.
        if None in [msarc, slits, spectrograph, par, lamps]:
            msgs.error(
                'CODING ERROR: Cannot instantiate BuildWaveCalib with Nones.')

        # Required parameters
        self.msarc = msarc
        self.slits = slits
        self.spectrograph = spectrograph
        self.par = par
        self.lamps = lamps

        # Optional parameters
        self.bpm = self.msarc.select_flag(
            flag='BPM') if msbpm is None else msbpm.astype(bool)
        if self.bpm.shape != self.msarc.shape:
            msgs.error(
                'Bad-pixel mask is not the same shape as the arc image.')
#        self.bpm = msbpm
#        if self.bpm is None and msarc is not None:
#            # msarc can be None for load;  will remove this for DataContainer
#            self.bpm = msarc.bpm
        self.binspectral = binspectral
        self.qa_path = qa_path
        self.det = det
        self.master_key = master_key

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

        # Get the non-linear count level
        # TODO: This is currently hacked to deal with Mosaics
        try:
            self.nonlinear_counts = self.msarc.detector.nonlinear_counts()
        except:
            self.nonlinear_counts = 1e10

#        self.nonlinear_counts = 1e10 if self.spectrograph is None \
#            else self.spectrograph.nonlinear_counts(self.msarc.detector)
#else self.spectrograph.nonlinear_counts(self.det)

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

# Set the slitmask and slit boundary related attributes that the
# code needs for execution. This also deals with arcimages that
# have a different binning then the trace images used to defined
# the slits
        if self.slits is not None and self.msarc is not None:
            # Load up slits
            # TODO -- Allow for flexure
            all_left, all_right, mask = self.slits.select_edges(
                initial=True, flexure=None)  # Grabs all, init slits + flexure
            self.orders = self.slits.ech_order  # Can be None
            #            self.spat_coo = self.slits.spatial_coordinates()  # All slits, even masked
            # Internal mask for failed wv_calib analysis
            # TODO -- Allow for an option to re-attempt those previously flagged as BADWVCALIB?
            self.wvc_bpm = np.invert(mask == 0)
            ## We want to keep the 'BOXSLIT', which mask value is 2. But we don't want to keep 'BOXSLIT'
            ## with other bad flag (for which the mask value would be > 2)
            #self.wvc_bpm = mask > 2
            self.wvc_bpm_init = self.wvc_bpm.copy()
            # Slitmask -- Grabs only unmasked, initial slits
            #self.slitmask_science = self.slits.slit_img(initial=True, flexure=None, exclude_flag=['BOXSLIT'])
            self.slitmask_science = self.slits.slit_img(initial=True,
                                                        flexure=None)
            # Resize
            self.shape_science = self.slitmask_science.shape
            self.shape_arc = self.msarc.image.shape
            # slitcen is padded to include slits that may be masked, for convenience in coding downstream
            self.slitcen = arc.resize_slits2arc(self.shape_arc,
                                                self.shape_science,
                                                (all_left + all_right) / 2)
            self.slitmask = arc.resize_mask2arc(self.shape_arc,
                                                self.slitmask_science)
            # Mask
            gpm = self.bpm == 0 if self.bpm is not None \
                else np.ones_like(self.slitmask_science, dtype=bool)
            self.gpm = arc.resize_mask2arc(self.shape_arc, gpm)
            # We want even the saturated lines in full_template for the cross-correlation
            #   They will be excised in the detect_lines() method on the extracted arc
            if self.par['method'] != 'full_template':
                self.gpm &= self.msarc.image < self.nonlinear_counts

        else:
            self.orders = None
            self.wvc_bpm = None
            self.wvc_bpm_init = None
            self.slitmask_science = None
            self.shape_science = None
            self.shape_arc = None
            self.slitcen = None
            self.slitmask = None
            self.gpm = None
예제 #9
0
파일: flexure.py 프로젝트: mcoughlin/PypeIt
def spat_flexure_shift(sciimg, slits, debug=False, maxlag=20):
    """
    Calculate a rigid flexure shift in the spatial dimension
    between the slitmask and the science image.

    It is *important* to use original=True when defining the
    slitmask as everything should be relative to the initial slits

    Otherwise, the WaveTilts could get out of sync with science images

    Args:
        sciimg (`numpy.ndarray`_):
        slits (:class:`pypeit.slittrace.SlitTraceSet`):
        maxlag (:obj:`int`, optional):
            Maximum flexure searched for

    Returns:
        float:  The spatial flexure shift relative to the initial slits

    """
    # Mask -- Includes short slits and those excluded by the user (e.g. ['rdx']['slitspatnum'])
    slitmask = slits.slit_img(initial=True,
                              exclude_flag=slits.bitmask.exclude_for_flexure)

    _sciimg = sciimg if slitmask.shape == sciimg.shape \
                else arc.resize_mask2arc(slitmask.shape, sciimg)
    onslits = slitmask > -1
    corr_slits = onslits.astype(float).flatten()

    # Compute
    mean_sci, med_sci, stddev_sci = stats.sigma_clipped_stats(_sciimg[onslits])
    thresh = med_sci + 5.0 * stddev_sci
    corr_sci = np.fmin(_sciimg.flatten(), thresh)

    lags, xcorr = utils.cross_correlate(corr_sci, corr_slits, maxlag)
    xcorr_denom = np.sqrt(
        np.sum(corr_sci * corr_sci) * np.sum(corr_slits * corr_slits))
    xcorr_norm = xcorr / xcorr_denom
    # TODO -- Generate a QA plot
    tampl_true, tampl, pix_max, twid, centerr, ww, arc_cont, nsig \
            = arc.detect_lines(xcorr_norm, sigdetect=3.0, fit_frac_fwhm=1.5, fwhm=5.0,
                               cont_frac_fwhm=1.0, cont_samp=30, nfind=1, debug=debug)
    # No peak? -- e.g. data fills the entire detector
    if len(tampl) == 0:
        msgs.warn(
            'No peak found in spatial flexure.  Assuming there is none..')
        if debug:
            embed(header='68 of flexure')
        return 0.

    # Find the peak
    xcorr_max = np.interp(pix_max, np.arange(lags.shape[0]), xcorr_norm)
    lag_max = np.interp(pix_max, np.arange(lags.shape[0]), lags)
    msgs.info('Spatial flexure measured: {}'.format(lag_max[0]))

    if debug:
        plt.figure(figsize=(14, 6))
        plt.plot(lags,
                 xcorr_norm,
                 color='black',
                 drawstyle='steps-mid',
                 lw=3,
                 label='x-corr',
                 linewidth=1.0)
        plt.plot(lag_max[0], xcorr_max[0], 'g+', markersize=6.0, label='peak')
        plt.title('Best shift = {:5.3f}'.format(lag_max[0]) +
                  ',  corr_max = {:5.3f}'.format(xcorr_max[0]))
        plt.legend()
        plt.show()

    #tslits_shift = trace_slits.shift_slits(tslits_dict, lag_max)
    # Now translate the tilts

    #slitmask_shift = pixels.tslits2mask(tslits_shift)
    #slitmask_shift = slits.slit_img(flexure=lag_max[0])
    if debug:
        # Now translate the slits in the tslits_dict
        all_left_flexure, all_right_flexure, mask = slits.select_edges(
            flexure=lag_max[0])
        gpm = mask == 0
        viewer, ch = display.show_image(_sciimg)
        #display.show_slits(viewer, ch, left_flexure[:,gpm], right_flexure)[:,gpm]#, slits.id) #, args.det)
        embed(header='83 of flexure.py')

    return lag_max[0]
예제 #10
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