Skip to content

Commit 3265f38

Browse files
Merge branch 'Issue98' of https://github.com/compomics/ThermoRawFileParser into Issue98
2 parents 9260458 + 79f8d84 commit 3265f38

File tree

4 files changed

+211
-8
lines changed

4 files changed

+211
-8
lines changed

ParseInput.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ public string RawFilePath
2929
if (value != null)
3030
{
3131
RawFileNameWithoutExtension = Path.GetFileNameWithoutExtension(value);
32+
//do we need it?
3233
var splittedPath = value.Split('/');
3334
_rawFileName = splittedPath[splittedPath.Length - 1];
3435
}
@@ -93,6 +94,7 @@ public string RawFilePath
9394

9495
public string BucketName { get; set; }
9596

97+
//this property assigned but never used
9698
/// <summary>
9799
/// The raw file name.
98100
/// </summary>

ThermoRawFileParser.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,7 @@
195195
<Compile Include="RawFileParser.cs" />
196196
<Compile Include="Util\LimitedSizeDictionary.cs" />
197197
<Compile Include="Util\Peptide.cs" />
198+
<Compile Include="Writer\ScanTrailer.cs" />
198199
<Compile Include="XIC\JSONInputUnit.cs" />
199200
<Compile Include="XIC\JSONParser.cs" />
200201
<Compile Include="XIC\XicData.cs" />

Writer/MzMlSpectrumWriter.cs

Lines changed: 62 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1163,13 +1163,54 @@ private SpectrumType ConstructMSSpectrum(int scanNumber)
11631163
};
11641164

11651165
// Trailer extra data list
1166-
var trailerData = _rawFile.GetTrailerExtraInformation(scanNumber);
1166+
var trailerData = new ScanTrailer(_rawFile.GetTrailerExtraInformation(scanNumber));
1167+
int? charge;
1168+
double? monoisotopicMz;
1169+
double? ionInjectionTime;
1170+
double? isolationWidth;
1171+
double? FAIMSCV = null;
1172+
List<double> SPSMasses = new List<double>();
1173+
1174+
charge = trailerData.AsPositiveInt("Charge State:");
1175+
monoisotopicMz = trailerData.AsDouble("Monoisotopic M/Z:");
1176+
ionInjectionTime = trailerData.AsDouble("Ion Injection Time (ms):");
1177+
isolationWidth = trailerData.AsDouble("MS" + (int)scanFilter.MSOrder + " Isolation Width:");
1178+
if (trailerData.AsBool("FAIMS Voltage On:").GetValueOrDefault(false))
1179+
FAIMSCV = trailerData.AsDouble("FAIMS CV:");
1180+
1181+
//tune version < 3
1182+
if (trailerData.Has("SPS Mass 1:"))
1183+
{
1184+
foreach (var label in trailerData.MatchKeys(_spSentry))
1185+
{
1186+
var mass = trailerData.AsDouble(label).GetValueOrDefault(0);
1187+
if (mass > 0) SPSMasses.Add((double)mass); //zero means mass does not exist
1188+
}
1189+
}
1190+
1191+
//tune version == 3
1192+
if (trailerData.Has("SPS Masses:"))
1193+
{
1194+
foreach (var labelvalue in trailerData.MatchValues(_spSentry3))
1195+
{
1196+
foreach (var mass in labelvalue.Trim().Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries))
1197+
{
1198+
SPSMasses.Add(double.Parse(mass));
1199+
}
1200+
1201+
}
1202+
}
1203+
1204+
//Older iterative version that works with trailer directly, can be removed if the new object version is better
1205+
/*var trailerData = _rawFile.GetTrailerExtraInformation(scanNumber);
11671206
int? charge = null;
11681207
double? monoisotopicMz = null;
11691208
double? ionInjectionTime = null;
11701209
double? FAIMSCV = null;
11711210
bool FAIMSON = false;
11721211
List<double> SPSMasses = new List<double>();
1212+
double? isolationWidth = null;
1213+
11731214
for (var i = 0; i < trailerData.Length; i++)
11741215
{
11751216
if (trailerData.Labels[i] == "Charge State:")
@@ -1192,6 +1233,12 @@ private SpectrumType ConstructMSSpectrum(int scanNumber)
11921233
CultureInfo.CurrentCulture);
11931234
}
11941235
1236+
if (trailerData.Labels[i] == "MS" + (int) scanFilter.MSOrder + " Isolation Width:")
1237+
{
1238+
isolationWidth = double.Parse(trailerData.Values[i], NumberStyles.Any,
1239+
CultureInfo.CurrentCulture);
1240+
}
1241+
11951242
if (trailerData.Labels[i] == "FAIMS CV:")
11961243
{
11971244
FAIMSCV = double.Parse(trailerData.Values[i], NumberStyles.Any,
@@ -1220,7 +1267,7 @@ private SpectrumType ConstructMSSpectrum(int scanNumber)
12201267
}
12211268
12221269
}
1223-
}
1270+
}*/
12241271

