Example #1
0
        public Transition(TransitionGroup group, IonType type, int?offset, int?massIndex, int charge, int?decoyMassShift, CustomIon customIon = null)
        {
            _group = group;

            IonType        = type;
            CleavageOffset = offset ?? 0;
            MassIndex      = massIndex ?? 0;
            Charge         = charge;
            DecoyMassShift = decoyMassShift;
            // Small molecule precursor transition should have same custom ion as parent
            if (IsPrecursor(type) && group.IsCustomIon)
            {
                CustomIon = group.CustomIon;
            }
            else
            {
                CustomIon = customIon;
            }
            // Derived values
            if (!IsCustom(type, group))
            {
                Peptide peptide = group.Peptide;
                Ordinal = OffsetToOrdinal(type, (int)offset, peptide.Length);
                AA      = (IsNTerminal()
                    ? peptide.Sequence[(int)offset]
                    : peptide.Sequence[(int)offset + 1]);
            }
            else
            {
                // caller may have passed in offset = group.Peptide.Length - 1, which for custom ions gives -1
                CleavageOffset = 0;
            }
            Validate();
        }
Example #2
0
        public static int CompareGroups(TransitionGroup group1, TransitionGroup group2)
        {
            int chargeDiff = group1.PrecursorCharge - group2.PrecursorCharge;

            if (chargeDiff != 0)
            {
                return(chargeDiff);
            }
            return(group1.LabelType.CompareTo(group2.LabelType));
        }
        public PeptideDocNode PermuteModificationsOnPeptide(SrmDocument document, PeptideGroupDocNode peptideGroupDocNode,
                                                            PeptideDocNode peptideDocNode, List <IsotopeLabelType> partialLabelTypes)
        {
            if (SkipPeptide(peptideDocNode))
            {
                return(peptideDocNode);
            }

            var potentiallyModifiedResidues = PotentiallyModifiedResidues(peptideDocNode, IsotopeModification);

            if (potentiallyModifiedResidues.Count == 0)
            {
                return(peptideDocNode);
            }

            // Create a document containing only one peptide so that "ChangePeptideMods" does not have to walk
            // over a long list of peptides to see which modifications are in use.
            var smallDocument = (SrmDocument)document.ChangeChildren(new DocNode[]
                                                                     { peptideGroupDocNode.ChangeChildren(new DocNode[] { peptideDocNode }) });
            var newTypedExplicitModifications = PermuteTypedExplicitModifications(partialLabelTypes, peptideDocNode, potentiallyModifiedResidues);
            var newExplicitMods = new ExplicitMods(peptideDocNode.Peptide, peptideDocNode.ExplicitMods?.StaticModifications, newTypedExplicitModifications);
            var identityPath    = new IdentityPath(peptideGroupDocNode.PeptideGroup, peptideDocNode.Peptide);

            smallDocument = smallDocument.ChangePeptideMods(identityPath, newExplicitMods, false, GlobalStaticMods,
                                                            GlobalIsotopeMods);
            peptideDocNode = (PeptideDocNode)smallDocument.FindPeptideGroup(peptideGroupDocNode.PeptideGroup).FindNode(peptideDocNode.Peptide);
            var lightChargeStates   = peptideDocNode.TransitionGroups.Where(tg => tg.IsLight).Select(tg => tg.PrecursorCharge).Distinct().ToList();
            var chargeStatesByLabel =
                peptideDocNode.TransitionGroups.ToLookup(tg => tg.LabelType, tg => tg.PrecursorCharge);
            var transitionGroupsToAdd = new List <TransitionGroupDocNode>();

            foreach (var typedExplicitModifications in newExplicitMods.GetHeavyModifications())
            {
                var labelType = typedExplicitModifications.LabelType;
                foreach (var chargeState in lightChargeStates.Except(chargeStatesByLabel[labelType]))
                {
                    var tranGroup = new TransitionGroup(peptideDocNode.Peptide, Adduct.FromChargeProtonated(chargeState), labelType);
                    TransitionDocNode[] transitions = peptideDocNode.GetMatchingTransitions(tranGroup, smallDocument.Settings, newExplicitMods);

                    var nodeGroup = new TransitionGroupDocNode(tranGroup, transitions);
                    nodeGroup = nodeGroup.ChangeSettings(smallDocument.Settings, peptideDocNode, newExplicitMods, SrmSettingsDiff.ALL);
                    transitionGroupsToAdd.Add(nodeGroup);
                }
            }

            if (transitionGroupsToAdd.Any())
            {
                var newChildren = peptideDocNode.TransitionGroups.Concat(transitionGroupsToAdd).ToList();
                newChildren.Sort(Peptide.CompareGroups);
                peptideDocNode = (PeptideDocNode)peptideDocNode.ChangeChildren(newChildren.Cast <DocNode>().ToList());
            }
            return(peptideDocNode);
        }
