public static bool Equivalent(Transition t, Transition obj) { return Equals(obj.IonType, t.IonType) && obj.CleavageOffset == t.CleavageOffset && obj.Charge == t.Charge && obj.MassIndex == t.MassIndex && CustomIon.Equivalent(obj.CustomIon, t.CustomIon) && // Looks at unlabeled formula or name only (obj.DecoyMassShift.Equals(t.DecoyMassShift) || // Deal with strange case of mProphet golden standard data set - only a concern for peptides, not small molecules (obj.DecoyMassShift.HasValue && t.DecoyMassShift.HasValue && (obj.Group.LabelType.IsLight && obj.DecoyMassShift == 0 && !t.Group.LabelType.IsLight && t.DecoyMassShift != 0) || (!obj.Group.LabelType.IsLight && obj.DecoyMassShift != 0 && t.Group.LabelType.IsLight && t.DecoyMassShift == 0))); }
private void CompleteTransitionGroup() { var precursorExp = GetBestPrecursorExp(); var transitionGroup = new TransitionGroup(_activePeptide, precursorExp.PrecursorCharge, precursorExp.LabelType, false, precursorExp.MassShift); var transitions = _activeTransitionInfos.ConvertAll(info => { var productExp = info.TransitionExps.Single(exp => Equals(precursorExp, exp.Precursor)).Product; var ionType = productExp.IonType; var ordinal = productExp.FragmentOrdinal; int offset = Transition.OrdinalToOffset(ionType, ordinal, _activePeptide.Sequence.Length); int? massShift = productExp.MassShift; if (massShift == null && precursorExp.MassShift.HasValue) massShift = 0; var tran = new Transition(transitionGroup, ionType, offset, 0, productExp.Charge, massShift); // m/z and library info calculated later return new TransitionDocNode(tran, productExp.Losses, 0, null, null); }); // m/z calculated later var newTransitionGroup = new TransitionGroupDocNode(transitionGroup, CompleteTransitions(transitions)); var currentLibrarySpectrum = !_activeLibraryIntensities.Any() ? null : new SpectrumMzInfo { Key = new LibKey(_activePeptide.Sequence, precursorExp.PrecursorCharge), PrecursorMz = _activePrecursorMz, Label = precursorExp.LabelType, SpectrumPeaks = new SpectrumPeaksInfo(_activeLibraryIntensities.ToArray()) }; _groupLibTriples.Add(new TransitionGroupLibraryIrtTriple(currentLibrarySpectrum, newTransitionGroup, _irtValue, _activePrecursorMz)); _activePrecursorMz = 0; _activePrecursorExps.Clear(); _activeTransitionInfos.Clear(); _activeLibraryIntensities.Clear(); _irtValue = null; }
public ChangedPeakBoundsEventArgs(IdentityPath groupPath, Transition transition, string nameSet, MsDataFileUri filePath, ScaledRetentionTime startTime, ScaledRetentionTime endTime, PeakIdentification identified, PeakBoundsChangeType changeType) : base(groupPath, nameSet, filePath) { Transition = transition; StartTime = startTime; EndTime = endTime; Identified = identified; ChangeType = changeType; }
public double GetFragmentMass(Transition transition, IsotopeDistInfo isotopeDist, ExplicitSequenceMods mods) { if (transition.IsCustom()) { var type = transition.IonType; var massIndex = transition.MassIndex; if (Transition.IsPrecursor(type) && (isotopeDist != null)) { var i = isotopeDist.MassIndexToPeakIndex(massIndex); if (0 > i || i >= isotopeDist.CountPeaks) { throw new IndexOutOfRangeException( string.Format(Resources.SequenceMassCalc_GetFragmentMass_Precursor_isotope__0__is_outside_the_isotope_distribution__1__to__2__, GetMassIDescripion(massIndex), isotopeDist.PeakIndexToMassIndex(0), isotopeDist.PeakIndexToMassIndex(isotopeDist.CountPeaks - 1))); } return isotopeDist.GetMassI(massIndex); } return (MassType == MassType.Average) ? transition.CustomIon.AverageMass : transition.CustomIon.MonoisotopicMass; } return GetFragmentMass(transition.Group.Peptide.Sequence, transition.IonType, transition.Ordinal, transition.DecoyMassShift, transition.MassIndex, isotopeDist, mods); }
private static TransitionDocNode[] GetDecoyTransitions(TransitionGroupDocNode nodeGroup, TransitionGroup decoyGroup, bool shiftMass) { var decoyNodeTranList = new List<TransitionDocNode>(); foreach (var nodeTran in nodeGroup.Transitions) { var transition = nodeTran.Transition; int productMassShift = 0; if (shiftMass) productMassShift = GetProductMassShift(); else if (transition.IsPrecursor() && decoyGroup.DecoyMassShift.HasValue) productMassShift = decoyGroup.DecoyMassShift.Value; var decoyTransition = new Transition(decoyGroup, transition.IonType, transition.CleavageOffset, transition.MassIndex, transition.Charge, productMassShift, transition.CustomIon); decoyNodeTranList.Add(new TransitionDocNode(decoyTransition, nodeTran.Losses, 0, nodeTran.IsotopeDistInfo, nodeTran.LibInfo)); } return decoyNodeTranList.ToArray(); }
/// <summary> /// True if a given transition is equivalent to this, ignoring the /// transition group. /// </summary> public bool Equivalent(Transition obj) { return Equivalent(this, obj); }
public double GetFragmentMass(Transition transition, IsotopeDistInfo isotopeDist) { return _massCalcBase.GetFragmentMass(transition, isotopeDist, _mods); }
public static bool IsGluAsp(string sequence, int cleavageOffset) { char c = Transition.GetFragmentCTermAA(sequence, cleavageOffset); return(c == 'G' || c == 'A'); }
public static bool IsPro(string sequence, int cleavageOffset) { return(Transition.GetFragmentNTermAA(sequence, cleavageOffset) == 'P'); }
private TransitionDocNode CreateTransitionNode(int massIndex, TypedMass precursorMassH, TransitionIsotopeDistInfo isotopeDistInfo, TransitionLosses losses, IDictionary <double, LibraryRankedSpectrumInfo.RankedMI> transitionRanks, CustomMolecule customMolecule = null) { Transition transition = new Transition(this, massIndex, customMolecule); var quantInfo = TransitionDocNode.TransitionQuantInfo.GetLibTransitionQuantInfo(transition, losses, Transition.CalcMass(precursorMassH, losses), transitionRanks).ChangeIsotopeDistInfo(isotopeDistInfo); var transitionDocNode = new TransitionDocNode(transition, losses, precursorMassH, quantInfo); if (massIndex < 0) { transitionDocNode = transitionDocNode.ChangeQuantitative(false); } return(transitionDocNode); }
private TransitionDocNode CreateTransitionNode(IonType type, int cleavageOffset, Adduct charge, TypedMass massH, TransitionLosses losses, IDictionary <double, LibraryRankedSpectrumInfo.RankedMI> transitionRanks, CustomMolecule customMolecule = null) { Transition transition = new Transition(this, type, cleavageOffset, 0, charge, null, customMolecule); var info = TransitionDocNode.TransitionQuantInfo.GetLibTransitionQuantInfo(transition, losses, Transition.CalcMass(massH, losses), transitionRanks); return(new TransitionDocNode(transition, losses, massH, info)); }
public IEnumerable <TransitionDocNode> GetPrecursorTransitions(SrmSettings settings, ExplicitMods mods, IPrecursorMassCalc calcPredictPre, IFragmentMassCalc calcPredict, double precursorMz, IsotopeDistInfo isotopeDist, IList <IList <ExplicitLoss> > potentialLosses, IDictionary <double, LibraryRankedSpectrumInfo.RankedMI> transitionRanks, bool libraryFilter, bool useFilter) { var tranSettings = settings.TransitionSettings; var fullScan = tranSettings.FullScan; int minMz = tranSettings.Instrument.GetMinMz(precursorMz); int maxMz = tranSettings.Instrument.MaxMz; bool precursorMS1 = fullScan.IsEnabledMs; MassType massType = tranSettings.Prediction.FragmentMassType; MassType massTypeIon = precursorMS1 ? tranSettings.Prediction.PrecursorMassType : massType; var sequence = Peptide.Target; var ionTypes = IsProteomic ? tranSettings.Filter.PeptideIonTypes : tranSettings.Filter.SmallMoleculeIonTypes; bool precursorNoProducts = precursorMS1 && !fullScan.IsEnabledMsMs && ionTypes.Count == 1 && ionTypes[0] == IonType.precursor; var precursorMassPredict = precursorMS1 ? calcPredictPre.GetPrecursorMass(sequence) : calcPredict.GetPrecursorFragmentMass(sequence); foreach (var losses in CalcTransitionLosses(IonType.precursor, 0, massType, potentialLosses)) { double ionMz = IsProteomic ? SequenceMassCalc.GetMZ(Transition.CalcMass(precursorMassPredict, losses), PrecursorAdduct) : PrecursorAdduct.MzFromNeutralMass(CustomMolecule.GetMass(massTypeIon), massTypeIon); if (losses == null) { if (precursorMS1 && isotopeDist != null) { foreach (int i in fullScan.SelectMassIndices(isotopeDist, useFilter)) { var precursorMS1Mass = isotopeDist.GetMassI(i, DecoyMassShift); ionMz = SequenceMassCalc.GetMZ(precursorMS1Mass, PrecursorAdduct); if (minMz > ionMz || ionMz > maxMz) { continue; } var isotopeDistInfo = new TransitionIsotopeDistInfo( isotopeDist.GetRankI(i), isotopeDist.GetProportionI(i)); yield return(CreateTransitionNode(i, precursorMS1Mass, isotopeDistInfo, null, transitionRanks)); } continue; } } // If there was loss, it is possible (though not likely) that the ion m/z value // will now fall below the minimum measurable value for the instrument else if (minMz > ionMz) { continue; } // If filtering precursors from MS1 scans, then ranking in MS/MS does not apply bool precursorIsProduct = !precursorMS1 || losses != null; // Skip product ion precursors, if the should not be included if (useFilter && precursorIsProduct && precursorNoProducts) { continue; } if (!useFilter || !precursorIsProduct || !libraryFilter || IsMatched(transitionRanks, ionMz, IonType.precursor, PrecursorAdduct, losses)) { yield return(CreateTransitionNode(0, precursorMassPredict, null, losses, precursorIsProduct ? transitionRanks : null)); } } }
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); } } } } } }
private static CellDesc CreateIon(IonType type, int ordinal, double massH, int charge, IEnumerable<DocNode> choices, ICollection<DocNode> chosen, Transition tranSelected, RenderTools rt) { double mz = SequenceMassCalc.GetMZ(massH, charge); CellDesc cell = CreateData(string.Format("{0:F02}", mz), rt); // Not L10N foreach (TransitionDocNode nodeTran in choices) { Transition tran = nodeTran.Transition; if (tran.IonType == type && tran.Ordinal == ordinal && tran.Charge == charge) { cell.Font = rt.FontBold; if (Equals(tran, tranSelected)) { cell.Brush = rt.BrushSelected; // Stop after selected break; } if (!chosen.Contains(nodeTran)) cell.Brush = rt.BrushChoice; // Keep looking else { cell.Brush = rt.BrushChosen; // Stop after chosen break; } } } return cell; }
public static int GetEquivalentHashCode(Transition t) { unchecked { int result = t.IonType.GetHashCode(); result = (result * 397) ^ t.CleavageOffset; result = (result * 397) ^ t.MassIndex; result = (result * 397) ^ t.Charge; result = (result * 397) ^ (t.DecoyMassShift ?? 0); result = (result * 397) ^ (t.CustomIon != null ? t.CustomIon.GetEquivalentHashCode() : 0); return result; } }
public static TransitionQuantInfo GetTransitionQuantInfo(Transition transition, TransitionLosses losses, IsotopeDistInfo isotopeDist, TypedMass massH, IDictionary <double, LibraryRankedSpectrumInfo.RankedMI> ranks) { var transitionIsotopeDistInfo = GetIsotopeDistInfo(transition, losses, isotopeDist); return(GetLibTransitionQuantInfo(transition, losses, massH, ranks).ChangeIsotopeDistInfo(transitionIsotopeDistInfo)); }
public bool Equals(Transition obj) { if (ReferenceEquals(null, obj)) return false; if (ReferenceEquals(this, obj)) return true; var equal = Equals(obj._group, _group) && obj.IonType == IonType && Equals(obj.CustomIon, CustomIon) && obj.CleavageOffset == CleavageOffset && obj.MassIndex == MassIndex && obj.Charge == Charge && obj.DecoyMassShift.Equals(DecoyMassShift); return equal; // For debugging convenience }
public string GetFragmentIonName(CultureInfo cultureInfo, double?tolerance = null) { string ionName = Transition.GetFragmentIonName(cultureInfo, tolerance); return(HasLoss ? string.Format("{0} -{1}", ionName, Math.Round(Losses.Mass, 1)) : ionName); // Not L10N }
public TransitionEquivalentKey(TransitionGroupDocNode parent, TransitionDocNode nodeTran) { _nodeTran = nodeTran.Transition; _customIonEquivalenceTestText = new TransitionLossKey(parent, nodeTran, null).CustomIonEquivalenceTestValue; }
/// <summary> /// Return product's neutral mass rounded for XML I/O /// </summary> public double GetMoleculePersistentNeutralMass() { var moleculeMass = GetMoleculeMass(); return(Transition.IsCustom() ? Math.Round(moleculeMass, SequenceMassCalc.MassPrecision) : SequenceMassCalc.PersistentNeutral(moleculeMass)); }
public double GetFragmentMass(Transition transition, IsotopeDistInfo isotopeDist) { return GetFragmentMass(transition, isotopeDist, null); }
public SkylineDocumentProto.Types.Transition ToTransitionProto(SrmSettings settings) { var transitionProto = new SkylineDocumentProto.Types.Transition { FragmentType = DataValues.ToIonType(Transition.IonType), NotQuantitative = !Quantitative }; if (Transition.IsCustom() && !Transition.IsPrecursor()) { SetCustomIonFragmentInfo(transitionProto); } transitionProto.DecoyMassShift = DataValues.ToOptional(Transition.DecoyMassShift); transitionProto.MassIndex = Transition.MassIndex; if (HasDistInfo) { transitionProto.IsotopeDistRank = DataValues.ToOptional(IsotopeDistInfo.Rank); transitionProto.IsotopeDistProportion = DataValues.ToOptional(IsotopeDistInfo.Proportion); } if (!Transition.IsPrecursor()) { if (!Transition.IsCustom()) { transitionProto.FragmentOrdinal = Transition.Ordinal; transitionProto.CalcNeutralMass = GetMoleculePersistentNeutralMass(); } transitionProto.Charge = Transition.Charge; if (!Transition.Adduct.IsProteomic) { transitionProto.Adduct = DataValues.ToOptional(Transition.Adduct.AsFormulaOrSignedInt()); } if (!Transition.IsCustom()) { transitionProto.CleavageAa = Transition.AA; transitionProto.LostMass = LostMass; } } if (Annotations != null) { transitionProto.Annotations = Annotations.ToProtoAnnotations(); } transitionProto.ProductMz = Mz; if (Losses != null) { foreach (var loss in Losses.Losses) { var neutralLoss = new SkylineDocumentProto.Types.TransitionLoss(); if (loss.PrecursorMod == null) { neutralLoss.Formula = loss.Loss.Formula; neutralLoss.MonoisotopicMass = loss.Loss.MonoisotopicMass; neutralLoss.AverageMass = loss.Loss.AverageMass; neutralLoss.LossInclusion = DataValues.ToLossInclusion(loss.Loss.Inclusion); } else { neutralLoss.ModificationName = loss.PrecursorMod.Name; neutralLoss.LossIndex = loss.LossIndex; } transitionProto.Losses.Add(neutralLoss); } } if (HasLibInfo) { transitionProto.LibInfo = new SkylineDocumentProto.Types.TransitionLibInfo { Intensity = LibInfo.Intensity, Rank = LibInfo.Rank }; } if (Results != null) { transitionProto.Results = new SkylineDocumentProto.Types.TransitionResults(); transitionProto.Results.Peaks.AddRange(GetTransitionPeakProtos(settings.MeasuredResults)); } return(transitionProto); }
public SrmDocument ConvertToSmallMolecules(SrmDocument document, ConvertToSmallMoleculesMode mode = ConvertToSmallMoleculesMode.formulas, bool invertCharges = false, bool ignoreDecoys=false) { if (mode == ConvertToSmallMoleculesMode.none) return document; var newdoc = new SrmDocument(document.Settings); var note = new Annotations(TestingConvertedFromProteomic, null, 1); // Mark this as a testing node so we don't sort it newdoc = (SrmDocument)newdoc.ChangeIgnoreChangingChildren(true); // Retain copied results foreach (var peptideGroupDocNode in document.MoleculeGroups) { if (!peptideGroupDocNode.IsProteomic) { newdoc = (SrmDocument)newdoc.Add(peptideGroupDocNode); // Already a small molecule } else { var newPeptideGroup = new PeptideGroup(); var newPeptideGroupDocNode = new PeptideGroupDocNode(newPeptideGroup, peptideGroupDocNode.Annotations.Merge(note), peptideGroupDocNode.Name, peptideGroupDocNode.Description, new PeptideDocNode[0], peptideGroupDocNode.AutoManageChildren); foreach (var mol in peptideGroupDocNode.Molecules) { var peptideSequence = mol.Peptide.Sequence; // Create a PeptideDocNode with the presumably baseline charge and label var precursorCharge = (mol.TransitionGroups.Any() ? mol.TransitionGroups.First().TransitionGroup.PrecursorCharge : 0) * (invertCharges ? -1 : 1); var isotopeLabelType = mol.TransitionGroups.Any() ? mol.TransitionGroups.First().TransitionGroup.LabelType : IsotopeLabelType.light; var moleculeCustomIon = ConvertToSmallMolecule(mode, document, mol, precursorCharge, isotopeLabelType); var precursorCustomIon = moleculeCustomIon; var newPeptide = new Peptide(moleculeCustomIon); var newPeptideDocNode = new PeptideDocNode(newPeptide, newdoc.Settings, null, null, null, null, mol.ExplicitRetentionTime, note, mol.Results, new TransitionGroupDocNode[0], mol.AutoManageChildren); foreach (var transitionGroupDocNode in mol.TransitionGroups) { if (transitionGroupDocNode.IsDecoy) { if (ignoreDecoys) continue; throw new Exception("There is no translation from decoy to small molecules"); // Not L10N } if (transitionGroupDocNode.TransitionGroup.PrecursorCharge != Math.Abs(precursorCharge) || !Equals(isotopeLabelType, transitionGroupDocNode.TransitionGroup.LabelType)) { // Different charges or labels mean different ion formulas precursorCharge = transitionGroupDocNode.TransitionGroup.PrecursorCharge * (invertCharges ? -1 : 1); isotopeLabelType = transitionGroupDocNode.TransitionGroup.LabelType; precursorCustomIon = ConvertToSmallMolecule(mode, document, mol, precursorCharge, isotopeLabelType); } var newTransitionGroup = new TransitionGroup(newPeptide, precursorCustomIon, precursorCharge, isotopeLabelType); // Remove any library info, since for the moment at least small molecules don't support this and it won't roundtrip var resultsNew = RemoveTransitionGroupChromInfoLibraryInfo(transitionGroupDocNode); var newTransitionGroupDocNode = new TransitionGroupDocNode(newTransitionGroup, transitionGroupDocNode.Annotations.Merge(note), document.Settings, null, null, transitionGroupDocNode.ExplicitValues, resultsNew, null, transitionGroupDocNode.AutoManageChildren); var mzShift = invertCharges ? 2.0 * BioMassCalc.MassProton : 0; // We removed hydrogen rather than added Assume.IsTrue((Math.Abs(newTransitionGroupDocNode.PrecursorMz + mzShift - transitionGroupDocNode.PrecursorMz) - Math.Abs(transitionGroupDocNode.TransitionGroup.PrecursorCharge * BioMassCalc.MassElectron)) <= 1E-5); foreach (var transition in transitionGroupDocNode.Transitions) { double mass = 0; var transitionCharge = transition.Transition.Charge * (invertCharges ? -1 : 1); var ionType = IonType.custom; CustomIon transitionCustomIon; double mzShiftTransition = 0; if (transition.Transition.IonType == IonType.precursor) { ionType = IonType.precursor; transitionCustomIon = new DocNodeCustomIon(precursorCustomIon.Formula, string.IsNullOrEmpty(precursorCustomIon.Formula) ? precursorCustomIon.MonoisotopicMass : (double?) null, string.IsNullOrEmpty(precursorCustomIon.Formula) ? precursorCustomIon.AverageMass : (double?) null, SmallMoleculeNameFromPeptide(peptideSequence, transitionCharge)); mzShiftTransition = invertCharges ? 2.0 * BioMassCalc.MassProton : 0; // We removed hydrogen rather than added } else if (transition.Transition.IonType == IonType.custom) { transitionCustomIon = transition.Transition.CustomIon; mass = transitionCustomIon.MonoisotopicMass; } else { // TODO - try to get fragment formula? mass = BioMassCalc.CalculateIonMassFromMz(transition.Mz, transition.Transition.Charge); transitionCustomIon = new DocNodeCustomIon(mass, mass,// We can't really get at mono vs average mass from m/z, but for test purposes this is fine transition.Transition.FragmentIonName); } if (mode == ConvertToSmallMoleculesMode.masses_and_names) { // Discard the formula if we're testing the use of mass-with-names (for matching in ratio calcs) target specification transitionCustomIon = new DocNodeCustomIon(transitionCustomIon.MonoisotopicMass, transitionCustomIon.AverageMass, transition.Transition.FragmentIonName); } else if (mode == ConvertToSmallMoleculesMode.masses_only) { // Discard the formula and name if we're testing the use of mass-only target specification transitionCustomIon = new DocNodeCustomIon(transitionCustomIon.MonoisotopicMass, transitionCustomIon.AverageMass); } var newTransition = new Transition(newTransitionGroup, ionType, null, transition.Transition.MassIndex, transition.Transition.Charge * (invertCharges ? -1 : 1), null, transitionCustomIon); if (ionType == IonType.precursor) { mass = document.Settings.GetFragmentMass(transitionGroupDocNode.TransitionGroup.LabelType, null, newTransition, newTransitionGroupDocNode.IsotopeDist); } var newTransitionDocNode = new TransitionDocNode(newTransition, transition.Annotations.Merge(note), null, mass, transition.IsotopeDistInfo, null, transition.Results); Assume.IsTrue((Math.Abs(newTransitionDocNode.Mz + mzShiftTransition - transition.Mz) - Math.Abs(transitionGroupDocNode.TransitionGroup.PrecursorCharge * BioMassCalc.MassElectron)) <= 1E-5, String.Format("unexpected mz difference {0}-{1}={2}", newTransitionDocNode.Mz , transition.Mz, newTransitionDocNode.Mz - transition.Mz)); // Not L10N newTransitionGroupDocNode = (TransitionGroupDocNode)newTransitionGroupDocNode.Add(newTransitionDocNode); } if (newPeptideDocNode != null) newPeptideDocNode = (PeptideDocNode)newPeptideDocNode.Add(newTransitionGroupDocNode); } newPeptideGroupDocNode = (PeptideGroupDocNode)newPeptideGroupDocNode.Add(newPeptideDocNode); } newdoc = (SrmDocument)newdoc.Add(newPeptideGroupDocNode); } } // No retention time prediction for small molecules (yet?) newdoc = newdoc.ChangeSettings(newdoc.Settings.ChangePeptideSettings(newdoc.Settings.PeptideSettings.ChangePrediction( newdoc.Settings.PeptideSettings.Prediction.ChangeRetentionTime(null)))); return newdoc; }
public static TransitionDocNode FromTransitionProto(StringPool stringPool, SrmSettings settings, TransitionGroup group, ExplicitMods mods, IsotopeDistInfo isotopeDist, SkylineDocumentProto.Types.Transition transitionProto) { IonType ionType = DataValues.FromIonType(transitionProto.FragmentType); MeasuredIon measuredIon = null; if (transitionProto.MeasuredIonName != null) { measuredIon = settings.TransitionSettings.Filter.MeasuredIons.SingleOrDefault( i => i.Name.Equals(transitionProto.MeasuredIonName.Value)); if (measuredIon == null) { throw new InvalidDataException(string.Format(Resources.TransitionInfo_ReadXmlAttributes_The_reporter_ion__0__was_not_found_in_the_transition_filter_settings_, transitionProto.MeasuredIonName)); } ionType = IonType.custom; } bool isCustom = Transition.IsCustom(ionType, group); bool isPrecursor = Transition.IsPrecursor(ionType); CustomMolecule customIon = null; if (isCustom) { if (measuredIon != null) { customIon = measuredIon.SettingsCustomIon; } else if (isPrecursor) { customIon = group.CustomMolecule; } else { var formula = DataValues.FromOptional(transitionProto.Formula); var moleculeID = MoleculeAccessionNumbers.FromString(DataValues.FromOptional(transitionProto.MoleculeId)); // Tab separated list of InChiKey, CAS etc var monoMassH = DataValues.FromOptional(transitionProto.MonoMassH); var averageMassH = DataValues.FromOptional(transitionProto.AverageMassH); var monoMass = DataValues.FromOptional(transitionProto.MonoMass) ?? monoMassH; var averageMass = DataValues.FromOptional(transitionProto.AverageMass) ?? averageMassH; customIon = new CustomMolecule(formula, new TypedMass(monoMass.Value, monoMassH.HasValue ? MassType.MonoisotopicMassH : MassType.Monoisotopic), new TypedMass(averageMass.Value, averageMassH.HasValue ? MassType.AverageMassH : MassType.Average), DataValues.FromOptional(transitionProto.CustomIonName), moleculeID); } } Transition transition; var adductString = DataValues.FromOptional(transitionProto.Adduct); var adduct = string.IsNullOrEmpty(adductString) ? Adduct.FromChargeProtonated(transitionProto.Charge) : Adduct.FromStringAssumeChargeOnly(adductString); if (isCustom) { transition = new Transition(group, isPrecursor ? group.PrecursorAdduct :adduct, transitionProto.MassIndex, customIon, ionType); } else if (isPrecursor) { transition = new Transition(group, ionType, group.Peptide.Length - 1, transitionProto.MassIndex, group.PrecursorAdduct, DataValues.FromOptional(transitionProto.DecoyMassShift)); } else { int offset = Transition.OrdinalToOffset(ionType, transitionProto.FragmentOrdinal, group.Peptide.Length); transition = new Transition(group, ionType, offset, transitionProto.MassIndex, adduct, DataValues.FromOptional(transitionProto.DecoyMassShift)); } var losses = TransitionLosses.FromLossProtos(settings, transitionProto.Losses); var mass = settings.GetFragmentMass(group, mods, transition, isotopeDist); var isotopeDistInfo = GetIsotopeDistInfo(transition, losses, isotopeDist); if (group.DecoyMassShift.HasValue && transitionProto.DecoyMassShift == null) { throw new InvalidDataException(Resources.SrmDocument_ReadTransitionXml_All_transitions_of_decoy_precursors_must_have_a_decoy_mass_shift); } TransitionLibInfo libInfo = null; if (transitionProto.LibInfo != null) { libInfo = new TransitionLibInfo(transitionProto.LibInfo.Rank, transitionProto.LibInfo.Intensity); } var annotations = Annotations.FromProtoAnnotations(stringPool, transitionProto.Annotations); var results = TransitionChromInfo.FromProtoTransitionResults(stringPool, settings, transitionProto.Results); return(new TransitionDocNode(transition, annotations, losses, mass, new TransitionQuantInfo(isotopeDistInfo, libInfo, !transitionProto.NotQuantitative), results)); }
private TransitionDocNode GetMoleculeTransition(SrmDocument document, DataGridViewRow row, Peptide pep, TransitionGroup group, bool requireProductInfo) { var massType = document.Settings.TransitionSettings.Prediction.FragmentMassType; var molecule = ReadPrecursorOrProductColumns(document, row, !requireProductInfo); // Re-read the product columns, or copy precursor if (requireProductInfo && molecule == null) { return null; } var ion = molecule.ToCustomIon(); var ionType = (!requireProductInfo || // We inspected the input list and found only precursor info ((ion.MonoisotopicMass.Equals(pep.CustomIon.MonoisotopicMass) && ion.AverageMass.Equals(pep.CustomIon.AverageMass)))) // Same mass, must be a precursor transition ? IonType.precursor : IonType.custom; double mass = ion.GetMass(massType); var transition = new Transition(group, molecule.Charge, null, ion, ionType); var annotations = document.Annotations; if (!string.IsNullOrEmpty(molecule.Note)) { var note = document.Annotations.Note; note = string.IsNullOrEmpty(note) ? molecule.Note : (note + "\r\n" + molecule.Note); // Not L10N annotations = new Annotations(note, document.Annotations.ListAnnotations(), 0); } return new TransitionDocNode(transition, annotations, null, mass, null, null, null); }
public static Adduct CalcProductCharge(TypedMass productPrecursorMass, Adduct precursorCharge, IList <IonType> acceptedIonTypes, IonTable <TypedMass> productMasses, IList <IList <ExplicitLoss> > potentialLosses, double productMz, double tolerance, MassType massType, MassShiftType massShiftType, out IonType?ionType, out int?ordinal, out TransitionLosses losses, out int massShift) { // Get length of fragment ion mass array int len = productMasses.GetLength(1); // Check all possible ion types and offsets double minDelta = double.MaxValue; var bestCharge = Adduct.EMPTY; IonType? bestIonType = null; int? bestOrdinal = null; TransitionLosses bestLosses = null; int bestMassShift = 0; // Check to see if it is the precursor foreach (var lossesTrial in TransitionGroup.CalcTransitionLosses(IonType.precursor, 0, massType, potentialLosses)) { var productMass = productPrecursorMass - (lossesTrial != null ? lossesTrial.Mass : 0); int potentialMassShift; int nearestCharge; var charge = CalcProductCharge(productMass, productMz, tolerance, false, precursorCharge, massShiftType, out potentialMassShift, out nearestCharge); if (Equals(charge, precursorCharge)) { double potentialMz = SequenceMassCalc.GetMZ(productMass, charge) + potentialMassShift; double delta = Math.Abs(productMz - potentialMz); if (CompareIonMatch(delta, lossesTrial, potentialMassShift, minDelta, bestLosses, bestMassShift) < 0) { bestCharge = charge; bestIonType = IonType.precursor; bestOrdinal = len + 1; bestLosses = lossesTrial; bestMassShift = potentialMassShift; minDelta = delta; } } } var categoryLast = -1; foreach (var typeAccepted in GetIonTypes(acceptedIonTypes)) { var type = typeAccepted.IonType; var category = typeAccepted.IonCategory; // Types have priorities. If changing type category, and there is already a // suitable answer stop looking. if (category != categoryLast && MatchMz(minDelta, tolerance)) { break; } categoryLast = category; for (int offset = 0; offset < len; offset++) { foreach (var lossesTrial in TransitionGroup.CalcTransitionLosses(type, offset, massType, potentialLosses)) { // Look for the closest match. var productMass = productMasses[type, offset]; if (lossesTrial != null) { productMass -= lossesTrial.Mass; } int potentialMassShift; int nearestCharge; var chargeFound = CalcProductCharge(productMass, productMz, tolerance, false, precursorCharge, massShiftType, out potentialMassShift, out nearestCharge); if (!chargeFound.IsEmpty) { var charge = chargeFound; double potentialMz = SequenceMassCalc.GetMZ(productMass, charge) + potentialMassShift; double delta = Math.Abs(productMz - potentialMz); if (CompareIonMatch(delta, lossesTrial, potentialMassShift, minDelta, bestLosses, bestMassShift) < 0) { bestCharge = charge; bestIonType = type; // The peptide length is 1 longer than the mass array bestOrdinal = Transition.OffsetToOrdinal(type, offset, len + 1); bestLosses = lossesTrial; bestMassShift = potentialMassShift; minDelta = delta; } } } } } ionType = bestIonType; ordinal = bestOrdinal; losses = bestLosses; massShift = bestMassShift; return(bestCharge); }