Commit 64b11e24 authored by Jay's avatar Jay Committed by jay
Browse files

Creating a single package incorporating other projects

parent 1a860d9a
Loading
Loading
Loading
Loading
+0 −0

Empty file added.

+107 −0
Original line number Diff line number Diff line
import numpy as np
from pandas import Series

#TODO: The common parsing should be a decorator

def band_minima(spectrum, low_endmember=None, high_endmember=None):
    """
    Given two end members, find the minimum observed value inclusively 
    between them.

    Parameters
    ==========
    spectrum : pd.series
               Pandas series

    low_endmember : float
                    The low wavelength

    high_endmember : float
                     The high wavelength

    Returns
    =======
    minidx : int
             The wavelength of the minimum value
    
    minvalue : float
               The observed minimal value
    """
    x = spectrum.index
    y = spectrum

    if not low_endmember:
        low_endmember = x[0]
    if not high_endmember:
        high_endmember = x[-1]

    ny = y[low_endmember:high_endmember]

    minidx = ny.idxmin()
    minvalue = ny.min()
    
    return minidx, minvalue

def band_center(spectrum, low_endmember=None, high_endmember=None, degree=3):

    x = spectrum.index
    y = spectrum

    if not low_endmember:
        low_endmember = x[0]
    if not high_endmember:
        high_endmember = x[-1]

    ny = y[low_endmember:high_endmember]

    fit = np.polyfit(ny.index, ny, degree)

    center_fit = Series(np.polyval(fit, ny.index), ny.index)
    center = band_minima(center_fit)

    return center, center_fit

def band_area(spectrum, low_endmember=None, high_endmember=None):
    """
    Compute the area under the curve between two endpoints where the
    y-value <= 1.
    """

    x = spectrum.index
    y = spectrum

    if not low_endmember:
        low_endmember = x[0]
    if not high_endmember:
        high_endmember = x[-1]

    ny = y[low_endmember:high_endmember]
    
    return np.trapz(-ny[ny <= 1.0])

def band_asymmetry(spectrum, low_endmember=None, high_endmember=None):
    """
    Compute the symmetry of an absorption feature as

    (left_area - right_area) / total_area
    """

    x = specturm.index
    y = spectrum 

    if not low_endmember:
        low_endmember = x[0]
    if not high_endmember:
        high_endmember = x[-1]

    ny = y[low_endmember:high_endmember]

    center, _ = band_center(ny, low_endmember, high_endmember)
    
    area_left = band_area(ny[:center], low_endmember, high_endmember)
    area_right = band_area(ny[center:], low_endmember, high_endmember)

    asymmetry = (area_left - area_right) / (area_left + area_right)
    return asymmetry

+113 −0
Original line number Diff line number Diff line
import numpy as np
import pandas as pd
import scipy.stats as ss

def continuum_correct(spectrum, nodes=None, method='linear'):
    """
    Apply a continuum correction to a given spectrum

    Parameters
    ==========
    spectrum : pd.Series
               A pandas series or Spectrum object

    nodes: list
           A list of the nodes between which piecewise continuum
           will be fit

    method : {'linear', 'regresison', 'cubic'}
             The type of regression to be fit, where 'linear' is a piecewise
             linear fit, 'regression' is an Ordinary Least Squares fit, and 
             'cubic' is a 2nd order polynomial fit.

    Returns
    =======
     : pd.Series
       The continuum corrected Spectrum
     
     : pd.Series
       The continuum line
    """

    x = spectrum.index
    y = spectrum
    if not nodes:
        nodes = [x[0], x[-1]]

    return_length = len(y)
    corrected = np.empty(return_length)
    continuum = np.empty(return_length)
    
    start = 0
    nlist = zip(nodes, nodes[1:])
    for i, n in enumerate(nlist):
        # Define indices into sub-series
        ny = y[n[0]:n[1]]
        nx = ny.index
        if i == 0:
            stop = start + len(y[:n[1]])
            c = correction_methods[method](nx, ny, ex=y[:n[1]].index.values)
            ey = y[:n[1]]
        elif i == len(nlist) - 1:
            stop = start + len(y[n[0]:])
            c = correction_methods[method](nx, ny, ex=y[n[0]:].index.values)
            ey = y[n[0]:]
        else:
            stop = start + len(ny)
            c = correction_methods[method](nx, ny)
            ey = ny
 
        continuum[start:stop] = c
        corrected[start:stop] = ey / c
        
        start = stop

    return pd.Series(corrected, index=x), pd.Series(continuum, index=x)


