def tospectrum(self, signal, fwhm=0.1, forceFwhm=True, autoAlign=True, iterLimit=None, relThreshold=0., pickingHeight=0.90, baseline=None): """Fit modeled profiles to spectrum using tmp peaklist. signal (numpy array) - m/z / intensity pairs fwhm (float) - defaut fwhm forceFwhm (bool) - use default fwhm autoAlign (bool) - automatic m/z shift iterLimit (int) - maximum number of iterations pickingHeight (float) - peak picking height for centroiding relThreshold (float) - relative intensity threshold baseline (numpy array) - signal baseline """ # crop signal to relevant m/z range i1 = mod_signal.locate(signal, self.mzrange[0]) i2 = mod_signal.locate(signal, self.mzrange[1]) signal = signal[i1:i2] # get peaklist from signal peaklist = mod_peakpicking.labelscan(signal=signal, pickingHeight=pickingHeight, relThreshold=relThreshold, baseline=baseline) # remove shoulder peaks peaklist.remshoulders(fwhm=fwhm) # correct signal baseline if baseline != None: self.spectrum = mod_signal.subbase(signal, baseline) # fit to peaklist return self.topeaklist( peaklist=peaklist, fwhm=fwhm, forceFwhm=forceFwhm, autoAlign=autoAlign, iterLimit=iterLimit, relThreshold=relThreshold, )
def labelpoint(signal, mz, baseline=None): """Return labeled peak at given x-value. signal (numpy array) - signal data points mz (float) - x-value to label baseline (numpy array) - signal baseline """ # check signal type if not isinstance(signal, numpy.ndarray): raise TypeError, "Signal must be NumPy array!" # check baseline type if baseline != None and not isinstance(baseline, numpy.ndarray): raise TypeError, "Baseline must be NumPy array!" # check signal data if len(signal) == 0: return None # check m/z value if mz <= 0: return None # get peak intensity ai = mod_signal.intensity(signal, mz) if not ai: return None # get peak baseline and s/n base = 0.0 sn = None if baseline == None: base, noise = mod_signal.noise(signal, x=mz) if noise: sn = (ai - base) / noise else: idx = mod_signal.locate(baseline, mz) if (idx > 0) and (idx < len(baseline)): base = mod_signal.interpolate( (baseline[idx-1][0], baseline[idx-1][1]), (baseline[idx][0], baseline[idx][1]), x=mz) noise = mod_signal.interpolate( (baseline[idx-1][0], baseline[idx-1][2]), (baseline[idx][0], baseline[idx][2]), x=mz) if noise: sn = (ai - base) / noise # check peak intensity if ai <= base: return None # get peak fwhm height = base + (ai - base) * 0.5 fwhm = mod_signal.width(signal, mz, height) # make peak object peak = obj_peak.peak(mz=mz, ai=ai, base=base, sn=sn, fwhm=fwhm) return peak
def tospectrum(self, signal, fwhm=0.1, forceFwhm=True, autoAlign=True, iterLimit=None, relThreshold=0., pickingHeight=0.90, baseline=None): """Fit modeled profiles to spectrum using tmp peaklist. signal (numpy array) - m/z / intensity pairs fwhm (float) - defaut fwhm forceFwhm (bool) - use default fwhm autoAlign (bool) - automatic m/z shift iterLimit (int) - maximum number of iterations pickingHeight (float) - peak picking height for centroiding relThreshold (float) - relative intensity threshold baseline (numpy array) - signal baseline """ # crop signal to relevant m/z range i1 = mod_signal.locate(signal, self.mzrange[0]) i2 = mod_signal.locate(signal, self.mzrange[1]) signal = signal[i1:i2] # get peaklist from signal peaklist = mod_peakpicking.labelscan( signal = signal, pickingHeight = pickingHeight, relThreshold = relThreshold, baseline = baseline ) # remove shoulder peaks peaklist.remshoulders(fwhm=fwhm) # correct signal baseline if baseline != None: self.spectrum = mod_signal.subbase(signal, baseline) # fit to peaklist return self.topeaklist( peaklist = peaklist, fwhm = fwhm, forceFwhm = forceFwhm, autoAlign = autoAlign, iterLimit = iterLimit, relThreshold = relThreshold, )
def labelscan(signal, minX=None, maxX=None, pickingHeight=0.75, absThreshold=0., relThreshold=0., snThreshold=0., baseline=None): """Return centroided peaklist for given data points. signal (numpy array) - signal data points minX (float) - x-range start maxX (float) - x-range end pickingHeight (float) - centroiding height absThreshold (float) - absolute intensity threshold relThreshold (float) - relative intensity threshold snThreshold (float) - signal to noise threshold baseline (numpy array) - signal baseline """ # check signal type if not isinstance(signal, numpy.ndarray): raise TypeError, "Signal must be NumPy array!" # check baseline type if baseline != None and not isinstance(baseline, numpy.ndarray): raise TypeError, "Baseline must be NumPy array!" # crop data if minX != None and maxX != None: i1 = mod_signal.locate(signal, minX) i2 = mod_signal.locate(signal, maxX) signal = signal[i1:i2] # check data points if len(signal) == 0: return obj_peaklist.peaklist([]) # get local maxima buff = [] basepeak = mod_signal.basepeak(signal) threshold = max(signal[basepeak][1] * relThreshold, absThreshold) for peak in mod_signal.maxima(signal): if peak[1] >= threshold: buff.append( [peak[0], peak[1], 0., None, None] ) # mz, ai, base, sn, fwhm CHECK_FORCE_QUIT() # get peaks baseline and s/n basepeak = 0.0 if baseline != None: for peak in buff: idx = mod_signal.locate(baseline, peak[0]) if (idx > 0) and (idx < len(baseline)): p1 = baseline[idx-1] p2 = baseline[idx] peak[2] = mod_signal.interpolate( (p1[0], p1[1]), (p2[0], p2[1]), x=peak[0]) noise = mod_signal.interpolate( (p1[0], p1[2]), (p2[0], p2[2]), x=peak[0]) intens = peak[1] - peak[2] if noise: peak[3] = intens / noise if intens > basepeak: basepeak = intens CHECK_FORCE_QUIT() # remove peaks bellow threshold threshold = max(basepeak * relThreshold, absThreshold) candidates = [] for peak in buff: if peak[0] > 0 and (peak[1] - peak[2]) >= threshold and (not peak[3] or peak[3] >= snThreshold): candidates.append(peak) # make centroides if pickingHeight < 1.: buff = [] previous = None for peak in candidates: CHECK_FORCE_QUIT() # calc peak height h = ((peak[1]-peak[2]) * pickingHeight) + peak[2] # get centroid indexes idx = mod_signal.locate(signal, peak[0]) if (idx == 0) or (idx == len(signal)): continue ileft = idx-1 while (ileft > 0) and (signal[ileft][1] > h): ileft -= 1 iright = idx while (iright < len(signal)-1) and (signal[iright][1] > h): iright += 1 # calculate peak mz leftMZ = mod_signal.interpolate(signal[ileft], signal[ileft+1], y=h) rightMZ = mod_signal.interpolate(signal[iright-1], signal[iright], y=h) peak[0] = (leftMZ + rightMZ)/2. # get peak intensity intens = mod_signal.intensity(signal, peak[0]) if intens and intens <= peak[1]: peak[1] = intens else: continue # try to group with previous peak if previous != None and leftMZ < previous: if peak[1] > buff[-1][1]: buff[-1] = peak previous = rightMZ else: buff.append(peak) previous = rightMZ # store as candidates candidates = buff CHECK_FORCE_QUIT() # get peaks baseline and s/n basepeak = 0.0 if baseline != None: for peak in candidates: idx = mod_signal.locate(baseline, peak[0]) if (idx > 0) and (idx < len(baseline)): p1 = baseline[idx-1] p2 = baseline[idx] peak[2] = mod_signal.interpolate( (p1[0], p1[1]), (p2[0], p2[1]), x=peak[0]) noise = mod_signal.interpolate( (p1[0], p1[2]), (p2[0], p2[2]), x=peak[0]) intens = peak[1] - peak[2] if noise: peak[3] = intens / noise if intens > basepeak: basepeak = intens CHECK_FORCE_QUIT() # remove peaks bellow threshold and calculate fwhm threshold = max(basepeak * relThreshold, absThreshold) centroides = [] for peak in candidates: if peak[0] > 0 and (peak[1] - peak[2]) >= threshold and (not peak[3] or peak[3] >= snThreshold): peak[4] = mod_signal.width(signal, peak[0], (peak[2] + ((peak[1] - peak[2]) * 0.5))) centroides.append(obj_peak.peak(mz=peak[0], ai=peak[1], base=peak[2], sn=peak[3], fwhm=peak[4])) # return peaklist object return obj_peaklist.peaklist(centroides)
def labelpeak(signal, mz=None, minX=None, maxX=None, pickingHeight=0.75, baseline=None): """Return labeled peak in given m/z range. signal (numpy array) - signal data points mz (float) - x-value to label minX (float) - x-range start maxX (float) - x-range end pickingHeight (float) - centroiding height baseline (numpy array) - signal baseline """ # check signal type if not isinstance(signal, numpy.ndarray): raise TypeError, "Signal must be NumPy array!" # check baseline type if baseline != None and not isinstance(baseline, numpy.ndarray): raise TypeError, "Baseline must be NumPy array!" # check m/z value or range if mz == None and minX == None and maxX == None: raise TypeError, "m/z value or range must be specified!" # check signal data if len(signal) == 0: return None # check m/z value if mz != None: minX = mz if minX <= 0: return False # get index of given m/z or range maximum if mz != None: imax = mod_signal.locate(signal, mz) else: i1 = mod_signal.locate(signal, minX) i2 = mod_signal.locate(signal, maxX) imax = i1 if i1 != i2: imax += mod_signal.basepeak(signal[i1:i2]) if (imax == 0) or (imax == len(signal)): return None # get centroid height h = signal[imax][1] * pickingHeight if baseline != None: idx = mod_signal.locate(baseline, signal[imax][0]) if (idx > 0) and (idx < len(baseline)): base = mod_signal.interpolate( (baseline[idx-1][0], baseline[idx-1][1]), (baseline[idx][0], baseline[idx][1]), x=signal[imax][0]) h = ((signal[imax][1] - base) * pickingHeight) + base # get centroid ileft = imax-1 while (ileft > 0) and (signal[ileft][1] > h): ileft -= 1 iright = imax while (iright < len(signal)-1) and (signal[iright][1] > h): iright += 1 leftMZ = mod_signal.interpolate(signal[ileft], signal[ileft+1], y=h) rightMZ = mod_signal.interpolate(signal[iright-1], signal[iright], y=h) # check range if mz == None and (leftMZ < minX or rightMZ > maxX) and (leftMZ != rightMZ): return None # label peak in the newly found selection if mz != None and leftMZ != rightMZ: peak = labelpeak( signal = signal, minX = leftMZ, maxX = rightMZ, pickingHeight = pickingHeight, baseline = baseline ) # label current point else: peak = labelpoint( signal = signal, mz = ((leftMZ + rightMZ)/2.), baseline = baseline ) return peak
def topoints(self, points, fwhm=0.1, autoAlign=True, iterLimit=None): """Fit modeled profiles to given points. points (numpy array or list) - m/z / intensity pairs fwhm (float) - defaut fwhm autoAlign (bool) - automatic m/z shift iterLimit (int) - maximum number of iterations """ self.fwhm = fwhm # reset previous results self.composition = {} self.ncomposition = {} self.average = 0. self.model = numpy.array([]) for x in self.models: self.models[x][2] = 0.0 # abs comp self.models[x][3] = 0.0 # rel comp # check points type if not isinstance(points, numpy.ndarray): points = numpy.array(points) # crop points to relevant m/z range i1 = mod_signal.locate(points, self.mzrange[0]) i2 = mod_signal.locate(points, self.mzrange[1]) self.data = numpy.array(points[i1:i2]) # check data if len(self.data) == 0: return False # auto align data and theoretical pattern if autoAlign: self._alignData() # split data to raster and intensities xAxis, yAxis = numpy.hsplit(self.data, 2) raster = xAxis.flatten() intensities = yAxis.flatten() # model profiles models, exchanged = self._makeModels(raster, reset=False) # fit data to models fit = self._leastSquare(intensities, models, iterLimit=iterLimit) if not sum(fit): return False f = 1. / sum(fit) for i, abundance in enumerate(fit): self.models[exchanged[i]][2] = abundance self.models[exchanged[i]][3] = f * abundance # calc average exchange for x in self.models: self.average += x * self.models[x][3] # get compositions for x in sorted(self.models.keys()): self.composition[x] = self.models[x][2] self.ncomposition[x] = self.models[x][3] # get calculated points raster.shape = (-1, 1) intensities = numpy.sum(models * [[x] for x in fit], axis=0) intensities.shape = (-1, 1) self.model = numpy.concatenate((raster, intensities), axis=1).copy() return True
def topoints(self, points, fwhm=0.1, autoAlign=True, iterLimit=None): """Fit modeled profiles to given points. points (numpy array or list) - m/z / intensity pairs fwhm (float) - defaut fwhm autoAlign (bool) - automatic m/z shift iterLimit (int) - maximum number of iterations """ self.fwhm = fwhm # reset previous results self.composition = {} self.ncomposition = {} self.average = 0. self.model = numpy.array([]) for x in self.models: self.models[x][2] = 0.0 # abs comp self.models[x][3] = 0.0 # rel comp # check points type if not isinstance(points, numpy.ndarray): points = numpy.array(points) # crop points to relevant m/z range i1 = mod_signal.locate(points, self.mzrange[0]) i2 = mod_signal.locate(points, self.mzrange[1]) self.data = numpy.array(points[i1:i2]) # check data if len(self.data) == 0: return False # auto align data and theoretical pattern if autoAlign: self._alignData() # split data to raster and intensities xAxis, yAxis = numpy.hsplit(self.data, 2) raster = xAxis.flatten() intensities = yAxis.flatten() # model profiles models, exchanged = self._makeModels(raster, reset=False) # fit data to models fit = self._leastSquare(intensities, models, iterLimit=iterLimit) if not sum(fit): return False f = 1./sum(fit) for i, abundance in enumerate(fit): self.models[exchanged[i]][2] = abundance self.models[exchanged[i]][3] = f*abundance # calc average exchange for x in self.models: self.average += x * self.models[x][3] # get compositions for x in sorted(self.models.keys()): self.composition[x] = self.models[x][2] self.ncomposition[x] = self.models[x][3] # get calculated points raster.shape = (-1,1) intensities = numpy.sum(models * [[x] for x in fit], axis=0) intensities.shape = (-1,1) self.model = numpy.concatenate((raster, intensities), axis=1).copy() return True