Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

IsoDec Deconvolution Algorithm #791

Open
wants to merge 45 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
45 commits
Select commit Hold shift + click to select a range
3d7ebd1
Added in foundation for John to use
nbollis Aug 2, 2024
ddd03b5
removed charge from johnny decon parameters
nbollis Aug 2, 2024
6720fc5
instantiated johhnydeconparams.decontype
nbollis Aug 2, 2024
73df199
Merge branch 'master' into JohnnyDeconv
trishorts Aug 2, 2024
50b8d9d
Merge branch 'master' into JohnnyDeconv
trishorts Aug 5, 2024
b626f41
IsoDec incorporated!
jgpavek Aug 5, 2024
7c5132e
Merge branch 'JohnnyDeconv' of https://github.com/nbollis/mzLib into …
jgpavek Aug 5, 2024
fc0f4bb
Did a little cleanup and made IsoDec run on my device
nbollis Aug 5, 2024
097b4bd
Changed isodec to use the embedded dlls and resources
nbollis Aug 5, 2024
ba54e46
changed around assembly references and added IsoDec to Deconvolution …
nbollis Aug 5, 2024
678dbc3
added test for negative mode
nbollis Aug 5, 2024
64d4a4b
updated nuspec to pack isodec resources
nbollis Aug 5, 2024
6ef4447
Updated dll. Now just making monoisotopic errors but getting generall…
jgpavek Aug 6, 2024
1a0bd54
Corrected some IsoDec issues. Not passing tests yet, but getting corr…
jgpavek Aug 6, 2024
963826b
IsoDec passes (updated) tests.
jgpavek Oct 4, 2024
bc1b6a9
began neutral mz spectrum
nbollis Oct 11, 2024
a8bba37
Refactor visibility and clean up deconvolution code
Oct 11, 2024
455f3c0
Finish NeutralMassSpectrum
Oct 11, 2024
0dd9e52
Refactor Deconvoluter and rename NeutralMzSpectrum
Oct 11, 2024
09cefc7
added neutral mass file bool
Oct 11, 2024
72d8202
Adjsuted and tested neutral mass spectra
nbollis Oct 11, 2024
4277814
Refactor Deconvoluter and add new tests
nbollis Oct 12, 2024
6c124c5
Make FirstX and LastX properties virtual; update tests
nbollis Oct 12, 2024
f049ee4
fixed nuspec
nbollis Oct 12, 2024
3c560ee
IsoDecDeconvolutionParameters and Multiple Monoisos
jgpavek Oct 28, 2024
93e4161
Refactor IsoDec classes and enhance parameters
nbollis Oct 28, 2024
b97a23d
Merged in NeutralMassSpectrum and reconciled errors
nbollis Oct 29, 2024
492f7e0
Bug Fixes and parameter cleanup
jgpavek Oct 30, 2024
fc32cd2
Fixed broken unit test and assertion structure in test deconvolution
nbollis Oct 30, 2024
2e4a772
Cleaned up isotopic Envelope
nbollis Oct 31, 2024
8ff5883
Refactor IsoDec classes and update parameters
nbollis Oct 31, 2024
302a07a
help me
nbollis Oct 31, 2024
e45fb3f
Changed resources from content to none
nbollis Nov 2, 2024
cf8b6a3
nuspec edit
nbollis Nov 14, 2024
9aa30a8
Refactor Deconvolute method and update variable handling
nbollis Nov 15, 2024
7cd2639
Fixed memory allocation/deallocation issues
jgpavek Nov 18, 2024
3db9ab4
simple restructure of parameter handling
nbollis Nov 18, 2024
788aa81
merged John and Nic Changes
nbollis Nov 18, 2024
4bacc61
Update namespaces, references, and version number
nbollis Nov 18, 2024
60d7e4e
idk man
nbollis Nov 19, 2024
98a609f
look mom, I did it
nbollis Nov 21, 2024
db27284
merged in master
nbollis Jan 7, 2025
13bda3d
Adjusted in response to merging in master
nbollis Jan 7, 2025
cf79e04
revised from PR and added tests for GetPeakIndicesWithinTolerance.
nbollis Jan 8, 2025
b3ed84d
Removed unnecessary changes
nbollis Jan 8, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ public class SinglePeakDeconvolutionTestCase
public SinglePeakDeconvolutionTestCase(DeconvolutionParameters deconParameters, string sampleInformation, string spectrumPath, int scanNumber,
double expectedMostAbundantObservedIsotopicMass, int expectedIonChargeState, double selectedIonMz, double precursorPpmMassTolerance)
{

DeconvolutionParameters = deconParameters;
SampleInformation = sampleInformation;
ExpectedMostAbundantObservedIsotopicMass = expectedMostAbundantObservedIsotopicMass;
ExpectedIonChargeState = expectedIonChargeState;
Expand Down
6 changes: 3 additions & 3 deletions mzLib/Development/Development.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,13 @@
</ItemGroup>

<ItemGroup>
<None Update="Deconvolution\TestData\Averaged_221110_CytoOnly.mzML">
<None Update="DeconvolutionDevelopment\TestData\Averaged_221110_CytoOnly.mzML">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="Deconvolution\TestData\Averaged_221110_HGHOnly.mzML">
<None Update="DeconvolutionDevelopment\TestData\Averaged_221110_HGHOnly.mzML">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="Deconvolution\TestData\Averaged_221110_UbiqOnly.mzML">
<None Update="DeconvolutionDevelopment\TestData\Averaged_221110_UbiqOnly.mzML">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Chemistry;
using MzLibUtil;

Expand Down
130 changes: 130 additions & 0 deletions mzLib/MassSpectrometry/Deconvolution/Algorithms/IsoDecAlgorithm.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using MzLibUtil;

namespace MassSpectrometry
{
internal class IsoDecAlgorithm : DeconvolutionAlgorithm
{

internal IsoDecAlgorithm(DeconvolutionParameters deconParameters) : base(deconParameters)
{

}

[StructLayout(LayoutKind.Sequential, Pack =1)]
public struct MatchedPeak
{
public float mz;
nbollis marked this conversation as resolved.
Show resolved Hide resolved
public int z;
public float monoiso;
public float peakmass;
public float avgmass;
public float area;
public float peakint;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 64)]
public float[] matchedindsiso;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 64)]
public float[] matchedindsexp;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 64)]
public float[] isomz;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 64)]
public float[] isodist;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 64)]
public float[] isomass;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)]
public float[] monoisos;
int startindex;
int endindex;
public float score;
public int realisolength;
}