Example #4
0
        public bool Equals(TransitionGroup obj)
        {
            if (ReferenceEquals(null, obj))
            {
                return(false);
            }
            if (ReferenceEquals(this, obj))
            {
                return(true);
            }
            bool equal = Equals(obj._peptide, _peptide) &&
                         Equals(obj.CustomIon, CustomIon) &&
                         obj.PrecursorCharge == PrecursorCharge &&
                         obj.LabelType.Equals(LabelType) &&
                         obj.DecoyMassShift.Equals(DecoyMassShift);

            return(equal); // For debugging convenience
        }
Example #5
0
        public Transition(TransitionGroup group, IonType type, int?offset, int?massIndex, Adduct adduct,
                          int?decoyMassShift, CustomMolecule customMolecule = null)
        {
            _group = group;

            IonType        = type;
            CleavageOffset = offset ?? 0;
            MassIndex      = massIndex ?? 0;
            Adduct         = adduct;
            DecoyMassShift = decoyMassShift;
            // Small molecule precursor transition should have same custom molecule as parent
            if (IsPrecursor(type) && group.IsCustomIon)
            {
                CustomIon = new CustomIon(group.CustomMolecule, adduct);
            }
            else if (customMolecule is CustomIon)
            {
                // As with reporter ions
                CustomIon = (CustomIon)customMolecule;
                Assume.IsTrue(Equals(adduct.AdductCharge, CustomIon.Adduct.AdductCharge));
                Adduct = CustomIon.Adduct; // Ion mass is part of formula, so use charge only adduct
            }
            else if (customMolecule != null)
            {
                CustomIon = new CustomIon(customMolecule, adduct);
            }
            // Derived values
            if (!IsCustom(type, group))
            {
                Peptide peptide = group.Peptide;
                Ordinal = OffsetToOrdinal(type, (int)offset, peptide.Length);
                AA      = (IsNTerminal()
                    ? peptide.Sequence[(int)offset]
                    : peptide.Sequence[(int)offset + 1]);
            }
            else
            {
                // caller may have passed in offset = group.Peptide.Length - 1, which for custom ions gives -1
                CleavageOffset = 0;
            }
            Validate();
        }
        public PeptideDocNode CreateDocNodeFromSettings(LibKey key, Peptide peptide, SrmSettingsDiff diff, out TransitionGroupDocNode nodeGroupMatched)
        {
            if (!key.Target.IsProteomic)
            {
                // Scan the spectral lib entry for top N ranked (for now, that's just by intensity with high mz as tie breaker) fragments,
                // add those as mass-only fragments, or with more detail if peak annotations are present.
                foreach (var nodePep in peptide.CreateDocNodes(Settings, new MaxModFilter(0)))
                {
                    SpectrumHeaderInfo libInfo;
                    if (nodePep != null && Settings.PeptideSettings.Libraries.TryGetLibInfo(key, out libInfo))
                    {
                        var isotopeLabelType = key.Adduct.HasIsotopeLabels ? IsotopeLabelType.heavy : IsotopeLabelType.light;
                        var group            = new TransitionGroup(peptide, key.Adduct, isotopeLabelType);
                        nodeGroupMatched = new TransitionGroupDocNode(group, Annotations.EMPTY, Settings, null, libInfo, ExplicitTransitionGroupValues.EMPTY, null, null, false);
                        SpectrumPeaksInfo spectrum;
                        if (Settings.PeptideSettings.Libraries.TryLoadSpectrum(key, out spectrum))
                        {
                            // Add fragment and precursor transitions as needed
                            var transitionDocNodes =
                                Settings.TransitionSettings.Filter.SmallMoleculeIonTypes.Contains(IonType.precursor)
                                    ? nodeGroupMatched.GetPrecursorChoices(Settings, null, true) // Gives list of precursors
                                    : new List <DocNode>();

                            if (Settings.TransitionSettings.Filter.SmallMoleculeIonTypes.Contains(IonType.custom))
                            {
                                GetSmallMoleculeFragments(key, nodeGroupMatched, spectrum, transitionDocNodes);
                            }
                            nodeGroupMatched = (TransitionGroupDocNode)nodeGroupMatched.ChangeChildren(transitionDocNodes);
                            return((PeptideDocNode)nodePep.ChangeChildren(new List <DocNode>()
                            {
                                nodeGroupMatched
                            }));
                        }
                    }
                }
                nodeGroupMatched = null;
                return(null);
            }
            return(CreateDocNodeFromSettings(key.Target, peptide, diff, out nodeGroupMatched));
        }
