From 756d26a3e0033410f7ef1be44083910f999e1037 Mon Sep 17 00:00:00 2001 From: rrad Date: Wed, 22 Jan 2025 17:22:39 -0800 Subject: [PATCH] add option to extract resolution data for orbitrap scans --- Monocle.CLI/MakeMonoOptions.cs | 3 +++ Monocle.CLI/Program.cs | 4 +++- Monocle/Data/Scan.cs | 15 +++++++++++++++ Monocle/File/MzDBReader.cs | 10 ++++++++++ Monocle/File/MzDBWriter.cs | 30 +++++++++++++++++------------- Monocle/File/RawReader.cs | 13 +++++++++++++ Monocle/File/ScanReaderOptions.cs | 6 ++++-- Monocle/MonocleOptions.cs | 7 +++++++ 8 files changed, 72 insertions(+), 16 deletions(-) diff --git a/Monocle.CLI/MakeMonoOptions.cs b/Monocle.CLI/MakeMonoOptions.cs index 1ec3b31..c97d72b 100644 --- a/Monocle.CLI/MakeMonoOptions.cs +++ b/Monocle.CLI/MakeMonoOptions.cs @@ -64,5 +64,8 @@ public class MakeMonoOptions [Option("Ms2Ms3Precursor", Hidden = true, Required = false, HelpText = "Assign precursors to the ms3 scan from the parent ms2.")] public bool Ms2Ms3Precursor { get; set; } = false; + + [Option("Resolution", Hidden = true, Required = false, HelpText = "Extract resolution from all scans with resolution information.")] + public bool Resolution { get; set; } = false; } } diff --git a/Monocle.CLI/Program.cs b/Monocle.CLI/Program.cs index 3383123..405d4a2 100644 --- a/Monocle.CLI/Program.cs +++ b/Monocle.CLI/Program.cs @@ -31,10 +31,12 @@ static void Main(string[] args) ForceCharges = options.ForceCharges, UseMostIntense = options.UseMostIntense, Ms2Ms3Precursor = options.Ms2Ms3Precursor, - RawMonoMz = options.RawMonoMz + RawMonoMz = options.RawMonoMz, + Resolution = options.Resolution, }; var readerOptions = new ScanReaderOptions(); + readerOptions.Resolution = monocleOptions.Resolution; SetupLogger(options.RunQuiet, options.WriteDebug); diff --git a/Monocle/Data/Scan.cs b/Monocle/Data/Scan.cs index 90c1cbc..3838173 100644 --- a/Monocle/Data/Scan.cs +++ b/Monocle/Data/Scan.cs @@ -130,6 +130,21 @@ public class Scan : IDisposable /// If a dependent scan, the activation method used to generate the scan fragments /// public string PrecursorActivationMethod { get; set; } = ""; + + /// + /// Whether the Centroids list has baseline data + /// + public bool HasBaseline { get; set; } + + /// + /// Whether the Centroids list has noise data + /// + public bool HasNoise { get; set; } + + /// + /// Whether the Centroids list has resolution data + /// + public bool HasResolution { get; set; } /// /// The observed centroid peaks in the scan diff --git a/Monocle/File/MzDBReader.cs b/Monocle/File/MzDBReader.cs index 424eaea..4742173 100644 --- a/Monocle/File/MzDBReader.cs +++ b/Monocle/File/MzDBReader.cs @@ -151,6 +151,16 @@ private void DecodePeaks(Scan scan, int flags, byte[] data) { } scan.Centroids.Add(centroid); } + + if ((flags & MzDBWriter.HAS_BASELINE) != 0) { + scan.HasBaseline = true; + } + if ((flags & MzDBWriter.HAS_NOISE) != 0) { + scan.HasNoise = true; + } + if ((flags & MzDBWriter.HAS_RESOLUTION) != 0) { + scan.HasResolution = true; + } } private byte[] DecompressData(byte[] data) { diff --git a/Monocle/File/MzDBWriter.cs b/Monocle/File/MzDBWriter.cs index c424ba1..46e6736 100644 --- a/Monocle/File/MzDBWriter.cs +++ b/Monocle/File/MzDBWriter.cs @@ -35,6 +35,11 @@ public class MzDBWriter : IScanWriter /// Path to the SQLite db file public void Open(string path) { + // Overwrite existing. + if (System.IO.File.Exists(path)) { + System.IO.File.Delete(path); + } + db = new SqliteConnection($"Data Source={path}"); db.Open(); @@ -225,9 +230,9 @@ public void WriteScan(Scan scan) peakInsert.Parameters.AddWithValue("$id", ++peakIndex); peakInsert.Parameters.AddWithValue("$scan", scan.ScanNumber); peakInsert.Parameters.AddWithValue("$peak_count", scan.Centroids.Count); - peakInsert.Parameters.AddWithValue("$data_type", getPeakFlags(scan)); + peakInsert.Parameters.AddWithValue("$data_type", GetPeakFlags(scan)); // skipping compression for now. - peakInsert.Parameters.AddWithValue("$data", encodePeaks(scan)); + peakInsert.Parameters.AddWithValue("$data", EncodePeaks(scan)); peakInsert.ExecuteNonQuery(); foreach(Precursor precursor in scan.Precursors) { @@ -252,15 +257,15 @@ public void WriteScan(Scan scan) /// /// The scan with the peak data. /// An integer with the flags for the type of data stored. - private int getPeakFlags(Scan scan) { + private int GetPeakFlags(Scan scan) { int output = 0; - if (scan.DetectorType == "FTMS" || scan.DetectorType == "ASTMS") { + if (scan.HasBaseline && scan.HasNoise) { output = HAS_MZ_DOUBLE | HAS_INTENSITY | HAS_BASELINE | HAS_NOISE; } else { output = HAS_MZ_FLOAT | HAS_INTENSITY; } - if (scan.DetectorType == "ASTMS") { + if (scan.HasResolution) { output |= HAS_RESOLUTION; } return output; @@ -271,7 +276,7 @@ private int getPeakFlags(Scan scan) { /// /// The scan with the peaks to store /// A byte array with the peak data. - private byte[] encodePeaks(Scan scan) { + private byte[] EncodePeaks(Scan scan) { int peakCount = scan.Centroids.Count; double[] mz = new double[peakCount]; float[] all = new float[peakCount * 5]; @@ -294,16 +299,16 @@ private byte[] encodePeaks(Scan scan) { int resolutionBytes = peakCount * sizeof(uint); byte[] output = null; - if (scan.DetectorType == "FTMS") { - output = new byte[mzDoubleBytes + intensityBytes + baselineBytes + noiseBytes]; - Buffer.BlockCopy(mz, 0, output, 0, mzDoubleBytes); - Buffer.BlockCopy(all, mzFloatBytes, output, mzDoubleBytes, intensityBytes + baselineBytes + noiseBytes); - } - else if (scan.DetectorType == "ASTMS") { + if (scan.HasResolution && scan.HasBaseline && scan.HasNoise) { + // BlockCopy (Array src, int srcOffset, Array dst, int dstOffset, int count); output = new byte[mzDoubleBytes + intensityBytes + baselineBytes + noiseBytes + resolutionBytes]; Buffer.BlockCopy(mz, 0, output, 0, mzDoubleBytes); Buffer.BlockCopy(all, mzFloatBytes, output, mzDoubleBytes, intensityBytes + baselineBytes + noiseBytes); Buffer.BlockCopy(resolution, 0, output, mzDoubleBytes + intensityBytes + baselineBytes + noiseBytes, resolutionBytes); + } else if (scan.HasBaseline && scan.HasNoise) { + output = new byte[mzDoubleBytes + intensityBytes + baselineBytes + noiseBytes]; + Buffer.BlockCopy(mz, 0, output, 0, mzDoubleBytes); + Buffer.BlockCopy(all, mzFloatBytes, output, mzDoubleBytes, intensityBytes + baselineBytes + noiseBytes); } else { output = new byte[mzFloatBytes + intensityBytes]; @@ -330,6 +335,5 @@ public static byte[] CompressData(byte[] data) } } } - } diff --git a/Monocle/File/RawReader.cs b/Monocle/File/RawReader.cs index e5e5f17..54b273b 100644 --- a/Monocle/File/RawReader.cs +++ b/Monocle/File/RawReader.cs @@ -293,6 +293,19 @@ public void CentroidsFromArrays( } scan.Centroids.Add(tempCentroid); } + + if (baselines != null) + { + scan.HasBaseline = true; + } + if (noises != null) + { + scan.HasNoise = true; + } + if ((scan.DetectorType == "ASTMS" || Options.Resolution) && resolutions != null) + { + scan.HasResolution = true; + } } /// diff --git a/Monocle/File/ScanReaderOptions.cs b/Monocle/File/ScanReaderOptions.cs index 2228fcc..87b7009 100644 --- a/Monocle/File/ScanReaderOptions.cs +++ b/Monocle/File/ScanReaderOptions.cs @@ -3,8 +3,10 @@ namespace Monocle.File { public class ScanReaderOptions { - /// Deprecated. Use member in MonocleOptions instead. - public bool RawMonoMz = false; + /// Extract resolution information for every scan that has + /// resolution information. Resolution for ASTMS will always + /// be extracted. + public bool Resolution = false; } } diff --git a/Monocle/MonocleOptions.cs b/Monocle/MonocleOptions.cs index e000ec1..174141c 100644 --- a/Monocle/MonocleOptions.cs +++ b/Monocle/MonocleOptions.cs @@ -128,6 +128,13 @@ public int MS_Level /// public bool RawMonoMz { get; set; } = false; + /// + /// If set to true, Resolution data will be extracted from all scans + /// that have resolution data (Orbitrap, Astral). + /// Requires mzdb format for output. + /// + public bool Resolution { get; set; } = false; + /// /// Allow get/set of property based on property name ///