[DllImport("isodeclib.dll", EntryPoint = "process_spectrum", CallingConvention = CallingConvention.Cdecl)]
protected static extern int process_spectrum(double[] cmz, float[] cintensity, int c, string fname, IntPtr matchedpeaks, IsoDecDeconvolutionParameters.IsoSettings settings);

internal override IEnumerable<IsotopicEnvelope> Deconvolute(MzSpectrum spectrum, MzRange range)
{
var deconParams = DeconvolutionParameters as IsoDecDeconvolutionParameters ?? throw new MzLibException("Deconvolution params and algorithm do not match");

var firstIndex = spectrum.GetClosestPeakIndex(range.Minimum);
var lastIndex = spectrum.GetClosestPeakIndex(range.Maximum);

var mzs = spectrum.XArray[firstIndex..lastIndex]
.Select(p => p)
.ToArray();
var intensities = spectrum.YArray[firstIndex..lastIndex]
.Select(p => (float)p)
.ToArray();

var mpArray = new byte[intensities.Length * Marshal.SizeOf(typeof(MatchedPeak))];
GCHandle handle = GCHandle.Alloc(mpArray, GCHandleType.Pinned);
try
{
IntPtr matchedPeaksPtr = (IntPtr)handle.AddrOfPinnedObject();
IsoDecDeconvolutionParameters.IsoSettings settings = deconParams.ToIsoSettings();
int result = process_spectrum(mzs, intensities, intensities.Length, null, matchedPeaksPtr, settings);
if (result <= 0)
return Enumerable.Empty<IsotopicEnvelope>();

Check warning on line 70 in mzLib/MassSpectrometry/Deconvolution/Algorithms/IsoDecAlgorithm.cs

View check run for this annotation

Codecov / codecov/patch

mzLib/MassSpectrometry/Deconvolution/Algorithms/IsoDecAlgorithm.cs#L70

Added line #L70 was not covered by tests

// Handle results
MatchedPeak[] matchedpeaks = new MatchedPeak[result];
for (int i = 0; i < result; i++)
{
matchedpeaks[i] = Marshal.PtrToStructure<MatchedPeak>(matchedPeaksPtr + i * Marshal.SizeOf(typeof(MatchedPeak)));
}

return ConvertToIsotopicEnvelopes(deconParams, matchedpeaks, spectrum);
}
finally
{
handle.Free();
}
}

