Skip to content

Commit 8da0889

Browse files
Merge branch '1.4.3' into zontal
# Conflicts: # RawFileParser.cs # Writer/MetadataWriter.cs # Writer/MzMlSpectrumWriter.cs
2 parents 3359fba + 233b898 commit 8da0889

File tree

5 files changed

+168
-58
lines changed

5 files changed

+168
-58
lines changed

RawFileParser.cs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,6 @@ private static void ProcessFile(ParseInput parseInput)
141141
if (rawFile.GetInstrumentCountOfType(Device.MS) != 0)
142142
{
143143
rawFile.SelectInstrument(Device.MS, 1);
144-
145144
rawFile.IncludeReferenceAndExceptionData = !parseInput.ExData;
146145

147146
// Get the first and last scan from the RAW file
@@ -154,7 +153,7 @@ private static void ProcessFile(ParseInput parseInput)
154153
throw new RawFileParserException("Empty RAW file, no output will be produced");
155154
}
156155
}
157-
156+
158157
if (parseInput.MetadataFormat != MetadataFormat.NONE)
159158
{
160159
MetadataWriter metadataWriter = new MetadataWriter(parseInput);

Writer/MetadataWriter.cs

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ public MetadataWriter(ParseInput parseInput)
4646
/// </summary>
4747
public void WriteMetadata(IRawDataPlus rawFile, int firstScanNumber, int lastScanNumber)
4848
{
49-
if (rawFile.SelectMsData())
49+
if(rawFile.SelectMsData())
5050
{
5151
for (var scanNumber = firstScanNumber; scanNumber <= lastScanNumber; scanNumber++)
5252
{
@@ -112,8 +112,6 @@ public void WriteMetadata(IRawDataPlus rawFile, int firstScanNumber, int lastSca
112112
}
113113
}
114114

115-
116-
117115
if (minCharge == 100000000000000)
118116
{
119117
minCharge = 0;
@@ -177,6 +175,7 @@ private void WriteJsonMetada(IRawDataPlus rawFile, int firstScanNumber, int last
177175
rawFile.GetInstrumentData().HardwareVersion));
178176
}
179177
}
178+
180179

181180
// MS Data
182181
if (rawFile.SelectMsData())
@@ -216,7 +215,7 @@ private void WriteJsonMetada(IRawDataPlus rawFile, int firstScanNumber, int last
216215
metadata.addScanSetting(new CVTerm("MS:1000016", "MS", "scan start time",
217216
startTime.ToString(CultureInfo.InvariantCulture)));
218217
metadata.addScanSetting(new CVTerm("", "", "expected runtime",
219-
rawFile.RunHeader.ExpectedRuntime.ToString(CultureInfo.InvariantCulture)));
218+
rawFile.RunHeader.ExpectedRuntime.ToString(CultureInfo.InvariantCulture)));
220219
metadata.addScanSetting(new CVTerm("MS:1000011", "MS", "mass resolution",
221220
rawFile.RunHeaderEx.MassResolution.ToString(CultureInfo.InvariantCulture)));
222221
metadata.addScanSetting(new CVTerm("UO:0000002", "MS", "mass unit",
@@ -371,7 +370,7 @@ private void WriteTextMetadata(IRawDataPlus rawFile, int firstScanNumber, int la
371370
output.Add("Firmware version=" + rawFile.GetInstrumentData().HardwareVersion);
372371
}
373372
}
374-
373+
375374
// MS Data
376375
if (rawFile.SelectMsData())
377376
{

Writer/MzMlSpectrumWriter.cs

Lines changed: 131 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,8 @@ public MzMlSpectrumWriter(ParseInput parseInput) : base(parseInput)
6868
_mzMlNamespace.Add(string.Empty, "http://psi.hupo.org/ms/mzml");
6969
_doIndexing = ParseInput.OutputFormat == OutputFormat.IndexMzML;
7070
_osOffset = Environment.NewLine == "\n" ? 0 : 1;
71+
_precursorScanNumbers[""] = -1;
72+
_precursorTree[-1] = new PrecursorInfo();
7173
}
7274

7375
/// <inheritdoc />
@@ -1416,61 +1418,52 @@ private SpectrumType ConstructMSSpectrum(int scanNumber)
14161418
_precursorScanNumber = GetParentFromScanString(result.Groups[1].Value);
14171419
}
14181420

1419-
if (_precursorScanNumber > 0)
1421+
//finding precursor scan failed
1422+
if (_precursorScanNumber == -2)
14201423
{
1424+
Log.Warn($"Cannot find precursor scan for scan# {scanNumber}");
1425+
_precursorTree[-2] = new PrecursorInfo(0, msLevel, FindLastReaction(scanEvent, msLevel), new PrecursorType[0]);
1426+
}
14211427

