25 public double MOverZ {
get;
private set; }
28 public int Charge {
get;
private set; }
29 public int Rank {
get;
set; }
43 public double RT {
get;
set; }
58 public static class MGFParser
60 public static List<Spectrum> ParseNextSpectra(
string filename)
62 List<Spectrum> spectra =
new List<Spectrum>();
63 int nrOfReadSpectra = 0;
67 Dictionary<int, double> peaks =
new Dictionary<int, double>();
68 Spectrum currentSpectrum =
null;
69 bool isCorrect =
true;
70 string lastScannumber =
string.Empty;
73 var SpectTitleMap =
new Dictionary<int, string>();
77 using (StreamReader sr =
new StreamReader(filename))
79 while (!sr.EndOfStream)
81 var line = sr.ReadLine();
83 if (line ==
null)
continue;
86 if (!isCorrect && (!line.ToUpper().StartsWith(
"BEGIN IONS", StringComparison.Ordinal)))
91 if (line.ToUpper().StartsWith(
"BEGIN IONS", StringComparison.Ordinal))
93 if (currentSpectrum !=
null && isCorrect)
96 " Skipping spectrum with scannumber '" + currentSpectrum.ScanNumber +
97 "'. No end ions found."
103 peaks =
new Dictionary<int, double>();
106 currentSpectrum =
new Spectrum
108 FragmentsPeaks =
new List<AMassCentroid>(),
109 ImmuneMasses =
new SortedSet<double>(),
110 ImmunePeaks =
new Dictionary<int, double>(),
114 else if (LineCanBeIgnored(line)) { }
117 if (currentSpectrum ==
null)
121 " Skipping spectrum after scannumber '" + lastScannumber +
"'. No begin ions found."
126 if (line.ToUpper().StartsWith(
"TITLE", StringComparison.Ordinal))
128 int inx = line.IndexOf(
"=");
129 title = line.Substring(inx + 1);
130 if (line.ToUpper().Contains(
"SCAN", StringComparison.Ordinal))
132 Match s = Regex.Match(line.ToUpper(),
@"SCAN.?[:=\s]\s?([0-9]+)");
134 currentSpectrum.ScanNumber = Int32.Parse(s.Groups[1].Value);
136 else if (line.ToUpper().Contains(
"INDEX", StringComparison.Ordinal))
138 Match s = Regex.Match(line.ToUpper(),
@"INDEX.?[:=\s]\s?([0-9]+)");
140 currentSpectrum.ScanNumber = Int32.Parse(s.Groups[1].Value);
143 else if (line.ToUpper().StartsWith(
"PEPMASS", StringComparison.Ordinal))
145 mOverZ = ParseMOverZ(line);
147 else if (line.ToUpper().StartsWith(
"CHARGE", StringComparison.Ordinal))
149 charge = ParseCharge(line);
151 else if (line.ToUpper().StartsWith(
"RTINSECONDS", StringComparison.Ordinal))
153 currentSpectrum.RT = ParseRt(line);
155 else if (line.ToUpper().StartsWith(
"SCANS", StringComparison.Ordinal))
157 currentSpectrum.ScanNumber = ParseScanNumber(line);
159 else if (line.ToUpper().StartsWith(
"END IONS", StringComparison.Ordinal))
161 if (currentSpectrum.ScanNumber == 0)
163 if (
string.IsNullOrEmpty(title))
166 " Skipping spectrum after scannumber '" +
167 lastScannumber +
"'. No title or scan number found."
173 string[] titleArr = title.Split(
'.');
174 if (titleArr.Length > 3)
175 currentSpectrum.ScanNumber =
176 Int32.Parse(titleArr[titleArr.Length - 3]);
179 if (currentSpectrum.FragmentsPeaks.Count == 0 || mOverZ == 0)
182 if (currentSpectrum.ScanNumber != 0)
183 text = currentSpectrum.ScanNumber.ToString();
188 " Skipping spectrum with scannumber '" + text +
"'. No mass value found."
194 " Skipping spectrum with scannumber '" + text +
"'. No peaks found."
207 foreach (
int consideredCharge
in new List<int>() { 2, 3, 4, 5, 6 })
209 var s = GenerateSpectrum(currentSpectrum.FragmentsPeaks,
210 currentSpectrum.ScanNumber, _scanId, currentSpectrum.RT, mOverZ,
218 currentSpectrum.Precursor.SetMassCharge(mOverZ, charge,
true);
219 spectra.Add(currentSpectrum);
220 SpectTitleMap.Add(_scanId, title.Trim());
226 lastScannumber = currentSpectrum.ScanNumber.ToString();
227 title =
string.Empty;
228 peaks =
new Dictionary<int, double>();
231 currentSpectrum =
null;
236 string[] parts = line.Split(
new[] {
' ' }, StringSplitOptions.RemoveEmptyEntries);
237 if (parts.Length == 1)
239 parts = line.Split(
new[] {
'\t' }, StringSplitOptions.RemoveEmptyEntries);
242 if (parts.Length == 2 || parts.Length == 3)
249 mass = ParseMass(parts[0], line);
254 " Skipping spectrum with scannumber '" +
255 currentSpectrum.ScanNumber +
"'. Error in parsing mass of peak.");
256 Console.WriteLine(e.ToString());
263 intensity = ParseIntensity(parts[1], line);
268 " Skipping spectrum with scannumber '" +
269 currentSpectrum.ScanNumber +
"'. Error in parsing intensity of peak.");
270 Console.WriteLine(e.ToString());
276 if (peaks.ContainsKey(key))
278 if (peaks[key] < intensity)
279 peaks[key] = intensity;
283 peaks.Add(key, intensity);
286 currentSpectrum.FragmentsPeaks.Add(
287 GenerateFragmentPeak(mass, peaks[key], charge));
292 " Skipping spectrum with scannumber '" +
293 currentSpectrum.ScanNumber +
"'. Error in parsing peak.");
303 Console.WriteLine(
"Error parsing mgf file at or after spectrum '" + title +
"'.");
304 Console.WriteLine(ex.ToString());
312 private static Spectrum GenerateSpectrum(List<AMassCentroid> fragmentsPeaks,
int numb,
int scanId,
double rt,
double mOverZ,
int charge)
314 Spectrum s =
new Spectrum
316 FragmentsPeaks = fragmentsPeaks,
320 ImmuneMasses =
new SortedSet<double>(),
321 ImmunePeaks =
new Dictionary<int, double>()
323 s.Precursor.SetMassCharge(mOverZ, charge,
true);
327 public static AMassCentroid GenerateFragmentPeak(
double position,
double intensity,
int charge)
329 AMassCentroid amass =
new AMassCentroid
332 Intensity = intensity,
333 Charge = (short)charge
339 private static double ParseIntensity(
string replace,
string line)
341 string ReplaceDecimalSeperator(
string toReplace)
343 return toReplace.Replace(
",", NumberFormatInfo.CurrentInfo.NumberDecimalSeparator, StringComparison.Ordinal)
344 .Replace(
".", NumberFormatInfo.CurrentInfo.NumberDecimalSeparator, StringComparison.Ordinal);
347 string i = ReplaceDecimalSeperator(replace);
348 double intensity = Double.Parse(i);
352 private static double ParseMass(
string replace,
string line)
354 string ReplaceDecimalSeperator(
string toReplace)
356 return toReplace.Replace(
",", NumberFormatInfo.CurrentInfo.NumberDecimalSeparator, StringComparison.Ordinal)
357 .Replace(
".", NumberFormatInfo.CurrentInfo.NumberDecimalSeparator, StringComparison.Ordinal);
360 string m = ReplaceDecimalSeperator(replace);
361 double mass = Double.Parse(m);
365 private static int ParseCharge(
string line)
367 int inx = line.IndexOf(
"+", StringComparison.Ordinal);
368 string m = line.Substring(7);
370 m = line.Substring(7, inx - 7);
371 if (!String.IsNullOrEmpty(m))
373 return Int32.Parse(m);
379 private static double ParseRt(
string line)
381 string ReplaceDecimalSeperator(
string toReplace)
383 return toReplace.Replace(
",", NumberFormatInfo.CurrentInfo.NumberDecimalSeparator, StringComparison.Ordinal)
384 .Replace(
".", NumberFormatInfo.CurrentInfo.NumberDecimalSeparator, StringComparison.Ordinal);
387 int inx = line.IndexOf(
"=", StringComparison.Ordinal);
388 string m = line.Substring(inx + 1);
389 m = ReplaceDecimalSeperator(m);
391 bool ok = Double.TryParse(m, out var rt);
392 if (!ok)
throw new Exception(
"Error in parsing: " + line);
397 private static int ParseScanNumber(
string line)
399 int inx = line.IndexOf(
"=", StringComparison.Ordinal);
400 string m = line.Substring(inx + 1);
401 if (m.Contains(
"MSMS:", StringComparison.Ordinal))
403 int idxMSMS = m.IndexOf(
"MSMS:", StringComparison.Ordinal);
404 m = m.Substring(idxMSMS + 5);
407 return Int32.Parse(m.Trim());
410 private static double ParseMOverZ(
string line)
412 string ReplaceDecimalSeperator(
string toReplace)
414 return toReplace.Replace(
",", NumberFormatInfo.CurrentInfo.NumberDecimalSeparator, StringComparison.Ordinal)
415 .Replace(
".", NumberFormatInfo.CurrentInfo.NumberDecimalSeparator, StringComparison.Ordinal);
418 double GetDoubleFromString(
string p)
420 if (
string.IsNullOrEmpty(p))
return -1;
424 return p.Contains(
".", StringComparison.Ordinal)
425 ?
double.Parse(p, CultureInfo.InvariantCulture)
426 :
double.Parse(ReplaceDecimalSeperator(p));
430 Console.WriteLine(e.ToString());
435 int inx = line.IndexOf(
" ", StringComparison.Ordinal);
438 inx = line.IndexOf(
"\t", StringComparison.Ordinal);
440 var m = (inx == -1) ? line.Substring(8) : line.Substring(8, inx - 8);
442 m = ReplaceDecimalSeperator(m);
443 var mOverZ = GetDoubleFromString(m);
447 private static bool LineCanBeIgnored(
string line)
451 if (
string.IsNullOrWhiteSpace(line))
454 var text = line.TrimStart().ToUpper();
456 if (text.StartsWith(
"#", StringComparison.Ordinal))
458 if (text.StartsWith(
"!", StringComparison.Ordinal))
460 if (text.StartsWith(
";", StringComparison.Ordinal))
462 if (text.StartsWith(
"/", StringComparison.Ordinal))
464 if (text.StartsWith(
"_", StringComparison.Ordinal))
467 if (text.StartsWith(
"MASS", StringComparison.Ordinal))
469 if (text.StartsWith(
"INSTRUMENT", StringComparison.Ordinal))
472 if (text.StartsWith(
"ACCESSION", StringComparison.Ordinal))
474 if (text.StartsWith(
"CLE", StringComparison.Ordinal))
476 if (text.StartsWith(
"COM", StringComparison.Ordinal))
478 if (text.StartsWith(
"CUTOUT", StringComparison.Ordinal))
480 if (text.StartsWith(
"COMP", StringComparison.Ordinal))
482 if (text.StartsWith(
"DB", StringComparison.Ordinal))
484 if (text.StartsWith(
"DECOY", StringComparison.Ordinal))
486 if (text.StartsWith(
"ERRORTOLERANT", StringComparison.Ordinal))
488 if (text.StartsWith(
"ETAG", StringComparison.Ordinal))
490 if (text.StartsWith(
"FORMAT", StringComparison.Ordinal))
492 if (text.StartsWith(
"FRAMES", StringComparison.Ordinal))
494 if (text.StartsWith(
"IT_MODS", StringComparison.Ordinal))
496 if (text.StartsWith(
"ITOL", StringComparison.Ordinal))
498 if (text.StartsWith(
"ITOLU", StringComparison.Ordinal))
500 if (text.StartsWith(
"LIBRARY_SEARCH", StringComparison.Ordinal))
502 if (text.StartsWith(
"LOCUS", StringComparison.Ordinal))
504 if (text.StartsWith(
"MODS", StringComparison.Ordinal))
506 if (text.StartsWith(
"MULTI_SITE_MODS", StringComparison.Ordinal))
508 if (text.StartsWith(
"PEP_ISOTOPE_ERROR", StringComparison.Ordinal))
510 if (text.StartsWith(
"PFA", StringComparison.Ordinal))
513 if (text.StartsWith(
"PRECURSOR", StringComparison.Ordinal))
515 if (text.StartsWith(
"QUANTIFICATION", StringComparison.Ordinal))
517 if (text.StartsWith(
"RAWFILE", StringComparison.Ordinal))
519 if (text.StartsWith(
"RAWSCANS", StringComparison.Ordinal))
521 if (text.StartsWith(
"REPORT", StringComparison.Ordinal))
523 if (text.StartsWith(
"REPTYPE", StringComparison.Ordinal))
525 if (text.StartsWith(
"SEARCH", StringComparison.Ordinal))
527 if (text.StartsWith(
"SEG", StringComparison.Ordinal))
529 if (text.StartsWith(
"SEQ", StringComparison.Ordinal))
531 if (text.StartsWith(
"TAG", StringComparison.Ordinal))
533 if (text.StartsWith(
"TAXONOMY", StringComparison.Ordinal))
535 if (text.StartsWith(
"TOL", StringComparison.Ordinal))
538 if (text.StartsWith(
"USER", StringComparison.Ordinal))