Exemplo n.º 1
0
    def __init__(self, wave, calib, ivar, mask, meancalib=None):
        """Lightweight wrapper object for flux calibration vectors

        Args:
            wave : 1D[nwave] input wavelength (Angstroms)
            calib: 2D[nspec, nwave] calibration vectors for each spectrum
            ivar : 2D[nspec, nwave] inverse variance of calib
            mask : 2D[nspec, nwave] mask of calib (0=good)
            meancalib : 1D[nwave] mean convolved calibration (optional)

        All arguments become attributes, plus nspec,nwave = calib.shape

        The calib vector should be such that

            [1e-17 erg/s/cm^2/A] = [photons/A] / calib
        """
        assert wave.ndim == 1
        assert calib.ndim == 2
        assert calib.shape == ivar.shape
        assert calib.shape == mask.shape
        assert np.all(ivar >= 0)

        self.nspec, self.nwave = calib.shape
        self.wave = wave
        self.calib = calib
        self.ivar = ivar
        self.mask = util.mask32(mask)
        self.meancalib = meancalib
Exemplo n.º 2
0
    def __init__(self,
                 wave,
                 flux,
                 ivar,
                 mask,
                 header=None,
                 nrej=0,
                 stat_ivar=None):
        """Create SkyModel object

        Args:
            wave  : 1D[nwave] wavelength in Angstroms
            flux  : 2D[nspec, nwave] sky model to subtract
            ivar  : 2D[nspec, nwave] inverse variance of the sky model
            mask  : 2D[nspec, nwave] 0=ok or >0 if problems; 32-bit
            header : (optional) header from FITS file HDU0
            nrej : (optional) Number of rejected pixels in fit

        All input arguments become attributes
        """
        assert wave.ndim == 1
        assert flux.ndim == 2
        assert ivar.shape == flux.shape
        assert mask.shape == flux.shape

        self.nspec, self.nwave = flux.shape
        self.wave = wave
        self.flux = flux
        self.ivar = ivar
        self.mask = util.mask32(mask)
        self.header = header
        self.nrej = nrej
        self.stat_ivar = stat_ivar
Exemplo n.º 3
0
    def __init__(self, wave, calib, ivar, mask, meancalib=None):
        """Lightweight wrapper object for flux calibration vectors

        Args:
            wave : 1D[nwave] input wavelength (Angstroms)
            calib: 2D[nspec, nwave] calibration vectors for each spectrum
            ivar : 2D[nspec, nwave] inverse variance of calib
            mask : 2D[nspec, nwave] mask of calib (0=good)
            meancalib : 1D[nwave] mean convolved calibration (optional)

        All arguments become attributes, plus nspec,nwave = calib.shape

        The calib vector should be such that

            [1e-17 erg/s/cm^2/A] = [photons/A] / calib
        """
        assert wave.ndim == 1
        assert calib.ndim == 2
        assert calib.shape == ivar.shape
        assert calib.shape == mask.shape
        assert np.all(ivar >= 0)

        self.nspec, self.nwave = calib.shape
        self.wave = wave
        self.calib = calib
        self.ivar = ivar
        self.mask = util.mask32(mask)
        self.meancalib = meancalib

        self.meta = dict(units='photons/(erg/s/cm^2)')
Exemplo n.º 4
0
    def __init__(self, wave, flux, ivar, mask, header=None, nrej=0, stat_ivar=None):
        """Create SkyModel object

        Args:
            wave  : 1D[nwave] wavelength in Angstroms
            flux  : 2D[nspec, nwave] sky model to subtract
            ivar  : 2D[nspec, nwave] inverse variance of the sky model
            mask  : 2D[nspec, nwave] 0=ok or >0 if problems; 32-bit
            header : (optional) header from FITS file HDU0
            nrej : (optional) Number of rejected pixels in fit

        All input arguments become attributes
        """
        assert wave.ndim == 1
        assert flux.ndim == 2
        assert ivar.shape == flux.shape
        assert mask.shape == flux.shape

        self.nspec, self.nwave = flux.shape
        self.wave = wave
        self.flux = flux
        self.ivar = ivar
        self.mask = util.mask32(mask)
        self.header = header
        self.nrej = nrej
        self.stat_ivar = stat_ivar
Exemplo n.º 5
0
    def test_mask32(self):
        for dtype in (
                int,
                'int64',
                'uint64',
                'i8',
                'u8',
                'int32',
                'uint32',
                'i4',
                'u4',
                'int16',
                'uint16',
                'i2',
                'u2',
                'int8',
                'uint8',
                'i1',
                'u1',
        ):
            x = np.ones(10, dtype=np.dtype(dtype))
            m32 = util.mask32(x)
            self.assertTrue(np.all(m32 == 1))

        x = util.mask32(np.array([-1, 0, 1], dtype='i4'))
        self.assertEqual(x[0], 2**32 - 1)
        self.assertEqual(x[1], 0)
        self.assertEqual(x[2], 1)

        with self.assertRaises(ValueError):
            util.mask32(np.arange(2**35, 2**35 + 5))

        with self.assertRaises(ValueError):
            util.mask32(np.arange(-2**35, -2**35 + 5))