1422-
try
1428+
try
1429+
{
1430+
try //since there is no direct way to get the number of reactions available, it is necessary to try and fail
1431+
{
1432+
scanEvent.GetReaction(_precursorTree[_precursorScanNumber].ReactionCount);
1433+
}
1434+
catch (ArgumentOutOfRangeException ex)
14231435
{
1424-
try //since there is no direct way to get the number of reactions available, it is necessary to try and fail
1436+
Log.Debug($"Using Tribrid decision tree fix for scan# {scanNumber}");
1437+
//Is it a decision tree scheduled scan on tribrid?
1438+
if (msLevel == _precursorTree[_precursorScanNumber].MSLevel)
14251439
{
1426-
scanEvent.GetReaction(_precursorTree[_precursorScanNumber].ReactionCount);
1440+
_precursorScanNumber = GetParentFromScanString(result.Groups[1].Value);
14271441
}
1428-
catch (ArgumentOutOfRangeException ex)
1442+
else
14291443
{
1430-
Log.Debug($"Using Tribrid decision tree fix for scan# {scanNumber}");
1431-
//Is it a decision tree scheduled scan on tribrid?
1432-
if (msLevel == _precursorTree[_precursorScanNumber].MSLevel)
1433-
{
1434-
_precursorScanNumber = GetParentFromScanString(result.Groups[1].Value);
1435-
}
1436-
else
1437-
{
1438-
throw new RawFileParserException(
1439-
$"Tribrid decision tree fix failed - cannot get reaction# {_precursorTree[_precursorScanNumber].ReactionCount} from {scanEvent.ToString()}",
1440-
ex);
1441-
}
1444+
throw new RawFileParserException(
1445+
$"Tribrid decision tree fix failed - cannot get reaction# {_precursorTree[_precursorScanNumber].ReactionCount} from {scanEvent.ToString()}",
1446+
ex);
14421447
}
1443-
1444-
// Construct and set the precursor list element of the spectrum
1445-
spectrum.precursorList =
1446-
ConstructPrecursorList(_precursorScanNumber, scanEvent, charge, monoisotopicMz, isolationWidth,
1447-
SPSMasses, out var reactionCount);
1448-
1449-
//save precursor information for later reference
1450-
_precursorTree[scanNumber] = new PrecursorInfo(_precursorScanNumber, msLevel, reactionCount, spectrum.precursorList.precursor);
14511448
}
1452-
catch (Exception e)
1453-
{
1454-
var extra = (e.InnerException is null) ? "" : $"\n{e.InnerException.StackTrace}";
14551449

1456-
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}");
1457-
ParseInput.NewWarn();
1458-
1459-
_precursorTree[scanNumber] = new PrecursorInfo(_precursorScanNumber, 1, 0, new PrecursorType[0]);
1460-
1461-
}
1450+
// Construct and set the precursor list element of the spectrum
1451+
spectrum.precursorList =
1452+
ConstructPrecursorList(_precursorScanNumber, scanEvent, charge, monoisotopicMz, isolationWidth,
1453+
SPSMasses, out var reactionCount);
14621454

1455+
//save precursor information for later reference
1456+
_precursorTree[scanNumber] = new PrecursorInfo(_precursorScanNumber, msLevel, reactionCount, spectrum.precursorList.precursor);
14631457
}
1464-
else
1458+
catch (Exception e)
14651459
{
1466-
spectrum.precursorList = new PrecursorListType
1467-
{
1468-
count = "0",
1469-
precursor = new PrecursorType[0]
1470-
};
1460+
var extra = (e.InnerException is null) ? "" : $"\n{e.InnerException.StackTrace}";
1461+
1462+
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}");
1463+
ParseInput.NewWarn();
1464+
1465+
_precursorTree[scanNumber] = new PrecursorInfo(_precursorScanNumber, 1, 0, new PrecursorType[0]);
14711466

1472-
Log.Error($"Failed finding precursor for {scanNumber}");
1473-
ParseInput.NewError();
14741467
}
14751468
}
14761469
else
@@ -1995,6 +1988,45 @@ private SpectrumType ConstructMSSpectrum(int scanNumber)
19951988
return spectrum;
19961989
}
19971990

