use of net.sf.mzmine.modules.peaklistmethods.peakpicking.deconvolution.ResolvedPeak in project mzmine2 by mzmine.
the class SavitzkyGolayPeakDetector method peaksSearch.
/**
* Search for peaks.
*
* @param chromatogram the chromatogram to search.
* @param scanNumbers scan number to focus search on
* @param derivativeOfIntensities derivatives of intensity values.
* @param noiseThreshold noise threshold.
* @return array of peaks found.
*/
private static Feature[] peaksSearch(final Feature chromatogram, final int[] scanNumbers, final double[] derivativeOfIntensities, final double noiseThreshold, CenterFunction mzCenterFunction, final double msmsRange, final double rTRangeMSMS) {
// Flag to identify the current and next overlapped peak.
boolean activeFirstPeak = false;
boolean activeSecondPeak = false;
// Flag to indicate the value of 2nd derivative pass noise threshold
// level.
boolean passThreshold = false;
// Number of times that 2nd derivative cross zero value for the current
// feature detection.
int crossZero = 0;
final int totalNumberPoints = derivativeOfIntensities.length;
// Indexes of start and ending of the current peak and beginning of the
// next.
int currentPeakStart = totalNumberPoints;
int nextPeakStart = totalNumberPoints;
int currentPeakEnd = 0;
final List<Feature> resolvedPeaks = new ArrayList<Feature>(2);
//
for (int i = 1; i < totalNumberPoints; i++) {
// Changing sign and crossing zero
if (derivativeOfIntensities[i - 1] < 0.0 && derivativeOfIntensities[i] > 0.0 || derivativeOfIntensities[i - 1] > 0.0 && derivativeOfIntensities[i] < 0.0) {
if (derivativeOfIntensities[i - 1] < 0.0 && derivativeOfIntensities[i] > 0.0) {
if (crossZero == 2) {
// passThreshold flag is activated.
if (passThreshold) {
activeSecondPeak = true;
nextPeakStart = i;
} else {
currentPeakStart = i;
crossZero = 0;
activeFirstPeak = true;
}
}
}
// Finalize the first overlapped peak.
if (crossZero == 3) {
activeFirstPeak = false;
currentPeakEnd = i;
}
// Increments when detect a crossing zero event
passThreshold = false;
if (activeFirstPeak || activeSecondPeak) {
crossZero++;
}
}
// Filter for noise threshold level.
if (Math.abs(derivativeOfIntensities[i]) > noiseThreshold) {
passThreshold = true;
}
// Start peak region.
if (crossZero == 0 && derivativeOfIntensities[i] > 0.0 && !activeFirstPeak) {
activeFirstPeak = true;
currentPeakStart = i;
crossZero++;
}
// Finalize the peak region in case of zero values.
if (derivativeOfIntensities[i - 1] == 0.0 && derivativeOfIntensities[i] == 0.0 && activeFirstPeak) {
currentPeakEnd = crossZero < 3 ? 0 : i;
activeFirstPeak = false;
activeSecondPeak = false;
crossZero = 0;
}
// start to the first available data point.
while (currentPeakStart < scanNumbers.length - 1) {
if (chromatogram.getDataPoint(scanNumbers[currentPeakStart]) == null) {
currentPeakStart++;
} else {
break;
}
}
// peak there.
for (int newEnd = currentPeakStart; newEnd <= currentPeakEnd; newEnd++) {
if (chromatogram.getDataPoint(scanNumbers[newEnd]) == null) {
currentPeakEnd = newEnd - 1;
break;
}
}
// the chromatogram.
if (currentPeakEnd - currentPeakStart > 0 && !activeFirstPeak) {
resolvedPeaks.add(new ResolvedPeak(chromatogram, currentPeakStart, currentPeakEnd, mzCenterFunction, msmsRange, rTRangeMSMS));
// for this new current peak.
if (activeSecondPeak) {
activeSecondPeak = false;
activeFirstPeak = true;
crossZero = derivativeOfIntensities[i] > 0.0 ? 1 : 2;
currentPeakStart = nextPeakStart;
} else {
crossZero = 0;
currentPeakStart = totalNumberPoints;
}
passThreshold = false;
nextPeakStart = totalNumberPoints;
currentPeakEnd = 0;
}
}
return resolvedPeaks.toArray(new Feature[resolvedPeaks.size()]);
}
Aggregations