Source code for spike.plugins.bcorr

#!/usr/bin/env python 
# encoding: utf-8

"""set of function for the baseline correction

First version - Not finished !

improved July 2016
"""

from __future__ import print_function, division
import numpy as np
from scipy import interpolate
from scipy.optimize import leastsq

from spike import NPKError
from spike.NPKData import NPKData_plugin

import sys
if sys.version_info[0] < 3:
    pass
else:
    xrange = range
#-------------------------------------------------------------------------------
[docs]def get_ypoints(buff, xpoints, nsmooth=0): """ from buff and xpoints, returns ypoints = buff[xpoints] eventually smoothed by moving average over 2*nsmooth+1 positions """ nsmooth = abs(nsmooth) xp = np.array(xpoints).astype(int) y = np.zeros(len(xpoints)) for i in range(2*nsmooth+1): xi = np.minimum( np.maximum(xp-i, 0), len(buff)-1) # shift and truncate y += buff[xi] y /= 2*nsmooth+1 return y
#------------------------------------------------------------------------------- def _spline_interpolate(buff, xpoints, kind = 3, nsmooth=0): """compute and returns a spline function we are using splrep and splev instead of interp1d because interp1d needs to have 0 and last point it doesn't extend. """ if len(xpoints) == 2 : return _linear_interpolate(buff, xpoints) elif len(xpoints) > 2: xpoints.sort() y = get_ypoints(buff, xpoints, nsmooth=nsmooth) tck = interpolate.splrep(xpoints, y, k=kind) def f(x): return interpolate.splev(x, tck, der=0, ext=0) return f else: # if only one points given, returns a constant, which is the value at that point. raise NPKError("too little points in spline interpolation") #------------------------------------------------------------------------------- def _linear_interpolate(buff, xpoints, nsmooth=0): """computes and returns a linear interpolation""" xdata = np.array(xpoints) ydata = get_ypoints(buff, xpoints, nsmooth=nsmooth) coeffs = np.polyfit(xdata, ydata, 1) return np.poly1d(coeffs) #------------------------------------------------------------------------------- def _interpolate(func, npkd, xpoints, axis = 'F2', nsmooth=0): """" compute and applies a linear function as a baseline correction xpoints are the location of pivot points """ if npkd.dim == 1: f = func(npkd.buffer, xpoints, nsmooth=nsmooth) x = np.arange(npkd.size1) npkd.buffer -= f(x) elif npkd.dim == 2: if npkd.test_axis(axis) == 2: x = np.arange(npkd.size2) for i in xrange(npkd.size1): f = func(npkd.buffer[i,:], xpoints, nsmooth=nsmooth) npkd.buffer[i,:] -= f(x) elif npkd.test_axis(axis) == 1: x = np.arange(npkd.size1) for i in xrange(npkd.size2): f = func(npkd.buffer[:,i], xpoints, nsmooth=nsmooth) npkd.buffer[:,i] -= f(x) else: raise NPKError("not implemented") return npkd
[docs]def linear_interpolate(npkd, xpoints, axis='F2', nsmooth=0): """" compute and applies a linear function as a baseline correction xpoints are the location of pivot points """ return _interpolate(_linear_interpolate, npkd, xpoints, axis=axis, nsmooth=nsmooth )
[docs]def spline_interpolate(npkd, xpoints, axis='F2', nsmooth=0): """" compute and applies a spline function as a baseline correction xpoints are the location of pivot points """ return _interpolate(_spline_interpolate, npkd, xpoints, axis=axis, nsmooth=nsmooth)
######################################################################## import spike.Algo.savitzky_golay as sgm import spike.Algo.BC as BC ########################################################################
[docs]def bcorr_auto(npkd, iterations=10, nbchunks=40, degree=1, nbcores=2, smooth=True): """applies an automatic baseline correction Find baseline by using low norm value and then high norm value to attract the baseline on the small values. Parameters : iterations : number of iterations for convergence toward the small values. nbchunks : number of chunks on which is done the minimization. Typically, each chunk must be larger than the peaks. degree : degree of the polynome used for approaching each signal chunk. nbcores : number of cores used for minimizing in parallel on many chunks (if not None) smooth i True, applies a final Savitsky-Golay smoothing """ npkd.check1D() bl = BC.correctbaseline(npkd.get_buffer(), iterations=iterations, nbchunks=nbchunks, degree=degree, nbcores=nbcores) #baseline(npkd.get_buffer(), degree=degree) if smooth: bl = sgm.savitzky_golay( bl, 205, 7) npkd.set_buffer( npkd.get_buffer() - bl) return npkd
[docs]def autopoints(npkd, Npoints=8): """ computes Npoints (defaut 8) positions for a spline baseline correction """ if Npoints is None : N = 8 else: N = Npoints bf = npkd.get_buffer().copy() bf -= np.percentile(bf,20) # assumes at least ~20% of data-set is baseline... bf = abs(bf) L = len(bf) chunksize = L//N #print (chunksize) xpoints = np.array([i+bf[i:i+chunksize-8].argmin() for i in range(4, L, chunksize)]) if npkd.itype == 1: xpoints *= 2 return xpoints
[docs]def bcorr(npkd, method='spline', xpoints=None, nsmooth=0): """ recapitulate all baseline correction methods, only 1D so far method is either auto: use bcorr_auto, uses an automatic determination of the baseline does not work with negative peaks. linear: simple 1D correction spline: a cubic spline correction both linear and spline use an additional list of pivot points 'xpoints' used to calculate the baseline if xpoints absent, pivots are estimated automaticaly if xpoints is integer, it determines the number of computed pivots (defaut is 8 if xpoints is None) if xpoints is a list of integers, there will used as pivots if nsmooth >0, buffer is smoothed by moving average over 2*nsmooth+1 positions around pivots. default is spline with automatic detection of 8 baseline points """ if method=='auto': return bcorr_auto(npkd) else: if xpoints is None or isinstance(xpoints,int): xpoints = autopoints(npkd, xpoints) if method=='linear': return linear_interpolate(npkd, xpoints, nsmooth=nsmooth) elif method=='spline': return spline_interpolate(npkd, xpoints, nsmooth=nsmooth) else: raise Exception("Wrong method in bcorr plugin")
NPKData_plugin("bcorr_lin", linear_interpolate) NPKData_plugin("bcorr_spline", spline_interpolate) NPKData_plugin("bcorr_auto", bcorr_auto) NPKData_plugin("bcorr", bcorr)