示例#1
0
        /// <summary>
        /// Get the number of proteoform sequences possible with the provided number of dynamic modifications
        /// </summary>
        /// <param name="nDynMods"></param>
        /// <returns></returns>
        public double GetNumProteoformSequencesByNumMods(int nDynMods)
        {
            if (nDynMods < 1 || nDynMods > ModificationParams.MaxNumDynModsPerSequence)
            {
                return(0);
            }

            var numModCombs  = _graph[_index].Length;
            var nProteoforms = 0d;

            for (var modIndex = 0; modIndex < numModCombs; modIndex++)
            {
                var modCombs = ModificationParams.GetModificationCombination(_graph[_index][modIndex].ModificationCombinationIndex);
                if (modCombs.GetNumModifications() < nDynMods)
                {
                    continue;
                }
                if (modCombs.GetNumModifications() > nDynMods)
                {
                    break;
                }

                nProteoforms += GetNumProteoformSequences(modIndex);
                //if (nProteoforms > double.MaxValue) return double.MaxValue; // overflow
            }
            return(nProteoforms);
        }
示例#2
0
        /// <summary>
        /// Get the modification combinations in the current sequence graph
        /// </summary>
        /// <returns></returns>
        public ModificationCombination[] GetModificationCombinations()
        {
            var numModCombs = _graph[_index].Length;
            var modCombs    = new ModificationCombination[numModCombs];

            for (var modIndex = 0; modIndex < numModCombs; modIndex++)
            {
                modCombs[modIndex] = ModificationParams.GetModificationCombination(_graph[_index][modIndex].ModificationCombinationIndex);
            }
            return(modCombs);
        }
示例#3
0
        /// <summary>
        /// Generate an amino acid map with 20 standard amino acids
        /// </summary>
        public AminoAcidSet()
        {
            // Initialization
            _modificationParams = new ModificationParams();
            SearchModifications = new List <SearchModification>();

            _locationSpecificResidueMap    = new Dictionary <SequenceLocation, Dictionary <char, AminoAcid> >();
            _locationSpecificResidueModMap = new Dictionary <SequenceLocation, Dictionary <char, int[]> >();
            foreach (var loc in AllSequenceLocations)
            {
                _locationSpecificResidueModMap[loc] = new Dictionary <char, int[]>();
            }

            // Initialize standard amino acid set
            foreach (var loc in AllSequenceLocations)
            {
                var residueMap = new Dictionary <char, AminoAcid>();
                switch (loc)
                {
                case SequenceLocation.PeptideNTerm:
                    residueMap.Add(AminoAcid.PeptideNTerm.Residue, AminoAcid.PeptideNTerm);
                    break;

                case SequenceLocation.PeptideCTerm:
                    residueMap.Add(AminoAcid.PeptideCTerm.Residue, AminoAcid.PeptideCTerm);
                    break;

                case SequenceLocation.ProteinNTerm:
                    residueMap.Add(AminoAcid.ProteinNTerm.Residue, AminoAcid.ProteinNTerm);
                    break;

                case SequenceLocation.ProteinCTerm:
                    residueMap.Add(AminoAcid.ProteinCTerm.Residue, AminoAcid.ProteinCTerm);
                    break;
                }

                // loc is SequenceLocation.Everywhere
                foreach (var aa in AminoAcid.StandardAminoAcidArr)
                {
                    residueMap.Add(aa.Residue, aa);
                }
                _locationSpecificResidueMap[loc] = residueMap;
            }
        }
示例#4
0
        // Generate an amino acid map with 20 standard amino acids
        public AminoAcidSet()
        {
            // Initialization
            _modificationParams = new ModificationParams();

            _locationSpecificResidueMap = new Dictionary<SequenceLocation, Dictionary<char, AminoAcid>>();
            _locationSpecificResidueModMap = new Dictionary<SequenceLocation, Dictionary<char, int[]>>();
            foreach (var loc in AllSequenceLocations)
            {
                _locationSpecificResidueModMap[loc] = new Dictionary<char, int[]>();
            }

            // Initialize standard amino acid set
            foreach (var loc in AllSequenceLocations)
            {
                var residueMap = new Dictionary<char, AminoAcid>();
                switch (loc)
                {
                    case SequenceLocation.PeptideNTerm:
                        residueMap.Add(AminoAcid.PeptideNTerm.Residue, AminoAcid.PeptideNTerm);
                        break;
                    case SequenceLocation.PeptideCTerm:
                        residueMap.Add(AminoAcid.PeptideCTerm.Residue, AminoAcid.PeptideCTerm);
                        break;
                    case SequenceLocation.ProteinNTerm:
                        residueMap.Add(AminoAcid.ProteinNTerm.Residue, AminoAcid.ProteinNTerm);
                        break;
                    case SequenceLocation.ProteinCTerm:
                        residueMap.Add(AminoAcid.ProteinCTerm.Residue, AminoAcid.ProteinCTerm);
                        break;
                }

                foreach (var aa in AminoAcid.StandardAminoAcidArr)
                {
                    residueMap.Add(aa.Residue, aa);
                }
                _locationSpecificResidueMap[loc] = residueMap;
            }
        }