Exemplo n.º 6
0
    def __init__(self,
                 pix,
                 ivar,
                 mask=None,
                 readnoise=0.0,
                 camera='unknown',
                 meta=None):
        """
        Create Image object
        
        Args:
            pix : 2D numpy.ndarray of image pixels
            
        Optional:
            ivar : inverse variance of pix, same shape as pix
            mask : 0 is good, non-0 is bad; default is (ivar==0)
            readnoise : CCD readout noise in electrons/pixel (float)
            camera : e.g. 'b0', 'r1', 'z9'
            meta : dict-like metadata key/values, e.g. from FITS header
        """
        if pix.ndim != 2:
            raise ValueError('pix must be 2D, not {}D'.format(pix.ndim))
        if pix.shape != ivar.shape:
            raise ValueError('pix.shape{} != ivar.shape{}'.format(
                pix.shape, ivar.shape))
        if (mask is not None) and (pix.shape != mask.shape):
            raise ValueError('pix.shape{} != mask.shape{}'.format(
                pix.shape, mask.shape))

        self.pix = pix
        self.ivar = ivar
        self.meta = meta
        if mask is not None:
            self.mask = util.mask32(mask)
        else:
            self.mask = np.zeros(self.ivar.shape, dtype=np.uint32)
            self.mask[self.ivar == 0] |= ccdmask.BAD

        #- Optional parameters
        self.readnoise = readnoise
        self.camera = camera
Exemplo n.º 7
0
    def test_mask32(self):
        for dtype in (
            int, 'int64', 'uint64', 'i8', 'u8',
            'int32', 'uint32', 'i4', 'u4',
            'int16', 'uint16', 'i2', 'u2',
            'int8', 'uint8', 'i1', 'u1',
            ):
            x = np.ones(10, dtype=np.dtype(dtype))
            m32 = util.mask32(x)                
            self.assertTrue(np.all(m32 == 1))
            
        x = util.mask32( np.array([-1,0,1], dtype='i4') )
        self.assertEqual(x[0], 2**32-1)
        self.assertEqual(x[1], 0)
        self.assertEqual(x[2], 1)
        
        with self.assertRaises(ValueError):
            util.mask32(np.arange(2**35, 2**35+5))

        with self.assertRaises(ValueError):
            util.mask32(np.arange(-2**35, -2**35+5))