12251272
// Construct and set the scan list element of the spectrum
12261273
var scanListType = ConstructScanList(scanNumber, scan, scanFilter, scanEvent, monoisotopicMz,
@@ -1251,6 +1298,10 @@ private SpectrumType ConstructMSSpectrum(int scanNumber)
12511298
value = ""
12521299
});
12531300

1301+
//update precursor scan if it is provided in trailer data
1302+
var trailerMasterScan = trailerData.AsPositiveInt("Master Scan Number:");
1303+
if (trailerMasterScan.HasValue) _precursorMs1ScanNumber = trailerMasterScan.Value;
1304+
12541305
// Keep track of scan number and isolation m/z for precursor reference
12551306
var result = _filterStringIsolationMzPattern.Match(scanEvent.ToString());
12561307
if (result.Success)
@@ -1265,7 +1316,7 @@ private SpectrumType ConstructMSSpectrum(int scanNumber)
12651316

12661317
// Construct and set the precursor list element of the spectrum
12671318
var precursorListType =
1268-
ConstructPrecursorList(scanEvent, charge, scanFilter.MSOrder, monoisotopicMz, SPSMasses);
1319+
ConstructPrecursorList(scanEvent, charge, scanFilter.MSOrder, monoisotopicMz, isolationWidth, SPSMasses);
12691320
spectrum.precursorList = precursorListType;
12701321
break;
12711322
case MSOrderType.Ms3:
@@ -1276,7 +1327,7 @@ private SpectrumType ConstructMSSpectrum(int scanNumber)
12761327
name = "MSn spectrum",
12771328
value = ""
12781329
});
1279-
precursorListType = ConstructPrecursorList(scanEvent, charge, scanFilter.MSOrder, monoisotopicMz, SPSMasses);
1330+
precursorListType = ConstructPrecursorList(scanEvent, charge, scanFilter.MSOrder, monoisotopicMz, isolationWidth, SPSMasses);
12801331
spectrum.precursorList = precursorListType;
12811332
break;
12821333
default:
@@ -1321,7 +1372,7 @@ private SpectrumType ConstructMSSpectrum(int scanNumber)
13211372
});
13221373

