private (List <LabeledMs2DataPoint>, int, int, int) SearchMS2Spectrum(IMsDataScanWithPrecursor <IMzSpectrum <IMzPeak> > ms2DataScan, Proteomics.Peptide peptide, int peptideCharge, PeptideSpectralMatch identification) { List <LabeledMs2DataPoint> result = new List <LabeledMs2DataPoint>(); int numMs2MassChargeCombinationsConsidered = 0; int numMs2MassChargeCombinationsThatAreIgnoredBecauseOfTooManyPeaks = 0; int numFragmentsIdentified = 0; if (ms2DataScan.MassSpectrum.Size == 0) { return(result, numMs2MassChargeCombinationsConsidered, numMs2MassChargeCombinationsThatAreIgnoredBecauseOfTooManyPeaks, numFragmentsIdentified); } // Key: mz value, Value: error var addedPeaks = new Dictionary <double, double>(); var countForThisMS2 = 0; var countForThisMS2a = 0; var scanWindowRange = ms2DataScan.ScanWindowRange; IHasChemicalFormula[] fragmentList = peptide.Fragment(fragmentTypesForCalibration, true).OfType <IHasChemicalFormula>().ToArray(); foreach (var fragment in fragmentList) { bool fragmentIdentified = false; bool computedIsotopologues = false; double[] masses = new double[0]; double[] intensities = new double[0]; // First look for monoisotopic masses, do not compute distribution spectrum! for (int chargeToLookAt = 1; chargeToLookAt <= peptideCharge; chargeToLookAt++) { var monoisotopicMZ = fragment.MonoisotopicMass.ToMz(chargeToLookAt); if (monoisotopicMZ > scanWindowRange.Maximum) { continue; } if (monoisotopicMZ < scanWindowRange.Minimum) { break; } var closestPeakMZ = ms2DataScan.MassSpectrum.GetClosestPeakXvalue(monoisotopicMZ); if (mzToleranceForMs2Search.Within(closestPeakMZ.Value, monoisotopicMZ) && !computedIsotopologues) { var dist = IsotopicDistribution.GetDistribution(fragment.ThisChemicalFormula, fineResolutionForIsotopeDistCalculation, 0.001); masses = dist.Masses.ToArray(); intensities = dist.Intensities.ToArray(); Array.Sort(intensities, masses, Comparer <double> .Create((x, y) => y.CompareTo(x))); computedIsotopologues = true; break; } } if (computedIsotopologues) { bool startingToAdd = false; for (int chargeToLookAt = 1; chargeToLookAt <= peptideCharge; chargeToLookAt++) { if (masses.First().ToMz(chargeToLookAt) > scanWindowRange.Maximum) { continue; } if (masses.Last().ToMz(chargeToLookAt) < scanWindowRange.Minimum) { break; } var trainingPointsToAverage = new List <LabeledMs2DataPoint>(); foreach (double a in masses) { double theMZ = a.ToMz(chargeToLookAt); var npwr = ms2DataScan.MassSpectrum.NumPeaksWithinRange(mzToleranceForMs2Search.GetMinimumValue(theMZ), mzToleranceForMs2Search.GetMaximumValue(theMZ)); if (npwr == 0) { break; } numMs2MassChargeCombinationsConsidered++; if (npwr > 1) { numMs2MassChargeCombinationsThatAreIgnoredBecauseOfTooManyPeaks++; continue; } var closestPeakIndex = ms2DataScan.MassSpectrum.GetClosestPeakIndex(theMZ); var closestPeakMZ = ms2DataScan.MassSpectrum.XArray[closestPeakIndex.Value]; if (!addedPeaks.ContainsKey(closestPeakMZ)) { addedPeaks.Add(closestPeakMZ, Math.Abs(closestPeakMZ - theMZ)); trainingPointsToAverage.Add(new LabeledMs2DataPoint(closestPeakMZ, double.NaN, double.NaN, double.NaN, Math.Log(ms2DataScan.MassSpectrum.YArray[closestPeakIndex.Value]), theMZ, null)); } } // If started adding and suddnely stopped, go to next one, no need to look at higher charges if (trainingPointsToAverage.Count == 0 && startingToAdd) { break; } if (trainingPointsToAverage.Count < Math.Min(minMS2isotopicPeaksNeededForConfirmedIdentification, intensities.Count())) { } else { startingToAdd = true; if (!fragmentIdentified) { fragmentIdentified = true; numFragmentsIdentified += 1; } countForThisMS2 += trainingPointsToAverage.Count; countForThisMS2a++; result.Add(new LabeledMs2DataPoint(trainingPointsToAverage.Select(b => b.mz).Average(), ms2DataScan.RetentionTime, Math.Log(ms2DataScan.TotalIonCurrent), ms2DataScan.InjectionTime.HasValue ? Math.Log(ms2DataScan.InjectionTime.Value) : double.NaN, trainingPointsToAverage.Select(b => b.logIntensity).Average(), trainingPointsToAverage.Select(b => b.expectedMZ).Average(), identification)); } } } } return(result, numMs2MassChargeCombinationsConsidered, numMs2MassChargeCombinationsThatAreIgnoredBecauseOfTooManyPeaks, numFragmentsIdentified); }