Exemplo n.º 8
0
    def __init__(self,
                 wave,
                 flux,
                 ivar,
                 mask=None,
                 resolution_data=None,
                 fibers=None,
                 spectrograph=None,
                 meta=None,
                 fibermap=None,
                 chi2pix=None,
                 scores=None,
                 scores_comments=None,
                 wsigma=None,
                 ndiag=21,
                 suppress_res_warning=False):
        """
        Lightweight wrapper for multiple spectra on a common wavelength grid

        x.wave, x.flux, x.ivar, x.mask, x.resolution_data, x.header, sp.R

        Args:
            wave: 1D[nwave] wavelength in Angstroms
            flux: 2D[nspec, nwave] flux
            ivar: 2D[nspec, nwave] inverse variance of flux

        Optional:
            mask: 2D[nspec, nwave] integer bitmask of flux.  0=good.
            resolution_data: 3D[nspec, ndiag, nwave]
                             diagonals of resolution matrix data
            fibers: ndarray of which fibers these spectra are
            spectrograph: integer, which spectrograph [0-9]
            meta: dict-like object (e.g. FITS header)
            fibermap: fibermap table
            chi2pix: 2D[nspec, nwave] chi2 of 2D model to pixel-level data
                for pixels that contributed to each flux bin
            scores: dictionnary of 1D arrays of size nspec
            scores_comments: dictionnary of string (explaining the scores)
            suppress_res_warning: bool to suppress Warning message when the Resolution image is not read
        
        Parameters below allow on-the-fly resolution calculation
            wsigma: 2D[nspec,nwave] sigma widths for each wavelength bin for all fibers
        Notes:
            spectrograph input is used only if fibers is None.  In this case,
            it assumes nspec_per_spectrograph = flux.shape[0] and calculates
            the fibers array for this spectrograph, i.e.
            fibers = spectrograph * flux.shape[0] + np.arange(flux.shape[0])

        Attributes:
            All input args become object attributes.
            nspec : number of spectra, flux.shape[0]
            nwave : number of wavelengths, flux.shape[1]
            specmin : minimum fiber number
            R: array of sparse Resolution matrix objects converted
               from resolution_data
            fibermap: fibermap table if provided
        """
        assert wave.ndim == 1
        assert flux.ndim == 2
        assert wave.shape[0] == flux.shape[1]
        assert ivar.shape == flux.shape
        assert (mask is None) or mask.shape == flux.shape
        assert (mask is None) or mask.dtype in \
            (int, np.int64, np.int32, np.uint64, np.uint32), "Bad mask type "+str(mask.dtype)

        self.wave = wave
        self.flux = flux
        self.ivar = ivar
        self.meta = meta
        self.fibermap = fibermap
        self.nspec, self.nwave = self.flux.shape
        self.chi2pix = chi2pix
        self.scores = scores
        self.scores_comments = scores_comments
        self.ndiag = ndiag
        fibers_per_spectrograph = 500  #- hardcode; could get from desimodel

        if mask is None:
            self.mask = np.zeros(flux.shape, dtype=np.uint32)
        else:
            self.mask = util.mask32(mask)

        if resolution_data is not None:
            if resolution_data.ndim != 3 or \
               resolution_data.shape[0] != self.nspec or \
               resolution_data.shape[2] != self.nwave:
                raise ValueError(
                    "Wrong dimensions for resolution_data[nspec, ndiag, nwave]"
                )

        #- Maybe setup non-None identity matrix resolution matrix instead?
        self.wsigma = wsigma
        self.resolution_data = resolution_data
        if resolution_data is not None:
            self.wsigma = None  #ignore width coefficients if resolution data is given explicitly
            self.ndiag = None
            self.R = np.array([Resolution(r) for r in resolution_data])
        elif wsigma is not None:
            from desispec.quicklook.qlresolution import QuickResolution
            assert ndiag is not None
            r = []
            for sigma in wsigma:
                r.append(QuickResolution(sigma=sigma, ndiag=self.ndiag))
            self.R = np.array(r)
        else:
            #SK I believe this should be error, but looking at the
            #tests frame objects are allowed to not to have resolution data
            # thus I changed value error to a simple warning message.
            if not suppress_res_warning:
                log = get_logger()
                log.warning("Frame object is constructed without resolution data or respective "\
                        "sigma widths. Resolution will not be available")
            # raise ValueError("Need either resolution_data or coefficients to generate it")
        self.spectrograph = spectrograph

        # Deal with Fibers (these must be set!)
        if fibers is not None:
            fibers = np.asarray(fibers)
            if len(fibers) != self.nspec:
                raise ValueError("len(fibers) != nspec ({} != {})".format(
                    len(fibers), self.nspec))
            if fibermap is not None and np.any(fibers != fibermap['FIBER']):
                raise ValueError("fibermap doesn't match fibers")
            if (spectrograph is not None):
                minfiber = spectrograph * fibers_per_spectrograph
                maxfiber = (spectrograph + 1) * fibers_per_spectrograph
                if np.any(fibers < minfiber) or np.any(maxfiber <= fibers):
                    raise ValueError('fibers inconsistent with spectrograph')
            self.fibers = fibers
        else:
            if fibermap is not None:
                self.fibers = fibermap['FIBER']
            elif spectrograph is not None:
                self.fibers = spectrograph * fibers_per_spectrograph + np.arange(
                    self.nspec, dtype=int)
            elif (self.meta is not None) and ('FIBERMIN' in self.meta):
                self.fibers = self.meta['FIBERMIN'] + np.arange(self.nspec,
                                                                dtype=int)
            else:
                raise ValueError("Must set fibers by one of the methods!")

        if self.meta is not None:
            self.meta['FIBERMIN'] = np.min(self.fibers)
