final int scanCount = scanNumbers.length;
final int lastScan = scanCount - 1;
assert scanCount > 0;
final Range peakDuration = parameters.getParameter(PEAK_DURATION)
.getValue();
final double searchRTRange = parameters.getParameter(SEARCH_RT_RANGE)
.getValue();
final double minRatio = parameters.getParameter(MIN_RATIO).getValue();
final double minHeight = Math.max(
parameters.getParameter(MIN_ABSOLUTE_HEIGHT).getValue(),
parameters.getParameter(MIN_RELATIVE_HEIGHT).getValue()
* chromatogram.getHeight());
final List<ResolvedPeak> resolvedPeaks = new ArrayList<ResolvedPeak>(2);
// First, remove all data points below chromatographic threshold.
final double chromatographicThresholdLevel = MathUtils.calcQuantile(
intensities,
parameters.getParameter(CHROMATOGRAPHIC_THRESHOLD_LEVEL)
.getValue());
for (int i = 0; i < intensities.length; i++) {
if (intensities[i] < chromatographicThresholdLevel) {
intensities[i] = 0.0;
}
}
// Current region is a region between two minima, representing a
// candidate for a resolved peak.
startSearch : for (int currentRegionStart = 0; currentRegionStart < lastScan - 2; currentRegionStart++) {
// Find at least two consecutive non-zero data points
if (intensities[currentRegionStart] != 0.0
&& intensities[currentRegionStart + 1] != 0.0) {
double currentRegionHeight = intensities[currentRegionStart];
endSearch : for (int currentRegionEnd = currentRegionStart + 1; currentRegionEnd < scanCount; currentRegionEnd++) {
// Update height of current region.
currentRegionHeight = Math.max(currentRegionHeight,
intensities[currentRegionEnd]);
// If we reached the end, or if the next intensity is 0, we
// have to stop here.
if (currentRegionEnd == lastScan
|| intensities[currentRegionEnd + 1] == 0.0) {
// Find the intensity at the sides (lowest data points).
final double peakMinLeft = intensities[currentRegionStart];
final double peakMinRight = intensities[currentRegionEnd];
// Check the shape of the peak.
if (currentRegionHeight >= minHeight
&& currentRegionHeight >= peakMinLeft
* minRatio
&& currentRegionHeight >= peakMinRight
* minRatio
&& peakDuration
.contains(retentionTimes[currentRegionEnd]
- retentionTimes[currentRegionStart])) {
resolvedPeaks.add(new ResolvedPeak(chromatogram,
currentRegionStart, currentRegionEnd));
}
// Set the next region start to current region end - 1
// because it will be immediately
// increased +1 as we continue the for-cycle.
currentRegionStart = currentRegionEnd - 1;
continue startSearch;
}
// Minimum duration of peak must be at least searchRTRange.
if (retentionTimes[currentRegionEnd]
- retentionTimes[currentRegionStart] >= searchRTRange) {
// Set the RT range to check
final Range checkRange = new Range(
retentionTimes[currentRegionEnd]
- searchRTRange,
retentionTimes[currentRegionEnd]
+ searchRTRange);
// Search if there is lower data point on the left from
// current peak i.
for (int i = currentRegionEnd - 1; i > 0
&& checkRange.contains(retentionTimes[i]); i--) {
if (intensities[i] < intensities[currentRegionEnd]) {
continue endSearch;
}
}
// Search on the right from current peak i.
for (int i = currentRegionEnd + 1; i < scanCount
&& checkRange.contains(retentionTimes[i]); i++) {
if (intensities[i] < intensities[currentRegionEnd]) {
continue endSearch;
}