Example #7
0
        public static Adduct CalcProductCharge(TypedMass productPrecursorMass,
                                               int?productZ,
                                               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 = null;
            double?minFragmentMass = null, maxFragmentMass = null, maxLoss = null;

            if (massShiftType == MassShiftType.none)
            {
                if (!productZ.HasValue)
                {
                    minFragmentMass = productMz - tolerance;
                }
                else
                {
                    minFragmentMass = SequenceMassCalc.GetMH(productMz - tolerance, productZ.Value);
                    maxFragmentMass = SequenceMassCalc.GetMH(productMz + tolerance, productZ.Value);
                }
            }

            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;
                if (lossesTrial != null)
                {
                    productMass -= lossesTrial.Mass;
                    maxLoss      = Math.Max(maxLoss ?? 0, lossesTrial.Mass);
                }
                int potentialMassShift;
                int nearestCharge;
                var charge = CalcProductCharge(productMass, productZ, 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;
                    }
                }
            }

            if (maxLoss.HasValue)
            {
                maxFragmentMass += maxLoss.Value;
            }

            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 && minDelta.HasValue && MatchMz(minDelta.Value, tolerance))
                {
                    break;
                }
                categoryLast = category;

                // The peptide length is 1 longer than the mass array
                for (int ord = len; ord > 0; ord--)
                {
                    int offset          = Transition.OrdinalToOffset(type, ord, len + 1);
                    var productMassBase = productMasses[type, offset];
                    // Until below the maximum fragment mass no possible matches
                    if (maxFragmentMass.HasValue && productMassBase > maxFragmentMass.Value)
                    {
                        continue;
                    }
                    // Once below the minimum fragment mass no more possible matches, so stop
                    if (minFragmentMass.HasValue && productMassBase < minFragmentMass.Value)
                    {
                        break;
                    }

                    foreach (var lossesTrial in TransitionGroup.CalcTransitionLosses(type, offset, massType, potentialLosses))
                    {
                        // Look for the closest match.
                        var productMass = productMassBase;
                        if (lossesTrial != null)
                        {
                            productMass -= lossesTrial.Mass;
                        }
                        int potentialMassShift;
                        int nearestCharge;
                        var chargeFound = CalcProductCharge(productMass, productZ, 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;
                                bestOrdinal   = ord;
                                bestLosses    = lossesTrial;
                                bestMassShift = potentialMassShift;

                                minDelta = delta;
                            }
                        }
                    }
                }
            }

            ionType   = bestIonType;
            ordinal   = bestOrdinal;
            losses    = bestLosses;
            massShift = bestMassShift;
            return(bestCharge);
        }
Example #8
0
 public Transition(TransitionGroup group, Adduct charge, int?massIndex, CustomMolecule customMolecule, IonType type = IonType.custom)
     : this(group, type, null, massIndex, charge, null, customMolecule)
 {
 }
Example #9
0
 public Transition(TransitionGroup group, IonType type, int offset, int massIndex, Adduct charge)
     : this(group, type, offset, massIndex, charge, null)
 {
 }
Example #10
0
 /// <summary>
 /// Creates a precursor transition
 /// </summary>
 /// <param name="group">The <see cref="TransitionGroup"/> which the transition represents</param>
 /// <param name="massIndex">Isotope mass shift</param>
 /// <param name="productAdduct">Adduct on the transition</param>
 /// <param name="customMolecule">Non-null if this is a custom transition</param>
 public Transition(TransitionGroup group, int massIndex, Adduct productAdduct, CustomMolecule customMolecule = null)
     : this(group, IonType.precursor, group.Peptide.Length - 1, massIndex, productAdduct, null, customMolecule)
 {
 }
Example #11
0
 public static bool IsCustom(IonType type, TransitionGroup parent)
 {
     return(type == IonType.custom || (type == IonType.precursor && parent.IsCustomIon));
 }
Example #12
0
        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);
        }
Example #13
0
        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      = null;
            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 && minDelta.HasValue && MatchMz(minDelta.Value, 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);
        }