Exemplo n.º 9
0
    def __init__(self,
                 wave,
                 flux,
                 ivar,
                 mask=None,
                 resolution_data=None,
                 fibers=None,
                 spectrograph=None,
                 meta=None,
                 fibermap=None,
                 chi2pix=None):
        """
        Lightweight wrapper for multiple spectra on a common wavelength grid

        x.wave, x.flux, x.ivar, x.mask, x.resolution_data, x.header, sp.R
        
        Args:
            wave: 1D[nwave] wavelength in Angstroms
            flux: 2D[nspec, nwave] flux
            ivar: 2D[nspec, nwave] inverse variance of flux

        Optional:
            mask: 2D[nspec, nwave] integer bitmask of flux.  0=good.
            resolution_data: 3D[nspec, ndiag, nwave]
                             diagonals of resolution matrix data
            fibers: ndarray of which fibers these spectra are
            spectrograph: integer, which spectrograph [0-9]
            meta: dict-like object (e.g. FITS header)
            fibermap: fibermap table
            chi2pix: 2D[nspec, nwave] chi2 of 2D model to pixel-level data
                for pixels that contributed to each flux bin

        Notes:
            spectrograph input is used only if fibers is None.  In this case,
            it assumes nspec_per_spectrograph = flux.shape[0] and calculates
            the fibers array for this spectrograph, i.e.
            fibers = spectrograph * flux.shape[0] + np.arange(flux.shape[0])

        Attributes:
            All input args become object attributes.
            nspec : number of spectra, flux.shape[0]
            nwave : number of wavelengths, flux.shape[1]
            specmin : minimum fiber number
            R: array of sparse Resolution matrix objects converted
               from resolution_data
            fibermap: fibermap table if provided
        """
        assert wave.ndim == 1
        assert flux.ndim == 2
        assert wave.shape[0] == flux.shape[1]
        assert ivar.shape == flux.shape
        assert (mask is None) or mask.shape == flux.shape
        assert (mask is None) or mask.dtype in \
            (int, np.int64, np.int32, np.uint64, np.uint32), "Bad mask type "+str(mask.dtype)

        self.wave = wave
        self.flux = flux
        self.ivar = ivar
        self.meta = meta
        self.fibermap = fibermap
        self.nspec, self.nwave = self.flux.shape
        self.chi2pix = chi2pix

        fibers_per_spectrograph = 500  #- hardcode; could get from desimodel

        if mask is None:
            self.mask = np.zeros(flux.shape, dtype=np.uint32)
        else:
            self.mask = util.mask32(mask)

        if resolution_data is not None:
            if resolution_data.ndim != 3 or \
               resolution_data.shape[0] != self.nspec or \
               resolution_data.shape[2] != self.nwave:
                raise ValueError(
                    "Wrong dimensions for resolution_data[nspec, ndiag, nwave]"
                )

        #- Maybe setup non-None identity matrix resolution matrix instead?
        self.resolution_data = resolution_data
        if resolution_data is not None:
            self.R = np.array([Resolution(r) for r in resolution_data])

        self.spectrograph = spectrograph

        # Deal with Fibers (these must be set!)
        if fibers is not None:
            fibers = np.asarray(fibers)
            if len(fibers) != self.nspec:
                raise ValueError("len(fibers) != nspec ({} != {})".format(
                    len(fibers), self.nspec))
            if fibermap is not None and np.any(fibers != fibermap['FIBER']):
                raise ValueError("fibermap doesn't match fibers")
            if (spectrograph is not None):
                minfiber = spectrograph * fibers_per_spectrograph
                maxfiber = (spectrograph + 1) * fibers_per_spectrograph
                if np.any(fibers < minfiber) or np.any(maxfiber <= fibers):
                    raise ValueError('fibers inconsistent with spectrograph')
            self.fibers = fibers
        else:
            if fibermap is not None:
                self.fibers = fibermap['FIBER']
            elif spectrograph is not None:
                self.fibers = spectrograph * fibers_per_spectrograph + np.arange(
                    self.nspec, dtype=int)
            elif (self.meta is not None) and ('FIBERMIN' in self.meta):
                self.fibers = self.meta['FIBERMIN'] + np.arange(self.nspec,
                                                                dtype=int)
            else:
                raise ValueError("Must set fibers by one of the methods!")

        if self.meta is not None:
            self.meta['FIBERMIN'] = np.min(self.fibers)
Exemplo n.º 10
0
    def __init__(self,
                 wave,
                 fiberflat,
                 ivar,
                 mask=None,
                 meanspec=None,
                 chi2pdf=None,
                 header=None,
                 fibers=None,
                 spectrograph=0):
        """
        Creates a lightweight data wrapper for fiber flats

        Args:
            wave: 1D[nwave] wavelength in Angstroms
            fiberflat: 2D[nspec, nwave]
            ivar: 2D[nspec, nwave] inverse variance of fiberflat

        Optional inputs:
            mask: 2D[nspec, nwave] mask where 0=good; default ivar==0; 32-bit
            meanspec: (optional) 1D[nwave] mean deconvolved average flat lamp spectrum
            chi2pdf: (optional) Normalized chi^2 for fit to mean spectrum
            header: (optional) FITS header from HDU0
            fibers: (optional) fiber indices
            spectrograph: (optional) spectrograph number [0-9]
        """
        if wave.ndim != 1:
            raise ValueError("wave should be 1D")

        if fiberflat.ndim != 2:
            raise ValueError("fiberflat should be 2D[nspec, nwave]")

        if ivar.ndim != 2:
            raise ValueError("ivar should be 2D")

        if fiberflat.shape != ivar.shape:
            raise ValueError("fiberflat and ivar must have the same shape")

        if mask is not None and mask.ndim != 2:
            raise ValueError("mask should be 2D")

        if meanspec is not None and meanspec.ndim != 1:
            raise ValueError("meanspec should be 1D")

        if mask is not None and fiberflat.shape != mask.shape:
            raise ValueError("fiberflat and mask must have the same shape")

        if meanspec is not None and wave.shape != meanspec.shape:
            raise ValueError("wrong size/shape for meanspec {}".format(
                meanspec.shape))

        if wave.shape[0] != fiberflat.shape[1]:
            raise ValueError(
                "nwave mismatch between wave.shape[0] and flux.shape[1]")

        if mask is None:
            mask = (ivar == 0)

        if meanspec is None:
            meanspec = np.ones_like(wave)

        self.wave = wave
        self.fiberflat = fiberflat
        self.ivar = ivar
        self.mask = util.mask32(mask)
        self.meanspec = meanspec

        self.nspec, self.nwave = self.fiberflat.shape
        self.header = header

        if chi2pdf is not None:
            self.chi2pdf = chi2pdf
        else:
            try:
                self.chi2pdf = header['chi2pdf']
            except (KeyError, TypeError):
                self.chi2pdf = None

        self.spectrograph = spectrograph
        if fibers is None:
            self.fibers = self.spectrograph + np.arange(self.nspec, dtype=int)
        else:
            if len(fibers) != self.nspec:
                raise ValueError("len(fibers) != nspec ({} != {})".format(
                    len(fibers), self.nspec))
            self.fibers = fibers
