示例#1
0
    def __init__(self,
                 speclist,
                 xtype='frequency',
                 xarr=None,
                 force=False,
                 **kwargs):

        if xarr is None:
            self.xarr = speclist[0].xarr
        else:
            self.xarr = xarr

        self.units = speclist[0].units
        self.header = speclist[0].header
        self.parse_header(self.header)

        for spec in speclist:
            if not isinstance(spec, Spectrum):
                raise TypeError(
                    "Must create an ObsBlock with a list of spectra.")
            if not np.array_equal(spec.xarr, self.xarr):
                if not force:
                    raise ValueError("Mismatch between X axes in ObsBlock")
            if spec.units != self.units:
                raise ValueError("Mismatched units")

        if force:
            self.speclist = [
                interpolation.interp(spec, self) for spec in speclist
            ]
        else:
            self.speclist = speclist
        self.nobs = len(self.speclist)

        # Create a 2-dimensional array of the data
        self.data = np.array([sp.data
                              for sp in self.speclist]).swapaxes(0,
                                                                 1).squeeze()
        self.error = np.array([sp.error
                               for sp in self.speclist]).swapaxes(0,
                                                                  1).squeeze()

        self.plotter = plotters.Plotter(self)
        self._register_fitters()
        self.specfit = fitters.Specfit(self, Registry=self.Registry)
        self.baseline = baseline.Baseline(self)
示例#2
0
    def __init__(self, speclist, xunits='GHz', **kwargs):
        print "Creating spectra"
        speclist = list(speclist)
        for ii, spec in enumerate(speclist):
            if type(spec) is str:
                spec = Spectrum(spec)
                speclist[ii] = spec

        self.speclist = speclist

        print "Concatenating data"
        self.xarr = units.SpectroscopicAxes(
            [sp.xarr.as_unit(xunits) for sp in speclist])
        self.xarr.units = xunits
        self.xarr.xtype = units.unit_type_dict[xunits]
        self.data = np.ma.concatenate([sp.data for sp in speclist])
        self.error = np.ma.concatenate([sp.error for sp in speclist])
        self._sort()

        self.header = pyfits.Header()
        for spec in speclist:
            for key, value in spec.header.items():
                try:
                    self.header[key] = value
                except (ValueError, KeyError):
                    warn("Could not update header KEY=%s to VALUE=%s" %
                         (key, value))

        self.plotter = plotters.Plotter(self)
        self._register_fitters()
        self.specfit = fitters.Specfit(self, Registry=self.Registry)
        self.baseline = baseline.Baseline(self)

        self.units = speclist[0].units
        for spec in speclist:
            if spec.units != self.units:
                raise ValueError("Mismatched units")

        # Special.  This needs to be modified to be more flexible; for now I need it to work for nh3
        self.plot_special = None
        self.plot_special_kwargs = {}
