/// <summary> /// This creates a scan number-to-byte index for .mzML files that have no index. /// This means that a dynamic connection can be created with unindexed .mzML files, /// it just takes longer because we have to read the entire file one line at a time /// to create the index via code. /// /// This does NOT write an index to the .mzML file. This is intentional. This .mzML reader /// does not modify the .mzML data file at all. It just creates an index in memory /// via code if one is not provided in the .mzML file. /// </summary> private void CreateIndexFromUnindexedMzml() { reader.BaseStream.Position = 0; reader.DiscardBufferedData(); int scanNumber = 0; while (reader.Peek() > 0) { // this byte offset might be a little different than what it technically // should be because of white space but it will work out ok long byteOffset = TextFileReading.GetByteOffsetAtCurrentPosition(reader); var line = reader.ReadLine(); line = line.Trim(); if (line.StartsWith("<spectrum ", StringComparison.InvariantCultureIgnoreCase)) { Match result = nativeIdScanNumberParser.Match(line); int ind = line.IndexOf("id=\""); string nativeId; if (ind >= 0) { StringBuilder nativeIdBuilder = new StringBuilder(); for (int r = ind + 4; r < line.Length; r++) { if (line[r] == '"') { break; } nativeIdBuilder.Append(line[r]); } nativeId = nativeIdBuilder.ToString(); } else { throw new MzLibException("Could not get nativeID from line: " + line); } if (result.Groups[2].Success) { scanNumber = int.Parse(result.Groups[2].Value); } else { scanNumber++; } NativeIdToScanNumber.Add(nativeId, scanNumber); ScanNumberToByteOffset.Add(scanNumber, byteOffset); } } }
/// <summary> /// Mgf files are not indexed, so the index will need to be built. /// This method builds the index. /// </summary> private void BuildIndex() { scanToByteOffset = new Dictionary <int, long>(); int oneBasedScanNumber = 0; long currentPositionByteOffset = 0; long oneBasedScanByteOffset = 0; bool scanHasAScanNumber = false; while (reader.Peek() > 0) { currentPositionByteOffset = TextFileReading.GetByteOffsetAtCurrentPosition(reader); string line = reader.ReadLine(); if (line.StartsWith("BEGIN IONS", StringComparison.InvariantCultureIgnoreCase)) { oneBasedScanByteOffset = currentPositionByteOffset; scanHasAScanNumber = false; } else if (line.StartsWith("SCANS=", StringComparison.InvariantCultureIgnoreCase)) { scanHasAScanNumber = true; Match result = scanNumberParser.Match(line); var scanString = result.Groups[2].Value; oneBasedScanNumber = int.Parse(scanString); } else if (line.StartsWith("END IONS", StringComparison.InvariantCultureIgnoreCase)) { if (!scanHasAScanNumber) { oneBasedScanNumber++; } if (scanToByteOffset.ContainsKey(oneBasedScanNumber)) { throw new MzLibException("Scan number " + oneBasedScanNumber.ToString() + " appeared multiple times in " + FilePath + ", which is not allowed because we assume all scan numbers are unique."); } scanToByteOffset.Add(oneBasedScanNumber, oneBasedScanByteOffset); } } }