diff --git a/MainClass.cs b/MainClass.cs index 7ece9cf..fa505ec 100644 --- a/MainClass.cs +++ b/MainClass.cs @@ -20,7 +20,7 @@ public static class MainClass private static readonly ILog Log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); - public const string Version = "1.4.2"; + public const string Version = "1.4.3"; public static void Main(string[] args) { // Set Invariant culture as default for all further processing diff --git a/README.md b/README.md index 704908d..e4d08dd 100644 --- a/README.md +++ b/README.md @@ -192,7 +192,8 @@ Provide one of the following filters: * M/Z start and end * sequence and tolerance (tolerance unit optional, defaults to `ppm`) -optionally one can define starting and ending retention times and thermo filter string (defaults to `ms`) +optionally one can define starting and ending retention times, provide filter string (defaults to `ms`, i.e. only MS1 scans), and a comment (free text) field; any valid filter string is supported, +however only basic validation is performed, see [issue #158](https://github.com/compomics/ThermoRawFileParser/issues/158) for details. Comment can contain any text and will be preserved in the output. An example input JSON file: @@ -219,7 +220,17 @@ An example input JSON file: { "sequence":"TRANNEL", "tolerance":10 + }, + { + "mz":1014.5099732499732, + "rt_start":14.0600881872, + "rt_end":14.4167198290667, + "tolerance":5, + "tolerance_unit":"ppm", + "comment":"Only ion trap scans" + "scan_filter":"ITMS" } + } ] ``` diff --git a/RawFileParser.cs b/RawFileParser.cs old mode 100644 new mode 100755 index 8ac667d..48b476a --- a/RawFileParser.cs +++ b/RawFileParser.cs @@ -136,18 +136,23 @@ private static void ProcessFile(ParseInput parseInput) // Get the number of instruments (controllers) present in the RAW file and set the // selected instrument to the MS instrument, first instance of it - rawFile.SelectInstrument(Device.MS, 1); + var firstScanNumber = -1; + var lastScanNumber = -1; - rawFile.IncludeReferenceAndExceptionData = !parseInput.ExData; + if (rawFile.GetInstrumentCountOfType(Device.MS) != 0) + { + rawFile.SelectInstrument(Device.MS, 1); + rawFile.IncludeReferenceAndExceptionData = !parseInput.ExData; - // Get the first and last scan from the RAW file - var firstScanNumber = rawFile.RunHeaderEx.FirstSpectrum; - var lastScanNumber = rawFile.RunHeaderEx.LastSpectrum; + // Get the first and last scan from the RAW file + firstScanNumber = rawFile.RunHeaderEx.FirstSpectrum; + lastScanNumber = rawFile.RunHeaderEx.LastSpectrum; - // Check for empty file - if (lastScanNumber < 1) - { - throw new RawFileParserException("Empty RAW file, no output will be produced"); + // Check for empty file + if (lastScanNumber < 1) + { + throw new RawFileParserException("Empty RAW file, no output will be produced"); + } } if (parseInput.MetadataFormat != MetadataFormat.NONE) diff --git a/ThermoRawFileParser.csproj b/ThermoRawFileParser.csproj index 536b601..115f686 100644 --- a/ThermoRawFileParser.csproj +++ b/ThermoRawFileParser.csproj @@ -176,11 +176,11 @@ - - packages\ThermoFisher.CommonCore.Data.5.0.0.88\lib\ThermoFisher.CommonCore.Data.dll + + packages\ThermoFisher.CommonCore.Data.5.0.0.93\lib\netstandard2.0\ThermoFisher.CommonCore.Data.dll - - packages\ThermoFisher.CommonCore.RawFileReader.5.0.0.88\lib\ThermoFisher.CommonCore.RawFileReader.dll + + packages\ThermoFisher.CommonCore.RawFileReader.5.0.0.93\lib\netstandard2.0\ThermoFisher.CommonCore.RawFileReader.dll packages\zlib.net.1.0.4.0\lib\zlib.net.dll @@ -199,6 +199,7 @@ + diff --git a/ThermoRawFileParserTest/OntologyMappingTests.cs b/ThermoRawFileParserTest/OntologyMappingTests.cs index d4f7f3f..69f0c31 100644 --- a/ThermoRawFileParserTest/OntologyMappingTests.cs +++ b/ThermoRawFileParserTest/OntologyMappingTests.cs @@ -12,13 +12,13 @@ public class OntologyMappingTests public void TestGetInstrumentModel() { // exact match - var match = OntologyMapping.getInstrumentModel("LTQ Orbitrap"); + var match = OntologyMapping.GetInstrumentModel("LTQ Orbitrap"); Assert.AreEqual("MS:1000449", match.accession); // partial match, should return the longest partial match - var partialMatch = OntologyMapping.getInstrumentModel("LTQ Orbitrap XXL"); + var partialMatch = OntologyMapping.GetInstrumentModel("LTQ Orbitrap XXL"); Assert.AreEqual("MS:1000449", partialMatch.accession); // no match, should return the generic thermo instrument - var noMatch = OntologyMapping.getInstrumentModel("non existing model"); + var noMatch = OntologyMapping.GetInstrumentModel("non existing model"); Assert.AreEqual("MS:1000483", noMatch.accession); } } diff --git a/ThermoRawFileParserTest/ThermoRawFileParserTest.csproj b/ThermoRawFileParserTest/ThermoRawFileParserTest.csproj index 9cf254a..eb86bb9 100644 --- a/ThermoRawFileParserTest/ThermoRawFileParserTest.csproj +++ b/ThermoRawFileParserTest/ThermoRawFileParserTest.csproj @@ -155,15 +155,15 @@ ..\packages\mzLib.1.0.450\lib\net471\ThermoFisher.CommonCore.BackgroundSubtraction.dll True - - ..\packages\ThermoFisher.CommonCore.Data.5.0.0.88\lib\ThermoFisher.CommonCore.Data.dll + + ..\packages\ThermoFisher.CommonCore.Data.5.0.0.93\lib\netstandard2.0\ThermoFisher.CommonCore.Data.dll ..\packages\mzLib.1.0.450\lib\net471\ThermoFisher.CommonCore.MassPrecisionEstimator.dll True - - ..\packages\ThermoFisher.CommonCore.RawFileReader.5.0.0.88\lib\ThermoFisher.CommonCore.RawFileReader.dll + + ..\packages\ThermoFisher.CommonCore.RawFileReader.5.0.0.93\lib\netstandard2.0\ThermoFisher.CommonCore.RawFileReader.dll ..\packages\mzLib.1.0.450\lib\net471\ThermoRawFileReader.dll diff --git a/ThermoRawFileParserTest/app.config b/ThermoRawFileParserTest/app.config index 3ee23db..60d020d 100644 --- a/ThermoRawFileParserTest/app.config +++ b/ThermoRawFileParserTest/app.config @@ -12,7 +12,7 @@ - + @@ -28,7 +28,7 @@ - + diff --git a/ThermoRawFileParserTest/packages.config b/ThermoRawFileParserTest/packages.config index b89c239..ec8a33e 100644 --- a/ThermoRawFileParserTest/packages.config +++ b/ThermoRawFileParserTest/packages.config @@ -19,7 +19,7 @@ - - + + \ No newline at end of file diff --git a/Util/CVHelpers.cs b/Util/CVHelpers.cs new file mode 100644 index 0000000..cf7c617 --- /dev/null +++ b/Util/CVHelpers.cs @@ -0,0 +1,21 @@ +using ThermoRawFileParser.Writer.MzML; + +namespace ThermoRawFileParser.Util +{ + public static class CVHelpers + { + public static CVParamType Copy (this CVParamType old) + { + return new CVParamType + { + accession = old.accession, + name = old.name, + cvRef = old.cvRef, + unitAccession = old.unitAccession, + unitCvRef = old.unitCvRef, + unitName = old.unitName, + value = old.value + }; + } + } +} diff --git a/Writer/MetadataWriter.cs b/Writer/MetadataWriter.cs index e7554ce..663ec13 100644 --- a/Writer/MetadataWriter.cs +++ b/Writer/MetadataWriter.cs @@ -46,73 +46,74 @@ public MetadataWriter(ParseInput parseInput) /// public void WriteMetadata(IRawDataPlus rawFile, int firstScanNumber, int lastScanNumber) { - // Get the start and end time from the RAW file - var startTime = rawFile.RunHeaderEx.StartTime; - var endTime = rawFile.RunHeaderEx.EndTime; - - for (var scanNumber = firstScanNumber; scanNumber <= lastScanNumber; scanNumber++) + if(rawFile.SelectMsData()) { - var time = rawFile.RetentionTimeFromScanNumber(scanNumber); - - // Get the scan filter for this scan number - var scanFilter = rawFile.GetFilterForScanNumber(scanNumber); + for (var scanNumber = firstScanNumber; scanNumber <= lastScanNumber; scanNumber++) + { + var time = rawFile.RetentionTimeFromScanNumber(scanNumber); - // Get the scan event for this scan number - var scanEvent = rawFile.GetScanEventForScanNumber(scanNumber); + // Get the scan filter for this scan number + var scanFilter = rawFile.GetFilterForScanNumber(scanNumber); - // Keep track of the number of MS spectra - if (msTypes.ContainsKey(scanFilter.MSOrder.ToString())) - { - var value = msTypes[scanFilter.MSOrder.ToString()]; - value += 1; - msTypes[scanFilter.MSOrder.ToString()] = value; - } - else - msTypes.Add(scanFilter.MSOrder.ToString(), 1); + // Get the scan event for this scan number + var scanEvent = rawFile.GetScanEventForScanNumber(scanNumber); - if (time > maxTime) - maxTime = time; - if (time < minTime) - minTime = time; + // Keep track of the number of MS spectra + if (msTypes.ContainsKey(scanFilter.MSOrder.ToString())) + { + msTypes[scanFilter.MSOrder.ToString()] += 1; + } + else + msTypes.Add(scanFilter.MSOrder.ToString(), 1); - if (scanFilter.MSOrder == MSOrderType.Ms2) - { - fragmentationTypes.Add(ParseActivationType(scanFilter.GetActivation(0))); + if (time > maxTime) + maxTime = time; + if (time < minTime) + minTime = time; - if (scanEvent.ScanData == ScanDataType.Centroid || (scanEvent.ScanData == ScanDataType.Profile)) + if (scanFilter.MSOrder == MSOrderType.Ms2) { - try - { - var reaction = scanEvent.GetReaction(0); - var precursorMass = reaction.PrecursorMass; - if (precursorMass > maxMz) - maxMz = precursorMass; - if (precursorMass < minMz) - minMz = precursorMass; - } - catch (ArgumentOutOfRangeException) - { - Log.Warn("No reaction found for scan " + scanNumber); - _parseInput.NewWarn(); - } + fragmentationTypes.Add(ParseActivationType(scanFilter.GetActivation(0))); - // trailer extra data list - var trailerData = rawFile.GetTrailerExtraInformation(scanNumber); - for (var i = 0; i < trailerData.Length; i++) + if (scanEvent.ScanData == ScanDataType.Centroid || (scanEvent.ScanData == ScanDataType.Profile)) { - if (trailerData.Labels[i] == "Charge State:") + try + { + var reaction = scanEvent.GetReaction(0); + var precursorMass = reaction.PrecursorMass; + if (precursorMass > maxMz) + maxMz = precursorMass; + if (precursorMass < minMz) + minMz = precursorMass; + } + catch (ArgumentOutOfRangeException) + { + Log.Warn("No reaction found for scan " + scanNumber); + _parseInput.NewWarn(); + } + + // trailer extra data list + try { - if (int.Parse(trailerData.Values[i]) > maxCharge) - maxCharge = int.Parse(trailerData.Values[i]); + var trailerData = new ScanTrailer(rawFile.GetTrailerExtraInformation(scanNumber)); + int? charge = trailerData.AsPositiveInt("Charge State:"); - if (int.Parse(trailerData.Values[i]) < minCharge) - minCharge = int.Parse(trailerData.Values[i]); + if (charge.HasValue && charge.Value > maxCharge) + maxCharge = charge.Value; + + if (charge.HasValue && charge.Value < minCharge) + minCharge = charge.Value; + } + catch (Exception ex) + { + Log.WarnFormat("Cannot load trailer infromation for scan {0} due to following exception\n{1}", scanNumber, ex.Message); + _parseInput.NewWarn(); } } } } } - + if (minCharge == 100000000000000) { minCharge = 0; @@ -145,10 +146,6 @@ public void WriteMetadata(IRawDataPlus rawFile, int firstScanNumber, int lastSca /// private void WriteJsonMetada(IRawDataPlus rawFile, int firstScanNumber, int lastScanNumber) { - // Get the start and end time from the RAW file - var startTime = rawFile.RunHeaderEx.StartTime; - var endTime = rawFile.RunHeaderEx.EndTime; - var metadata = new Metadata(); // File Properties @@ -164,19 +161,23 @@ private void WriteJsonMetada(IRawDataPlus rawFile, int firstScanNumber, int last } // Instrument Properties - metadata.addInstrumentProperty(new CVTerm("MS:1000494", "MS", "Thermo Scientific instrument model", - rawFile.GetInstrumentData().Model)); - metadata.addInstrumentProperty(new CVTerm("MS:1000496", "MS", "instrument attribute", - rawFile.GetInstrumentData().Name)); - metadata.addInstrumentProperty(new CVTerm("MS:1000529", "MS", "instrument serial number", - rawFile.GetInstrumentData().SerialNumber)); - metadata.addInstrumentProperty(new CVTerm("NCIT:C111093", "NCIT", "Software Version", - rawFile.GetInstrumentData().SoftwareVersion)); - if (!rawFile.GetInstrumentData().HardwareVersion.IsNullOrEmpty()) + if (rawFile.SelectMsData()) { - metadata.addInstrumentProperty(new CVTerm("AFR:0001259", "AFO", "firmware version", - rawFile.GetInstrumentData().HardwareVersion)); + metadata.addInstrumentProperty(new CVTerm("MS:1000494", "MS", "Thermo Scientific instrument model", + rawFile.GetInstrumentData().Model)); + metadata.addInstrumentProperty(new CVTerm("MS:1000496", "MS", "instrument attribute", + rawFile.GetInstrumentData().Name)); + metadata.addInstrumentProperty(new CVTerm("MS:1000529", "MS", "instrument serial number", + rawFile.GetInstrumentData().SerialNumber)); + metadata.addInstrumentProperty(new CVTerm("NCIT:C111093", "NCIT", "Software Version", + rawFile.GetInstrumentData().SoftwareVersion)); + if (!rawFile.GetInstrumentData().HardwareVersion.IsNullOrEmpty()) + { + metadata.addInstrumentProperty(new CVTerm("AFR:0001259", "AFO", "firmware version", + rawFile.GetInstrumentData().HardwareVersion)); + } } + // MS Data foreach (KeyValuePair entry in msTypes) @@ -208,21 +209,31 @@ private void WriteJsonMetada(IRawDataPlus rawFile, int firstScanNumber, int last maxMz.ToString(CultureInfo.InvariantCulture))); // Scan Settings - metadata.addScanSetting(new CVTerm("MS:1000016", "MS", "scan start time", - startTime.ToString(CultureInfo.InvariantCulture))); - metadata.addScanSetting(new CVTerm("MS:1000011", "MS", "mass resolution", - rawFile.RunHeaderEx.MassResolution.ToString(CultureInfo.InvariantCulture))); - metadata.addScanSetting(new CVTerm("UO:0000002", "MS", "mass unit", - rawFile.GetInstrumentData().Units.ToString())); - metadata.addScanSetting(new CVTerm("PRIDE:0000478", "PRIDE", "Number of scans", - rawFile.RunHeaderEx.SpectraCount.ToString())); - metadata.addScanSetting(new CVTerm("PRIDE:0000479", "PRIDE", "MS scan range", - firstScanNumber + ":" + lastScanNumber)); - metadata.addScanSetting(new CVTerm("PRIDE:0000484", "PRIDE", "Retention time range", - startTime + ":" + endTime)); - metadata.addScanSetting(new CVTerm("PRIDE:0000485", "PRIDE", "Mz range", - rawFile.RunHeaderEx.LowMass + ":" + rawFile.RunHeaderEx.HighMass)); - metadata.addScanSetting(fragmentationTypes); + // Get the start and end time from the RAW file + + if (rawFile.SelectMsData()) + { + var runHeaderEx = rawFile.RunHeaderEx; + var startTime = runHeaderEx.StartTime; + var endTime = runHeaderEx.EndTime; + metadata.addScanSetting(new CVTerm("MS:1000016", "MS", "scan start time", + startTime.ToString(CultureInfo.InvariantCulture))); + metadata.addScanSetting(new CVTerm("", "", "expected runtime", + runHeaderEx.ExpectedRunTime.ToString(CultureInfo.InvariantCulture))); + metadata.addScanSetting(new CVTerm("MS:1000011", "MS", "mass resolution", + runHeaderEx.MassResolution.ToString(CultureInfo.InvariantCulture))); + metadata.addScanSetting(new CVTerm("UO:0000002", "MS", "mass unit", + rawFile.GetInstrumentData().Units.ToString())); + metadata.addScanSetting(new CVTerm("PRIDE:0000478", "PRIDE", "Number of scans", + runHeaderEx.SpectraCount.ToString())); + metadata.addScanSetting(new CVTerm("PRIDE:0000484", "PRIDE", "Retention time range", + startTime + ":" + endTime)); + metadata.addScanSetting(new CVTerm("PRIDE:0000485", "PRIDE", "Mz range", + runHeaderEx.LowMass + ":" + runHeaderEx.HighMass)); + metadata.addScanSetting(fragmentationTypes); + metadata.addScanSetting(new CVTerm("PRIDE:0000479", "PRIDE", "MS scan range", + firstScanNumber + ":" + lastScanNumber)); + } // Sample Data if (!rawFile.SampleInformation.SampleName.IsNullOrEmpty()) @@ -280,6 +291,43 @@ private void WriteJsonMetada(IRawDataPlus rawFile, int firstScanNumber, int last rawFile.SampleInformation.DilutionFactor.ToString(CultureInfo.InvariantCulture))); } + if (!rawFile.SampleInformation.InstrumentMethodFile.IsNullOrEmpty()) + { + metadata.addSampleProperty(new CVTerm("AFR:0002045", "AFO", "device acquisition method", rawFile.SampleInformation.InstrumentMethodFile)); + } + + if (rawFile.SampleInformation.IstdAmount != 0) + { + metadata.addSampleProperty(new CVTerm("", "", "internal standard amount", rawFile.SampleInformation.IstdAmount.ToString())); + } + + if (!rawFile.SampleInformation.CalibrationLevel.IsNullOrEmpty()) + { + metadata.addSampleProperty(new CVTerm("AFR:0001849", "AFO", "calibration level", rawFile.SampleInformation.CalibrationLevel)); + } + + if (!rawFile.SampleInformation.ProcessingMethodFile.IsNullOrEmpty()) + { + metadata.addSampleProperty(new CVTerm("AFR:0002175", "AFO", "data processing method", rawFile.SampleInformation.ProcessingMethodFile)); + } + + if (rawFile.SampleInformation.SampleWeight != 0) + { + metadata.addSampleProperty(new CVTerm("AFR:0001982", "AFO", "sample weight", rawFile.SampleInformation.SampleWeight.ToString())); + } + + string[] userLabels = rawFile.UserLabel; + string[] userTexts = rawFile.SampleInformation.UserText; + if (!userLabels.IsNullOrEmpty() && !userTexts.IsNullOrEmpty()) + { + for (int i = 0; i < userLabels.Length; i++) + { + if (i < userTexts.Length && !userTexts[i].IsNullOrEmpty()) + { + metadata.addSampleProperty(new CVTerm("", "", userLabels[i], userTexts[i])); + } + } + } // Write the meta data to file var json = JsonConvert.SerializeObject(metadata); @@ -296,10 +344,6 @@ private void WriteJsonMetada(IRawDataPlus rawFile, int firstScanNumber, int last /// private void WriteTextMetadata(IRawDataPlus rawFile, int firstScanNumber, int lastScanNumber) { - // Get the start and end time from the RAW file - var startTime = rawFile.RunHeaderEx.StartTime; - var endTime = rawFile.RunHeaderEx.EndTime; - // File Properties var output = new List { @@ -314,20 +358,23 @@ private void WriteTextMetadata(IRawDataPlus rawFile, int firstScanNumber, int la } // Instrument Properties - output.Add("#InstrumentProperties"); - output.AddRange(new List + if (rawFile.SelectMsData()) + { + output.Add("#InstrumentProperties"); + output.AddRange(new List { $"Instrument model=[MS, MS:1000494, Thermo Scientific instrument model, {rawFile.GetInstrumentData().Model}]", "Instrument name=" + rawFile.GetInstrumentData().Name, $"Instrument serial number=[MS, MS:1000529, instrument serial number, {rawFile.GetInstrumentData().SerialNumber}]", $"Software version=[NCIT, NCIT:C111093, Software Version, {rawFile.GetInstrumentData().SoftwareVersion}]", } - ); - if (!rawFile.GetInstrumentData().HardwareVersion.IsNullOrEmpty()) - { - output.Add("Firmware version=" + rawFile.GetInstrumentData().HardwareVersion); + ); + if (!rawFile.GetInstrumentData().HardwareVersion.IsNullOrEmpty()) + { + output.Add("Firmware version=" + rawFile.GetInstrumentData().HardwareVersion); + } } - + // MS Data output.Add("#MsData"); foreach (KeyValuePair entry in msTypes) @@ -342,8 +389,8 @@ private void WriteTextMetadata(IRawDataPlus rawFile, int firstScanNumber, int la output.AddRange(new List { - "MS min charge=" + minCharge.ToString(CultureInfo.InvariantCulture), - "MS max charge=" + maxCharge.ToString(CultureInfo.InvariantCulture), + $"MS min charge={minCharge.ToString(CultureInfo.InvariantCulture)}", + $"MS max charge={maxCharge.ToString(CultureInfo.InvariantCulture)}", $"MS min RT={minTime.ToString(CultureInfo.InvariantCulture)}", $"MS max RT={maxTime.ToString(CultureInfo.InvariantCulture)}", $"MS min MZ={minMz.ToString(CultureInfo.InvariantCulture)}", @@ -352,20 +399,26 @@ private void WriteTextMetadata(IRawDataPlus rawFile, int firstScanNumber, int la ); // Scan Settings - output.AddRange(new List - { - "#ScanSettings", - $"Scan start time={startTime.ToString(CultureInfo.InvariantCulture)}", - $"Mass resolution=[MS, MS:1000011, mass resolution, {rawFile.RunHeaderEx.MassResolution.ToString(CultureInfo.InvariantCulture)}]", - "Units=" + rawFile.GetInstrumentData().Units, - $"Number of scans={rawFile.RunHeaderEx.SpectraCount}", - $"Scan range={firstScanNumber};{lastScanNumber}", - $"Time range={startTime.ToString(CultureInfo.InvariantCulture)};{endTime.ToString(CultureInfo.InvariantCulture)}", - $"Mass range={rawFile.RunHeaderEx.LowMass.ToString(CultureInfo.InvariantCulture)};{rawFile.RunHeaderEx.HighMass.ToString(CultureInfo.InvariantCulture)}", - "Fragmentation types=" + String.Join(", ", fragmentationTypes.Select(f => f.value)) - } - ); - + if (rawFile.SelectMsData()) + { + // Get the start and end time from the RAW file + var startTime = rawFile.RunHeaderEx.StartTime; + var endTime = rawFile.RunHeaderEx.EndTime; + output.AddRange(new List + { + "#ScanSettings", + $"Scan start time={startTime.ToString(CultureInfo.InvariantCulture)}", + $"Expected runtime={rawFile.RunHeaderEx.ExpectedRunTime.ToString(CultureInfo.InvariantCulture)}", + $"Mass resolution=[MS, MS:1000011, mass resolution, {rawFile.RunHeaderEx.MassResolution.ToString(CultureInfo.InvariantCulture)}]", + "Units=" + rawFile.GetInstrumentData().Units, + $"Number of scans={rawFile.RunHeaderEx.SpectraCount}", + $"Scan range={firstScanNumber};{lastScanNumber}", + $"Time range={startTime.ToString(CultureInfo.InvariantCulture)};{endTime.ToString(CultureInfo.InvariantCulture)}", + $"Mass range={rawFile.RunHeaderEx.LowMass.ToString(CultureInfo.InvariantCulture)};{rawFile.RunHeaderEx.HighMass.ToString(CultureInfo.InvariantCulture)}", + "Fragmentation types=" + String.Join(", ", fragmentationTypes.Select(f => f.value)) + } + ); + } // Sample Data output.Add("#SampleData"); @@ -415,6 +468,44 @@ private void WriteTextMetadata(IRawDataPlus rawFile, int firstScanNumber, int la output.Add("Sample dilution factor=" + rawFile.SampleInformation.DilutionFactor); } + if (rawFile.SampleInformation.IstdAmount != 0) + { + output.Add("Internal standard amount=" + rawFile.SampleInformation.IstdAmount); + } + + if (!rawFile.SampleInformation.CalibrationLevel.IsNullOrEmpty()) + { + output.Add("Calibration level=" + rawFile.SampleInformation.CalibrationLevel); + } + + if (!rawFile.SampleInformation.InstrumentMethodFile.IsNullOrEmpty()) + { + output.Add("Device acquisition method=" + rawFile.SampleInformation.InstrumentMethodFile); + } + + if (rawFile.SampleInformation.SampleWeight != 0) + { + output.Add("Sample weight=" + rawFile.SampleInformation.SampleWeight); + } + + if (!rawFile.SampleInformation.ProcessingMethodFile.IsNullOrEmpty()) + { + output.Add("Data processing method=" + rawFile.SampleInformation.ProcessingMethodFile); + } + + string[] userLabels = rawFile.UserLabel; + string[] userTexts = rawFile.SampleInformation.UserText; + if (!userLabels.IsNullOrEmpty() && !userTexts.IsNullOrEmpty()) + { + for (int i = 0; i < userLabels.Length; i++) + { + if (i < userTexts.Length && !userTexts[i].IsNullOrEmpty()) + { + output.Add(userLabels[i] + "=" + userTexts[i]); + } + } + } + // Write the meta data to file File.WriteAllLines(_metadataFileName, output.ToArray()); } diff --git a/Writer/MgfSpectrumWriter.cs b/Writer/MgfSpectrumWriter.cs index c347944..0c86189 100644 --- a/Writer/MgfSpectrumWriter.cs +++ b/Writer/MgfSpectrumWriter.cs @@ -38,9 +38,15 @@ public MgfSpectrumWriter(ParseInput parseInput) : base(parseInput) /// public override void Write(IRawDataPlus rawFile, int firstScanNumber, int lastScanNumber) { + if (!rawFile.HasMsData) + { + throw new RawFileParserException("No MS data in RAW file, no output will be produced"); + } + ConfigureWriter(".mgf"); using (Writer) { + Log.Info("Processing " + (lastScanNumber - firstScanNumber + 1) + " scans"); var lastScanProgress = 0; @@ -48,7 +54,7 @@ public override void Write(IRawDataPlus rawFile, int firstScanNumber, int lastSc { if (ParseInput.LogFormat == LogFormat.DEFAULT) { - var scanProgress = (int) ((double) scanNumber / (lastScanNumber - firstScanNumber + 1) * 100); + var scanProgress = (int)((double)scanNumber / (lastScanNumber - firstScanNumber + 1) * 100); if (scanProgress % ProgressPercentageStep == 0) { if (scanProgress != lastScanProgress) @@ -160,12 +166,12 @@ public override void Write(IRawDataPlus rawFile, int firstScanNumber, int lastSc Writer.WriteLine("BEGIN IONS"); if (!ParseInput.MgfPrecursor) { - Writer.WriteLine($"TITLE={ConstructSpectrumTitle((int) Device.MS, 1, scanNumber)}"); + Writer.WriteLine($"TITLE={ConstructSpectrumTitle((int)Device.MS, 1, scanNumber)}"); } else { Writer.WriteLine( - $"TITLE={ConstructSpectrumTitle((int) Device.MS, 1, scanNumber)} [PRECURSOR={precursorReference}]"); + $"TITLE={ConstructSpectrumTitle((int)Device.MS, 1, scanNumber)} [PRECURSOR={precursorReference}]"); } Writer.WriteLine($"SCANS={scanNumber}"); @@ -250,6 +256,7 @@ public override void Write(IRawDataPlus rawFile, int firstScanNumber, int lastSc { Console.WriteLine(); } + } } } diff --git a/Writer/MzMlSpectrumWriter.cs b/Writer/MzMlSpectrumWriter.cs index c830677..411f2dc 100644 --- a/Writer/MzMlSpectrumWriter.cs +++ b/Writer/MzMlSpectrumWriter.cs @@ -1,6 +1,8 @@ using System; using System.Collections.Generic; using System.Collections.Specialized; +using System.Diagnostics; +using System.Diagnostics.Eventing.Reader; using System.Globalization; using System.IO; using System.IO.Compression; @@ -16,7 +18,6 @@ using ThermoFisher.CommonCore.Data.Business; using ThermoFisher.CommonCore.Data.FilterEnums; using ThermoFisher.CommonCore.Data.Interfaces; -using ThermoRawFileParser.Util; using ThermoRawFileParser.Writer.MzML; using zlib; @@ -68,6 +69,8 @@ public MzMlSpectrumWriter(ParseInput parseInput) : base(parseInput) _mzMlNamespace.Add(string.Empty, "http://psi.hupo.org/ms/mzml"); _doIndexing = ParseInput.OutputFormat == OutputFormat.IndexMzML; _osOffset = Environment.NewLine == "\n" ? 0 : 1; + _precursorScanNumbers[""] = -1; + _precursorTree[-1] = new PrecursorInfo(); } /// @@ -140,30 +143,35 @@ public override void Write(IRawDataPlus rawFile, int firstScanNumber, int lastSc _writer.WriteStartElement("fileDescription"); // fileContent _writer.WriteStartElement("fileContent"); - // MS1 - SerializeCvParam(new CVParamType - { - accession = "MS:1000579", - name = "MS1 spectrum", - cvRef = "MS", - value = "" - }); - // MSn - SerializeCvParam(new CVParamType - { - accession = "MS:1000580", - name = "MSn spectrum", - cvRef = "MS", - value = "" - }); - // Ion current chromatogram - SerializeCvParam(new CVParamType + + //accumulating different types of file content + HashSet content = new HashSet(); + + if (_rawFile.HasMsData) { - accession = "MS:1000810", - name = "ion current chromatogram", - cvRef = "MS", - value = "" - }); + var nMS1 = rawFile.GetFilteredScanEnumerator("ms").Count(); + var nMS = rawFile.RunHeaderEx.SpectraCount; + // MS1 + if(ParseInput.MsLevel.Contains(1) && nMS1 > 0) + content.Add(new CVParamType + { + accession = "MS:1000579", + name = "MS1 spectrum", + cvRef = "MS", + value = "" + }); + // MSn + if(ParseInput.MsLevel.Any(n => n > 1) && nMS > nMS1) + content.Add(new CVParamType + { + accession = "MS:1000580", + name = "MSn spectrum", + cvRef = "MS", + value = "" + }); + // Ion current chromatogram + content.Add(OntologyMapping.GetChromatogramType("current")); + } // Other detector data if (ParseInput.AllDetectors) @@ -171,7 +179,7 @@ public override void Write(IRawDataPlus rawFile, int firstScanNumber, int lastSc // PDA spectrum if (_rawFile.GetInstrumentCountOfType(Device.Pda) > 0) { - SerializeCvParam(new CVParamType + content.Add(new CVParamType { accession = "MS:1000806", name = "absorption spectrum", @@ -184,14 +192,39 @@ public override void Write(IRawDataPlus rawFile, int firstScanNumber, int lastSc if (_rawFile.GetInstrumentCountOfType(Device.Pda) > 0 || _rawFile.GetInstrumentCountOfType(Device.UV) > 0) { - SerializeCvParam(new CVParamType + content.Add(OntologyMapping.GetChromatogramType("absorption")); + } + //non-standard chromatograms pressure, flow, FID, etc + foreach (var deviceType in new Device[2] { Device.Analog, Device.MSAnalog }) + { + for (int nrI = 1; nrI < _rawFile.GetInstrumentCountOfType(deviceType) + 1; nrI++) { - accession = "MS:1000812", - name = "absorption chromatogram", - cvRef = "MS", - value = "" - }); + _rawFile.SelectInstrument(deviceType, nrI); + + var instData = _rawFile.GetInstrumentData(); + + for (int channel = 0; channel < instData.ChannelLabels.Length; channel++) + { + var channelName = instData.ChannelLabels[channel]; + if (channelName.ToLower().Contains("pressure")) + content.Add(OntologyMapping.GetChromatogramType("pressure")); + else if (channelName.ToLower().Contains("flow")) + content.Add(OntologyMapping.GetChromatogramType("flow")); + + else if (channelName.ToLower().Contains("fid")) + content.Add(OntologyMapping.GetChromatogramType("current")); + else + content.Add(OntologyMapping.GetChromatogramType("unknown")); + } + } } + _rawFile.SelectMsData(); + } + + //write content + foreach (var item in content) + { + SerializeCvParam(item); } _writer.WriteEndElement(); // fileContent @@ -229,27 +262,33 @@ public override void Write(IRawDataPlus rawFile, int firstScanNumber, int lastSc _writer.WriteEndElement(); // sourceFileList _writer.WriteEndElement(); // fileDescription - var instrumentData = _rawFile.GetInstrumentData(); + //default instrument model + var instrumentModel = new CVParamType(); - // ReferenceableParamGroupList - _writer.WriteStartElement("referenceableParamGroupList"); - _writer.WriteAttributeString("count", "1"); - // ReferenceableParamGroup - _writer.WriteStartElement("referenceableParamGroup"); - _writer.WriteAttributeString("id", "commonInstrumentParams"); + if (_rawFile.HasMsData) + { + var instrumentData = _rawFile.GetInstrumentData(); - var instrumentModel = OntologyMapping.getInstrumentModel(instrumentData.Name); - SerializeCvParam(instrumentModel); + // ReferenceableParamGroupList + _writer.WriteStartElement("referenceableParamGroupList"); + _writer.WriteAttributeString("count", "1"); + // ReferenceableParamGroup + _writer.WriteStartElement("referenceableParamGroup"); + _writer.WriteAttributeString("id", "commonInstrumentParams"); - SerializeCvParam(new CVParamType - { - cvRef = "MS", - accession = "MS:1000529", - name = "instrument serial number", - value = instrumentData.SerialNumber - }); - _writer.WriteEndElement(); // referenceableParamGroup - _writer.WriteEndElement(); // referenceableParamGroupList + instrumentModel = OntologyMapping.GetInstrumentModel(instrumentData.Model); + SerializeCvParam(instrumentModel); + + SerializeCvParam(new CVParamType + { + cvRef = "MS", + accession = "MS:1000529", + name = "instrument serial number", + value = instrumentData.SerialNumber + }); + _writer.WriteEndElement(); // referenceableParamGroup + _writer.WriteEndElement(); // referenceableParamGroupList + } // SoftwareList _writer.WriteStartElement("softwareList"); @@ -267,7 +306,20 @@ public override void Write(IRawDataPlus rawFile, int firstScanNumber, int lastSc _writer.WriteEndElement(); // software _writer.WriteEndElement(); // softwareList - PopulateInstrumentConfigurationList(firstScanNumber, lastScanNumber, instrumentModel); + Log.Debug("Populating instrument configurations"); + if (_rawFile.HasMsData) + { + PopulateInstrumentConfigurationList(firstScanNumber, lastScanNumber, instrumentModel); + } + else + { + _writer.WriteStartElement("instrumentConfigurationList"); + _writer.WriteAttributeString("count", "1"); + _writer.WriteStartElement("instrumentConfiguration"); + _writer.WriteAttributeString("id", "IC1"); + _writer.WriteEndElement(); // instrumentConfiguration + _writer.WriteEndElement(); // instrumentConfigurationList + } // DataProcessingList _writer.WriteStartElement("dataProcessingList"); @@ -287,7 +339,7 @@ public override void Write(IRawDataPlus rawFile, int firstScanNumber, int lastSc value = "" }); _writer.WriteEndElement(); // processingMethod - if (ParseInput.NoPeakPicking.Count < ParseInput.AllLevels.Count) + if (_rawFile.HasMsData && ParseInput.NoPeakPicking.Count < ParseInput.AllLevels.Count) { _writer.WriteStartElement("processingMethod"); _writer.WriteAttributeString("order", "1"); @@ -307,78 +359,83 @@ public override void Write(IRawDataPlus rawFile, int firstScanNumber, int lastSc // Run _writer.WriteStartElement("run"); - //TODO: validate id against NCName - _writer.WriteAttributeString("id", ParseInput.RawFileNameWithoutExtension); + _writer.WriteAttributeString("id", GetNCName(ParseInput.RawFileNameWithoutExtension)); _writer.WriteAttributeString("defaultInstrumentConfigurationRef", "IC1"); _writer.WriteAttributeString("startTimeStamp", XmlConvert.ToString(_rawFile.CreationDate, XmlDateTimeSerializationMode.Utc)); _writer.WriteAttributeString("defaultSourceFileRef", SourceFileId); + + //indices + int index = 0; + int lastScanProgress; + // SpectrumList _writer.WriteStartElement("spectrumList"); _writer.WriteAttributeString("count", GetTotalScanNumber()); _writer.WriteAttributeString("defaultDataProcessingRef", "ThermoRawFileParserProcessing"); - serializer = _factory.CreateSerializer(typeof(SpectrumType)); + if (_rawFile.HasMsData) + { + serializer = _factory.CreateSerializer(typeof(SpectrumType)); - // MS Spectra - var index = 0; - var lastScanProgress = 0; + // MS Spectra + index = 0; + lastScanProgress = 0; - Log.Info(String.Format("Processing {0} MS scans", +(1 + lastScanNumber - firstScanNumber))); + Log.Info(String.Format("Processing {0} MS scans", +(1 + lastScanNumber - firstScanNumber))); - for (var scanNumber = firstScanNumber; scanNumber <= lastScanNumber; scanNumber++) - { - if (ParseInput.LogFormat == LogFormat.DEFAULT) + for (var scanNumber = firstScanNumber; scanNumber <= lastScanNumber; scanNumber++) { - var scanProgress = (int) ((double) scanNumber / (lastScanNumber - firstScanNumber + 1) * 100); - if (scanProgress % ProgressPercentageStep == 0) + if (ParseInput.LogFormat == LogFormat.DEFAULT) { - if (scanProgress != lastScanProgress) + var scanProgress = (int)((double)scanNumber / (lastScanNumber - firstScanNumber + 1) * 100); + if (scanProgress % ProgressPercentageStep == 0) { - Console.Write("" + scanProgress + "% "); - lastScanProgress = scanProgress; + if (scanProgress != lastScanProgress) + { + Console.Write("" + scanProgress + "% "); + lastScanProgress = scanProgress; + } } } - } - SpectrumType spectrum = null; + SpectrumType spectrum = null; - try - { - spectrum = ConstructMSSpectrum(scanNumber); - } - catch (Exception ex) - { - Log.Error($"Scan #{scanNumber} cannot be processed because of the following exception: {ex.Message}\n{ex.StackTrace}"); - ParseInput.NewError(); - } + try + { + spectrum = ConstructMSSpectrum(scanNumber); + } + catch (Exception ex) + { + Log.Error($"Scan #{scanNumber} cannot be processed because of the following exception: {ex.Message}\n{ex.StackTrace}"); + ParseInput.NewError(); + } - var level = spectrum != null ? int.Parse(spectrum.cvParam.Where(p => p.accession == "MS:1000511").First().value) : 0; - - if (spectrum != null && ParseInput.MsLevel.Contains(level)) //applying MS level filter - { - spectrum.index = index.ToString(); - if (_doIndexing) + var level = spectrum != null ? int.Parse(spectrum.cvParam.Where(p => p.accession == "MS:1000511").First().value) : 0; + + if (spectrum != null && ParseInput.MsLevel.Contains(level)) //applying MS level filter { - // flush the writers before getting the position - _writer.Flush(); - Writer.Flush(); - if (spectrumOffSets.Count != 0) + spectrum.index = index.ToString(); + if (_doIndexing) { - spectrumOffSets.Add(spectrum.id, Writer.BaseStream.Position + 6 + _osOffset); - } - else - { - spectrumOffSets.Add(spectrum.id, Writer.BaseStream.Position + 7 + _osOffset); + // flush the writers before getting the position + _writer.Flush(); + Writer.Flush(); + if (spectrumOffSets.Count != 0) + { + spectrumOffSets.Add(spectrum.id, Writer.BaseStream.Position + 6 + _osOffset); + } + else + { + spectrumOffSets.Add(spectrum.id, Writer.BaseStream.Position + 7 + _osOffset); + } } - } - Serialize(serializer, spectrum); + Serialize(serializer, spectrum); - Log.Debug("Spectrum added to list of spectra -- ID " + spectrum.id); - - index++; + index++; + } } } @@ -500,7 +557,9 @@ public override void Write(IRawDataPlus rawFile, int firstScanNumber, int lastSc _writer.WriteEndElement(); // chromatogramList } - _writer.WriteEndElement(); // run + _writer.Flush(); + _writer.WriteEndElement(); // run + _writer.Flush(); _writer.WriteEndElement(); // mzML if (_doIndexing) @@ -512,22 +571,26 @@ public override void Write(IRawDataPlus rawFile, int firstScanNumber, int lastSc // IndexList _writer.WriteStartElement("indexList"); - var indexCount = chromatograms.IsNullOrEmpty() ? 1 : 2; + var indexCount = ((spectrumOffSets.Count > 0) ? 1 : 0) + (chromatograms.IsNullOrEmpty() ? 0 : 1); _writer.WriteAttributeString("count", indexCount.ToString()); // Index - _writer.WriteStartElement("index"); - _writer.WriteAttributeString("name", "spectrum"); - var spectrumOffsetEnumerator = spectrumOffSets.GetEnumerator(); - while (spectrumOffsetEnumerator.MoveNext()) - { - // Offset - _writer.WriteStartElement("offset"); - _writer.WriteAttributeString("idRef", spectrumOffsetEnumerator.Key.ToString()); - _writer.WriteString(spectrumOffsetEnumerator.Value.ToString()); - _writer.WriteEndElement(); // offset - } + + if (spectrumOffSets.Count > 0) + { + _writer.WriteStartElement("index"); + _writer.WriteAttributeString("name", "spectrum"); + var spectrumOffsetEnumerator = spectrumOffSets.GetEnumerator(); + while (spectrumOffsetEnumerator.MoveNext()) + { + // Offset + _writer.WriteStartElement("offset"); + _writer.WriteAttributeString("idRef", spectrumOffsetEnumerator.Key.ToString()); + _writer.WriteString(spectrumOffsetEnumerator.Value.ToString()); + _writer.WriteEndElement(); // offset + } - _writer.WriteEndElement(); // index + _writer.WriteEndElement(); // index + } if (!chromatograms.IsNullOrEmpty()) { @@ -587,8 +650,16 @@ public override void Write(IRawDataPlus rawFile, int firstScanNumber, int lastSc if (_doIndexing) { - cryptoStream.Flush(); - cryptoStream.Close(); + try + { + cryptoStream.Flush(); + cryptoStream.Close(); + } + catch (System.ObjectDisposedException e) + { + // Cannot access a closed file. CryptoStream was already closed when closing _writer + Log.Warn($"Warning: {e.Message}"); + } } } @@ -618,27 +689,41 @@ public override void Write(IRawDataPlus rawFile, int firstScanNumber, int lastSc } } + private string GetNCName(string filename) + { + string result = Regex.Replace(filename, @"[^\d\w\.\-]+", "_"); + + if (Regex.IsMatch(result, @"^\d")) + { + result = $"_{result}"; + } + + return result; + } + private string GetTotalScanNumber() { // Save the last selected instrument var lastSelectedInstrument = _rawFile.SelectedInstrument; var numScans = 0; - _rawFile.SelectInstrument(Device.MS, 1); + if (_rawFile.HasMsData) + { + _rawFile.SelectInstrument(Device.MS, 1); - var levelFilter = _rawFile.GetFilterFromString(""); + var levelFilter = _rawFile.GetFilterFromString(""); - foreach (var level in ParseInput.MsLevel) - { - levelFilter.MSOrder = (MSOrderType) level; + foreach (var level in ParseInput.MsLevel) + { + levelFilter.MSOrder = (MSOrderType)level; - var filteredScans = _rawFile.GetFilteredScansListByScanRange(levelFilter, - _rawFile.RunHeader.FirstSpectrum, _rawFile.RunHeader.LastSpectrum); + var filteredScans = _rawFile.GetFilteredScansListByScanRange(levelFilter, + _rawFile.RunHeader.FirstSpectrum, _rawFile.RunHeader.LastSpectrum); - numScans += filteredScans.Count; + numScans += filteredScans.Count; + } } - if (ParseInput.AllDetectors) { for (int nrI = 1; nrI < _rawFile.GetInstrumentCountOfType(Device.Pda) + 1; nrI++) @@ -649,7 +734,7 @@ private string GetTotalScanNumber() } // Return instrument to last selected one - if (lastSelectedInstrument != null) + if (lastSelectedInstrument.InstrumentIndex >= 1) _rawFile.SelectInstrument(lastSelectedInstrument.DeviceType, lastSelectedInstrument.InstrumentIndex); return numScans.ToString(); @@ -664,11 +749,8 @@ private string GetTotalScanNumber() private void PopulateInstrumentConfigurationList(int firstScanNumber, int lastScanNumber, CVParamType instrumentModel) { - // Go over the first scans until an MS2 scan is encountered - // to collect all mass analyzer and ionization types - var encounteredMs2 = false; - var scanNumber = firstScanNumber; - do + // Go over scan filters to collect all mass analyzer and ionization types + for (int scanNumber = firstScanNumber; scanNumber <= lastScanNumber; scanNumber++) { // Get the scan filter for this scan number try @@ -705,10 +787,6 @@ private void PopulateInstrumentConfigurationList(int firstScanNumber, int lastSc _massAnalyzers.Add(scanFilter.MassAnalyzer, "IC" + (_massAnalyzers.Count + 1)); } - if (scanFilter.MSOrder == MSOrderType.Ms2) - { - encounteredMs2 = true; - } } catch (Exception) { @@ -724,8 +802,7 @@ private void PopulateInstrumentConfigurationList(int firstScanNumber, int lastSc } } - scanNumber++; - } while (!encounteredMs2 && scanNumber <= lastScanNumber); + } // Add a default analyzer if none were found if (_massAnalyzers.Count == 0) @@ -835,45 +912,53 @@ private List ConstructChromatograms(int firstScanNumber, int l { var chromatograms = new List(); - // MS chromatograms - // Reselect MS device - _rawFile.SelectInstrument(Device.MS, 1); - // Define the settings for getting the Base Peak chromatogram - var settings = new ChromatogramTraceSettings(TraceType.BasePeak); + //common variables + ChromatogramTraceSettings settings; + IChromatogramData data; + ChromatogramSignal[] trace; - // Get the chromatogram from the RAW file. - var data = _rawFile.GetChromatogramData(new IChromatogramSettings[] {settings}, -1, -1); + if (_rawFile.HasMsData) + { + // MS chromatograms + // Reselect MS device + _rawFile.SelectInstrument(Device.MS, 1); + // Define the settings for getting the Base Peak chromatogram + settings = new ChromatogramTraceSettings(TraceType.BasePeak); - // Split the data into the chromatograms - var trace = ChromatogramSignal.FromChromatogramData(data); + // Get the chromatogram from the RAW file. + data = _rawFile.GetChromatogramData(new IChromatogramSettings[] { settings }, -1, -1); - for (var i = 0; i < trace.Length; i++) - { - if (trace[i].Length > 0) + // Split the data into the chromatograms + trace = ChromatogramSignal.FromChromatogramData(data); + + for (var i = 0; i < trace.Length; i++) { - // CV Data for Base Peak Chromatogram - var chroType = new CVParamType + if (trace[i].Length > 0) { - accession = "MS:1000628", - name = "basepeak chromatogram", - cvRef = "MS", - value = "" - }; + // CV Data for Base Peak Chromatogram + var chroType = new CVParamType + { + accession = "MS:1000628", + name = "basepeak chromatogram", + cvRef = "MS", + value = "" + }; - var intensType = new CVParamType - { - accession = "MS:1000515", - name = "intensity array", - cvRef = "MS", - unitName = "number of counts", - value = "", - unitCvRef = "MS", - unitAccession = "MS:1000131" - }; + var intensType = new CVParamType + { + accession = "MS:1000515", + name = "intensity array", + cvRef = "MS", + unitName = "number of counts", + value = "", + unitCvRef = "MS", + unitAccession = "MS:1000131" + }; - var chromatogram = TraceToChromatogram(trace[i], "BasePeak_" + i.ToString(), chroType, intensType); + var chromatogram = TraceToChromatogram(trace[i], "BasePeak_" + i.ToString(), chroType, intensType); - chromatograms.Add(chromatogram); + chromatograms.Add(chromatogram); + } } } @@ -895,24 +980,9 @@ private List ConstructChromatograms(int firstScanNumber, int l for (var i = 0; i < trace.Length; i++) { // CV Data for Total Absorbance Chromatogram - var chroType = new CVParamType - { - accession = "MS:1000812", - name = "absorption chromatogram", - cvRef = "MS", - value = "" - }; - - var intensType = new CVParamType - { - accession = "MS:1000515", - name = "intensity array", - cvRef = "MS", - unitName = "absorbance unit", - value = instData.Units.ToString(), - unitCvRef = "UO", - unitAccession = "UO:0000269" - }; + var chroType = OntologyMapping.GetChromatogramType("absorption"); + var intensType = OntologyMapping.GetDataArrayType("absorption"); + intensType.value = instData.Units.ToString(); var chromatogram = TraceToChromatogram(trace[i], String.Format("PDA#{0}_TotalAbsorbance_{1}", nrI, i), @@ -941,25 +1011,10 @@ private List ConstructChromatograms(int firstScanNumber, int l for (var i = 0; i < trace.Length; i++) { // CV Data for Absorbance Chromatogram - var chroType = new CVParamType - { - accession = "MS:1000812", - name = "absorption chromatogram", - cvRef = "MS", - value = "" - }; - - var intensType = new CVParamType - { - accession = "MS:1000515", - name = "intensity array", - cvRef = "MS", - unitName = "absorbance unit", - value = instData.Units.ToString(), - unitCvRef = "UO", - unitAccession = "UO:0000269" - }; - + var chroType = OntologyMapping.GetChromatogramType("absorption"); + var intensType = OntologyMapping.GetDataArrayType("absorption"); + intensType.value = instData.Units.ToString(); + var chromatogram = TraceToChromatogram(trace[i], String.Format("UV#{0}_{1}_{2}", nrI, channelName, i), chroType, intensType); @@ -969,49 +1024,53 @@ private List ConstructChromatograms(int firstScanNumber, int l } } - for (int nrI = 1; nrI < _rawFile.GetInstrumentCountOfType(Device.Analog) + 1; nrI++) + //Chromatograms from (MS)Analog devices: Pressure, FID, etc + foreach (var deviceType in new Device[2] { Device.Analog, Device.MSAnalog }) { - _rawFile.SelectInstrument(Device.Analog, nrI); - - var instData = _rawFile.GetInstrumentData(); - - for (int channel = 0; channel < instData.ChannelLabels.Length; channel++) + var channelNameIndex = 0; + for (int nrI = 1; nrI < _rawFile.GetInstrumentCountOfType(deviceType) + 1; nrI++) { - var channelName = instData.ChannelLabels[channel]; + _rawFile.SelectInstrument(deviceType, nrI); - if (channelName.ToLower().Contains("pressure")) - { - settings = new ChromatogramTraceSettings(TraceType.StartPCA2DChromatogramTraces + channel + - 1); + var instData = _rawFile.GetInstrumentData(); - data = _rawFile.GetChromatogramData(new IChromatogramSettings[] {settings}, -1, -1); + for (int channel = 0; channel < instData.ChannelLabels.Length; channel++) + { + var channelName = instData.ChannelLabels[channel]; + if (channelName.IsNullOrEmpty()) + { + channelName = $"Channel{channelNameIndex++}"; + } + settings = new ChromatogramTraceSettings(TraceType.StartAnalogChromatogramTraces + channel + 1); + data = _rawFile.GetChromatogramData(new IChromatogramSettings[] { settings }, -1, -1); trace = ChromatogramSignal.FromChromatogramData(data); for (var i = 0; i < trace.Length; i++) { - // CV Data for Absorbance Chromatogram - var chroType = new CVParamType + //Default data type + var chroType = OntologyMapping.GetChromatogramType("unknown"); + var intensType = OntologyMapping.GetDataArrayType("unknown"); + + if (channelName.ToLower().Contains("pressure")) { - accession = "MS:1003019", - name = "pressure chromatogram", - cvRef = "MS", - value = "" - }; - - var intensType = new CVParamType + chroType = OntologyMapping.GetChromatogramType("pressure"); + intensType = OntologyMapping.GetDataArrayType("pressure"); + } + else if (channelName.ToLower().Contains("flow")) { - accession = "MS:1000821", - name = "pressure array", - cvRef = "MS", - unitName = "pressure unit", - value = "", - unitCvRef = "UO", - unitAccession = "UO:0000109" - }; + chroType = OntologyMapping.GetChromatogramType("flow"); + intensType = OntologyMapping.GetDataArrayType("flow"); + } + else if (channelName.ToLower().Contains("fid")) + { + //FID is ion current type + chroType = OntologyMapping.GetChromatogramType("current"); + intensType = OntologyMapping.GetDataArrayType("intensity"); + } var chromatogram = TraceToChromatogram(trace[i], - String.Format("AD#{0}_{1}_{2}", nrI, channelName, i), + String.Format("{0}#{1}_{2}_{3}", deviceType.ToString(), nrI, channelName.Replace(" ", "_"), i), chroType, intensType); chromatograms.Add(chromatogram); @@ -1019,6 +1078,7 @@ private List ConstructChromatograms(int firstScanNumber, int l } } } + } return chromatograms; @@ -1062,16 +1122,7 @@ private ChromatogramType TraceToChromatogram(ChromatogramSignal trace, string ch .binary.Length / 3)).ToString(CultureInfo.InvariantCulture); var timesBinaryDataCvParams = new List { - new CVParamType - { - accession = "MS:1000595", - name = "time array", - cvRef = "MS", - unitName = "minute", - value = "", - unitCvRef = "UO", - unitAccession = "UO:0000031" - }, + OntologyMapping.GetDataArrayType("time"), new CVParamType { accession = "MS:1000523", name = "64-bit float", cvRef = "MS", value = "" @@ -1312,61 +1363,52 @@ private SpectrumType ConstructMSSpectrum(int scanNumber) _precursorScanNumber = GetParentFromScanString(result.Groups[1].Value); } - if (_precursorScanNumber > 0) + //finding precursor scan failed + if (_precursorScanNumber == -2) { + Log.Warn($"Cannot find precursor scan for scan# {scanNumber}"); + _precursorTree[-2] = new PrecursorInfo(0, msLevel, FindLastReaction(scanEvent, msLevel), new PrecursorType[0]); + } - try + try + { + try //since there is no direct way to get the number of reactions available, it is necessary to try and fail + { + scanEvent.GetReaction(_precursorTree[_precursorScanNumber].ReactionCount); + } + catch (ArgumentOutOfRangeException ex) { - try //since there is no direct way to get the number of reactions available, it is necessary to try and fail + Log.Debug($"Using Tribrid decision tree fix for scan# {scanNumber}"); + //Is it a decision tree scheduled scan on tribrid? + if (msLevel == _precursorTree[_precursorScanNumber].MSLevel) { - scanEvent.GetReaction(_precursorTree[_precursorScanNumber].ReactionCount); + _precursorScanNumber = GetParentFromScanString(result.Groups[1].Value); } - catch (ArgumentOutOfRangeException ex) + else { - Log.Debug($"Using Tribrid decision tree fix for scan# {scanNumber}"); - //Is it a decision tree scheduled scan on tribrid? - if (msLevel == _precursorTree[_precursorScanNumber].MSLevel) - { - _precursorScanNumber = GetParentFromScanString(result.Groups[1].Value); - } - else - { - throw new RawFileParserException( - $"Tribrid decision tree fix failed - cannot get reaction# {_precursorTree[_precursorScanNumber].ReactionCount} from {scanEvent.ToString()}", - ex); - } + throw new RawFileParserException( + $"Tribrid decision tree fix failed - cannot get reaction# {_precursorTree[_precursorScanNumber].ReactionCount} from {scanEvent.ToString()}", + ex); } - - // Construct and set the precursor list element of the spectrum - spectrum.precursorList = - ConstructPrecursorList(_precursorScanNumber, scanEvent, charge, monoisotopicMz, isolationWidth, - SPSMasses, out var reactionCount); - - //save precursor information for later reference - _precursorTree[scanNumber] = new PrecursorInfo(_precursorScanNumber, msLevel, reactionCount, spectrum.precursorList.precursor); } - catch (Exception e) - { - var extra = (e.InnerException is null) ? "" : $"\n{e.InnerException.StackTrace}"; - Log.Warn($"Failed creating precursor list for scan# {scanNumber} - precursor information for this and dependent scans will be empty\nException details:{e.Message}\n{e.StackTrace}\n{extra}"); - ParseInput.NewWarn(); + // Construct and set the precursor list element of the spectrum + spectrum.precursorList = + ConstructPrecursorList(_precursorScanNumber, scanEvent, charge, monoisotopicMz, isolationWidth, + SPSMasses, out var reactionCount); - _precursorTree[scanNumber] = new PrecursorInfo(_precursorScanNumber, 1, 0, new PrecursorType[0]); - - } - + //save precursor information for later reference + _precursorTree[scanNumber] = new PrecursorInfo(_precursorScanNumber, msLevel, reactionCount, spectrum.precursorList.precursor); } - else + catch (Exception e) { - spectrum.precursorList = new PrecursorListType - { - count = "0", - precursor = new PrecursorType[0] - }; + var extra = (e.InnerException is null) ? "" : $"\n{e.InnerException.StackTrace}"; + + Log.Warn($"Failed creating precursor list for scan# {scanNumber} - precursor information for this and dependent scans will be empty\nException details:{e.Message}\n{e.StackTrace}\n{extra}"); + ParseInput.NewWarn(); + + _precursorTree[scanNumber] = new PrecursorInfo(_precursorScanNumber, 1, 0, new PrecursorType[0]); - Log.Error($"Failed finding precursor for {scanNumber}"); - ParseInput.NewError(); } } else @@ -1891,6 +1933,45 @@ private SpectrumType ConstructMSSpectrum(int scanNumber) return spectrum; } + private int FindLastReaction(IScanEvent scanEvent, int msLevel) + { + int lastReactionIndex = msLevel - 2; + + //iteratively trying find the last available index for reaction + while(true) + { + try + { + scanEvent.GetReaction(lastReactionIndex + 1); + } + catch (ArgumentOutOfRangeException) + { + //stop trying + break; + } + + lastReactionIndex++; + } + + //supplemental activation flag is on -> one of the levels (not necissirily the last one) used supplemental activation + //check last two activations + if (scanEvent.SupplementalActivation == TriState.On) + { + var lastActivation = scanEvent.GetReaction(lastReactionIndex).ActivationType; + var beforeLastActivation = scanEvent.GetReaction(lastReactionIndex - 1).ActivationType; + + if ((beforeLastActivation == ActivationType.ElectronTransferDissociation || beforeLastActivation == ActivationType.ElectronCaptureDissociation) && + (lastActivation == ActivationType.CollisionInducedDissociation || lastActivation == ActivationType.HigherEnergyCollisionalDissociation)) + return lastReactionIndex - 1; //ETD or ECD followed by HCD or CID -> supplemental activation in the last level (move the last reaction one step back) + else + return lastReactionIndex; + } + else //just use the last one + { + return lastReactionIndex; + } + } + private SpectrumType ConstructPDASpectrum(int scanNumber, int instrumentNumber) { // Get each scan from the RAW file @@ -2153,20 +2234,25 @@ private PrecursorListType ConstructPrecursorList(int precursorScanNumber, IScanE // Get precursors from earlier levels var prevPrecursors = _precursorTree[precursorScanNumber]; - var spectrumRef = ""; + string spectrumRef = null; int msLevel = (int)scanEvent.MSOrder; IReaction reaction = null; var precursorMz = 0.0; reactionCount = prevPrecursors.ReactionCount; - spectrumRef = ConstructSpectrumTitle((int)Device.MS, 1, precursorScanNumber); reaction = scanEvent.GetReaction(reactionCount); - - precursorMz = reaction.PrecursorMass; //if isolation width was not found in the trailer, try to get one from the reaction if (isolationWidth == null) isolationWidth = reaction.IsolationWidth; - + if (isolationWidth < 0) isolationWidth = null; + + precursorMz = reaction.PrecursorMass; + + if (precursorScanNumber > 0) + { + spectrumRef = ConstructSpectrumTitle((int)Device.MS, 1, precursorScanNumber); + } + var precursor = new PrecursorType { selectedIonList = @@ -2203,7 +2289,7 @@ private PrecursorListType ConstructPrecursorList(int precursorScanNumber, IScanE }); } - if (selectedIonMz > ZeroDelta) + if (selectedIonMz > ZeroDelta && precursorScanNumber > 0) { var selectedIonIntensity = CalculatePrecursorPeakIntensity(_rawFile, precursorScanNumber, reaction.PrecursorMass, isolationWidth, ParseInput.NoPeakPicking.Contains(msLevel - 1)); @@ -2384,6 +2470,51 @@ private PrecursorListType ConstructPrecursorList(int precursorScanNumber, IScanE spectrumRef = spectrumRef }; + //Isolation window for SPS masses is the same as for the first precursor + SPSPrecursor.isolationWindow = + new ParamGroupType + { + cvParam = new CVParamType[3] + }; + + SPSPrecursor.isolationWindow.cvParam[0] = + new CVParamType + { + accession = "MS:1000827", + name = "isolation window target m/z", + value = SPSMasses[n].ToString(CultureInfo.InvariantCulture), + cvRef = "MS", + unitCvRef = "MS", + unitAccession = "MS:1000040", + unitName = "m/z" + }; + if (isolationWidth != null) + { + var offset = isolationWidth.Value / 2 + reaction.IsolationWidthOffset; + SPSPrecursor.isolationWindow.cvParam[1] = + new CVParamType + { + accession = "MS:1000828", + name = "isolation window lower offset", + value = (isolationWidth.Value - offset).ToString(CultureInfo.InvariantCulture), + cvRef = "MS", + unitCvRef = "MS", + unitAccession = "MS:1000040", + unitName = "m/z" + }; + SPSPrecursor.isolationWindow.cvParam[2] = + new CVParamType + { + accession = "MS:1000829", + name = "isolation window upper offset", + value = offset.ToString(CultureInfo.InvariantCulture), + cvRef = "MS", + unitCvRef = "MS", + unitAccession = "MS:1000040", + unitName = "m/z" + }; + } + // Selected ion MZ only SPSPrecursor.selectedIonList.selectedIon[0] = new ParamGroupType @@ -2426,8 +2557,7 @@ private PrecursorListType ConstructPrecursorList(int precursorScanNumber, IScanE private int GetParentFromScanString(string scanString) { - var result = _filterStringIsolationMzPattern.Match(scanString); - var parts = Regex.Split(result.Groups[1].Value, " "); + var parts = Regex.Split(scanString, " "); //find the position of the first (from the end) precursor with a different mass //to account for possible supplementary activations written in the filter @@ -2445,7 +2575,7 @@ private int GetParentFromScanString(string scanString) return _precursorScanNumbers[parentFilter]; } - return -1; //unsuccessful parsing + return -2; //unsuccessful parsing } /// diff --git a/Writer/OntologyMapping.cs b/Writer/OntologyMapping.cs index 35f78d2..bece09f 100644 --- a/Writer/OntologyMapping.cs +++ b/Writer/OntologyMapping.cs @@ -3,6 +3,7 @@ using ThermoFisher.CommonCore.Data; using ThermoFisher.CommonCore.Data.FilterEnums; using ThermoRawFileParser.Writer.MzML; +using ThermoRawFileParser.Util; namespace ThermoRawFileParser.Writer { @@ -68,6 +69,15 @@ public static class OntologyMapping value = "" } }, + { + MassAnalyzerType.MassAnalyzerASTMS, new CVParamType + { + accession = "MS:1003379", + name = "asymmetric track lossless time-of-flight analyzer", + cvRef = "MS", + value = "" + } + }, { MassAnalyzerType.Any, new CVParamType { @@ -543,6 +553,15 @@ public static class OntologyMapping value = "" } }, + { + "ORBITRAP ASCEND", new CVParamType + { + accession = "MS:1003356", + name = "Orbitrap Ascend", + cvRef = "MS", + value = "" + } + }, { "ORBITRAP EXPLORIS 120", new CVParamType { @@ -570,6 +589,15 @@ public static class OntologyMapping value = "" } }, + { + "ORBITRAP ASTRAL", new CVParamType + { + accession = "MS:1003378", + name = "Orbitrap Astral", + cvRef = "MS", + value = "" + } + }, { "EXACTIVE", new CVParamType { @@ -658,7 +686,7 @@ public static class OntologyMapping /// /// the instrument name /// the instrument CV param - public static CVParamType getInstrumentModel(string instrumentName) + public static CVParamType GetInstrumentModel(string instrumentName) { CVParamType instrumentModel; instrumentName = instrumentName.ToUpper(); @@ -730,6 +758,8 @@ public static List GetDetectors(string instrumentAccession) case "MS:1002732": // ORBITRAP ECLIPSE case "MS:1003029": + // ORBITRAP ASCEND + case "MS:1003356": // ORBITRAP ID-X case "MS:1003112": detectors = new List @@ -768,6 +798,8 @@ public static List GetDetectors(string instrumentAccession) case "MS:1003094": // ORBITRAP EXPLORIS 480 case "MS:1003028": + // ORBITRAP ASTRAL + case "MS:1003378": detectors = new List { new CVParamType @@ -820,5 +852,208 @@ public static List GetDetectors(string instrumentAccession) return detectors; } + + private static readonly Dictionary chromatogramTypes = + new Dictionary + { + { + "basepeak", new CVParamType + { + accession = "MS:1000628", + name = "basepeak chromatogram", + cvRef = "MS", + value = "" + } + }, + + { + "tic", new CVParamType + { + accession = "MS:1000235", + name = "total ion current chromatogram", + cvRef = "MS", + value = "" + } + }, + + { + "current", new CVParamType + { + accession = "MS:1000810", + name = "ion current chromatogram", + cvRef = "MS", + value = "" + } + }, + + { + "radiation", new CVParamType + { + accession = "MS:1000811", + name = "electromagnetic radiation chromatogram", + cvRef = "MS", + value = "" + } + }, + + { + "absorption", new CVParamType + { + accession = "MS:1000812", + name = "absorption chromatogram", + cvRef = "MS", + value = "" + } + }, + + { + "emission", new CVParamType + { + accession = "MS:1000813", + name = "emission chromatogram", + cvRef = "MS", + value = "" + } + }, + + { + "pressure", new CVParamType + { + accession = "MS:1003019", + name = "pressure chromatogram", + cvRef = "MS", + value = "" + } + }, + + { + "flow", new CVParamType + { + accession = "MS:1003020", + name = "flow rate chromatogram", + cvRef = "MS", + value = "" + } + }, + + { + "unknown", new CVParamType + { + accession = "MS:1000626", + name = "chromatogram type", + cvRef = "MS", + value = "" + } + }, + }; + + public static CVParamType GetChromatogramType(string key) + { + return CVHelpers.Copy(chromatogramTypes[key]); + } + + private static readonly Dictionary dataArrayTypes = + new Dictionary + { + { + "mz", new CVParamType + { + accession = "MS:1000514", + name = "m/z array", + cvRef = "MS", + value = "" + } + }, + + { + "intensity", new CVParamType + { + accession = "MS:1000515", + name = "intensity array", + cvRef = "MS", + value = "" + } + }, + + { + "absorption", new CVParamType + { + accession = "MS:1000515", + name = "intensity array", + cvRef = "MS", + value = "", + unitName = "absorbance unit", + unitCvRef = "UO", + unitAccession = "UO:0000269" + } + }, + + { + "time", new CVParamType + { + accession = "MS:1000595", + name = "time array", + cvRef = "MS", + value = "", + unitName = "minute", + unitCvRef = "UO", + unitAccession = "UO:0000031" + } + }, + + { + "wavelength", new CVParamType + { + accession = "MS:1000617", + name = "wavelength array", + cvRef = "MS", + value = "" + } + }, + + { + "flow", new CVParamType + { + accession = "MS:1000820", + name = "flow rate array", + cvRef = "MS", + value = "", + unitName = "volumetric flow rate unit", + unitCvRef = "UO", + unitAccession = "UO:0000270 " + } + }, + + { + "pressure", new CVParamType + { + accession = "MS:1000821", + name = "pressure array", + cvRef = "MS", + value = "", + unitName = "pressure unit", + unitCvRef = "UO", + unitAccession = "UO:0000109" + } + }, + + { + "unknown", new CVParamType + { + accession = "MS:1000786", + name = "non-standard data array", + cvRef = "MS", + value = "", + unitName = "unit", + unitCvRef = "UO", + unitAccession = "UO:0000000" + } + } + }; + + public static CVParamType GetDataArrayType(string key) + { + return CVHelpers.Copy(dataArrayTypes[key]); + } } } \ No newline at end of file diff --git a/Writer/ParquetSpectrumWriter.cs b/Writer/ParquetSpectrumWriter.cs index ced94be..6ea4071 100644 --- a/Writer/ParquetSpectrumWriter.cs +++ b/Writer/ParquetSpectrumWriter.cs @@ -35,8 +35,15 @@ public ParquetSpectrumWriter(ParseInput parseInput) : base(parseInput) public override void Write(IRawDataPlus rawFile, int firstScanNumber, int lastScanNumber) { _rawFile = rawFile; - List pScans = new List(); - WritePScans(ParseInput.OutputDirectory, rawFile.FileName, rawFile, pScans); + if (rawFile.HasMsData) + { + List pScans = new List(); + WritePScans(ParseInput.OutputDirectory, rawFile.FileName, rawFile, pScans); + } + else + { + throw new RawFileParserException("No MS data in RAW file, no output will be produced"); + } } private static void WritePScans(string outputDirectory, string fileName, diff --git a/Writer/PrecursorInfo.cs b/Writer/PrecursorInfo.cs index 2189369..535f9ee 100644 --- a/Writer/PrecursorInfo.cs +++ b/Writer/PrecursorInfo.cs @@ -5,7 +5,7 @@ /// public class PrecursorInfo { - //for future use + //Current MSLevel public int MSLevel { get; } //precursor scan number, 0 - means not a precursor diff --git a/packages.config b/packages.config index 010dc8f..2bfb52b 100644 --- a/packages.config +++ b/packages.config @@ -27,7 +27,7 @@ - - + + \ No newline at end of file diff --git a/packages/ThermoFisher.CommonCore.Data.5.0.0.88/ThermoFisher.CommonCore.Data.5.0.0.88.nupkg b/packages/ThermoFisher.CommonCore.Data.5.0.0.88/ThermoFisher.CommonCore.Data.5.0.0.88.nupkg deleted file mode 100644 index e7660e5..0000000 Binary files a/packages/ThermoFisher.CommonCore.Data.5.0.0.88/ThermoFisher.CommonCore.Data.5.0.0.88.nupkg and /dev/null differ diff --git a/packages/ThermoFisher.CommonCore.Data.5.0.0.88/lib/ThermoFisher.CommonCore.Data.dll b/packages/ThermoFisher.CommonCore.Data.5.0.0.88/lib/ThermoFisher.CommonCore.Data.dll deleted file mode 100644 index 1ed8566..0000000 Binary files a/packages/ThermoFisher.CommonCore.Data.5.0.0.88/lib/ThermoFisher.CommonCore.Data.dll and /dev/null differ diff --git a/packages/ThermoFisher.CommonCore.Data.5.0.0.93/ThermoFisher.CommonCore.Data.5.0.0.93.nupkg b/packages/ThermoFisher.CommonCore.Data.5.0.0.93/ThermoFisher.CommonCore.Data.5.0.0.93.nupkg new file mode 100644 index 0000000..48aa0e8 Binary files /dev/null and b/packages/ThermoFisher.CommonCore.Data.5.0.0.93/ThermoFisher.CommonCore.Data.5.0.0.93.nupkg differ diff --git a/packages/ThermoFisher.CommonCore.Data.5.0.0.93/lib/netstandard2.0/ThermoFisher.CommonCore.Data.dll b/packages/ThermoFisher.CommonCore.Data.5.0.0.93/lib/netstandard2.0/ThermoFisher.CommonCore.Data.dll new file mode 100644 index 0000000..c21eee4 Binary files /dev/null and b/packages/ThermoFisher.CommonCore.Data.5.0.0.93/lib/netstandard2.0/ThermoFisher.CommonCore.Data.dll differ diff --git a/packages/ThermoFisher.CommonCore.Data.5.0.0.88/lib/ThermoFisher.CommonCore.Data.xml b/packages/ThermoFisher.CommonCore.Data.5.0.0.93/lib/netstandard2.0/ThermoFisher.CommonCore.Data.xml similarity index 99% rename from packages/ThermoFisher.CommonCore.Data.5.0.0.88/lib/ThermoFisher.CommonCore.Data.xml rename to packages/ThermoFisher.CommonCore.Data.5.0.0.93/lib/netstandard2.0/ThermoFisher.CommonCore.Data.xml index a83161d..ff68fe1 100644 --- a/packages/ThermoFisher.CommonCore.Data.5.0.0.88/lib/ThermoFisher.CommonCore.Data.xml +++ b/packages/ThermoFisher.CommonCore.Data.5.0.0.93/lib/netstandard2.0/ThermoFisher.CommonCore.Data.xml @@ -11287,7 +11287,7 @@ - The subtract profile segments. + subtract profile data, with segmented scans The identical flag. @@ -18228,9 +18228,10 @@ Match any type - + - MultiReflection Time of Flight + Asymmetric Track Lossless (ASTRAL) + AS T diff --git a/packages/ThermoFisher.CommonCore.RawFileReader.5.0.0.88/ThermoFisher.CommonCore.RawFileReader.5.0.0.88.nupkg b/packages/ThermoFisher.CommonCore.RawFileReader.5.0.0.88/ThermoFisher.CommonCore.RawFileReader.5.0.0.88.nupkg deleted file mode 100644 index c36275c..0000000 Binary files a/packages/ThermoFisher.CommonCore.RawFileReader.5.0.0.88/ThermoFisher.CommonCore.RawFileReader.5.0.0.88.nupkg and /dev/null differ diff --git a/packages/ThermoFisher.CommonCore.RawFileReader.5.0.0.88/lib/ThermoFisher.CommonCore.RawFileReader.dll b/packages/ThermoFisher.CommonCore.RawFileReader.5.0.0.88/lib/ThermoFisher.CommonCore.RawFileReader.dll deleted file mode 100644 index f84548a..0000000 Binary files a/packages/ThermoFisher.CommonCore.RawFileReader.5.0.0.88/lib/ThermoFisher.CommonCore.RawFileReader.dll and /dev/null differ diff --git a/packages/ThermoFisher.CommonCore.RawFileReader.5.0.0.93/ThermoFisher.CommonCore.RawFileReader.5.0.0.93.nupkg b/packages/ThermoFisher.CommonCore.RawFileReader.5.0.0.93/ThermoFisher.CommonCore.RawFileReader.5.0.0.93.nupkg new file mode 100644 index 0000000..f9f427c Binary files /dev/null and b/packages/ThermoFisher.CommonCore.RawFileReader.5.0.0.93/ThermoFisher.CommonCore.RawFileReader.5.0.0.93.nupkg differ diff --git a/packages/ThermoFisher.CommonCore.RawFileReader.5.0.0.93/lib/netstandard2.0/ThermoFisher.CommonCore.RawFileReader.dll b/packages/ThermoFisher.CommonCore.RawFileReader.5.0.0.93/lib/netstandard2.0/ThermoFisher.CommonCore.RawFileReader.dll new file mode 100644 index 0000000..841bd0d Binary files /dev/null and b/packages/ThermoFisher.CommonCore.RawFileReader.5.0.0.93/lib/netstandard2.0/ThermoFisher.CommonCore.RawFileReader.dll differ diff --git a/packages/ThermoFisher.CommonCore.RawFileReader.5.0.0.88/lib/ThermoFisher.CommonCore.RawFileReader.xml b/packages/ThermoFisher.CommonCore.RawFileReader.5.0.0.93/lib/netstandard2.0/ThermoFisher.CommonCore.RawFileReader.xml similarity index 97% rename from packages/ThermoFisher.CommonCore.RawFileReader.5.0.0.88/lib/ThermoFisher.CommonCore.RawFileReader.xml rename to packages/ThermoFisher.CommonCore.RawFileReader.5.0.0.93/lib/netstandard2.0/ThermoFisher.CommonCore.RawFileReader.xml index 4089a49..138f0dd 100644 --- a/packages/ThermoFisher.CommonCore.RawFileReader.5.0.0.88/lib/ThermoFisher.CommonCore.RawFileReader.xml +++ b/packages/ThermoFisher.CommonCore.RawFileReader.5.0.0.93/lib/netstandard2.0/ThermoFisher.CommonCore.RawFileReader.xml @@ -1136,7 +1136,7 @@ Data for a particular device, from an instrument method. - + Opens a stream on created storage @@ -1144,7 +1144,7 @@ The stream within the device Access to the requested stream - + get stream names. @@ -1167,7 +1167,7 @@ Other streams (private to the instrument) may also be created. - + Open the streams for the device, and retrieve the text description. @@ -1199,14 +1199,6 @@ Gets the error message. - - - Get the list of storage names, of a particular storage type - - Storage to open - Type of storage - The names of the storages - The file header errors. @@ -2769,9 +2761,10 @@ Any analyzer. - + - MultiReflection Time of Flight + Asymmetric Track Lossless (ASTRAL) + AS T @@ -9251,11 +9244,6 @@ Contains factories to read various Xcalibur data system files. - - - The native methods, pulled from OLE 32 DLL. - - The stream seek. @@ -9372,214 +9360,6 @@ therefore the method reduces time and resources used in an allocation and free operation. - - - IOleStorage interface. - - - - - create OLE stream. - - - The stream name. - - - The storage mode. - - - The reserved 1. - - - The reserved 2. - - - The . - - - - - open a stream. - - - The stream name. - - - The reserved 1. - - - The mode. - - - The reserved 2. - - - The . - - - - - create a storage. - - - The name. - - - The mode. - - - The reserved 1. - - - The reserved 2. - - - The . - - - - - Opens an existing storage object with the specified name according to - the specified access mode. The name must not exceed 31 characters - in length (not including the string terminator). - The 000 through 01f characters, serving as the - first character of the stream/storage name, are reserved for use by OLE. - This is a compound file restriction, not a structured storage restriction. - - - A pointer to a wide character null-terminated Unicode string that - contains the name of the storage object to open. - The 000 through 01f characters, serving as the first character - of the stream/storage name, are reserved for use by OLE. - This is a compound file restriction, not a structured storage restriction. - It is ignored if pstgPriority is non-NULL. - - - Priority Must be NULL. A non-NULL value will return STG_E_INVALIDPARAMETER. - - - Specifies the access mode to use when opening the storage object. For descriptions of the possible values, see STGM Constants. Other modes you choose must at least specify STGM_SHARE_EXCLUSIVE when calling this method. - - - Exclude Must be NULL. A non-NULL value will return STG_E_INVALIDPARAMETER. - - - Reserved for future use; must be zero. - - - The . - - - - - The CopyTo method copies the entire contents of an open storage object to another storage object. - - The number of elements in the array pointed to by rgiidExclude. - If rgiidExclude is NULL, then ciidExclude is ignored. - An array of interface identifiers (IIDs) that either the caller - knows about and does not want copied or that the storage object does not support, - but whose state the caller will later explicitly copy. The array can include IStorage, - indicating that only stream objects are to be copied, and IStream, indicating that only storage - objects are to be copied. An array length of zero indicates that only the state exposed by the IStorage - object is to be copied; all other interfaces on the object are to be ignored. - Passing NULL indicates that all interfaces on the object are to be copied. - A string name block (refer to SNB) that specifies a block of storage - or stream objects that are not to be copied to the destination. These elements are not created at the destination. - If IID_IStorage is in the rgiidExclude array, this parameter is ignored. This parameter may be NULL. - A pointer to the open storage object into which this storage object is to be copied. - The destination storage object can be a different implementation of the IStorage interface from the source storage object. - Thus, IStorage::CopyTo can use only publicly available methods of the destination storage object. - If pstgDest is open in transacted mode, it can be reverted by calling its IStorage::Revert method. - - - - The MoveElementTo method copies or moves a sub-storage or stream from this - storage object to another storage object. - - Pointer to a wide character null-terminated Unicode string that contains the name of the element - in this storage object to be moved or copied. - IStorage pointer to the destination storage object. - Pointer to a wide character null-terminated unicode string that contains the new name for the element in its new storage object. - Specifies whether the operation should be a move (STGMOVE_MOVE) or a copy (STGMOVE_COPY). See the STGMOVE enumeration. - - - - The Commit method ensures that any changes made to a storage object open - in transacted mode are reflected in the parent storage. - For non-root storage objects in direct mode, - this method has no effect. For a root storage, it reflects the changes - in the actual device; for example, a file on disk. For a root storage object opened - in direct mode, always call the IStorage::Commit method prior to Release. - IStorage::Commit flushes all memory buffers to the disk for a root storage - in direct mode and will return an error code upon failure. Although Release - also flushes memory buffers to disk, it has no capacity to return any error - codes upon failure. Therefore, calling - Release without first calling Commit causes indeterminate results. - - Controls how the changes are committed to the storage object. - See the STGC enumeration for a definition of these values. - - - - The Revert method discards all changes that have been made to the storage object since the last commit operation. - - - - - The method retrieves a pointer to an enumerator - object that can be used to enumerate the storage - and stream objects contained within this storage object. - - Reserved 1 is Reserved for future use; must be zero. - Reserved for future use; must be NULL. - Reserved for future use; must be zero. - Pointer to IEnumSTATSTG* pointer variable - that receives the interface pointer to the new enumerator object. - - - - The DestroyElement method removes the specified storage or stream from this storage object. - - A pointer to a wide character null-terminated Unicode string that contains - the name of the storage or stream to be removed. - - - - The RenameElement method renames the specified sub-storage or stream in this storage object. - - Pointer to a wide character null-terminated Unicode string that contains the name of the sub-storage or stream to be changed. - Pointer to a wide character null-terminated Unicode string that contains the new name for the specified sub-storage or stream. - - - - The SetElementTimes method sets the modification, access, and creation times of the specified storage element, if the underlying file system supports this method. - - The name of the storage object element whose times are to be modified. If NULL, the time is set on the root storage rather than one of its elements. - Either the new creation time for the element or NULL if the creation time is not to be modified. - Either the new access time for the element or NULL if the access time is not to be modified. - Either the new modification time for the element or NULL if the modification time is not to be modified. - - - - The SetClass method assigns the specified class identifier (CLSID) to this storage object. - - The CLSID that is to be associated with the storage object. - - - - stores up to 32 bits of state information in this storage object. This method is reserved for future use. - - Specifies the new values of the bits to set. No legal values are defined for these bits; they are all reserved for future use and must not be used by applications. - A binary mask indicating which bits in grfStateBits are significant in this call. - - - - The Stat method retrieves the STATSTG structure for this open storage object. - - On return, pointer to a STATSTG structure where this method places information about the open storage object. This parameter is NULL if an error occurs. - Specifies that some of the members in the STATSTG structure are not returned, thus saving a memory allocation operation. - Values are taken from the STATFLAG enumeration. - The LOCKTYPE enumeration values indicate the type of locking requested @@ -9631,149 +9411,6 @@ Indicates that the storage element is a stream object. - - - Replacement for UCOMIOleStream (and ComTypes.IOleStream) interface. - for Read() and Write(). - - - - - Reads a specified number of bytes from the stream object into memory starting at the current seek pointer. - - A pointer to the buffer which the stream data is read into. - The number of bytes of data to read from the stream object. - [out] Returns the actual number of bytes read from the stream object. - - - - writes a specified number of bytes into the stream object starting at the current seek pointer. - - A pointer to the buffer that contains the data that is to be written to the stream. - A valid pointer must be provided for this parameter even when cb is zero. - The number of bytes of data to attempt to write into the stream. This value can be zero. - [out] Returns the actual number of bytes written to the stream object. - - - - changes the seek pointer to a new location. - The new location is relative to either the beginning of the stream, - the end of the stream, or the current seek pointer. - - The displacement to be added to the location - indicated by the origin parameter. If dwOrigin is STREAM_SEEK_SET, - this is interpreted as an unsigned value rather than a signed value. - The origin for the displacement specified in dlibMove. - The origin can be the beginning of the file (STREAM_SEEK_SET), - the current seek pointer (STREAM_SEEK_CUR), or the end of the file (STREAM_SEEK_END). - For more information about values, see the STREAM_SEEK enumeration. - the value of the new seek pointer from the beginning of the stream. - - - - changes the size of the stream object. - - Specifies the new size, in bytes, of the stream. - - - - The CopyTo method copies a specified number of bytes - from the current seek pointer in the stream to the current seek pointer in another stream. - - A pointer to the destination stream. The stream pointed to by pstm - can be a new stream or a clone of the source stream. - The number of bytes to copy from the source stream. - A pointer to the location where this method writes the actual - number of bytes read from the source. You can set this pointer to NULL. - In this case, this method does not provide the actual number of bytes read. - the actual number of bytes written to the destination. - - - - ensures that any changes made to a stream object open in transacted mode are reflected in the parent storage - . If the stream object is open in direct mode, IStream::Commit has - no effect other than flushing all memory buffers to the next-level storage object. - The COM compound file implementation of streams does not support opening streams in transacted mode. - - Controls how the changes for the stream object are committed. - See the STGC enumeration for a definition of these values. - - - - discards all changes that have been made to a transacted stream since the last IStream::Commit call. On streams open in - direct mode and streams using the COM compound file implementation of IStream::Revert, this method has no effect. - - - - - restricts access to a specified range of bytes in the stream. - Supporting this functionality is optional since some file systems do not provide it. - - Integer that specifies the byte offset for the beginning of the range. - Integer that specifies the length of the range, in bytes, to be restricted. - Specifies the restrictions being requested on accessing the range. - - - - removes the access restriction on a range of bytes previously restricted with IStream::LockRegion. - - Specifies the byte offset for the beginning of the range. - Specifies, in bytes, the length of the range to be restricted. - Specifies the access restrictions previously placed on the range. - - - - retrieves the STATSTG structure for this stream. - - Pointer to a STATSTG structure where this method places information about this stream object. - Specifies that this method does not return some of the members in the STATSTG structure, - thus saving a memory allocation operation. Values are taken from the STATFLAG enumeration. - - - - creates a new stream object with its own seek pointer that references the same bytes as the original stream. - - pointer to the new stream object. - - - - IEnumSTATSTG interface. - - - - - retrieves a specified number of STATSTG structures, - that follow in the enumeration sequence. If there are fewer than the requested - number of STATSTG structures that remain in the enumeration sequence, - it retrieves the remaining STATSTG structures. - - The number of STATSTG structures requested. - An array of STATSTG structures returned. - The number of STATSTG structures retrieved in the rgelt parameter. - S_OK on success - - - - skips a specified number of STATSTG structures in the enumeration sequence. - - The number of STATSTG structures to skip. - - - - resets the enumeration sequence to the beginning of the STATSTG structure array. - - - - - creates a new enumerator that contains the same enumeration state as the current - STATSTG structure enumerator. Using this method, a client - can record a particular point in the enumeration - sequence and then return to that point at a later time. - The new enumerator supports the same IEnumSTATSTG interface. - - A pointer to the variable that receives the IEnumSTATSTG interface pointer. - If the method is unsuccessful, the value of the ppenum parameter is undefined. - The storage mode. @@ -11946,16 +11583,6 @@ Name of the file. store the mapped disk file information. - - - create memory mapped file security token. - This is a slow method (needs to access user's permissions) - but can be static, as the user's permission doesn't change. - - - The . - - Opens the exist memory mapped file. @@ -12922,7 +12549,7 @@ For additional read/write examples see version in "foundation Apps" project. - + Initializes a new instance of the class. @@ -13267,7 +12894,7 @@ Any errors that occur during calculation True if successful - + Updates the file header checksum. @@ -27977,13 +27604,6 @@ An array of internal structures size - - - Show mutex security. - - The mutex security. - The errors. - The try reopen mutex. @@ -28029,7 +27649,7 @@ The . - + Saves the audit trailer to IOleStream. @@ -29141,7 +28761,7 @@ The . - + Calculates the instrument method file checksum. It's duplicating exactly the Xcalibur checksum for compound doc file. @@ -29938,7 +29558,7 @@ Gets the file header for the instrument method file - + Creates a device method storage. @@ -29947,7 +29567,7 @@ Stores the error information if error occurs. Device method storage. - + Saves the audit trail. @@ -29956,7 +29576,7 @@ Stores the error information if error occurs. True if audit trail is saved successfully; otherwise false. - + Saves the file header to stream. @@ -29966,7 +29586,7 @@ Stores the error information if error occurs. True if file header saved successfully; otherwise false. - + Saves the device method to stream. @@ -29975,7 +29595,7 @@ Stores the error information if error occurs. True if the device method saved successfully; otherwise false. - + Saves the device method streams, i.e. "Text", "Data, etc. If the stream value is NULL, it will save an empty stream. @@ -30029,49 +29649,7 @@ Provides common methods to deal with IOleStorage and IOleStream. - - - Opens an existing compound document file (instrument method file). - - Name of the file. - Specifies the access mode to use when opening the compound document file. - The root storage object. - - - - Creates the compound document file (instrument method file) with a specified file name. - - Name of the file. - The root storage object (IOleStorage). - - - - Creates a storage (Device method). - - The storage. - Name of the device storage. - IOleStorage object (Device method). - - - - Opens an existing storage (Device method). - - The storage. - Name of the storage. - Specifies the access mode to use when opening the storage object. - Device storage. - - - - Saves the device stream data to the compound storage. - - The method. - The storage (either the root storage or device method). - Name of the stream data. - Stores the last error information. - True if data saved successfully; otherwise false. - - + Reads the device stream data from the storage. @@ -30081,21 +29659,17 @@ Returns the error information if error occurs. True if data saved successfully; otherwise false. - + - Writes the integer 4-byte value to stream. - - The data stream. - The value. - - - - Writes the bytes to the stream. + Saves the device stream data to the compound storage. - The data stream. - The value in byte array. + The method. + The storage (either the root storage or device method). + Name of the stream data. + Stores the last error information. + True if data saved successfully; otherwise false. - + Saves the file header to the IOleStream. @@ -30104,23 +29678,11 @@ Stores the error information if error occurs. True if the file header saved successfully; otherwise false. - + - Releases the specified storage. - - The storage. - - - - Releases the specified stream. - - The stream. - - - - Releases the specified enumerator for STATSTG structures. + Creates the compound document file (instrument method file) with a specified file name. - The enumerator. + The root storage object (IOleStorage). @@ -30909,16 +30471,6 @@ true on success - - - Finalizes the raw file security. - Begin create a temporary file to get its FileSecurity object instead of the one from the raw file. - Add an access rule to remove the WellKnownSidType.WorldSid into this FileSecurity object. - Apply the modified ACL to the raw file. - - Name of the raw file. - The errors. - mark acquisition complete.