protected override void IterateOverScans() { DeconMSnResults.Clear(); _scanCounter = 0; var resultCounter = 0; foreach (var scanSet in Run.ScanSetCollection.ScanSetList) { _scanCounter++; if (BackgroundWorker != null) { if (BackgroundWorker.CancellationPending) { return; } } //check ms level var currentMSLevel = Run.GetMSLevel(scanSet.PrimaryScanNumber); if (currentMSLevel == 1) { Run.ResultCollection.IsosResultBin.Clear(); Run.CurrentScanSet = scanSet; MSGenerator.Execute(Run.ResultCollection); _currentMS1XYValues = new XYData { Xvalues = Run.XYData.Xvalues, Yvalues = Run.XYData.Yvalues }; _currentMS1TICIntensity = Run.GetTICFromInstrumentInfo(scanSet.PrimaryScanNumber); PeakDetector.Execute(Run.ResultCollection); _currentMS1Peaks = new List <Peak>(Run.PeakList); } else if (currentMSLevel == 2) { if (_currentMS1Peaks == null || _currentMS1Peaks.Count == 0) { continue; } var precursorInfo = Run.GetPrecursorInfo(scanSet.PrimaryScanNumber); Run.CurrentScanSet = scanSet; var inaccurateParentMZ = precursorInfo.PrecursorMZ; resultCounter++; var deconMSnResult = new DeconMSnResult { ParentScan = Run.GetParentScan(scanSet.PrimaryScanNumber) }; deconMSnResult.IonInjectionTime = Run.GetIonInjectionTimeInMilliseconds(deconMSnResult.ParentScan); deconMSnResult.ScanNum = scanSet.PrimaryScanNumber; deconMSnResult.OriginalMZTarget = inaccurateParentMZ; deconMSnResult.ParentScanTICIntensity = _currentMS1TICIntensity; MSGenerator.Execute(Run.ResultCollection); var lowerMZ = inaccurateParentMZ - 1.1; var upperMZ = inaccurateParentMZ + 1.1; var dataIsCentroided = Run.IsDataCentroided(scanSet.PrimaryScanNumber); if (dataIsCentroided) { _ms2PeakDetectorForCentroidData.Execute(Run.ResultCollection); } else { _ms2PeakDetectorForProfileData.Execute(Run.ResultCollection); } var ms2Peaks = new List <Peak>(Run.PeakList); var filteredMS1Peaks = _currentMS1Peaks.Where(p => p.XValue > lowerMZ && p.XValue < upperMZ).ToList(); IsotopicProfile selectedMS1Feature = null; for (var attemptNum = 0; attemptNum < NumMaxAttemptsAtLowIntensitySpecies; attemptNum++) { var candidateMS1Features = GetCandidateMS1Features(inaccurateParentMZ, filteredMS1Peaks); //if none were found, will regenerate MS1 spectrum and find peaks again if (candidateMS1Features.Count == 0) { var numSummed = attemptNum * 2 + 3; var ms1Scan = precursorInfo.PrecursorScan; var ms1ScanSet = new ScanSetFactory().CreateScanSet(Run, ms1Scan, numSummed); //get MS1 mass spectrum again. This time sum spectra Run.CurrentScanSet = ms1ScanSet; MSGenerator.Execute(Run.ResultCollection); //run MS1 peak detector, with greater sensitivity var isLastAttempt = attemptNum >= NumMaxAttemptsAtLowIntensitySpecies - 2; //need to do -2 because of the way the loop advances the counter. if (isLastAttempt) { _superSensitiveMS1PeakDetector.MinX = lowerMZ; _superSensitiveMS1PeakDetector.MaxX = upperMZ; _superSensitiveMS1PeakDetector.Execute(Run.ResultCollection); filteredMS1Peaks = new List <Peak>(Run.PeakList); } else { _moreSensitiveMS1PeakDetector.Execute(Run.ResultCollection); var moreSensitiveMS1Peaks = new List <Peak>(Run.PeakList); filteredMS1Peaks = moreSensitiveMS1Peaks.Where(p => p.XValue > lowerMZ && p.XValue < upperMZ).ToList(); } } else if (candidateMS1Features.Count == 1) { selectedMS1Feature = candidateMS1Features.First(); break; //we found something, so no need for any further attempts } else { var highQualityCandidates = candidateMS1Features.Where(p => p.Score < 0.15).ToList(); if (highQualityCandidates.Count == 0) { selectedMS1Feature = candidateMS1Features.OrderByDescending(p => p.IntensityMostAbundantTheor).First(); } else if (highQualityCandidates.Count == 1) { selectedMS1Feature = highQualityCandidates.First(); } else { selectedMS1Feature = highQualityCandidates.OrderByDescending(p => p.IntensityMostAbundantTheor).First(); } deconMSnResult.ExtraInfo = "Warning - multiple MSFeatures found for target parent MZ"; break; //we found something, so no need for any further attempts } } if (selectedMS1Feature != null) { deconMSnResult.ParentMZ = selectedMS1Feature.MonoPeakMZ; deconMSnResult.ParentChargeState = selectedMS1Feature.ChargeState; deconMSnResult.ParentIntensity = selectedMS1Feature.IntensityMostAbundantTheor; deconMSnResult.IntensityAggregate = selectedMS1Feature.IntensityMostAbundantTheor; deconMSnResult.IsotopicProfile = selectedMS1Feature; } else { var candidatePeaks = new List <Peak>(); foreach (var peak in filteredMS1Peaks) { var currentDiff = Math.Abs(peak.XValue - inaccurateParentMZ); var toleranceInMZ = ToleranceInPPM * peak.XValue / 1e6; if (currentDiff < toleranceInMZ) { candidatePeaks.Add(peak); } } Peak selectedPeak = null; if (candidatePeaks.Count == 0) { //cannot even find a suitable MS1 peak. So can't do anything } else if (candidatePeaks.Count == 1) { selectedPeak = candidatePeaks.First(); } else { selectedPeak = candidatePeaks.OrderByDescending(p => p.Height).First(); } if (selectedPeak != null) { deconMSnResult.ParentMZ = selectedPeak.XValue; deconMSnResult.ParentChargeState = 1; //not sure what charge I should assign... Ask SangTae deconMSnResult.ParentIntensity = selectedPeak.Height; deconMSnResult.IsotopicProfile = null; deconMSnResult.ExtraInfo = "Failure code 1: No MSFeature, but peak found"; } else { deconMSnResult.ParentMZ = precursorInfo.PrecursorMZ; //could not find the accurate parentMZ, so just report what the instrument found. deconMSnResult.ParentChargeState = 1; //not sure what charge I should assign... Ask SangTae deconMSnResult.ParentIntensity = 0; deconMSnResult.IsotopicProfile = null; deconMSnResult.ExtraInfo = "Failure code 2: No MSFeature or peak found"; } } //Build export data. var outputString = GetMGFOutputString(Run, scanSet.PrimaryScanNumber, deconMSnResult, ms2Peaks); var includeHeader = resultCounter == 1; var summaryString = GetSummaryString(deconMSnResult, includeHeader); var parentProfileString = GetParentProfileString(deconMSnResult, includeHeader); if (ExportData) { WriteOutMainData(outputString); WriteOutDeconMSnSummary(summaryString); if (IsParentProfileDataExported) { WriteOutParentProfileInfoString(parentProfileString); } } if (deconMSnResult.ParentIntensity > 0) { DeconMSnResults.Add(deconMSnResult); } } else { throw new ApplicationException( "DeconMSn only works on MS1 and MS2 data; You are attempting MS3"); } ReportProgress(); } }