private List<IsotopicEnvelope> ConvertToIsotopicEnvelopes(IsoDecDeconvolutionParameters parameters, MatchedPeak[] matchedpeaks, MzSpectrum spectrum)
{
List<IsotopicEnvelope> result = new List<IsotopicEnvelope>();
int currentId = 0;
var tolerance = new PpmTolerance(5);
foreach(MatchedPeak peak in matchedpeaks)
{
List<(double,double)> peaks = new List<(double,double)> ();
for (int i = 0; i < peak.realisolength; i++)
{

List<int> indicesWithinTolerance = spectrum.GetPeakIndicesWithinTolerance(peak.isomz[i], tolerance);
double maxIntensity = 0;
int maxIndex = -1;
foreach (int index in indicesWithinTolerance)
{
if (spectrum.YArray[index] > maxIntensity) { maxIntensity = spectrum.YArray[index]; maxIndex = index; }
}
if (maxIndex >= 0)
{
peaks.Add((spectrum.XArray[maxIndex], spectrum.YArray[maxIndex]));
}
else
{
peaks.Add((peak.isomz[i], 0));
}

}
int charge = peak.z;
if(parameters.Polarity == Polarity.Negative) { charge = -peak.z; }
if(parameters.ReportMulitpleMonoisos)
{
foreach (float monoiso in peak.monoisos)
{
if (monoiso > 0) { result.Add(new IsotopicEnvelope(currentId, peaks, (double)monoiso, charge, peak.peakint, peak.score)); }
}
}
else { result.Add(new IsotopicEnvelope(currentId, peaks, (double)peak.monoiso, charge, peak.peakint, peak.score)); }

Check warning on line 124 in mzLib/MassSpectrometry/Deconvolution/Algorithms/IsoDecAlgorithm.cs

View check run for this annotation

Codecov / codecov/patch

mzLib/MassSpectrometry/Deconvolution/Algorithms/IsoDecAlgorithm.cs#L124

Added line #L124 was not covered by tests
currentId++;
}
return result;
}
}
}
72 changes: 40 additions & 32 deletions mzLib/MassSpectrometry/Deconvolution/Deconvoluter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,6 @@

