public DataPoint[] getMassValues(Scan scan, String job, ParameterSet parameters) { double noiseLevel = parameters.getParameter(ExactMassDetectorParameters.noiseLevel).getValue(); // Create a tree set of detected mzPeaks sorted by MZ in ascending order TreeSet<ExactMzDataPoint> mzPeaks = new TreeSet<ExactMzDataPoint>( new DataPointSorter(SortingProperty.MZ, SortingDirection.Ascending)); // Create a tree set of candidate mzPeaks sorted by intensity in // descending order. TreeSet<ExactMzDataPoint> candidatePeaks = new TreeSet<ExactMzDataPoint>( new DataPointSorter(SortingProperty.Intensity, SortingDirection.Descending)); // First get all candidate peaks (local maximum) getLocalMaxima(scan, candidatePeaks, noiseLevel); // We calculate the exact mass for each peak, // starting with biggest intensity peak and so on while (candidatePeaks.size() > 0) { // Always take the biggest (intensity) peak ExactMzDataPoint currentCandidate = candidatePeaks.first(); // Calculate the exact mass and update value in current candidate // (MzPeak) double exactMz = calculateExactMass(currentCandidate); currentCandidate.setMZ(exactMz); // Add this candidate to the final tree set sorted by MZ and remove // from tree set sorted by intensity mzPeaks.add(currentCandidate); candidatePeaks.remove(currentCandidate); } // Return an array of detected MzPeaks sorted by MZ return mzPeaks.toArray(new ExactMzDataPoint[0]); }
/** * This method calculates the exact mass of a peak using the FWHM concept and linear equation (y = * mx + b). * * @param ExactMassDataPoint * @return double */ private double calculateExactMass(ExactMzDataPoint currentCandidate) { /* * According with the FWHM concept, the exact mass of this peak is the * half point of FWHM. In order to get the points in the curve that * define the FWHM, we use the linear equation. * * First we look for, in left side of the peak, 2 data points together * that have an intensity less (first data point) and bigger (second * data point) than half of total intensity. Then we calculate the slope * of the line defined by this two data points. At least, we calculate * the point in this line that has an intensity equal to the half of * total intensity * * We repeat the same process in the right side. */ double xRight = -1, xLeft = -1; double halfIntensity = currentCandidate.getIntensity() / 2; DataPoint[] rangeDataPoints = currentCandidate.getRawDataPoints(); for (int i = 0; i < rangeDataPoints.length - 1; i++) { // Left side of the curve if ((rangeDataPoints[i].getIntensity() <= halfIntensity) && (rangeDataPoints[i].getMZ() < currentCandidate.getMZ()) && (rangeDataPoints[i + 1].getIntensity() >= halfIntensity)) { // First point with intensity just less than half of total // intensity double leftY1 = rangeDataPoints[i].getIntensity(); double leftX1 = rangeDataPoints[i].getMZ(); // Second point with intensity just bigger than half of total // intensity double leftY2 = rangeDataPoints[i + 1].getIntensity(); double leftX2 = rangeDataPoints[i + 1].getMZ(); // We calculate the slope with formula m = Y1 - Y2 / X1 - X2 double mLeft = (leftY1 - leftY2) / (leftX1 - leftX2); // We calculate the desired point (at half intensity) with the // linear equation // X = X1 + [(Y - Y1) / m ], where Y = half of total intensity xLeft = leftX1 + (((halfIntensity) - leftY1) / mLeft); continue; } // Right side of the curve if ((rangeDataPoints[i].getIntensity() >= halfIntensity) && (rangeDataPoints[i].getMZ() > currentCandidate.getMZ()) && (rangeDataPoints[i + 1].getIntensity() <= halfIntensity)) { // First point with intensity just bigger than half of total // intensity double rightY1 = rangeDataPoints[i].getIntensity(); double rightX1 = rangeDataPoints[i].getMZ(); // Second point with intensity just less than half of total // intensity double rightY2 = rangeDataPoints[i + 1].getIntensity(); double rightX2 = rangeDataPoints[i + 1].getMZ(); // We calculate the slope with formula m = Y1 - Y2 / X1 - X2 double mRight = (rightY1 - rightY2) / (rightX1 - rightX2); // We calculate the desired point (at half intensity) with the // linear equation // X = X1 + [(Y - Y1) / m ], where Y = half of total intensity xRight = rightX1 + (((halfIntensity) - rightY1) / mRight); break; } } // We verify the values to confirm we find the desired points. If not we // return the same mass value. if ((xRight == -1) || (xLeft == -1)) return currentCandidate.getMZ(); // The center of left and right points is the exact mass of our peak. double exactMass = (xLeft + xRight) / 2; return exactMass; }