private bool CanAddLabelType(IsotopeLabelType labelType) { if (_settings.TryGetPrecursorCalc(labelType, null) != null) { return(true); } return(_document.Molecules.Any(nodePep => _settings.TryGetPrecursorCalc(labelType, nodePep.ExplicitMods) != null)); }
private static IEnumerable <KeyValuePair <IsotopeLabelType, string> > GetTypedModifiedSequences( PeptideDocNode nodePep, SrmSettings settings) { foreach (var labelType in settings.PeptideSettings.Modifications.GetModificationTypes()) { if (nodePep.Peptide.IsCustomMolecule) { continue; } // Only return the modified sequence, if the peptide actually as a child // of this type. if (!nodePep.HasChildType(labelType)) { continue; } var calc = settings.TryGetPrecursorCalc(labelType, nodePep.ExplicitMods); if (calc == null) { continue; } string modSequence = calc.GetModifiedSequence(nodePep.Peptide.Target, true).Sequence; // Never have to worry about this being a custom molecule, we already checked // Only return if the modified sequence contains modifications if (modSequence.Contains('[')) { yield return(new KeyValuePair <IsotopeLabelType, string>(labelType, modSequence)); } } }
/// <summary> /// Creates a text sequence with the fully modified peptide sequence text /// and font information for a given label type. /// </summary> private static TextSequence CreateTypeTextSequence(PeptideDocNode nodePep, SrmSettings settings, IsotopeLabelType labelType, ModFontHolder fonts) { var calc = settings.TryGetPrecursorCalc(labelType, nodePep.ExplicitMods); if (calc == null) { return(null); } return(new TextSequence { Text = nodePep.IsProteomic ? calc.GetModifiedSequence(nodePep.Peptide.Target, SequenceModFormatType.mass_diff_narrow, false).Sequence : nodePep.CustomMolecule.DisplayName, Font = fonts.GetModFont(labelType), Color = ModFontHolder.GetModColor(labelType) }); }
/// <summary> /// Creates a text sequence with the fully modified peptide sequence text /// and font information for a given label type. /// </summary> private static TextSequence CreateTypeTextSequence(PeptideDocNode nodePep, SrmSettings settings, IsotopeLabelType labelType, ModFontHolder fonts) { var calc = settings.TryGetPrecursorCalc(labelType, nodePep.ExplicitMods); if (calc == null) { return(null); } return(new TextSequence { Text = nodePep.IsProteomic ? calc.GetModifiedSequence(nodePep.Peptide.Sequence, true) : nodePep.CustomIon.DisplayName, Font = fonts.GetModFont(labelType), Color = ModFontHolder.GetModColor(labelType) }); }
public IEnumerable <TransitionDocNode> GetTransitions(SrmSettings settings, TransitionGroupDocNode groupDocNode, ExplicitMods mods, double precursorMz, IsotopeDistInfo isotopeDist, SpectrumHeaderInfo libInfo, IDictionary <double, LibraryRankedSpectrumInfo.RankedMI> transitionRanks, bool useFilter) { Assume.IsTrue(ReferenceEquals(groupDocNode.TransitionGroup, this)); // Get necessary mass calculators and masses var calcFilterPre = settings.GetPrecursorCalc(IsotopeLabelType.light, mods); var calcPredictPre = settings.TryGetPrecursorCalc(LabelType, mods) ?? calcFilterPre; var calcFilter = settings.GetFragmentCalc(IsotopeLabelType.light, mods); var calcPredict = settings.GetFragmentCalc(LabelType, mods); var sequence = Peptide.Target; // Save the true precursor m/z for TranstionSettings.Accept() now that all isotope types are // checked. This is more correct than just using the light precursor m/z for precursor window // exclusion. double precursorMzAccept = precursorMz; if (!ReferenceEquals(calcFilter, calcPredict)) { // Get the normal precursor m/z for filtering, so that light and heavy ion picks will match. var adduct = groupDocNode.TransitionGroup.PrecursorAdduct; string isotopicFormula; precursorMz = IsCustomIon ? adduct.MzFromNeutralMass(calcFilterPre.GetPrecursorMass(groupDocNode.CustomMolecule, null, Adduct.EMPTY, out isotopicFormula), calcFilterPre.MassType.IsMonoisotopic() ? MassType.Monoisotopic : MassType.Average) : // Don't pass the isMassH bit SequenceMassCalc.GetMZ(calcFilterPre.GetPrecursorMass(sequence), adduct); } if (!IsAvoidMismatchedIsotopeTransitions) { precursorMzAccept = precursorMz; } var tranSettings = settings.TransitionSettings; var filter = tranSettings.Filter; var adducts = groupDocNode.IsCustomIon ? filter.SmallMoleculeFragmentAdducts : filter.PeptideProductCharges; var startFinder = filter.FragmentRangeFirst; var endFinder = filter.FragmentRangeLast; double precursorMzWindow = filter.PrecursorMzWindow; var types = groupDocNode.IsCustomIon ? filter.SmallMoleculeIonTypes : filter.PeptideIonTypes; MassType massType = tranSettings.Prediction.FragmentMassType; int minMz = tranSettings.Instrument.GetMinMz(precursorMzAccept); int maxMz = tranSettings.Instrument.MaxMz; var pepMods = settings.PeptideSettings.Modifications; var potentialLosses = CalcPotentialLosses(sequence, pepMods, mods, massType); // A start m/z will need to be calculated if the start fragment // finder uses m/z and their are losses to consider. If the filter // is set to only consider fragments with m/z greater than the // precursor, the code below needs to also prevent loss fragments // from being under that m/z. double startMz = 0; // Get library settings var pick = tranSettings.Libraries.Pick; if (!useFilter) { pick = TransitionLibraryPick.all; var listAll = IsProteomic ? Transition.DEFAULT_PEPTIDE_CHARGES.ToList() : Transition.DEFAULT_MOLECULE_CHARGES.ToList(); listAll.AddRange(adducts.Where(c => !listAll.Contains(c))); listAll.Sort(); adducts = listAll.ToArray(); types = IsProteomic ? Transition.PEPTIDE_ION_TYPES : Transition.MOLECULE_ION_TYPES; } // If there are no libraries or no library information, then // picking cannot use library information else if (!settings.PeptideSettings.Libraries.HasLibraries || libInfo == null) { pick = TransitionLibraryPick.none; } // If filtering without library picking if (potentialLosses != null && IsProteomic) { if (pick == TransitionLibraryPick.none) { // Only include loss combinations where all losses are included always potentialLosses = potentialLosses.Where(losses => losses.All(loss => loss.TransitionLoss.Loss.Inclusion == LossInclusion.Always)).ToArray(); } else if (useFilter) { // Exclude all losses which should never be included by default potentialLosses = potentialLosses.Where(losses => losses.All(loss => loss.TransitionLoss.Loss.Inclusion != LossInclusion.Never)).ToArray(); } if (!potentialLosses.Any()) { potentialLosses = null; } } // Return precursor ions if (!useFilter || types.Contains(IonType.precursor)) { bool libraryFilter = (pick == TransitionLibraryPick.all || pick == TransitionLibraryPick.filter); foreach (var nodeTran in GetPrecursorTransitions(settings, mods, calcPredictPre, calcPredict ?? calcFilter, precursorMz, isotopeDist, potentialLosses, transitionRanks, libraryFilter, useFilter)) { if (minMz <= nodeTran.Mz && nodeTran.Mz <= maxMz) { yield return(nodeTran); } } } // Return special ions from settings, if this is a peptide if (!IsCustomIon) { // This is a peptide, but it may have custom transitions (reporter ions), check those foreach (var measuredIon in tranSettings.Filter.MeasuredIons.Where(m => m.IsCustom)) { if (useFilter && measuredIon.IsOptional) { continue; } var tran = new Transition(this, measuredIon.Adduct, null, measuredIon.SettingsCustomIon); var mass = settings.GetFragmentMass(null, null, tran, null); var nodeTran = new TransitionDocNode(tran, null, mass, TransitionDocNode.TransitionQuantInfo.DEFAULT); if (minMz <= nodeTran.Mz && nodeTran.Mz <= maxMz) { yield return(nodeTran); } } } // For small molecules we can't generate new nodes, so just mz filter those we have foreach (var nodeTran in groupDocNode.Transitions.Where(tran => tran.Transition.IsNonPrecursorNonReporterCustomIon())) { if (minMz <= nodeTran.Mz && nodeTran.Mz <= maxMz) { yield return(nodeTran); } } if (!sequence.IsProteomic) // Completely custom CONSIDER(bspratt) can this be further extended for small mol libs? { yield break; } // If picking relies on library information if (useFilter && pick != TransitionLibraryPick.none) { // If it is not yet loaded, or nothing got ranked, return an empty enumeration if (!settings.PeptideSettings.Libraries.IsLoaded || (transitionRanks != null && transitionRanks.Count == 0)) { yield break; } } var massesPredict = calcPredict.GetFragmentIonMasses(sequence); int len = massesPredict.GetLength(1); if (len == 0) { yield break; } var massesFilter = massesPredict; if (!ReferenceEquals(calcFilter, calcPredict)) { // Get the normal m/z values for filtering, so that light and heavy // ion picks will match. massesFilter = calcFilter.GetFragmentIonMasses(sequence); } // Get types other than this to make sure matches are possible for all types var listOtherTypes = new List <Tuple <TransitionGroupDocNode, IFragmentMassCalc> >(); foreach (var labelType in settings.PeptideSettings.Modifications.GetModificationTypes()) { if (Equals(labelType, LabelType)) { continue; } var calc = settings.GetFragmentCalc(labelType, mods); if (calc == null) { continue; } var tranGroupOther = new TransitionGroup(Peptide, PrecursorAdduct, labelType, false, DecoyMassShift); var nodeGroupOther = new TransitionGroupDocNode(tranGroupOther, Annotations.EMPTY, settings, mods, libInfo, ExplicitTransitionGroupValues.EMPTY, null, new TransitionDocNode[0], false); listOtherTypes.Add(new Tuple <TransitionGroupDocNode, IFragmentMassCalc>(nodeGroupOther, calc)); } // Loop over potential product ions picking transitions foreach (IonType type in types) { // Precursor type is handled above. if (type == IonType.precursor) { continue; } foreach (var adduct in adducts) { // Precursor charge can never be lower than product ion charge. if (Math.Abs(PrecursorAdduct.AdductCharge) < Math.Abs(adduct.AdductCharge)) { continue; } int start = 0, end = 0; if (pick != TransitionLibraryPick.all) { start = startFinder.FindStartFragment(massesFilter, type, adduct, precursorMz, precursorMzWindow, out startMz); end = endFinder.FindEndFragment(type, start, len); if (Transition.IsCTerminal(type)) { Helpers.Swap(ref start, ref end); } } for (int i = 0; i < len; i++) { // Get the predicted m/z that would be used in the transition var massH = massesPredict[type, i]; Assume.IsTrue(massH.IsMassH()); Assume.IsTrue(massH.IsMonoIsotopic() == calcPredict.MassType.IsMonoisotopic()); foreach (var losses in CalcTransitionLosses(type, i, massType, potentialLosses)) { double ionMz = SequenceMassCalc.GetMZ(Transition.CalcMass(massH, losses), adduct); // Make sure the fragment m/z value falls within the valid instrument range. // CONSIDER: This means that a heavy transition might excede the instrument // range where a light one is accepted, leading to a disparity // between heavy and light transtions picked. if (minMz > ionMz || ionMz > maxMz) { continue; } TransitionDocNode nodeTranReturn = null; bool accept = true; if (pick == TransitionLibraryPick.all || pick == TransitionLibraryPick.all_plus) { if (!useFilter) { nodeTranReturn = CreateTransitionNode(type, i, adduct, massH, losses, transitionRanks); accept = false; } else { if (IsMatched(transitionRanks, ionMz, type, adduct, losses)) { nodeTranReturn = CreateTransitionNode(type, i, adduct, massH, losses, transitionRanks); accept = false; } // If allowing library or filter, check the filter to decide whether to accept else if (pick == TransitionLibraryPick.all_plus && tranSettings.Accept(sequence, precursorMzAccept, type, i, ionMz, start, end, startMz)) { nodeTranReturn = CreateTransitionNode(type, i, adduct, massH, losses, transitionRanks); } } } else if (tranSettings.Accept(sequence, precursorMzAccept, type, i, ionMz, start, end, startMz)) { if (pick == TransitionLibraryPick.none) { nodeTranReturn = CreateTransitionNode(type, i, adduct, massH, losses, transitionRanks); } else { if (IsMatched(transitionRanks, ionMz, type, adduct, losses)) { nodeTranReturn = CreateTransitionNode(type, i, adduct, massH, losses, transitionRanks); } } } if (nodeTranReturn != null) { if (IsAvoidMismatchedIsotopeTransitions && !OtherLabelTypesAllowed(settings, minMz, maxMz, start, end, startMz, accept, groupDocNode, nodeTranReturn, listOtherTypes)) { continue; } Assume.IsTrue(minMz <= nodeTranReturn.Mz && nodeTranReturn.Mz <= maxMz); yield return(nodeTranReturn); } } } } } }