namespace MassSpectrometry
{
public enum DeconvolutionType
{
ClassicDeconvolution,
ExampleNewDeconvolutionTemplate,
}

/// <summary>
/// Context class for all deconvolution
/// </summary>
Expand All @@ -26,9 +20,7 @@ public static IEnumerable<IsotopicEnvelope> Deconvolute(MsDataScan scan,
DeconvolutionParameters deconvolutionParameters, MzRange rangeToGetPeaksFrom = null)
{
// set any specific deconvolution parameters found only in the MsDataScan

foreach (var isotopicEnvelope in Deconvolute(scan.MassSpectrum, deconvolutionParameters, rangeToGetPeaksFrom))
yield return isotopicEnvelope;
return Deconvolute(scan.MassSpectrum, deconvolutionParameters, rangeToGetPeaksFrom);
}

/// <summary>
Expand All @@ -43,37 +35,53 @@ public static IEnumerable<IsotopicEnvelope> Deconvolute(MzSpectrum spectrum,
{
rangeToGetPeaksFrom ??= spectrum.Range;

// Short circuit deconvolution if it is called on a neutral mass spectrum
if (spectrum is NeutralMassSpectrum newt)
return DeconvoluteNeutralMassSpectrum(newt, rangeToGetPeaksFrom);

// set deconvolution algorithm
DeconvolutionAlgorithm deconAlgorithm;
switch (deconvolutionParameters.DeconvolutionType)
{
case DeconvolutionType.ClassicDeconvolution:
deconAlgorithm = new ClassicDeconvolutionAlgorithm(deconvolutionParameters);
break;
DeconvolutionAlgorithm deconAlgorithm = CreateAlgorithm(deconvolutionParameters);

case DeconvolutionType.ExampleNewDeconvolutionTemplate:
deconAlgorithm = new ExampleNewDeconvolutionAlgorithmTemplate(deconvolutionParameters);
break;
// Delegate deconvolution to the algorithm
return deconAlgorithm.Deconvolute(spectrum, rangeToGetPeaksFrom);
}

default: throw new MzLibException("DeconvolutionType not yet supported");
}
/// <summary>
/// Factory method to create the correct deconvolution algorithm from the parameters
/// </summary>
/// <param name="parameters"></param>
/// <returns></returns>
/// <exception cref="MzLibException"></exception>
private static DeconvolutionAlgorithm CreateAlgorithm(DeconvolutionParameters parameters)
{
return parameters.DeconvolutionType switch
{
DeconvolutionType.ClassicDeconvolution => new ClassicDeconvolutionAlgorithm(parameters),
DeconvolutionType.ExampleNewDeconvolutionTemplate => new ExampleNewDeconvolutionAlgorithmTemplate(parameters),
DeconvolutionType.IsoDecDeconvolution => new IsoDecAlgorithm(parameters),
_ => throw new MzLibException("DeconvolutionType not yet supported")
};
}

// Short circuit deconvolution if it is called on a neutral mass spectrum
if (spectrum is NeutralMassSpectrum newt)
/// <summary>
/// Returns all peaks in the neutral mass spectrum as an isotopic envelope with a single peak
/// </summary>
/// <param name="neutralSpectrum"></param>
/// <param name="range"></param>
/// <returns></returns>
private static IEnumerable<IsotopicEnvelope> DeconvoluteNeutralMassSpectrum(NeutralMassSpectrum neutralSpectrum, MzRange range)
{
for (int i = 0; i < neutralSpectrum.XArray.Length; i++)
{
for (int i = 0; i < newt.XArray.Length; i++)
double neutralMass = neutralSpectrum.XArray[i];
double intensity = neutralSpectrum.YArray[i];
int chargeState = neutralSpectrum.Charges[i];

if (range.Contains(neutralMass.ToMz(chargeState)))
{
// skip this peak if it's outside the range of interest (e.g. if we're only interested in deconvoluting a small m/z range)
if (!rangeToGetPeaksFrom.Contains(newt.XArray[i].ToMz(newt.Charges[i])))
continue;
yield return new IsotopicEnvelope(newt.XArray[i], newt.YArray[i], newt.Charges[i]);
yield return new IsotopicEnvelope(neutralMass, intensity, chargeState);
}
}
else
{
foreach (var isotopicEnvelope in deconAlgorithm.Deconvolute(spectrum, rangeToGetPeaksFrom))
yield return isotopicEnvelope;
}
}
}
}
15 changes: 15 additions & 0 deletions mzLib/MassSpectrometry/Deconvolution/DeconvolutionType.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace MassSpectrometry
{
public enum DeconvolutionType
{
ClassicDeconvolution,
ExampleNewDeconvolutionTemplate,
IsoDecDeconvolution,
}
}
Loading
Loading