/** * 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; }