Exemplo n.º 11
0
    def __init__(self, wave, fiberflat, ivar, mask=None, meanspec=None,
            chi2pdf=None, header=None, fibers=None, spectrograph=0):
        """
        Creates a lightweight data wrapper for fiber flats

        Args:
            wave: 1D[nwave] wavelength in Angstroms
            fiberflat: 2D[nspec, nwave]
            ivar: 2D[nspec, nwave] inverse variance of fiberflat

        Optional inputs:
            mask: 2D[nspec, nwave] mask where 0=good; default ivar==0; 32-bit
            meanspec: (optional) 1D[nwave] mean deconvolved average flat lamp spectrum
            chi2pdf: (optional) Normalized chi^2 for fit to mean spectrum
            header: (optional) FITS header from HDU0
            fibers: (optional) fiber indices
            spectrograph: (optional) spectrograph number [0-9]
        """
        if wave.ndim != 1:
            raise ValueError("wave should be 1D")

        if fiberflat.ndim != 2:
            raise ValueError("fiberflat should be 2D[nspec, nwave]")

        if ivar.ndim != 2:
            raise ValueError("ivar should be 2D")

        if fiberflat.shape != ivar.shape:
            raise ValueError("fiberflat and ivar must have the same shape")

        if mask is not None and mask.ndim != 2:
            raise ValueError("mask should be 2D")

        if meanspec is not None and meanspec.ndim != 1:
            raise ValueError("meanspec should be 1D")

        if mask is not None and fiberflat.shape != mask.shape:
            raise ValueError("fiberflat and mask must have the same shape")

        if meanspec is not None and wave.shape != meanspec.shape:
            raise ValueError("wrong size/shape for meanspec {}".format(meanspec.shape))

        if wave.shape[0] != fiberflat.shape[1]:
            raise ValueError("nwave mismatch between wave.shape[0] and flux.shape[1]")

        if mask is None:
            mask = (ivar == 0)

        if meanspec is None:
            meanspec = np.ones_like(wave)

        self.wave = wave
        self.fiberflat = fiberflat
        self.ivar = ivar
        self.mask = util.mask32(mask)
        self.meanspec = meanspec

        self.nspec, self.nwave = self.fiberflat.shape
        self.header = header

        if chi2pdf is not None:
            self.chi2pdf = chi2pdf
        else:
            try:
                self.chi2pdf = header['chi2pdf']
            except (KeyError, TypeError):
                self.chi2pdf = None

        self.spectrograph = spectrograph
        if fibers is None:
            self.fibers = self.spectrograph + np.arange(self.nspec, dtype=int)
        else:
            if len(fibers) != self.nspec:
                raise ValueError("len(fibers) != nspec ({} != {})".format(len(fibers), self.nspec))
            self.fibers = fibers