示例#3
0
    def __init__(self,
                 filename=None,
                 filetype=None,
                 xarr=None,
                 data=None,
                 error=None,
                 header=None,
                 doplot=False,
                 maskdata=True,
                 plotkwargs={},
                 xarrkwargs={},
                 **kwargs):
        """
        Create a Spectrum object.

        Must either pass in a filename or ALL of xarr, data, and header, plus
        optionally error.

        kwargs are passed to the file reader

        Parameters
        ----------
        filename : string
            The file to read the spectrum from.  If data, xarr, and error are
            specified, leave filename blank.
        filetype : string
            Specify the file type (only needed if it cannot be automatically
            determined from the filename)
        xarr : `units.SpectroscopicAxis` or `np.ndarray`
            The X-axis of the data.  If it is an np.ndarray, you must pass
            `xarrkwargs` or a valid header if you want to use any of the unit
            functionality.
        data : `np.ndarray`
            The data array (must have same length as xarr)
        error : `np.ndarray` 
            The error array (must have same length as the data and xarr arrays)
        header : `pyfits.Header` or dict
            The header from which to read unit information.  Needs to be a
            `pyfits.Header` instance or another dictionary-like object with the
            appropriate information
        maskdata : boolean
            turn the array into a masked array with all nan and inf values masked
        doplot : boolean
            Plot the spectrum after loading it?
        plotkwargs : dict
            keyword arguments to pass to the plotter
        xarrkwargs : dict
            keyword arguments to pass to the SpectroscopicAxis initialization
            (can be used in place of a header)

        Examples
        --------

        >>> sp = pyspeckit.Spectrum(data=np.random.randn(100),
                    xarr=np.linspace(-50, 50, 100), error=np.ones(100)*0.1, 
                    xarrkwargs={'unit':'km/s', 'refX':4.829, 'refX_units':'GHz',
                        'xtype':'VLSR-RAD'}, header={})

        >>> xarr = pyspeckit.units.SpectroscopicAxis(np.linspace(-50,50,100),
                    units='km/s', refX=6562.83, refX_units='angstroms')
        >>> data = np.random.randn(100)*5 + np.random.rand(100)*100
        >>> err = np.sqrt(data/5.)*5. # Poisson noise
        >>> sp = pyspeckit.Spectrum(data=data, error=err, xarr=xarr, header={}) 
        
        >>> # if you already have a simple fits file
        >>> sp = pyspeckit.Spectrum('test.fits')
        """

        if filename:
            if filetype is None:
                suffix = filename.rsplit('.', 1)[1]
                if suffix in readers.suffix_types:
                    # use the default reader for that suffix
                    filetype = readers.suffix_types[suffix][0]
                    reader = readers.readers[filetype]
                else:
                    raise TypeError("File with suffix %s is not recognized." %
                                    suffix)
            else:
                if filetype in readers.readers:
                    reader = readers.readers[filetype]
                else:
                    raise TypeError("Filetype %s not recognized" % filetype)

            self.data, self.error, self.xarr, self.header = reader(
                filename, **kwargs)

            # these should probably be replaced with registerable function s...
            if filetype in ('fits', 'tspec', 'pyfits', 'sdss'):
                self.parse_header(self.header)
            elif filetype is 'txt':
                self.parse_text_header(self.header)
            elif filetype in ('hdf5', 'h5'):
                self.parse_hdf5_header(self.header)

            if isinstance(filename, str):
                self.fileprefix = filename.rsplit(
                    '.', 1)[0]  # Everything prior to .fits or .txt
        elif xarr is not None and data is not None:
            # technically, this is unpythonic.  But I don't want to search for all 10 attributes required.
            if issubclass(type(xarr), units.SpectroscopicAxis):
                self.xarr = xarr
            else:
                self.xarr = units.SpectroscopicAxis(xarr, **xarrkwargs)
            self.data = data
            if error is not None:
                self.error = error
            else:
                self.error = data * 0
            if hasattr(header, 'get'):
                self.header = header
            else:  # set as blank
                warn("WARNING: Blank header.")
                self.header = pyfits.Header()
            self.parse_header(self.header)

        if maskdata:
            if hasattr(self.data, 'mask'):
                self.data.mask += np.isnan(self.data) + np.isinf(self.data)
                self.error.mask += np.isnan(self.data) + np.isinf(self.data)
            else:
                self.data = np.ma.masked_where(
                    np.isnan(self.data) + np.isinf(self.data), self.data)
                self.error = np.ma.masked_where(
                    np.isnan(self.data) + np.isinf(self.data), self.error)

        self.plotter = plotters.Plotter(self)
        self._register_fitters()
        self.specfit = fitters.Specfit(self, Registry=self.Registry)
        self.baseline = baseline.Baseline(self)
        self.speclines = speclines
        self._sort()

        # Special.  This needs to be modified to be more flexible; for now I need it to work for nh3
        self.plot_special = None
        self.plot_special_kwargs = {}

        if doplot: self.plotter(**plotkwargs)
示例#4
0
    def slice(self,
              start=None,
              stop=None,
              units='pixel',
              copy=True,
              preserve_fits=False):
        """Slicing the spectrum

        .. WARNING:: this is the same as cropping right now, but it returns a
            copy instead of cropping inplace
        
        Parameters
        ----------
        start : numpy.float or int
            start of slice
        stop :  numpy.float or int
            stop of slice
        units : str
            allowed values are any supported physical unit, 'pixel'
        copy : bool
            Return a 'view' of the data or a copy?
        preserve_fits : bool
            Save the fitted parameters from self.fitter?
        """

        if units in ('pixel', 'pixels'):
            start_ind = start
            stop_ind = stop
        else:
            x_in_units = self.xarr.as_unit(units)
            start_ind = x_in_units.x_to_pix(start)
            stop_ind = x_in_units.x_to_pix(stop)
        if start_ind > stop_ind: start_ind, stop_ind = stop_ind, start_ind
        spectrum_slice = slice(start_ind, stop_ind)

        if copy:
            sp = self.copy()
        else:
            sp = self
        sp.data = sp.data[spectrum_slice]
        if sp.error is not None:
            sp.error = sp.error[spectrum_slice]
        sp.xarr = sp.xarr[spectrum_slice]

        if copy:
            # create new specfit / baseline instances (otherwise they'll be the wrong length)
            sp._register_fitters()
            sp.baseline = baseline.Baseline(sp)
            sp.specfit = fitters.Specfit(sp, Registry=sp.Registry)
        else:
            # inplace modification
            sp.baseline.crop(start_ind, stop_ind)
            sp.specfit.crop(start_ind, stop_ind)

        if preserve_fits:
            sp.specfit.modelpars = self.specfit.modelpars
            sp.specfit.parinfo = self.specfit.parinfo
            sp.baseline.baselinepars = self.baseline.baselinepars
            sp.baseline.order = self.baseline.order

        return sp