Example #14
0
        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 calcFilter    = settings.GetFragmentCalc(IsotopeLabelType.light, mods);
            var calcPredict   = settings.GetFragmentCalc(LabelType, mods);

            string sequence = Peptide.Sequence;

            // 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.
                precursorMz = IsCustomIon ?
                              BioMassCalc.CalculateIonMz(calcFilterPre.GetPrecursorMass(groupDocNode.CustomIon), groupDocNode.TransitionGroup.PrecursorCharge) :
                              SequenceMassCalc.GetMZ(calcFilterPre.GetPrecursorMass(sequence), groupDocNode.TransitionGroup.PrecursorCharge);
            }
            if (!IsAvoidMismatchedIsotopeTransitions)
            {
                precursorMzAccept = precursorMz;
            }

            var      tranSettings      = settings.TransitionSettings;
            var      filter            = tranSettings.Filter;
            var      charges           = filter.ProductCharges;
            var      startFinder       = filter.FragmentRangeFirst;
            var      endFinder         = filter.FragmentRangeLast;
            double   precursorMzWindow = filter.PrecursorMzWindow;
            var      types             = filter.IonTypes;
            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 = Transition.ALL_CHARGES.ToList();
                listAll.AddRange(charges.Where(c => !Transition.ALL_CHARGES.Contains(c)));
                listAll.Sort();
                charges = listAll.ToArray();
                types   = Transition.ALL_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)
            {
                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, calcFilterPre, calcPredict,
                                                                 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.Charge, null, measuredIon.CustomIon);
                    double mass     = settings.GetFragmentMass(IsotopeLabelType.light, null, tran, null);
                    var    nodeTran = new TransitionDocNode(tran, null, mass, null, null);
                    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 == null) // Completely custom
            {
                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;
                }
            }

            double[,] massesPredict = calcPredict.GetFragmentIonMasses(sequence);
            int len = massesPredict.GetLength(1);

            if (len == 0)
            {
                yield break;
            }

            double[,] 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, PrecursorCharge, 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 (int charge in charges)
                {
                    // Precursor charge can never be lower than product ion charge.
                    if (Math.Abs(PrecursorCharge) < Math.Abs(charge))
                    {
                        continue;
                    }

                    int start = 0, end = 0;
                    if (pick != TransitionLibraryPick.all)
                    {
                        start = startFinder.FindStartFragment(massesFilter, type, charge,
                                                              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
                        double massH = massesPredict[(int)type, i];
                        foreach (var losses in CalcTransitionLosses(type, i, massType, potentialLosses))
                        {
                            double ionMz = SequenceMassCalc.GetMZ(Transition.CalcMass(massH, losses), charge);

                            // 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, charge, massH, losses, transitionRanks);
                                    accept         = false;
                                }
                                else
                                {
                                    if (IsMatched(transitionRanks, ionMz, type, charge, losses))
                                    {
                                        nodeTranReturn = CreateTransitionNode(type, i, charge, 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, charge, massH, losses, transitionRanks);
                                    }
                                }
                            }
                            else if (tranSettings.Accept(sequence, precursorMzAccept, type, i, ionMz, start, end, startMz))
                            {
                                if (pick == TransitionLibraryPick.none)
                                {
                                    nodeTranReturn = CreateTransitionNode(type, i, charge, massH, losses, transitionRanks);
                                }
                                else
                                {
                                    if (IsMatched(transitionRanks, ionMz, type, charge, losses))
                                    {
                                        nodeTranReturn = CreateTransitionNode(type, i, charge, 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);
                            }
                        }
                    }
                }
            }
        }
Example #15
0
        public static TransitionDocNode FromTransitionProto(AnnotationScrubber scrubber, SrmSettings settings,
                                                            TransitionGroup group, ExplicitMods mods, IsotopeDistInfo isotopeDist, ExplicitTransitionValues pre422ExplicitTransitionValues,
                                                            SkylineDocumentProto.Types.Transition transitionProto)
        {
            var         stringPool  = scrubber.StringPool;
            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 = scrubber.ScrubAnnotations(Annotations.FromProtoAnnotations(transitionProto.Annotations), AnnotationDef.AnnotationTarget.transition);
            var results     = TransitionChromInfo.FromProtoTransitionResults(scrubber, settings, transitionProto.Results);
            var explicitTransitionValues = pre422ExplicitTransitionValues ?? ExplicitTransitionValues.Create(
                DataValues.FromOptional(transitionProto.ExplicitCollisionEnergy),
                DataValues.FromOptional(transitionProto.ExplicitIonMobilityHighEnergyOffset),
                DataValues.FromOptional(transitionProto.ExplicitSLens),
                DataValues.FromOptional(transitionProto.ExplicitConeVoltage),
                DataValues.FromOptional(transitionProto.ExplicitDeclusteringPotential));

            return(new TransitionDocNode(transition, annotations, losses, mass, new TransitionQuantInfo(isotopeDistInfo, libInfo, !transitionProto.NotQuantitative), explicitTransitionValues, results));
        }
Example #16
0
 public Transition(TransitionGroup group, int charge, int?massIndex, CustomIon customIon, IonType type = IonType.custom)
     : this(group, type, null, massIndex, charge, null, customIon)
 {
 }
Example #17
0
 /// <summary>
 /// Creates a precursor transition
 /// </summary>
 /// <param name="group">The <see cref="TransitionGroup"/> which the transition represents</param>
 /// <param name="massIndex">Isotope mass shift</param>
 /// <param name="customIon">Non-null if this is a custom transition</param>
 public Transition(TransitionGroup group, int massIndex, CustomIon customIon = null)
     : this(group, IonType.precursor, group.Peptide.Length - 1, massIndex, group.PrecursorCharge, null, customIon)
 {
 }