From 738cdd87d07826f97b20ed458611b164216c8607 Mon Sep 17 00:00:00 2001 From: nbollis Date: Thu, 12 Dec 2024 18:08:44 -0600 Subject: [PATCH 1/8] PpmTolerance Optimization --- mzLib/MzLibUtil/PpmTolerance.cs | 29 ++++++++++++----------------- 1 file changed, 12 insertions(+), 17 deletions(-) diff --git a/mzLib/MzLibUtil/PpmTolerance.cs b/mzLib/MzLibUtil/PpmTolerance.cs index 7bc88e33d..c6b36c911 100644 --- a/mzLib/MzLibUtil/PpmTolerance.cs +++ b/mzLib/MzLibUtil/PpmTolerance.cs @@ -25,40 +25,35 @@ namespace MzLibUtil /// public class PpmTolerance : Tolerance { + private readonly double _factor; + /// - /// Creates a new tolerance given a unit, value, and whether the tolerance is ± + /// Creates a new tolerance given value /// - /// The units for this tolerance /// The numerical value of the tolerance - public PpmTolerance(double value) + public PpmTolerance(double value) : base(value) { + _factor = value / 1e6; } - public override string ToString() - { - return $"{"±"}{Value.ToString("f4", System.Globalization.CultureInfo.InvariantCulture)} PPM"; - } + public override string ToString() => $"\u00b1{Value.ToString("f4", System.Globalization.CultureInfo.InvariantCulture)} PPM"; public override DoubleRange GetRange(double mean) { - double tol = Value * mean / 1e6; + double tol = _factor * mean; return new DoubleRange(mean - tol, mean + tol); } - public override double GetMinimumValue(double mean) - { - return mean * (1 - (Value / 1e6)); - } + public override double GetMinimumValue(double mean) => mean * (1 - _factor); - public override double GetMaximumValue(double mean) - { - return mean * (1 + (Value / 1e6)); - } + public override double GetMaximumValue(double mean) => mean * (1 + _factor); public override bool Within(double experimental, double theoretical) { - return Math.Abs((experimental - theoretical) / theoretical * 1e6) <= Value; + double diff = experimental - theoretical; + double scaledTolerance = theoretical * _factor; + return -scaledTolerance <= diff && diff <= scaledTolerance; } } } \ No newline at end of file From 1d9bd59f58977e6e607016fba2e8d4851e352ef6 Mon Sep 17 00:00:00 2001 From: nbollis Date: Thu, 12 Dec 2024 18:36:06 -0600 Subject: [PATCH 2/8] Added HashSetPool and reduced runtime of Digestion --- mzLib/MzLibUtil/HashSetPool.cs | 64 +++++++++++++ mzLib/MzLibUtil/MzLibUtil.csproj | 1 + mzLib/Omics/Digestion/DigestionAgent.cs | 12 ++- mzLib/Omics/Digestion/DigestionProduct.cs | 63 ++++++------- mzLib/mzLib.sln | 105 ++++++++++++++++++++++ 5 files changed, 203 insertions(+), 42 deletions(-) create mode 100644 mzLib/MzLibUtil/HashSetPool.cs diff --git a/mzLib/MzLibUtil/HashSetPool.cs b/mzLib/MzLibUtil/HashSetPool.cs new file mode 100644 index 000000000..25a90966f --- /dev/null +++ b/mzLib/MzLibUtil/HashSetPool.cs @@ -0,0 +1,64 @@ +using System; +using System.Collections.Generic; +using Microsoft.Extensions.ObjectPool; + +namespace MzLibUtil; + +// Example Usage: +// var pool = new HashSetPool(); +// var hashSet = pool.Get(); +// hashSet.Add(1); +// Do Work +// pool.Return(hashSet); + +// Used to pool HashSet instances to reduce memory allocations +public class HashSetPool +{ + private readonly ObjectPool> _pool; + + /// + /// Initializes a new instance of the class. + /// + /// Initial capacity for the pooled HashSet instances. + public HashSetPool(int initialCapacity = 16) + { + var policy = new HashSetPooledObjectPolicy(initialCapacity); + _pool = new DefaultObjectPool>(policy); + } + + /// + /// Retrieves a HashSet instance from the pool. + /// + /// A HashSet instance. + public HashSet Get() => _pool.Get(); + + /// + /// Returns a HashSet instance back to the pool. + /// + /// The HashSet instance to return. + public void Return(HashSet hashSet) + { + if (hashSet == null) throw new ArgumentNullException(nameof(hashSet)); + hashSet.Clear(); // Ensure the HashSet is clean before returning it to the pool + _pool.Return(hashSet); + } + + private class HashSetPooledObjectPolicy(int initialCapacity) : PooledObjectPolicy> + { + public override HashSet Create() + { + return new HashSet(capacity: initialCapacity); + } + + public override bool Return(HashSet obj) + { + // Ensure the HashSet can be safely reused + obj.Clear(); + return true; + } + } +} + + + + diff --git a/mzLib/MzLibUtil/MzLibUtil.csproj b/mzLib/MzLibUtil/MzLibUtil.csproj index c6b5cf526..ae8fef5ea 100644 --- a/mzLib/MzLibUtil/MzLibUtil.csproj +++ b/mzLib/MzLibUtil/MzLibUtil.csproj @@ -14,6 +14,7 @@ + diff --git a/mzLib/Omics/Digestion/DigestionAgent.cs b/mzLib/Omics/Digestion/DigestionAgent.cs index d860659b9..94c489472 100644 --- a/mzLib/Omics/Digestion/DigestionAgent.cs +++ b/mzLib/Omics/Digestion/DigestionAgent.cs @@ -1,4 +1,5 @@ -using Omics.Modifications; +using MzLibUtil; +using Omics.Modifications; using System; using System.Collections.Generic; using System.Linq; @@ -9,6 +10,7 @@ namespace Omics.Digestion { public abstract class DigestionAgent { + protected static readonly HashSetPool HashSetPool = new HashSetPool(); protected DigestionAgent(string name, CleavageSpecificity cleavageSpecificity, List motifList, Modification cleavageMod) { Name = name; @@ -68,7 +70,8 @@ protected static bool ValidMaxLength(int? length, int maxLength) /// public List GetDigestionSiteIndices(string sequence) { - var indices = new List(); + var indices = HashSetPool.Get(); // use hash set to ensure no duplicates + indices.Add(0); // The start of the protein is treated as a cleavage site to retain the n-terminal peptide for (int r = 0; r < sequence.Length; r++) { @@ -99,9 +102,10 @@ public List GetDigestionSiteIndices(string sequence) } } - indices.Add(0); // The start of the protein is treated as a cleavage site to retain the n-terminal peptide indices.Add(sequence.Length); // The end of the protein is treated as a cleavage site to retain the c-terminal peptide - return indices.Distinct().OrderBy(i => i).ToList(); + var toReturn = indices.ToList(); + HashSetPool.Return(indices); + return toReturn.ToList(); } } } diff --git a/mzLib/Omics/Digestion/DigestionProduct.cs b/mzLib/Omics/Digestion/DigestionProduct.cs index 55aed3255..1e86ec53b 100644 --- a/mzLib/Omics/Digestion/DigestionProduct.cs +++ b/mzLib/Omics/Digestion/DigestionProduct.cs @@ -1,10 +1,4 @@ -using System; -using System.Collections.Generic; -using System.ComponentModel; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using Omics.Modifications; +using Omics.Modifications; namespace Omics.Digestion { @@ -52,8 +46,17 @@ protected static IEnumerable> GetVariableModificat var possible_variable_modifications = new Dictionary>(possibleVariableModifications); int[] base_variable_modification_pattern = new int[peptideLength + 4]; - var totalAvailableMods = possible_variable_modifications.Sum(b => b.Value == null ? 0 : b.Value.Count); - for (int variable_modifications = 0; variable_modifications <= Math.Min(totalAvailableMods, maxModsForPeptide); variable_modifications++) + int totalAvailableMods = 0; + foreach (var kvp in possible_variable_modifications) + { + if (kvp.Value != null) + { + totalAvailableMods += kvp.Value.Count; + } + } + + int maxVariableMods = Math.Min(totalAvailableMods, maxModsForPeptide); + for (int variable_modifications = 0; variable_modifications <= maxVariableMods; variable_modifications++) { foreach (int[] variable_modification_pattern in GetVariableModificationPatterns(new List>>(possible_variable_modifications), possible_variable_modifications.Count - variable_modifications, base_variable_modification_pattern, 0)) @@ -76,28 +79,16 @@ protected Dictionary GetFixedModsOneIsNorFivePrimeTerminus(in case "Oligo 5'-terminal.": case "N-terminal.": case "Peptide N-terminal.": - //the modification is protease associated and is applied to the n-terminal cleaved residue, not at the beginign of the protein - if (mod.ModificationType == "Protease" && ModificationLocalization.ModFits(mod, Parent.BaseSequence, 1, length, OneBasedStartResidue)) + //the modification is protease associated and is applied to the n-terminal cleaved residue, not at the beginning of the protein + if (ModificationLocalization.ModFits(mod, Parent.BaseSequence, 1, length, OneBasedStartResidue)) { - if (OneBasedStartResidue != 1) + if (mod.ModificationType == "Protease") { - fixedModsOneIsNterminus[2] = mod; - } - } - //Normal N-terminal peptide modification - else if (ModificationLocalization.ModFits(mod, Parent.BaseSequence, 1, length, OneBasedStartResidue)) - { - fixedModsOneIsNterminus[1] = mod; - } - break; - - case "Anywhere.": - for (int i = 2; i <= length + 1; i++) - { - if (ModificationLocalization.ModFits(mod, Parent.BaseSequence, i - 1, length, OneBasedStartResidue + i - 2)) - { - fixedModsOneIsNterminus[i] = mod; + if (OneBasedStartResidue != 1) + fixedModsOneIsNterminus[2] = mod; } + else //Normal N-terminal peptide modification + fixedModsOneIsNterminus[1] = mod; } break; @@ -106,17 +97,15 @@ protected Dictionary GetFixedModsOneIsNorFivePrimeTerminus(in case "C-terminal.": case "Peptide C-terminal.": //the modification is protease associated and is applied to the c-terminal cleaved residue, not if it is at the end of the protein - if (mod.ModificationType == "Protease" && ModificationLocalization.ModFits(mod, Parent.BaseSequence, length, length, OneBasedStartResidue + length - 1)) + if (ModificationLocalization.ModFits(mod, Parent.BaseSequence, length, length, OneBasedStartResidue + length - 1)) { - if (OneBasedEndResidue != Parent.Length) + if (mod.ModificationType == "Protease") { - fixedModsOneIsNterminus[length + 1] = mod; + if (OneBasedEndResidue != Parent.Length) + fixedModsOneIsNterminus[length + 1] = mod; } - } - //Normal C-terminal peptide modification - else if (ModificationLocalization.ModFits(mod, Parent.BaseSequence, length, length, OneBasedStartResidue + length - 1)) - { - fixedModsOneIsNterminus[length + 2] = mod; + else //Normal C-terminal peptide modification + fixedModsOneIsNterminus[length + 2] = mod; } break; @@ -188,7 +177,5 @@ private static Dictionary GetNewVariableModificationPattern(i return modification_pattern; } - - } } diff --git a/mzLib/mzLib.sln b/mzLib/mzLib.sln index f8b4f8a51..ae3b61483 100644 --- a/mzLib/mzLib.sln +++ b/mzLib/mzLib.sln @@ -39,110 +39,215 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Transcriptomics", "Transcri EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU Debug|x64 = Debug|x64 + Release|Any CPU = Release|Any CPU Release|x64 = Release|x64 + TestAndRelease|Any CPU = TestAndRelease|Any CPU TestAndRelease|x64 = TestAndRelease|x64 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution + {4658AE10-B660-46DB-B56B-7F4701339FD0}.Debug|Any CPU.ActiveCfg = Debug|x64 + {4658AE10-B660-46DB-B56B-7F4701339FD0}.Debug|Any CPU.Build.0 = Debug|x64 {4658AE10-B660-46DB-B56B-7F4701339FD0}.Debug|x64.ActiveCfg = Debug|x64 {4658AE10-B660-46DB-B56B-7F4701339FD0}.Debug|x64.Build.0 = Debug|x64 + {4658AE10-B660-46DB-B56B-7F4701339FD0}.Release|Any CPU.ActiveCfg = Release|x64 + {4658AE10-B660-46DB-B56B-7F4701339FD0}.Release|Any CPU.Build.0 = Release|x64 {4658AE10-B660-46DB-B56B-7F4701339FD0}.Release|x64.ActiveCfg = Release|x64 {4658AE10-B660-46DB-B56B-7F4701339FD0}.Release|x64.Build.0 = Release|x64 + {4658AE10-B660-46DB-B56B-7F4701339FD0}.TestAndRelease|Any CPU.ActiveCfg = Release|x64 + {4658AE10-B660-46DB-B56B-7F4701339FD0}.TestAndRelease|Any CPU.Build.0 = Release|x64 {4658AE10-B660-46DB-B56B-7F4701339FD0}.TestAndRelease|x64.ActiveCfg = Release|x64 {4658AE10-B660-46DB-B56B-7F4701339FD0}.TestAndRelease|x64.Build.0 = Release|x64 + {3385FB51-AA75-476A-8D5E-7C55F0A2DB10}.Debug|Any CPU.ActiveCfg = Debug|x64 + {3385FB51-AA75-476A-8D5E-7C55F0A2DB10}.Debug|Any CPU.Build.0 = Debug|x64 {3385FB51-AA75-476A-8D5E-7C55F0A2DB10}.Debug|x64.ActiveCfg = Debug|x64 {3385FB51-AA75-476A-8D5E-7C55F0A2DB10}.Debug|x64.Build.0 = Debug|x64 + {3385FB51-AA75-476A-8D5E-7C55F0A2DB10}.Release|Any CPU.ActiveCfg = Release|x64 + {3385FB51-AA75-476A-8D5E-7C55F0A2DB10}.Release|Any CPU.Build.0 = Release|x64 {3385FB51-AA75-476A-8D5E-7C55F0A2DB10}.Release|x64.ActiveCfg = Release|x64 {3385FB51-AA75-476A-8D5E-7C55F0A2DB10}.Release|x64.Build.0 = Release|x64 + {3385FB51-AA75-476A-8D5E-7C55F0A2DB10}.TestAndRelease|Any CPU.ActiveCfg = Release|x64 + {3385FB51-AA75-476A-8D5E-7C55F0A2DB10}.TestAndRelease|Any CPU.Build.0 = Release|x64 {3385FB51-AA75-476A-8D5E-7C55F0A2DB10}.TestAndRelease|x64.ActiveCfg = Release|x64 {3385FB51-AA75-476A-8D5E-7C55F0A2DB10}.TestAndRelease|x64.Build.0 = Release|x64 + {0DE04F7B-EE40-4055-ACF7-472167B70A04}.Debug|Any CPU.ActiveCfg = Debug|x64 + {0DE04F7B-EE40-4055-ACF7-472167B70A04}.Debug|Any CPU.Build.0 = Debug|x64 {0DE04F7B-EE40-4055-ACF7-472167B70A04}.Debug|x64.ActiveCfg = Debug|x64 {0DE04F7B-EE40-4055-ACF7-472167B70A04}.Debug|x64.Build.0 = Debug|x64 + {0DE04F7B-EE40-4055-ACF7-472167B70A04}.Release|Any CPU.ActiveCfg = Release|x64 + {0DE04F7B-EE40-4055-ACF7-472167B70A04}.Release|Any CPU.Build.0 = Release|x64 {0DE04F7B-EE40-4055-ACF7-472167B70A04}.Release|x64.ActiveCfg = Release|x64 {0DE04F7B-EE40-4055-ACF7-472167B70A04}.Release|x64.Build.0 = Release|x64 + {0DE04F7B-EE40-4055-ACF7-472167B70A04}.TestAndRelease|Any CPU.ActiveCfg = Release|x64 + {0DE04F7B-EE40-4055-ACF7-472167B70A04}.TestAndRelease|Any CPU.Build.0 = Release|x64 {0DE04F7B-EE40-4055-ACF7-472167B70A04}.TestAndRelease|x64.ActiveCfg = Release|x64 {0DE04F7B-EE40-4055-ACF7-472167B70A04}.TestAndRelease|x64.Build.0 = Release|x64 + {244A891E-BCDA-432F-8160-26EE0C5F8096}.Debug|Any CPU.ActiveCfg = Debug|x64 + {244A891E-BCDA-432F-8160-26EE0C5F8096}.Debug|Any CPU.Build.0 = Debug|x64 {244A891E-BCDA-432F-8160-26EE0C5F8096}.Debug|x64.ActiveCfg = Debug|x64 {244A891E-BCDA-432F-8160-26EE0C5F8096}.Debug|x64.Build.0 = Debug|x64 + {244A891E-BCDA-432F-8160-26EE0C5F8096}.Release|Any CPU.ActiveCfg = Release|x64 + {244A891E-BCDA-432F-8160-26EE0C5F8096}.Release|Any CPU.Build.0 = Release|x64 {244A891E-BCDA-432F-8160-26EE0C5F8096}.Release|x64.ActiveCfg = Release|x64 {244A891E-BCDA-432F-8160-26EE0C5F8096}.Release|x64.Build.0 = Release|x64 + {244A891E-BCDA-432F-8160-26EE0C5F8096}.TestAndRelease|Any CPU.ActiveCfg = Release|x64 + {244A891E-BCDA-432F-8160-26EE0C5F8096}.TestAndRelease|Any CPU.Build.0 = Release|x64 {244A891E-BCDA-432F-8160-26EE0C5F8096}.TestAndRelease|x64.ActiveCfg = Release|x64 {244A891E-BCDA-432F-8160-26EE0C5F8096}.TestAndRelease|x64.Build.0 = Release|x64 + {D2B8F696-1172-405B-B788-3251B27CC71A}.Debug|Any CPU.ActiveCfg = Debug|x64 + {D2B8F696-1172-405B-B788-3251B27CC71A}.Debug|Any CPU.Build.0 = Debug|x64 {D2B8F696-1172-405B-B788-3251B27CC71A}.Debug|x64.ActiveCfg = Debug|x64 {D2B8F696-1172-405B-B788-3251B27CC71A}.Debug|x64.Build.0 = Debug|x64 + {D2B8F696-1172-405B-B788-3251B27CC71A}.Release|Any CPU.ActiveCfg = Release|x64 + {D2B8F696-1172-405B-B788-3251B27CC71A}.Release|Any CPU.Build.0 = Release|x64 {D2B8F696-1172-405B-B788-3251B27CC71A}.Release|x64.ActiveCfg = Release|x64 {D2B8F696-1172-405B-B788-3251B27CC71A}.Release|x64.Build.0 = Release|x64 + {D2B8F696-1172-405B-B788-3251B27CC71A}.TestAndRelease|Any CPU.ActiveCfg = Release|x64 + {D2B8F696-1172-405B-B788-3251B27CC71A}.TestAndRelease|Any CPU.Build.0 = Release|x64 {D2B8F696-1172-405B-B788-3251B27CC71A}.TestAndRelease|x64.ActiveCfg = Release|x64 {D2B8F696-1172-405B-B788-3251B27CC71A}.TestAndRelease|x64.Build.0 = Release|x64 + {C5EF6CE1-9E90-48D6-A19E-FAE2A9F28E3C}.Debug|Any CPU.ActiveCfg = Debug|x64 + {C5EF6CE1-9E90-48D6-A19E-FAE2A9F28E3C}.Debug|Any CPU.Build.0 = Debug|x64 {C5EF6CE1-9E90-48D6-A19E-FAE2A9F28E3C}.Debug|x64.ActiveCfg = Debug|x64 {C5EF6CE1-9E90-48D6-A19E-FAE2A9F28E3C}.Debug|x64.Build.0 = Debug|x64 + {C5EF6CE1-9E90-48D6-A19E-FAE2A9F28E3C}.Release|Any CPU.ActiveCfg = Release|x64 + {C5EF6CE1-9E90-48D6-A19E-FAE2A9F28E3C}.Release|Any CPU.Build.0 = Release|x64 {C5EF6CE1-9E90-48D6-A19E-FAE2A9F28E3C}.Release|x64.ActiveCfg = Release|x64 {C5EF6CE1-9E90-48D6-A19E-FAE2A9F28E3C}.Release|x64.Build.0 = Release|x64 + {C5EF6CE1-9E90-48D6-A19E-FAE2A9F28E3C}.TestAndRelease|Any CPU.ActiveCfg = Release|x64 + {C5EF6CE1-9E90-48D6-A19E-FAE2A9F28E3C}.TestAndRelease|Any CPU.Build.0 = Release|x64 {C5EF6CE1-9E90-48D6-A19E-FAE2A9F28E3C}.TestAndRelease|x64.ActiveCfg = Release|x64 {C5EF6CE1-9E90-48D6-A19E-FAE2A9F28E3C}.TestAndRelease|x64.Build.0 = Release|x64 + {9697BC5E-1F2C-4E3C-BC53-3532CBDFFCC7}.Debug|Any CPU.ActiveCfg = Debug|x64 + {9697BC5E-1F2C-4E3C-BC53-3532CBDFFCC7}.Debug|Any CPU.Build.0 = Debug|x64 {9697BC5E-1F2C-4E3C-BC53-3532CBDFFCC7}.Debug|x64.ActiveCfg = Debug|x64 {9697BC5E-1F2C-4E3C-BC53-3532CBDFFCC7}.Debug|x64.Build.0 = Debug|x64 + {9697BC5E-1F2C-4E3C-BC53-3532CBDFFCC7}.Release|Any CPU.ActiveCfg = Release|x64 + {9697BC5E-1F2C-4E3C-BC53-3532CBDFFCC7}.Release|Any CPU.Build.0 = Release|x64 {9697BC5E-1F2C-4E3C-BC53-3532CBDFFCC7}.Release|x64.ActiveCfg = Release|x64 {9697BC5E-1F2C-4E3C-BC53-3532CBDFFCC7}.Release|x64.Build.0 = Release|x64 + {9697BC5E-1F2C-4E3C-BC53-3532CBDFFCC7}.TestAndRelease|Any CPU.ActiveCfg = Release|x64 + {9697BC5E-1F2C-4E3C-BC53-3532CBDFFCC7}.TestAndRelease|Any CPU.Build.0 = Release|x64 {9697BC5E-1F2C-4E3C-BC53-3532CBDFFCC7}.TestAndRelease|x64.ActiveCfg = Release|x64 {9697BC5E-1F2C-4E3C-BC53-3532CBDFFCC7}.TestAndRelease|x64.Build.0 = Release|x64 + {AD3D126D-6359-481B-BE17-69DFB0BC4E40}.Debug|Any CPU.ActiveCfg = Debug|x64 + {AD3D126D-6359-481B-BE17-69DFB0BC4E40}.Debug|Any CPU.Build.0 = Debug|x64 {AD3D126D-6359-481B-BE17-69DFB0BC4E40}.Debug|x64.ActiveCfg = Debug|x64 {AD3D126D-6359-481B-BE17-69DFB0BC4E40}.Debug|x64.Build.0 = Debug|x64 + {AD3D126D-6359-481B-BE17-69DFB0BC4E40}.Release|Any CPU.ActiveCfg = Release|x64 + {AD3D126D-6359-481B-BE17-69DFB0BC4E40}.Release|Any CPU.Build.0 = Release|x64 {AD3D126D-6359-481B-BE17-69DFB0BC4E40}.Release|x64.ActiveCfg = Release|x64 {AD3D126D-6359-481B-BE17-69DFB0BC4E40}.Release|x64.Build.0 = Release|x64 + {AD3D126D-6359-481B-BE17-69DFB0BC4E40}.TestAndRelease|Any CPU.ActiveCfg = Release|x64 + {AD3D126D-6359-481B-BE17-69DFB0BC4E40}.TestAndRelease|Any CPU.Build.0 = Release|x64 {AD3D126D-6359-481B-BE17-69DFB0BC4E40}.TestAndRelease|x64.ActiveCfg = Release|x64 {AD3D126D-6359-481B-BE17-69DFB0BC4E40}.TestAndRelease|x64.Build.0 = Release|x64 + {6A510911-5F37-4314-8176-82772B7E5AE3}.Debug|Any CPU.ActiveCfg = Debug|x64 + {6A510911-5F37-4314-8176-82772B7E5AE3}.Debug|Any CPU.Build.0 = Debug|x64 {6A510911-5F37-4314-8176-82772B7E5AE3}.Debug|x64.ActiveCfg = Debug|x64 {6A510911-5F37-4314-8176-82772B7E5AE3}.Debug|x64.Build.0 = Debug|x64 + {6A510911-5F37-4314-8176-82772B7E5AE3}.Release|Any CPU.ActiveCfg = Release|x64 + {6A510911-5F37-4314-8176-82772B7E5AE3}.Release|Any CPU.Build.0 = Release|x64 {6A510911-5F37-4314-8176-82772B7E5AE3}.Release|x64.ActiveCfg = Release|x64 {6A510911-5F37-4314-8176-82772B7E5AE3}.Release|x64.Build.0 = Release|x64 + {6A510911-5F37-4314-8176-82772B7E5AE3}.TestAndRelease|Any CPU.ActiveCfg = Release|x64 + {6A510911-5F37-4314-8176-82772B7E5AE3}.TestAndRelease|Any CPU.Build.0 = Release|x64 {6A510911-5F37-4314-8176-82772B7E5AE3}.TestAndRelease|x64.ActiveCfg = Release|x64 {6A510911-5F37-4314-8176-82772B7E5AE3}.TestAndRelease|x64.Build.0 = Release|x64 + {3DFDFDE6-0355-412B-BD62-2D2AD36C5639}.Debug|Any CPU.ActiveCfg = Debug|x64 + {3DFDFDE6-0355-412B-BD62-2D2AD36C5639}.Debug|Any CPU.Build.0 = Debug|x64 {3DFDFDE6-0355-412B-BD62-2D2AD36C5639}.Debug|x64.ActiveCfg = Debug|x64 {3DFDFDE6-0355-412B-BD62-2D2AD36C5639}.Debug|x64.Build.0 = Debug|x64 + {3DFDFDE6-0355-412B-BD62-2D2AD36C5639}.Release|Any CPU.ActiveCfg = Release|x64 + {3DFDFDE6-0355-412B-BD62-2D2AD36C5639}.Release|Any CPU.Build.0 = Release|x64 {3DFDFDE6-0355-412B-BD62-2D2AD36C5639}.Release|x64.ActiveCfg = Release|x64 {3DFDFDE6-0355-412B-BD62-2D2AD36C5639}.Release|x64.Build.0 = Release|x64 + {3DFDFDE6-0355-412B-BD62-2D2AD36C5639}.TestAndRelease|Any CPU.ActiveCfg = Release|x64 + {3DFDFDE6-0355-412B-BD62-2D2AD36C5639}.TestAndRelease|Any CPU.Build.0 = Release|x64 {3DFDFDE6-0355-412B-BD62-2D2AD36C5639}.TestAndRelease|x64.ActiveCfg = Release|x64 {3DFDFDE6-0355-412B-BD62-2D2AD36C5639}.TestAndRelease|x64.Build.0 = Release|x64 + {78FF34E1-B093-4D10-B77B-5A3AED043DD7}.Debug|Any CPU.ActiveCfg = Debug|x64 + {78FF34E1-B093-4D10-B77B-5A3AED043DD7}.Debug|Any CPU.Build.0 = Debug|x64 {78FF34E1-B093-4D10-B77B-5A3AED043DD7}.Debug|x64.ActiveCfg = Debug|x64 {78FF34E1-B093-4D10-B77B-5A3AED043DD7}.Debug|x64.Build.0 = Debug|x64 + {78FF34E1-B093-4D10-B77B-5A3AED043DD7}.Release|Any CPU.ActiveCfg = Release|x64 + {78FF34E1-B093-4D10-B77B-5A3AED043DD7}.Release|Any CPU.Build.0 = Release|x64 {78FF34E1-B093-4D10-B77B-5A3AED043DD7}.Release|x64.ActiveCfg = Release|x64 {78FF34E1-B093-4D10-B77B-5A3AED043DD7}.Release|x64.Build.0 = Release|x64 + {78FF34E1-B093-4D10-B77B-5A3AED043DD7}.TestAndRelease|Any CPU.ActiveCfg = Release|x64 + {78FF34E1-B093-4D10-B77B-5A3AED043DD7}.TestAndRelease|Any CPU.Build.0 = Release|x64 {78FF34E1-B093-4D10-B77B-5A3AED043DD7}.TestAndRelease|x64.ActiveCfg = Release|x64 {78FF34E1-B093-4D10-B77B-5A3AED043DD7}.TestAndRelease|x64.Build.0 = Release|x64 + {7FA686DC-0269-47D1-9BD4-03D5F1BA3597}.Debug|Any CPU.ActiveCfg = Debug|x64 + {7FA686DC-0269-47D1-9BD4-03D5F1BA3597}.Debug|Any CPU.Build.0 = Debug|x64 {7FA686DC-0269-47D1-9BD4-03D5F1BA3597}.Debug|x64.ActiveCfg = Debug|x64 {7FA686DC-0269-47D1-9BD4-03D5F1BA3597}.Debug|x64.Build.0 = Debug|x64 + {7FA686DC-0269-47D1-9BD4-03D5F1BA3597}.Release|Any CPU.ActiveCfg = Release|x64 + {7FA686DC-0269-47D1-9BD4-03D5F1BA3597}.Release|Any CPU.Build.0 = Release|x64 {7FA686DC-0269-47D1-9BD4-03D5F1BA3597}.Release|x64.ActiveCfg = Release|x64 {7FA686DC-0269-47D1-9BD4-03D5F1BA3597}.Release|x64.Build.0 = Release|x64 + {7FA686DC-0269-47D1-9BD4-03D5F1BA3597}.TestAndRelease|Any CPU.ActiveCfg = Release|x64 + {7FA686DC-0269-47D1-9BD4-03D5F1BA3597}.TestAndRelease|Any CPU.Build.0 = Release|x64 {7FA686DC-0269-47D1-9BD4-03D5F1BA3597}.TestAndRelease|x64.ActiveCfg = Release|x64 {7FA686DC-0269-47D1-9BD4-03D5F1BA3597}.TestAndRelease|x64.Build.0 = Release|x64 + {891888CA-E5CC-4168-B6F2-2B2CED74EA37}.Debug|Any CPU.ActiveCfg = Debug|x64 + {891888CA-E5CC-4168-B6F2-2B2CED74EA37}.Debug|Any CPU.Build.0 = Debug|x64 {891888CA-E5CC-4168-B6F2-2B2CED74EA37}.Debug|x64.ActiveCfg = Debug|x64 {891888CA-E5CC-4168-B6F2-2B2CED74EA37}.Debug|x64.Build.0 = Debug|x64 + {891888CA-E5CC-4168-B6F2-2B2CED74EA37}.Release|Any CPU.ActiveCfg = Release|x64 + {891888CA-E5CC-4168-B6F2-2B2CED74EA37}.Release|Any CPU.Build.0 = Release|x64 {891888CA-E5CC-4168-B6F2-2B2CED74EA37}.Release|x64.ActiveCfg = Release|x64 {891888CA-E5CC-4168-B6F2-2B2CED74EA37}.Release|x64.Build.0 = Release|x64 + {891888CA-E5CC-4168-B6F2-2B2CED74EA37}.TestAndRelease|Any CPU.ActiveCfg = Release|x64 + {891888CA-E5CC-4168-B6F2-2B2CED74EA37}.TestAndRelease|Any CPU.Build.0 = Release|x64 {891888CA-E5CC-4168-B6F2-2B2CED74EA37}.TestAndRelease|x64.ActiveCfg = Release|x64 {891888CA-E5CC-4168-B6F2-2B2CED74EA37}.TestAndRelease|x64.Build.0 = Release|x64 + {04615EBF-20FC-437C-9CF7-47DA6260FAE3}.Debug|Any CPU.ActiveCfg = Debug|x64 + {04615EBF-20FC-437C-9CF7-47DA6260FAE3}.Debug|Any CPU.Build.0 = Debug|x64 {04615EBF-20FC-437C-9CF7-47DA6260FAE3}.Debug|x64.ActiveCfg = Debug|x64 {04615EBF-20FC-437C-9CF7-47DA6260FAE3}.Debug|x64.Build.0 = Debug|x64 + {04615EBF-20FC-437C-9CF7-47DA6260FAE3}.Release|Any CPU.ActiveCfg = Release|x64 + {04615EBF-20FC-437C-9CF7-47DA6260FAE3}.Release|Any CPU.Build.0 = Release|x64 {04615EBF-20FC-437C-9CF7-47DA6260FAE3}.Release|x64.ActiveCfg = Release|x64 + {04615EBF-20FC-437C-9CF7-47DA6260FAE3}.TestAndRelease|Any CPU.ActiveCfg = Release|x64 + {04615EBF-20FC-437C-9CF7-47DA6260FAE3}.TestAndRelease|Any CPU.Build.0 = Release|x64 {04615EBF-20FC-437C-9CF7-47DA6260FAE3}.TestAndRelease|x64.ActiveCfg = Release|x64 {04615EBF-20FC-437C-9CF7-47DA6260FAE3}.TestAndRelease|x64.Build.0 = Release|x64 + {E27A5C14-0C05-466A-91CE-ABB5151A69C4}.Debug|Any CPU.ActiveCfg = Debug|x64 + {E27A5C14-0C05-466A-91CE-ABB5151A69C4}.Debug|Any CPU.Build.0 = Debug|x64 {E27A5C14-0C05-466A-91CE-ABB5151A69C4}.Debug|x64.ActiveCfg = Debug|x64 {E27A5C14-0C05-466A-91CE-ABB5151A69C4}.Debug|x64.Build.0 = Debug|x64 + {E27A5C14-0C05-466A-91CE-ABB5151A69C4}.Release|Any CPU.ActiveCfg = Release|x64 + {E27A5C14-0C05-466A-91CE-ABB5151A69C4}.Release|Any CPU.Build.0 = Release|x64 {E27A5C14-0C05-466A-91CE-ABB5151A69C4}.Release|x64.ActiveCfg = Release|x64 {E27A5C14-0C05-466A-91CE-ABB5151A69C4}.Release|x64.Build.0 = Release|x64 + {E27A5C14-0C05-466A-91CE-ABB5151A69C4}.TestAndRelease|Any CPU.ActiveCfg = Release|x64 + {E27A5C14-0C05-466A-91CE-ABB5151A69C4}.TestAndRelease|Any CPU.Build.0 = Release|x64 {E27A5C14-0C05-466A-91CE-ABB5151A69C4}.TestAndRelease|x64.ActiveCfg = Release|x64 {E27A5C14-0C05-466A-91CE-ABB5151A69C4}.TestAndRelease|x64.Build.0 = Release|x64 + {48CA975B-65DD-4A03-89A3-EA2448293894}.Debug|Any CPU.ActiveCfg = Debug|x64 + {48CA975B-65DD-4A03-89A3-EA2448293894}.Debug|Any CPU.Build.0 = Debug|x64 {48CA975B-65DD-4A03-89A3-EA2448293894}.Debug|x64.ActiveCfg = Debug|x64 {48CA975B-65DD-4A03-89A3-EA2448293894}.Debug|x64.Build.0 = Debug|x64 + {48CA975B-65DD-4A03-89A3-EA2448293894}.Release|Any CPU.ActiveCfg = Release|x64 + {48CA975B-65DD-4A03-89A3-EA2448293894}.Release|Any CPU.Build.0 = Release|x64 {48CA975B-65DD-4A03-89A3-EA2448293894}.Release|x64.ActiveCfg = Release|x64 {48CA975B-65DD-4A03-89A3-EA2448293894}.Release|x64.Build.0 = Release|x64 + {48CA975B-65DD-4A03-89A3-EA2448293894}.TestAndRelease|Any CPU.ActiveCfg = Release|x64 + {48CA975B-65DD-4A03-89A3-EA2448293894}.TestAndRelease|Any CPU.Build.0 = Release|x64 {48CA975B-65DD-4A03-89A3-EA2448293894}.TestAndRelease|x64.ActiveCfg = Release|x64 {48CA975B-65DD-4A03-89A3-EA2448293894}.TestAndRelease|x64.Build.0 = Release|x64 + {4661C249-5B9A-4D9F-B852-15EAF3B4F9A3}.Debug|Any CPU.ActiveCfg = Debug|x64 + {4661C249-5B9A-4D9F-B852-15EAF3B4F9A3}.Debug|Any CPU.Build.0 = Debug|x64 {4661C249-5B9A-4D9F-B852-15EAF3B4F9A3}.Debug|x64.ActiveCfg = Debug|x64 {4661C249-5B9A-4D9F-B852-15EAF3B4F9A3}.Debug|x64.Build.0 = Debug|x64 + {4661C249-5B9A-4D9F-B852-15EAF3B4F9A3}.Release|Any CPU.ActiveCfg = Release|x64 + {4661C249-5B9A-4D9F-B852-15EAF3B4F9A3}.Release|Any CPU.Build.0 = Release|x64 {4661C249-5B9A-4D9F-B852-15EAF3B4F9A3}.Release|x64.ActiveCfg = Release|x64 {4661C249-5B9A-4D9F-B852-15EAF3B4F9A3}.Release|x64.Build.0 = Release|x64 + {4661C249-5B9A-4D9F-B852-15EAF3B4F9A3}.TestAndRelease|Any CPU.ActiveCfg = Release|x64 + {4661C249-5B9A-4D9F-B852-15EAF3B4F9A3}.TestAndRelease|Any CPU.Build.0 = Release|x64 {4661C249-5B9A-4D9F-B852-15EAF3B4F9A3}.TestAndRelease|x64.ActiveCfg = Release|x64 {4661C249-5B9A-4D9F-B852-15EAF3B4F9A3}.TestAndRelease|x64.Build.0 = Release|x64 EndGlobalSection From 4ea1843541db207f9638c2deadc59fbe66c4d817 Mon Sep 17 00:00:00 2001 From: nbollis Date: Thu, 12 Dec 2024 18:52:52 -0600 Subject: [PATCH 3/8] Reduced conditional checks in ModificaitonLocalization and stringbuilder simplificaiton in BioPolymerWithSetModsExtensions --- .../Omics/BioPolymerWithSetModsExtensions.cs | 34 +++++----- mzLib/Omics/IBioPolymerWithSetMods.cs | 10 +-- .../Modifications/ModificationLocalization.cs | 65 ++++++++++--------- mzLib/Proteomics/Protein/Protein.cs | 2 +- 4 files changed, 58 insertions(+), 53 deletions(-) diff --git a/mzLib/Omics/BioPolymerWithSetModsExtensions.cs b/mzLib/Omics/BioPolymerWithSetModsExtensions.cs index 2e5d29718..a82660d9a 100644 --- a/mzLib/Omics/BioPolymerWithSetModsExtensions.cs +++ b/mzLib/Omics/BioPolymerWithSetModsExtensions.cs @@ -18,9 +18,9 @@ public static string FullSequenceWithMassShift(this IBioPolymerWithSetMods withS var subsequence = new StringBuilder(); // modification on peptide N-terminus - if (withSetMods.AllModsOneIsNterminus.TryGetValue(1, out Modification mod)) + if (withSetMods.AllModsOneIsNterminus.TryGetValue(1, out Modification? mod)) { - subsequence.Append('[' + mod.MonoisotopicMass.RoundedDouble(6).ToString() + ']'); + subsequence.Append($"[{mod.MonoisotopicMass.RoundedDouble(6)}]"); } for (int r = 0; r < withSetMods.Length; r++) @@ -32,11 +32,11 @@ public static string FullSequenceWithMassShift(this IBioPolymerWithSetMods withS { if (mod.MonoisotopicMass > 0) { - subsequence.Append("[+" + mod.MonoisotopicMass.RoundedDouble(6).ToString() + ']'); + subsequence.Append($"[+{mod.MonoisotopicMass.RoundedDouble(6)}]"); } else { - subsequence.Append("[" + mod.MonoisotopicMass.RoundedDouble(6).ToString() + ']'); + subsequence.Append($"[{mod.MonoisotopicMass.RoundedDouble(6)}]"); } } } @@ -46,11 +46,11 @@ public static string FullSequenceWithMassShift(this IBioPolymerWithSetMods withS { if (mod.MonoisotopicMass > 0) { - subsequence.Append("[+" + mod.MonoisotopicMass.RoundedDouble(6).ToString() + ']'); + subsequence.Append($"[+{mod.MonoisotopicMass.RoundedDouble(6)}]"); } else { - subsequence.Append("[" + mod.MonoisotopicMass.RoundedDouble(6).ToString() + ']'); + subsequence.Append($"[{mod.MonoisotopicMass.RoundedDouble(6)}]"); } } return subsequence.ToString(); @@ -68,14 +68,15 @@ public static string EssentialSequence(this IBioPolymerWithSetMods withSetMods, string essentialSequence = withSetMods.BaseSequence; if (modstoWritePruned != null) { - var sbsequence = new StringBuilder(); + var sbsequence = new StringBuilder(withSetMods.FullSequence.Length); // variable modification on peptide N-terminus if (withSetMods.AllModsOneIsNterminus.TryGetValue(1, out Modification pep_n_term_variable_mod)) { if (modstoWritePruned.ContainsKey(pep_n_term_variable_mod.ModificationType)) { - sbsequence.Append('[' + pep_n_term_variable_mod.ModificationType + ":" + pep_n_term_variable_mod.IdWithMotif + ']'); + sbsequence.Append( + $"[{pep_n_term_variable_mod.ModificationType}:{pep_n_term_variable_mod.IdWithMotif}]"); } } for (int r = 0; r < withSetMods.Length; r++) @@ -86,7 +87,8 @@ public static string EssentialSequence(this IBioPolymerWithSetMods withSetMods, { if (modstoWritePruned.ContainsKey(residue_variable_mod.ModificationType)) { - sbsequence.Append('[' + residue_variable_mod.ModificationType + ":" + residue_variable_mod.IdWithMotif + ']'); + sbsequence.Append( + $"[{residue_variable_mod.ModificationType}:{residue_variable_mod.IdWithMotif}]"); } } } @@ -96,7 +98,8 @@ public static string EssentialSequence(this IBioPolymerWithSetMods withSetMods, { if (modstoWritePruned.ContainsKey(pep_c_term_variable_mod.ModificationType)) { - sbsequence.Append('[' + pep_c_term_variable_mod.ModificationType + ":" + pep_c_term_variable_mod.IdWithMotif + ']'); + sbsequence.Append( + $"[{pep_c_term_variable_mod.ModificationType}:{pep_c_term_variable_mod.IdWithMotif}]"); } } @@ -112,12 +115,13 @@ public static string EssentialSequence(this IBioPolymerWithSetMods withSetMods, /// public static string DetermineFullSequence(this IBioPolymerWithSetMods withSetMods) { - var subSequence = new StringBuilder(); + // start string builder with initial capacity to avoid resizing costs. + var subSequence = new StringBuilder(withSetMods.BaseSequence.Length + withSetMods.AllModsOneIsNterminus.Count * 20); // modification on peptide N-terminus - if (withSetMods.AllModsOneIsNterminus.TryGetValue(1, out Modification mod)) + if (withSetMods.AllModsOneIsNterminus.TryGetValue(1, out Modification? mod)) { - subSequence.Append('[' + mod.ModificationType + ":" + mod.IdWithMotif + ']'); + subSequence.Append($"[{mod.ModificationType}:{mod.IdWithMotif}]"); } for (int r = 0; r < withSetMods.Length; r++) @@ -127,14 +131,14 @@ public static string DetermineFullSequence(this IBioPolymerWithSetMods withSetMo // modification on this residue if (withSetMods.AllModsOneIsNterminus.TryGetValue(r + 2, out mod)) { - subSequence.Append('[' + mod.ModificationType + ":" + mod.IdWithMotif + ']'); + subSequence.Append($"[{mod.ModificationType}:{mod.IdWithMotif}]"); } } // modification on peptide C-terminus if (withSetMods.AllModsOneIsNterminus.TryGetValue(withSetMods.Length + 2, out mod)) { - subSequence.Append('[' + mod.ModificationType + ":" + mod.IdWithMotif + ']'); + subSequence.Append($"[{mod.ModificationType}:{mod.IdWithMotif}]"); } return subSequence.ToString(); diff --git a/mzLib/Omics/IBioPolymerWithSetMods.cs b/mzLib/Omics/IBioPolymerWithSetMods.cs index 8bbca0d33..675b32d15 100644 --- a/mzLib/Omics/IBioPolymerWithSetMods.cs +++ b/mzLib/Omics/IBioPolymerWithSetMods.cs @@ -1,4 +1,5 @@ -using System.Text; +using System.Runtime.CompilerServices; +using System.Text; using Chemistry; using MassSpectrometry; using Omics.Digestion; @@ -63,7 +64,7 @@ public void FragmentInternally(DissociationType dissociationType, int minLengthO public static string GetBaseSequenceFromFullSequence(string fullSequence) { - StringBuilder sb = new StringBuilder(); + StringBuilder sb = new StringBuilder(fullSequence.Length); int bracketCount = 0; foreach (char c in fullSequence) { @@ -163,10 +164,5 @@ public static Dictionary GetModificationDictionaryFromFullSeq /// public static List GetModificationsFromFullSequence(string fullSequence, Dictionary allModsKnown) => [.. GetModificationDictionaryFromFullSequence(fullSequence, allModsKnown).Values]; - - public bool Equals(IBioPolymerWithSetMods other); - - public int GetHashCode(); - } } diff --git a/mzLib/Omics/Modifications/ModificationLocalization.cs b/mzLib/Omics/Modifications/ModificationLocalization.cs index bbf25d1a3..1b8d84c31 100644 --- a/mzLib/Omics/Modifications/ModificationLocalization.cs +++ b/mzLib/Omics/Modifications/ModificationLocalization.cs @@ -2,45 +2,47 @@ { public static class ModificationLocalization { + // This method is called a ton (8.8 billion times in Bottom-Up Jenkins as of 1.0.6) in MetaMorpheus. If changes are made, ensure they are efficient. public static bool ModFits(Modification attemptToLocalize, string sequence, int digestionProductOneBasedIndex, int digestionProductLength, int bioPolymerOneBasedIndex) { // First find the capital letter... - var motif = attemptToLocalize.Target; - var motifStartLocation = motif.ToString().IndexOf(motif.ToString().First(b => char.IsUpper(b))); + var motif = attemptToLocalize.Target.ToString(); + var motifStartLocation = -1; + for (int i = 0; i < motif.Length; i++) + { + if (char.IsUpper(motif[i])) + { + motifStartLocation = i; + break; + } + } // Look up starting at and including the capital letter var proteinToMotifOffset = bioPolymerOneBasedIndex - motifStartLocation - 1; - var indexUp = 0; - while (indexUp < motif.ToString().Length) + for (int indexUp = 0; indexUp < motif.Length; indexUp++) { - if (indexUp + proteinToMotifOffset < 0 || indexUp + proteinToMotifOffset >= sequence.Length - || !MotifMatches(motif.ToString()[indexUp], sequence[indexUp + proteinToMotifOffset])) + int sequenceIndex = indexUp + proteinToMotifOffset; + if (sequenceIndex < 0 || sequenceIndex >= sequence.Length || !MotifMatches(motif[indexUp], sequence[sequenceIndex])) { return false; } - indexUp++; } - switch (attemptToLocalize.LocationRestriction) + + return attemptToLocalize.LocationRestriction switch { - case "N-terminal." when bioPolymerOneBasedIndex > 2: - case "Peptide N-terminal." when digestionProductOneBasedIndex > 1: - case "C-terminal." when bioPolymerOneBasedIndex < sequence.Length: - case "Peptide C-terminal." when digestionProductOneBasedIndex < digestionProductLength: - case "5'-terminal." when bioPolymerOneBasedIndex > 2: + "N-terminal." when bioPolymerOneBasedIndex > 2 => false, + "Peptide N-terminal." when digestionProductOneBasedIndex > 1 => false, + "C-terminal." when bioPolymerOneBasedIndex < sequence.Length => false, + "Peptide C-terminal." when digestionProductOneBasedIndex < digestionProductLength => false, + "5'-terminal." when bioPolymerOneBasedIndex > 2 => false, // first residue in oligo but not first in nucleic acid - case "Oligo 5'-terminal." when digestionProductOneBasedIndex > 1 - || bioPolymerOneBasedIndex == 1: - case "3'-terminal." when bioPolymerOneBasedIndex < sequence.Length: + "Oligo 5'-terminal." when digestionProductOneBasedIndex > 1 || bioPolymerOneBasedIndex == 1 => false, + "3'-terminal." when bioPolymerOneBasedIndex < sequence.Length => false, // not the last residue in oligo but not in nucleic acid - case "Oligo 3'-terminal." when digestionProductOneBasedIndex < digestionProductLength - || bioPolymerOneBasedIndex == sequence.Length: - return false; - - default: - // I guess Anywhere. and Unassigned. are true since how do you localize anywhere or unassigned. - - return true; - } + "Oligo 3'-terminal." when digestionProductOneBasedIndex < digestionProductLength || + bioPolymerOneBasedIndex == sequence.Length => false, + _ => true + }; } public static bool UniprotModExists(IBioPolymer bioPolymer, int i, Modification attemptToLocalize) @@ -56,11 +58,14 @@ public static bool UniprotModExists(IBioPolymer bioPolymer, int i, Modification private static bool MotifMatches(char motifChar, char sequenceChar) { char upperMotifChar = char.ToUpper(motifChar); - return upperMotifChar.Equals('X') - || upperMotifChar.Equals(sequenceChar) - || upperMotifChar.Equals('B') && new[] { 'D', 'N' }.Contains(sequenceChar) - || upperMotifChar.Equals('J') && new[] { 'I', 'L' }.Contains(sequenceChar) - || upperMotifChar.Equals('Z') && new[] { 'E', 'Q' }.Contains(sequenceChar); + return upperMotifChar switch + { + 'X' => true, + 'B' => sequenceChar is 'D' or 'N', + 'J' => sequenceChar is 'I' or 'L', + 'Z' => sequenceChar is 'E' or 'Q', + _ => upperMotifChar == sequenceChar + }; } } } \ No newline at end of file diff --git a/mzLib/Proteomics/Protein/Protein.cs b/mzLib/Proteomics/Protein/Protein.cs index 1c91cd59c..d8cac6a1b 100644 --- a/mzLib/Proteomics/Protein/Protein.cs +++ b/mzLib/Proteomics/Protein/Protein.cs @@ -12,7 +12,7 @@ namespace Proteomics { - public class Protein : IBioPolymer + public class Protein : IBioPolymer, IComparable { private List _proteolysisProducts; From 0c340cf59589ca356e2b439bb3ce7936c68ad30b Mon Sep 17 00:00:00 2001 From: nbollis Date: Thu, 12 Dec 2024 20:09:29 -0600 Subject: [PATCH 4/8] Reduced Runtime of Peptide with set modificaitons and parent classes --- mzLib/MzLibUtil/DictionaryPool.cs | 59 ++++++++++++++ mzLib/Omics/Digestion/DigestionProduct.cs | 13 ++- .../PeptideWithSetModifications.cs | 79 ++++++++++--------- .../ProteolyticDigestion/Protease.cs | 7 +- .../ProteolyticPeptide.cs | 11 +-- 5 files changed, 122 insertions(+), 47 deletions(-) create mode 100644 mzLib/MzLibUtil/DictionaryPool.cs diff --git a/mzLib/MzLibUtil/DictionaryPool.cs b/mzLib/MzLibUtil/DictionaryPool.cs new file mode 100644 index 000000000..009fa8522 --- /dev/null +++ b/mzLib/MzLibUtil/DictionaryPool.cs @@ -0,0 +1,59 @@ +using Microsoft.Extensions.ObjectPool; +using System.Collections.Generic; +using System; + +namespace MzLibUtil; + +// var dictionaryPool = new DictionaryPool(); +// var dictionary = dictionaryPool.Get(); +// dictionary["key"] = 42; +// do work with dictionary +// dictionaryPool.Return(dictionary); + +public class DictionaryPool +{ + private readonly ObjectPool> _pool; + + /// + /// Initializes a new instance of the class. + /// + /// Initial capacity for the pooled Dictionary instances. + public DictionaryPool(int initialCapacity = 16) + { + var policy = new DictionaryPooledObjectPolicy(initialCapacity); + _pool = new DefaultObjectPool>(policy); + } + + /// + /// Retrieves a Dictionary instance from the pool. + /// + /// A Dictionary instance. + public Dictionary Get() => _pool.Get(); + + /// + /// Returns a Dictionary instance back to the pool. + /// + /// The Dictionary instance to return. + public void Return(Dictionary dictionary) + { + if (dictionary == null) throw new ArgumentNullException(nameof(dictionary)); + dictionary.Clear(); // Ensure the Dictionary is clean before returning it to the pool + _pool.Return(dictionary); + } + + private class DictionaryPooledObjectPolicy(int initialCapacity) + : PooledObjectPolicy> + { + public override Dictionary Create() + { + return new Dictionary(capacity: initialCapacity); + } + + public override bool Return(Dictionary obj) + { + // Ensure the Dictionary can be safely reused + obj.Clear(); + return true; + } + } +} \ No newline at end of file diff --git a/mzLib/Omics/Digestion/DigestionProduct.cs b/mzLib/Omics/Digestion/DigestionProduct.cs index 1e86ec53b..40783370a 100644 --- a/mzLib/Omics/Digestion/DigestionProduct.cs +++ b/mzLib/Omics/Digestion/DigestionProduct.cs @@ -79,7 +79,8 @@ protected Dictionary GetFixedModsOneIsNorFivePrimeTerminus(in case "Oligo 5'-terminal.": case "N-terminal.": case "Peptide N-terminal.": - //the modification is protease associated and is applied to the n-terminal cleaved residue, not at the beginning of the protein + + //the modification is protease associated and is applied to the n-terminal cleaved residue, not at the beginign of the protein if (ModificationLocalization.ModFits(mod, Parent.BaseSequence, 1, length, OneBasedStartResidue)) { if (mod.ModificationType == "Protease") @@ -92,6 +93,16 @@ protected Dictionary GetFixedModsOneIsNorFivePrimeTerminus(in } break; + case "Anywhere.": + for (int i = 2; i <= length + 1; i++) + { + if (ModificationLocalization.ModFits(mod, Parent.BaseSequence, i - 1, length, OneBasedStartResidue + i - 2)) + { + fixedModsOneIsNterminus[i] = mod; + } + } + break; + case "3'-terminal.": case "Oligo 3'-terminal.": case "C-terminal.": diff --git a/mzLib/Proteomics/ProteolyticDigestion/PeptideWithSetModifications.cs b/mzLib/Proteomics/ProteolyticDigestion/PeptideWithSetModifications.cs index ebb304161..6fae60596 100644 --- a/mzLib/Proteomics/ProteolyticDigestion/PeptideWithSetModifications.cs +++ b/mzLib/Proteomics/ProteolyticDigestion/PeptideWithSetModifications.cs @@ -1,4 +1,5 @@ -using Chemistry; +#nullable enable +using Chemistry; using MassSpectrometry; using Proteomics.AminoAcidPolymer; using System; @@ -10,12 +11,14 @@ using Omics.Fragmentation; using Omics.Fragmentation.Peptide; using Omics.Modifications; +using MzLibUtil; namespace Proteomics.ProteolyticDigestion { [Serializable] public class PeptideWithSetModifications : ProteolyticPeptide, IBioPolymerWithSetMods { + private static readonly HashSetPool HashSetPool = new(); public string FullSequence { get; private set; } //sequence with modifications public int NumFixedMods { get; } // Parameter to store the full sequence of the corresponding Target or Decoy peptide @@ -98,13 +101,17 @@ public double MonoisotopicMass foreach (var mod in AllModsOneIsNterminus.Values) { - monoMass += mod.MonoisotopicMass.Value; + monoMass += mod.MonoisotopicMass!.Value; + } + + for (var index = 0; index < BaseSequence.Length; index++) + { + monoMass += Residue.ResidueMonoisotopicMass[BaseSequence[index]]; } - monoMass += BaseSequence.Sum(b => Residue.ResidueMonoisotopicMass[b]); _monoisotopicMass = monoMass; } - return (double)ClassExtensions.RoundedDouble(_monoisotopicMass.Value); + return (double)_monoisotopicMass.Value.RoundedDouble()!; } } @@ -142,10 +149,10 @@ public double MostAbundantMonoisotopicMass IsotopicDistribution dist = IsotopicDistribution.GetDistribution(this.FullChemicalFormula); double maxIntensity = dist.Intensities.Max(); _mostAbundantMonoisotopicMass = - (double)ClassExtensions.RoundedDouble( - dist.Masses.ToList()[dist.Intensities.ToList().IndexOf(maxIntensity)]); + (double) + dist.Masses.ToList()[dist.Intensities.ToList().IndexOf(maxIntensity)].RoundedDouble()!; } - return (double)ClassExtensions.RoundedDouble(_mostAbundantMonoisotopicMass.Value); + return (double)_mostAbundantMonoisotopicMass.Value.RoundedDouble()!; } } @@ -157,7 +164,7 @@ public string SequenceWithChemicalFormulas if (!_hasChemicalFormulas.HasValue) { _hasChemicalFormulas = true; - var subsequence = new StringBuilder(); + var subsequence = new StringBuilder(FullSequence.Length); // variable modification on peptide N-terminus if (AllModsOneIsNterminus.TryGetValue(1, out Modification pep_n_term_variable_mod)) @@ -254,30 +261,30 @@ public void Fragment(DissociationType dissociationType, FragmentationTerminus fr // inefficient memory usage and thus frequent garbage collection. // TODO: If you can think of a way to remove these collections and still maintain correct // fragmentation, please do so. - HashSet nTermNeutralLosses = null; - HashSet cTermNeutralLosses = null; + HashSet? nTermNeutralLosses = null!; + HashSet? cTermNeutralLosses = null!; // n-terminus mod if (calculateNTermFragments) { - if (AllModsOneIsNterminus.TryGetValue(1, out Modification mod)) + if (AllModsOneIsNterminus.TryGetValue(1, out Modification? mod)) { - nTermMass += mod.MonoisotopicMass.Value; + nTermMass += mod.MonoisotopicMass!.Value; // n-term mod neutral loss - nTermNeutralLosses = AddNeutralLossesFromMods(mod, nTermNeutralLosses, dissociationType); + AddNeutralLossesFromMods(mod, dissociationType, ref nTermNeutralLosses); } } // c-terminus mod if (calculateCTermFragments) { - if (AllModsOneIsNterminus.TryGetValue(BaseSequence.Length + 2, out Modification mod)) + if (AllModsOneIsNterminus.TryGetValue(BaseSequence.Length + 2, out Modification? mod)) { - cTermMass += mod.MonoisotopicMass.Value; + cTermMass += mod.MonoisotopicMass!.Value; // c-term mod neutral loss - cTermNeutralLosses = AddNeutralLossesFromMods(mod, cTermNeutralLosses, dissociationType); + AddNeutralLossesFromMods(mod, dissociationType, ref cTermNeutralLosses); } } @@ -348,7 +355,7 @@ public void Fragment(DissociationType dissociationType, FragmentationTerminus fr r + 1, 0)); - nTermNeutralLosses = AddNeutralLossesFromMods(mod, nTermNeutralLosses, dissociationType); + AddNeutralLossesFromMods(mod, dissociationType, ref nTermNeutralLosses); if (nTermNeutralLosses != null) { @@ -434,7 +441,7 @@ public void Fragment(DissociationType dissociationType, FragmentationTerminus fr BaseSequence.Length - r, 0)); - cTermNeutralLosses = AddNeutralLossesFromMods(mod, cTermNeutralLosses, dissociationType); + AddNeutralLossesFromMods(mod, dissociationType, ref cTermNeutralLosses); if (cTermNeutralLosses != null) { @@ -482,7 +489,7 @@ public void Fragment(DissociationType dissociationType, FragmentationTerminus fr 1, 0)); - cTermNeutralLosses = AddNeutralLossesFromMods(mod, cTermNeutralLosses, dissociationType); + AddNeutralLossesFromMods(mod, dissociationType, ref cTermNeutralLosses); if (cTermNeutralLosses != null) { @@ -499,6 +506,12 @@ public void Fragment(DissociationType dissociationType, FragmentationTerminus fr } } + // release hashsets to reuse memory in next fragmentation event + if (cTermNeutralLosses is not null) + HashSetPool.Return(cTermNeutralLosses); + if (nTermNeutralLosses is not null) + HashSetPool.Return(nTermNeutralLosses); + foreach (var mod in AllModsOneIsNterminus.Where(p => p.Value.NeutralLosses != null)) { // molecular ion minus neutral losses @@ -952,41 +965,31 @@ private void UpdateCleavageSpecificity() } } - private HashSet AddNeutralLossesFromMods(Modification mod, HashSet allNeutralLossesSoFar, DissociationType dissociationType) + private void AddNeutralLossesFromMods(Modification? mod, DissociationType dissociationType, ref HashSet? allNeutralLossesSoFar) { + // if mod or mod.NeutralLosses is null, return + if (mod is not { NeutralLosses: not null }) + return; + // add neutral losses specific to this dissociation type - if (mod != null - && mod.NeutralLosses != null - && mod.NeutralLosses.TryGetValue(dissociationType, out List neutralLossesFromMod)) + if (mod.NeutralLosses.TryGetValue(dissociationType, out List? neutralLossesFromMod)) { foreach (double neutralLoss in neutralLossesFromMod.Where(p => p != 0)) { - if (allNeutralLossesSoFar == null) - { - allNeutralLossesSoFar = new HashSet(); - } - + allNeutralLossesSoFar ??= HashSetPool.Get(); allNeutralLossesSoFar.Add(neutralLoss); } } // add neutral losses that are generic to any dissociation type - if (mod != null - && mod.NeutralLosses != null - && mod.NeutralLosses.TryGetValue(DissociationType.AnyActivationType, out neutralLossesFromMod)) + if (mod.NeutralLosses.TryGetValue(DissociationType.AnyActivationType, out neutralLossesFromMod)) { foreach (double neutralLoss in neutralLossesFromMod.Where(p => p != 0)) { - if (allNeutralLossesSoFar == null) - { - allNeutralLossesSoFar = new HashSet(); - } - + allNeutralLossesSoFar ??= HashSetPool.Get(); allNeutralLossesSoFar.Add(neutralLoss); } } - - return allNeutralLossesSoFar; } //This function maintains the amino acids associated with the protease motif and reverses all other amino acids. diff --git a/mzLib/Proteomics/ProteolyticDigestion/Protease.cs b/mzLib/Proteomics/ProteolyticDigestion/Protease.cs index 5bca90400..99aafb566 100644 --- a/mzLib/Proteomics/ProteolyticDigestion/Protease.cs +++ b/mzLib/Proteomics/ProteolyticDigestion/Protease.cs @@ -90,7 +90,7 @@ public CleavageSpecificity GetCleavageSpecificity(Protein protein, int startInde internal List GetUnmodifiedPeptides(Protein protein, int maximumMissedCleavages, InitiatorMethionineBehavior initiatorMethionineBehavior, int minPeptideLength, int maxPeptideLength, Protease specificProtease, bool topDownTruncationSearch = false) { - List peptides = new List(); + List peptides; // proteolytic cleavage in one spot (N) if (CleavageSpecificity == CleavageSpecificity.SingleN) @@ -107,6 +107,7 @@ internal List GetUnmodifiedPeptides(Protein protein, int max //top-down else if (CleavageSpecificity == CleavageSpecificity.None) { + peptides = new(20); if (!topDownTruncationSearch)//standard top-down { // retain methionine @@ -136,13 +137,13 @@ internal List GetUnmodifiedPeptides(Protein protein, int max // Full proteolytic cleavage else if (CleavageSpecificity == CleavageSpecificity.Full) { - peptides.AddRange(FullDigestion(protein, initiatorMethionineBehavior, maximumMissedCleavages, minPeptideLength, maxPeptideLength)); + peptides = FullDigestion(protein, initiatorMethionineBehavior, maximumMissedCleavages, minPeptideLength, maxPeptideLength).ToList(); } // Cleavage rules for semi-specific search else if (CleavageSpecificity == CleavageSpecificity.Semi) { - peptides.AddRange(SemiProteolyticDigestion(protein, initiatorMethionineBehavior, maximumMissedCleavages, minPeptideLength, maxPeptideLength)); + peptides = SemiProteolyticDigestion(protein, initiatorMethionineBehavior, maximumMissedCleavages, minPeptideLength, maxPeptideLength).ToList(); } else { diff --git a/mzLib/Proteomics/ProteolyticDigestion/ProteolyticPeptide.cs b/mzLib/Proteomics/ProteolyticDigestion/ProteolyticPeptide.cs index 954ce449a..789b386ee 100644 --- a/mzLib/Proteomics/ProteolyticDigestion/ProteolyticPeptide.cs +++ b/mzLib/Proteomics/ProteolyticDigestion/ProteolyticPeptide.cs @@ -1,7 +1,6 @@ using System; using System.Collections.Generic; -using System.Linq; -using System.Security.Cryptography; +using MzLibUtil; using Omics.Digestion; using Omics.Modifications; @@ -14,7 +13,8 @@ namespace Proteomics.ProteolyticDigestion [Serializable] public class ProteolyticPeptide : DigestionProduct { - + private static readonly DictionaryPool> DictionaryPool = new(); + internal ProteolyticPeptide(Protein protein, int oneBasedStartResidueInProtein, int oneBasedEndResidueInProtein, int missedCleavages, CleavageSpecificity cleavageSpecificityForFdrCategory, string peptideDescription = null, string baseSequence = null) : base(protein, oneBasedStartResidueInProtein, oneBasedEndResidueInProtein, missedCleavages, cleavageSpecificityForFdrCategory, peptideDescription, baseSequence) { @@ -51,13 +51,13 @@ public string PeptideDescription /// /// /// - internal IEnumerable GetModifiedPeptides(IEnumerable allKnownFixedModifications, + internal IEnumerable GetModifiedPeptides(List allKnownFixedModifications, DigestionParams digestionParams, List variableModifications) { int peptideLength = OneBasedEndResidue - OneBasedStartResidue + 1; int maximumVariableModificationIsoforms = digestionParams.MaxModificationIsoforms; int maxModsForPeptide = digestionParams.MaxModsForPeptide; - var twoBasedPossibleVariableAndLocalizeableModifications = new Dictionary>(peptideLength + 4); + var twoBasedPossibleVariableAndLocalizeableModifications = DictionaryPool.Get(); var pepNTermVariableMods = new List(); twoBasedPossibleVariableAndLocalizeableModifications.Add(1, pepNTermVariableMods); @@ -163,6 +163,7 @@ internal IEnumerable GetModifiedPeptides(IEnumerabl yield break; } } + DictionaryPool.Return(twoBasedPossibleVariableAndLocalizeableModifications); } /// From 6a43a4238af90201d9a9e9ccad9c2e1dfb671156 Mon Sep 17 00:00:00 2001 From: nbollis Date: Thu, 12 Dec 2024 20:33:24 -0600 Subject: [PATCH 5/8] Increase StringBuilder capacity, add ObjectPool tests Modified DetermineFullSequence to reduce StringBuilder resizes. Added Microsoft.Extensions.ObjectPool dependency. Introduced ObjectPoolTests for DictionaryPool and HashSetPool. --- .../Omics/BioPolymerWithSetModsExtensions.cs | 2 +- mzLib/Test/ObjectPoolTests.cs | 73 +++++++++++++++++++ mzLib/mzLib.nuspec | 2 + 3 files changed, 76 insertions(+), 1 deletion(-) create mode 100644 mzLib/Test/ObjectPoolTests.cs diff --git a/mzLib/Omics/BioPolymerWithSetModsExtensions.cs b/mzLib/Omics/BioPolymerWithSetModsExtensions.cs index a82660d9a..20d0e7abe 100644 --- a/mzLib/Omics/BioPolymerWithSetModsExtensions.cs +++ b/mzLib/Omics/BioPolymerWithSetModsExtensions.cs @@ -116,7 +116,7 @@ public static string EssentialSequence(this IBioPolymerWithSetMods withSetMods, public static string DetermineFullSequence(this IBioPolymerWithSetMods withSetMods) { // start string builder with initial capacity to avoid resizing costs. - var subSequence = new StringBuilder(withSetMods.BaseSequence.Length + withSetMods.AllModsOneIsNterminus.Count * 20); + var subSequence = new StringBuilder(withSetMods.BaseSequence.Length + withSetMods.AllModsOneIsNterminus.Count * 30); // modification on peptide N-terminus if (withSetMods.AllModsOneIsNterminus.TryGetValue(1, out Modification? mod)) diff --git a/mzLib/Test/ObjectPoolTests.cs b/mzLib/Test/ObjectPoolTests.cs new file mode 100644 index 000000000..3820517b6 --- /dev/null +++ b/mzLib/Test/ObjectPoolTests.cs @@ -0,0 +1,73 @@ +using System; +using NUnit.Framework; +using MzLibUtil; +using System.Collections.Generic; +using System.Text; +using System.Diagnostics.CodeAnalysis; + +namespace Test +{ + [TestFixture] + [ExcludeFromCodeCoverage] + public class DictionaryPoolTests + { + [Test] + public void Get_ReturnsDictionaryInstance() + { + var dictionaryPool = new DictionaryPool(); + var dictionary = dictionaryPool.Get(); + Assert.That(dictionary, Is.Not.Null); + Assert.That(dictionary, Is.InstanceOf>()); + } + + [Test] + public void Return_ClearsAndReturnsDictionaryToPool() + { + var dictionaryPool = new DictionaryPool(); + var dictionary = dictionaryPool.Get(); + dictionary["key"] = 42; + + dictionaryPool.Return(dictionary); + + Assert.That(dictionary.Count, Is.EqualTo(0)); + } + + [Test] + public void Return_ThrowsArgumentNullException_WhenDictionaryIsNull() + { + var dictionaryPool = new DictionaryPool(); + Assert.Throws(() => dictionaryPool.Return(null)); + } + } + + [TestFixture] + [ExcludeFromCodeCoverage] + public class HashSetPoolTests + { + [Test] + public void Get_ReturnsHashSetInstance() + { + var pool = new HashSetPool(); + var hashSet = pool.Get(); + Assert.That(hashSet, Is.Not.Null); + pool.Return(hashSet); + } + + [Test] + public void Return_ClearsHashSetBeforeReturningToPool() + { + var pool = new HashSetPool(); + var hashSet = pool.Get(); + hashSet.Add(1); + pool.Return(hashSet); + Assert.That(hashSet.Count, Is.EqualTo(0)); + } + + [Test] + public void Return_ThrowsArgumentNullException_WhenHashSetIsNull() + { + var pool = new HashSetPool(); + Assert.Throws(() => pool.Return(null)); + } + } +} diff --git a/mzLib/mzLib.nuspec b/mzLib/mzLib.nuspec index 3aa393afe..7b80e0abc 100644 --- a/mzLib/mzLib.nuspec +++ b/mzLib/mzLib.nuspec @@ -23,6 +23,7 @@ + @@ -35,6 +36,7 @@ + From 197ae9077debd1d4b9dfd500b0ed730e2b13190f Mon Sep 17 00:00:00 2001 From: nbollis Date: Thu, 12 Dec 2024 20:53:56 -0600 Subject: [PATCH 6/8] Implemented pools in classic deconv --- .../ClassicDeconvolutionAlgorithm.cs | 22 ++++++++++++++----- .../Algorithms/DeconvolutionAlgorithm.cs | 5 +++-- 2 files changed, 19 insertions(+), 8 deletions(-) diff --git a/mzLib/MassSpectrometry/Deconvolution/Algorithms/ClassicDeconvolutionAlgorithm.cs b/mzLib/MassSpectrometry/Deconvolution/Algorithms/ClassicDeconvolutionAlgorithm.cs index 8f7bb320b..188e0ecd1 100644 --- a/mzLib/MassSpectrometry/Deconvolution/Algorithms/ClassicDeconvolutionAlgorithm.cs +++ b/mzLib/MassSpectrometry/Deconvolution/Algorithms/ClassicDeconvolutionAlgorithm.cs @@ -32,7 +32,10 @@ internal override IEnumerable Deconvolute(MzSpectrum spectrumT yield break; } - var isolatedMassesAndCharges = new List(); + // start with different sizes for ms1 and ms2 deconvolution + var isolatedMassesAndCharges = range.Width > 10 + ? new List(16) + : new List(128); (int start, int end) indexes = ExtractIndices(range.Minimum, range.Maximum); @@ -48,6 +51,7 @@ internal override IEnumerable Deconvolute(MzSpectrum spectrumT //go through each peak in the selected range and assume it is the most intense peak of its isotopic envelope (if it's not, it will hopefully get a low score) //cycle through possible charge states and select the one that has the best score (fit) with the averagine model + HashSet allPossibleChargeStates = IntegerHashSetPool.Get(); for (int candidateForMostIntensePeakIndex = indexes.start; candidateForMostIntensePeakIndex < indexes.end; candidateForMostIntensePeakIndex++) @@ -61,7 +65,7 @@ internal override IEnumerable Deconvolute(MzSpectrum spectrumT double candidateForMostIntensePeakMz = spectrum.XArray[candidateForMostIntensePeakIndex]; //Find what charge states this peak might be based on the spacing of nearby peaks (assumes isotopic resolution) - HashSet allPossibleChargeStates = new HashSet(); + allPossibleChargeStates.Clear(); for (int i = candidateForMostIntensePeakIndex + 1; i < spectrum.XArray.Length; i++) //look at peaks of higher m/z @@ -149,7 +153,9 @@ internal override IEnumerable Deconvolute(MzSpectrum spectrumT } } - HashSet seen = new HashSet(); + IntegerHashSetPool.Return(allPossibleChargeStates); + + HashSet seen = DoubleHashSetPool.Get(); foreach (var ok in isolatedMassesAndCharges.OrderByDescending(b => b.Score)) { if (seen.Overlaps(ok.Peaks.Select(b => b.mz))) @@ -162,6 +168,7 @@ internal override IEnumerable Deconvolute(MzSpectrum spectrumT } yield return ok; } + DoubleHashSetPool.Return(seen); } private IsotopicEnvelope FindIsotopicEnvelope(int massIndex, double candidateForMostIntensePeakMz, double candidateForMostIntensePeakIntensity, double testMostIntenseMass, int chargeState, double deconvolutionTolerancePpm, double intensityRatioLimit, List monoisotopicMassPredictions) @@ -169,8 +176,9 @@ private IsotopicEnvelope FindIsotopicEnvelope(int massIndex, double candidateFor double[] theoreticalMasses = allMasses[massIndex]; double[] theoreticalIntensities = allIntensities[massIndex]; //add "most intense peak" - var listOfObservedPeaks = new List<(double, double)> { (candidateForMostIntensePeakMz, candidateForMostIntensePeakIntensity) }; - var listOfRatios = new List { theoreticalIntensities[0] / candidateForMostIntensePeakIntensity }; // theoreticalIntensities and theoreticalMasses are sorted by intensity, so first is most intense + var listOfObservedPeaks = new List<(double, double)>(32) { (candidateForMostIntensePeakMz, candidateForMostIntensePeakIntensity) }; + var listOfRatios = DoubleHashSetPool.Get(); + listOfRatios.Add(theoreticalIntensities[0] / candidateForMostIntensePeakIntensity); // theoreticalIntensities and theoreticalMasses are sorted by intensity, so first is most intense // Assuming the test peak is most intense... // Try to find the rest of the isotopes! double differenceBetweenTheorAndActualMass = testMostIntenseMass - theoreticalMasses[0]; //mass difference actual-theoretical for the tallest peak (not necessarily the monoisotopic) @@ -202,7 +210,9 @@ private IsotopicEnvelope FindIsotopicEnvelope(int massIndex, double candidateFor } } - return new IsotopicEnvelope(listOfObservedPeaks, monoisotopicMass, chargeState, totalIntensity, listOfRatios.StandardDeviation()); + var stDev = listOfRatios.StandardDeviation(); + DoubleHashSetPool.Return(listOfRatios); + return new IsotopicEnvelope(listOfObservedPeaks, monoisotopicMass, chargeState, totalIntensity, stDev); } private int ObserveAdjacentChargeStates(IsotopicEnvelope originalEnvelope, double mostIntensePeakMz, int massIndex, double deconvolutionTolerancePpm, double intensityRatioLimit, double minChargeToLookFor, double maxChargeToLookFor, List monoisotopicMassPredictions) diff --git a/mzLib/MassSpectrometry/Deconvolution/Algorithms/DeconvolutionAlgorithm.cs b/mzLib/MassSpectrometry/Deconvolution/Algorithms/DeconvolutionAlgorithm.cs index 1bb6bf523..0191e8719 100644 --- a/mzLib/MassSpectrometry/Deconvolution/Algorithms/DeconvolutionAlgorithm.cs +++ b/mzLib/MassSpectrometry/Deconvolution/Algorithms/DeconvolutionAlgorithm.cs @@ -1,8 +1,6 @@ using System; using System.Collections.Generic; using System.Linq; -using System.Text; -using System.Threading.Tasks; using Chemistry; using MzLibUtil; @@ -65,6 +63,9 @@ static DeconvolutionAlgorithm() #endregion protected readonly DeconvolutionParameters DeconvolutionParameters; + protected readonly HashSetPool IntegerHashSetPool = new(32); + protected readonly HashSetPool DoubleHashSetPool = new(32); + /// /// Constructor for deconvolution algorithms, nothing should be added to child constructors From 91a0b3b85b31716fe83925320d7800be17c46bb6 Mon Sep 17 00:00:00 2001 From: nbollis Date: Thu, 12 Dec 2024 21:09:02 -0600 Subject: [PATCH 7/8] Removed accidental AnyCPU addition --- mzLib/mzLib.nuspec | 12 +++--- mzLib/mzLib.sln | 105 --------------------------------------------- 2 files changed, 6 insertions(+), 111 deletions(-) diff --git a/mzLib/mzLib.nuspec b/mzLib/mzLib.nuspec index 7b80e0abc..388ca541e 100644 --- a/mzLib/mzLib.nuspec +++ b/mzLib/mzLib.nuspec @@ -2,7 +2,7 @@ mzLib - 1.0.547 + 1.0.902 mzLib Stef S. Stef S. @@ -16,8 +16,8 @@ - - + + @@ -29,8 +29,8 @@ - - + + @@ -87,4 +87,4 @@ - + \ No newline at end of file diff --git a/mzLib/mzLib.sln b/mzLib/mzLib.sln index ae3b61483..f8b4f8a51 100644 --- a/mzLib/mzLib.sln +++ b/mzLib/mzLib.sln @@ -39,215 +39,110 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Transcriptomics", "Transcri EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Any CPU = Debug|Any CPU Debug|x64 = Debug|x64 - Release|Any CPU = Release|Any CPU Release|x64 = Release|x64 - TestAndRelease|Any CPU = TestAndRelease|Any CPU TestAndRelease|x64 = TestAndRelease|x64 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution - {4658AE10-B660-46DB-B56B-7F4701339FD0}.Debug|Any CPU.ActiveCfg = Debug|x64 - {4658AE10-B660-46DB-B56B-7F4701339FD0}.Debug|Any CPU.Build.0 = Debug|x64 {4658AE10-B660-46DB-B56B-7F4701339FD0}.Debug|x64.ActiveCfg = Debug|x64 {4658AE10-B660-46DB-B56B-7F4701339FD0}.Debug|x64.Build.0 = Debug|x64 - {4658AE10-B660-46DB-B56B-7F4701339FD0}.Release|Any CPU.ActiveCfg = Release|x64 - {4658AE10-B660-46DB-B56B-7F4701339FD0}.Release|Any CPU.Build.0 = Release|x64 {4658AE10-B660-46DB-B56B-7F4701339FD0}.Release|x64.ActiveCfg = Release|x64 {4658AE10-B660-46DB-B56B-7F4701339FD0}.Release|x64.Build.0 = Release|x64 - {4658AE10-B660-46DB-B56B-7F4701339FD0}.TestAndRelease|Any CPU.ActiveCfg = Release|x64 - {4658AE10-B660-46DB-B56B-7F4701339FD0}.TestAndRelease|Any CPU.Build.0 = Release|x64 {4658AE10-B660-46DB-B56B-7F4701339FD0}.TestAndRelease|x64.ActiveCfg = Release|x64 {4658AE10-B660-46DB-B56B-7F4701339FD0}.TestAndRelease|x64.Build.0 = Release|x64 - {3385FB51-AA75-476A-8D5E-7C55F0A2DB10}.Debug|Any CPU.ActiveCfg = Debug|x64 - {3385FB51-AA75-476A-8D5E-7C55F0A2DB10}.Debug|Any CPU.Build.0 = Debug|x64 {3385FB51-AA75-476A-8D5E-7C55F0A2DB10}.Debug|x64.ActiveCfg = Debug|x64 {3385FB51-AA75-476A-8D5E-7C55F0A2DB10}.Debug|x64.Build.0 = Debug|x64 - {3385FB51-AA75-476A-8D5E-7C55F0A2DB10}.Release|Any CPU.ActiveCfg = Release|x64 - {3385FB51-AA75-476A-8D5E-7C55F0A2DB10}.Release|Any CPU.Build.0 = Release|x64 {3385FB51-AA75-476A-8D5E-7C55F0A2DB10}.Release|x64.ActiveCfg = Release|x64 {3385FB51-AA75-476A-8D5E-7C55F0A2DB10}.Release|x64.Build.0 = Release|x64 - {3385FB51-AA75-476A-8D5E-7C55F0A2DB10}.TestAndRelease|Any CPU.ActiveCfg = Release|x64 - {3385FB51-AA75-476A-8D5E-7C55F0A2DB10}.TestAndRelease|Any CPU.Build.0 = Release|x64 {3385FB51-AA75-476A-8D5E-7C55F0A2DB10}.TestAndRelease|x64.ActiveCfg = Release|x64 {3385FB51-AA75-476A-8D5E-7C55F0A2DB10}.TestAndRelease|x64.Build.0 = Release|x64 - {0DE04F7B-EE40-4055-ACF7-472167B70A04}.Debug|Any CPU.ActiveCfg = Debug|x64 - {0DE04F7B-EE40-4055-ACF7-472167B70A04}.Debug|Any CPU.Build.0 = Debug|x64 {0DE04F7B-EE40-4055-ACF7-472167B70A04}.Debug|x64.ActiveCfg = Debug|x64 {0DE04F7B-EE40-4055-ACF7-472167B70A04}.Debug|x64.Build.0 = Debug|x64 - {0DE04F7B-EE40-4055-ACF7-472167B70A04}.Release|Any CPU.ActiveCfg = Release|x64 - {0DE04F7B-EE40-4055-ACF7-472167B70A04}.Release|Any CPU.Build.0 = Release|x64 {0DE04F7B-EE40-4055-ACF7-472167B70A04}.Release|x64.ActiveCfg = Release|x64 {0DE04F7B-EE40-4055-ACF7-472167B70A04}.Release|x64.Build.0 = Release|x64 - {0DE04F7B-EE40-4055-ACF7-472167B70A04}.TestAndRelease|Any CPU.ActiveCfg = Release|x64 - {0DE04F7B-EE40-4055-ACF7-472167B70A04}.TestAndRelease|Any CPU.Build.0 = Release|x64 {0DE04F7B-EE40-4055-ACF7-472167B70A04}.TestAndRelease|x64.ActiveCfg = Release|x64 {0DE04F7B-EE40-4055-ACF7-472167B70A04}.TestAndRelease|x64.Build.0 = Release|x64 - {244A891E-BCDA-432F-8160-26EE0C5F8096}.Debug|Any CPU.ActiveCfg = Debug|x64 - {244A891E-BCDA-432F-8160-26EE0C5F8096}.Debug|Any CPU.Build.0 = Debug|x64 {244A891E-BCDA-432F-8160-26EE0C5F8096}.Debug|x64.ActiveCfg = Debug|x64 {244A891E-BCDA-432F-8160-26EE0C5F8096}.Debug|x64.Build.0 = Debug|x64 - {244A891E-BCDA-432F-8160-26EE0C5F8096}.Release|Any CPU.ActiveCfg = Release|x64 - {244A891E-BCDA-432F-8160-26EE0C5F8096}.Release|Any CPU.Build.0 = Release|x64 {244A891E-BCDA-432F-8160-26EE0C5F8096}.Release|x64.ActiveCfg = Release|x64 {244A891E-BCDA-432F-8160-26EE0C5F8096}.Release|x64.Build.0 = Release|x64 - {244A891E-BCDA-432F-8160-26EE0C5F8096}.TestAndRelease|Any CPU.ActiveCfg = Release|x64 - {244A891E-BCDA-432F-8160-26EE0C5F8096}.TestAndRelease|Any CPU.Build.0 = Release|x64 {244A891E-BCDA-432F-8160-26EE0C5F8096}.TestAndRelease|x64.ActiveCfg = Release|x64 {244A891E-BCDA-432F-8160-26EE0C5F8096}.TestAndRelease|x64.Build.0 = Release|x64 - {D2B8F696-1172-405B-B788-3251B27CC71A}.Debug|Any CPU.ActiveCfg = Debug|x64 - {D2B8F696-1172-405B-B788-3251B27CC71A}.Debug|Any CPU.Build.0 = Debug|x64 {D2B8F696-1172-405B-B788-3251B27CC71A}.Debug|x64.ActiveCfg = Debug|x64 {D2B8F696-1172-405B-B788-3251B27CC71A}.Debug|x64.Build.0 = Debug|x64 - {D2B8F696-1172-405B-B788-3251B27CC71A}.Release|Any CPU.ActiveCfg = Release|x64 - {D2B8F696-1172-405B-B788-3251B27CC71A}.Release|Any CPU.Build.0 = Release|x64 {D2B8F696-1172-405B-B788-3251B27CC71A}.Release|x64.ActiveCfg = Release|x64 {D2B8F696-1172-405B-B788-3251B27CC71A}.Release|x64.Build.0 = Release|x64 - {D2B8F696-1172-405B-B788-3251B27CC71A}.TestAndRelease|Any CPU.ActiveCfg = Release|x64 - {D2B8F696-1172-405B-B788-3251B27CC71A}.TestAndRelease|Any CPU.Build.0 = Release|x64 {D2B8F696-1172-405B-B788-3251B27CC71A}.TestAndRelease|x64.ActiveCfg = Release|x64 {D2B8F696-1172-405B-B788-3251B27CC71A}.TestAndRelease|x64.Build.0 = Release|x64 - {C5EF6CE1-9E90-48D6-A19E-FAE2A9F28E3C}.Debug|Any CPU.ActiveCfg = Debug|x64 - {C5EF6CE1-9E90-48D6-A19E-FAE2A9F28E3C}.Debug|Any CPU.Build.0 = Debug|x64 {C5EF6CE1-9E90-48D6-A19E-FAE2A9F28E3C}.Debug|x64.ActiveCfg = Debug|x64 {C5EF6CE1-9E90-48D6-A19E-FAE2A9F28E3C}.Debug|x64.Build.0 = Debug|x64 - {C5EF6CE1-9E90-48D6-A19E-FAE2A9F28E3C}.Release|Any CPU.ActiveCfg = Release|x64 - {C5EF6CE1-9E90-48D6-A19E-FAE2A9F28E3C}.Release|Any CPU.Build.0 = Release|x64 {C5EF6CE1-9E90-48D6-A19E-FAE2A9F28E3C}.Release|x64.ActiveCfg = Release|x64 {C5EF6CE1-9E90-48D6-A19E-FAE2A9F28E3C}.Release|x64.Build.0 = Release|x64 - {C5EF6CE1-9E90-48D6-A19E-FAE2A9F28E3C}.TestAndRelease|Any CPU.ActiveCfg = Release|x64 - {C5EF6CE1-9E90-48D6-A19E-FAE2A9F28E3C}.TestAndRelease|Any CPU.Build.0 = Release|x64 {C5EF6CE1-9E90-48D6-A19E-FAE2A9F28E3C}.TestAndRelease|x64.ActiveCfg = Release|x64 {C5EF6CE1-9E90-48D6-A19E-FAE2A9F28E3C}.TestAndRelease|x64.Build.0 = Release|x64 - {9697BC5E-1F2C-4E3C-BC53-3532CBDFFCC7}.Debug|Any CPU.ActiveCfg = Debug|x64 - {9697BC5E-1F2C-4E3C-BC53-3532CBDFFCC7}.Debug|Any CPU.Build.0 = Debug|x64 {9697BC5E-1F2C-4E3C-BC53-3532CBDFFCC7}.Debug|x64.ActiveCfg = Debug|x64 {9697BC5E-1F2C-4E3C-BC53-3532CBDFFCC7}.Debug|x64.Build.0 = Debug|x64 - {9697BC5E-1F2C-4E3C-BC53-3532CBDFFCC7}.Release|Any CPU.ActiveCfg = Release|x64 - {9697BC5E-1F2C-4E3C-BC53-3532CBDFFCC7}.Release|Any CPU.Build.0 = Release|x64 {9697BC5E-1F2C-4E3C-BC53-3532CBDFFCC7}.Release|x64.ActiveCfg = Release|x64 {9697BC5E-1F2C-4E3C-BC53-3532CBDFFCC7}.Release|x64.Build.0 = Release|x64 - {9697BC5E-1F2C-4E3C-BC53-3532CBDFFCC7}.TestAndRelease|Any CPU.ActiveCfg = Release|x64 - {9697BC5E-1F2C-4E3C-BC53-3532CBDFFCC7}.TestAndRelease|Any CPU.Build.0 = Release|x64 {9697BC5E-1F2C-4E3C-BC53-3532CBDFFCC7}.TestAndRelease|x64.ActiveCfg = Release|x64 {9697BC5E-1F2C-4E3C-BC53-3532CBDFFCC7}.TestAndRelease|x64.Build.0 = Release|x64 - {AD3D126D-6359-481B-BE17-69DFB0BC4E40}.Debug|Any CPU.ActiveCfg = Debug|x64 - {AD3D126D-6359-481B-BE17-69DFB0BC4E40}.Debug|Any CPU.Build.0 = Debug|x64 {AD3D126D-6359-481B-BE17-69DFB0BC4E40}.Debug|x64.ActiveCfg = Debug|x64 {AD3D126D-6359-481B-BE17-69DFB0BC4E40}.Debug|x64.Build.0 = Debug|x64 - {AD3D126D-6359-481B-BE17-69DFB0BC4E40}.Release|Any CPU.ActiveCfg = Release|x64 - {AD3D126D-6359-481B-BE17-69DFB0BC4E40}.Release|Any CPU.Build.0 = Release|x64 {AD3D126D-6359-481B-BE17-69DFB0BC4E40}.Release|x64.ActiveCfg = Release|x64 {AD3D126D-6359-481B-BE17-69DFB0BC4E40}.Release|x64.Build.0 = Release|x64 - {AD3D126D-6359-481B-BE17-69DFB0BC4E40}.TestAndRelease|Any CPU.ActiveCfg = Release|x64 - {AD3D126D-6359-481B-BE17-69DFB0BC4E40}.TestAndRelease|Any CPU.Build.0 = Release|x64 {AD3D126D-6359-481B-BE17-69DFB0BC4E40}.TestAndRelease|x64.ActiveCfg = Release|x64 {AD3D126D-6359-481B-BE17-69DFB0BC4E40}.TestAndRelease|x64.Build.0 = Release|x64 - {6A510911-5F37-4314-8176-82772B7E5AE3}.Debug|Any CPU.ActiveCfg = Debug|x64 - {6A510911-5F37-4314-8176-82772B7E5AE3}.Debug|Any CPU.Build.0 = Debug|x64 {6A510911-5F37-4314-8176-82772B7E5AE3}.Debug|x64.ActiveCfg = Debug|x64 {6A510911-5F37-4314-8176-82772B7E5AE3}.Debug|x64.Build.0 = Debug|x64 - {6A510911-5F37-4314-8176-82772B7E5AE3}.Release|Any CPU.ActiveCfg = Release|x64 - {6A510911-5F37-4314-8176-82772B7E5AE3}.Release|Any CPU.Build.0 = Release|x64 {6A510911-5F37-4314-8176-82772B7E5AE3}.Release|x64.ActiveCfg = Release|x64 {6A510911-5F37-4314-8176-82772B7E5AE3}.Release|x64.Build.0 = Release|x64 - {6A510911-5F37-4314-8176-82772B7E5AE3}.TestAndRelease|Any CPU.ActiveCfg = Release|x64 - {6A510911-5F37-4314-8176-82772B7E5AE3}.TestAndRelease|Any CPU.Build.0 = Release|x64 {6A510911-5F37-4314-8176-82772B7E5AE3}.TestAndRelease|x64.ActiveCfg = Release|x64 {6A510911-5F37-4314-8176-82772B7E5AE3}.TestAndRelease|x64.Build.0 = Release|x64 - {3DFDFDE6-0355-412B-BD62-2D2AD36C5639}.Debug|Any CPU.ActiveCfg = Debug|x64 - {3DFDFDE6-0355-412B-BD62-2D2AD36C5639}.Debug|Any CPU.Build.0 = Debug|x64 {3DFDFDE6-0355-412B-BD62-2D2AD36C5639}.Debug|x64.ActiveCfg = Debug|x64 {3DFDFDE6-0355-412B-BD62-2D2AD36C5639}.Debug|x64.Build.0 = Debug|x64 - {3DFDFDE6-0355-412B-BD62-2D2AD36C5639}.Release|Any CPU.ActiveCfg = Release|x64 - {3DFDFDE6-0355-412B-BD62-2D2AD36C5639}.Release|Any CPU.Build.0 = Release|x64 {3DFDFDE6-0355-412B-BD62-2D2AD36C5639}.Release|x64.ActiveCfg = Release|x64 {3DFDFDE6-0355-412B-BD62-2D2AD36C5639}.Release|x64.Build.0 = Release|x64 - {3DFDFDE6-0355-412B-BD62-2D2AD36C5639}.TestAndRelease|Any CPU.ActiveCfg = Release|x64 - {3DFDFDE6-0355-412B-BD62-2D2AD36C5639}.TestAndRelease|Any CPU.Build.0 = Release|x64 {3DFDFDE6-0355-412B-BD62-2D2AD36C5639}.TestAndRelease|x64.ActiveCfg = Release|x64 {3DFDFDE6-0355-412B-BD62-2D2AD36C5639}.TestAndRelease|x64.Build.0 = Release|x64 - {78FF34E1-B093-4D10-B77B-5A3AED043DD7}.Debug|Any CPU.ActiveCfg = Debug|x64 - {78FF34E1-B093-4D10-B77B-5A3AED043DD7}.Debug|Any CPU.Build.0 = Debug|x64 {78FF34E1-B093-4D10-B77B-5A3AED043DD7}.Debug|x64.ActiveCfg = Debug|x64 {78FF34E1-B093-4D10-B77B-5A3AED043DD7}.Debug|x64.Build.0 = Debug|x64 - {78FF34E1-B093-4D10-B77B-5A3AED043DD7}.Release|Any CPU.ActiveCfg = Release|x64 - {78FF34E1-B093-4D10-B77B-5A3AED043DD7}.Release|Any CPU.Build.0 = Release|x64 {78FF34E1-B093-4D10-B77B-5A3AED043DD7}.Release|x64.ActiveCfg = Release|x64 {78FF34E1-B093-4D10-B77B-5A3AED043DD7}.Release|x64.Build.0 = Release|x64 - {78FF34E1-B093-4D10-B77B-5A3AED043DD7}.TestAndRelease|Any CPU.ActiveCfg = Release|x64 - {78FF34E1-B093-4D10-B77B-5A3AED043DD7}.TestAndRelease|Any CPU.Build.0 = Release|x64 {78FF34E1-B093-4D10-B77B-5A3AED043DD7}.TestAndRelease|x64.ActiveCfg = Release|x64 {78FF34E1-B093-4D10-B77B-5A3AED043DD7}.TestAndRelease|x64.Build.0 = Release|x64 - {7FA686DC-0269-47D1-9BD4-03D5F1BA3597}.Debug|Any CPU.ActiveCfg = Debug|x64 - {7FA686DC-0269-47D1-9BD4-03D5F1BA3597}.Debug|Any CPU.Build.0 = Debug|x64 {7FA686DC-0269-47D1-9BD4-03D5F1BA3597}.Debug|x64.ActiveCfg = Debug|x64 {7FA686DC-0269-47D1-9BD4-03D5F1BA3597}.Debug|x64.Build.0 = Debug|x64 - {7FA686DC-0269-47D1-9BD4-03D5F1BA3597}.Release|Any CPU.ActiveCfg = Release|x64 - {7FA686DC-0269-47D1-9BD4-03D5F1BA3597}.Release|Any CPU.Build.0 = Release|x64 {7FA686DC-0269-47D1-9BD4-03D5F1BA3597}.Release|x64.ActiveCfg = Release|x64 {7FA686DC-0269-47D1-9BD4-03D5F1BA3597}.Release|x64.Build.0 = Release|x64 - {7FA686DC-0269-47D1-9BD4-03D5F1BA3597}.TestAndRelease|Any CPU.ActiveCfg = Release|x64 - {7FA686DC-0269-47D1-9BD4-03D5F1BA3597}.TestAndRelease|Any CPU.Build.0 = Release|x64 {7FA686DC-0269-47D1-9BD4-03D5F1BA3597}.TestAndRelease|x64.ActiveCfg = Release|x64 {7FA686DC-0269-47D1-9BD4-03D5F1BA3597}.TestAndRelease|x64.Build.0 = Release|x64 - {891888CA-E5CC-4168-B6F2-2B2CED74EA37}.Debug|Any CPU.ActiveCfg = Debug|x64 - {891888CA-E5CC-4168-B6F2-2B2CED74EA37}.Debug|Any CPU.Build.0 = Debug|x64 {891888CA-E5CC-4168-B6F2-2B2CED74EA37}.Debug|x64.ActiveCfg = Debug|x64 {891888CA-E5CC-4168-B6F2-2B2CED74EA37}.Debug|x64.Build.0 = Debug|x64 - {891888CA-E5CC-4168-B6F2-2B2CED74EA37}.Release|Any CPU.ActiveCfg = Release|x64 - {891888CA-E5CC-4168-B6F2-2B2CED74EA37}.Release|Any CPU.Build.0 = Release|x64 {891888CA-E5CC-4168-B6F2-2B2CED74EA37}.Release|x64.ActiveCfg = Release|x64 {891888CA-E5CC-4168-B6F2-2B2CED74EA37}.Release|x64.Build.0 = Release|x64 - {891888CA-E5CC-4168-B6F2-2B2CED74EA37}.TestAndRelease|Any CPU.ActiveCfg = Release|x64 - {891888CA-E5CC-4168-B6F2-2B2CED74EA37}.TestAndRelease|Any CPU.Build.0 = Release|x64 {891888CA-E5CC-4168-B6F2-2B2CED74EA37}.TestAndRelease|x64.ActiveCfg = Release|x64 {891888CA-E5CC-4168-B6F2-2B2CED74EA37}.TestAndRelease|x64.Build.0 = Release|x64 - {04615EBF-20FC-437C-9CF7-47DA6260FAE3}.Debug|Any CPU.ActiveCfg = Debug|x64 - {04615EBF-20FC-437C-9CF7-47DA6260FAE3}.Debug|Any CPU.Build.0 = Debug|x64 {04615EBF-20FC-437C-9CF7-47DA6260FAE3}.Debug|x64.ActiveCfg = Debug|x64 {04615EBF-20FC-437C-9CF7-47DA6260FAE3}.Debug|x64.Build.0 = Debug|x64 - {04615EBF-20FC-437C-9CF7-47DA6260FAE3}.Release|Any CPU.ActiveCfg = Release|x64 - {04615EBF-20FC-437C-9CF7-47DA6260FAE3}.Release|Any CPU.Build.0 = Release|x64 {04615EBF-20FC-437C-9CF7-47DA6260FAE3}.Release|x64.ActiveCfg = Release|x64 - {04615EBF-20FC-437C-9CF7-47DA6260FAE3}.TestAndRelease|Any CPU.ActiveCfg = Release|x64 - {04615EBF-20FC-437C-9CF7-47DA6260FAE3}.TestAndRelease|Any CPU.Build.0 = Release|x64 {04615EBF-20FC-437C-9CF7-47DA6260FAE3}.TestAndRelease|x64.ActiveCfg = Release|x64 {04615EBF-20FC-437C-9CF7-47DA6260FAE3}.TestAndRelease|x64.Build.0 = Release|x64 - {E27A5C14-0C05-466A-91CE-ABB5151A69C4}.Debug|Any CPU.ActiveCfg = Debug|x64 - {E27A5C14-0C05-466A-91CE-ABB5151A69C4}.Debug|Any CPU.Build.0 = Debug|x64 {E27A5C14-0C05-466A-91CE-ABB5151A69C4}.Debug|x64.ActiveCfg = Debug|x64 {E27A5C14-0C05-466A-91CE-ABB5151A69C4}.Debug|x64.Build.0 = Debug|x64 - {E27A5C14-0C05-466A-91CE-ABB5151A69C4}.Release|Any CPU.ActiveCfg = Release|x64 - {E27A5C14-0C05-466A-91CE-ABB5151A69C4}.Release|Any CPU.Build.0 = Release|x64 {E27A5C14-0C05-466A-91CE-ABB5151A69C4}.Release|x64.ActiveCfg = Release|x64 {E27A5C14-0C05-466A-91CE-ABB5151A69C4}.Release|x64.Build.0 = Release|x64 - {E27A5C14-0C05-466A-91CE-ABB5151A69C4}.TestAndRelease|Any CPU.ActiveCfg = Release|x64 - {E27A5C14-0C05-466A-91CE-ABB5151A69C4}.TestAndRelease|Any CPU.Build.0 = Release|x64 {E27A5C14-0C05-466A-91CE-ABB5151A69C4}.TestAndRelease|x64.ActiveCfg = Release|x64 {E27A5C14-0C05-466A-91CE-ABB5151A69C4}.TestAndRelease|x64.Build.0 = Release|x64 - {48CA975B-65DD-4A03-89A3-EA2448293894}.Debug|Any CPU.ActiveCfg = Debug|x64 - {48CA975B-65DD-4A03-89A3-EA2448293894}.Debug|Any CPU.Build.0 = Debug|x64 {48CA975B-65DD-4A03-89A3-EA2448293894}.Debug|x64.ActiveCfg = Debug|x64 {48CA975B-65DD-4A03-89A3-EA2448293894}.Debug|x64.Build.0 = Debug|x64 - {48CA975B-65DD-4A03-89A3-EA2448293894}.Release|Any CPU.ActiveCfg = Release|x64 - {48CA975B-65DD-4A03-89A3-EA2448293894}.Release|Any CPU.Build.0 = Release|x64 {48CA975B-65DD-4A03-89A3-EA2448293894}.Release|x64.ActiveCfg = Release|x64 {48CA975B-65DD-4A03-89A3-EA2448293894}.Release|x64.Build.0 = Release|x64 - {48CA975B-65DD-4A03-89A3-EA2448293894}.TestAndRelease|Any CPU.ActiveCfg = Release|x64 - {48CA975B-65DD-4A03-89A3-EA2448293894}.TestAndRelease|Any CPU.Build.0 = Release|x64 {48CA975B-65DD-4A03-89A3-EA2448293894}.TestAndRelease|x64.ActiveCfg = Release|x64 {48CA975B-65DD-4A03-89A3-EA2448293894}.TestAndRelease|x64.Build.0 = Release|x64 - {4661C249-5B9A-4D9F-B852-15EAF3B4F9A3}.Debug|Any CPU.ActiveCfg = Debug|x64 - {4661C249-5B9A-4D9F-B852-15EAF3B4F9A3}.Debug|Any CPU.Build.0 = Debug|x64 {4661C249-5B9A-4D9F-B852-15EAF3B4F9A3}.Debug|x64.ActiveCfg = Debug|x64 {4661C249-5B9A-4D9F-B852-15EAF3B4F9A3}.Debug|x64.Build.0 = Debug|x64 - {4661C249-5B9A-4D9F-B852-15EAF3B4F9A3}.Release|Any CPU.ActiveCfg = Release|x64 - {4661C249-5B9A-4D9F-B852-15EAF3B4F9A3}.Release|Any CPU.Build.0 = Release|x64 {4661C249-5B9A-4D9F-B852-15EAF3B4F9A3}.Release|x64.ActiveCfg = Release|x64 {4661C249-5B9A-4D9F-B852-15EAF3B4F9A3}.Release|x64.Build.0 = Release|x64 - {4661C249-5B9A-4D9F-B852-15EAF3B4F9A3}.TestAndRelease|Any CPU.ActiveCfg = Release|x64 - {4661C249-5B9A-4D9F-B852-15EAF3B4F9A3}.TestAndRelease|Any CPU.Build.0 = Release|x64 {4661C249-5B9A-4D9F-B852-15EAF3B4F9A3}.TestAndRelease|x64.ActiveCfg = Release|x64 {4661C249-5B9A-4D9F-B852-15EAF3B4F9A3}.TestAndRelease|x64.Build.0 = Release|x64 EndGlobalSection From 0575432f2599665d7c4c3a43afb7bd856cbfe43c Mon Sep 17 00:00:00 2001 From: nbollis Date: Thu, 12 Dec 2024 23:01:35 -0600 Subject: [PATCH 8/8] fixed bugs --- mzLib/Omics/IBioPolymer.cs | 9 ++++ mzLib/Omics/IBioPolymerWithSetMods.cs | 22 ++++++++++ mzLib/Proteomics/Protein/Protein.cs | 16 ++++---- .../PeptideWithSetModifications.cs | 24 +++++------ .../Transcriptomics/TestOligoWithSetMods.cs | 41 ++++++++++++++++--- .../Digestion/OligoWithSetMods.cs | 26 +++++------- mzLib/Transcriptomics/NucleicAcid.cs | 19 +++------ 7 files changed, 102 insertions(+), 55 deletions(-) diff --git a/mzLib/Omics/IBioPolymer.cs b/mzLib/Omics/IBioPolymer.cs index c4dd5b5eb..43ceea17d 100644 --- a/mzLib/Omics/IBioPolymer.cs +++ b/mzLib/Omics/IBioPolymer.cs @@ -29,5 +29,14 @@ public interface IBioPolymer : IEquatable IEnumerable Digest(IDigestionParams digestionParams, List allKnownFixedModifications, List variableModifications, List silacLabels = null, (SilacLabel startLabel, SilacLabel endLabel)? turnoverLabels = null, bool topDownTruncationSearch = false); + + bool IEquatable.Equals(IBioPolymer? other) + { + if (other is null) return false; + if (ReferenceEquals(this, other)) return true; + if (other.GetType() != GetType()) return false; + return Accession == other.Accession + && BaseSequence == other.BaseSequence; + } } } diff --git a/mzLib/Omics/IBioPolymerWithSetMods.cs b/mzLib/Omics/IBioPolymerWithSetMods.cs index 675b32d15..6daa05187 100644 --- a/mzLib/Omics/IBioPolymerWithSetMods.cs +++ b/mzLib/Omics/IBioPolymerWithSetMods.cs @@ -45,6 +45,28 @@ public interface IBioPolymerWithSetMods : IHasChemicalFormula, IEquatable BaseSequence[zeroBasedIndex]; IBioPolymer Parent { get; } + /// + /// Default Equals Method for IBioPolymerWithSetMods + /// + /// + /// + /// + /// Different parent but same sequence and digestion condition => are equal + /// Different Digestion agent but same sequence => are not equal (this is for multi-protease analysis in MetaMorpheus) + /// + bool IEquatable.Equals(IBioPolymerWithSetMods? other) + { + if (other is null) return false; + if (ReferenceEquals(this, other)) return true; + if (other.GetType() != GetType()) return false; + + if (Parent is null && other.Parent is null) + return FullSequence.Equals(other.FullSequence); + + return FullSequence == other.FullSequence + && DigestionParams?.DigestionAgent == other.DigestionParams?.DigestionAgent; + } + public void Fragment(DissociationType dissociationType, FragmentationTerminus fragmentationTerminus, List products); diff --git a/mzLib/Proteomics/Protein/Protein.cs b/mzLib/Proteomics/Protein/Protein.cs index d8cac6a1b..e6e612a47 100644 --- a/mzLib/Proteomics/Protein/Protein.cs +++ b/mzLib/Proteomics/Protein/Protein.cs @@ -12,7 +12,7 @@ namespace Proteomics { - public class Protein : IBioPolymer, IComparable + public class Protein : IBioPolymer, IEquatable, IComparable { private List _proteolysisProducts; @@ -969,16 +969,18 @@ public int CompareTo(Protein other) //not sure if we require any additional fields for equality public override bool Equals(object obj) { - Protein otherProtein = (Protein)obj; - return otherProtein != null && otherProtein.Accession.Equals(Accession) && otherProtein.BaseSequence.Equals(BaseSequence); + if (obj is Protein bioPol) + { + return Equals(bioPol); + } + return false; } - public bool Equals(IBioPolymer other) + public bool Equals(Protein other) { - Protein otherProtein = (Protein)other; - return otherProtein != null && otherProtein.Accession.Equals(Accession) && otherProtein.BaseSequence.Equals(BaseSequence); + return (this as IBioPolymer).Equals(other); } - + /// /// The protein object uses the default hash code method for speed, /// but note that two protein objects with the same information will give two different hash codes. diff --git a/mzLib/Proteomics/ProteolyticDigestion/PeptideWithSetModifications.cs b/mzLib/Proteomics/ProteolyticDigestion/PeptideWithSetModifications.cs index 6fae60596..831705a83 100644 --- a/mzLib/Proteomics/ProteolyticDigestion/PeptideWithSetModifications.cs +++ b/mzLib/Proteomics/ProteolyticDigestion/PeptideWithSetModifications.cs @@ -16,7 +16,7 @@ namespace Proteomics.ProteolyticDigestion { [Serializable] - public class PeptideWithSetModifications : ProteolyticPeptide, IBioPolymerWithSetMods + public class PeptideWithSetModifications : ProteolyticPeptide, IBioPolymerWithSetMods, IEquatable { private static readonly HashSetPool HashSetPool = new(); public string FullSequence { get; private set; } //sequence with modifications @@ -899,18 +899,16 @@ public override string ToString() public override bool Equals(object obj) { - var q = obj as PeptideWithSetModifications; - if (q == null) return false; - return Equals(q); + if (obj is PeptideWithSetModifications peptide) + { + return Equals(peptide); + } + return false; } - public bool Equals(IBioPolymerWithSetMods other) + public bool Equals(PeptideWithSetModifications other) { - return FullSequence == other.FullSequence - && OneBasedStartResidue == other.OneBasedStartResidue - && ((Parent != null && Parent.Equals(other.Parent)) || (Parent == null & other.Parent == null)) - && ((DigestionParams?.DigestionAgent != null && DigestionParams.DigestionAgent.Equals(other.DigestionParams?.DigestionAgent)) - || (DigestionParams?.DigestionAgent == null & other.DigestionParams?.DigestionAgent == null)); + return (this as IBioPolymerWithSetMods).Equals(other); } public override int GetHashCode() @@ -918,11 +916,9 @@ public override int GetHashCode() var hash = new HashCode(); hash.Add(FullSequence); hash.Add(OneBasedStartResidue); - if (Parent != null) + if (Parent?.Accession != null) { - hash.Add(Parent); - if (Parent.Accession != null) - hash.Add(Parent.Accession); + hash.Add(Parent.Accession); } if (DigestionParams?.DigestionAgent != null) { diff --git a/mzLib/Test/Transcriptomics/TestOligoWithSetMods.cs b/mzLib/Test/Transcriptomics/TestOligoWithSetMods.cs index f093d2547..44ab3d701 100644 --- a/mzLib/Test/Transcriptomics/TestOligoWithSetMods.cs +++ b/mzLib/Test/Transcriptomics/TestOligoWithSetMods.cs @@ -96,24 +96,53 @@ public static void TestEquality() } [Test] - [TestCase("GUACUG", "GUACUGGUACUG", "RNase A", 0, 0)] - [TestCase("GUAGGAG", "GUAGCAG", "RNase A", 0, 1)] - public static void TestInequality(string sequence1, string sequence2, string enzyme, int digestedOligo1, int digestedOligo2) + [TestCase("GUACUG", "GUACUGGUACUG", "RNase A")] + [TestCase("GUAGGAG", "GUAGCAG", "RNase A")] + public static void TestEquality_DifferentParentSameDigestionProduct(string sequence1, string sequence2, string enzyme) { var digestionParams = new RnaDigestionParams(rnase: enzyme, minLength: 1, maxMissedCleavages: 0); var oligo1 = new RNA(sequence1) .Digest(digestionParams, [], []) - .ElementAt(digestedOligo1); + .First(); var oligo2 = new RNA(sequence2) .Digest(digestionParams, [], []) - .ElementAt(digestedOligo2); + .First(); + + Assert.That(oligo1, Is.EqualTo(oligo2)); + Assert.That(oligo1, Is.EqualTo((object)oligo2)); + Assert.That(oligo1.GetHashCode(), Is.EqualTo(oligo2.GetHashCode())); + } + + /// + /// The purpose of this test is to ensure that two oligos digested from two different rnases are not equal even if their sequences are equal + /// This is important for multiprotease parsimony in MetaMorpheus + /// + [Test] + [TestCase("AUAGUCUGG", "RNase T1", "colicin_E5")] + [TestCase("AUAGUCUGGGAUCUG", "RNase T1", "colicin_E5")] + public static void TestInequality_SameParentAndDigestionProduct_DifferentRnases(string sequence, string enzyme1, string enzyme2) + { + var digestionParams1 = new RnaDigestionParams(rnase: enzyme1, minLength: 1, maxMissedCleavages: 0); + var digestionParams2 = new RnaDigestionParams(rnase: enzyme2, minLength: 1, maxMissedCleavages: 0); + + var oligo1 = new RNA(sequence) + .Digest(digestionParams1, [], []) + .ToArray(); + + var oligo2 = new RNA(sequence) + .Digest(digestionParams2, [], []) + .ToArray(); + + Assert.That(oligo1.Length, Is.Not.EqualTo(oligo2.Length)); + + Assert.That(oligo1.First().BaseSequence, Is.EqualTo("AUAG")); + Assert.That(oligo2.First().BaseSequence, Is.EqualTo("AUAG")); Assert.That(oligo1, Is.Not.EqualTo(oligo2)); Assert.That(oligo1, Is.Not.EqualTo((object)oligo2)); Assert.That(oligo1.GetHashCode(), Is.Not.EqualTo(oligo2.GetHashCode())); - Assert.That(!oligo1.Equals(digestionParams)); // Test the Equals(Object obj) method } } } diff --git a/mzLib/Transcriptomics/Digestion/OligoWithSetMods.cs b/mzLib/Transcriptomics/Digestion/OligoWithSetMods.cs index 4afbe83c9..6d35d80aa 100644 --- a/mzLib/Transcriptomics/Digestion/OligoWithSetMods.cs +++ b/mzLib/Transcriptomics/Digestion/OligoWithSetMods.cs @@ -20,7 +20,7 @@ namespace Transcriptomics.Digestion /// always available based on the current state of the oligonucleotide and its modifications. Therefor, it is important to set those /// properties to null whenever a termini or modification is changed. /// - public class OligoWithSetMods : NucleolyticOligo, IBioPolymerWithSetMods, INucleicAcid + public class OligoWithSetMods : NucleolyticOligo, IBioPolymerWithSetMods, INucleicAcid, IEquatable { public OligoWithSetMods(NucleicAcid nucleicAcid, RnaDigestionParams digestionParams, int oneBaseStartResidue, int oneBasedEndResidue, int missedCleavages, CleavageSpecificity cleavageSpecificity, @@ -215,20 +215,18 @@ public void Fragment(DissociationType dissociationType, FragmentationTerminus fr products.AddRange(GetNeutralFragments(type, sequence)); } - public override bool Equals(object obj) + public override bool Equals(object? obj) { - var q = obj as OligoWithSetMods; - if (q == null) return false; - return Equals(q); + if (obj is OligoWithSetMods oligo) + { + return Equals(oligo); + } + return false; } - public bool Equals(IBioPolymerWithSetMods other) + public bool Equals(OligoWithSetMods? other) { - return FullSequence == other.FullSequence - && OneBasedStartResidue == other.OneBasedStartResidue - && ((Parent != null && Parent.Equals(other.Parent)) || (Parent == null & other.Parent == null)) - && ((DigestionParams?.DigestionAgent != null && DigestionParams.DigestionAgent.Equals(other.DigestionParams?.DigestionAgent)) - || (DigestionParams?.DigestionAgent == null & other.DigestionParams?.DigestionAgent == null)); + return (this as IBioPolymerWithSetMods).Equals(other); } public override int GetHashCode() @@ -236,11 +234,9 @@ public override int GetHashCode() var hash = new HashCode(); hash.Add(FullSequence); hash.Add(OneBasedStartResidue); - if (Parent != null) + if (Parent?.Accession != null) { - hash.Add(Parent); - if (Parent.Accession != null) - hash.Add(Parent.Accession); + hash.Add(Parent.Accession); } if (DigestionParams?.DigestionAgent != null) { diff --git a/mzLib/Transcriptomics/NucleicAcid.cs b/mzLib/Transcriptomics/NucleicAcid.cs index 7e8821c74..f9951590c 100644 --- a/mzLib/Transcriptomics/NucleicAcid.cs +++ b/mzLib/Transcriptomics/NucleicAcid.cs @@ -324,25 +324,18 @@ private void ParseSequenceString(string sequence) public bool Equals(NucleicAcid? other) { - if (ReferenceEquals(null, other)) return false; - if (ReferenceEquals(this, other)) return true; - return _sequence == other._sequence + return (this as IBioPolymer).Equals(other) && _5PrimeTerminus.Equals(other._5PrimeTerminus) && _3PrimeTerminus.Equals(other._3PrimeTerminus); } public override bool Equals(object? obj) { - if (ReferenceEquals(null, obj)) return false; - if (ReferenceEquals(this, obj)) return true; - if (obj.GetType() != this.GetType()) return false; - return Equals((NucleicAcid)obj); - } - - public bool Equals(IBioPolymer other) - { - var castedOther = other as NucleicAcid; - return(Equals(castedOther)); + if (obj is NucleicAcid oligo) + { + return Equals(oligo); + } + return false; } public override int GetHashCode()