private void StoreExtendedHeaderInfo( clsDataOutput dataOutputHandler, clsScanInfo scanInfo, IReadOnlyCollection <KeyValuePair <string, string> > statusEntries) { StoreExtendedHeaderInfo(dataOutputHandler, scanInfo, statusEntries, new SortedSet <string>()); }
private void SaveRawDataToDiskWork( StreamWriter dataWriter, StreamWriter scanInfoWriter, clsScanInfo currentScan, clsSpectraCache spectraCache, string inputFileName, bool fragmentationScan, ref int spectrumExportCount) { switch (mOptions.RawDataExportOptions.FileFormat) { case clsRawDataExportOptions.eExportRawDataFileFormatConstants.PEKFile: SavePEKFileToDiskWork(dataWriter, currentScan, spectraCache, inputFileName, fragmentationScan, ref spectrumExportCount); break; case clsRawDataExportOptions.eExportRawDataFileFormatConstants.CSVFile: SaveCSVFilesToDiskWork(dataWriter, scanInfoWriter, currentScan, spectraCache, fragmentationScan, ref spectrumExportCount); break; default: // Unknown format // This code should never be reached break; } }
private int GetScanData(XRawFileIO reader, clsScanInfo scanInfo, out double[] mzList, out double[] intensityList) { if (scanInfo.IsFTMS) { var labelDataCount = reader.GetScanLabelData(scanInfo.ScanNumber, out var labelData); if (labelDataCount > 0) { mzList = new double[labelDataCount]; intensityList = new double[labelDataCount]; for (var i = 0; i < labelDataCount; i++) { mzList[i] = labelData[i].Mass; intensityList[i] = labelData[i].Intensity; } return(labelDataCount); } } var dataPointCount = reader.GetScanData(scanInfo.ScanNumber, out mzList, out intensityList, 0, true); return(dataPointCount); }
/// <summary> /// Constructor - open the file, and prepare to read /// </summary> /// <param name="filePath"></param> public XCaliburReader(string filePath) { _cachedScanInfo = new clsScanInfo(-1); _msfileReader = new XRawFileIO(); _msfileReader.ErrorEvent += _msfileReader_ErrorEvent; var dataFile = new FileInfo(filePath); if (!dataFile.Exists) { throw new FileNotFoundException("Thermo .raw file not found: " + filePath, dataFile.FullName); } FilePath = filePath; _checkSum = string.Empty; _msfileReader.OpenRawFile(filePath); _minLcScan = 1; NumSpectra = ReadNumSpectra(); _maxLcScan = NumSpectra; _msLevel = new Dictionary <int, int>(); FileFormatVersion = _msfileReader.FileInfo.VersionNumber.ToString(); }
private clsScanInfo GetScanByMasterScanIndex(clsScanList scanList, int masterScanIndex) { var currentScan = new clsScanInfo(); if (scanList.MasterScanOrder != null) { if (masterScanIndex < 0) { masterScanIndex = 0; } else if (masterScanIndex >= scanList.MasterScanOrderCount) { masterScanIndex = scanList.MasterScanOrderCount - 1; } switch (scanList.MasterScanOrder[masterScanIndex].ScanType) { case clsScanList.eScanTypeConstants.SurveyScan: // Survey scan currentScan = scanList.SurveyScans[scanList.MasterScanOrder[masterScanIndex].ScanIndexPointer]; break; case clsScanList.eScanTypeConstants.FragScan: // Frag Scan currentScan = scanList.FragScans[scanList.MasterScanOrder[masterScanIndex].ScanIndexPointer]; break; default: // Unknown scan type break; } } return(currentScan); }
/// <summary> /// Constructor - open the file, and prepare to read /// </summary> /// <param name="filePath"></param> public XCaliburReader(string filePath) { _cachedScanInfo = new clsScanInfo(-1); _msfileReader = new XRawFileIO(); var dataFile = new FileInfo(filePath); if (!dataFile.Exists) { throw new FileNotFoundException("Thermo .raw file not found: " + filePath, dataFile.FullName); } FilePath = filePath; using (var fs = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) using (var sha1 = new SHA1Managed()) { var hash = sha1.ComputeHash(fs); SrcFileChecksum = BitConverter.ToString(hash).ToLower().Replace("-", ""); } _msfileReader.OpenRawFile(filePath); _minLcScan = 1; _numSpectra = ReadNumSpectra(); _maxLcScan = _numSpectra; _msLevel = new Dictionary <int, int>(); FileFormatVersion = _msfileReader.FileInfo.VersionNumber.ToString(); }
private void WriteDecon2LSScanFileEntry( StreamWriter writer, clsScanInfo currentScan, clsSpectraCache spectraCache) { int numPeaks; if (spectraCache == null) { numPeaks = 0; } else { if (!spectraCache.GetSpectrum(currentScan.ScanNumber, out var spectrum, true)) { SetLocalErrorCode(clsMASIC.eMasicErrorCodes.ErrorUncachingSpectrum); return; } numPeaks = spectrum.IonCount; } var scanNumber = currentScan.ScanNumber; var msLevel = currentScan.FragScanInfo.MSLevel; if (msLevel < 1) { msLevel = 1; } var numIsotopicSignatures = 0; WriteDecon2LSScanFileEntry(writer, currentScan, scanNumber, msLevel, numPeaks, numIsotopicSignatures); }
/// <summary> /// Gets the clsScanInfo instance for the given scan /// </summary> /// <param name="scanNumber"></param> /// <param name="scanInfo"></param> /// <returns>Bool if successful, false if the scan number is out of range</returns> private bool TryGetScanInfo(int scanNumber, out clsScanInfo scanInfo) { if (scanNumber < mRawFileReader.FileInfo.ScanStart || scanNumber > mRawFileReader.FileInfo.ScanEnd) { scanInfo = new clsScanInfo(0); return(false); } var success = mRawFileReader.GetScanInfo(scanNumber, out scanInfo); return(success); }
private void StoreExtendedHeaderInfo( clsDataOutput dataOutputHandler, clsScanInfo scanInfo, string entryName, string entryValue) { if (entryValue == null) { entryValue = string.Empty; } var statusEntries = new List <KeyValuePair <string, string> >() { new KeyValuePair <string, string>(entryName, entryValue) }; StoreExtendedHeaderInfo(dataOutputHandler, scanInfo, statusEntries); }
private clsSpectrumTypeClassifier.eCentroidStatusConstants GetCentroidStatus( int scanNumber, clsScanInfo scanInfo) { if (scanInfo.IsCentroided) { if (mIsProfileM.IsMatch(scanInfo.FilterText)) { OnWarningEvent("Warning: Scan " + scanNumber + " appears to be profile mode data, yet XRawFileIO reported it to be centroid"); } return(clsSpectrumTypeClassifier.eCentroidStatusConstants.Centroid); } if (mIsCentroid.IsMatch(scanInfo.FilterText)) { OnWarningEvent("Warning: Scan " + scanNumber + " appears to be centroided data, yet XRawFileIO reported it to be profile"); } return(clsSpectrumTypeClassifier.eCentroidStatusConstants.Profile); }
public void WriteDecon2LSScanFileEntry( StreamWriter writer, clsScanInfo currentScan, int scanNumber, int msLevel, int numPeaks, int numIsotopicSignatures) { var dataLine = new List <string>() { scanNumber.ToString(), currentScan.ScanTime.ToString("0.0000"), msLevel.ToString(), DynamicValueToString(currentScan.BasePeakIonIntensity), currentScan.BasePeakIonMZ.ToString("0.00000"), DynamicValueToString(currentScan.TotalIonIntensity), numPeaks.ToString(), numIsotopicSignatures.ToString() }; writer.WriteLine(string.Join(",", dataLine)); }
private clsScanInfo GetParentScan(XRawFileIO reader, clsScanInfo scanInfo) { if (scanInfo.MSLevel <= 1) { return(scanInfo); } var parentScanNumber = scanInfo.ScanNumber - 1; while (parentScanNumber > 0) { var success = reader.GetScanInfo(parentScanNumber, out var parentScanInfo); if (success && parentScanInfo.MSLevel <= 1) { return(parentScanInfo); } parentScanNumber--; } reader.GetScanInfo(1, out var scanInfoFirstScan); return(scanInfoFirstScan); }
public bool ExtractScanInfoFromMGFandCDF( string filePath, clsScanList scanList, clsSpectraCache spectraCache, DataOutput.clsDataOutput dataOutputHandler, bool keepRawSpectra, bool keepMSMSSpectra) { // Returns True if Success, False if failure // Note: This function assumes filePath exists // // This function can be used to read a pair of MGF and NetCDF files that contain MS/MS and MS-only parent ion scans, respectively // Typically, this will apply to LC-MS/MS analyses acquired using an Agilent mass spectrometer running DataAnalysis software // filePath can contain the path to the MGF or to the CDF file; the extension will be removed in order to determine the base file name, // then the two files will be looked for separately var scanTime = 0.0; var cdfReader = new NetCDFReader.clsMSNetCdf(); var mgfReader = new MSDataFileReader.clsMGFFileReader(); try { Console.Write("Reading CDF/MGF data files "); ReportMessage("Reading CDF/MGF data files"); UpdateProgress(0, "Opening data file: " + Environment.NewLine + Path.GetFileName(filePath)); // Obtain the full path to the file var mgfFileInfo = new FileInfo(filePath); var mgfInputFilePathFull = mgfFileInfo.FullName; // Make sure the extension for mgfInputFilePathFull is .MGF mgfInputFilePathFull = Path.ChangeExtension(mgfInputFilePathFull, AGILENT_MSMS_FILE_EXTENSION); var cdfInputFilePathFull = Path.ChangeExtension(mgfInputFilePathFull, AGILENT_MS_FILE_EXTENSION); var datasetID = mOptions.SICOptions.DatasetID; var sicOptions = mOptions.SICOptions; var success = UpdateDatasetFileStats(mgfFileInfo, datasetID); mDatasetFileInfo.ScanCount = 0; // Open a handle to each data file if (!cdfReader.OpenMSCdfFile(cdfInputFilePathFull)) { ReportError("Error opening input data file: " + cdfInputFilePathFull); SetLocalErrorCode(clsMASIC.eMasicErrorCodes.InputFileAccessError); return(false); } if (!mgfReader.OpenFile(mgfInputFilePathFull)) { ReportError("Error opening input data file: " + mgfInputFilePathFull); SetLocalErrorCode(clsMASIC.eMasicErrorCodes.InputFileAccessError); return(false); } var msScanCount = cdfReader.GetScanCount(); mDatasetFileInfo.ScanCount = msScanCount; if (msScanCount <= 0) { // No scans found ReportError("No scans found in the input file: " + cdfInputFilePathFull); SetLocalErrorCode(clsMASIC.eMasicErrorCodes.InputFileAccessError); return(false); } // Reserve memory for all of the Survey Scan data scanList.Initialize(); var scanCount = mOptions.SICOptions.ScanRangeCount; if (scanCount <= 0) { scanCount = msScanCount * 3; } scanList.ReserveListCapacity(scanCount, Math.Min(msScanCount, scanCount / 3)); // Assume there are 2 frag scans for every survey scan mScanTracking.ReserveListCapacity(scanCount); spectraCache.SpectrumCount = Math.Max(spectraCache.SpectrumCount, scanCount); UpdateProgress("Reading CDF/MGF data (" + msScanCount.ToString() + " scans)" + Environment.NewLine + Path.GetFileName(filePath)); ReportMessage("Reading CDF/MGF data; Total MS scan count: " + msScanCount.ToString()); // Read all of the Survey scans from the CDF file // CDF files created by the Agilent XCT list the first scan number as 0; use scanNumberCorrection to correct for this var scanNumberCorrection = 0; for (var msScanIndex = 0; msScanIndex < msScanCount; msScanIndex++) { success = cdfReader.GetScanInfo(msScanIndex, out var scanNumber, out var scanTotalIntensity, out scanTime, out _, out _); if (msScanIndex == 0 && scanNumber == 0) { scanNumberCorrection = 1; } if (!success) { // Error reading CDF file ReportError("Error obtaining data from CDF file: " + cdfInputFilePathFull); SetLocalErrorCode(clsMASIC.eMasicErrorCodes.InputFileDataReadError); return(false); } if (scanNumberCorrection > 0) { scanNumber += scanNumberCorrection; } if (mScanTracking.CheckScanInRange(scanNumber, scanTime, sicOptions)) { var newSurveyScan = new clsScanInfo { ScanNumber = scanNumber, TotalIonIntensity = (float)scanTotalIntensity, // Copy the Total Scan Intensity to .TotalIonIntensity ScanHeaderText = string.Empty, ScanTypeName = "MS", }; if (mOptions.CDFTimeInSeconds) { newSurveyScan.ScanTime = (float)(scanTime / 60); } else { newSurveyScan.ScanTime = (float)scanTime; } // Survey scans typically lead to multiple parent ions; we do not record them here newSurveyScan.FragScanInfo.ParentIonInfoIndex = -1; scanList.SurveyScans.Add(newSurveyScan); success = cdfReader.GetMassSpectrum(msScanIndex, out var mzData, out var intensityData, out var intIonCount, out _); if (success && intIonCount > 0) { var msSpectrum = new clsMSSpectrum(scanNumber, mzData, intensityData, intIonCount); double msDataResolution; newSurveyScan.IonCount = msSpectrum.IonCount; newSurveyScan.IonCountRaw = newSurveyScan.IonCount; // Find the base peak ion mass and intensity newSurveyScan.BasePeakIonMZ = FindBasePeakIon(msSpectrum.IonsMZ, msSpectrum.IonsIntensity, out var basePeakIonIntensity, out var mzMin, out var mzMax); newSurveyScan.BasePeakIonIntensity = basePeakIonIntensity; // Determine the minimum positive intensity in this scan newSurveyScan.MinimumPositiveIntensity = mPeakFinder.FindMinimumPositiveValue(msSpectrum.IonsIntensity, 0); if (sicOptions.SICToleranceIsPPM) { // Define MSDataResolution based on the tolerance value that will be used at the lowest m/z in this spectrum, divided by COMPRESS_TOLERANCE_DIVISOR // However, if the lowest m/z value is < 100, then use 100 m/z if (mzMin < 100) { msDataResolution = clsParentIonProcessing.GetParentIonToleranceDa(sicOptions, 100) / sicOptions.CompressToleranceDivisorForPPM; } else { msDataResolution = clsParentIonProcessing.GetParentIonToleranceDa(sicOptions, mzMin) / sicOptions.CompressToleranceDivisorForPPM; } } else { msDataResolution = sicOptions.SICTolerance / sicOptions.CompressToleranceDivisorForDa; } mScanTracking.ProcessAndStoreSpectrum( newSurveyScan, this, spectraCache, msSpectrum, sicOptions.SICPeakFinderOptions.MassSpectraNoiseThresholdOptions, clsMASIC.DISCARD_LOW_INTENSITY_MS_DATA_ON_LOAD, sicOptions.CompressMSSpectraData, msDataResolution, keepRawSpectra); } else { newSurveyScan.IonCount = 0; newSurveyScan.IonCountRaw = 0; } // Note: Since we're reading all of the Survey Scan data, we cannot update .MasterScanOrder() at this time } // Note: We need to take msScanCount * 2 since we have to read two different files if (msScanCount > 1) { UpdateProgress((short)(msScanIndex / (double)(msScanCount * 2 - 1) * 100)); } else { UpdateProgress(0); } UpdateCacheStats(spectraCache); if (mOptions.AbortProcessing) { scanList.ProcessingIncomplete = true; break; } if (msScanIndex % 100 == 0) { ReportMessage("Reading MS scan index: " + msScanIndex.ToString()); Console.Write("."); } } // Record the current memory usage (before we close the .CDF file) OnUpdateMemoryUsage(); cdfReader.CloseMSCdfFile(); // We loaded all of the survey scan data above // We can now initialize .MasterScanOrder() var lastSurveyScanIndex = 0; scanList.AddMasterScanEntry(clsScanList.eScanTypeConstants.SurveyScan, lastSurveyScanIndex); var surveyScansRecorded = new SortedSet <int>() { lastSurveyScanIndex }; // Reset scanNumberCorrection; we might also apply it to MS/MS data scanNumberCorrection = 0; // Now read the MS/MS data from the MGF file do { var fragScanFound = mgfReader.ReadNextSpectrum(out var spectrumInfo); if (!fragScanFound) { break; } mDatasetFileInfo.ScanCount += 1; while (spectrumInfo.ScanNumber < scanList.SurveyScans[lastSurveyScanIndex].ScanNumber) { // The scan number for the current MS/MS spectrum is less than the last survey scan index scan number // This can happen, due to oddities with combining scans when creating the .MGF file // Need to decrement lastSurveyScanIndex until we find the appropriate survey scan lastSurveyScanIndex -= 1; if (lastSurveyScanIndex == 0) { break; } } if (scanNumberCorrection == 0) { // See if udtSpectrumHeaderInfo.ScanNumberStart is equivalent to one of the survey scan numbers, yielding conflicting scan numbers // If it is, then there is an indexing error in the .MGF file; this error was present in .MGF files generated with // an older version of Agilent Chemstation. These files typically have lines like ###MSMS: #13-29 instead of ###MSMS: #13/29/ // If this indexing error is found, then we'll set scanNumberCorrection = 1 and apply it to all subsequent MS/MS scans; // we'll also need to correct prior MS/MS scans for (var surveyScanIndex = lastSurveyScanIndex; surveyScanIndex < scanList.SurveyScans.Count; surveyScanIndex++) { if (scanList.SurveyScans[surveyScanIndex].ScanNumber == spectrumInfo.ScanNumber) { // Conflicting scan numbers were found scanNumberCorrection = 1; // Need to update prior MS/MS scans foreach (var fragScan in scanList.FragScans) { fragScan.ScanNumber += scanNumberCorrection; var scanTimeInterpolated = InterpolateRTandFragScanNumber( scanList.SurveyScans, 0, fragScan.ScanNumber, out var fragScanIterationOut); fragScan.FragScanInfo.FragScanNumber = fragScanIterationOut; fragScan.ScanTime = scanTimeInterpolated; } break; } if (scanList.SurveyScans[surveyScanIndex].ScanNumber > spectrumInfo.ScanNumber) { break; } } } if (scanNumberCorrection > 0) { spectrumInfo.ScanNumber += scanNumberCorrection; spectrumInfo.ScanNumberEnd += scanNumberCorrection; } scanTime = InterpolateRTandFragScanNumber( scanList.SurveyScans, lastSurveyScanIndex, spectrumInfo.ScanNumber, out var fragScanIteration); // Make sure this fragmentation scan isn't present yet in scanList.FragScans // This can occur in Agilent .MGF files if the scan is listed both singly and grouped with other MS/MS scans var validFragScan = true; foreach (var fragScan in scanList.FragScans) { if (fragScan.ScanNumber == spectrumInfo.ScanNumber) { // Duplicate found validFragScan = false; break; } } if (!(validFragScan && mScanTracking.CheckScanInRange(spectrumInfo.ScanNumber, scanTime, sicOptions))) { continue; } // See if lastSurveyScanIndex needs to be updated // At the same time, populate .MasterScanOrder while (lastSurveyScanIndex < scanList.SurveyScans.Count - 1 && spectrumInfo.ScanNumber > scanList.SurveyScans[lastSurveyScanIndex + 1].ScanNumber) { lastSurveyScanIndex += 1; // Add the given SurveyScan to .MasterScanOrder, though only if it hasn't yet been added if (!surveyScansRecorded.Contains(lastSurveyScanIndex)) { surveyScansRecorded.Add(lastSurveyScanIndex); scanList.AddMasterScanEntry(clsScanList.eScanTypeConstants.SurveyScan, lastSurveyScanIndex); } } scanList.AddMasterScanEntry(clsScanList.eScanTypeConstants.FragScan, scanList.FragScans.Count, spectrumInfo.ScanNumber, (float)scanTime); var newFragScan = new clsScanInfo { ScanNumber = spectrumInfo.ScanNumber, ScanTime = (float)scanTime, ScanHeaderText = string.Empty, ScanTypeName = "MSn", }; newFragScan.FragScanInfo.FragScanNumber = fragScanIteration; newFragScan.FragScanInfo.MSLevel = 2; newFragScan.MRMScanInfo.MRMMassCount = 0; scanList.FragScans.Add(newFragScan); var msSpectrum = new clsMSSpectrum(newFragScan.ScanNumber, spectrumInfo.MZList, spectrumInfo.IntensityList, spectrumInfo.DataCount); if (spectrumInfo.DataCount > 0) { newFragScan.IonCount = msSpectrum.IonCount; newFragScan.IonCountRaw = newFragScan.IonCount; // Find the base peak ion mass and intensity newFragScan.BasePeakIonMZ = FindBasePeakIon(msSpectrum.IonsMZ, msSpectrum.IonsIntensity, out var basePeakIonIntensity, out _, out _); newFragScan.BasePeakIonIntensity = basePeakIonIntensity; // Compute the total scan intensity newFragScan.TotalIonIntensity = 0; for (var ionIndex = 0; ionIndex < newFragScan.IonCount; ionIndex++) { newFragScan.TotalIonIntensity += msSpectrum.IonsIntensity[ionIndex]; } // Determine the minimum positive intensity in this scan newFragScan.MinimumPositiveIntensity = mPeakFinder.FindMinimumPositiveValue(msSpectrum.IonsIntensity, 0); var msDataResolution = mOptions.BinningOptions.BinSize / sicOptions.CompressToleranceDivisorForDa; var keepRawSpectrum = keepRawSpectra && keepMSMSSpectra; mScanTracking.ProcessAndStoreSpectrum( newFragScan, this, spectraCache, msSpectrum, sicOptions.SICPeakFinderOptions.MassSpectraNoiseThresholdOptions, clsMASIC.DISCARD_LOW_INTENSITY_MSMS_DATA_ON_LOAD, sicOptions.CompressMSMSSpectraData, msDataResolution, keepRawSpectrum); } else { newFragScan.IonCount = 0; newFragScan.IonCountRaw = 0; newFragScan.TotalIonIntensity = 0; } mParentIonProcessor.AddUpdateParentIons(scanList, lastSurveyScanIndex, spectrumInfo.ParentIonMZ, scanList.FragScans.Count - 1, spectraCache, sicOptions); // Note: We need to take msScanCount * 2, in addition to adding msScanCount to lastSurveyScanIndex, since we have to read two different files if (msScanCount > 1) { UpdateProgress((short)((lastSurveyScanIndex + msScanCount) / (double)(msScanCount * 2 - 1) * 100)); } else { UpdateProgress(0); } UpdateCacheStats(spectraCache); if (mOptions.AbortProcessing) { scanList.ProcessingIncomplete = true; break; } if (scanList.FragScans.Count % 100 == 0) { ReportMessage("Reading MSMS scan index: " + scanList.FragScans.Count); Console.Write("."); } }while (true); // Record the current memory usage (before we close the .MGF file) OnUpdateMemoryUsage(); mgfReader.CloseFile(); // Check for any other survey scans that need to be added to MasterScanOrder // See if lastSurveyScanIndex needs to be updated // At the same time, populate .MasterScanOrder while (lastSurveyScanIndex < scanList.SurveyScans.Count - 1) { lastSurveyScanIndex += 1; // Note that scanTime is the scan time of the most recent survey scan processed in the above Do loop, so it's not accurate if (mScanTracking.CheckScanInRange(scanList.SurveyScans[lastSurveyScanIndex].ScanNumber, scanTime, sicOptions)) { // Add the given SurveyScan to .MasterScanOrder, though only if it hasn't yet been added if (!surveyScansRecorded.Contains(lastSurveyScanIndex)) { surveyScansRecorded.Add(lastSurveyScanIndex); scanList.AddMasterScanEntry(clsScanList.eScanTypeConstants.SurveyScan, lastSurveyScanIndex); } } } // Make sure that MasterScanOrder really is sorted by scan number ValidateMasterScanOrderSorting(scanList); // Now that all of the data has been read, write out to the scan stats file, in order of scan number for (var scanIndex = 0; scanIndex < scanList.MasterScanOrderCount; scanIndex++) { var eScanType = scanList.MasterScanOrder[scanIndex].ScanType; clsScanInfo currentScan; if (eScanType == clsScanList.eScanTypeConstants.SurveyScan) { // Survey scan currentScan = scanList.SurveyScans[scanList.MasterScanOrder[scanIndex].ScanIndexPointer]; } else { // Frag Scan currentScan = scanList.FragScans[scanList.MasterScanOrder[scanIndex].ScanIndexPointer]; } SaveScanStatEntry(dataOutputHandler.OutputFileHandles.ScanStats, eScanType, currentScan, sicOptions.DatasetID); } Console.WriteLine(); scanList.SetListCapacityToCount(); mScanTracking.SetListCapacityToCount(); return(success); } catch (Exception ex) { ReportError("Error in ExtractScanInfoFromMGFandCDF", ex, clsMASIC.eMasicErrorCodes.InputFileDataReadError); return(false); } }
protected void SaveScanStatEntry( StreamWriter writer, clsScanList.eScanTypeConstants eScanType, clsScanInfo currentScan, int datasetID) { const char TAB_DELIMITER = '\t'; var scanStatsEntry = new ScanStatsEntry() { ScanNumber = currentScan.ScanNumber }; if (eScanType == clsScanList.eScanTypeConstants.SurveyScan) { scanStatsEntry.ScanType = 1; scanStatsEntry.ScanTypeName = string.Copy(currentScan.ScanTypeName); } else { if (currentScan.FragScanInfo.MSLevel <= 1) { // This is a fragmentation scan, so it must have a scan type of at least 2 scanStatsEntry.ScanType = 2; } else { // .MSLevel is 2 or higher, record the actual MSLevel value scanStatsEntry.ScanType = currentScan.FragScanInfo.MSLevel; } scanStatsEntry.ScanTypeName = string.Copy(currentScan.ScanTypeName); } scanStatsEntry.ScanFilterText = currentScan.ScanHeaderText; scanStatsEntry.ElutionTime = currentScan.ScanTime.ToString("0.0000"); scanStatsEntry.TotalIonIntensity = StringUtilities.ValueToString(currentScan.TotalIonIntensity, 5); scanStatsEntry.BasePeakIntensity = StringUtilities.ValueToString(currentScan.BasePeakIonIntensity, 5); scanStatsEntry.BasePeakMZ = StringUtilities.DblToString(currentScan.BasePeakIonMZ, 4); // Base peak signal to noise ratio scanStatsEntry.BasePeakSignalToNoiseRatio = StringUtilities.ValueToString(MASICPeakFinder.clsMASICPeakFinder.ComputeSignalToNoise(currentScan.BasePeakIonIntensity, currentScan.BaselineNoiseStats.NoiseLevel), 4); scanStatsEntry.IonCount = currentScan.IonCount; scanStatsEntry.IonCountRaw = currentScan.IonCountRaw; mScanTracking.ScanStats.Add(scanStatsEntry); var dataColumns = new List <string>() { datasetID.ToString(), // Dataset ID scanStatsEntry.ScanNumber.ToString(), // Scan number scanStatsEntry.ElutionTime, // Scan time (minutes) scanStatsEntry.ScanType.ToString(), // Scan type (1 for MS, 2 for MS2, etc.) scanStatsEntry.TotalIonIntensity, // Total ion intensity scanStatsEntry.BasePeakIntensity, // Base peak ion intensity scanStatsEntry.BasePeakMZ, // Base peak ion m/z scanStatsEntry.BasePeakSignalToNoiseRatio, // Base peak signal to noise ratio scanStatsEntry.IonCount.ToString(), // Number of peaks (aka ions) in the spectrum scanStatsEntry.IonCountRaw.ToString(), // Number of peaks (aka ions) in the spectrum prior to any filtering scanStatsEntry.ScanTypeName // Scan type name }; writer.WriteLine(string.Join(TAB_DELIMITER.ToString(), dataColumns)); }
private bool ExtractXcaliburSurveyScan( XRawFileIO xcaliburAccessor, clsScanList scanList, clsSpectraCache spectraCache, clsDataOutput dataOutputHandler, clsSICOptions sicOptions, ThermoRawFileReader.clsScanInfo thermoScanInfo) { var scanInfo = new clsScanInfo() { ScanNumber = thermoScanInfo.ScanNumber, ScanTime = (float)thermoScanInfo.RetentionTime, ScanHeaderText = XRawFileIO.MakeGenericThermoScanFilter(thermoScanInfo.FilterText), ScanTypeName = XRawFileIO.GetScanTypeNameFromThermoScanFilterText(thermoScanInfo.FilterText), BasePeakIonMZ = thermoScanInfo.BasePeakMZ, BasePeakIonIntensity = thermoScanInfo.BasePeakIntensity, TotalIonIntensity = thermoScanInfo.TotalIonCurrent, MinimumPositiveIntensity = 0, // This will be determined in LoadSpectraForThermoRawFile ZoomScan = thermoScanInfo.ZoomScan, SIMScan = thermoScanInfo.SIMScan, MRMScanType = thermoScanInfo.MRMScanType, LowMass = thermoScanInfo.LowMass, HighMass = thermoScanInfo.HighMass, IsFTMS = thermoScanInfo.IsFTMS }; // Survey scans typically lead to multiple parent ions; we do not record them here scanInfo.FragScanInfo.ParentIonInfoIndex = -1; if (scanInfo.MRMScanType != MRMScanTypeConstants.NotMRM) { // This is an MRM scan scanList.MRMDataPresent = true; } if (scanInfo.SIMScan) { scanList.SIMDataPresent = true; var simKey = scanInfo.LowMass + "_" + scanInfo.HighMass; if (mSIMScanMapping.TryGetValue(simKey, out var simIndex)) { scanInfo.SIMIndex = simIndex; } else { scanInfo.SIMIndex = mSIMScanMapping.Count; mSIMScanMapping.Add(simKey, mSIMScanMapping.Count); } } // Store the ScanEvent values in .ExtendedHeaderInfo StoreExtendedHeaderInfo(dataOutputHandler, scanInfo, thermoScanInfo.ScanEvents); // Store the collision mode and possibly the scan filter text scanInfo.FragScanInfo.CollisionMode = thermoScanInfo.CollisionMode; StoreExtendedHeaderInfo(dataOutputHandler, scanInfo, clsExtendedStatsWriter.EXTENDED_STATS_HEADER_COLLISION_MODE, thermoScanInfo.CollisionMode); if (mOptions.WriteExtendedStatsIncludeScanFilterText) { StoreExtendedHeaderInfo(dataOutputHandler, scanInfo, clsExtendedStatsWriter.EXTENDED_STATS_HEADER_SCAN_FILTER_TEXT, thermoScanInfo.FilterText); } if (mOptions.WriteExtendedStatsStatusLog) { // Store the StatusLog values in .ExtendedHeaderInfo StoreExtendedHeaderInfo(dataOutputHandler, scanInfo, thermoScanInfo.StatusLog, mOptions.StatusLogKeyNameFilterList); } scanList.SurveyScans.Add(scanInfo); if (!scanInfo.ZoomScan) { mLastNonZoomSurveyScanIndex = scanList.SurveyScans.Count - 1; } scanList.AddMasterScanEntry(clsScanList.eScanTypeConstants.SurveyScan, scanList.SurveyScans.Count - 1); double msDataResolution; if (sicOptions.SICToleranceIsPPM) { // Define MSDataResolution based on the tolerance value that will be used at the lowest m/z in this spectrum, divided by sicOptions.CompressToleranceDivisorForPPM // However, if the lowest m/z value is < 100, then use 100 m/z if (thermoScanInfo.LowMass < 100) { msDataResolution = clsParentIonProcessing.GetParentIonToleranceDa(sicOptions, 100) / sicOptions.CompressToleranceDivisorForPPM; } else { msDataResolution = clsParentIonProcessing.GetParentIonToleranceDa(sicOptions, thermoScanInfo.LowMass) / sicOptions.CompressToleranceDivisorForPPM; } } else { msDataResolution = sicOptions.SICTolerance / sicOptions.CompressToleranceDivisorForDa; } // Note: Even if mKeepRawSpectra = False, we still need to load the raw data so that we can compute the noise level for the spectrum var success = LoadSpectraForThermoRawFile( xcaliburAccessor, spectraCache, scanInfo, sicOptions.SICPeakFinderOptions.MassSpectraNoiseThresholdOptions, clsMASIC.DISCARD_LOW_INTENSITY_MS_DATA_ON_LOAD, sicOptions.CompressMSSpectraData, msDataResolution, mKeepRawSpectra); if (!success) { return(false); } SaveScanStatEntry(dataOutputHandler.OutputFileHandles.ScanStats, clsScanList.eScanTypeConstants.SurveyScan, scanInfo, sicOptions.DatasetID); return(true); }
private bool ExtractXcaliburFragmentationScan( XRawFileIO xcaliburAccessor, clsScanList scanList, clsSpectraCache spectraCache, clsDataOutput dataOutputHandler, clsSICOptions sicOptions, clsBinningOptions binningOptions, ThermoRawFileReader.clsScanInfo thermoScanInfo) { // Note that MinimumPositiveIntensity will be determined in LoadSpectraForThermoRawFile var scanInfo = new clsScanInfo(thermoScanInfo.ParentIonMZ) { ScanNumber = thermoScanInfo.ScanNumber, ScanTime = (float)thermoScanInfo.RetentionTime, ScanHeaderText = XRawFileIO.MakeGenericThermoScanFilter(thermoScanInfo.FilterText), ScanTypeName = XRawFileIO.GetScanTypeNameFromThermoScanFilterText(thermoScanInfo.FilterText), BasePeakIonMZ = thermoScanInfo.BasePeakMZ, BasePeakIonIntensity = thermoScanInfo.BasePeakIntensity, TotalIonIntensity = thermoScanInfo.TotalIonCurrent, MinimumPositiveIntensity = 0, ZoomScan = thermoScanInfo.ZoomScan, SIMScan = thermoScanInfo.SIMScan, MRMScanType = thermoScanInfo.MRMScanType }; // Typically .EventNumber is 1 for the parent-ion scan; 2 for 1st frag scan, 3 for 2nd frag scan, etc. // This resets for each new parent-ion scan scanInfo.FragScanInfo.FragScanNumber = thermoScanInfo.EventNumber - 1; // The .EventNumber value is sometimes wrong; need to check for this // For example, if the dataset only has MS2 scans and no parent-ion scan, .EventNumber will be 2 for every MS2 scan if (scanList.FragScans.Count > 0) { var prevFragScan = scanList.FragScans[scanList.FragScans.Count - 1]; if (prevFragScan.ScanNumber == scanInfo.ScanNumber - 1) { if (scanInfo.FragScanInfo.FragScanNumber <= prevFragScan.FragScanInfo.FragScanNumber) { scanInfo.FragScanInfo.FragScanNumber = prevFragScan.FragScanInfo.FragScanNumber + 1; } } } scanInfo.FragScanInfo.MSLevel = thermoScanInfo.MSLevel; if (scanInfo.MRMScanType != MRMScanTypeConstants.NotMRM) { // This is an MRM scan scanList.MRMDataPresent = true; scanInfo.MRMScanInfo = clsMRMProcessing.DuplicateMRMInfo(thermoScanInfo.MRMInfo, thermoScanInfo.ParentIonMZ); if (scanList.SurveyScans.Count == 0) { // Need to add a "fake" survey scan that we can map this parent ion to mLastNonZoomSurveyScanIndex = scanList.AddFakeSurveyScan(); } } else { scanInfo.MRMScanInfo.MRMMassCount = 0; } scanInfo.LowMass = thermoScanInfo.LowMass; scanInfo.HighMass = thermoScanInfo.HighMass; scanInfo.IsFTMS = thermoScanInfo.IsFTMS; // Store the ScanEvent values in .ExtendedHeaderInfo StoreExtendedHeaderInfo(dataOutputHandler, scanInfo, thermoScanInfo.ScanEvents); // Store the collision mode and possibly the scan filter text scanInfo.FragScanInfo.CollisionMode = thermoScanInfo.CollisionMode; StoreExtendedHeaderInfo(dataOutputHandler, scanInfo, clsExtendedStatsWriter.EXTENDED_STATS_HEADER_COLLISION_MODE, thermoScanInfo.CollisionMode); if (mOptions.WriteExtendedStatsIncludeScanFilterText) { StoreExtendedHeaderInfo(dataOutputHandler, scanInfo, clsExtendedStatsWriter.EXTENDED_STATS_HEADER_SCAN_FILTER_TEXT, thermoScanInfo.FilterText); } if (mOptions.WriteExtendedStatsStatusLog) { // Store the StatusLog values in .ExtendedHeaderInfo StoreExtendedHeaderInfo(dataOutputHandler, scanInfo, thermoScanInfo.StatusLog, mOptions.StatusLogKeyNameFilterList); } scanList.FragScans.Add(scanInfo); var fragScanIndex = scanList.FragScans.Count - 1; scanList.AddMasterScanEntry(clsScanList.eScanTypeConstants.FragScan, fragScanIndex); // Note: Even if keepRawSpectra = False, we still need to load the raw data so that we can compute the noise level for the spectrum var msDataResolution = binningOptions.BinSize / sicOptions.CompressToleranceDivisorForDa; var success = LoadSpectraForThermoRawFile( xcaliburAccessor, spectraCache, scanInfo, sicOptions.SICPeakFinderOptions.MassSpectraNoiseThresholdOptions, clsMASIC.DISCARD_LOW_INTENSITY_MSMS_DATA_ON_LOAD, sicOptions.CompressMSMSSpectraData, msDataResolution, mKeepRawSpectra && mKeepMSMSSpectra); if (!success) { return(false); } SaveScanStatEntry(dataOutputHandler.OutputFileHandles.ScanStats, clsScanList.eScanTypeConstants.FragScan, scanInfo, sicOptions.DatasetID); if (thermoScanInfo.MRMScanType == MRMScanTypeConstants.NotMRM) { // This is not an MRM scan mParentIonProcessor.AddUpdateParentIons(scanList, mLastNonZoomSurveyScanIndex, thermoScanInfo.ParentIonMZ, fragScanIndex, spectraCache, sicOptions); } else { // This is an MRM scan mParentIonProcessor.AddUpdateParentIons(scanList, mLastNonZoomSurveyScanIndex, thermoScanInfo.ParentIonMZ, scanInfo.MRMScanInfo, spectraCache, sicOptions); } if (mLastNonZoomSurveyScanIndex >= 0) { var precursorScanNumber = scanList.SurveyScans[mLastNonZoomSurveyScanIndex].ScanNumber; // Compute the interference of the parent ion in the MS1 spectrum for this frag scan scanInfo.FragScanInfo.InterferenceScore = ComputeInterference(xcaliburAccessor, thermoScanInfo, precursorScanNumber); } return(true); }
private bool LoadSpectraForThermoRawFile( XRawFileIO xcaliburAccessor, clsSpectraCache spectraCache, clsScanInfo scanInfo, clsBaselineNoiseOptions noiseThresholdOptions, bool discardLowIntensityData, bool compressSpectraData, double msDataResolution, bool keepRawSpectrum) { var lastKnownLocation = "Start"; try { // Load the ions for this scan lastKnownLocation = "xcaliburAccessor.GetScanData for scan " + scanInfo.ScanNumber; // Retrieve the m/z and intensity values for the given scan // We retrieve the profile-mode data, since that's required for determining spectrum noise scanInfo.IonCountRaw = xcaliburAccessor.GetScanData(scanInfo.ScanNumber, out var mzList, out var intensityList); if (scanInfo.IonCountRaw > 0) { var ionCountVerified = VerifyDataSorted(scanInfo.ScanNumber, scanInfo.IonCountRaw, mzList, intensityList); if (ionCountVerified != scanInfo.IonCountRaw) { scanInfo.IonCountRaw = ionCountVerified; } } scanInfo.IonCount = scanInfo.IonCountRaw; lastKnownLocation = "Instantiate new clsMSSpectrum"; var msSpectrum = new clsMSSpectrum(scanInfo.ScanNumber, mzList, intensityList, scanInfo.IonCountRaw); lastKnownLocation = "Manually determine the base peak m/z and base peak intensity"; // ReSharper disable once CommentTypo // Regarding BPI, comparison of data read via the ThermoRawFileReader vs. // that read from the .mzML file for dataset QC_Shew_18_02-run1_02Mar19_Arwen_18-11-02 // showed that 25% of the spectra had incorrect BPI values double totalIonIntensity = 0; double basePeakIntensity = 0; double basePeakMz = 0; for (var ionIndex = 0; ionIndex < scanInfo.IonCountRaw; ionIndex++) { totalIonIntensity += intensityList[ionIndex]; if (intensityList[ionIndex] > basePeakIntensity) { basePeakIntensity = intensityList[ionIndex]; basePeakMz = mzList[ionIndex]; } } if (Math.Abs(scanInfo.BasePeakIonMZ - basePeakMz) > 0.1) { mBpiUpdateCount += 1; if (mBpiUpdateCount < 10) { ConsoleMsgUtils.ShowDebug("Updating BPI in scan {0} from {1:F3} m/z to {2:F3} m/z, and BPI Intensity from {3:F0} to {4:F0}", scanInfo.ScanNumber, scanInfo.BasePeakIonMZ, basePeakMz, scanInfo.BasePeakIonIntensity, basePeakIntensity); } scanInfo.BasePeakIonMZ = basePeakMz; scanInfo.BasePeakIonIntensity = basePeakIntensity; } // Determine the minimum positive intensity in this scan lastKnownLocation = "Call mMASICPeakFinder.FindMinimumPositiveValue"; scanInfo.MinimumPositiveIntensity = mPeakFinder.FindMinimumPositiveValue(msSpectrum.IonsIntensity, 0); if (msSpectrum.IonCount > 0) { if (scanInfo.TotalIonIntensity < float.Epsilon) { scanInfo.TotalIonIntensity = totalIonIntensity; } } else { scanInfo.TotalIonIntensity = 0; } bool discardLowIntensityDataWork; bool compressSpectraDataWork; if (scanInfo.MRMScanType == MRMScanTypeConstants.NotMRM) { discardLowIntensityDataWork = discardLowIntensityData; compressSpectraDataWork = compressSpectraData; } else { discardLowIntensityDataWork = false; compressSpectraDataWork = false; } lastKnownLocation = "Call ProcessAndStoreSpectrum"; mScanTracking.ProcessAndStoreSpectrum( scanInfo, this, spectraCache, msSpectrum, noiseThresholdOptions, discardLowIntensityDataWork, compressSpectraDataWork, msDataResolution, keepRawSpectrum); } catch (Exception ex) { ReportError("Error in LoadSpectraForThermoRawFile (LastKnownLocation: " + lastKnownLocation + ")", ex, clsMASIC.eMasicErrorCodes.InputFileDataReadError); return(false); } return(true); }
private void StoreExtendedHeaderInfo( clsDataOutput dataOutputHandler, clsScanInfo scanInfo, IReadOnlyCollection <KeyValuePair <string, string> > statusEntries, IReadOnlyCollection <string> keyNameFilterList) { var filterItems = false; try { if (statusEntries == null) { return; } if (keyNameFilterList != null && keyNameFilterList.Count > 0) { if (keyNameFilterList.Any(item => item.Length > 0)) { filterItems = true; } } foreach (var statusEntry in statusEntries) { if (string.IsNullOrWhiteSpace(statusEntry.Key)) { // Empty entry name; do not add continue; } bool saveItem; if (filterItems) { saveItem = false; foreach (var item in keyNameFilterList) { if (statusEntry.Key.ToLower().Contains(item.ToLower())) { saveItem = true; break; } } } else { saveItem = true; } if (string.IsNullOrWhiteSpace(statusEntry.Key) || statusEntry.Key.Equals("1")) { // Name is null; skip it saveItem = false; } if (saveItem) { var extendedHeaderID = dataOutputHandler.ExtendedStatsWriter.GetExtendedHeaderInfoIdByName(statusEntry.Key); // Add or update the value for extendedHeaderID scanInfo.ExtendedHeaderInfo[extendedHeaderID] = statusEntry.Value.Trim(); } } } catch (Exception ex) { // Ignore any errors here } }
private void SavePEKFileToDiskWork( TextWriter writer, clsScanInfo currentScan, clsSpectraCache spectraCache, string inputFileName, bool fragmentationScan, ref int spectrumExportCount) { var exportCount = 0; if (!spectraCache.GetSpectrum(currentScan.ScanNumber, out var spectrum, true)) { SetLocalErrorCode(clsMASIC.eMasicErrorCodes.ErrorUncachingSpectrum); return; } spectrumExportCount += 1; writer.WriteLine("Time domain signal level:" + "\t" + currentScan.BasePeakIonIntensity.ToString("0.000")); // Store the base peak ion intensity as the time domain signal level value writer.WriteLine("MASIC " + mOptions.MASICVersion); // Software version var dataLine = "MS/MS-based PEK file"; if (mOptions.RawDataExportOptions.IncludeMSMS) { dataLine += " (includes both survey scans and fragmentation spectra)"; } else { dataLine += " (includes only survey scans)"; } writer.WriteLine(dataLine); int scanNumber; if (mOptions.RawDataExportOptions.RenumberScans) { scanNumber = spectrumExportCount; } else { scanNumber = currentScan.ScanNumber; } dataLine = "Filename: " + inputFileName + "." + scanNumber.ToString("00000"); writer.WriteLine(dataLine); if (fragmentationScan) { writer.WriteLine("ScanType: Fragmentation Scan"); } else { writer.WriteLine("ScanType: Survey Scan"); } writer.WriteLine("Charge state mass transform results:"); writer.WriteLine("First CS, Number of CS, Abundance, Mass, Standard deviation"); if (spectrum.IonCount > 0) { // Populate intensities and pointerArray() var intensities = new double[spectrum.IonCount]; var pointerArray = new int[spectrum.IonCount]; for (var ionIndex = 0; ionIndex < spectrum.IonCount; ionIndex++) { intensities[ionIndex] = spectrum.IonsIntensity[ionIndex]; pointerArray[ionIndex] = ionIndex; } // Sort pointerArray() based on the intensities in intensities Array.Sort(intensities, pointerArray); int startIndex; if (mOptions.RawDataExportOptions.MaxIonCountPerScan > 0) { // Possibly limit the number of ions to maxIonCount startIndex = spectrum.IonCount - mOptions.RawDataExportOptions.MaxIonCountPerScan; if (startIndex < 0) { startIndex = 0; } } else { startIndex = 0; } // Define the minimum data point intensity value var minimumIntensityCurrentScan = spectrum.IonsIntensity[pointerArray[startIndex]]; // Update the minimum intensity if a higher minimum intensity is defined in .IntensityMinimum minimumIntensityCurrentScan = Math.Max(minimumIntensityCurrentScan, mOptions.RawDataExportOptions.IntensityMinimum); // If mOptions.RawDataExportOptions.MinimumSignalToNoiseRatio is > 0, then possibly update minimumIntensityCurrentScan if (mOptions.RawDataExportOptions.MinimumSignalToNoiseRatio > 0) { minimumIntensityCurrentScan = Math.Max(minimumIntensityCurrentScan, currentScan.BaselineNoiseStats.NoiseLevel * mOptions.RawDataExportOptions.MinimumSignalToNoiseRatio); } exportCount = 0; for (var ionIndex = 0; ionIndex < spectrum.IonCount; ionIndex++) { if (spectrum.IonsIntensity[ionIndex] >= minimumIntensityCurrentScan) { var dataLine1 = "1" + "\t" + "1" + "\t" + spectrum.IonsIntensity[ionIndex] + "\t" + spectrum.IonsMZ[ionIndex] + "\t" + "0"; writer.WriteLine(dataLine1); exportCount += 1; } } } writer.WriteLine("Number of peaks in spectrum = " + spectrum.IonCount.ToString()); writer.WriteLine("Number of isotopic distributions detected = " + exportCount.ToString()); writer.WriteLine(); }
private void SaveCSVFilesToDiskWork( StreamWriter dataWriter, StreamWriter scanInfoWriter, clsScanInfo currentScan, clsSpectraCache spectraCache, bool fragmentationScan, ref int spectrumExportCount) { int scanNumber; if (!spectraCache.GetSpectrum(currentScan.ScanNumber, out var spectrum, true)) { SetLocalErrorCode(clsMASIC.eMasicErrorCodes.ErrorUncachingSpectrum); return; } spectrumExportCount += 1; // First, write an entry to the "_scans.csv" file if (mOptions.RawDataExportOptions.RenumberScans) { scanNumber = spectrumExportCount; } else { scanNumber = currentScan.ScanNumber; } int msLevel; if (fragmentationScan) { msLevel = currentScan.FragScanInfo.MSLevel; } else { msLevel = 1; } var numIsotopicSignatures = 0; var numPeaks = spectrum.IonCount; var baselineNoiseLevel = currentScan.BaselineNoiseStats.NoiseLevel; if (baselineNoiseLevel < 1) { baselineNoiseLevel = 1; } mBPIWriter.WriteDecon2LSScanFileEntry(scanInfoWriter, currentScan, scanNumber, msLevel, numPeaks, numIsotopicSignatures); // Now write an entry to the "_isos.csv" file if (spectrum.IonCount > 0) { // Populate intensities and pointerArray() var intensities = new double[spectrum.IonCount]; var pointerArray = new int[spectrum.IonCount]; for (var ionIndex = 0; ionIndex < spectrum.IonCount; ionIndex++) { intensities[ionIndex] = spectrum.IonsIntensity[ionIndex]; pointerArray[ionIndex] = ionIndex; } // Sort pointerArray() based on the intensities in intensities Array.Sort(intensities, pointerArray); int startIndex; if (mOptions.RawDataExportOptions.MaxIonCountPerScan > 0) { // Possibly limit the number of ions to maxIonCount startIndex = spectrum.IonCount - mOptions.RawDataExportOptions.MaxIonCountPerScan; if (startIndex < 0) { startIndex = 0; } } else { startIndex = 0; } // Define the minimum data point intensity value var minimumIntensityCurrentScan = spectrum.IonsIntensity[pointerArray[startIndex]]; // Update the minimum intensity if a higher minimum intensity is defined in .IntensityMinimum minimumIntensityCurrentScan = Math.Max(minimumIntensityCurrentScan, mOptions.RawDataExportOptions.IntensityMinimum); // If mOptions.RawDataExportOptions.MinimumSignalToNoiseRatio is > 0, then possibly update minimumIntensityCurrentScan if (mOptions.RawDataExportOptions.MinimumSignalToNoiseRatio > 0) { minimumIntensityCurrentScan = Math.Max(minimumIntensityCurrentScan, currentScan.BaselineNoiseStats.NoiseLevel * mOptions.RawDataExportOptions.MinimumSignalToNoiseRatio); } for (var ionIndex = 0; ionIndex < spectrum.IonCount; ionIndex++) { if (spectrum.IonsIntensity[ionIndex] >= minimumIntensityCurrentScan) { var charge = 1; var isoFit = 0; var mass = clsUtilities.ConvoluteMass(spectrum.IonsMZ[ionIndex], 1, 0); var peakFWHM = 0; var signalToNoise = spectrum.IonsIntensity[ionIndex] / baselineNoiseLevel; var monoisotopicAbu = -10; var monoPlus2Abu = -10; mBPIWriter.WriteDecon2LSIsosFileEntry( dataWriter, scanNumber, charge, spectrum.IonsIntensity[ionIndex], spectrum.IonsMZ[ionIndex], isoFit, mass, mass, mass, peakFWHM, signalToNoise, monoisotopicAbu, monoPlus2Abu); } } } }