public static Ms1Scan Create(MsScan scan)
        {
            var ms1 = new Ms1Scan(
                scan.ScanNumber, scan.MsLevel, scan.PeaksCount,
                scan.Polarity, scan.ScanType, scan.FilterLine,
                scan.RetentionTime, scan.LowMz, scan.HighMz,
                scan.BasePeakMz, scan.BasePeakIntensity,
                scan.TotIonCurrent, scan.PeakData)
            {
                // Initialize list to hold references to Ms2Scans
                Ms2s = new List <Ms2Scan>()
            };

            return(ms1);
        }
        private bool ProcessFile(string filePath, string outputDirectoryPath)
        {
            try
            {
                OnStatusEvent(string.Format("Processing {0}", filePath));

                // Compute the SHA-1 hash of the .Raw file
                var fileSha1 = HashRawFile(filePath);

                // Disable loading the method
                // Method loading doesn't work on Linux and this program doesn't need that information
                var readerOptions = new ThermoReaderOptions
                {
                    LoadMSMethodInfo = false
                };

                // Open up the raw file connection
                var reader = new XRawFileIO(filePath, readerOptions);

                // Get all unique CV values from scans
                var cvValues = GetUniqueCvValues(reader);

                var totalScanCount = reader.GetNumScans();
                var scansProcessed = 0;

                var lastProgress = DateTime.UtcNow;

                // Reset tracking variables
                ByteTracking.Reset(true);

                // Now work for each unique CV value (# files we're going to need to split into)
                // get all scans that have the CV that we're currently targeting
                foreach (var cvValue in cvValues)
                {
                    var baseName = Path.GetFileNameWithoutExtension(filePath);

                    var mzXmlPath = Path.Combine(outputDirectoryPath, baseName + "_" + cvValue + ".mzXML");

                    OnDebugEvent(string.Format("Creating file {0}", mzXmlPath));

                    var targetScans = FindAllTargetScans(cvValue, reader);

                    var parentScanToMS2Map = new Dictionary <int, List <int> >();

                    using (var writer = new StreamWriter(new FileStream(mzXmlPath, FileMode.Create, FileAccess.Write, FileShare.Read)))
                    {
                        WriteHeader(writer, filePath, reader, fileSha1, targetScans);

                        Ms1Scan currentMS1Scan = null;

                        // Write out our target scans
                        foreach (var scanNumber in targetScans)
                        {
                            if (DateTime.UtcNow.Subtract(lastProgress).TotalSeconds >= 3)
                            {
                                var percentComplete = scansProcessed / (double)totalScanCount * 100;

                                OnDebugEvent(string.Format("... processing: {0:F0}% complete", percentComplete));
                                lastProgress = DateTime.UtcNow;
                            }

                            var scan = new MsScan(scanNumber, reader);

                            if (scan.MsLevel == 1)
                            {
                                parentScanToMS2Map.Add(scan.ScanNumber, new List <int>());

                                if (currentMS1Scan == null)
                                {
                                    // Start condition
                                    currentMS1Scan = Ms1Scan.Create(scan);
                                }
                                else
                                {
                                    // Write currentMS1Scan to file
                                    var outString = currentMS1Scan.ToXML(this);
                                    writer.WriteLine(outString);

                                    currentMS1Scan = Ms1Scan.Create(scan);
                                }
                            }
                            else if (scan.MsLevel == 2)
                            {
                                if (currentMS1Scan != null)
                                {
                                    parentScanToMS2Map[currentMS1Scan.ScanNumber].Add(scan.ScanNumber);
                                }

                                var ms2Scan = Ms2Scan.Create(scan);
                                ms2Scan.AddMs2ScanParameters(reader);
                                currentMS1Scan?.AddMs2Scan(ms2Scan);
                            }

                            scansProcessed++;
                        }

                        if (currentMS1Scan != null)
                        {
                            // Once we're out, we need to write out our last currentMS1Scan
                            writer.WriteLine(currentMS1Scan.ToXML(this));
                        }

                        // Finish off msRun
                        writer.WriteLine(" </msRun>");

                        writer.WriteLine(" <index name=\"scan\">");

                        // Add special entry to our indexOffset list for where the offsets start
                        var index = new Index(0, ByteTracking.ByteDepth + ByteTracking.Encoder.GetByteCount(" </msRun>") + 3);
                        ByteTracking.ScanOffsets.Add(index);

                        // Write all index offsets
                        for (var i = 0; i < ByteTracking.ScanOffsets.Count - 1; i++)
                        {
                            var offset = ByteTracking.ScanOffsets[i];
                            writer.WriteLine("  <offset id=\"" + offset.ScanNumber + "\">" + offset.ByteDepth + "</offset>");
                        }

                        writer.WriteLine(" </index>");
                        writer.WriteLine(" <indexOffset>" + ByteTracking.ScanOffsets.Last().ByteDepth + "</indexOffset>");
                        writer.Write(" <sha1>");
                    }

                    // Compute the SHA-1 hash of the file up to this point
                    var mzXmlHash = HashMzXML(mzXmlPath);

                    // Append the hash
                    using (var writer = new StreamWriter(mzXmlPath, true))
                    {
                        writer.Write(mzXmlHash);
                        writer.WriteLine("</sha1>");
                        writer.WriteLine("</mzXML>");
                    }

                    // Reset tracking variables, but do not restart scan numbering
                    ByteTracking.Reset(false);
                }

                OnDebugEvent(string.Format("... processing: {0:F0}% complete", 100));

                return(true);
            }
            catch (Exception ex)
            {
                OnErrorEvent("Error in ProcessFile", ex);
                return(false);
            }
        }