public TransitionLoss(StaticMod precursorMod, FragmentLoss loss, MassType massType) : this() { PrecursorMod = precursorMod; Loss = loss; Mass = Loss.GetMass(massType); }
public DatabaseSearcher(IList<string> dataFilepaths, int minimumAssumedPrecursorChargeState, int maximumAssumedPrecursorChargeState, double absoluteThreshold, double relativeThresholdPercent, int maximumNumberOfPeaks, bool assignChargeStates, bool deisotope, string proteinFastaDatabaseFilepath, bool onTheFlyDecoys, Protease protease, int maximumMissedCleavages, InitiatorMethionineBehavior initiatorMethionineBehavior, IEnumerable<Modification> fixedModifications, IEnumerable<Modification> variableModifications, int maximumVariableModificationIsoforms, MassTolerance precursorMassTolerance, MassType precursorMassType, bool precursorMonoisotopicPeakCorrection, int minimumPrecursorMonoisotopicPeakOffset, int maximumPrecursorMonoisotopicPeakOffset, MassTolerance productMassTolerance, MassType productMassType, double maximumFalseDiscoveryRate, bool considerModifiedFormsAsUniquePeptides, int maximumThreads, bool minimizeMemoryUsage, string outputFolder) { this.dataFilepaths = dataFilepaths; this.assignChargeStates = assignChargeStates; this.deisotope = deisotope; this.proteinFastaDatabaseFilepath = proteinFastaDatabaseFilepath; this.onTheFlyDecoys = onTheFlyDecoys; this.protease = protease; this.maximumMissedCleavages = maximumMissedCleavages; this.initiatorMethionineBehavior = initiatorMethionineBehavior; this.fixedModifications = fixedModifications; this.variableModifications = variableModifications; this.maximumVariableModificationIsoforms = maximumVariableModificationIsoforms; this.minimumAssumedPrecursorChargeState = minimumAssumedPrecursorChargeState; this.maximumAssumedPrecursorChargeState = maximumAssumedPrecursorChargeState; this.absoluteThreshold = absoluteThreshold; this.relativeThresholdPercent = relativeThresholdPercent; this.maximumNumberOfPeaks = maximumNumberOfPeaks; this.precursorMassTolerance = precursorMassTolerance; this.precursorMassType = precursorMassType; this.precursorMonoisotopicPeakCorrection = precursorMonoisotopicPeakCorrection; this.minimumPrecursorMonoisotopicPeakOffset = minimumPrecursorMonoisotopicPeakOffset; this.maximumPrecursorMonoisotopicPeakOffset = maximumPrecursorMonoisotopicPeakOffset; this.productMassTolerance = productMassTolerance; this.productMassType = productMassType; this.maximumFalseDiscoveryRate = maximumFalseDiscoveryRate; this.considerModifiedFormsAsUniquePeptides = considerModifiedFormsAsUniquePeptides; this.maximumThreads = maximumThreads; this.minimizeMemoryUsage = minimizeMemoryUsage; this.outputFolder = outputFolder; }
/// <summary> /// Create a simple mass calculator for use in calculating /// protein, peptide and fragment masses. /// </summary> /// <param name="type">Monoisotopic or average mass calculations</param> public BioMassCalc(MassType type) { MassType = type; AddMass(H, 1.007825035, 1.00794); //Unimod AddMass(H2, 2.014101779, 2.014101779); //Unimod AddMass(O, 15.99491463, 15.9994); //Unimod AddMass(O17, 16.9991315, 16.9991315); //NIST AddMass(O18, 17.9991604, 17.9991604); //NIST, Unimod=17.9991603 AddMass(N, 14.003074, 14.0067); //Unimod AddMass(N15, 15.0001088984, 15.0001088984); //NIST, Unimod=15.00010897 AddMass(C, 12.0, 12.01085); //MacCoss average AddMass(C13, 13.0033548378, 13.0033548378); //NIST, Unimod=13.00335483 AddMass(S, 31.9720707, 32.065); //Unimod AddMass(P, 30.973762, 30.973761); //Unimod AddMass(Se, 79.9165196, 78.96); //Unimod, Most abundant Se isotope is 80 AddMass(Li, 7.016003, 6.941); //Unimod AddMass(F, 18.99840322, 18.9984032); //Unimod AddMass(Na, 22.9897677, 22.98977); //Unimod AddMass(S, 31.9720707, 32.065); //Unimod AddMass(Cl, 34.96885272, 35.453); //Unimod AddMass(K, 38.9637074, 39.0983); //Unimod AddMass(Ca, 39.9625906, 40.078); //Unimod AddMass(Fe, 55.9349393, 55.845); //Unimod AddMass(Ni, 57.9353462, 58.6934); //Unimod AddMass(Cu, 62.9295989, 63.546); //Unimod AddMass(Zn, 63.9291448, 65.409); //Unimod AddMass(Br, 78.9183361, 79.904); //Unimod AddMass(Mo, 97.9054073, 95.94); //Unimod AddMass(Ag, 106.905092, 107.8682); //Unimod AddMass(I, 126.904473, 126.90447); //Unimod AddMass(Au, 196.966543, 196.96655); //Unimod AddMass(Hg, 201.970617, 200.59); //Unimod AddMass(B, 11.0093055, 10.811); AddMass(As, 74.9215942, 74.9215942); AddMass(Cd, 113.903357, 112.411); AddMass(Cr, 51.9405098, 51.9961); AddMass(Co, 58.9331976, 58.933195); AddMass(Mn, 54.9380471, 54.938045); AddMass(Mg, 23.9850423, 24.305); AddMass(Si, 27.9769265, 28.085); // Per Wikipedia }
public IList<double> GetModMasses(MassType massType, IsotopeLabelType labelType) { var index = GetModIndex(labelType); // This will throw, if the modification type is not found. return _modifications[index].GetModMasses(massType); }
public TransitionLosses(List<TransitionLoss> losses, MassType massType) { // Make sure losses are always in a consistent order, ascending my mass if (losses.Count > 1) losses.Sort((l1, l2) => Comparer<double>.Default.Compare(l1.Mass, l2.Mass)); _losses = new OneOrManyList<TransitionLoss>(losses); MassType = massType; Mass = CalcLossMass(Losses); }
public double GetMass(MassType massType) { return massType == MassType.Monoisotopic ? MonoisotopicMass : AverageMass; }
public double this[ProductType productType, MassType massType] { get { return PRODUCT_CAP_MASSES[(int)productType, (int)massType]; } }
private static SequenceMassCalc CreateMassCalc(MassType type, IEnumerable<StaticMod> staticMods) { return CreateMassCalc(type, staticMods, null); }
public static bool IsMonoisotopic(this MassType val) { return(!val.IsAverage()); }
public static MassType GetEnum(string enumValue, MassType defaultValue) { return(Helpers.EnumFromLocalizedString(enumValue, LOCALIZED_VALUES, defaultValue)); }
public static string GetLocalizedString(this MassType val) { return(LOCALIZED_VALUES[(int)val & (int)MassType.Average]); // Strip off bMassH, bHeavy }
public TypedMass(double value, MassType t) { _value = value; _massType = t; }
public static bool IsHeavy(this MassType val) { return((val & MassType.bHeavy) != 0); }
public double GetMass(MassType massType) => _hasMass.GetMass(massType);
public double GetMass(MassType massType) => _chemicalFormula.GetMass(massType);
public static bool IsAverage(this MassType val) { return((val & MassType.Average) != 0); }
public static void SetPrecursorMassType(MassType precursorMassType) { PeptideSpectrumMatch.precursorMassType = precursorMassType; }
public static bool IsMassH(this MassType val) { return((val & MassType.bMassH) != 0); }
private ImmutableList<TypedMassCalc> CreateMassCalcs(MassType type) { var calcs = new List<TypedMassCalc>(); var mods = PeptideSettings.Modifications; var modsStatic = mods.StaticModifications; calcs.Add(new TypedMassCalc(IsotopeLabelType.light, CreateMassCalc(type, modsStatic))); foreach (var typedMods in mods.GetHeavyModifications()) { // Only add a heavy calculator for this type if it contains // implicit modifications. var modsHeavy = typedMods.Modifications; if (modsHeavy.Contains(mod => !mod.IsExplicit)) { calcs.Add(new TypedMassCalc(typedMods.LabelType, CreateMassCalc(type, modsStatic, modsHeavy))); } } return MakeReadOnly(calcs.ToArray()); }
public double GetScore(MassType type) { return(score.GetScore(type)); }
public double GetMass(MassType massType) { return (massType == MassType.Average) ? AverageMass : MonoisotopicMass; }
public string ToString(MassType massType) { return(Formula != null? string.Format("{0:F04} - {1}", GetMass(massType), Formula) : // Not L10N string.Format("{0:F04}", GetMass(massType))); // Not L10N }
public string ToString(MassType massType) { return Formula != null ? string.Format("{0:F04} - {1}", GetMass(massType), Formula) : // Not L10N string.Format("{0:F04}", GetMass(massType)); // Not L10N }
public static IList <IList <ExplicitLoss> > CalcPotentialLosses(Target target, PeptideModifications pepMods, ExplicitMods mods, MassType massType) { if (!target.IsProteomic || string.IsNullOrEmpty(target.Sequence)) { return(new IList <ExplicitLoss> [0]); } var sequence = target.Sequence; // First build a list of the amino acids in this peptide which can be experience loss, // and the losses which apply to them. IList <KeyValuePair <IList <TransitionLoss>, int> > listIndexedListLosses = null; // Add losses for any explicit static modifications bool explicitStatic = (mods != null && mods.StaticModifications != null); bool explicitLosses = (explicitStatic && mods.HasNeutralLosses); // Add the losses for the implicit modifications, if there // are no explicit static modifications, or if explicit static // modifications exist, but they are for variable modifications. bool implicitAllowed = (!explicitStatic || mods.IsVariableStaticMods); bool implicitLosses = (implicitAllowed && pepMods.HasNeutralLosses); if (explicitLosses || implicitLosses) { // Enumerate each amino acid in the sequence int len = sequence.Length; for (int i = 0; i < len; i++) { char aa = sequence[i]; if (implicitLosses) { // Test implicit modifications to see if they apply foreach (var mod in pepMods.NeutralLossModifications) { // If the modification does apply, store it in the list if (mod.IsLoss(aa, i, len)) { listIndexedListLosses = AddNeutralLosses(i, mod, massType, listIndexedListLosses); } } } if (explicitLosses) { foreach (var mod in mods.NeutralLossModifications) { if (mod.IndexAA == i) { listIndexedListLosses = AddNeutralLosses(mod.IndexAA, mod.Modification, massType, listIndexedListLosses); } } } } } // If no losses were found, return null if (listIndexedListLosses == null) { return(null); } var listListLosses = new List <IList <ExplicitLoss> >(); int maxLossCount = Math.Min(pepMods.MaxNeutralLosses, listIndexedListLosses.Count); for (int lossCount = 1; lossCount <= maxLossCount; lossCount++) { var lossStateMachine = new NeutralLossStateMachine(lossCount, listIndexedListLosses); foreach (var listLosses in lossStateMachine.GetStates()) { listListLosses.Add(listLosses); } } return(listListLosses); }
public TransitionLosses ChangeMassType(MassType massType) { var listLosses = new List<TransitionLoss>(); foreach (var loss in Losses) listLosses.Add(new TransitionLoss(loss.PrecursorMod, loss.Loss, massType)); if (ArrayUtil.EqualsDeep(listLosses, _losses)) return this; return ChangeProp(ImClone(this), im => { im._losses = new OneOrManyList<TransitionLoss>(listLosses); im.Mass = CalcLossMass(im.Losses); }); }
private static IList <KeyValuePair <IList <TransitionLoss>, int> > AddNeutralLosses(int indexAA, StaticMod mod, MassType massType, IList <KeyValuePair <IList <TransitionLoss>, int> > listListMods) { if (listListMods == null) { listListMods = new List <KeyValuePair <IList <TransitionLoss>, int> >(); } if (listListMods.Count == 0 || listListMods[listListMods.Count - 1].Value != indexAA) { listListMods.Add(new KeyValuePair <IList <TransitionLoss>, int>(new List <TransitionLoss>(), indexAA)); } foreach (var loss in mod.Losses) { listListMods[listListMods.Count - 1].Key.Add(new TransitionLoss(mod, loss, massType)); } return(listListMods); }
public IList<double> GetModMasses(MassType massType) { return (massType == MassType.Monoisotopic ? _modMassesMono : _modMassesAvg); }
/// <summary> /// Calculate all possible transition losses that apply to a transition with /// a specific type and cleavage offset, given all of the potential loss permutations /// for the precursor. /// </summary> public static IEnumerable <TransitionLosses> CalcTransitionLosses(IonType type, int cleavageOffset, MassType massType, IEnumerable <IList <ExplicitLoss> > potentialLosses) { // First return no losses yield return(null); if (type.Equals(IonType.custom)) { foreach (var potentialLoss in potentialLosses) { yield return(GetCustomTransitionLosses(potentialLoss, massType)); } } else if (potentialLosses != null) { // Try to avoid allocating a whole list for this, as in many cases // there should be only one loss TransitionLosses firstLosses = null; List <TransitionLosses> allLosses = null; HashSet <double> allLossMasses = null; foreach (var losses in potentialLosses) { double lossMass = CalcTransitionLossesMass(type, cleavageOffset, massType, losses); if (lossMass == 0 || (firstLosses != null && firstLosses.Mass == lossMass) || (allLossMasses != null && allLossMasses.Contains(lossMass))) { continue; } var tranLosses = CalcTransitionLosses(type, cleavageOffset, massType, losses); if (allLosses == null) { if (firstLosses == null) { firstLosses = tranLosses; } else { allLosses = new List <TransitionLosses> { firstLosses }; allLossMasses = new HashSet <double>(); allLossMasses.Add(firstLosses.Mass); firstLosses = null; } } if (allLosses != null) { allLosses.Add(tranLosses); } if (allLossMasses != null) { allLossMasses.Add(tranLosses.Mass); } } // Handle the single losses case first if (firstLosses != null) { yield return(firstLosses); } else if (allLosses != null) { // If more then one set of transition losses return them sorted by mass allLosses.Sort((l1, l2) => Comparer <double> .Default.Compare(l1.Mass, l2.Mass)); foreach (var tranLosses in allLosses) { yield return(tranLosses); } } } }
public SequenceMassCalc(MassType type) { _massCalc = new BioMassCalc(type); // Not L10N // Mass of a proton, i.e. +1 positive charge, hydrogen atom without its electron. // See http://antoine.frostburg.edu/chem/senese/101/atoms/index.shtml // _massWater = _massCalc.CalculateMass("H2O"); // _massAmmonia = _massCalc.CalculateMass("NH3"); // ReSharper disable NonLocalizedString _massDiffA = -_massCalc.CalculateMassFromFormula("CO"); _massDiffB = 0.0; _massDiffC = _massCalc.CalculateMassFromFormula("NH3"); _massDiffY = _massCalc.CalculateMassFromFormula("H2O"); _massDiffX = _massCalc.CalculateMassFromFormula("CO2"); _massDiffZ = _massDiffY - _massCalc.CalculateMassFromFormula("NH2"); _massCleaveN = _massCalc.CalculateMassFromFormula("H"); _massCleaveC = _massCalc.CalculateMassFromFormula("OH"); // ReSharper restore NonLocalizedString // These numbers are set intentionally smaller than any known instrument // can measure. Filters are then applied to resulting distributions // to get more useful numbers. _massResolution = 0.001; _minimumAbundance = 0.00001; // 0.001% InitAminoAcidMasses(); }
private static TransitionLosses GetCustomTransitionLosses(IEnumerable <ExplicitLoss> losses, MassType massType) { List <TransitionLoss> listLosses = new List <TransitionLoss>(); foreach (var loss in losses) { listLosses.Add(loss.TransitionLoss); } return(new TransitionLosses(listLosses, massType)); }
public static MassType GetEnum(string enumValue, MassType defaultValue) { return Helpers.EnumFromLocalizedString(enumValue, LOCALIZED_VALUES, defaultValue); }
public TypedMass GetMass(MassType massType) { return(massType.IsMonoisotopic() ? MonoisotopicMass : AverageMass); }
public static int CalcProductCharge(double productPrecursorMass, int precursorCharge, double[,] 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, minDeltaNs = double.MaxValue; int bestCharge = 0, bestChargeNs = 0; IonType? bestIonType = null, bestIonTypeNs = null; int? bestOrdinal = null, bestOrdinalNs = null; TransitionLosses bestLosses = null, bestLossesNs = null; int bestMassShift = 0; // Check to see if it is the precursor foreach (var lossesTrial in TransitionGroup.CalcTransitionLosses(IonType.precursor, 0, massType, potentialLosses)) { double productMass = productPrecursorMass - (lossesTrial != null ? lossesTrial.Mass : 0); int potentialMassShift; int nearestCharge; int? charge = CalcProductCharge(productMass, productMz, tolerance, false, precursorCharge, massShiftType, out potentialMassShift, out nearestCharge); if (charge.HasValue && charge.Value == precursorCharge) { double potentialMz = SequenceMassCalc.GetMZ(productMass, charge.Value) + potentialMassShift; double delta = Math.Abs(productMz - potentialMz); if (potentialMassShift == 0 && minDeltaNs > delta) { bestChargeNs = charge.Value; bestIonTypeNs = IonType.precursor; bestOrdinalNs = len + 1; bestLossesNs = lossesTrial; minDeltaNs = delta; } else if (potentialMassShift != 0 && minDelta > delta) { bestCharge = charge.Value; bestIonType = IonType.precursor; bestOrdinal = len + 1; bestLosses = lossesTrial; bestMassShift = potentialMassShift; minDelta = delta; } } } foreach (IonType type in Transition.ALL_TYPES) { // Types have priorities. If moving to a lower priority type, and there is already a // suitable answer stop looking. if ((type == Transition.ALL_TYPES[2] || type == Transition.ALL_TYPES[2]) && (MatchMz(minDelta, tolerance) || MatchMz(minDeltaNs, tolerance))) break; for (int offset = 0; offset < len; offset++) { foreach (var lossesTrial in TransitionGroup.CalcTransitionLosses(type, offset, massType, potentialLosses)) { // Look for the closest match. double productMass = productMasses[(int) type, offset]; if (lossesTrial != null) productMass -= lossesTrial.Mass; int potentialMassShift; int nearestCharge; int? chargeFound = CalcProductCharge(productMass, productMz, tolerance, false, precursorCharge, massShiftType, out potentialMassShift, out nearestCharge); if (chargeFound.HasValue) { int charge = chargeFound.Value; double potentialMz = SequenceMassCalc.GetMZ(productMass, charge) + potentialMassShift; double delta = Math.Abs(productMz - potentialMz); if (potentialMassShift == 0 && minDeltaNs > delta) { bestChargeNs = charge; bestIonTypeNs = type; // The peptide length is 1 longer than the mass array bestOrdinalNs = Transition.OffsetToOrdinal(type, offset, len + 1); bestLossesNs = lossesTrial; minDeltaNs = delta; } else if (potentialMassShift != 0 && minDelta > delta) { 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; } } } } } // Pefer no-shift to shift, even if the shift value is closer if (MatchMz(minDelta, tolerance) && !MatchMz(minDeltaNs, tolerance)) { ionType = bestIonType; ordinal = bestOrdinal; losses = bestLosses; massShift = bestMassShift; return bestCharge; } ionType = bestIonTypeNs; ordinal = bestOrdinalNs; losses = bestLossesNs; massShift = 0; return bestChargeNs; }
public ModifiedSequence(string unmodifiedSequence, IEnumerable <Modification> explicitMods, MassType defaultMassType) { _unmodifiedSequence = unmodifiedSequence; _explicitMods = ImmutableList.ValueOf(explicitMods.OrderBy(mod => mod.IndexAA, SortOrder.Ascending)); _defaultMassType = defaultMassType; }
public override void OnInspectorGUI() { PhysicsObject obj = (PhysicsObject)target; EditorGUILayout.BeginHorizontal(); massType = (MassType)EditorGUILayout.EnumPopup(massType); if (massType==MassType.mass) obj.mass = EditorGUILayout.FloatField(obj.mass); else if (massType==MassType.density) obj.density = EditorGUILayout.FloatField(obj.density); else if (massType==MassType.momentOfInertia) obj.momentOfInertia = EditorGUILayout.FloatField(obj.momentOfInertia); EditorGUILayout.EndHorizontal(); base.OnInspectorGUI(); }
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, ExplicitTransitionValues.EMPTY); 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 SequenceMassCalc CreateMassCalc(MassType type, IEnumerable<StaticMod> staticMods, IEnumerable<StaticMod> heavyMods) { SequenceMassCalc calc = new SequenceMassCalc(type); // Add implicit modifications to the mass calculator calc.AddStaticModifications(from mod in staticMods where !mod.IsExplicit select mod); if (heavyMods != null) { calc.AddHeavyModifications(from mod in heavyMods where !mod.IsExplicit select mod); } return calc; }
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 static void SetProductMassType(MassType productMassType) { AminoAcidPolymer.productMassType = productMassType; }
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); }