|
1 | | -using System; |
| 1 | +using ComponentAce.Compression.Libs.zlib; |
| 2 | +using log4net; |
| 3 | +using System; |
2 | 4 | using System.Collections.Generic; |
3 | 5 | using System.Collections.Specialized; |
4 | 6 | using System.IO; |
|
10 | 12 | using System.Text.RegularExpressions; |
11 | 13 | using System.Xml; |
12 | 14 | using System.Xml.Serialization; |
13 | | -using log4net; |
14 | 15 | using ThermoFisher.CommonCore.Data; |
15 | 16 | using ThermoFisher.CommonCore.Data.Business; |
16 | 17 | using ThermoFisher.CommonCore.Data.FilterEnums; |
17 | 18 | using ThermoFisher.CommonCore.Data.Interfaces; |
18 | 19 | using ThermoRawFileParser.Util; |
19 | 20 | using ThermoRawFileParser.Writer.MzML; |
20 | | -using ComponentAce.Compression.Libs.zlib; |
21 | 21 |
|
22 | 22 | namespace ThermoRawFileParser.Writer |
23 | 23 | { |
@@ -1260,6 +1260,9 @@ private SpectrumType ConstructMSSpectrum(int scanNumber) |
1260 | 1260 | // Keep the CV params in a list and convert to array afterwards |
1261 | 1261 | var spectrumCvParams = new List<CVParamType>(); |
1262 | 1262 |
|
| 1263 | + // Keep user params in a list and convert to array afterwards |
| 1264 | + var spectrumUserParams = new List<UserParamType>(); |
| 1265 | + |
1263 | 1266 | // Trailer extra data list |
1264 | 1267 | ScanTrailer trailerData; |
1265 | 1268 |
|
@@ -1426,45 +1429,76 @@ private SpectrumType ConstructMSSpectrum(int scanNumber) |
1426 | 1429 | ParseInput.NewWarn(); |
1427 | 1430 | } |
1428 | 1431 |
|
1429 | | - try |
| 1432 | + |
| 1433 | + if (msLevel == (int)MSOrderType.Ng) |
1430 | 1434 | { |
1431 | | - try //since there is no direct way to get the number of reactions available, it is necessary to try and fail |
| 1435 | + // Neutral loss/gain spectra do not have precursor information |
| 1436 | + spectrum.productList = ConstructProductList(scanNumber, scanEvent, out double neutralgain); |
| 1437 | + spectrumUserParams.Add(new UserParamType |
1432 | 1438 | { |
1433 | | - scanEvent.GetReaction(_precursorTree[_precursorScanNumber].ReactionCount); |
1434 | | - } |
1435 | | - catch (ArgumentOutOfRangeException ex) |
| 1439 | + name = "neutral gain", |
| 1440 | + type = "xsd:float", |
| 1441 | + value = neutralgain.ToString(), |
| 1442 | + unitAccession = "MS:1000040", |
| 1443 | + unitCvRef = "MS", |
| 1444 | + unitName = "m/z" |
| 1445 | + }); |
| 1446 | + } |
| 1447 | + else if (msLevel == (int)MSOrderType.Nl) |
| 1448 | + { |
| 1449 | + spectrum.productList = ConstructProductList(scanNumber, scanEvent, out double neutralloss); |
| 1450 | + spectrumUserParams.Add(new UserParamType |
| 1451 | + { |
| 1452 | + name = "neutral loss", |
| 1453 | + type = "xsd:float", |
| 1454 | + value = neutralloss.ToString(), |
| 1455 | + unitAccession = "MS:1000040", |
| 1456 | + unitCvRef = "MS", |
| 1457 | + unitName = "m/z" |
| 1458 | + }); |
| 1459 | + } |
| 1460 | + else |
| 1461 | + { |
| 1462 | + try |
1436 | 1463 | { |
1437 | | - Log.Debug($"Using Tribrid decision tree fix for scan# {scanNumber}"); |
1438 | | - //Is it a decision tree scheduled scan on tribrid? |
1439 | | - if (msLevel == _precursorTree[_precursorScanNumber].MSLevel) |
| 1464 | + try //since there is no direct way to get the number of reactions available, it is necessary to try and fail |
1440 | 1465 | { |
1441 | | - _precursorScanNumber = GetParentFromScanString(result.Groups[1].Value); |
| 1466 | + scanEvent.GetReaction(_precursorTree[_precursorScanNumber].ReactionCount); |
1442 | 1467 | } |
1443 | | - else |
| 1468 | + catch (ArgumentOutOfRangeException ex) |
1444 | 1469 | { |
1445 | | - throw new RawFileParserException( |
1446 | | - $"Tribrid decision tree fix failed - cannot get reaction# {_precursorTree[_precursorScanNumber].ReactionCount} from {scanEvent.ToString()}", |
1447 | | - ex); |
| 1470 | + Log.Debug($"Using Tribrid decision tree fix for scan# {scanNumber}"); |
| 1471 | + //Is it a decision tree scheduled scan on tribrid? |
| 1472 | + if (msLevel == _precursorTree[_precursorScanNumber].MSLevel) |
| 1473 | + { |
| 1474 | + _precursorScanNumber = GetParentFromScanString(result.Groups[1].Value); |
| 1475 | + } |
| 1476 | + else |
| 1477 | + { |
| 1478 | + throw new RawFileParserException( |
| 1479 | + $"Tribrid decision tree fix failed - cannot get reaction# {_precursorTree[_precursorScanNumber].ReactionCount} from {scanEvent.ToString()}", |
| 1480 | + ex); |
| 1481 | + } |
1448 | 1482 | } |
1449 | | - } |
1450 | 1483 |
|
1451 | | - // Construct and set the precursor list element of the spectrum |
1452 | | - spectrum.precursorList = |
1453 | | - ConstructPrecursorList(_precursorScanNumber, scanEvent, charge, monoisotopicMz, isolationWidth, |
1454 | | - SPSMasses, out var reactionCount); |
| 1484 | + // Construct and set the precursor list element of the spectrum |
| 1485 | + spectrum.precursorList = |
| 1486 | + ConstructPrecursorList(_precursorScanNumber, scanEvent, charge, monoisotopicMz, isolationWidth, |
| 1487 | + SPSMasses, out var reactionCount); |
1455 | 1488 |
|
1456 | | - //save precursor information for later reference |
1457 | | - _precursorTree[scanNumber] = new PrecursorInfo(_precursorScanNumber, msLevel, reactionCount, spectrum.precursorList.precursor); |
1458 | | - } |
1459 | | - catch (Exception e) |
1460 | | - { |
1461 | | - var extra = (e.InnerException is null) ? "" : $"\n{e.InnerException.StackTrace}"; |
| 1489 | + //save precursor information for later reference |
| 1490 | + _precursorTree[scanNumber] = new PrecursorInfo(_precursorScanNumber, msLevel, reactionCount, spectrum.precursorList.precursor); |
| 1491 | + } |
| 1492 | + catch (Exception e) |
| 1493 | + { |
| 1494 | + var extra = (e.InnerException is null) ? "" : $"\n{e.InnerException.StackTrace}"; |
1462 | 1495 |
|
1463 | | - 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}"); |
1464 | | - ParseInput.NewWarn(); |
| 1496 | + 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}"); |
| 1497 | + ParseInput.NewWarn(); |
1465 | 1498 |
|
1466 | | - _precursorTree[scanNumber] = new PrecursorInfo(_precursorScanNumber, 1, 0, new PrecursorType[0]); |
| 1499 | + _precursorTree[scanNumber] = new PrecursorInfo(_precursorScanNumber, 1, 0, new PrecursorType[0]); |
1467 | 1500 |
|
| 1501 | + } |
1468 | 1502 | } |
1469 | 1503 | } |
1470 | 1504 |
|
@@ -1641,6 +1675,8 @@ private SpectrumType ConstructMSSpectrum(int scanNumber) |
1641 | 1675 |
|
1642 | 1676 | // Add the CV params to the spectrum |
1643 | 1677 | spectrum.cvParam = spectrumCvParams.ToArray(); |
| 1678 | + // Add user params to the spectrum |
| 1679 | + spectrum.userParam = spectrumUserParams.ToArray(); |
1644 | 1680 |
|
1645 | 1681 | // Binary data array list |
1646 | 1682 | var binaryData = new List<BinaryDataArrayType>(); |
@@ -2008,6 +2044,60 @@ private SpectrumType ConstructMSSpectrum(int scanNumber) |
2008 | 2044 |
|
2009 | 2045 | return spectrum; |
2010 | 2046 | } |
| 2047 | + |
| 2048 | + private ProductListType ConstructProductList(int scanNumber, IScanEvent scanEvent, out double neutral) |
| 2049 | + { |
| 2050 | + IReaction reaction = null; |
| 2051 | + |
| 2052 | + reaction = scanEvent.GetReaction(0); |
| 2053 | + |
| 2054 | + double? isolationWidth = reaction.IsolationWidth; |
| 2055 | + if (isolationWidth < 0) isolationWidth = null; |
| 2056 | + |
| 2057 | + neutral = reaction.PrecursorMass; |
| 2058 | + |
| 2059 | + var product = new ProductType(); |
| 2060 | + |
| 2061 | + if (isolationWidth != null) |
| 2062 | + { |
| 2063 | + product.isolationWindow = |
| 2064 | + new ParamGroupType |
| 2065 | + { |
| 2066 | + cvParam = new CVParamType[2] |
| 2067 | + }; |
| 2068 | + |
| 2069 | + var offset = isolationWidth.Value / 2 + reaction.IsolationWidthOffset; |
| 2070 | + product.isolationWindow.cvParam[0] = |
| 2071 | + new CVParamType |
| 2072 | + { |
| 2073 | + accession = "MS:1000828", |
| 2074 | + name = "isolation window lower offset", |
| 2075 | + value = (isolationWidth.Value - offset).ToString(), |
| 2076 | + cvRef = "MS", |
| 2077 | + unitCvRef = "MS", |
| 2078 | + unitAccession = "MS:1000040", |
| 2079 | + unitName = "m/z" |
| 2080 | + }; |
| 2081 | + product.isolationWindow.cvParam[1] = |
| 2082 | + new CVParamType |
| 2083 | + { |
| 2084 | + accession = "MS:1000829", |
| 2085 | + name = "isolation window upper offset", |
| 2086 | + value = offset.ToString(), |
| 2087 | + cvRef = "MS", |
| 2088 | + unitCvRef = "MS", |
| 2089 | + unitAccession = "MS:1000040", |
| 2090 | + unitName = "m/z" |
| 2091 | + }; |
| 2092 | + } |
| 2093 | + |
| 2094 | + return new ProductListType |
| 2095 | + { |
| 2096 | + count = "1", |
| 2097 | + product = new ProductType[] { product } |
| 2098 | + }; |
| 2099 | + } |
| 2100 | + |
2011 | 2101 | private SpectrumType ConstructPDASpectrum(int scanNumber, int instrumentNumber) |
2012 | 2102 | { |
2013 | 2103 | // Get each scan from the RAW file |
|
0 commit comments