示例#5
0
        /// <summary>
        /// Add an amino acid residue to this generator.
        /// </summary>
        /// <param name="index">index to add the amino acid. 0 is C-term. 1 is the C-term amino acid.</param>
        /// <param name="residue">amino acid residue to add.</param>
        /// <returns>true if residue is a valid amino acid; false otherwise.</returns>
        private bool PutAminoAcid(int index, char residue)
        {
            _index = index + 1;

            SequenceLocation?location = null;

            if (_index == 1) // C-term residue
            {
                if (residue == AminoAcid.PeptideCTerm.Residue)
                {
                    location = SequenceLocation.PeptideCTerm;
                }
                else if (residue == AminoAcid.ProteinCTerm.Residue)
                {
                    location = SequenceLocation.ProteinCTerm;
                }
            }
            else if (_index == _aminoAcidSequence.Length - 1 - NumNTermCleavages)   // N-term residue
            {
                if (residue == AminoAcid.PeptideNTerm.Residue)
                {
                    location = SequenceLocation.PeptideNTerm;
                }
                else if (residue == AminoAcid.ProteinNTerm.Residue)
                {
                    location = SequenceLocation.ProteinNTerm;
                }
            }
            else if (_index == 2) // Amino acid at the C-term
            {
                if (_aminoAcidSequence[1] == AminoAcid.PeptideCTerm)
                {
                    location = SequenceLocation.PeptideCTerm;
                }
                else if (_aminoAcidSequence[1] == AminoAcid.ProteinCTerm)
                {
                    location = SequenceLocation.ProteinCTerm;
                }
            }
            else if (_index == _aminoAcidSequence.Length - 2 - NumNTermCleavages) // Amino acid at the N-term
            {
                if (_aminoAcidSequence[_aminoAcidSequence.Length - 1] == AminoAcid.PeptideNTerm)
                {
                    location = SequenceLocation.PeptideNTerm;
                }
                else if (_aminoAcidSequence[_aminoAcidSequence.Length - 1] == AminoAcid.ProteinNTerm)
                {
                    location = SequenceLocation.ProteinNTerm;
                }
            }
            else
            {
                location = SequenceLocation.Everywhere;
            }

            if (location == null)
            {
                return(false);
            }

            var loc       = (SequenceLocation)location;
            var aminoAcid = AminoAcidSet.GetAminoAcid(residue, loc);

            if (aminoAcid == null) // residue is not valid
            {
                return(false);
            }

            _aminoAcidSequence[_index] = aminoAcid;
            _suffixComposition[_index] = _suffixComposition[_index - 1] + aminoAcid.Composition;

            var modIndices = AminoAcidSet.GetModificationIndices(residue, loc);

            if (!modIndices.Any())  // No modification
            {
                _graph[_index] = new Node[_graph[_index - 1].Length];
                for (var i = 0; i < _graph[_index - 1].Length; i++)
                {
                    _graph[_index][i] = new Node(_graph[_index - 1][i].ModificationCombinationIndex, i);
                }
            }
            else
            {
                var modCombIndexToNodeMap = new Dictionary <int, Node>();
                for (var i = 0; i < _graph[_index - 1].Length; i++)
                {
                    var prevNodeIndex    = i;
                    var prevNode         = _graph[_index - 1][i];
                    var prevModCombIndex = prevNode.ModificationCombinationIndex;

                    // unmodified edge
                    if (modCombIndexToNodeMap.TryGetValue(prevModCombIndex, out var unmodifiedEdgeNode))
                    {
                        unmodifiedEdgeNode.AddPrevNodeIndex(prevNodeIndex);
                    }
                    else
                    {
                        modCombIndexToNodeMap.Add(prevModCombIndex, new Node(prevModCombIndex, prevNodeIndex));
                    }

                    // modified edge
                    foreach (var modIndex in modIndices)
                    {
                        var modCombIndex = ModificationParams.GetModificationCombinationIndex(
                            prevNode.ModificationCombinationIndex, modIndex);
                        if (modCombIndex < 0)   // too many modifications
                        {
                            continue;
                        }
                        if (modCombIndexToNodeMap.TryGetValue(modCombIndex, out var modifiedEdgeNode))
                        {
                            modifiedEdgeNode.AddPrevNodeIndex(prevNodeIndex);
                        }
                        else
                        {
                            modCombIndexToNodeMap.Add(modCombIndex, new Node(modCombIndex, prevNodeIndex));
                        }
                    }
                    _graph[_index] = modCombIndexToNodeMap.Values.ToArray();
                }
            }

            return(true);
        }
