Skip to content

Commit

Permalink
Merge branch 'master' into GetModificationMethod
Browse files Browse the repository at this point in the history
  • Loading branch information
trishorts authored Oct 30, 2024
2 parents da7ee7d + 7dcf9a9 commit 40f90df
Show file tree
Hide file tree
Showing 12 changed files with 420 additions and 100 deletions.
Original file line number Diff line number Diff line change
@@ -1,20 +1,17 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Chemistry;
using Easy.Common.Extensions;
using MathNet.Numerics.Statistics;
using MzLibUtil;

namespace MassSpectrometry
{
public class ClassicDeconvolutionAlgorithm : DeconvolutionAlgorithm
internal class ClassicDeconvolutionAlgorithm : DeconvolutionAlgorithm
{
private MzSpectrum spectrum;

public ClassicDeconvolutionAlgorithm(DeconvolutionParameters deconParameters) : base(deconParameters)
internal ClassicDeconvolutionAlgorithm(DeconvolutionParameters deconParameters) : base(deconParameters)
{

}
Expand All @@ -25,7 +22,7 @@ public ClassicDeconvolutionAlgorithm(DeconvolutionParameters deconParameters) :
/// <param name="spectrumToDeconvolute">spectrum to deconvolute</param>
/// <param name="range">Range of peaks to deconvolute</param>
/// <returns></returns>
public override IEnumerable<IsotopicEnvelope> Deconvolute(MzSpectrum spectrumToDeconvolute, MzRange range)
internal override IEnumerable<IsotopicEnvelope> Deconvolute(MzSpectrum spectrumToDeconvolute, MzRange range)
{
var deconParams = DeconvolutionParameters as ClassicDeconvolutionParameters ?? throw new MzLibException("Deconvolution params and algorithm do not match");
spectrum = spectrumToDeconvolute;
Expand Down Expand Up @@ -205,7 +202,7 @@ private IsotopicEnvelope FindIsotopicEnvelope(int massIndex, double candidateFor
}
}

return new IsotopicEnvelope(listOfObservedPeaks, monoisotopicMass, chargeState, totalIntensity, Statistics.StandardDeviation(listOfRatios), massIndex);
return new IsotopicEnvelope(listOfObservedPeaks, monoisotopicMass, chargeState, totalIntensity, listOfRatios.StandardDeviation());
}

private int ObserveAdjacentChargeStates(IsotopicEnvelope originalEnvelope, double mostIntensePeakMz, int massIndex, double deconvolutionTolerancePpm, double intensityRatioLimit, double minChargeToLookFor, double maxChargeToLookFor, List<double> monoisotopicMassPredictions)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@

namespace MassSpectrometry
{
/// <summary>
/// Parent class defining minimum requirement to be used <see cref="Deconvoluter"/>
/// </summary>
public abstract class DeconvolutionAlgorithm
{
// For ClassicDeconv. If not used elsewhere, move to that class
Expand Down Expand Up @@ -79,6 +82,6 @@ protected DeconvolutionAlgorithm(DeconvolutionParameters deconParameters)
/// <param name="spectrum">spectrum to be deconvoluted</param>
/// <param name="range">Range of peaks to deconvolute</param>
/// <returns></returns>
public abstract IEnumerable<IsotopicEnvelope> Deconvolute(MzSpectrum spectrum, MzRange range);
internal abstract IEnumerable<IsotopicEnvelope> Deconvolute(MzSpectrum spectrum, MzRange range);
}
}
Original file line number Diff line number Diff line change
@@ -1,22 +1,19 @@
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using MzLibUtil;

namespace MassSpectrometry
{
[ExcludeFromCodeCoverage]
public class ExampleNewDeconvolutionAlgorithmTemplate : DeconvolutionAlgorithm
internal class ExampleNewDeconvolutionAlgorithmTemplate : DeconvolutionAlgorithm
{
public ExampleNewDeconvolutionAlgorithmTemplate(DeconvolutionParameters deconParameters) : base(deconParameters)
internal ExampleNewDeconvolutionAlgorithmTemplate(DeconvolutionParameters deconParameters) : base(deconParameters)
{

}

public override IEnumerable<IsotopicEnvelope> Deconvolute(MzSpectrum spectrum, MzRange range = null)
internal override IEnumerable<IsotopicEnvelope> Deconvolute(MzSpectrum spectrum, MzRange range = null)
{
var deconParams = DeconvolutionParameters as ExampleNewDeconvolutionParametersTemplate ?? throw new MzLibException("Deconvolution params and algorithm do not match");
range ??= spectrum.Range;
Expand Down
48 changes: 21 additions & 27 deletions mzLib/MassSpectrometry/Deconvolution/Deconvoluter.cs
Original file line number Diff line number Diff line change
@@ -1,10 +1,5 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Easy.Common.Extensions;
using Easy.Common.Interfaces;
using System.Collections.Generic;
using Chemistry;
using MzLibUtil;

namespace MassSpectrometry
Expand All @@ -30,27 +25,11 @@ public static class Deconvoluter
public static IEnumerable<IsotopicEnvelope> Deconvolute(MsDataScan scan,
DeconvolutionParameters deconvolutionParameters, MzRange rangeToGetPeaksFrom = null)
{
rangeToGetPeaksFrom ??= scan.MassSpectrum.Range;
// set any specific deconvolution parameters found only in the MsDataScan

// set deconvolution algorithm and any specific deconvolution parameters found in the MsDataScan
DeconvolutionAlgorithm deconAlgorithm;
switch (deconvolutionParameters.DeconvolutionType)
{
case DeconvolutionType.ClassicDeconvolution:
deconAlgorithm = new ClassicDeconvolutionAlgorithm(deconvolutionParameters);
break;

case DeconvolutionType.ExampleNewDeconvolutionTemplate:
deconAlgorithm = new ExampleNewDeconvolutionAlgorithmTemplate(deconvolutionParameters);
break;

default: throw new MzLibException("DeconvolutionType not yet supported");
}

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



/// <summary>
/// Static deconvolution of an MzSpectrum that does not require Deconvoluter construction
Expand Down Expand Up @@ -79,7 +58,22 @@ public static IEnumerable<IsotopicEnvelope> Deconvolute(MzSpectrum spectrum,
default: throw new MzLibException("DeconvolutionType not yet supported");
}

return deconAlgorithm.Deconvolute(spectrum, rangeToGetPeaksFrom);
// Short circuit deconvolution if it is called on a neutral mass spectrum
if (spectrum is NeutralMassSpectrum newt)
{
for (int i = 0; i < newt.XArray.Length; i++)
{
// 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]);
}
}
else
{
foreach (var isotopicEnvelope in deconAlgorithm.Deconvolute(spectrum, rangeToGetPeaksFrom))
yield return isotopicEnvelope;
}
}
}
}
4 changes: 4 additions & 0 deletions mzLib/MassSpectrometry/MassSpectrometry.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,8 @@
<ProjectReference Include="..\MzLibUtil\MzLibUtil.csproj" />
</ItemGroup>

<ItemGroup>
<InternalsVisibleTo Include="Development" />
<InternalsVisibleTo Include="Test" />
</ItemGroup>
</Project>
3 changes: 0 additions & 3 deletions mzLib/MassSpectrometry/MsDataFile.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,6 @@

namespace MassSpectrometry
{
// TODO: Define scope of class
// Class scope is to provide to the data loaded from the DataFile.

/// <summary>
/// A class for interacting with data collected from a Mass Spectrometer, and stored in a file
/// </summary>
Expand Down
32 changes: 19 additions & 13 deletions mzLib/MassSpectrometry/MzSpectra/IsotopicEnvelope.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,40 +14,47 @@ public class IsotopicEnvelope : IHasMass
/// <summary>
/// Mass of most abundant observed isotopic peak, not accounting for addition or subtraction or protons due to ESI charge state induction
/// </summary>
public double MostAbundantObservedIsotopicMass { get; private set; }
internal double MostAbundantObservedIsotopicMass { get; private set; }
public readonly int Charge;
public readonly double TotalIntensity;
public readonly double StDev;
public readonly int MassIndex;

public double Score { get; private set; }

public IsotopicEnvelope(List<(double mz, double intensity)> bestListOfPeaks, double bestMonoisotopicMass, int bestChargeState, double bestTotalIntensity, double bestStDev, int bestMassIndex)
/// <summary>
/// Used for an isotopic envelope that mzLib deconvoluted (e.g., from a mass spectrum)
/// </summary>
public IsotopicEnvelope(List<(double mz, double intensity)> bestListOfPeaks, double bestMonoisotopicMass, int bestChargeState, double bestTotalIntensity, double bestStDev)
{
Peaks = bestListOfPeaks;
MonoisotopicMass = bestMonoisotopicMass;
MostAbundantObservedIsotopicMass = GetMostAbundantObservedIsotopicMass(bestListOfPeaks, bestChargeState);
MostAbundantObservedIsotopicMass = bestListOfPeaks.MaxBy(p => p.intensity).mz * Math.Abs(bestChargeState);
Charge = bestChargeState;
TotalIntensity = bestTotalIntensity;
StDev = bestStDev;
MassIndex = bestMassIndex;
Score = ScoreIsotopeEnvelope();
Score = ScoreIsotopeEnvelope(bestStDev);
}

public double GetMostAbundantObservedIsotopicMass(List<(double mz, double intensity)> peaks, int charge)
/// <summary>
/// Used for a neutral mass read in from a deconvoluted file
/// Assumes the mass is correct: score is max value
/// </summary>
public IsotopicEnvelope(double monoisotopicMass, double intensity, int charge)
{
return peaks.MaxBy(p => p.intensity).mz * Math.Abs(charge);
MonoisotopicMass = monoisotopicMass;
Charge = charge;
TotalIntensity = intensity;
Score = double.MaxValue;
Peaks = [(monoisotopicMass.ToMz(charge), intensity)];
}

public override string ToString()
{
return Charge + "\t" + Peaks[0].mz.ToString("G8") + "\t" + Peaks.Count + "\t" + TotalIntensity;
}

private double ScoreIsotopeEnvelope() //likely created by Stefan Solntsev using peptide data
private double ScoreIsotopeEnvelope(double stDev) //likely created by Stefan Solntsev using peptide data
{
return Peaks.Count >= 2 ?
TotalIntensity / Math.Pow(StDev, 0.13) * Math.Pow(Peaks.Count, 0.4) / Math.Pow(Math.Abs(Charge), 0.06) :
TotalIntensity / Math.Pow(stDev, 0.13) * Math.Pow(Peaks.Count, 0.4) / Math.Pow(Math.Abs(Charge), 0.06) :
0;
}

Expand All @@ -60,6 +67,5 @@ public void SetMedianMonoisotopicMass(List<double> monoisotopicMassPredictions)
{
MonoisotopicMass = monoisotopicMassPredictions.Median();
}

}
}
15 changes: 9 additions & 6 deletions mzLib/MassSpectrometry/MzSpectra/MzSpectrum.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,8 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text.Json;

namespace MassSpectrometry
{
Expand Down Expand Up @@ -126,7 +124,7 @@ public MzRange Range
}
}