1991+
private int FindLastReaction(IScanEvent scanEvent, int msLevel)
1992+
{
1993+
int lastReactionIndex = msLevel - 2;
1994+
1995+
//iteratively trying find the last available index for reaction
1996+
while(true)
1997+
{
1998+
try
1999+
{
2000+
scanEvent.GetReaction(lastReactionIndex + 1);
2001+
}
2002+
catch (ArgumentOutOfRangeException)
2003+
{
2004+
//stop trying
2005+
break;
2006+
}
2007+
2008+
lastReactionIndex++;
2009+
}
2010+
2011+
//supplemental activation flag is on -> one of the levels (not necissirily the last one) used supplemental activation
2012+
//check last two activations
2013+
if (scanEvent.SupplementalActivation == TriState.On)
2014+
{
2015+
var lastActivation = scanEvent.GetReaction(lastReactionIndex).ActivationType;
2016+
var beforeLastActivation = scanEvent.GetReaction(lastReactionIndex - 1).ActivationType;
2017+
2018+
if ((beforeLastActivation == ActivationType.ElectronTransferDissociation || beforeLastActivation == ActivationType.ElectronCaptureDissociation) &&
2019+
(lastActivation == ActivationType.CollisionInducedDissociation || lastActivation == ActivationType.HigherEnergyCollisionalDissociation))
2020+
return lastReactionIndex - 1; //ETD or ECD followed by HCD or CID -> supplemental activation in the last level (move the last reaction one step back)
2021+
else
2022+
return lastReactionIndex;
2023+
}
2024+
else //just use the last one
2025+
{
2026+
return lastReactionIndex;
2027+
}
2028+
}
2029+
19982030
private SpectrumType ConstructPDASpectrum(int scanNumber, int instrumentNumber)
19992031
{
20002032
// Get each scan from the RAW file
@@ -2257,19 +2289,24 @@ private PrecursorListType ConstructPrecursorList(int precursorScanNumber, IScanE
22572289
// Get precursors from earlier levels
22582290
var prevPrecursors = _precursorTree[precursorScanNumber];
22592291

2260-
var spectrumRef = "";
2292+
string spectrumRef = null;
22612293
int msLevel = (int)scanEvent.MSOrder;
22622294
IReaction reaction = null;
22632295
var precursorMz = 0.0;
22642296
reactionCount = prevPrecursors.ReactionCount;
22652297

2266-
spectrumRef = ConstructSpectrumTitle((int)Device.MS, 1, precursorScanNumber);
22672298
reaction = scanEvent.GetReaction(reactionCount);
22682299

2269-
precursorMz = reaction.PrecursorMass;
2270-
22712300
//if isolation width was not found in the trailer, try to get one from the reaction
22722301
if (isolationWidth == null) isolationWidth = reaction.IsolationWidth;
2302+
if (isolationWidth < 0) isolationWidth = null;
2303+
2304+
precursorMz = reaction.PrecursorMass;
2305+
2306+
if (precursorScanNumber > 0)
2307+
{
2308+
spectrumRef = ConstructSpectrumTitle((int)Device.MS, 1, precursorScanNumber);
2309+
}
22732310

22742311
var precursor = new PrecursorType
22752312
{
@@ -2307,7 +2344,7 @@ private PrecursorListType ConstructPrecursorList(int precursorScanNumber, IScanE
23072344
});
23082345
}
23092346

2310-
if (selectedIonMz > ZeroDelta)
2347+
if (selectedIonMz > ZeroDelta && precursorScanNumber > 0)
23112348
{
23122349
var selectedIonIntensity = CalculatePrecursorPeakIntensity(_rawFile, precursorScanNumber, reaction.PrecursorMass, isolationWidth,
23132350
ParseInput.NoPeakPicking.Contains(msLevel - 1));
@@ -2488,6 +2525,51 @@ private PrecursorListType ConstructPrecursorList(int precursorScanNumber, IScanE
24882525
spectrumRef = spectrumRef
24892526
};
24902527

2528+
//Isolation window for SPS masses is the same as for the first precursor
2529+
SPSPrecursor.isolationWindow =
2530+
new ParamGroupType
2531+
{
2532+
cvParam = new CVParamType[3]
2533+
};
2534+
2535+
SPSPrecursor.isolationWindow.cvParam[0] =
2536+
new CVParamType
2537+
{
2538+
accession = "MS:1000827",
2539+
name = "isolation window target m/z",
2540+
value = SPSMasses[n].ToString(CultureInfo.InvariantCulture),
2541+
cvRef = "MS",
2542+
unitCvRef = "MS",
2543+
unitAccession = "MS:1000040",
2544+
unitName = "m/z"
2545+
};
2546+
if (isolationWidth != null)
2547+
{
2548+
var offset = isolationWidth.Value / 2 + reaction.IsolationWidthOffset;
2549+
SPSPrecursor.isolationWindow.cvParam[1] =
2550+
new CVParamType
2551+
{
2552+
accession = "MS:1000828",
2553+
name = "isolation window lower offset",
2554+
value = (isolationWidth.Value - offset).ToString(CultureInfo.InvariantCulture),
2555+
cvRef = "MS",
2556+
unitCvRef = "MS",
2557+
unitAccession = "MS:1000040",
2558+
unitName = "m/z"
2559+
};
2560+
SPSPrecursor.isolationWindow.cvParam[2] =
2561+
new CVParamType
2562+
{
2563+
accession = "MS:1000829",
2564+
name = "isolation window upper offset",
2565+
value = offset.ToString(CultureInfo.InvariantCulture),
2566+
cvRef = "MS",
2567+
unitCvRef = "MS",
2568+
unitAccession = "MS:1000040",
2569+
unitName = "m/z"
2570+
};
2571+
}
2572+
24912573
// Selected ion MZ only
24922574
SPSPrecursor.selectedIonList.selectedIon[0] =
24932575
new ParamGroupType
@@ -2530,8 +2612,7 @@ private PrecursorListType ConstructPrecursorList(int precursorScanNumber, IScanE
25302612

25312613
private int GetParentFromScanString(string scanString)
25322614
{
2533-
var result = _filterStringIsolationMzPattern.Match(scanString);
2534-
var parts = Regex.Split(result.Groups[1].Value, " ");
2615+
var parts = Regex.Split(scanString, " ");
25352616

25362617
//find the position of the first (from the end) precursor with a different mass
25372618
//to account for possible supplementary activations written in the filter
@@ -2549,7 +2630,7 @@ private int GetParentFromScanString(string scanString)
25492630
return _precursorScanNumbers[parentFilter];
25502631
}
25512632

2552-
return -1; //unsuccessful parsing
2633+
return -2; //unsuccessful parsing
25532634
}
25542635

25552636
/// <summary>

Writer/OntologyMapping.cs

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,15 @@ public static class OntologyMapping
6868
value = ""
6969
}
7070
},
71+
{
72+
MassAnalyzerType.MassAnalyzerMRTOF, new CVParamType
73+
{
74+
accession = "MS:1003379",
75+
name = "asymmetric track lossless time-of-flight analyzer",
76+
cvRef = "MS",
77+
value = ""
78+
}
79+
},
7180
{
7281
MassAnalyzerType.Any, new CVParamType
7382
{
@@ -543,6 +552,15 @@ public static class OntologyMapping
543552
value = ""
544553
}
545554
},
555+
{
556+
"ORBITRAP ASCEND", new CVParamType
557+
{
558+
accession = "MS:1003356",
559+
name = "Orbitrap Ascend",
560+
cvRef = "MS",
561+
value = ""
562+
}
563+
},
546564
{
547565
"ORBITRAP EXPLORIS 120", new CVParamType
548566
{
@@ -570,6 +588,15 @@ public static class OntologyMapping
570588
value = ""
571589
}
572590
},
591+
{
592+
"ORBITRAP ASTRAL", new CVParamType
593+
{
594+
accession = "MS:1003378",
595+
name = "Orbitrap Astral",
596+
cvRef = "MS",
597+
value = ""
598+
}
599+
},
573600
{
574601
"EXACTIVE", new CVParamType
575602
{
@@ -730,6 +757,8 @@ public static List<CVParamType> GetDetectors(string instrumentAccession)
730757
case "MS:1002732":
731758
// ORBITRAP ECLIPSE
732759
case "MS:1003029":
760+
// ORBITRAP ASCEND
761+
case "MS:1003356":
733762
// ORBITRAP ID-X
734763
case "MS:1003112":
735764
detectors = new List<CVParamType>
@@ -768,6 +797,8 @@ public static List<CVParamType> GetDetectors(string instrumentAccession)
768797
case "MS:1003094":
769798
// ORBITRAP EXPLORIS 480
770799
case "MS:1003028":
800+
// ORBITRAP ASTRAL
801+
case "MS:1003378":
771802
detectors = new List<CVParamType>
772803
{
773804
new CVParamType

Writer/PrecursorInfo.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
/// </summary>
66
public class PrecursorInfo
77
{
8-
//for future use
8+
//Current MSLevel
99
public int MSLevel { get; }
1010

1111
//precursor scan number, 0 - means not a precursor

0 commit comments

Comments
 (0)