示例#6
0
        private Tuple <double, string> GetFragmentScoreAndModifications(int seqIndex, int modIndex, IScorer scorer, double?[][] nodeScore, Tuple <double, string>[][] maxScoreAndMods)
        {
            var scoreAndMods = maxScoreAndMods[seqIndex][modIndex];

            if (scoreAndMods != null)
            {
                return(scoreAndMods);
            }

            var node         = _graph[seqIndex][modIndex];
            var curNodeScore = nodeScore[seqIndex][modIndex] ??
                               (nodeScore[seqIndex][modIndex] = scorer.GetFragmentScore(GetComplementaryComposition(seqIndex, modIndex), GetComposition(seqIndex, modIndex)));

            var    bestPrevNodeIndex = -1;
            var    bestPrevNodeScore = double.NegativeInfinity;
            string bestPrevSequence  = null;

            foreach (var prevNodeIndex in node.GetPrevNodeIndices())
            {
                var prevNodeScoreAndSequence = GetFragmentScoreAndModifications(seqIndex - 1, prevNodeIndex, scorer,
                                                                                nodeScore, maxScoreAndMods);
                var prevNodeScore = prevNodeScoreAndSequence.Item1;
                if (prevNodeScore > bestPrevNodeScore)
                {
                    bestPrevNodeIndex = prevNodeIndex;
                    bestPrevNodeScore = prevNodeScore;
                    bestPrevSequence  = prevNodeScoreAndSequence.Item2;
                }
            }

            if (bestPrevNodeIndex < 0)  // source
            {
                return(maxScoreAndMods[seqIndex][modIndex] = new Tuple <double, string>((double)curNodeScore, ""));
            }

            var modPos    = _index - seqIndex;
            var aminoAcid = _aminoAcidSequence[seqIndex];
            var modAa     = aminoAcid as ModifiedAminoAcid;

            if (modAa != null)
            {
                var modificationName = modAa.Modification.Name;
                if (string.IsNullOrEmpty(bestPrevSequence))
                {
                    bestPrevSequence = modificationName + " " + modPos;
                }
                else
                {
                    bestPrevSequence = modificationName + " " + modPos + "," + bestPrevSequence;
                }
            }

            var prevModCombIndex = _graph[seqIndex - 1][bestPrevNodeIndex].ModificationCombinationIndex;
            var curModCombIndex  = node.ModificationCombinationIndex;

            if (prevModCombIndex != curModCombIndex) // modified
            {
                var    modificationName = ModificationParams.GetModificationIndexBetween(prevModCombIndex, curModCombIndex).Name;
                string newModSequence;
                if (string.IsNullOrEmpty(bestPrevSequence))
                {
                    newModSequence = modificationName + " " + modPos;
                }
                else
                {
                    newModSequence = modificationName + " " + modPos + ",";
                }
                return(maxScoreAndMods[seqIndex][modIndex] = new Tuple <double, string>
                                                                 ((double)curNodeScore + bestPrevNodeScore, newModSequence + bestPrevSequence));
            }

            return(maxScoreAndMods[seqIndex][modIndex] = new Tuple <double, string>
                                                             ((double)curNodeScore + bestPrevNodeScore, bestPrevSequence));
        }
