/// <summary> /// Find the index of the scan closest to scanOrAcqTime (searching both Survey and Frag Scans using the MasterScanList) /// </summary> /// <param name="scanList"></param> /// <param name="scanOrAcqTime">can be absolute, relative, or AcquisitionTime</param> /// <param name="eScanType">Specifies what type of value scanOrAcqTime is; 0=absolute, 1=relative, 2=acquisition time (aka elution time)</param> /// <returns>The index of the scan closest to scanOrAcqTime, or 0 if an error</returns> /// <remarks></remarks> private int FindNearestScanNumIndex( clsScanList scanList, float scanOrAcqTime, clsCustomSICList.eCustomSICScanTypeConstants eScanType) { try { int scanIndexMatch; if (eScanType == clsCustomSICList.eCustomSICScanTypeConstants.Absolute || eScanType == clsCustomSICList.eCustomSICScanTypeConstants.Relative) { var absoluteScanNumber = ScanOrAcqTimeToAbsolute(scanList, scanOrAcqTime, eScanType, false); scanIndexMatch = clsBinarySearch.BinarySearchFindNearest(scanList.MasterScanNumList, absoluteScanNumber, clsBinarySearch.eMissingDataModeConstants.ReturnClosestPoint); } else { // eScanType = eCustomSICScanTypeConstants.AcquisitionTime // Find the closest match in scanList.MasterScanTimeList scanIndexMatch = clsBinarySearch.BinarySearchFindNearest( scanList.MasterScanTimeList, scanOrAcqTime, clsBinarySearch.eMissingDataModeConstants.ReturnClosestPoint); } return(scanIndexMatch); } catch (Exception ex) { OnErrorEvent("Error in FindNearestScanNumIndex", ex); return(0); } }
/// <summary> /// Add the parent ion, or associate the fragmentation scan with an existing parent ion /// </summary> /// <param name="scanList"></param> /// <param name="surveyScanIndex"></param> /// <param name="parentIonMZ"></param> /// <param name="fragScanIndex"></param> /// <param name="spectraCache"></param> /// <param name="sicOptions"></param> public void AddUpdateParentIons( clsScanList scanList, int surveyScanIndex, double parentIonMZ, int fragScanIndex, clsSpectraCache spectraCache, clsSICOptions sicOptions) { AddUpdateParentIons(scanList, surveyScanIndex, parentIonMZ, 0, 0, fragScanIndex, spectraCache, sicOptions); }
public int FindNearestSurveyScanIndex( clsScanList scanList, float scanOrAcqTime, clsCustomSICList.eCustomSICScanTypeConstants eScanType) { // Finds the index of the survey scan closest to scanOrAcqTime // Note that scanOrAcqTime can be absolute, relative, or AcquisitionTime; eScanType specifies which it is try { var surveyScanIndexMatch = -1; var scanNumberToFind = ScanOrAcqTimeToAbsolute(scanList, scanOrAcqTime, eScanType, false); for (var index = 0; index < scanList.SurveyScans.Count; index++) { if (scanList.SurveyScans[index].ScanNumber >= scanNumberToFind) { surveyScanIndexMatch = index; if (scanList.SurveyScans[index].ScanNumber != scanNumberToFind && index < scanList.SurveyScans.Count - 1) { // Didn't find an exact match; determine which survey scan is closer if (Math.Abs(scanList.SurveyScans[index + 1].ScanNumber - scanNumberToFind) < Math.Abs(scanList.SurveyScans[index].ScanNumber - scanNumberToFind)) { surveyScanIndexMatch += 1; } } break; } } if (surveyScanIndexMatch < 0) { // Match not found; return either the first or the last survey scan if (scanList.SurveyScans.Count > 0) { surveyScanIndexMatch = scanList.SurveyScans.Count - 1; } else { surveyScanIndexMatch = 0; } } return(surveyScanIndexMatch); } catch (Exception ex) { OnErrorEvent("Error in FindNearestSurveyScanIndex", ex); return(0); } }
/// <summary> /// Export MRM data to disk /// </summary> /// <param name="scanList"></param> /// <param name="spectraCache"></param> /// <param name="inputFileName"></param> /// <param name="outputDirectoryPath"></param> /// <returns></returns> public bool ExportMRMDataToDisk( clsScanList scanList, clsSpectraCache spectraCache, string inputFileName, string outputDirectoryPath) { if (!DetermineMRMSettings(scanList, out var mrmSettings, out var srmList)) { return(false); } var success = ExportMRMDataToDisk(scanList, spectraCache, mrmSettings, srmList, inputFileName, outputDirectoryPath); return(success); }
private void AppendParentIonToUniqueMZEntry( clsScanList scanList, int parentIonIndex, clsUniqueMZListItem mzListEntry, double searchMZOffset) { var parentIon = scanList.ParentIons[parentIonIndex]; if (mzListEntry.MatchCount == 0) { mzListEntry.MZAvg = parentIon.MZ - searchMZOffset; mzListEntry.MatchIndices.Add(parentIonIndex); } else { // Update the average MZ: NewAvg = (OldAvg * OldCount + NewValue) / NewCount mzListEntry.MZAvg = (mzListEntry.MZAvg * mzListEntry.MatchCount + (parentIon.MZ - searchMZOffset)) / (mzListEntry.MatchCount + 1); mzListEntry.MatchIndices.Add(parentIonIndex); } var sicStats = parentIon.SICStats; if (sicStats.Peak.MaxIntensityValue > mzListEntry.MaxIntensity || mzListEntry.MatchCount == 1) { mzListEntry.MaxIntensity = sicStats.Peak.MaxIntensityValue; if (sicStats.ScanTypeForPeakIndices == clsScanList.eScanTypeConstants.FragScan) { mzListEntry.ScanNumberMaxIntensity = scanList.FragScans[sicStats.PeakScanIndexMax].ScanNumber; mzListEntry.ScanTimeMaxIntensity = scanList.FragScans[sicStats.PeakScanIndexMax].ScanTime; } else { mzListEntry.ScanNumberMaxIntensity = scanList.SurveyScans[sicStats.PeakScanIndexMax].ScanNumber; mzListEntry.ScanTimeMaxIntensity = scanList.SurveyScans[sicStats.PeakScanIndexMax].ScanTime; } mzListEntry.ParentIonIndexMaxIntensity = parentIonIndex; } if (sicStats.Peak.Area > mzListEntry.MaxPeakArea || mzListEntry.MatchCount == 1) { mzListEntry.MaxPeakArea = sicStats.Peak.Area; mzListEntry.ParentIonIndexMaxPeakArea = parentIonIndex; } }
/// <summary> /// Add the parent ion, or associate the fragmentation scan with an existing parent ion /// </summary> /// <param name="scanList"></param> /// <param name="surveyScanIndex"></param> /// <param name="parentIonMZ"></param> /// <param name="mrmInfo"></param> /// <param name="spectraCache"></param> /// <param name="sicOptions"></param> public void AddUpdateParentIons( clsScanList scanList, int surveyScanIndex, double parentIonMZ, clsMRMScanInfo mrmInfo, clsSpectraCache spectraCache, clsSICOptions sicOptions) { for (var mrmIndex = 0; mrmIndex < mrmInfo.MRMMassCount; mrmIndex++) { var mrmDaughterMZ = mrmInfo.MRMMassList[mrmIndex].CentralMass; var mrmToleranceHalfWidth = Math.Round((mrmInfo.MRMMassList[mrmIndex].EndMass - mrmInfo.MRMMassList[mrmIndex].StartMass) / 2, 6); if (mrmToleranceHalfWidth < 0.001) { mrmToleranceHalfWidth = 0.001; } AddUpdateParentIons(scanList, surveyScanIndex, parentIonMZ, mrmDaughterMZ, mrmToleranceHalfWidth, scanList.FragScans.Count - 1, spectraCache, sicOptions); } }
/// <summary> /// Store custom SIC values defined in CustomMZSearchValues /// </summary> /// <param name="scanList"></param> /// <param name="defaultSICTolerance"></param> /// <param name="sicToleranceIsPPM"></param> /// <param name="defaultScanOrAcqTimeTolerance"></param> public void AddCustomSICValues( clsScanList scanList, double defaultSICTolerance, bool sicToleranceIsPPM, float defaultScanOrAcqTimeTolerance) { var scanOrAcqTimeSumCount = 0; float scanOrAcqTimeSumForAveraging = 0; try { if (CustomMZSearchValues.Count == 0) { return; } var scanNumScanConverter = new clsScanNumScanTimeConversion(); RegisterEvents(scanNumScanConverter); foreach (var customMzSearchValue in CustomMZSearchValues) { // Add a new parent ion entry to .ParentIons() for this custom MZ value var currentParentIon = new clsParentIonInfo(customMzSearchValue.MZ); if (customMzSearchValue.ScanOrAcqTimeCenter < float.Epsilon) { // Set the SurveyScanIndex to the center of the analysis currentParentIon.SurveyScanIndex = scanNumScanConverter.FindNearestSurveyScanIndex( scanList, 0.5F, eCustomSICScanTypeConstants.Relative); } else { currentParentIon.SurveyScanIndex = scanNumScanConverter.FindNearestSurveyScanIndex( scanList, customMzSearchValue.ScanOrAcqTimeCenter, ScanToleranceType); } // Find the next MS2 scan that occurs after the survey scan (parent scan) var surveyScanNumberAbsolute = 0; if (currentParentIon.SurveyScanIndex < scanList.SurveyScans.Count) { surveyScanNumberAbsolute = scanList.SurveyScans[currentParentIon.SurveyScanIndex].ScanNumber + 1; } if (scanList.MasterScanOrderCount == 0) { currentParentIon.FragScanIndices.Add(0); } else { var fragScanIndexMatch = clsBinarySearch.BinarySearchFindNearest( scanList.MasterScanNumList, surveyScanNumberAbsolute, clsBinarySearch.eMissingDataModeConstants.ReturnClosestPoint); while (fragScanIndexMatch < scanList.MasterScanOrderCount && scanList.MasterScanOrder[fragScanIndexMatch].ScanType == clsScanList.eScanTypeConstants.SurveyScan) { fragScanIndexMatch += 1; } if (fragScanIndexMatch == scanList.MasterScanOrderCount) { // Did not find the next frag scan; find the previous frag scan fragScanIndexMatch -= 1; while (fragScanIndexMatch > 0 && scanList.MasterScanOrder[fragScanIndexMatch].ScanType == clsScanList.eScanTypeConstants.SurveyScan) { fragScanIndexMatch -= 1; } if (fragScanIndexMatch < 0) { fragScanIndexMatch = 0; } } // This is a custom SIC-based parent ion // Prior to August 2014, we set .FragScanIndices(0) = 0, which made it appear that the fragmentation scan was the first MS2 spectrum in the dataset for all custom SICs // This caused undesirable display results in MASIC browser, so we now set it to the next MS2 scan that occurs after the survey scan (parent scan) if (scanList.MasterScanOrder[fragScanIndexMatch].ScanType == clsScanList.eScanTypeConstants.FragScan) { currentParentIon.FragScanIndices.Add(scanList.MasterScanOrder[fragScanIndexMatch].ScanIndexPointer); } else { currentParentIon.FragScanIndices.Add(0); } } currentParentIon.CustomSICPeak = true; currentParentIon.CustomSICPeakComment = customMzSearchValue.Comment; currentParentIon.CustomSICPeakMZToleranceDa = customMzSearchValue.MZToleranceDa; currentParentIon.CustomSICPeakScanOrAcqTimeTolerance = customMzSearchValue.ScanOrAcqTimeTolerance; if (currentParentIon.CustomSICPeakMZToleranceDa < double.Epsilon) { if (sicToleranceIsPPM) { currentParentIon.CustomSICPeakMZToleranceDa = clsUtilities.PPMToMass(defaultSICTolerance, currentParentIon.MZ); } else { currentParentIon.CustomSICPeakMZToleranceDa = defaultSICTolerance; } } if (currentParentIon.CustomSICPeakScanOrAcqTimeTolerance < float.Epsilon) { currentParentIon.CustomSICPeakScanOrAcqTimeTolerance = defaultScanOrAcqTimeTolerance; } else { scanOrAcqTimeSumForAveraging += currentParentIon.CustomSICPeakScanOrAcqTimeTolerance; scanOrAcqTimeSumCount += 1; } if (currentParentIon.SurveyScanIndex < scanList.SurveyScans.Count) { currentParentIon.OptimalPeakApexScanNumber = scanList.SurveyScans[currentParentIon.SurveyScanIndex].ScanNumber; } else { currentParentIon.OptimalPeakApexScanNumber = 1; } currentParentIon.PeakApexOverrideParentIonIndex = -1; scanList.ParentIons.Add(currentParentIon); } if (scanOrAcqTimeSumCount == CustomMZSearchValues.Count && scanOrAcqTimeSumForAveraging > 0) { // All of the entries had a custom scan or acq time tolerance defined // Update mScanOrAcqTimeTolerance to the average of the values ScanOrAcqTimeTolerance = (float)(Math.Round(scanOrAcqTimeSumForAveraging / scanOrAcqTimeSumCount, 4)); } } catch (Exception ex) { OnErrorEvent("Error in AddCustomSICValues", ex); } }
/// <summary> /// Looks for the reporter ion peaks using FindReporterIonsWork /// </summary> /// <param name="scanList"></param> /// <param name="spectraCache"></param> /// <param name="inputFilePathFull">Full path to the input file</param> /// <param name="outputDirectoryPath"></param> /// <returns></returns> /// <remarks></remarks> public bool FindReporterIons( clsScanList scanList, clsSpectraCache spectraCache, string inputFilePathFull, string outputDirectoryPath) { const char TAB_DELIMITER = '\t'; var outputFilePath = "??"; try { // Use Xraw to read the .Raw files var readerOptions = new ThermoReaderOptions() { LoadMSMethodInfo = false, LoadMSTuneInfo = false }; var rawFileReader = new XRawFileIO(readerOptions); RegisterEvents(rawFileReader); var includeFtmsColumns = false; if (inputFilePathFull.ToUpper().EndsWith(DataInput.clsDataImport.THERMO_RAW_FILE_EXTENSION.ToUpper())) { // Processing a thermo .Raw file // Check whether any of the frag scans has IsFTMS true for (var masterOrderIndex = 0; masterOrderIndex < scanList.MasterScanOrderCount; masterOrderIndex++) { var scanPointer = scanList.MasterScanOrder[masterOrderIndex].ScanIndexPointer; if (scanList.MasterScanOrder[masterOrderIndex].ScanType == clsScanList.eScanTypeConstants.SurveyScan) { // Skip survey scans continue; } if (scanList.FragScans[scanPointer].IsFTMS) { includeFtmsColumns = true; break; } } if (includeFtmsColumns) { rawFileReader.OpenRawFile(inputFilePathFull); } } if (mOptions.ReporterIons.ReporterIonList.Count == 0) { // No reporter ions defined; default to ITraq mOptions.ReporterIons.SetReporterIonMassMode(clsReporterIons.eReporterIonMassModeConstants.ITraqFourMZ); } // Populate array reporterIons, which we will sort by m/z var reporterIons = new clsReporterIonInfo[mOptions.ReporterIons.ReporterIonList.Count]; var reporterIonIndex = 0; foreach (var reporterIon in mOptions.ReporterIons.ReporterIonList) { reporterIons[reporterIonIndex] = reporterIon; reporterIonIndex += 1; } Array.Sort(reporterIons, new clsReportIonInfoComparer()); outputFilePath = clsDataOutput.ConstructOutputFilePath( Path.GetFileName(inputFilePathFull), outputDirectoryPath, clsDataOutput.eOutputFileTypeConstants.ReporterIonsFile); using (var writer = new StreamWriter(outputFilePath)) { // Write the file headers var reporterIonMZsUnique = new SortedSet <string>(); var headerColumns = new List <string>(7 + reporterIons.Length + 1) { "Dataset", "ScanNumber", "Collision Mode", "ParentIonMZ", "BasePeakIntensity", "BasePeakMZ", "ReporterIonIntensityMax" }; var obsMZHeaders = new List <string>(reporterIons.Length); var uncorrectedIntensityHeaders = new List <string>(reporterIons.Length); var ftmsSignalToNoise = new List <string>(reporterIons.Length); var ftmsResolution = new List <string>(reporterIons.Length); //var ftmsLabelDataMz = new List<string>(reporterIons.Length); var saveUncorrectedIntensities = mOptions.ReporterIons.ReporterIonApplyAbundanceCorrection && mOptions.ReporterIons.ReporterIonSaveUncorrectedIntensities; var dataAggregation = new clsDataAggregation(); RegisterEvents(dataAggregation); foreach (var reporterIon in reporterIons) { if (!reporterIon.ContaminantIon || saveUncorrectedIntensities) { // Construct the reporter ion intensity header // We skip contaminant ions, unless saveUncorrectedIntensities is True, then we include them string mzValue; if (mOptions.ReporterIons.ReporterIonMassMode == clsReporterIons.eReporterIonMassModeConstants.TMTTenMZ || mOptions.ReporterIons.ReporterIonMassMode == clsReporterIons.eReporterIonMassModeConstants.TMTElevenMZ || mOptions.ReporterIons.ReporterIonMassMode == clsReporterIons.eReporterIonMassModeConstants.TMTSixteenMZ) { mzValue = reporterIon.MZ.ToString("#0.000"); } else { mzValue = ((int)Math.Round(reporterIon.MZ, 0)).ToString(); } if (reporterIonMZsUnique.Contains(mzValue)) { // Uniquify the m/z value mzValue += "_" + reporterIonIndex; } try { reporterIonMZsUnique.Add(mzValue); } catch (Exception ex) { // Error updating the SortedSet; // this shouldn't happen based on the .ContainsKey test above } // Append the reporter ion intensity title to the headers headerColumns.Add("Ion_" + mzValue); // This string will only be included in the header line if mOptions.ReporterIons.ReporterIonSaveObservedMasses is true obsMZHeaders.Add("Ion_" + mzValue + "_ObsMZ"); // This string will be included in the header line if saveUncorrectedIntensities is true uncorrectedIntensityHeaders.Add("Ion_" + mzValue + "_OriginalIntensity"); // This string will be included in the header line if includeFtmsColumns is true ftmsSignalToNoise.Add("Ion_" + mzValue + "_SignalToNoise"); ftmsResolution.Add("Ion_" + mzValue + "_Resolution"); // Uncomment to include the label data m/z value in the _ReporterIons.txt file // This string will only be included in the header line if mOptions.ReporterIons.ReporterIonSaveObservedMasses is true //ftmsLabelDataMz.Add("Ion_" + mzValue + "_LabelDataMZ"); } } headerColumns.Add("Weighted Avg Pct Intensity Correction"); if (mOptions.ReporterIons.ReporterIonSaveObservedMasses) { headerColumns.AddRange(obsMZHeaders); } if (saveUncorrectedIntensities) { headerColumns.AddRange(uncorrectedIntensityHeaders); } if (includeFtmsColumns) { headerColumns.AddRange(ftmsSignalToNoise); headerColumns.AddRange(ftmsResolution); // Uncomment to include the label data m/z value in the _ReporterIons.txt file // If mOptions.ReporterIons.ReporterIonSaveObservedMasses Then // headerColumns.AddRange(ftmsLabelDataMz) // End If } // Write the headers to the output file, separated by tabs writer.WriteLine(string.Join(TAB_DELIMITER.ToString(), headerColumns)); UpdateProgress(0, "Searching for reporter ions"); for (var masterOrderIndex = 0; masterOrderIndex < scanList.MasterScanOrderCount; masterOrderIndex++) { var scanPointer = scanList.MasterScanOrder[masterOrderIndex].ScanIndexPointer; if (scanList.MasterScanOrder[masterOrderIndex].ScanType == clsScanList.eScanTypeConstants.SurveyScan) { // Skip Survey Scans continue; } FindReporterIonsWork( rawFileReader, dataAggregation, includeFtmsColumns, mOptions.SICOptions, scanList, spectraCache, scanList.FragScans[scanPointer], writer, reporterIons, TAB_DELIMITER, saveUncorrectedIntensities, mOptions.ReporterIons.ReporterIonSaveObservedMasses); if (scanList.MasterScanOrderCount > 1) { UpdateProgress((short)(masterOrderIndex / (double)(scanList.MasterScanOrderCount - 1) * 100)); } else { UpdateProgress(0); } UpdateCacheStats(spectraCache); if (mOptions.AbortProcessing) { break; } } } if (includeFtmsColumns) { // Close the handle to the data file rawFileReader.CloseRawFile(); } return(true); } catch (Exception ex) { ReportError("Error writing the reporter ions to: " + outputFilePath, ex, clsMASIC.eMasicErrorCodes.OutputFileWriteError); return(false); } }
/// <summary> /// Looks for the reporter ion m/z values, +/- a tolerance /// Calls AggregateIonsInRange with returnMax = True, meaning we're reporting the maximum ion abundance for each reporter ion m/z /// </summary> /// <param name="rawFileReader"></param> /// <param name="dataAggregation"></param> /// <param name="includeFtmsColumns"></param> /// <param name="sicOptions"></param> /// <param name="scanList"></param> /// <param name="spectraCache"></param> /// <param name="currentScan"></param> /// <param name="writer"></param> /// <param name="reporterIons"></param> /// <param name="delimiter"></param> /// <param name="saveUncorrectedIntensities"></param> /// <param name="saveObservedMasses"></param> /// <remarks></remarks> private void FindReporterIonsWork( XRawFileIO rawFileReader, clsDataAggregation dataAggregation, bool includeFtmsColumns, clsSICOptions sicOptions, clsScanList scanList, clsSpectraCache spectraCache, clsScanInfo currentScan, TextWriter writer, IList <clsReporterIonInfo> reporterIons, char delimiter, bool saveUncorrectedIntensities, bool saveObservedMasses) { const bool USE_MAX_ABUNDANCE_IN_WINDOW = true; // The following will be a value between 0 and 100 // Using Absolute Value of percent change to avoid averaging both negative and positive values double parentIonMZ; if (currentScan.FragScanInfo.ParentIonInfoIndex >= 0 && currentScan.FragScanInfo.ParentIonInfoIndex < scanList.ParentIons.Count) { parentIonMZ = scanList.ParentIons[currentScan.FragScanInfo.ParentIonInfoIndex].MZ; } else { parentIonMZ = 0; } if (!spectraCache.GetSpectrum(currentScan.ScanNumber, out var spectrum, true)) { SetLocalErrorCode(clsMASIC.eMasicErrorCodes.ErrorUncachingSpectrum); return; } // Initialize the arrays used to track the observed reporter ion values var reporterIntensities = new double[reporterIons.Count]; var reporterIntensitiesCorrected = new double[reporterIons.Count]; var closestMZ = new double[reporterIons.Count]; // Initialize the output variables var dataColumns = new List <string>() { sicOptions.DatasetID.ToString(), currentScan.ScanNumber.ToString(), currentScan.FragScanInfo.CollisionMode, StringUtilities.DblToString(parentIonMZ, 2), StringUtilities.DblToString(currentScan.BasePeakIonIntensity, 2), StringUtilities.DblToString(currentScan.BasePeakIonMZ, 4) }; var reporterIntensityList = new List <string>(reporterIons.Count); var obsMZList = new List <string>(reporterIons.Count); var uncorrectedIntensityList = new List <string>(reporterIons.Count); var ftmsSignalToNoise = new List <string>(reporterIons.Count); var ftmsResolution = new List <string>(reporterIons.Count); //var ftmsLabelDataMz = new List<string>(reporterIons.Count); double reporterIntensityMax = 0; // Find the reporter ion intensities // Also keep track of the closest m/z for each reporter ion // Note that we're using the maximum intensity in the range (not the sum) for (var reporterIonIndex = 0; reporterIonIndex < reporterIons.Count; reporterIonIndex++) { var ion = reporterIons[reporterIonIndex]; // Search for the reporter ion MZ in this mass spectrum reporterIntensities[reporterIonIndex] = dataAggregation.AggregateIonsInRange( spectrum, ion.MZ, ion.MZToleranceDa, out _, out closestMZ[reporterIonIndex], USE_MAX_ABUNDANCE_IN_WINDOW); ion.SignalToNoise = 0; ion.Resolution = 0; ion.LabelDataMZ = 0; } if (includeFtmsColumns && currentScan.IsFTMS) { // Retrieve the label data for this spectrum rawFileReader.GetScanLabelData(currentScan.ScanNumber, out var ftLabelData); // Find each reporter ion in ftLabelData for (var reporterIonIndex = 0; reporterIonIndex < reporterIons.Count; reporterIonIndex++) { var mzToFind = reporterIons[reporterIonIndex].MZ; var mzToleranceDa = reporterIons[reporterIonIndex].MZToleranceDa; var highestIntensity = 0.0; var udtBestMatch = new udtFTLabelInfoType(); var matchFound = false; foreach (var labelItem in ftLabelData) { // Compare labelItem.Mass (which is m/z of the ion in labelItem) to the m/z of the current reporter ion if (Math.Abs(mzToFind - labelItem.Mass) > mzToleranceDa) { continue; } // m/z is within range if (labelItem.Intensity > highestIntensity) { udtBestMatch = labelItem; highestIntensity = labelItem.Intensity; matchFound = true; } } if (matchFound) { reporterIons[reporterIonIndex].SignalToNoise = udtBestMatch.SignalToNoise; reporterIons[reporterIonIndex].Resolution = udtBestMatch.Resolution; reporterIons[reporterIonIndex].LabelDataMZ = udtBestMatch.Mass; } } } // Populate reporterIntensitiesCorrected with the data in reporterIntensities Array.Copy(reporterIntensities, reporterIntensitiesCorrected, reporterIntensities.Length); if (mOptions.ReporterIons.ReporterIonApplyAbundanceCorrection) { if (mOptions.ReporterIons.ReporterIonMassMode == clsReporterIons.eReporterIonMassModeConstants.ITraqFourMZ || mOptions.ReporterIons.ReporterIonMassMode == clsReporterIons.eReporterIonMassModeConstants.ITraqEightMZHighRes || mOptions.ReporterIons.ReporterIonMassMode == clsReporterIons.eReporterIonMassModeConstants.ITraqEightMZLowRes || mOptions.ReporterIons.ReporterIonMassMode == clsReporterIons.eReporterIonMassModeConstants.TMTTenMZ || mOptions.ReporterIons.ReporterIonMassMode == clsReporterIons.eReporterIonMassModeConstants.TMTElevenMZ || mOptions.ReporterIons.ReporterIonMassMode == clsReporterIons.eReporterIonMassModeConstants.TMTSixteenMZ) { // Correct the reporter ion intensities using the Reporter Ion Intensity Corrector class if (intensityCorrector.ReporterIonMode != mOptions.ReporterIons.ReporterIonMassMode || intensityCorrector.ITraq4PlexCorrectionFactorType != mOptions.ReporterIons.ReporterIonITraq4PlexCorrectionFactorType) { intensityCorrector.UpdateReporterIonMode( mOptions.ReporterIons.ReporterIonMassMode, mOptions.ReporterIons.ReporterIonITraq4PlexCorrectionFactorType); } // Count the number of non-zero data points in reporterIntensitiesCorrected() var positiveCount = 0; for (var reporterIonIndex = 0; reporterIonIndex < reporterIons.Count; reporterIonIndex++) { if (reporterIntensitiesCorrected[reporterIonIndex] > 0) { positiveCount += 1; } } // Apply the correction if 2 or more points are non-zero if (positiveCount >= 2) { intensityCorrector.ApplyCorrection(reporterIntensitiesCorrected); } } } // Now construct the string of intensity values, delimited by delimiter // Will also compute the percent change in intensities // Initialize the variables used to compute the weighted average percent change double pctChangeSum = 0; double originalIntensitySum = 0; for (var reporterIonIndex = 0; reporterIonIndex < reporterIons.Count; reporterIonIndex++) { if (!reporterIons[reporterIonIndex].ContaminantIon) { // Update the PctChange variables and the IntensityMax variable only if this is not a Contaminant Ion originalIntensitySum += reporterIntensities[reporterIonIndex]; if (reporterIntensities[reporterIonIndex] > 0) { // Compute the percent change, then update pctChangeSum var pctChange = (reporterIntensitiesCorrected[reporterIonIndex] - reporterIntensities[reporterIonIndex]) / reporterIntensities[reporterIonIndex]; // Using Absolute Value here to prevent negative changes from cancelling out positive changes pctChangeSum += Math.Abs(pctChange * reporterIntensities[reporterIonIndex]); } if (reporterIntensitiesCorrected[reporterIonIndex] > reporterIntensityMax) { reporterIntensityMax = reporterIntensitiesCorrected[reporterIonIndex]; } } if (!reporterIons[reporterIonIndex].ContaminantIon || saveUncorrectedIntensities) { // Append the reporter ion intensity to reporterIntensityList // We skip contaminant ions, unless saveUncorrectedIntensities is True, then we include them reporterIntensityList.Add(StringUtilities.DblToString(reporterIntensitiesCorrected[reporterIonIndex], 2)); if (saveObservedMasses) { // Append the observed reporter mass value to obsMZList obsMZList.Add(StringUtilities.DblToString(closestMZ[reporterIonIndex], 3)); } if (saveUncorrectedIntensities) { // Append the original, uncorrected intensity value uncorrectedIntensityList.Add(StringUtilities.DblToString(reporterIntensities[reporterIonIndex], 2)); } if (includeFtmsColumns) { if (Math.Abs(reporterIons[reporterIonIndex].SignalToNoise) < float.Epsilon && Math.Abs(reporterIons[reporterIonIndex].Resolution) < float.Epsilon && Math.Abs(reporterIons[reporterIonIndex].LabelDataMZ) < float.Epsilon) { // A match was not found in the label data; display blanks (not zeroes) ftmsSignalToNoise.Add(string.Empty); ftmsResolution.Add(string.Empty); //ftmsLabelDataMz.Add(string.Empty); } else { ftmsSignalToNoise.Add(StringUtilities.DblToString(reporterIons[reporterIonIndex].SignalToNoise, 2)); ftmsResolution.Add(StringUtilities.DblToString(reporterIons[reporterIonIndex].Resolution, 2)); //ftmsLabelDataMz.Add(StringUtilities.DblToString(reporterIons(reporterIonIndex).LabelDataMZ, 4)); } } } } // Compute the weighted average percent intensity correction value float weightedAvgPctIntensityCorrection; if (originalIntensitySum > 0) { weightedAvgPctIntensityCorrection = (float)(pctChangeSum / originalIntensitySum * 100); } else { weightedAvgPctIntensityCorrection = 0; } // Resize the target list capacity to large enough to hold all data. dataColumns.Capacity = reporterIntensityList.Count + 3 + obsMZList.Count + uncorrectedIntensityList.Count + ftmsSignalToNoise.Count + ftmsResolution.Count; // Append the maximum reporter ion intensity then the individual reporter ion intensities dataColumns.Add(StringUtilities.DblToString(reporterIntensityMax, 2)); dataColumns.AddRange(reporterIntensityList); // Append the weighted average percent intensity correction if (weightedAvgPctIntensityCorrection < float.Epsilon) { dataColumns.Add("0"); } else { dataColumns.Add(StringUtilities.DblToString(weightedAvgPctIntensityCorrection, 1)); } if (saveObservedMasses) { dataColumns.AddRange(obsMZList); } if (saveUncorrectedIntensities) { dataColumns.AddRange(uncorrectedIntensityList); } if (includeFtmsColumns) { dataColumns.AddRange(ftmsSignalToNoise); dataColumns.AddRange(ftmsResolution); // Uncomment to include the label data m/z value in the _ReporterIons.txt file //if (saveObservedMasses) // dataColumns.AddRange(ftmsLabelDataMz) } writer.WriteLine(string.Join(delimiter.ToString(), dataColumns)); }
/// <summary> /// Add the parent ion, or associate the fragmentation scan with an existing parent ion /// /// Checks to see if the parent ion specified by surveyScanIndex and parentIonMZ exists in .ParentIons() /// If mrmDaughterMZ is > 0, also considers that value when determining uniqueness /// /// If the parent ion entry already exists, adds an entry to .FragScanIndices() /// If it does not exist, adds a new entry to .ParentIons() /// </summary> /// <param name="scanList"></param> /// <param name="surveyScanIndex"> /// If this is less than 0 the first MS2 scan(s) in the file occurred before we encountered a survey scan /// In this case, we cannot properly associate the fragmentation scan with a survey scan /// </param> /// <param name="parentIonMZ"></param> /// <param name="mrmDaughterMZ"></param> /// <param name="mrmToleranceHalfWidth"></param> /// <param name="fragScanIndex">This is typically equal to scanList.FragScans.Count - 1</param> /// <param name="spectraCache"></param> /// <param name="sicOptions"></param> private void AddUpdateParentIons( clsScanList scanList, int surveyScanIndex, double parentIonMZ, double mrmDaughterMZ, double mrmToleranceHalfWidth, int fragScanIndex, clsSpectraCache spectraCache, clsSICOptions sicOptions) { const double MINIMUM_TOLERANCE_PPM = 0.01; const double MINIMUM_TOLERANCE_DA = 0.0001; var parentIonIndex = 0; double parentIonTolerance; if (sicOptions.SICToleranceIsPPM) { parentIonTolerance = sicOptions.SICTolerance / sicOptions.CompressToleranceDivisorForPPM; if (parentIonTolerance < MINIMUM_TOLERANCE_PPM) { parentIonTolerance = MINIMUM_TOLERANCE_PPM; } } else { parentIonTolerance = sicOptions.SICTolerance / sicOptions.CompressToleranceDivisorForDa; if (parentIonTolerance < MINIMUM_TOLERANCE_DA) { parentIonTolerance = MINIMUM_TOLERANCE_DA; } } // See if an entry exists yet in .ParentIons for the parent ion for this fragmentation scan var matchFound = false; if (mrmDaughterMZ > 0) { if (sicOptions.SICToleranceIsPPM) { // Force the tolerances to 0.01 m/z units parentIonTolerance = MINIMUM_TOLERANCE_PPM; } else { // Force the tolerances to 0.01 m/z units parentIonTolerance = MINIMUM_TOLERANCE_DA; } } if (parentIonMZ > 0) { var parentIonToleranceDa = GetParentIonToleranceDa(sicOptions, parentIonMZ, parentIonTolerance); for (parentIonIndex = scanList.ParentIons.Count - 1; parentIonIndex >= 0; parentIonIndex += -1) { if (scanList.ParentIons[parentIonIndex].SurveyScanIndex >= surveyScanIndex) { if (Math.Abs(scanList.ParentIons[parentIonIndex].MZ - parentIonMZ) <= parentIonToleranceDa) { if (mrmDaughterMZ < double.Epsilon || Math.Abs(scanList.ParentIons[parentIonIndex].MRMDaughterMZ - mrmDaughterMZ) <= parentIonToleranceDa) { matchFound = true; break; } } } else { break; } } } if (!matchFound) { // Add a new parent ion entry to .ParentIons(), but only if surveyScanIndex is non-negative if (surveyScanIndex < 0) { return; } var newParentIon = new clsParentIonInfo(parentIonMZ) { SurveyScanIndex = surveyScanIndex, CustomSICPeak = false, MRMDaughterMZ = mrmDaughterMZ, MRMToleranceHalfWidth = mrmToleranceHalfWidth }; newParentIon.FragScanIndices.Add(fragScanIndex); newParentIon.OptimalPeakApexScanNumber = scanList.SurveyScans[surveyScanIndex].ScanNumber; // Was: .FragScans(fragScanIndex).ScanNumber newParentIon.PeakApexOverrideParentIonIndex = -1; scanList.FragScans[fragScanIndex].FragScanInfo.ParentIonInfoIndex = scanList.ParentIons.Count; // Look for .MZ in the survey scan, using a tolerance of parentIonTolerance // If found, then update the mass to the matched ion // This is done to determine the parent ion mass more precisely if (sicOptions.RefineReportedParentIonMZ) { if (FindClosestMZ(spectraCache, scanList.SurveyScans, surveyScanIndex, parentIonMZ, parentIonTolerance, out var parentIonMZMatch)) { newParentIon.UpdateMz(parentIonMZMatch); } } scanList.ParentIons.Add(newParentIon); return; } // Add a new entry to .FragScanIndices() for the matching parent ion // However, do not add a new entry if this is an MRM scan if (mrmDaughterMZ < double.Epsilon) { scanList.ParentIons[parentIonIndex].FragScanIndices.Add(fragScanIndex); scanList.FragScans[fragScanIndex].FragScanInfo.ParentIonInfoIndex = parentIonIndex; } }
private float CompareFragSpectraForParentIons( clsScanList scanList, clsSpectraCache spectraCache, int parentIonIndex1, int parentIonIndex2, clsBinningOptions binningOptions, MASICPeakFinder.clsBaselineNoiseOptions noiseThresholdOptions, DataInput.clsDataImport dataImportUtilities) { // Compare the fragmentation spectra for the two parent ions // Returns the highest similarity score (ranging from 0 to 1) // Returns 0 if no similarity or no spectra to compare // Returns -1 if an error float highestSimilarityScore; try { if (scanList.ParentIons[parentIonIndex1].CustomSICPeak || scanList.ParentIons[parentIonIndex2].CustomSICPeak) { // Custom SIC values do not have fragmentation spectra; nothing to compare highestSimilarityScore = 0; } else if (scanList.ParentIons[parentIonIndex1].MRMDaughterMZ > 0 || scanList.ParentIons[parentIonIndex2].MRMDaughterMZ > 0) { // MRM Spectra should not be compared highestSimilarityScore = 0; } else { highestSimilarityScore = 0; foreach (var fragSpectrumIndex1 in scanList.ParentIons[parentIonIndex1].FragScanIndices) { if (!spectraCache.GetSpectrum(scanList.FragScans[fragSpectrumIndex1].ScanNumber, out var spectrum1, false)) { SetLocalErrorCode(clsMASIC.eMasicErrorCodes.ErrorUncachingSpectrum); return(-1); } // ReSharper disable once ConditionIsAlwaysTrueOrFalse if (!clsMASIC.DISCARD_LOW_INTENSITY_MSMS_DATA_ON_LOAD) #pragma warning disable 162 // ReSharper disable HeuristicUnreachableCode { dataImportUtilities.DiscardDataBelowNoiseThreshold(spectrum1, scanList.FragScans[fragSpectrumIndex1].BaselineNoiseStats.NoiseLevel, 0, 0, noiseThresholdOptions); } // ReSharper restore HeuristicUnreachableCode #pragma warning restore 162 foreach (var fragSpectrumIndex2 in scanList.ParentIons[parentIonIndex2].FragScanIndices) { if (!spectraCache.GetSpectrum(scanList.FragScans[fragSpectrumIndex2].ScanNumber, out var spectrum2, false)) { SetLocalErrorCode(clsMASIC.eMasicErrorCodes.ErrorUncachingSpectrum); return(-1); } // ReSharper disable once ConditionIsAlwaysTrueOrFalse if (!clsMASIC.DISCARD_LOW_INTENSITY_MSMS_DATA_ON_LOAD) #pragma warning disable 162 // ReSharper disable HeuristicUnreachableCode { dataImportUtilities.DiscardDataBelowNoiseThreshold(spectrum2, scanList.FragScans[fragSpectrumIndex2].BaselineNoiseStats.NoiseLevel, 0, 0, noiseThresholdOptions); } // ReSharper restore HeuristicUnreachableCode #pragma warning restore 162 var similarityScore = CompareSpectra(spectrum1, spectrum2, binningOptions); if (similarityScore > highestSimilarityScore) { highestSimilarityScore = similarityScore; } } } } } catch (Exception ex) { ReportError("Error in CompareFragSpectraForParentIons", ex); return(-1); } return(highestSimilarityScore); }
private bool DetermineMRMSettings( clsScanList scanList, out List <clsMRMScanInfo> mrmSettings, out List <udtSRMListType> srmList) { // Returns true if this dataset has MRM data and if it is parsed successfully // Returns false if the dataset does not have MRM data, or if an error occurs mrmSettings = new List <clsMRMScanInfo>(200); srmList = new List <udtSRMListType>(600); // Assume there are 3 frag masses for each parent mass try { var mrmDataPresent = false; UpdateProgress(0, "Determining MRM settings"); // Initialize the tracking arrays var mrmHashToIndexMap = new Dictionary <string, clsMRMScanInfo>(); // Construct a list of the MRM search values used foreach (var fragScan in scanList.FragScans) { if (fragScan.MRMScanType == MRMScanTypeConstants.SRM) { mrmDataPresent = true; // See if this MRM spec is already in mrmSettings var mrmInfoHash = GenerateMRMInfoHash(fragScan.MRMScanInfo); if (!mrmHashToIndexMap.TryGetValue(mrmInfoHash, out var mrmInfoForHash)) { mrmInfoForHash = DuplicateMRMInfo(fragScan.MRMScanInfo); mrmInfoForHash.ScanCount = 1; mrmInfoForHash.ParentIonInfoIndex = fragScan.FragScanInfo.ParentIonInfoIndex; mrmSettings.Add(mrmInfoForHash); mrmHashToIndexMap.Add(mrmInfoHash, mrmInfoForHash); // Append the new entries to srmList for (var mrmMassIndex = 0; mrmMassIndex < mrmInfoForHash.MRMMassCount; mrmMassIndex++) { // Add this new transition to srmList() only if not already present var matchFound = false; foreach (var srmItem in srmList) { if (MRMParentDaughterMatch(srmItem, mrmInfoForHash, mrmMassIndex)) { matchFound = true; break; } } if (!matchFound) { // Entry is not yet present; add it var newSRMItem = new udtSRMListType() { ParentIonMZ = mrmInfoForHash.ParentIonMZ, CentralMass = mrmInfoForHash.MRMMassList[mrmMassIndex].CentralMass }; srmList.Add(newSRMItem); } } } else { mrmInfoForHash.ScanCount += 1; } } } // Resize the lists to their contents mrmSettings.Capacity = mrmSettings.Count; srmList.Capacity = srmList.Count; return(mrmDataPresent); } catch (Exception ex) { ReportError("Error determining the MRM settings", ex, clsMASIC.eMasicErrorCodes.OutputFileWriteError); return(false); } }
public bool ProcessMRMList( clsScanList scanList, clsSpectraCache spectraCache, clsSICProcessing sicProcessor, clsXMLResultsWriter xmlResultsWriter, clsMASICPeakFinder peakFinder, ref int parentIonsProcessed) { try { // Initialize sicDetails var sicDetails = new clsSICDetails(); sicDetails.Reset(); sicDetails.SICScanType = clsScanList.eScanTypeConstants.FragScan; for (var parentIonIndex = 0; parentIonIndex < scanList.ParentIons.Count; parentIonIndex++) { if (scanList.ParentIons[parentIonIndex].MRMDaughterMZ <= 0) { continue; } // Step 1: Create the SIC for this MRM Parent/Daughter pair var parentIonMZ = scanList.ParentIons[parentIonIndex].MZ; var mrmDaughterMZ = scanList.ParentIons[parentIonIndex].MRMDaughterMZ; var searchToleranceHalfWidth = scanList.ParentIons[parentIonIndex].MRMToleranceHalfWidth; // Reset SICData sicDetails.SICData.Clear(); // Step through the fragmentation spectra, finding those that have matching parent and daughter ion m/z values for (var scanIndex = 0; scanIndex < scanList.FragScans.Count; scanIndex++) { if (scanList.FragScans[scanIndex].MRMScanType != MRMScanTypeConstants.SRM) { continue; } var fragScan = scanList.FragScans[scanIndex]; var useScan = false; for (var mrmMassIndex = 0; mrmMassIndex < fragScan.MRMScanInfo.MRMMassCount; mrmMassIndex++) { if (MRMParentDaughterMatch(fragScan.MRMScanInfo.ParentIonMZ, fragScan.MRMScanInfo.MRMMassList[mrmMassIndex].CentralMass, parentIonMZ, mrmDaughterMZ)) { useScan = true; break; } } if (!useScan) { continue; } // Include this scan in the SIC for this parent ion mDataAggregation.FindMaxValueInMZRange(spectraCache, scanList.FragScans[scanIndex], mrmDaughterMZ - searchToleranceHalfWidth, mrmDaughterMZ + searchToleranceHalfWidth, out var closestMZ, out var matchIntensity); sicDetails.AddData(fragScan.ScanNumber, matchIntensity, closestMZ, scanIndex); } // Step 2: Find the largest peak in the SIC // Compute the noise level; the noise level may change with increasing index number if the background is increasing for a given m/z var success = peakFinder.ComputeDualTrimmedNoiseLevelTTest(sicDetails.SICIntensities, 0, sicDetails.SICDataCount - 1, mOptions.SICOptions.SICPeakFinderOptions. SICBaselineNoiseOptions, out var noiseStatsSegments); if (!success) { SetLocalErrorCode(clsMASIC.eMasicErrorCodes.FindSICPeaksError, true); return(false); } // Initialize the peak scanList.ParentIons[parentIonIndex].SICStats.Peak = new clsSICStatsPeak(); // Find the data point with the maximum intensity double maximumIntensity = 0; scanList.ParentIons[parentIonIndex].SICStats.Peak.IndexObserved = 0; for (var scanIndex = 0; scanIndex < sicDetails.SICDataCount; scanIndex++) { var intensity = sicDetails.SICIntensities[scanIndex]; if (intensity > maximumIntensity) { maximumIntensity = intensity; scanList.ParentIons[parentIonIndex].SICStats.Peak.IndexObserved = scanIndex; } } // Compute the minimum potential peak area in the entire SIC, populating udtSICPotentialAreaStatsInFullSIC peakFinder.FindPotentialPeakArea(sicDetails.SICData, out var potentialAreaStatsInFullSIC, mOptions.SICOptions.SICPeakFinderOptions); // Update .BaselineNoiseStats in scanList.ParentIons(parentIonIndex).SICStats.Peak scanList.ParentIons[parentIonIndex].SICStats.Peak.BaselineNoiseStats = peakFinder.LookupNoiseStatsUsingSegments( scanList.ParentIons[parentIonIndex].SICStats.Peak.IndexObserved, noiseStatsSegments); var parentIon = scanList.ParentIons[parentIonIndex]; // Clear udtSICPotentialAreaStatsForPeak parentIon.SICStats.SICPotentialAreaStatsForPeak = new clsSICPotentialAreaStats(); var peakIsValid = peakFinder.FindSICPeakAndArea(sicDetails.SICData, out var potentialAreaStatsForPeakOut, parentIon.SICStats.Peak, out var smoothedYDataSubset, mOptions.SICOptions.SICPeakFinderOptions, potentialAreaStatsInFullSIC, false, scanList.SIMDataPresent, false); parentIon.SICStats.SICPotentialAreaStatsForPeak = potentialAreaStatsForPeakOut; sicProcessor.StorePeakInParentIon(scanList, parentIonIndex, sicDetails, parentIon.SICStats.SICPotentialAreaStatsForPeak, parentIon.SICStats.Peak, peakIsValid); // Step 3: store the results // Possibly save the stats for this SIC to the SICData file mDataOutputHandler.SaveSICDataToText(mOptions.SICOptions, scanList, parentIonIndex, sicDetails); // Save the stats for this SIC to the XML file xmlResultsWriter.SaveDataToXML(scanList, parentIonIndex, sicDetails, smoothedYDataSubset, mDataOutputHandler); parentIonsProcessed += 1; // --------------------------------------------------------- // Update progress // --------------------------------------------------------- try { if (scanList.ParentIons.Count > 1) { UpdateProgress((short)(parentIonsProcessed / (double)(scanList.ParentIons.Count - 1) * 100)); } else { UpdateProgress(0); } UpdateCacheStats(spectraCache); if (mOptions.AbortProcessing) { scanList.ProcessingIncomplete = true; break; } if (parentIonsProcessed % 100 == 0) { if (DateTime.UtcNow.Subtract(mOptions.LastParentIonProcessingLogTime).TotalSeconds >= 10 || parentIonsProcessed % 500 == 0) { ReportMessage("Parent Ions Processed: " + parentIonsProcessed.ToString()); Console.Write("."); mOptions.LastParentIonProcessingLogTime = DateTime.UtcNow; } } } catch (Exception ex) { ReportError("Error updating progress", ex, clsMASIC.eMasicErrorCodes.CreateSICsError); } } return(true); } catch (Exception ex) { ReportError("Error creating SICs for MRM spectra", ex, clsMASIC.eMasicErrorCodes.CreateSICsError); return(false); } }
/// <summary> /// Export MRM data to disk /// </summary> /// <param name="scanList"></param> /// <param name="spectraCache"></param> /// <param name="mrmSettings"></param> /// <param name="srmList"></param> /// <param name="inputFileName"></param> /// <param name="outputDirectoryPath"></param> /// <returns>True if the MRM data is successfully written to disk, or if the mrmSettings list is empty</returns> private bool ExportMRMDataToDisk( clsScanList scanList, clsSpectraCache spectraCache, IReadOnlyList <clsMRMScanInfo> mrmSettings, IReadOnlyList <udtSRMListType> srmList, string inputFileName, string outputDirectoryPath) { const char TAB_DELIMITER = '\t'; StreamWriter dataWriter = null; StreamWriter crosstabWriter = null; bool success; try { // Only write this data if 1 or more fragmentation spectra are of type SRM if (mrmSettings == null || mrmSettings.Count == 0) { return(true); } UpdateProgress(0, "Exporting MRM data"); // Write out the MRM Settings var mrmSettingsFilePath = clsDataOutput.ConstructOutputFilePath( inputFileName, outputDirectoryPath, clsDataOutput.eOutputFileTypeConstants.MRMSettingsFile); using (var settingsWriter = new StreamWriter(mrmSettingsFilePath)) { settingsWriter.WriteLine(mDataOutputHandler.GetHeadersForOutputFile(scanList, clsDataOutput.eOutputFileTypeConstants.MRMSettingsFile)); var dataColumns = new List <string>(7); for (var mrmInfoIndex = 0; mrmInfoIndex < mrmSettings.Count; mrmInfoIndex++) { var mrmSetting = mrmSettings[mrmInfoIndex]; for (var mrmMassIndex = 0; mrmMassIndex < mrmSetting.MRMMassCount; mrmMassIndex++) { dataColumns.Clear(); dataColumns.Add(mrmInfoIndex.ToString()); dataColumns.Add(mrmSetting.ParentIonMZ.ToString("0.000")); dataColumns.Add(mrmSetting.MRMMassList[mrmMassIndex].CentralMass.ToString("0.000")); dataColumns.Add(mrmSetting.MRMMassList[mrmMassIndex].StartMass.ToString("0.000")); dataColumns.Add(mrmSetting.MRMMassList[mrmMassIndex].EndMass.ToString("0.000")); dataColumns.Add(mrmSetting.ScanCount.ToString()); settingsWriter.WriteLine(string.Join(TAB_DELIMITER.ToString(), dataColumns)); } } if (mOptions.WriteMRMDataList || mOptions.WriteMRMIntensityCrosstab) { // Populate srmKeyToIndexMap var srmKeyToIndexMap = new Dictionary <string, int>(); for (var srmIndex = 0; srmIndex < srmList.Count; srmIndex++) { srmKeyToIndexMap.Add(ConstructSRMMapKey(srmList[srmIndex]), srmIndex); } if (mOptions.WriteMRMDataList) { // Write out the raw MRM Data var dataFilePath = clsDataOutput.ConstructOutputFilePath(inputFileName, outputDirectoryPath, clsDataOutput.eOutputFileTypeConstants.MRMDatafile); dataWriter = new StreamWriter(dataFilePath); // Write the file headers dataWriter.WriteLine(mDataOutputHandler.GetHeadersForOutputFile(scanList, clsDataOutput.eOutputFileTypeConstants.MRMDatafile)); } if (mOptions.WriteMRMIntensityCrosstab) { // Write out the raw MRM Data var crosstabFilePath = clsDataOutput.ConstructOutputFilePath(inputFileName, outputDirectoryPath, clsDataOutput.eOutputFileTypeConstants.MRMCrosstabFile); crosstabWriter = new StreamWriter(crosstabFilePath); // Initialize the crosstab header variable using the data in udtSRMList() var headerNames = new List <string>(srmList.Count + 2) { "Scan_First", "ScanTime" }; for (var srmIndex = 0; srmIndex < srmList.Count; srmIndex++) { headerNames.Add(ConstructSRMMapKey(srmList[srmIndex])); } crosstabWriter.WriteLine(string.Join(TAB_DELIMITER.ToString(), headerNames)); } var scanFirst = int.MinValue; float scanTimeFirst = 0; var srmIndexLast = 0; var crosstabColumnValue = new double[srmList.Count]; var crosstabColumnFlag = new bool[srmList.Count]; // For scanIndex = 0 To scanList.FragScanCount - 1 foreach (var fragScan in scanList.FragScans) { if (fragScan.MRMScanType != MRMScanTypeConstants.SRM) { continue; } if (scanFirst == int.MinValue) { scanFirst = fragScan.ScanNumber; scanTimeFirst = fragScan.ScanTime; } // Look for each of the m/z values specified in fragScan.MRMScanInfo.MRMMassList for (var mrmMassIndex = 0; mrmMassIndex < fragScan.MRMScanInfo.MRMMassCount; mrmMassIndex++) { // Find the maximum value between fragScan.StartMass and fragScan.EndMass // Need to define a tolerance to account for numeric rounding artifacts in the variables var mzStart = fragScan.MRMScanInfo.MRMMassList[mrmMassIndex].StartMass; var mzEnd = fragScan.MRMScanInfo.MRMMassList[mrmMassIndex].EndMass; var mrmToleranceHalfWidth = Math.Round((mzEnd - mzStart) / 2, 6); if (mrmToleranceHalfWidth < 0.001) { mrmToleranceHalfWidth = 0.001; } var matchFound = mDataAggregation.FindMaxValueInMZRange( spectraCache, fragScan, mzStart - mrmToleranceHalfWidth, mzEnd + mrmToleranceHalfWidth, out _, out var matchIntensity); if (mOptions.WriteMRMDataList) { dataColumns.Clear(); dataColumns.Add(fragScan.ScanNumber.ToString()); dataColumns.Add(fragScan.MRMScanInfo.ParentIonMZ.ToString("0.000")); if (matchFound) { dataColumns.Add(fragScan.MRMScanInfo.MRMMassList[mrmMassIndex].CentralMass.ToString("0.000")); dataColumns.Add(matchIntensity.ToString("0.000")); } else { dataColumns.Add(fragScan.MRMScanInfo.MRMMassList[mrmMassIndex].CentralMass.ToString("0.000")); dataColumns.Add("0"); } dataWriter?.WriteLine(string.Join(TAB_DELIMITER.ToString(), dataColumns)); } if (!mOptions.WriteMRMIntensityCrosstab) { continue; } var srmMapKey = ConstructSRMMapKey(fragScan.MRMScanInfo.ParentIonMZ, fragScan.MRMScanInfo.MRMMassList[mrmMassIndex].CentralMass); // Use srmKeyToIndexMap to determine the appropriate column index for srmMapKey if (srmKeyToIndexMap.TryGetValue(srmMapKey, out var srmIndex)) { if (crosstabColumnFlag[srmIndex] || srmIndex == 0 && srmIndexLast == srmList.Count - 1) { // Either the column is already populated, or the SRMIndex has cycled back to zero // Write out the current crosstab line and reset the crosstab column arrays ExportMRMDataWriteLine(crosstabWriter, scanFirst, scanTimeFirst, crosstabColumnValue, crosstabColumnFlag, TAB_DELIMITER, true); scanFirst = fragScan.ScanNumber; scanTimeFirst = fragScan.ScanTime; } if (matchFound) { crosstabColumnValue[srmIndex] = matchIntensity; } crosstabColumnFlag[srmIndex] = true; srmIndexLast = srmIndex; } else { // Unknown combination of parent ion m/z and daughter m/z; this is unexpected // We won't write this entry out } } UpdateCacheStats(spectraCache); if (mOptions.AbortProcessing) { break; } } if (mOptions.WriteMRMIntensityCrosstab) { // Write out any remaining crosstab values ExportMRMDataWriteLine(crosstabWriter, scanFirst, scanTimeFirst, crosstabColumnValue, crosstabColumnFlag, TAB_DELIMITER, false); } } } success = true; } catch (Exception ex) { ReportError("Error writing the SRM data to disk", ex, clsMASIC.eMasicErrorCodes.OutputFileWriteError); success = false; } finally { dataWriter?.Close(); crosstabWriter?.Close(); } return(success); }
public float ScanOrAcqTimeToScanTime( clsScanList scanList, float scanOrAcqTime, clsCustomSICList.eCustomSICScanTypeConstants eScanType, bool convertingRangeOrTolerance) { try { float computedScanTime = 0; switch (eScanType) { case clsCustomSICList.eCustomSICScanTypeConstants.Absolute: // scanOrAcqTime is an absolute scan number (or range of scan numbers) // If convertingRangeOrTolerance = False, then look for the scan that is nearest to scanOrAcqTime // If convertingRangeOrTolerance = True, then Convert scanOrAcqTime to a relative scan range and then // call this function again with that relative time if (convertingRangeOrTolerance) { var totalScans = scanList.MasterScanNumList[scanList.MasterScanOrderCount - 1] - scanList.MasterScanNumList[0]; if (totalScans < 1) { totalScans = 1; } var relativeTime = scanOrAcqTime / totalScans; computedScanTime = ScanOrAcqTimeToScanTime(scanList, relativeTime, clsCustomSICList.eCustomSICScanTypeConstants.Relative, true); } else { var masterScanIndex = FindNearestScanNumIndex(scanList, scanOrAcqTime, eScanType); if (masterScanIndex >= 0 && scanList.MasterScanOrderCount > 0) { computedScanTime = scanList.MasterScanTimeList[masterScanIndex]; } } break; case clsCustomSICList.eCustomSICScanTypeConstants.Relative: // scanOrAcqTime is a fraction of the total number of scans (for example, 0.5) // Use the total range of scan times if (scanList.MasterScanOrderCount > 0) { var totalRunTime = scanList.MasterScanTimeList[scanList.MasterScanOrderCount - 1] - scanList.MasterScanTimeList[0]; computedScanTime = scanOrAcqTime * totalRunTime + scanList.MasterScanTimeList[0]; } else { computedScanTime = 0; } break; case clsCustomSICList.eCustomSICScanTypeConstants.AcquisitionTime: // scanOrAcqTime is an elution time value (or elution time range) // No conversion needed; simply return the value computedScanTime = scanOrAcqTime; break; default: // Unknown type; assume already a scan time computedScanTime = scanOrAcqTime; break; } return(computedScanTime); } catch (Exception ex) { OnErrorEvent("Error in clsMasic->ScanOrAcqTimeToScanTime", ex); return(0); } }