Exemplo n.º 12
0
    def __init__(self, wave, flux, ivar, mask=None, resolution_data=None,
                fibers=None, spectrograph=None, meta=None, fibermap=None):
        """
        Lightweight wrapper for multiple spectra on a common wavelength grid

        x.wave, x.flux, x.ivar, x.mask, x.resolution_data, x.header, sp.R
        
        Args:
            wave: 1D[nwave] wavelength in Angstroms
            flux: 2D[nspec, nwave] flux
            ivar: 2D[nspec, nwave] inverse variance of flux

        Optional:
            mask: 2D[nspec, nwave] integer bitmask of flux.  0=good.
            resolution_data: 3D[nspec, ndiag, nwave]
                             diagonals of resolution matrix data
            fibers: ndarray of which fibers these spectra are
            spectrograph: integer, which spectrograph [0-9]
            meta: dict-like object (e.g. FITS header)
            fibermap: fibermap table

        Notes:
            spectrograph input is used only if fibers is None.  In this case,
            it assumes nspec_per_spectrograph = flux.shape[0] and calculates
            the fibers array for this spectrograph, i.e.
            fibers = spectrograph * flux.shape[0] + np.arange(flux.shape[0])

        Attributes:
            All input args become object attributes.
            nspec : number of spectra, flux.shape[0]
            nwave : number of wavelengths, flux.shape[1]
            specmin : minimum fiber number
            R: array of sparse Resolution matrix objects converted
               from resolution_data
            fibermap: fibermap table if provided
        """
        assert wave.ndim == 1
        assert flux.ndim == 2
        assert wave.shape[0] == flux.shape[1]
        assert ivar.shape == flux.shape
        assert (mask is None) or mask.shape == flux.shape
        assert (mask is None) or mask.dtype in \
            (int, np.int64, np.int32, np.uint64, np.uint32), "Bad mask type "+str(mask.dtype)

        self.wave = wave
        self.flux = flux
        self.ivar = ivar
        self.meta = meta
        self.fibermap = fibermap
        self.nspec, self.nwave = self.flux.shape
        
        fibers_per_spectrograph = 500   #- hardcode; could get from desimodel
        
        if mask is None:
            self.mask = np.zeros(flux.shape, dtype=np.uint32)
        else:
            self.mask = util.mask32(mask)

        if resolution_data is not None:
            if resolution_data.ndim != 3 or \
               resolution_data.shape[0] != self.nspec or \
               resolution_data.shape[2] != self.nwave:
               raise ValueError("Wrong dimensions for resolution_data[nspec, ndiag, nwave]")

        #- Maybe setup non-None identity matrix resolution matrix instead?
        self.resolution_data = resolution_data
        if resolution_data is not None:
            self.R = np.array( [Resolution(r) for r in resolution_data] )

        self.spectrograph = spectrograph

        # Deal with Fibers (these must be set!)
        if fibers is not None:
            fibers = np.asarray(fibers)
            if len(fibers) != self.nspec:
                raise ValueError("len(fibers) != nspec ({} != {})".format(len(fibers), self.nspec))
            if fibermap is not None and np.any(fibers != fibermap['FIBER']):
                raise ValueError("fibermap doesn't match fibers")
            if (spectrograph is not None):
                minfiber = spectrograph*fibers_per_spectrograph
                maxfiber = (spectrograph+1)*fibers_per_spectrograph
                if np.any(fibers < minfiber) or np.any(maxfiber <= fibers):
                    raise ValueError('fibers inconsistent with spectrograph')
            self.fibers = fibers
        else:
            if fibermap is not None:
                self.fibers = fibermap['FIBER']
            elif spectrograph is not None:
                self.fibers = spectrograph*fibers_per_spectrograph + np.arange(self.nspec, dtype=int)
            elif (self.meta is not None) and ('FIBERMIN' in self.meta.keys()):
                self.fibers = self.meta['FIBERMIN'] + np.arange(self.nspec, dtype=int)
            else:
                raise ValueError("Must set fibers by one of the methods!")

        if self.meta is not None:
            self.meta['FIBERMIN'] = np.min(self.fibers)