示例#7
0
        public AminoAcidSet(IEnumerable <SearchModification> searchModifications, int maxNumModsPerSequence) : this()
        {
            if (searchModifications == null)
            {
                return;
            }

            var modifications = searchModifications as SearchModification[] ?? searchModifications.ToArray();

            // apply fixed modifications
            foreach (var searchModification in modifications)
            {
                if (!searchModification.IsFixedModification)
                {
                    continue;
                }

                var location      = searchModification.Location;
                var targetResidue = searchModification.TargetResidue;

                foreach (var loc in AffectedLocations[location])
                {
                    var appliedResidue = targetResidue != '*' ? targetResidue : SequenceLocationToLocationResidue[loc];
                    var residueMap     = _locationSpecificResidueMap[loc];
                    residueMap[appliedResidue] = new ModifiedAminoAcid(residueMap[appliedResidue], searchModification.Modification);
                }
            }

            if (maxNumModsPerSequence <= 0)
            {
                return;
            }

            // apply dynamic modifications
            var dynamicModifications = new HashSet <Modification>();
            var locationSpecificResidueVariableModMap = new Dictionary <SequenceLocation, Dictionary <char, List <Modification> > >();

            foreach (var loc in AllSequenceLocations)
            {
                locationSpecificResidueVariableModMap[loc] = new Dictionary <char, List <Modification> >();
            }

            foreach (var searchModification in modifications)
            {
                if (searchModification.IsFixedModification)
                {
                    continue;
                }

                dynamicModifications.Add(searchModification.Modification);
                var location      = searchModification.Location;
                var targetResidue = searchModification.TargetResidue;

                foreach (var loc in AffectedLocations[location])
                {
                    var residueModMap  = locationSpecificResidueVariableModMap[loc];
                    var appliedResidue = targetResidue != '*' ? targetResidue : SequenceLocationToLocationResidue[loc];
                    List <Modification> modList;
                    if (residueModMap.TryGetValue(appliedResidue, out modList))
                    {
                        modList.Add(searchModification.Modification);
                    }
                    else
                    {
                        residueModMap.Add(appliedResidue, new List <Modification> {
                            searchModification.Modification
                        });
                    }
                }
            }

            var dynModArray = dynamicModifications.ToArray();

            _modificationParams = new ModificationParams(dynModArray, maxNumModsPerSequence);

            foreach (var loc in AllSequenceLocations)
            {
                var residueModMap = locationSpecificResidueVariableModMap[loc];
                foreach (var entry in residueModMap)
                {
                    var residue = entry.Key;
                    var modList = entry.Value;

                    var modIndexArr = new int[modList.Count];
                    var index       = -1;
                    foreach (var mod in modList)
                    {
                        var modIndex = Array.IndexOf(dynModArray, mod);
                        modIndexArr[++index] = modIndex;
                    }
                    _locationSpecificResidueModMap[loc].Add(residue, modIndexArr);
                }
            }
        }
示例#8
0
        public AminoAcidSet(IEnumerable<SearchModification> searchModifications, int maxNumModsPerSequence): this()
        {
            if (searchModifications == null) return;

            var modifications = searchModifications as SearchModification[] ?? searchModifications.ToArray();

            // apply fixed modifications
            foreach (var searchModification in modifications)
            {
                if (!searchModification.IsFixedModification) continue;

                var location = searchModification.Location;
                var targetResidue = searchModification.TargetResidue;

                foreach (var loc in AffectedLocations[location])
                {
                    var appliedResidue = targetResidue != '*' ? targetResidue : SequenceLocationToLocationResidue[loc];
                    var residueMap = _locationSpecificResidueMap[loc];
                    residueMap[appliedResidue] = new ModifiedAminoAcid(residueMap[appliedResidue], searchModification.Modification);
                }
            }

            if (maxNumModsPerSequence <= 0) return;

            // apply dynamic modifications
            var dynamicModifications = new HashSet<Modification>();
            var locationSpecificResidueVariableModMap = new Dictionary<SequenceLocation,Dictionary<char, List<Modification>>>();
            foreach (var loc in AllSequenceLocations)
            {
                locationSpecificResidueVariableModMap[loc] = new Dictionary<char, List<Modification>>();
            }

            foreach (var searchModification in modifications)
            {
                if (searchModification.IsFixedModification) continue;

                dynamicModifications.Add(searchModification.Modification);
                var location = searchModification.Location;
                var targetResidue = searchModification.TargetResidue;

                foreach (var loc in AffectedLocations[location])
                {
                    var residueModMap = locationSpecificResidueVariableModMap[loc];
                    var appliedResidue = targetResidue != '*' ? targetResidue : SequenceLocationToLocationResidue[loc];
                    List<Modification> modList;
                    if (residueModMap.TryGetValue(appliedResidue, out modList))
                    {
                        modList.Add(searchModification.Modification);
                    }
                    else
                    {
                        residueModMap.Add(appliedResidue, new List<Modification> { searchModification.Modification });
                    }
                }
            }

            var dynModArray = dynamicModifications.ToArray();
            _modificationParams = new ModificationParams(dynModArray, maxNumModsPerSequence);

            foreach (var loc in AllSequenceLocations)
            {
                var residueModMap = locationSpecificResidueVariableModMap[loc];
                foreach (var entry in residueModMap)
                {
                    var residue = entry.Key;
                    var modList = entry.Value;

                    var modIndexArr = new int[modList.Count];
                    var index = -1;
                    foreach (var mod in modList)
                    {
                        var modIndex = Array.IndexOf(dynModArray, mod);
                        modIndexArr[++index] = modIndex;
                    }
                    _locationSpecificResidueModMap[loc].Add(residue, modIndexArr);
                }
            }

        }
