public bool Equals(PrecursorTextId other) { return(PrecursorMz.Equals(other.PrecursorMz) && Equals(IonMobility, other.IonMobility) && Equals(Target, other.Target) && Extractor == other.Extractor); }
public SpectrumFilterPair(PrecursorTextId precursorTextId, Color peptideColor, int id, double?minTime, double?maxTime, double highEnergyIonMobilityValueOffset, bool highAccQ1, bool highAccQ3) { Id = id; ModifiedSequence = precursorTextId.Target; PeptideColor = peptideColor; Q1 = precursorTextId.PrecursorMz; Extractor = precursorTextId.Extractor; MinTime = minTime; MaxTime = maxTime; IonMobilityInfo = precursorTextId.IonMobility; HighEnergyIonMobilityValueOffset = highEnergyIonMobilityValueOffset; MinIonMobilityValue = IonMobilityInfo.IsEmpty ? null : IonMobilityInfo.IonMobility.Mobility - (IonMobilityInfo.IonMobilityExtractionWindowWidth ?? 0) / 2; MaxIonMobilityValue = IonMobilityInfo.IsEmpty ? null : MinIonMobilityValue + (IonMobilityInfo.IonMobilityExtractionWindowWidth ?? 0); HighAccQ1 = highAccQ1; HighAccQ3 = highAccQ3; Ms1ProductFilters = SimProductFilters = Ms2ProductFilters = EMPTY_FILTERS; if (Q1 == 0) { Ms1ProductFilters = new[] { new SpectrumProductFilter(SignedMz.ZERO, 0) }; SimProductFilters = Ms1ProductFilters; // We want TIC and BPC for all scans, even if they have narrow machine settings and look like SIM } }
public SpectrumFilterPair(PrecursorTextId precursorTextId, Color peptideColor, int id, double?minTime, double?maxTime, bool highAccQ1, bool highAccQ3) { Id = id; ModifiedSequence = precursorTextId.Target; PeptideColor = peptideColor; Q1 = precursorTextId.PrecursorMz; Extractor = precursorTextId.Extractor; if (minTime.HasValue && maxTime.HasValue) { _filterByTime = true; _minTime = minTime.Value; _maxTime = maxTime.Value; } else { // If not min and max, then it should be neither. Asymmetric limits not supported. Assume.IsTrue(!minTime.HasValue && !maxTime.HasValue); } IonMobilityInfo = precursorTextId.IonMobility; MinIonMobilityValue = IonMobilityInfo.IsEmpty ? null : IonMobilityInfo.IonMobility.Mobility - (IonMobilityInfo.IonMobilityExtractionWindowWidth ?? 0) / 2; MaxIonMobilityValue = IonMobilityInfo.IsEmpty ? null : MinIonMobilityValue + (IonMobilityInfo.IonMobilityExtractionWindowWidth ?? 0); HighAccQ1 = highAccQ1; HighAccQ3 = highAccQ3; Ms1ProductFilters = SimProductFilters = Ms2ProductFilters = EMPTY_FILTERS; if (Q1 == 0) { Ms1ProductFilters = new[] { new SpectrumProductFilter(SignedMz.ZERO, 0, 0) }; SimProductFilters = Ms1ProductFilters; // We want TIC and BPC for all scans, even if they have narrow machine settings and look like SIM } }
public SpectrumFilterPair(PrecursorTextId precursorTextId, Color peptideColor, int id, double?minTime, double?maxTime, double?minDriftTimeMsec, double?maxDriftTimeMsec, double highEnergyDriftTimeOffsetMsec, bool highAccQ1, bool highAccQ3) { Id = id; ModifiedSequence = precursorTextId.TextId; PeptideColor = peptideColor; Q1 = precursorTextId.PrecursorMz; Extractor = precursorTextId.Extractor; MinTime = minTime; MaxTime = maxTime; MinDriftTimeMsec = minDriftTimeMsec; MaxDriftTimeMsec = maxDriftTimeMsec; HighEnergyDriftTimeOffsetMsec = highEnergyDriftTimeOffsetMsec; HighAccQ1 = highAccQ1; HighAccQ3 = highAccQ3; Ms1ProductFilters = SimProductFilters = Ms2ProductFilters = EMPTY_FILTERS; if (Q1 == 0) { Ms1ProductFilters = new[] { new SpectrumProductFilter(0, 0) }; } }
public SpectrumFilterPair(PrecursorTextId precursorTextId, Color peptideColor, int id, double?minTime, double?maxTime, double?minIonMobilityValue, double?maxIonMobilityValue, IonMobilityAndCCS ionMobilityInfo, bool highAccQ1, bool highAccQ3) { Id = id; ModifiedSequence = precursorTextId.Target; PeptideColor = peptideColor; Q1 = precursorTextId.PrecursorMz; Extractor = precursorTextId.Extractor; MinTime = minTime; MaxTime = maxTime; MinIonMobilityValue = minIonMobilityValue; MaxIonMobilityValue = maxIonMobilityValue; IonMobilityInfo = ionMobilityInfo ?? IonMobilityAndCCS.EMPTY; HighAccQ1 = highAccQ1; HighAccQ3 = highAccQ3; Ms1ProductFilters = SimProductFilters = Ms2ProductFilters = EMPTY_FILTERS; if (Q1 == 0) { Ms1ProductFilters = new[] { new SpectrumProductFilter(SignedMz.ZERO, 0) }; SimProductFilters = Ms1ProductFilters; // We want TIC and BPC for all scans, even if they have narrow machine settings and look like SIM } }
public IsotopeDistInfo(MassDistribution massDistribution, TypedMass monoisotopicMass, Adduct adduct, Func <double, double> calcFilterWindow, double massResolution, double minimumAbundance) { _monoisotopicMass = monoisotopicMass; _adduct = adduct.Unlabeled; // Don't reapply explicit isotope labels // Get peak center of mass values for the given resolution var q1FilterValues = MassDistribution.NewInstance(massDistribution, massResolution, 0).Keys.ToList(); // Find the monoisotopic m/z and make sure it is exactly the expected number double monoMz = _adduct.MzFromNeutralMass(_monoisotopicMass); double monoMzDist = monoMz; int monoMassIndex = 0; for (int i = 0; i < q1FilterValues.Count; i++) { double peakCenterMz = q1FilterValues[i]; double filterWindow = calcFilterWindow(peakCenterMz); double startMz = peakCenterMz - filterWindow / 2; double endMz = startMz + filterWindow; if (startMz < monoMz && monoMz < endMz) { monoMzDist = q1FilterValues[i]; q1FilterValues[i] = monoMz; monoMassIndex = i; break; } } // Insert a M-1 peak, even if it is not expected in the isotope mass distribution if (monoMassIndex == 0 && q1FilterValues.Count > 1) { // Use the delta from the original distribution monoMz to the next peak q1FilterValues.Insert(0, monoMz + monoMzDist - q1FilterValues[1]); monoMassIndex++; } if (!q1FilterValues.Any()) { // This should never happen, but just in case it does happen, we safely exit the constructor ExpectedPeaks = ImmutableList.Singleton(new MzRankProportion(monoMz, 0, 1.0f)); MonoMassIndex = BaseMassIndex = 0; return; } var signedQ1FilterValues = q1FilterValues.Select(q => new SignedMz(q, adduct.AdductCharge < 0)).ToList(); // Use the filtering algorithm that will be used on real data to determine the // expected proportions of the mass distribution that will end up filtered into // peaks // CONSIDER: Mass accuracy information is not calculated here var key = new PrecursorTextId(signedQ1FilterValues[monoMassIndex], null, null, ChromExtractor.summed); var filter = new SpectrumFilterPair(key, PeptideDocNode.UNKNOWN_COLOR, 0, null, null, false, false); filter.AddQ1FilterValues(signedQ1FilterValues, calcFilterWindow); var expectedSpectrum = filter.FilterQ1SpectrumList(new[] { new MsDataSpectrum { Mzs = massDistribution.Keys.ToArray(), Intensities = massDistribution.Values.ToArray(), NegativeCharge = (adduct.AdductCharge < 0) } }); int startIndex = expectedSpectrum.Intensities.IndexOf(inten => inten >= minimumAbundance); if (startIndex == -1) { // This can happen if the amino acid modifications are messed up, // and the peptide mass is negative or something. ExpectedPeaks = ImmutableList.Singleton(new MzRankProportion(monoMz, 0, 1.0f)); MonoMassIndex = BaseMassIndex = 0; return; } // Always include the M-1 peak, even if it is expected to have zero intensity if (startIndex > monoMassIndex - 1) { startIndex = monoMassIndex - 1; } if (startIndex < 0) { startIndex = 0; } int endIndex = expectedSpectrum.Intensities.LastIndexOf(inten => inten >= minimumAbundance) + 1; int countPeaks = endIndex - startIndex; var listProportionIndices = new List <KeyValuePair <float, int> >(countPeaks); for (int i = 0; i < countPeaks; i++) { listProportionIndices.Add(new KeyValuePair <float, int>( expectedSpectrum.Intensities[i + startIndex], i)); } // Sort proportions descending. listProportionIndices.Sort((p1, p2) => Comparer.Default.Compare(p2.Key, p1.Key)); // Set proportions and ranks back in the original locations var expectedProportionRanks = new KeyValuePair <float, int> [countPeaks]; for (int i = 0; i < countPeaks; i++) { expectedProportionRanks[listProportionIndices[i].Value] = new KeyValuePair <float, int>(listProportionIndices[i].Key, i + 1); } MonoMassIndex = monoMassIndex - startIndex; // Find the base peak and fill in the masses and proportions var expectedPeaks = new List <MzRankProportion>(); for (int i = 0; i < countPeaks; i++) { float expectedProportion = expectedProportionRanks[i].Key; int rank = expectedProportionRanks[i].Value; expectedPeaks.Add(new MzRankProportion(q1FilterValues[i + startIndex], rank, expectedProportion)); if (expectedProportion > expectedProportionRanks[BaseMassIndex].Key) { BaseMassIndex = i; } } ExpectedPeaks = expectedPeaks; }
public SpectrumFilter(SrmDocument document, MsDataFileUri msDataFileUri, IFilterInstrumentInfo instrumentInfo, IRetentionTimePredictor retentionTimePredictor = null, bool firstPass = false) { _fullScan = document.Settings.TransitionSettings.FullScan; _instrument = document.Settings.TransitionSettings.Instrument; _acquisitionMethod = _fullScan.AcquisitionMethod; if (instrumentInfo != null) { _isWatersFile = instrumentInfo.IsWatersFile; } IsFirstPass = firstPass; var comparer = PrecursorTextId.PrecursorTextIdComparerInstance; var dictPrecursorMzToFilter = new SortedDictionary <PrecursorTextId, SpectrumFilterPair>(comparer); if (EnabledMs || EnabledMsMs) { if (EnabledMs) { _isHighAccMsFilter = !Equals(_fullScan.PrecursorMassAnalyzer, FullScanMassAnalyzerType.qit); if (!firstPass) { var key = new PrecursorTextId(SignedMz.ZERO, null, ChromExtractor.summed); // TIC dictPrecursorMzToFilter.Add(key, new SpectrumFilterPair(key, PeptideDocNode.UNKNOWN_COLOR, dictPrecursorMzToFilter.Count, _instrument.MinTime, _instrument.MaxTime, null, null, 0, _isHighAccMsFilter, _isHighAccProductFilter)); key = new PrecursorTextId(SignedMz.ZERO, null, ChromExtractor.base_peak); // BPC dictPrecursorMzToFilter.Add(key, new SpectrumFilterPair(key, PeptideDocNode.UNKNOWN_COLOR, dictPrecursorMzToFilter.Count, _instrument.MinTime, _instrument.MaxTime, null, null, 0, _isHighAccMsFilter, _isHighAccProductFilter)); } } if (EnabledMsMs) { _isHighAccProductFilter = !Equals(_fullScan.ProductMassAnalyzer, FullScanMassAnalyzerType.qit); if (_fullScan.AcquisitionMethod == FullScanAcquisitionMethod.DIA && _fullScan.IsolationScheme.IsAllIons) { if (instrumentInfo != null) { _isWatersMse = _isWatersFile; _isAgilentMse = instrumentInfo.IsAgilentFile; } _mseLevel = 1; } } Func <double, double> calcWindowsQ1 = _fullScan.GetPrecursorFilterWindow; Func <double, double> calcWindowsQ3 = _fullScan.GetProductFilterWindow; _minTime = _instrument.MinTime; _maxTime = _instrument.MaxTime; bool canSchedule = CanSchedule(document, retentionTimePredictor); // TODO: Figure out a way to turn off time sharing on first SIM scan so that // times can be shared for MS1 without SIM scans _isSharedTime = !canSchedule; // If we're using bare measured drift times from spectral libraries, go get those now var libraryIonMobilityInfo = document.Settings.PeptideSettings.Prediction.UseLibraryDriftTimes ? document.Settings.GetIonMobilities(msDataFileUri) : null; foreach (var nodePep in document.Molecules) { if (firstPass && !retentionTimePredictor.IsFirstPassPeptide(nodePep)) { continue; } foreach (TransitionGroupDocNode nodeGroup in nodePep.Children) { if (nodeGroup.Children.Count == 0) { continue; } double? minTime = _minTime, maxTime = _maxTime; double? startDriftTimeMsec = null, endDriftTimeMsec = null; double windowDT; double highEnergyDriftTimeOffsetMsec = 0; DriftTimeInfo centerDriftTime = document.Settings.PeptideSettings.Prediction.GetDriftTime( nodePep, nodeGroup, libraryIonMobilityInfo, out windowDT); if (centerDriftTime.DriftTimeMsec(false).HasValue) { startDriftTimeMsec = centerDriftTime.DriftTimeMsec(false) - windowDT / 2; // Get the low energy drift time endDriftTimeMsec = startDriftTimeMsec + windowDT; highEnergyDriftTimeOffsetMsec = centerDriftTime.HighEnergyDriftTimeOffsetMsec; } if (canSchedule) { if (RetentionTimeFilterType.scheduling_windows == _fullScan.RetentionTimeFilterType) { double?centerTime = null; double windowRT = 0; if (retentionTimePredictor != null) { centerTime = retentionTimePredictor.GetPredictedRetentionTime(nodePep); } else { var prediction = document.Settings.PeptideSettings.Prediction; if (prediction.RetentionTime == null || !prediction.RetentionTime.IsAutoCalculated) { centerTime = document.Settings.PeptideSettings.Prediction.PredictRetentionTimeForChromImport( document, nodePep, nodeGroup, out windowRT); } } // Force the center time to be at least zero if (centerTime.HasValue && centerTime.Value < 0) { centerTime = 0; } if (_fullScan.RetentionTimeFilterLength != 0) { windowRT = _fullScan.RetentionTimeFilterLength * 2; } if (centerTime != null) { double startTime = centerTime.Value - windowRT / 2; double endTime = startTime + windowRT; minTime = Math.Max(minTime ?? 0, startTime); maxTime = Math.Min(maxTime ?? double.MaxValue, endTime); } } else if (RetentionTimeFilterType.ms2_ids == _fullScan.RetentionTimeFilterType) { var times = document.Settings.GetBestRetentionTimes(nodePep, msDataFileUri); if (times.Length > 0) { minTime = Math.Max(minTime ?? 0, times.Min() - _fullScan.RetentionTimeFilterLength); maxTime = Math.Min(maxTime ?? double.MaxValue, times.Max() + _fullScan.RetentionTimeFilterLength); } } } SpectrumFilterPair filter; string textId = nodePep.RawTextId; // Modified Sequence for peptides, or some other string for custom ions var mz = new SignedMz(nodeGroup.PrecursorMz, nodeGroup.PrecursorCharge < 0); var key = new PrecursorTextId(mz, textId, ChromExtractor.summed); if (!dictPrecursorMzToFilter.TryGetValue(key, out filter)) { filter = new SpectrumFilterPair(key, nodePep.Color, dictPrecursorMzToFilter.Count, minTime, maxTime, startDriftTimeMsec, endDriftTimeMsec, highEnergyDriftTimeOffsetMsec, _isHighAccMsFilter, _isHighAccProductFilter); dictPrecursorMzToFilter.Add(key, filter); } if (!EnabledMs) { filter.AddQ3FilterValues(from TransitionDocNode nodeTran in nodeGroup.Children select nodeTran.Mz, calcWindowsQ3); } else if (!EnabledMsMs) { filter.AddQ1FilterValues(GetMS1MzValues(nodeGroup), calcWindowsQ1); } else { filter.AddQ1FilterValues(GetMS1MzValues(nodeGroup), calcWindowsQ1); filter.AddQ3FilterValues(from TransitionDocNode nodeTran in nodeGroup.Children where !nodeTran.IsMs1 select nodeTran.Mz, calcWindowsQ3); } } } _filterMzValues = dictPrecursorMzToFilter.Values.ToArray(); var listChromKeyFilterIds = new List <ChromKey>(); foreach (var spectrumFilterPair in _filterMzValues) { spectrumFilterPair.AddChromKeys(listChromKeyFilterIds); } _productChromKeys = listChromKeyFilterIds.ToArray(); // Sort a copy of the filter pairs by maximum retention time so that we can detect when // filters are no longer active. _filterRTValues = new SpectrumFilterPair[_filterMzValues.Length]; Array.Copy(_filterMzValues, _filterRTValues, _filterMzValues.Length); Array.Sort(_filterRTValues, CompareByRT); } InitRTLimits(); }
public IsotopeDistInfo(MassDistribution massDistribution, double monoisotopicMass, bool isMassH, // Is monoisotopicMass M+H, or just M as in small molecule use? int charge, Func <double, double> calcFilterWindow, double massResolution, double minimumAbundance) { _monoisotopicMass = monoisotopicMass; _charge = charge; _isMassH = isMassH; // Get peak center of mass values for the given resolution var q1FilterValues = MassDistribution.NewInstance(massDistribution, massResolution, 0).Keys.ToList(); // Find the monoisotopic m/z and make sure it is exactly the expected number double monoMz = isMassH ? SequenceMassCalc.GetMZ(_monoisotopicMass, _charge) : BioMassCalc.CalculateIonMz(_monoisotopicMass, _charge); double monoMzDist = monoMz; int monoMassIndex = 0; for (int i = 0; i < q1FilterValues.Count; i++) { double peakCenterMz = q1FilterValues[i]; double filterWindow = calcFilterWindow(peakCenterMz); double startMz = peakCenterMz - filterWindow / 2; double endMz = startMz + filterWindow; if (startMz < monoMz && monoMz < endMz) { monoMzDist = q1FilterValues[i]; q1FilterValues[i] = monoMz; monoMassIndex = i; break; } } // Insert a M-1 peak, even if it is not expected in the isotope mass distribution if (monoMassIndex == 0 && q1FilterValues.Count > 1) { // Use the delta from the original distribution monoMz to the next peak q1FilterValues.Insert(0, monoMz + monoMzDist - q1FilterValues[1]); monoMassIndex++; } if (!q1FilterValues.Any()) // As is small molecule docs with mz values only, no formulas { return; } // Use the filtering algorithm that will be used on real data to determine the // expected proportions of the mass distribution that will end up filtered into // peaks // CONSIDER: Mass accuracy information is not calculated here var key = new PrecursorTextId(q1FilterValues[monoMassIndex], null, ChromExtractor.summed); var filter = new SpectrumFilterPair(key, PeptideDocNode.UNKNOWN_COLOR, 0, null, null, null, null, 0, false, false); filter.AddQ1FilterValues(q1FilterValues, calcFilterWindow); var expectedSpectrum = filter.FilterQ1SpectrumList(new[] { new MsDataSpectrum { Mzs = massDistribution.Keys.ToArray(), Intensities = massDistribution.Values.ToArray() } }); int startIndex = expectedSpectrum.Intensities.IndexOf(inten => inten >= minimumAbundance); if (startIndex == -1) { throw new InvalidOperationException( string.Format(Resources.IsotopeDistInfo_IsotopeDistInfo_Minimum_abundance__0__too_high, minimumAbundance)); } // Always include the M-1 peak, even if it is expected to have zero intensity if (startIndex > monoMassIndex - 1) { startIndex = monoMassIndex - 1; } if (startIndex < 0) { startIndex = 0; } int endIndex = expectedSpectrum.Intensities.LastIndexOf(inten => inten >= minimumAbundance) + 1; int countPeaks = endIndex - startIndex; var listProportionIndices = new List <KeyValuePair <float, int> >(countPeaks); for (int i = 0; i < countPeaks; i++) { listProportionIndices.Add(new KeyValuePair <float, int>( expectedSpectrum.Intensities[i + startIndex], i)); } // Sort proportions descending. listProportionIndices.Sort((p1, p2) => Comparer.Default.Compare(p2.Key, p1.Key)); // Set proportions and ranks back in the original locations var expectedProportionRanks = new KeyValuePair <float, int> [countPeaks]; for (int i = 0; i < countPeaks; i++) { expectedProportionRanks[listProportionIndices[i].Value] = new KeyValuePair <float, int>(listProportionIndices[i].Key, i + 1); } // TODO: Can this be discarded? // MassDistribution = massDistribution; MonoMassIndex = monoMassIndex - startIndex; // Find the base peak and fill in the masses and proportions var expectedPeaks = new List <MzRankProportion>(); for (int i = 0; i < countPeaks; i++) { float expectedProportion = expectedProportionRanks[i].Key; int rank = expectedProportionRanks[i].Value; expectedPeaks.Add(new MzRankProportion(q1FilterValues[i + startIndex], rank, expectedProportion)); if (expectedProportion > expectedProportionRanks[BaseMassIndex].Key) { BaseMassIndex = i; } } ExpectedPeaks = expectedPeaks; }
public bool Equals(PrecursorTextId other) { return(PrecursorMz.Equals(other.PrecursorMz) && string.Equals(TextId, other.TextId) && Extractor == other.Extractor); }