Exemplo n.º 13
0
    def __init__(self, wave, flux, ivar, mask=None, resolution_data=None,
                fibers=None, spectrograph=None, meta=None, fibermap=None,
                 chi2pix=None,scores=None,scores_comments=None,
                 wsigma=None,ndiag=21, suppress_res_warning=False
    ):
        """
        Lightweight wrapper for multiple spectra on a common wavelength grid

        x.wave, x.flux, x.ivar, x.mask, x.resolution_data, x.header, sp.R

        Args:
            wave: 1D[nwave] wavelength in Angstroms
            flux: 2D[nspec, nwave] flux
            ivar: 2D[nspec, nwave] inverse variance of flux

        Optional:
            mask: 2D[nspec, nwave] integer bitmask of flux.  0=good.
            resolution_data: 3D[nspec, ndiag, nwave]
                             diagonals of resolution matrix data
            fibers: ndarray of which fibers these spectra are
            spectrograph: integer, which spectrograph [0-9]
            meta: dict-like object (e.g. FITS header)
            fibermap: fibermap table
            chi2pix: 2D[nspec, nwave] chi2 of 2D model to pixel-level data
                for pixels that contributed to each flux bin
            scores: dictionnary of 1D arrays of size nspec
            scores_comments: dictionnary of string (explaining the scores)
            suppress_res_warning: bool to suppress Warning message when the Resolution image is not read
        
        Parameters below allow on-the-fly resolution calculation
            wsigma: 2D[nspec,nwave] sigma widths for each wavelength bin for all fibers
        Notes:
            spectrograph input is used only if fibers is None.  In this case,
            it assumes nspec_per_spectrograph = flux.shape[0] and calculates
            the fibers array for this spectrograph, i.e.
            fibers = spectrograph * flux.shape[0] + np.arange(flux.shape[0])

        Attributes:
            All input args become object attributes.
            nspec : number of spectra, flux.shape[0]
            nwave : number of wavelengths, flux.shape[1]
            specmin : minimum fiber number
            R: array of sparse Resolution matrix objects converted
               from resolution_data
            fibermap: fibermap table if provided
        """
        assert wave.ndim == 1
        assert flux.ndim == 2
        assert wave.shape[0] == flux.shape[1]
        assert ivar.shape == flux.shape
        assert (mask is None) or mask.shape == flux.shape
        assert (mask is None) or mask.dtype in \
            (int, np.int64, np.int32, np.uint64, np.uint32), "Bad mask type "+str(mask.dtype)

        self.wave = wave
        self.flux = flux
        self.ivar = ivar
        self.meta = meta
        self.fibermap = fibermap
        self.nspec, self.nwave = self.flux.shape
        self.chi2pix = chi2pix
        self.scores  = scores
        self.scores_comments  = scores_comments
        self.ndiag=ndiag
        fibers_per_spectrograph = 500   #- hardcode; could get from desimodel

        if mask is None:
            self.mask = np.zeros(flux.shape, dtype=np.uint32)
        else:
            self.mask = util.mask32(mask)

        if resolution_data is not None:
            if resolution_data.ndim != 3 or \
               resolution_data.shape[0] != self.nspec or \
               resolution_data.shape[2] != self.nwave:
               raise ValueError("Wrong dimensions for resolution_data[nspec, ndiag, nwave]")

        #- Maybe setup non-None identity matrix resolution matrix instead?
        self.wsigma=wsigma
        self.resolution_data = resolution_data
        if resolution_data is not None:
            self.wsigma=None #ignore width coefficients if resolution data is given explicitly
            self.ndiag=None 
            self.R = np.array( [Resolution(r) for r in resolution_data] )
        elif wsigma is not None:
            from desispec.quicklook.qlresolution import QuickResolution
            assert ndiag is not None
            r=[]
            for sigma in wsigma:
                r.append(QuickResolution(sigma=sigma,ndiag=self.ndiag))
            self.R=np.array(r)
        else:
            #SK I believe this should be error, but looking at the
            #tests frame objects are allowed to not to have resolution data
            # thus I changed value error to a simple warning message.
            if not suppress_res_warning:
                log = get_logger()
                log.warning("Frame object is constructed without resolution data or respective "\
                        "sigma widths. Resolution will not be available")
            # raise ValueError("Need either resolution_data or coefficients to generate it")
        self.spectrograph = spectrograph

        # Deal with Fibers (these must be set!)
        if fibers is not None:
            fibers = np.asarray(fibers)
            if len(fibers) != self.nspec:
                raise ValueError("len(fibers) != nspec ({} != {})".format(len(fibers), self.nspec))
            if fibermap is not None and np.any(fibers != fibermap['FIBER']):
                raise ValueError("fibermap doesn't match fibers")
            if (spectrograph is not None):
                minfiber = spectrograph*fibers_per_spectrograph
                maxfiber = (spectrograph+1)*fibers_per_spectrograph
                if np.any(fibers < minfiber) or np.any(maxfiber <= fibers):
                    raise ValueError('fibers inconsistent with spectrograph')
            self.fibers = fibers
        else:
            if fibermap is not None:
                self.fibers = fibermap['FIBER']
            elif spectrograph is not None:
                self.fibers = spectrograph*fibers_per_spectrograph + np.arange(self.nspec, dtype=int)
            elif (self.meta is not None) and ('FIBERMIN' in self.meta):
                self.fibers = self.meta['FIBERMIN'] + np.arange(self.nspec, dtype=int)
            else:
                raise ValueError("Must set fibers by one of the methods!")

        if self.meta is not None:
            self.meta['FIBERMIN'] = np.min(self.fibers)
Exemplo n.º 14
0
    def __init__(
        self,
        wave,
        flux,
        ivar,
        mask=None,
        sigma=None,
        fibers=None,
        spectrograph=None,
        meta=None,
        fibermap=None,
    ):
        """
        Lightweight wrapper for multiple spectra 

        Args:
            wave: 2D[nspec, nwave] wavelength in Angstroms
            flux: 2D[nspec, nwave] flux
            ivar: 2D[nspec, nwave] inverse variance of flux

        Optional:
            mask: 2D[nspec, nwave] integer bitmask of flux.  0=good.
            sigma: 2D[nspec, nwave] LSF sigma in pixel units
            fibers: ndarray of which fibers these spectra are
            spectrograph: integer, which spectrograph [0-9]
            meta: dict-like object (e.g. FITS header)
            fibermap: fibermap table
            
        Attributes:
            All input args become object attributes.
            nspec : number of spectra, flux.shape[0]
            nwave : number of wavelengths, flux.shape[1]
            specmin : minimum fiber number
            R: array of sparse Resolution matrix objects converted
               from resolution_data
            fibermap: fibermap table if provided
        """
        assert wave.ndim == 2
        assert flux.ndim == 2
        assert wave.shape == flux.shape
        assert ivar.shape == flux.shape
        assert (mask is None) or mask.shape == flux.shape
        assert (mask is None) or mask.dtype in \
            (int, np.int64, np.int32, np.uint64, np.uint32), "Bad mask type "+str(mask.dtype)
        assert (sigma is None) or sigma.shape == flux.shape

        self.wave = wave
        self.flux = flux
        self.ivar = ivar
        self.meta = meta
        self.fibermap = fibermap
        if mask is None:
            self.mask = np.zeros(flux.shape, dtype=np.uint32)
        else:
            self.mask = util.mask32(mask)
        self.sigma = sigma

        self.nspec = self.flux.shape[0]

        self.spectrograph = spectrograph

        # Deal with Fibers (these must be set!)
        fibers_per_spectrograph = 500  #- hardcode; could get from desimodel
        if fibers is not None:
            fibers = np.asarray(fibers)
            if len(fibers) != self.flux.shape[0]:
                raise ValueError(
                    "len(fibers) != flux.shape[0] ({} != {})".format(
                        len(fibers), flux.shape[0]))
            if fibermap is not None and np.any(fibers != fibermap['FIBER']):
                raise ValueError("fibermap doesn't match fibers")
            if (spectrograph is not None):
                minfiber = spectrograph * fibers_per_spectrograph
                maxfiber = (spectrograph + 1) * fibers_per_spectrograph
                if np.any(fibers < minfiber) or np.any(maxfiber <= fibers):
                    raise ValueError('fibers inconsistent with spectrograph')
            self.fibers = fibers
        else:
            if fibermap is not None:
                self.fibers = np.asarray(fibermap['FIBER'])
            elif spectrograph is not None:
                self.fibers = spectrograph * fibers_per_spectrograph + np.arange(
                    self.nspec, dtype=int)
            elif (self.meta is not None) and ('FIBERMIN' in self.meta):
                self.fibers = self.meta['FIBERMIN'] + np.arange(self.nspec,
                                                                dtype=int)
            else:
                self.fibers = np.arange(self.flux.shape[0])

        if self.meta is not None:
            self.meta['FIBERMIN'] = np.min(self.fibers)