示例#9
0
        /// <summary>
        /// Add an amino acid residue to this generator.
        /// </summary>
        /// <param name="index">index to add the amino acid. 0 is C-term. 1 is the C-term amino acid.</param>
        /// <param name="residue">amino acid residue to add.</param>
        /// <param name="loc">location of the residue</param>
        /// <returns>true if residue is a valid amino acid; false otherwise.</returns>
        private bool PutAminoAcid(int index, char residue, SequenceLocation loc)
        {
            _index = index + 1;

            var aminoAcid = AminoAcidSet.GetAminoAcid(residue, loc);

            if (aminoAcid == null) // residue is not valid
            {
                return(false);
            }

            var fragmentComposition = _fragmentComposition[_index - 1] + aminoAcid.Composition;

            if (fragmentComposition.Mass > _maxSequenceMass)
            {
                return(false);
            }

            _aminoAcidSequence[_index]   = aminoAcid;
            _fragmentComposition[_index] = fragmentComposition;

            var modIndices = AminoAcidSet.GetModificationIndices(residue, loc);

            if (!modIndices.Any())  // No modification
            {
                _graph[_index] = new Node[_graph[_index - 1].Length];
                for (var i = 0; i < _graph[_index - 1].Length; i++)
                {
                    _graph[_index][i] = new Node(_graph[_index - 1][i].ModificationCombinationIndex, i);
                }
            }
            else
            {
                var modCombIndexToNodeMap = new Dictionary <int, Node>();
                for (var i = 0; i < _graph[_index - 1].Length; i++)
                {
                    var prevNodeIndex    = i;
                    var prevNode         = _graph[_index - 1][i];
                    var prevModCombIndex = prevNode.ModificationCombinationIndex;

                    // unmodified edge
                    if (modCombIndexToNodeMap.TryGetValue(prevModCombIndex, out var unmodifiedEdgeNode))
                    {
                        unmodifiedEdgeNode.AddPrevNodeIndex(prevNodeIndex);
                    }
                    else
                    {
                        modCombIndexToNodeMap.Add(prevModCombIndex, new Node(prevModCombIndex, prevNodeIndex));
                    }

                    // modified edge
                    foreach (var modIndex in modIndices)
                    {
                        var modCombIndex = ModificationParams.GetModificationCombinationIndex(
                            prevNode.ModificationCombinationIndex, modIndex);
                        if (modCombIndex < 0)   // too many modifications
                        {
                            continue;
                        }
                        if (modCombIndexToNodeMap.TryGetValue(modCombIndex, out var modifiedEdgeNode))
                        {
                            modifiedEdgeNode.AddPrevNodeIndex(prevNodeIndex);
                        }
                        else
                        {
                            modCombIndexToNodeMap.Add(modCombIndex, new Node(modCombIndex, prevNodeIndex));
                        }
                    }
                    _graph[_index] = modCombIndexToNodeMap.Values.ToArray();
                }
            }

            return(true);
        }
