From 4fe1016cd8bc328cc76b90cde417288a85587cad Mon Sep 17 00:00:00 2001 From: Michael Shortreed Date: Tue, 2 Jan 2024 13:10:06 -0600 Subject: [PATCH] peak merge and sorted array merge --- mzLib/MassSpectrometry/ExtensionMethods.cs | 88 +++++++++++++++++++ .../MassSpectrometry/MzSpectra/MzSpectrum.cs | 64 +++----------- mzLib/Test/TestMzSpectrum.cs | 18 ++-- 3 files changed, 112 insertions(+), 58 deletions(-) create mode 100644 mzLib/MassSpectrometry/ExtensionMethods.cs diff --git a/mzLib/MassSpectrometry/ExtensionMethods.cs b/mzLib/MassSpectrometry/ExtensionMethods.cs new file mode 100644 index 000000000..44fa7c623 --- /dev/null +++ b/mzLib/MassSpectrometry/ExtensionMethods.cs @@ -0,0 +1,88 @@ +using System.Collections.Generic; +using System.Linq; +using MzLibUtil; + +namespace MassSpectrometry +{ + public class ExtensionMethods + { + public static void MergeMzAndIntensityValuesForAnyMzsWithinTolerance(ref double[] mzArray, ref double[] intensityArray, PpmTolerance ppmTolerance) + { + List newMzArray = new List(); + List newIntensityArray = new List(); + + List indiciesToMerge = new List(); + for (int i = 0; i < mzArray.Length; i++) + { + if (i < (mzArray.Length - 1) && ppmTolerance.Within(mzArray[i], mzArray[i + 1])) // two mzValues are close enough to merge + { + indiciesToMerge.Add(i); + indiciesToMerge.Add(i + 1); + } + else // mzValues are NOT close enough to merge so we merge any that we've collected so far. + { + if (indiciesToMerge.Any()) + { + newMzArray.Add(GetWeightedMz(indiciesToMerge.DistinctBy(i => i).ToList(), mzArray.ToList(), intensityArray.ToList())); + newIntensityArray.Add(GetIntensityAverage(indiciesToMerge, mzArray, intensityArray)); + indiciesToMerge.Clear(); //we clear this array because we have merged a contiguous group and can begin again with the next group + } + else + { + newMzArray.Add(mzArray[i]); + newIntensityArray.Add(intensityArray[i]); + } + } + } + + mzArray = newMzArray.ToArray(); + intensityArray = newIntensityArray.ToArray(); + } + private static double GetIntensityAverage(List indiciesToMerge, double[] mzArray, double[] intensityArray) + { + double intensitySum = 0; + foreach (var index in indiciesToMerge) + { + intensitySum += intensityArray[index]; + } + return (intensitySum / (double)indiciesToMerge.Count); + } + + private static double GetWeightedMz(List indiciesToMerge, List mzArray, List intensityArray) + { + double weightedMz = 0; + double intensitySum = 0; + foreach (var index in indiciesToMerge) + { + weightedMz += mzArray[index] * intensityArray[index]; + intensitySum += intensityArray[index]; + } + return (weightedMz / intensitySum); + } + + public static double[] MergeTwoSortedArraysIntoSortedArray(double[] sortedArrayOne, double[] sortedArrayTwo) + { + double[] mergedSortedArray = new double[sortedArrayOne.Length + sortedArrayTwo.Length]; + int oneIndex = 0; + int twoIndex = 0; + + for (int i = 0; i < mergedSortedArray.Length; i++) + { + if (oneIndex mzArray, List intensityArray, PpmTolerance ppmTolerance) - { - List newMzArray = new List(); - List newIntensityArray = new List(); - - List indiciesToMerge = new List(); - for (int i = 0; i < mzArray.Count; i++) - { - if (i < (mzArray.Count - 1) && ppmTolerance.Within(mzArray[i], mzArray[i+1])) // two mzValues are close enough to merge - { - indiciesToMerge.Add(i); - indiciesToMerge.Add(i+1); - } - else // mzValues are NOT close enough to merge so we merge any that we've collected so far. - { - if (indiciesToMerge.Any()) - { - newMzArray.Add(GetWeightedMz(indiciesToMerge.DistinctBy(i=>i).ToList(),mzArray,intensityArray)); - newIntensityArray.Add(GetIntensityAverage(indiciesToMerge, mzArray, intensityArray)); - indiciesToMerge.Clear(); //we clear this array because we have merged a contiguous group and can begin again with the next group - } - else - { - newMzArray.Add(mzArray[i]); - newIntensityArray.Add(intensityArray[i]); - } - } - } - return (newMzArray.ToArray(), newIntensityArray.ToArray()); - } - - private double GetIntensityAverage(List indiciesToMerge, List mzArray, List intensityArray) + /// + /// Method takes a list of mz and intensity values from a spectrum and merges those pairs of mzs and intensities when the difference in the mzs is less than specified tolerance + /// + /// + /// + /// + /// + public void MergeMzAndIntensityValuesForAnyMzsWithinTolerance(PpmTolerance ppmTolerance) { - double intensitySum = 0; - foreach (var index in indiciesToMerge) - { - intensitySum += intensityArray[index]; - } - return (intensitySum / (double)indiciesToMerge.Count); + var mzArray = this.XArray; + var intensityArray= this.YArray; + ExtensionMethods.MergeMzAndIntensityValuesForAnyMzsWithinTolerance(ref mzArray, ref intensityArray, ppmTolerance); + this.XArray = mzArray; + this.YArray = intensityArray; } - private double GetWeightedMz(List indiciesToMerge, List mzArray, List intensityArray) - { - double weightedMz = 0; - double intensitySum = 0; - foreach (var index in indiciesToMerge) - { - weightedMz += mzArray[index] * intensityArray[index]; - intensitySum += intensityArray[index]; - } - return (weightedMz / intensitySum); - } } } \ No newline at end of file diff --git a/mzLib/Test/TestMzSpectrum.cs b/mzLib/Test/TestMzSpectrum.cs index 57094f7ab..5aef3d03e 100644 --- a/mzLib/Test/TestMzSpectrum.cs +++ b/mzLib/Test/TestMzSpectrum.cs @@ -1,11 +1,7 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using MassSpectrometry; +using MassSpectrometry; using MzLibUtil; using NUnit.Framework; +using TopDownProteomics.IO.MzIdentMl; namespace Test { @@ -22,8 +18,14 @@ public void Bubba() bool shouldCopy = false; MzSpectrum s = new MzSpectrum(mzs,intensities,shouldCopy); - (mzs,intensities) = s.Yoyo(mzs.ToList(), intensities.ToList(), new PpmTolerance(100)); - Assert.IsTrue(false); + s.MergeMzAndIntensityValuesForAnyMzsWithinTolerance(new PpmTolerance(0.01)); + } + + [Test] + public void Bubba2() + { + var j = ExtensionMethods.MergeTwoSortedArraysIntoSortedArray(new double[] { 2, 4, 6, }, new double[] { 1, 3, 5, 7, 8, 9, 10, 11, 12 }); + CollectionAssert.AreEquivalent(new double[]{ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 }, j); } } }