/// <summary> /// Finds the highest peak from the raw data lists withing the specified m/z range. /// </summary> /// <param name="startMz">minimum m\z at which to look for the peak</param> /// <param name="stopMz">maximum m\z at which to look for the peak.</param> /// <param name="peak"> instance whose mz and intensity are set to the peak that is found.</param> /// <remarks>The function only sets the mz, intensity of the peak, not the other members (SN, FWHM etc).</remarks> public void FindPeak(double startMz, double stopMz, out ThrashV1Peak peak) { peak = new ThrashV1Peak(-1); var width = (stopMz - startMz) / 2; var foundExistingPeak = GetClosestPeak(startMz + width, width, out peak); if (foundExistingPeak) { // peak already exists. Send it back. } else { // peak doesn't exist. Lets find a starting index to start looking at. // perhaps there was a peak there. var foundPeak = GetClosestPeakFromAll(startMz + width, width, out peak); var numPts = MzList.Count; if (foundPeak) { var index = peak.DataIndex; while (index > 0 && MzList[index] >= startMz) { var intensity = IntensityList[index]; var mz = MzList[index]; if (intensity > peak.Intensity && mz <= stopMz) { peak.Mz = mz; peak.Intensity = intensity; peak.DataIndex = index; } index--; } index = peak.DataIndex; while (index < numPts && MzList[index] <= stopMz) { var intensity = IntensityList[index]; if (intensity > peak.Intensity) { var mz = MzList[index]; peak.Mz = mz; peak.Intensity = intensity; peak.DataIndex = index; } index++; } if (peak.Intensity <= 0) { peak.Mz = 0; } } else { var startIndex = PeakIndex.GetNearestBinary(MzList, startMz, 0, numPts - 1); if (startIndex > numPts - 1) { startIndex = numPts - 1; } if (startIndex < 0) { startIndex = 0; } if (MzList[startIndex] > startMz) { while (startIndex > 0 && MzList[startIndex] > startMz) { startIndex--; } } else { while (startIndex < numPts && MzList[startIndex] < startMz) { startIndex++; } startIndex--; } for (var i = startIndex; i < numPts; i++) { var mz = MzList[i]; var intensity = IntensityList[i]; if (mz > stopMz) { break; } if (intensity > peak.Intensity) { peak.Mz = mz; peak.Intensity = intensity; peak.DataIndex = i; } } } } }
/// <summary> /// Function discovers peaks in the m/z and intensity vectors supplied within the supplied m/z window. /// </summary> /// <param name="mzList">is the pointer to List of m/z values</param> /// <param name="intensityList">is the pointer to List of intensity values</param> /// <param name="startMz">minimum m/z of the peak.</param> /// <param name="stopMz">maximum m/z of the peak.</param> /// <returns>returns the number of peaks that were found in the vectors.</returns> /// <remarks> /// The function uses <see cref="PeakStatistician.FindFwhm" />, and /// <see cref="PeakStatistician.FindSignalToNoise" /> /// to discover the full width at half maximum and signal to noise values for a peak. The signal to noise of a /// peak is tested against the threshold value before its accepted as a peak. All peaks are used during the process, /// but once generated only those which are above <see cref="_peakIntensityThreshold" /> are tested for peptidicity by /// Deconvolution.HornMassTransform /// </remarks> public int DiscoverPeaks(List <double> mzList, List <double> intensityList, double startMz, double stopMz) { if (intensityList.Count < 1) { return(0); } PeakData.Clear(); var numDataPts = intensityList.Count; var startIndex = PeakIndex.GetNearestBinary(mzList, startMz, 0, numDataPts - 1); var stopIndex = PeakIndex.GetNearestBinary(mzList, stopMz, startIndex, numDataPts - 1); if (startIndex <= 0) { startIndex = 1; } if (stopIndex >= mzList.Count - 2) { stopIndex = mzList.Count - 2; } for (var index = startIndex; index <= stopIndex; index++) { double fwhm = -1; var currentIntensity = intensityList[index]; var lastIntensity = intensityList[index - 1]; var nextIntensity = intensityList[index + 1]; var currentMz = mzList[index]; if (_arePeaksCentroided) { if (currentIntensity >= _peakIntensityThreshold) { var mz = mzList[index]; var signalToNoise = currentIntensity / _peakIntensityThreshold; fwhm = 0.6; PeakData.AddPeak(new ThrashV1Peak(mz, currentIntensity, signalToNoise, PeakData.GetNumPeaks(), index, fwhm)); } } else { //three point peak picking. Check if peak is greater than both the previous and next points if (currentIntensity >= lastIntensity && currentIntensity >= nextIntensity && currentIntensity >= _peakIntensityThreshold) { //See if the peak meets the conditions. //The peak data will be found at _transformData.begin()+i+1. double signalToNoise; if (!_isDataThresholded) { signalToNoise = PeakStatistician.FindSignalToNoise(currentIntensity, intensityList, index); } else { signalToNoise = currentIntensity / _backgroundIntensity; } // Run Full-Width Half-Max algorithm to try and squeak out a higher SN if (signalToNoise < _signalToNoiseThreshold) { //double mz = mzList[index]; fwhm = PeakStatistician.FindFwhm(mzList, intensityList, index, signalToNoise); if (fwhm > 0 && fwhm < 0.5) { var iLow = PeakIndex.GetNearestBinary(mzList, currentMz - fwhm, 0, index); var iHigh = PeakIndex.GetNearestBinary(mzList, currentMz + fwhm, index, stopIndex); var lowIntensity = intensityList[iLow]; var highIntensity = intensityList[iHigh]; var sumIntensity = lowIntensity + highIntensity; if (sumIntensity > 0) { signalToNoise = 2.0 * currentIntensity / sumIntensity; } else { signalToNoise = 10; } } } // Found a peak if (signalToNoise >= _signalToNoiseThreshold) { // Find a more accurate m/z location of the peak. var fittedPeak = _peakFit.Fit(index, mzList, intensityList); if (fwhm.Equals(-1)) { fwhm = PeakStatistician.FindFwhm(mzList, intensityList, index, signalToNoise); } if (fwhm > 0) { PeakData.AddPeak(new ThrashV1Peak(fittedPeak, currentIntensity, signalToNoise, PeakData.GetNumPeaks(), index, fwhm)); } // move beyond peaks have the same intensity. var incremented = false; while (index < numDataPts && intensityList[index].Equals(currentIntensity)) { incremented = true; index++; } if (index > 0 && index < numDataPts && incremented) { index--; } } } } } PeakData.MzList = mzList; PeakData.IntensityList = intensityList; return(PeakData.GetNumPeaks()); }