示例#10
0
        /// <summary>
        /// Get the fragment score and modifications
        /// </summary>
        /// <param name="seqIndex"></param>
        /// <param name="modIndex"></param>
        /// <param name="scorer"></param>
        /// <param name="nodeScore"></param>
        /// <param name="maxScoreAndMods"></param>
        /// <returns></returns>
        private Tuple <double, LinkedList <ModificationInstance> > GetFragmentScoreAndModifications(
            int seqIndex,
            int modIndex,
            IScorer scorer,
            IReadOnlyList <double?[]> nodeScore,
            IReadOnlyList <Tuple <double, LinkedList <ModificationInstance> >[]> maxScoreAndMods)
        {
            var scoreAndMods = maxScoreAndMods[seqIndex][modIndex];

            if (scoreAndMods != null)
            {
                return(scoreAndMods);
            }

            var node         = _graph[seqIndex][modIndex];
            var curNodeScore = nodeScore[seqIndex][modIndex] ??
                               (nodeScore[seqIndex][modIndex] = _isForward
                                   ? scorer.GetFragmentScore(GetComposition(seqIndex, modIndex),
                                                             GetComplementaryComposition(seqIndex, modIndex))
                                   : scorer.GetFragmentScore(GetComplementaryComposition(seqIndex, modIndex),
                                                             GetComposition(seqIndex, modIndex))
                               );

            var bestPrevNodeIndex = -1;
            var bestPrevNodeScore = double.NegativeInfinity;
            LinkedList <ModificationInstance> bestPrevMods = null;

            foreach (var prevNodeIndex in node.GetPrevNodeIndices())
            {
                var prevNodeScoreAndSequence = GetFragmentScoreAndModifications(seqIndex - 1, prevNodeIndex, scorer,
                                                                                nodeScore, maxScoreAndMods);
                var prevNodeScore = prevNodeScoreAndSequence.Item1;
                if (prevNodeScore > bestPrevNodeScore)
                {
                    bestPrevNodeIndex = prevNodeIndex;
                    bestPrevNodeScore = prevNodeScore;
                    bestPrevMods      = prevNodeScoreAndSequence.Item2;
                }
            }

            if (bestPrevNodeIndex < 0)  // source
            {
                return(maxScoreAndMods[seqIndex][modIndex] = new Tuple <double, LinkedList <ModificationInstance> >((double)curNodeScore, new LinkedList <ModificationInstance>()));
            }

            var modPos = _isForward ? seqIndex : _index - seqIndex;

            if (modPos <= 1)
            {
                --modPos;
            }
            var aminoAcid = _aminoAcidSequence[seqIndex];
            var modAa     = aminoAcid as ModifiedAminoAcid;

            LinkedList <ModificationInstance> newMods = null;

            if (modAa != null)
            {
                newMods = bestPrevMods == null ? new LinkedList <ModificationInstance>() : new LinkedList <ModificationInstance>(bestPrevMods);
                var modIns = new ModificationInstance(modAa.Modification, modPos);
                if (_isForward)
                {
                    newMods.AddLast(modIns);
                }
                else
                {
                    newMods.AddFirst(modIns);
                }
            }

            var prevModCombIndex = _graph[seqIndex - 1][bestPrevNodeIndex].ModificationCombinationIndex;
            var curModCombIndex  = node.ModificationCombinationIndex;

            if (prevModCombIndex != curModCombIndex) // modified
            {
                if (newMods == null)
                {
                    newMods = bestPrevMods == null ? new LinkedList <ModificationInstance>() : new LinkedList <ModificationInstance>(bestPrevMods);
                }
                var modification = ModificationParams.GetModificationIndexBetween(prevModCombIndex, curModCombIndex);
                var modIns       = new ModificationInstance(modification, modPos);
                if (_isForward)
                {
                    newMods.AddLast(modIns);
                }
                else
                {
                    newMods.AddFirst(modIns);
                }
            }

            return(maxScoreAndMods[seqIndex][modIndex] = new Tuple <double, LinkedList <ModificationInstance> >
                                                             ((double)curNodeScore + bestPrevNodeScore, newMods ?? bestPrevMods));
        }
示例#11
0
        public void TestModificationParams()
        {
            var methodName = MethodBase.GetCurrentMethod().Name;
            ShowStarting(methodName);

            var modifications = new[] { Modification.Acetylation, Modification.Phosphorylation, Modification.Oxidation}; //, Modification.PyroGluQ };
            var modParams = new ModificationParams(modifications, 3);
            int numCombinations = modParams.NumModificationCombinations;
            for (int modCombIndex = 0; modCombIndex < numCombinations; modCombIndex++)
            {
                var modCombination = modParams.GetModificationCombination(modCombIndex);
                Console.WriteLine("{0}: {1} {2} {3}", modCombIndex, modCombination, modCombination.Composition, modCombination.Composition.Mass);
            }

            Console.WriteLine(modParams.GetModificationCombinationIndex(8, 0));
            Console.WriteLine(modParams.GetModificationCombinationIndex(19, 1));
        }