def regression(nx, ny):
    """
    Parameters
    ==========
    specturm : pd.series
               Pandas Series object

    nodes : list
            of nodes to be used for the continuum

    Returns
    =======
    corrected : array
                Continuum corrected array

    continuum : array
                The continuum used to correct the data

    x : array
        The potentially truncated x values
    """

    m, b, r_value, p_value, stderr = ss.linregress(nx, ny)
    c = m * nx + b
    return c

def linear(nx, ny, ex=None):
    y1 = ny.iloc[0]
    y2 = ny.iloc[-1]
    wv1 = nx[0]
    wv2 = nx[-1]
    if not isinstance(ex, np.ndarray):
        ex = nx
    m = (y2-y1) / (wv2-wv1)
    b = y1 - (m * wv1)
    
    c = m * ex + b

    return c 

def cubic(spectrum, nodes):
    raise(NotImplemented)

correction_methods = {'linear':linear,
                      'regression':regression,
                      'cubic': cubic}
+46 −0
Original line number Diff line number Diff line
import numpy as np
from scipy import signal

from pandas import Series

def boxcar(y, window_size=3):
    """
    Smooth the input vector using the mean of the neighboring values,
    where neighborhood size is defined by the window.

    Parameters
    ==========
    y : array
        The vector to be smoothed.

    window_size : int
                  An odd integer describing the window size.

    Returns
    =======
     : array 
       The smoothed array.

    """
    filt = np.ones(window_size) / window_size
    return Series(np.convolve(y, filt, mode='same'), index=y.index)

def gaussian(y, window_size=3, sigma=2):
    """
    Apply a gaussian filter to smooth the input vector

    Parameters
    ==========
    y :  array
         The input array

    window_size : int
                  An odd integer describing the size of the filter.

    sigma : float
            The numver of standard deviation
    """
    filt = signal.gaussian(window_size, sigma)
    return Series(signal.convolve(y, filt, mode='same'), index=y.index)

+88 −0
Original line number Diff line number Diff line
from pandas import DataFrame, Series

from autocnet.spectral.smoothing import boxcar, gaussian
from autocnet.spectral.continuum import continuum_correct
import autocnet.spectral.analytics as analytics


def tospectra(func):
    def wrapper(*args, **kwargs):
        result = func(*args, **kwargs)
        return Spectra(result)
    return wrapper


def tospectrum(func):
    def wrapper(*args, **kwargs):
        result = func(*args, **kwargs)
        return Spectrum(result)
    return wrapper


class Spectrum(object):

    def __init__(self, series):
        self.series = series

    def __repr__(self):
        return self.series.__repr__()

    def __getattr__(self, attr):
        result = getattr(self.series, attr)
        if callable(result):
            result = tospectrum(result)
        return result
    
    def __getitem__(self, key):
        try:
            result = self.series.iloc[key]
        except:
            result = self.series[key]
        return result

    def boxcar_smooth(self, *args, **kwargs):
        return Spectrum(boxcar(self.series, *args, **kwargs))

    def gaussian_smooth(self, *args, **kwargs):
        return Spectrum(gaussian(self.series, *args, **kwargs))
    
    def continuum_correct(self, *args, **kwargs):
        corrected, continuum = continuum_correct(self.series, *args, **kwargs)
        return Spectrum(corrected), Spectrum(continuum)

    def band_minima(self, *args, **kwargs):
        minidx, minvalue = analytics.band_minima(self, *args, **kwargs)
        return minidx, minvalue

    def band_center(self, *args, **kwargs):
        return analytics.band_center(self, *args, **kwargs)

    def band_area(self, *args, **kwargs):
        return analytics.band_area(self, *args, **kwargs)


class Spectra(object):

    def __init__(self, df=None):
        self.df = df

    def __getitem__(self, key):
        result = self.df[key]
        if isinstance(result, type(self.df)):
            result = Spectra(result)
        elif isinstance(result, Series):
            return Spectrum(result)
        return result

    def __getattr__(self, attr):
        result = getattr(self.df, attr)
        if callable(result):
            result = tospectra(result)
        return result

    def __repr__(self):
        return repr(self.df)

    
       
    
Loading