/// <summary> /// Returns a 'peak-to-the-left' of the monoisotopic peak if: 1) it exists and 2) it is above the user provided relative intensity /// </summary> /// <param name="monoPeak"></param> /// <param name="chargeState"></param> /// <param name="peakList"></param> /// <param name="minRelIntensityForFlag"></param> /// <returns></returns> public MSPeak LookforPeakToTheLeftOfMonoPeak(MSPeak monoPeak, int chargeState, List <Peak> peakList, double minRelIntensityForFlag) { double mzTol = monoPeak.Width; var targetMZ = monoPeak.XValue - (1.003 / (double)chargeState); var foundLeftOfMonoPeaks = PeakUtilities.GetPeaksWithinTolerance(peakList, targetMZ, mzTol); //if found a peak to the left, will return that peak. If if (foundLeftOfMonoPeaks.Count == 0) { return(null); } var peakToTheLeft = foundLeftOfMonoPeaks.OrderByDescending(p => p.Height).First() as MSPeak; if (peakToTheLeft == null) { return(null); } if (peakToTheLeft.Height > monoPeak.Height * MinRatioToGiveFlag) { return(peakToTheLeft); } return(null); }
private List <Peak> FilterPeaksBasedOnBasePeakList(List <Peak> basePeaklist, List <Peak> inputPeakList) { var trimmedPeakList = new List <Peak>(); foreach (var peak in basePeaklist) { var mzTolerance = _toleranceInPPM * peak.XValue / 1e6; var foundPeaks = PeakUtilities.GetPeaksWithinTolerance(inputPeakList, peak.XValue, mzTolerance); if (foundPeaks.Count == 1) { trimmedPeakList.Add(foundPeaks.First()); } else if (foundPeaks.Count > 1) { trimmedPeakList.Add(foundPeaks.OrderByDescending(p => p.Height).First()); } } //if we can't find any observed peaks, we won't trim anything. Just return the original list if (!trimmedPeakList.Any()) { return(basePeaklist); } return(trimmedPeakList); }
public void FindPeaksWithinTolerance_highMZRangeTest() { List <IPeak> peakList = TestUtilities.GeneratePeakList(new ScanSet(6005)); List <IPeak> filteredList = PeakUtilities.GetPeaksWithinTolerance(peakList, 1500, 100); Assert.AreEqual(809, peakList.Count); TestUtilities.DisplayPeaks(filteredList); Assert.AreEqual(115, filteredList.Count); }
private void GetIsotopicProfilePeaks(List <Peak> peakList, int chargeState, double monoMass, ref IsotopicProfile inputProfile) { double toleranceInPPM = 20; var tff = new BasicTFF(toleranceInPPM); var theorProfile = new IsotopicProfile(); theorProfile.MonoIsotopicMass = monoMass; theorProfile.ChargeState = chargeState; theorProfile.MonoPeakMZ = monoMass / chargeState + Globals.PROTON_MASS; //a hack to guess how many peaks to include in the theor isotopic profile int numPeaksToIncludeInProfile = (int)Math.Round(Math.Max(3, 3 + (monoMass - 1000) / 1000)); double monoPeakMZ = monoMass / chargeState + Globals.PROTON_MASS; for (int i = 0; i < numPeaksToIncludeInProfile; i++) { var peak = new MSPeak(); peak.XValue = monoPeakMZ + i * Globals.MASS_DIFF_BETWEEN_ISOTOPICPEAKS / chargeState; if (i == 0) { peak.Height = 1; } else { peak.Height = 0; } theorProfile.Peaklist.Add(peak); } var foundIso = tff.FindMSFeature(peakList, theorProfile); if (foundIso == null) { var monoPeak = PeakUtilities.GetPeaksWithinTolerance(peakList, monoPeakMZ, toleranceInPPM).OrderByDescending(p => p.Height).FirstOrDefault(); if (monoPeak != null) { inputProfile.Peaklist.Add((MSPeak)monoPeak); } } else { inputProfile.Peaklist = new List <MSPeak>(foundIso.Peaklist); } }
/// <summary> /// Calculates mass error based on the theoretical most intense peak. /// </summary> /// <returns> This returns the mass error between a theoretical and observed peak. Nota bene the is MASS, not m/z /// If no peak is detected, we return the mass error 999999. This should be interpreted as a null value.</returns> protected double TheorMostIntensePeakMassError(IsotopicProfile theoreticalIso, IsotopicProfile observedIso, int chargeState) { var theoreticalMostIntensePeak = theoreticalIso.getMostIntensePeak(); //find peak in obs data var mzTolerance = WorkflowParameters.MSToleranceInPPM * theoreticalMostIntensePeak.XValue / 1e6; var foundPeaks = PeakUtilities.GetPeaksWithinTolerance(new List <Peak>(observedIso.Peaklist), theoreticalMostIntensePeak.XValue, mzTolerance); if (foundPeaks.Count == 0) { return(999999); } var obsXValue = foundPeaks.OrderByDescending(p => p.Height).First().XValue; //order the peaks and take the first (most intense) one. return((theoreticalMostIntensePeak.XValue * chargeState) - (obsXValue * chargeState)); }
private List <Peak> ApplySmartTrimming(List <Peak> theorPeakList, List <Peak> massSpectrumPeakList) { var trimmedPeakList = new List <Peak>(); foreach (var peak in theorPeakList) { var mzTolerance = _toleranceInPPM * peak.XValue / 1e6; var foundPeaks = PeakUtilities.GetPeaksWithinTolerance(massSpectrumPeakList, peak.XValue, mzTolerance); if (foundPeaks.Any()) { trimmedPeakList.Add(peak); } } //if we can't find any observed peaks, we won't trim anything. Just return the original list if (!trimmedPeakList.Any()) { return(theorPeakList); } return(trimmedPeakList); }
public double GetFit( List <Peak> theorPeakList, List <Peak> observedPeakList, double minIntensityForScore, double toleranceInPPM, int numPeaksToTheLeftForScoring, out int ionCountUsed) { Utilities.IqLogger.IqLogger.LogTrace("Min Intensity For Scoring: " + minIntensityForScore); Utilities.IqLogger.IqLogger.LogTrace("PPM Tolerance: " + toleranceInPPM); ionCountUsed = 0; var theorIntensitiesUsedInCalc = new List <double>(); var observedIntensitiesUsedInCalc = new List <double>(); //first gather all the intensities from theor and obs peaks var maxTheorIntensity = double.MinValue; foreach (var peak in theorPeakList) { if (peak.Height > maxTheorIntensity) { maxTheorIntensity = peak.Height; } } for (var index = 0; index < theorPeakList.Count; index++) { var peak = theorPeakList[index]; var overrideMinIntensityCutoff = index < numPeaksToTheLeftForScoring; if (peak.Height > minIntensityForScore || overrideMinIntensityCutoff) { theorIntensitiesUsedInCalc.Add(peak.Height); Utilities.IqLogger.IqLogger.LogTrace("Theoretical Peak Selected! Peak Height: "+ peak.Height + " Peak X-Value: " + peak.XValue); //find peak in obs data var mzTolerance = toleranceInPPM * peak.XValue / 1e6; var foundPeaks = PeakUtilities.GetPeaksWithinTolerance(observedPeakList, peak.XValue, mzTolerance); double obsIntensity; if (foundPeaks.Count == 0) { Utilities.IqLogger.IqLogger.LogTrace("No Observed Peaks Found Within Tolerance"); obsIntensity = 0; } else if (foundPeaks.Count == 1) { obsIntensity = foundPeaks.First().Height; Utilities.IqLogger.IqLogger.LogTrace("Observed Peak Selected! Peak Height: "+ foundPeaks[0].Height + " Peak X-Value " + foundPeaks[0].XValue); } else { obsIntensity = foundPeaks.OrderByDescending(p => p.Height).First().Height; Utilities.IqLogger.IqLogger.LogTrace("Observed Peak Selected! Peak Height: "+ foundPeaks[0].Height + " Peak X-Value " + foundPeaks[0].XValue); } observedIntensitiesUsedInCalc.Add(obsIntensity); } else { Utilities.IqLogger.IqLogger.LogTrace("Theoretical Peak Not Selected! Peak Height: "+ peak.Height + " Peak X-Value: " + peak.XValue); } } //the minIntensityForScore is too high and no theor peaks qualified. This is bad. But we don't //want to throw errors here if (theorIntensitiesUsedInCalc.Count == 0) { Utilities.IqLogger.IqLogger.LogTrace("No peaks meet minIntensityForScore."); return(1.0); } var maxObs = observedIntensitiesUsedInCalc.Max(); if (Math.Abs(maxObs) < float.Epsilon) { maxObs = double.PositiveInfinity; } Utilities.IqLogger.IqLogger.LogTrace("Max Observed Intensity: " + maxObs); var normalizedObs = observedIntensitiesUsedInCalc.Select(p => p / maxObs).ToList(); var maxTheor = theorIntensitiesUsedInCalc.Max(); var normalizedTheor = theorIntensitiesUsedInCalc.Select(p => p / maxTheor).ToList(); Utilities.IqLogger.IqLogger.LogTrace("Max Theoretical Intensity: " + maxTheor); //foreach (var val in normalizedObs) //{ // Console.WriteLine(val); //} //Console.WriteLine(); //foreach (var val in normalizedTheor) //{ // Console.WriteLine(val); //} double sumSquareOfDiffs = 0; double sumSquareOfTheor = 0; for (var i = 0; i < normalizedTheor.Count; i++) { var diff = normalizedObs[i] - normalizedTheor[i]; sumSquareOfDiffs += (diff * diff); sumSquareOfTheor += (normalizedTheor[i] * normalizedTheor[i]); Utilities.IqLogger.IqLogger.LogTrace("Normalized Observed: " + normalizedObs[i]); Utilities.IqLogger.IqLogger.LogTrace("Normalized Theoretical: " + normalizedTheor[i]); Utilities.IqLogger.IqLogger.LogTrace("Iterator: " + i + " Sum of Squares Differences: " + sumSquareOfDiffs + " Sum of Squares Theoretical: " + sumSquareOfTheor); } ionCountUsed = normalizedTheor.Count; var fitScore = sumSquareOfDiffs / sumSquareOfTheor; if (double.IsNaN(fitScore) || fitScore > 1) { fitScore = 1; } else { // Future possibility (considered in January 2014): // Normalize the fit score by the number of theoretical ions // fitScore /= ionCountUsed; } Utilities.IqLogger.IqLogger.LogTrace("Fit Score: " + fitScore); return(fitScore); }
public virtual IsotopicProfile FindMSFeature(List <Peak> peakList, IsotopicProfile theorFeature) { Check.Require(theorFeature != null, "Theoretical feature hasn't been defined."); if (theorFeature == null) { return(null); } Check.Require(theorFeature.Peaklist != null && theorFeature.Peaklist.Count > 0, "Theoretical feature hasn't been defined."); var outFeature = new IsotopicProfile { ChargeState = theorFeature.ChargeState }; var indexOfMaxTheorPeak = theorFeature.GetIndexOfMostIntensePeak(); var toleranceInMZ = theorFeature.getMonoPeak().XValue *ToleranceInPPM / 1e6; var foundMatchingMaxPeak = false; double massDefect = 0; // this is the m/z diff between the max peak of theor feature and the max peak of the experimental feature var failedResult = false; for (var i = indexOfMaxTheorPeak; i >= 0; i--) { //find experimental peak(s) within range var peaksWithinTol = PeakUtilities.GetPeaksWithinTolerance(peakList, theorFeature.Peaklist[i].XValue, toleranceInMZ); if (i == indexOfMaxTheorPeak) { foundMatchingMaxPeak = peaksWithinTol.Count > 0; } if (!foundMatchingMaxPeak) // can't even find the observed peak that matches the most intense theor peak. { failedResult = true; break; } if (peaksWithinTol.Count == 0) { if (NeedMonoIsotopicPeak) { //here, we are looking to the left of most intense theor peak. If we have the prerequisite of finding the monoIsotopic peak and fail here, we'll return a failed result failedResult = true; } break; // stop looking to the left of the most intense peak. } if (peaksWithinTol.Count == 1) { if (outFeature.Peaklist.Count == 0) { outFeature.Peaklist.Add((MSPeak)peaksWithinTol[0]); } else { outFeature.Peaklist.Insert(0, (MSPeak)peaksWithinTol[0]); } } else // when we have several peaks within tolerance, we'll need to decide what to do { MSPeak bestPeak; if (i == indexOfMaxTheorPeak) //when matching to most intense peak, we will use the most intense peak { bestPeak = (MSPeak)findMostIntensePeak(peaksWithinTol); } else { bestPeak = (MSPeak)findClosestToXValue(peaksWithinTol, theorFeature.Peaklist[i].XValue - massDefect); } if (outFeature.Peaklist.Count == 0) { outFeature.Peaklist.Add(bestPeak); } else { outFeature.Peaklist.Insert(0, bestPeak); } } if (i == indexOfMaxTheorPeak) //when matching to most intense peak, we will get the mass defect using the most intense peak { massDefect = theorFeature.Peaklist[i].XValue - outFeature.Peaklist[0].XValue; } } //------------------------- look right ------------------------------------------- for (var i = indexOfMaxTheorPeak + 1; i < theorFeature.Peaklist.Count; i++) //start one peak to the right of the max intense theor peak { var peaksWithinTol = PeakUtilities.GetPeaksWithinTolerance(peakList, theorFeature.Peaklist[i].XValue, toleranceInMZ); if (peaksWithinTol.Count == 0) { if (i == indexOfMaxTheorPeak + 1) // first peak to the right of the max peak. We need this one or we declare it to be a failure (= null) { failedResult = true; } break; // finished. Exit loop. } if (peaksWithinTol.Count == 1) { outFeature.Peaklist.Add((MSPeak)peaksWithinTol[0]); //here, we tack peaks onto the profile } else //two or more peaks are within tolerance. Need to get the best one, which is based on the distance from the { outFeature.Peaklist.Add((MSPeak)findClosestToXValue(peaksWithinTol, theorFeature.Peaklist[i].XValue - massDefect)); } } //for higher mass peptides, we will return the profile if there is 2 or more peaks, regardless if none are found to the right of the most abundant if (indexOfMaxTheorPeak > 0 && outFeature.Peaklist.Count > 1) { failedResult = false; } if (failedResult) { return(null); // return a null Isotopic profile, indicating a failed result } addMassInfoToIsotopicProfile(theorFeature, outFeature); return(outFeature); }
public static int GetChargeState(XYData rawData, List <Peak> peakList, MSPeak peak) { //look in rawData to the left (-0.1) and right (+1.1) of peak var minus = 0.1; var plus = 1.1; double fwhm = peak.Width; var leftIndex = MathUtils.GetClosest(rawData.Xvalues, peak.XValue - fwhm - minus); var rightIndex = MathUtils.GetClosest(rawData.Xvalues, peak.XValue + fwhm + plus); var filteredXYData = getFilteredXYData(rawData, leftIndex, rightIndex); var minMZ = filteredXYData.Xvalues[0]; var maxMZ = filteredXYData.Xvalues[filteredXYData.Xvalues.Length - 1]; double sumOfDiffsBetweenValues = 0; double pointCounter = 0; for (var i = 0; i < filteredXYData.Xvalues.Length - 1; i++) { var y1 = filteredXYData.Yvalues[i]; var y2 = filteredXYData.Yvalues[i + 1]; if (y1 > 0 && y2 > 0) { var x1 = filteredXYData.Xvalues[i]; var x2 = filteredXYData.Xvalues[i + 1]; sumOfDiffsBetweenValues += (x2 - x1); pointCounter++; } } int numL; if (pointCounter > 5) { var averageDiffBetweenPoints = sumOfDiffsBetweenValues / pointCounter; numL = (int)Math.Ceiling((maxMZ - minMZ) / averageDiffBetweenPoints); numL = (int)(numL + numL * 0.1); //numL = 445; } else { var numPoints = rightIndex - leftIndex + 1; var desiredNumPoints = 256; var pointMultiplier = (int)Math.Ceiling(desiredNumPoints / (double)numPoints); if (numPoints < 5) { return(-1); } if (numPoints < desiredNumPoints) { pointMultiplier = Math.Max(5, pointMultiplier); numL = pointMultiplier * numPoints; } else { numL = numPoints; } } //Console.WriteLine("Number of points in interpolated data= " + numL); var interpolationFunction = new alglib.spline1d.spline1dinterpolant(); var sw = new System.Diagnostics.Stopwatch(); sw.Start(); alglib.spline1d.spline1dbuildcubic( filteredXYData.Xvalues, filteredXYData.Yvalues, filteredXYData.Xvalues.Length, 1, +1, 1, -1, interpolationFunction); sw.Stop(); //Console.WriteLine("spline time = " + sw.ElapsedMilliseconds); // DisplayXYVals(filteredXYData); var evenlySpacedXYData = new XYData { Xvalues = new double[numL], Yvalues = new double[numL] }; for (var i = 0; i < numL; i++) { var xVal = (minMZ + ((maxMZ - minMZ) * i) / numL); var yVal = alglib.spline1d.spline1dcalc(interpolationFunction, xVal); evenlySpacedXYData.Xvalues[i] = xVal; evenlySpacedXYData.Yvalues[i] = yVal; } //Console.WriteLine(); //DisplayXYVals(evenlySpacedXYData); var autoCorrScores = ACss(evenlySpacedXYData.Yvalues); //var tempXYData = new XYData //{ // Xvalues = autoCorrScores, // Yvalues = autoCorrScores //}; // DisplayXYVals(tempXYData); var startingIndex = 0; while (startingIndex < numL - 1 && autoCorrScores[startingIndex] > autoCorrScores[startingIndex + 1]) { startingIndex++; } double bestAutoCorrScore = -1; var bestChargeState = -1; GetHighestChargeStatePeak(minMZ, maxMZ, startingIndex, autoCorrScores, MaxCharge, ref bestAutoCorrScore, ref bestChargeState); if (bestChargeState == -1) { return(-1); } var returnChargeStateVal = -1; var chargeStateList = new List <int>(); GenerateChargeStateData(minMZ, maxMZ, startingIndex, autoCorrScores, MaxCharge, bestAutoCorrScore, chargeStateList); for (var i = 0; i < chargeStateList.Count; i++) { var tempChargeState = chargeStateList[i]; var skip = false; for (var j = 0; j < i; j++) { if (chargeStateList[j] == tempChargeState) { skip = true; break; } } if (skip) { continue; } if (tempChargeState > 0) { var anotherPeak = peak.XValue + (1.003d / tempChargeState); var foundPeak = PeakUtilities.GetPeaksWithinTolerance(peakList, anotherPeak, peak.Width).Count > 0; if (foundPeak) { returnChargeStateVal = tempChargeState; if (peak.XValue * tempChargeState < 3000) { break; } return(tempChargeState); } } } return(returnChargeStateVal); //StringBuilder sb = new StringBuilder(); //foreach (var item in chargeStatesAndScores) //{ // sb.Append(item.Key + "\t" + item.Value + "\n"); //} //Console.WriteLine(sb.ToString()); //StringBuilder sb = new StringBuilder(); //foreach (var item in autoCorrScores) //{ // sb.Append(item); // sb.Append(Environment.NewLine); //} //Console.WriteLine(sb.ToString()); //then extract AutoCorrelation scores (ACss) //determine highest charge state peak (?) }
public void AppendO16O18PeakInfo(List <Peak> peakList, List <IsosResult> resultList) { //iterate over each ms feature foreach (var isosResult in resultList) { if (!(isosResult is O16O18IsosResult msFeature)) { continue; } if (msFeature.IsotopicProfile == null) { continue; } var monoMZ = msFeature.IsotopicProfile.GetMZ(); var mzMinusDaltons = monoMZ - (MASS_UNIT_BETWEEN_ISO * 4 / msFeature.IsotopicProfile.ChargeState); var mzPlusDaltons = monoMZ + (MASS_UNIT_BETWEEN_ISO * 4 / msFeature.IsotopicProfile.ChargeState); var mzPlusTwoDaltons = monoMZ + (MASS_UNIT_BETWEEN_ISO * 2 / msFeature.IsotopicProfile.ChargeState); double toleranceInPPM = 50; var toleranceInMZ = toleranceInPPM * monoMZ / 1e6; var minusPeaksWithinTol = PeakUtilities.GetPeaksWithinTolerance(peakList, mzMinusDaltons, toleranceInMZ); var plusPeaksWithinTol = PeakUtilities.GetPeaksWithinTolerance(peakList, mzPlusDaltons, toleranceInMZ); var twoDaltonsPlusPeaksWithinTol = PeakUtilities.GetPeaksWithinTolerance(peakList, mzPlusTwoDaltons, toleranceInMZ); var fourDaltonsMinusPeak = GetBestPeak(minusPeaksWithinTol, mzMinusDaltons); var fourDaltonsPlusPeak = GetBestPeak(plusPeaksWithinTol, mzPlusDaltons); var twoDaltonsPlusPeak = GetBestPeak(twoDaltonsPlusPeaksWithinTol, mzPlusTwoDaltons); if (fourDaltonsMinusPeak != null) { msFeature.MonoMinus4Abundance = fourDaltonsMinusPeak.Height; } else { msFeature.MonoMinus4Abundance = 0; } if (fourDaltonsPlusPeak != null) { msFeature.MonoPlus4Abundance = fourDaltonsPlusPeak.Height; } else { msFeature.MonoPlus4Abundance = 0; } if (twoDaltonsPlusPeak != null) { msFeature.MonoPlus2Abundance = twoDaltonsPlusPeak.Height; } else { msFeature.MonoPlus2Abundance = 0; } } }