public double? FirstX
public virtual double? FirstX
{
get
{
Expand All @@ -138,7 +136,7 @@ public double? FirstX
}
}

public double? LastX
public virtual double? LastX
{
get
{
Expand Down Expand Up @@ -373,7 +371,7 @@ public IsotopicEnvelope FindIsotopicEnvelope(int massIndex, double candidateForM
}
}

return new IsotopicEnvelope(listOfObservedPeaks, monoisotopicMass, chargeState, totalIntensity, Statistics.StandardDeviation(listOfRatios), massIndex);
return new IsotopicEnvelope(listOfObservedPeaks, monoisotopicMass, chargeState, totalIntensity, listOfRatios.StandardDeviation());
}

[Obsolete("Deconvolution Has been moved to the Deconvoluter Object")]
Expand Down Expand Up @@ -796,7 +794,12 @@ private MzPeak GetPeak(int index)
return peakList[index];
}

private MzPeak GeneratePeak(int index)
/// <summary>
/// The source of all peaks which populate the peakList
/// </summary>
/// <param name="index"></param>
/// <returns></returns>
protected virtual MzPeak GeneratePeak(int index)
{
return new MzPeak(XArray[index], YArray[index]);
}
Expand Down
65 changes: 65 additions & 0 deletions mzLib/MassSpectrometry/MzSpectra/NeutralMassSpectrum.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
using System;
using Chemistry;