13231374
// FAIMS
1324-
if(FAIMSCV != null && FAIMSON)
1375+
if(FAIMSCV != null)
13251376
{
13261377
spectrumCvParams.Add(new CVParamType
13271378
{
@@ -1863,9 +1914,10 @@ private SpectrumType ConstructPDASpectrum(int scanNumber, int instrumentNumber)
18631914
/// <param name="msLevel">the MS level</param>
18641915
/// <param name="monoisotopicMz">the monoisotopic m/z value</param>
18651916
/// <param name="isolationWidth">the isolation width</param>
1917+
/// <param name="SPSMasses">List of masses selected for SPS</param>
18661918
/// <returns>the precursor list</returns>
18671919
private PrecursorListType ConstructPrecursorList(IScanEventBase scanEvent, int? charge, MSOrderType msLevel,
1868-
double? monoisotopicMz, List<double> SPSMasses)
1920+
double? monoisotopicMz, double? isolationWidth, List<double> SPSMasses)
18691921
{
18701922
// Construct the precursor
18711923
var precursorList = new PrecursorListType
@@ -1878,7 +1930,6 @@ private PrecursorListType ConstructPrecursorList(IScanEventBase scanEvent, int?
18781930
int precursorScanNumber = _precursorMs1ScanNumber;
18791931
IReaction reaction = null;
18801932
var precursorMz = 0.0;
1881-
double? isolationWidth = null;
18821933
try
18831934
{
18841935
switch (msLevel)
@@ -1908,7 +1959,10 @@ private PrecursorListType ConstructPrecursorList(IScanEventBase scanEvent, int?
19081959
}
19091960

19101961
precursorMz = reaction.PrecursorMass;
1911-
isolationWidth = reaction.IsolationWidth;
1962+
1963+
//if isolation width was not found in the trailer, try to get one from the reaction
1964+
if (isolationWidth == null) isolationWidth = reaction.IsolationWidth;
1965+
19121966
}
19131967
catch (ArgumentOutOfRangeException)
19141968
{

Writer/ScanTrailer.cs

Lines changed: 146 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
1+
using System.Collections.Generic;
2+
using System.Linq;
3+
using System.Text.RegularExpressions;
4+
using ThermoFisher.CommonCore.Data.Business;
5+
6+
namespace ThermoRawFileParser.Writer
7+
{
8+
public class ScanTrailer
9+
{
10+
public int Length { get => data.Count; }
11+
12+
public string[] Labels { get => data.Keys.ToArray(); }
13+
14+
public string[] Values { get => data.Values.ToArray(); }
15+
16+
private readonly Dictionary<string, string> data;
17+
18+
public ScanTrailer(LogEntry trailerData)
19+
{
20+
data = new Dictionary<string, string>();
21+
22+
for (int i = 0; i < trailerData.Length; i++)
23+
{
24+
data[trailerData.Labels[i]] = trailerData.Values[i].Trim();
25+
}
26+
}
27+
28+
/// <summary>
29+
/// Try returning selected trailer element as boolean value,
30+
/// if the element does not exist or cannot be converted to boolean return null
31+
/// </summary>
32+
/// <param name="key">name of the element</param>
33+
public bool? AsBool(string key)
34+
{
35+
if(data.ContainsKey(key))
36+
{
37+
var stringValue = data[key].ToLower();
38+
39+
switch (stringValue)
40+
{
41+
case "on":
42+
case "true":
43+
case "yes":
44+
return true;
45+
default:
46+
return false;
47+
}
48+
}
49+
50+
return null;
51+
}
52+
53+
/// <summary>
54+
/// Try returning selected trailer element as double value,
55+
/// if the element does not exist or cannot be converted to double return null
56+
/// </summary>
57+
/// <param name="key">name of the element</param>
58+
public double? AsDouble(string key)
59+
{
60+
if (data.ContainsKey(key))
61+
{
62+
if (double.TryParse(data[key], out var result)) return result;
63+
}
64+
return null;
65+
}
66+
67+
/// <summary>
68+
/// Try returning selected trailer element as integer value,
69+
/// if the element does not exist or cannot be converted to integer return null
70+
/// </summary>
71+
/// <param name="key">name of the element</param>
72+
public int? AsInt(string key)
73+
{
74+
if (data.ContainsKey(key))
75+
{
76+
if (int.TryParse(data[key], out var result)) return result;
77+
}
78+
return null;
79+
}
80+
81+
/// <summary>
82+
/// Try returning selected trailer element as strictly positive (non zero) integer value,
83+
/// if the element does not exist or cannot be converted to strictly positive integer return null
84+
/// </summary>
85+
/// <param name="key">name of the element</param>
86+
public int? AsPositiveInt(string key)
87+
{
88+
int? value = AsInt(key);
89+
90+
if (value != null && value > 0) return value;
91+
else return null;
92+
93+
}
94+
95+
/// <summary>
96+
/// Try returning selected trailer element as string,
97+
/// alias to `Get`
98+
/// </summary>
99+
/// <param name="key">name of the element</param>
100+
public string AsString(string key)
101+
{
102+
return Get(key);
103+
}
104+
105+
/// <summary>
106+
/// Try getting selected trailer element by name,
107+
/// if the element does not exist return null
108+
/// </summary>
109+
/// <param name="key">name of the element</param>
110+
public string Get(string key)
111+
{
112+
if (data.ContainsKey(key))
113+
{
114+
return data[key];
115+
}
116+
return null;
117+
}
118+
119+
/// <summary>
120+
/// Check if selected trailer element exists
121+
/// </summary>
122+
/// <param name="key">name of the element</param>
123+
public bool Has(string key)
124+
{
125+
return data.ContainsKey(key);
126+
}
127+
128+
/// <summary>
129+
/// Return iterator over trailer element names matching regex
130+
/// </summary>
131+
/// <param name="regex">compiled regex object</param>
132+
public IEnumerable<string> MatchKeys(Regex regex)
133+
{
134+
return data.Keys.Where(k => regex.IsMatch(k));
135+
}
136+
137+
/// <summary>
138+
/// Return iterator over trailer element values which names are matching regex
139+
/// </summary>
140+
/// <param name="regex">compiled regex object</param>
141+
public IEnumerable<string> MatchValues(Regex regex)
142+
{
143+
return data.Where(item => regex.IsMatch(item.Key)).Select(item => item.Value);
144+
}
145+
}
146+
}

0 commit comments

Comments
 (0)