protected virtual void GetRawData(out List <double> vectMZs, out List <double> vectIntensities, int scan, double min_mz, double max_mz, bool centroid) { if (max_mz <= min_mz) { throw new Exception("max_mz should be greater than min_mz"); } vectMZs = new List <double>(); vectIntensities = new List <double>(); List <double> allMZs; List <double> allIntensities; GetRawData(out allMZs, out allIntensities, scan, centroid); var numPts = allMZs.Count; if (numPts <= 1) { Console.Error.WriteLine(scan); throw new Exception("mz_vector empty in GetRawData in RawData.cpp"); } var startIndex = PeakIndex.GetNearestBinary(allMZs, min_mz, 0, numPts - 1); var stopIndex = PeakIndex.GetNearestBinary(allMZs, max_mz, 0, numPts - 1); if ((stopIndex - startIndex) <= 1) //nothing in this m/z range { return; } vectMZs.AddRange(allMZs.GetRange(startIndex, stopIndex - startIndex)); vectIntensities.AddRange(allIntensities.GetRange(startIndex, stopIndex - startIndex)); }
/// <summary> /// Gets the charge state (determined by AutoCorrelation algorithm) for a peak in some data. /// </summary> /// <param name="peak">is the peak whose charge we want to detect.</param> /// <param name="peakData">is the PeakData object containing raw data, peaks, etc which are used in the process.</param> /// <param name="debug"></param> /// <returns>Returns the charge of the feature.</returns> public static int GetChargeState(ThrashV1Peak peak, PeakData peakData, bool debug) { var minus = 0.1; var plus = 1.1; // right direction to look var startIndex = PeakIndex.GetNearest(peakData.MzList, peak.Mz - peak.FWHM - minus, peak.DataIndex); var stopIndex = PeakIndex.GetNearest(peakData.MzList, peak.Mz + peak.FWHM + plus, peak.DataIndex); var numPts = stopIndex - startIndex; var numL = numPts; if (numPts < 5) { return(-1); } if (numPts < 256) { numL = 10 * numPts; } // TODO: PattersonChargeStateCalculator does a lot of funny stuff around here. // variable to help us perform spline interpolation. // count is stopIndex - startIndex + 1 because we need to include the values at stopIndex as well // NOTE: This output is different from what the DeconEngineV2 code outputs; there are notes in that code // wondering if there was a bug in the previous implementation imported from VB, of starting at startIndex + 1. // That code performed interpolation on the range from startIndex + 1 to stopIndex, inclusive, and minMz set to PeakData.MzList[startIndex + 1]. // This code can produce output that more closely matches the DeconEngineV2 output by using // "startIndex, stopIndex - startIndex + 2" as the parameters to "GetRange()", and setting minMz to PeakData.MzList[startIndex + 1]. // Since using startIndex and stopIndex directly produces output that mostly differs on fit score by a small amount, // we are changing this code to use them. var interpolator = CubicSpline.InterpolateNaturalSorted( peakData.MzList.GetRange(startIndex, stopIndex - startIndex + 1).ToArray(), peakData.IntensityList.GetRange(startIndex, stopIndex - startIndex + 1).ToArray()); var minMz = peakData.MzList[startIndex]; var maxMz = peakData.MzList[stopIndex]; // List to store the interpolated intensities of the region on which we performed the cubic spline interpolation. var iv = new List <double>(numL); for (var i = 0; i < numL; i++) { var xVal = minMz + (maxMz - minMz) * i / numL; var fVal = interpolator.Interpolate(xVal); iv.Add(fVal); } if (debug) { Console.Error.WriteLine("mz,intensity"); for (var i = 0; i < numL; i++) { var xVal = minMz + (maxMz - minMz) * i / numL; Console.Error.WriteLine(xVal + "," + iv[i]); } } // List to store the auto correlation values at the points in the region. var autoCorrelationScores = ACss(iv.ToArray()); if (debug) { Console.Error.WriteLine("AutoCorrelation values"); for (var i = 0; i < autoCorrelationScores.Count; i++) { var score = autoCorrelationScores[i]; Console.Error.WriteLine((maxMz - minMz) * i / numL + "," + score); } } var minN = 0; while (minN < numL - 1 && autoCorrelationScores[minN] > autoCorrelationScores[minN + 1]) { minN++; } var success = HighestChargeStatePeak(minMz, maxMz, minN, autoCorrelationScores, MaxCharge, out var bestAcScore, out _); if (!success) { return(-1); // Didn't find anything } // List to temporarily store charge list. These charges are calculated at peak values of auto correlation. // Now go back through the CS peaks and make a list of all CS that are at least 10% of the highest var charges = GenerateChargeStates(minMz, maxMz, minN, autoCorrelationScores, MaxCharge, bestAcScore); // Get the final CS value to be returned var returnChargeStateVal = -1; // TODO: PattersonChargeStateCalculator really doesn't match the following code. var fwhm = peak.FWHM; // Store a copy of the FWHM to avoid modifying the actual value if (fwhm > 0.1) { fwhm = 0.1; } for (var i = 0; i < charges.Count; i++) { // no point retesting previous charge. var tempChargeState = charges[i]; var skip = false; for (var j = 0; j < i; j++) { if (charges[j] == tempChargeState) { skip = true; break; } } if (skip) { continue; } if (tempChargeState > 0) { var peakA = peak.Mz + 1.0 / tempChargeState; var found = peakData.GetPeakFromAllOriginalIntensity(peakA - fwhm, peakA + fwhm, out var isoPeak); if (found) { returnChargeStateVal = tempChargeState; if (isoPeak.Mz * tempChargeState < 3000) { break; } // if the mass is greater than 3000, lets make sure that multiple isotopes exist. peakA = peak.Mz - 1.03 / tempChargeState; found = peakData.GetPeakFromAllOriginalIntensity(peakA - fwhm, peakA + fwhm, out isoPeak); if (found) { return(tempChargeState); } } else { peakA = peak.Mz - 1.0 / tempChargeState; found = peakData.GetPeakFromAllOriginalIntensity(peakA - fwhm, peakA + fwhm, out isoPeak); if (found && isoPeak.Mz * tempChargeState < 3000) { return(tempChargeState); } } } } return(returnChargeStateVal); }
public bool FindPeak(double minMz, double maxMz, out double mzValue, out double intensity, bool debug) { if (!_lastValueWasCached) { var found = IsotopeDistribution.FindPeak(minMz, maxMz, out mzValue, out intensity); return(found); } mzValue = 0; intensity = 0; var numPts = TheoreticalDistMzs.Count; var index = PeakIndex.GetNearestBinary(TheoreticalDistMzs, minMz, 0, numPts - 1); if (index >= numPts) { return(false); } if (TheoreticalDistMzs[index] > minMz) { while (index > 0 && TheoreticalDistMzs[index] > minMz) { index--; } } else { while (index < numPts && TheoreticalDistMzs[index] < minMz) { index++; } index--; } //find index of peak with maximum intensity var maxIndex = -1; for (; index < numPts; index++) { var mz = TheoreticalDistMzs[index]; if (mz > maxMz) { break; } if (mz > minMz) { if (TheoreticalDistIntensities[index] > intensity) { maxIndex = index; intensity = TheoreticalDistIntensities[index]; } } } if (maxIndex == -1) { return(false); } var x2 = TheoreticalDistMzs[maxIndex]; var x1 = x2 - 1.0 / IsotopeDistribution.PointsPerAmu; var x3 = x2 + 1.0 / IsotopeDistribution.PointsPerAmu; if (maxIndex > 0 && maxIndex < numPts - 1) { var y1 = TheoreticalDistIntensities[maxIndex - 1]; var y2 = TheoreticalDistIntensities[maxIndex]; var y3 = TheoreticalDistIntensities[maxIndex + 1]; // if the points are cached, these could be single sticks with surrounding // points below background. To avoid that case, lets just check // and see if the differences in the theoretical mz values is as // expected or not. if (TheoreticalDistMzs[maxIndex - 1] > x2 - 2.0 / IsotopeDistribution.PointsPerAmu && TheoreticalDistMzs[maxIndex + 1] < x2 + 2.0 / IsotopeDistribution.PointsPerAmu) { var d = (y2 - y1) * (x3 - x2); //[gord] slope? what is this?... Denominator... see below d = d - (y3 - y2) * (x2 - x1); // if (d.Equals(0)) { mzValue = x2; } else { mzValue = (x1 + x2 - (y2 - y1) * (x3 - x2) * (x1 - x3) / d) / 2.0; } //[gord] what's this doing?? Looks like a mid-point calculation } else { mzValue = x2; intensity = TheoreticalDistIntensities[maxIndex]; } return(true); } mzValue = x2; intensity = TheoreticalDistIntensities[maxIndex]; return(true); }
/// <summary> /// gets the intensity for a given mz. /// </summary> /// <remarks> /// We look for the intensity at a given m/z value in the raw data List mzs /// (the intensities are stored in the corresponding raw data intensity List intensities). /// If the value does not exist, we interpolate the intensities of points before and after this m/z value. /// </remarks> /// <param name="mz">the m/z value for which we want to find the intensity.</param> /// <param name="mzs">pointer to List with observed m/z values.</param> /// <param name="intensities">pointer to List with observed intensity values.</param> /// <returns> /// returns the intensity of the peak which has the given m/z. If the exact peak is not present, /// then we interpolate the intensity. If the m/z value is greater than the maximum mz or less, /// then the minimum m/z, 0 is returned. /// </returns> public double GetPointIntensity(double mz, List <double> mzs, List <double> intensities) { if ((Mz1 < mz && Mz2 < mz) || (Mz1 > mz && Mz2 > mz)) { var numpts = mzs.Count; if (LastPointIndex >= numpts) { LastPointIndex = -1; } //since points are more likely to be searched in order. if (LastPointIndex != -1 && Mz2 < mz) { if (LastPointIndex < numpts - 1 && mzs[LastPointIndex + 1] > mz) { LastPointIndex++; } else { LastPointIndex = PeakIndex.GetNearestBinary(mzs, mz, LastPointIndex, numpts - 1); } } else { LastPointIndex = PeakIndex.GetNearestBinary(mzs, mz, 0, numpts - 1); } if (LastPointIndex >= numpts) { return(0); } if (LastPointIndex < 0) { LastPointIndex = 0; } if (mzs[LastPointIndex] > mz) { while (LastPointIndex > 0 && mzs[LastPointIndex] > mz) { LastPointIndex--; } } else { while (LastPointIndex < numpts && mzs[LastPointIndex] < mz) { LastPointIndex++; } LastPointIndex--; } if (LastPointIndex == numpts - 1) { LastPointIndex = numpts - 2; } Mz1 = mzs[LastPointIndex]; Mz2 = mzs[LastPointIndex + 1]; Intensity1 = intensities[LastPointIndex]; Intensity2 = intensities[LastPointIndex + 1]; } if (Mz1.Equals(Mz2)) { return(Intensity1); } return((mz - Mz1) / (Mz2 - Mz1) * (Intensity2 - Intensity1) + Intensity1); }