Exemplo n.º 15
0
    def __init__(self, wave, flux, ivar, mask=None, sigma=None,
                fibers=None, spectrograph=None, meta=None, fibermap=None,
    ):
        """
        Lightweight wrapper for multiple spectra 

        Args:
            wave: 2D[nspec, nwave] wavelength in Angstroms
            flux: 2D[nspec, nwave] flux
            ivar: 2D[nspec, nwave] inverse variance of flux

        Optional:
            mask: 2D[nspec, nwave] integer bitmask of flux.  0=good.
            sigma: 2D[nspec, nwave] LSF sigma in pixel units
            fibers: ndarray of which fibers these spectra are
            spectrograph: integer, which spectrograph [0-9]
            meta: dict-like object (e.g. FITS header)
            fibermap: fibermap table
            
        Attributes:
            All input args become object attributes.
            nspec : number of spectra, flux.shape[0]
            nwave : number of wavelengths, flux.shape[1]
            specmin : minimum fiber number
            R: array of sparse Resolution matrix objects converted
               from resolution_data
            fibermap: fibermap table if provided
        """
        assert wave.ndim == 2
        assert flux.ndim == 2
        assert wave.shape == flux.shape
        assert ivar.shape == flux.shape
        assert (mask is None) or mask.shape == flux.shape
        assert (mask is None) or mask.dtype in \
            (int, np.int64, np.int32, np.uint64, np.uint32), "Bad mask type "+str(mask.dtype)
        assert (sigma is None) or sigma.shape == flux.shape
        
        self.wave = wave
        self.flux = flux
        self.ivar = ivar
        self.meta = meta
        self.fibermap = fibermap
        if mask is None:
            self.mask = np.zeros(flux.shape, dtype=np.uint32)
        else:
            self.mask = util.mask32(mask)
        self.sigma = sigma
        
        self.nspec = self.flux.shape[0]
            
        self.spectrograph = spectrograph
        
        # Deal with Fibers (these must be set!)
        fibers_per_spectrograph = 500   #- hardcode; could get from desimodel
        if fibers is not None:
            fibers = np.asarray(fibers)
            if len(fibers) != self.flux.shape[0]:
                raise ValueError("len(fibers) != flux.shape[0] ({} != {})".format(len(fibers), flux.shape[0]))
            if fibermap is not None and np.any(fibers != fibermap['FIBER']):
                raise ValueError("fibermap doesn't match fibers")
            if (spectrograph is not None):
                minfiber = spectrograph*fibers_per_spectrograph
                maxfiber = (spectrograph+1)*fibers_per_spectrograph
                if np.any(fibers < minfiber) or np.any(maxfiber <= fibers):
                    raise ValueError('fibers inconsistent with spectrograph')
            self.fibers = fibers
        else:
            if fibermap is not None:
                self.fibers = np.asarray(fibermap['FIBER'])
            elif spectrograph is not None:
                self.fibers = spectrograph*fibers_per_spectrograph + np.arange(self.nspec, dtype=int)
            elif (self.meta is not None) and ('FIBERMIN' in self.meta):
                self.fibers = self.meta['FIBERMIN'] + np.arange(self.nspec, dtype=int)
            else:
                self.fibers = np.arange(self.flux.shape[0])

        if self.meta is not None:
            self.meta['FIBERMIN'] = np.min(self.fibers)