namespace MassSpectrometry
{
public class NeutralMassSpectrum : MzSpectrum
{
public int[] Charges { get; init; }
public NeutralMassSpectrum(double[,] monoisotopicMassesIntensities, int[] charges) : base(monoisotopicMassesIntensities)
{
if (monoisotopicMassesIntensities.GetLength(0) != charges.Length)
throw new ArgumentException("The lengths of monoisotopicMasses, intensities, and charges must be the same.");

Charges = charges;

double minMz = double.MaxValue;
double maxMz = double.MinValue;
for (int i = 0; i < monoisotopicMassesIntensities.GetLength(0); i++)
{
var mz = monoisotopicMassesIntensities[i,0].ToMz(charges[i]);
if (mz < minMz)
minMz = mz;
if (mz > maxMz)
maxMz = mz;
}

FirstX = minMz;
LastX = maxMz;
}

public NeutralMassSpectrum(double[] monoisotopicMasses, double[] intensities, int[] charges, bool shouldCopy)
: base(monoisotopicMasses, intensities, shouldCopy)
{
if (monoisotopicMasses.GetLength(0) != intensities.Length || monoisotopicMasses.Length != charges.Length)
throw new ArgumentException("The lengths of monoisotopicMasses, intensities, and charges must be the same.");

Charges = charges;

double minMz = double.MaxValue;
double maxMz = double.MinValue;
for (int i = 0; i < monoisotopicMasses.Length; i++)
{
var mz = monoisotopicMasses[i].ToMz(charges[i]);
if (mz < minMz)
minMz = mz;
if (mz > maxMz)
maxMz = mz;
}

FirstX = minMz;
LastX = maxMz;
}

public override double? FirstX { get; } // in m/z
public override double? LastX { get; } // in m/z

/// <summary>
/// Converts to a charged spectrum
/// </summary>
protected override MzPeak GeneratePeak(int index)
{
return new MzPeak(XArray[index].ToMz(Charges[index]), YArray[index]);
}
}
}
5 changes: 3 additions & 2 deletions mzLib/SpectralAveraging/Algorithms/SpectraFileAveraging.cs
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ private static MsDataScan[] AverageAll(IReadOnlyCollection<MsDataScan> scans, Sp
// create output
MsDataScan averagedScan = new(averagedSpectrum, 1, representativeScan.OneBasedScanNumber,
representativeScan.IsCentroid, representativeScan.Polarity, scans.Select(p => p.RetentionTime).Average(),
averagedSpectrum.Range, null, representativeScan.MzAnalyzer, scans.Select(p => p.TotalIonCurrent).Average(),
averagedSpectrum.Range, representativeScan.ScanFilter, representativeScan.MzAnalyzer, scans.Select(p => p.TotalIonCurrent).Average(),
representativeScan.InjectionTime, null, representativeScan.NativeId);
MsDataScan[] msDataScans = { averagedScan };
return msDataScans;
Expand Down Expand Up @@ -129,7 +129,8 @@ private static MsDataScan GetAveragedDataScanFromAveragedSpectrum(MzSpectrum ave
centralScan.IsCentroid,
centralScan.Polarity,
centralScan.RetentionTime,
averagedSpectrum.Range, null,
averagedSpectrum.Range,
centralScan.ScanFilter,
centralScan.MzAnalyzer,
averagedSpectrum.SumOfAllY,
centralScan.InjectionTime,
Expand Down
Loading

0 comments on commit 40f90df

Please sign in to comment.