Source code for crikit.data.spectra

"""
Spectra class and function (very similar to Spetcrum except this deals with
multiple entries)

"""

import numpy as _np
import copy as _copy

from crikit.data.frequency import Frequency as _Frequency
from crikit.data.spectrum import Spectrum as _Spectrum
from crikit.data.replicate import Replicate as _Replicate

__all__ = ['Spectra']

[docs]class Spectra(_Spectrum): """ Spectra class Attributes ---------- data : 2D ndarray [n_pix, f_pix] Spectra. Note: input can be a ndarray of any dimension: it will be \ CONVERTED to [n_pix, f_pix] shape, assuming that shape[-1] is the f_pix \ long. freq : crikit.data.frequency.Frequency instance Frequency [wavelength, wavenumber] object (i.e., the independent \ variable) label : str Spectrum label (i.e., a string describing what the spectrum is) units : str Units of spectrum reps : crikit.data.replicate.Replicate instance, Not implemented yet Object describing the meaning of multiple spectra (i.e., the physical \ meaning of n_pix). meta : dict Meta-data dictionary shape : tuple, read-only Shape of data n_pix : int, read-only Size of data's replicate/spectral number axis. Methods ------- mean : 1D ndarray Mean spectrum. If extent [a,b] is provided, calculate mean over that\ inclusive region. std : 1D ndarray Standard deviation of spectrum. If extent [a,b] is provided, calculate standard\ deviation over that inclusive region. subtract : 2D ndarray or None Subtract spectrum or object Notes ----- * freq object contains some useful parameters such as op_range* and \ plot_range*, which define spectral regions-of-interest. (It's debatable \ as to whether those parameters should be in Frequency or Spectrum classes) """ # Configurations config = {} config['nd_axis'] = -1 def __init__(self, data=None, freq=None, label=None, units=None, meta=None): super().__init__(data, freq, label, units, meta) self._reps = _Replicate()
[docs] @staticmethod def _mean_axes(*args, **kwargs): """ Inhereted from Spectrum """ raise NotImplementedError('Only applicable to Spectrum class.')
[docs] @staticmethod def _reshape_axes(shape, spectral_axis): """ Parameters ---------- shape : tuple Input data shape spectral_axis : int Spectral axis Returns ------- Reshape vector """ ndim = len(shape) if ndim >= 2: out = [-1, -1] else: out = [1, 1] out[spectral_axis] = shape[spectral_axis] return tuple(out)
@property def data(self): return self._data @data.setter def data(self, value): if not isinstance(value, _np.ndarray): raise TypeError('data must be of type ndarray') if self.freq.data is None or self.freq.op_list_pix is None: if value.ndim != 2: print('Spectra: converting data input from {}D to 2D ndarray'.format(value.ndim)) ax_rs = self._reshape_axes(value.shape, spectral_axis=self.config['nd_axis']) self._data = value.reshape(ax_rs) else: if value.ndim != 2: print('Spectra: converting data input from {}D to 2D ndarray'.format(value.ndim)) if value.shape[-1] == self.freq.op_range_pix.size: temp = _np.zeros((self._data.shape), dtype=value.dtype) temp[:,self.freq.op_range_pix] = value self._data = temp elif value.shape[-1] == self.freq.size: temp = _np.zeros((self._data.shape), dtype=value.dtype) temp[..., self.freq.op_range_pix] = value[..., self.freq.op_range_pix].reshape((-1, len(self.freq.op_range_pix))) self._data = temp else: raise TypeError('data is of an unrecognized shape: {}'.format(value.shape)) @property def n_pix(self): return self._data.shape[0] @property def reps(self): return self._reps @reps.setter def reps(self, value): if isinstance(value, _Replicate): self._reps = value elif isinstance(value, _np.ndarray): self._reps.data = value
[docs] def subtract(self, spectra, overwrite=True): """ Subtract spectrum from data """ # Order IS important if isinstance(spectra, Spectra): if overwrite: self.data -= spectra.data return None else: return self.data - spectra.data elif isinstance(spectra, _Spectrum): if overwrite: self.data -= spectra.data[None,:] return None else: return self.data - spectra.data[None,:] elif isinstance(spectra, _np.ndarray): if spectra.shape == self.data.shape: if overwrite: self.data -= spectra return None else: return self.data - spectra else: if overwrite: self.data -= spectra[None,:] return None else: return self.data - spectra[None,:]
def __sub__(self, spectrum): return self.subtract(spectrum, overwrite=False)
if __name__ == '__main__': # pragma: no cover sp = Spectra() print(sp.__dict__) print('Subclass? : {}'.format(issubclass(Spectra,_Spectrum))) print('Instance of Spectra? : {}'.format(isinstance(sp,Spectra))) print('Instance of Spectrum? : {}'.format(isinstance(sp,_Spectrum))) print('Type(sp) == Spectrum? : {}'.format(type(sp)==_Spectrum)) print('Type(sp) == Spectra? : {}'.format(type(sp)==Spectra))