private static void WritePScans(string fileName, IRawDataPlus raw, List <PScan> scans) { var enumerator = raw.GetFilteredScanEnumerator(" "); foreach (var scanNumber in enumerator) // note in my tests serial is faster than Parallel.Foreach() (this involves disk access, so it makes sense) { //trailer iinformation is extracted via index var trailers = raw.GetTrailerExtraValues(scanNumber); var trailerLabels = raw.GetTrailerExtraInformation(scanNumber); object chargeState = 0; for (int i = 0; i < trailerLabels.Labels.Length; i++) { if (trailerLabels.Labels[i] == "Charge State:") { chargeState = raw.GetTrailerExtraValue(scanNumber, i); break; } } var scanFilter = raw.GetFilterForScanNumber(scanNumber); var scanStats = raw.GetScanStatsForScanNumber(scanNumber); CentroidStream centroidStream = new CentroidStream(); //check for FT mass analyzer data if (scanFilter.MassAnalyzer == MassAnalyzerType.MassAnalyzerFTMS) { centroidStream = raw.GetCentroidStream(scanNumber, false); } //check for IT mass analyzer data if (scanFilter.MassAnalyzer == MassAnalyzerType.MassAnalyzerITMS) { var scanData = raw.GetSimplifiedScan(scanNumber); centroidStream.Masses = scanData.Masses; centroidStream.Intensities = scanData.Intensities; } var msOrder = raw.GetScanEventForScanNumber(scanNumber).MSOrder; if (msOrder == MSOrderType.Ms) { var pscan = GetPScan(scanStats, centroidStream, 1, fileName, Convert.ToInt32(chargeState)); scans.Add(pscan); } if (msOrder == MSOrderType.Ms2) { var precursorMz = raw.GetScanEventForScanNumber(scanNumber).GetReaction(0).PrecursorMass; var pscan = GetPScan(scanStats, centroidStream, 2, fileName, precursorMz, Convert.ToInt32(chargeState)); scans.Add(pscan); } var t = raw.GetTrailerExtraValues(scanNumber); } WriteScans(scans, fileName); }
public static void GetIndex(this IRawDataPlus rawFile) { int firstScanNumber = rawFile.RunHeaderEx.FirstSpectrum; int lastScanNumber = rawFile.RunHeaderEx.LastSpectrum; int idxCharge = rawFile.GetIndexOfPattern(); int idxMasterScan = rawFile.GetIndexOfPattern("Master Scan Number:"); int idxDependencyType = rawFile.GetIndexOfPattern("Dependency Type:"); double charge, precursorMass; int masterScan, dependencyType; Console.WriteLine("scan;scanType;rtinseconds;precursorMass;MSOrder;charge;masterScan;dependencyType"); for (int scanNumber = firstScanNumber; scanNumber < lastScanNumber; scanNumber++) { var scanTrailer = rawFile.GetTrailerExtraInformation(scanNumber); var scanStatistics = rawFile.GetScanStatsForScanNumber(scanNumber); var scanEvent = rawFile.GetScanEventForScanNumber(scanNumber); var scanFilter = rawFile.GetFilterForScanNumber(scanNumber); try{ var reaction0 = scanEvent.GetReaction(0); precursorMass = reaction0.PrecursorMass; } catch { precursorMass = -1; } try{ charge = int.Parse(scanTrailer.Values.ToArray()[idxCharge]); } catch { charge = -1; } try{ masterScan = int.Parse(scanTrailer.Values.ToArray()[idxMasterScan]); } catch { masterScan = -1; } try{ dependencyType = int.Parse(scanTrailer.Values.ToArray()[idxDependencyType]); } catch { dependencyType = -1; } Console.WriteLine("{0};{1};{2};{3};{4};{5};{6};{7}", scanNumber, scanStatistics.ScanType.ToString(), Math.Round(scanStatistics.StartTime * 60 * 1000) / 1000, precursorMass, scanFilter.MSOrder.ToString(), charge, masterScan, dependencyType); } }
public string[] GetTrailerExtraHeaderInformationLabel() { List <string> rv = new List <string>(); var scanTrailer = rawFile.GetTrailerExtraInformation(rawFile.RunHeaderEx.FirstSpectrum); foreach (var field in scanTrailer.Labels) { rv.Add(field.ToString().CleanRawfileTrailerHeader()); } return(rv.ToArray()); }
private void updateTrailerExtraTextBox() { var trailer = RawData.GetTrailerExtraInformation(Convert.ToInt32(scanNumber.Text)); string text = ""; for (int i = 0; i < trailer.Length; i++) { text += String.Format("{0} {1}{2}", trailer.Labels[i], trailer.Values[i], Environment.NewLine); } trailerExtraTextBox.Text = text; }
/// <summary> /// implements /// https://github.com/fgcz/rawrr/issues/43 /// </summary> /// <param name="rawFile"></param> /// <param name="filename"></param> /// <param name="L"></param> public static void WriteCentroidSpectrumAsRcode(this IRawDataPlus rawFile, string filename, List <int> L) { int count = 1; var trailerFields = rawFile.GetTrailerExtraHeaderInformation(); int indexCharge = rawFile.GetIndexOfPattern("Charge State"); using (System.IO.StreamWriter file = new System.IO.StreamWriter(filename)) { foreach (int scanNumber in L) { var scan = Scan.FromFile(rawFile, scanNumber); var scanStatistics = rawFile.GetScanStatsForScanNumber(scanNumber); var centroidStream = rawFile.GetCentroidStream(scanNumber, false); var scanEvent = rawFile.GetScanEventForScanNumber(scanNumber); var scanTrailer = rawFile.GetTrailerExtraInformation(scanNumber); file.WriteLine("e$Spectrum[[{0}]] <- list(", count++); file.WriteLine("\tscan = {0},", scanNumber); file.WriteLine("\trtinseconds = {0},", Math.Round(scanStatistics.StartTime * 60 * 1000) / 1000); if (indexCharge > 0) { file.WriteLine("\tcharge = {0},", int.Parse(scanTrailer.Values.ToArray()[indexCharge])); } else { file.WriteLine("\tcharge = NA,"); } try{ var reaction0 = scanEvent.GetReaction(0); file.WriteLine("\tpepmass = {0},", reaction0.PrecursorMass); }catch { file.WriteLine("\tpepmass = NA,"); } if (scanStatistics.IsCentroidScan && centroidStream.Length > 0) { file.WriteLine("\tmZ = c(" + string.Join(", ", centroidStream.Masses) + "),"); file.WriteLine("\tintensity = c(" + string.Join(", ", centroidStream.Intensities) + ")"); } else { file.WriteLine("\tmZ = NULL,\n\tintensity = NULL"); } file.WriteLine("\t)"); } } }
public static void WriteSpectrumAsRcode0(this IRawDataPlus rawFile, string filename) { int idxCharge = rawFile.GetIndexOfPattern(); int firstScanNumber = rawFile.RunHeaderEx.FirstSpectrum; int lastScanNumber = rawFile.RunHeaderEx.LastSpectrum; int charge = -1; double pc = -1; using (System.IO.StreamWriter file = new System.IO.StreamWriter(filename)) { for (int scanNumber = firstScanNumber; scanNumber < lastScanNumber; scanNumber++) { var scanTrailer = rawFile.GetTrailerExtraInformation(scanNumber); var scanStatistics = rawFile.GetScanStatsForScanNumber(scanNumber); var scanEvent = rawFile.GetScanEventForScanNumber(scanNumber); var scanFilter = rawFile.GetFilterForScanNumber(scanNumber); try{ var reaction0 = scanEvent.GetReaction(0); pc = reaction0.PrecursorMass; } catch { pc = -1; } try{ charge = int.Parse(scanTrailer.Values.ToArray()[idxCharge]); } catch { charge = -1; } file.WriteLine("e$Spectrum[[{0}]] <- list(", scanNumber); file.WriteLine("\tscan = {0};", scanNumber); file.WriteLine("\tscanType = \"{0}\";", scanStatistics.ScanType.ToString()); file.WriteLine("\trtinseconds = {0};", Math.Round(scanStatistics.StartTime * 60 * 1000) / 1000); file.WriteLine("\tprecursorMass = {0};", pc); file.WriteLine("\tMSOrder = '{0}';", scanFilter.MSOrder.ToString()); file.WriteLine("\tcharge = {0}", charge); file.WriteLine(")"); } } }
/// <summary> /// Get additional double from scan information /// </summary> /// <param name="rawPlus"></param> /// <param name="scan"></param> /// <param name="token"></param> /// <returns></returns> internal static double GetScanExtraDouble(IRawDataPlus rawPlus, int scan, string token) { double dVal = -1.0; LogEntry instLog = rawPlus.GetTrailerExtraInformation(scan); int iLen = instLog.Length; for (int ii = 0; ii < iLen; ii++) { if (instLog.Labels[ii].Contains(token)) { if (double.TryParse(instLog.Values[ii], out dVal)) { return(dVal); } } } return(dVal); }
public Rawfile(string rawfile) { int deviceNumber = 1; _rawfile = rawfile; rawFile = RawFileReaderAdapter.FileFactory(_rawfile); // https://github.com/cpanse/MsBackendRawFileReader/issues/12 rawFile.IncludeReferenceAndExceptionData = false; rawFile.SelectInstrument(Device.MS, deviceNumber); dictInfo.Add("filename", rawFile.FileName); dictInfo.Add("creation date", rawFile.FileHeader.CreationDate.ToString()); dictInfo.Add("first scan", this.GetFirstScanNumber().ToString()); dictInfo.Add("last scan", this.GetLastScanNumber().ToString()); dictInfo.Add("model", rawFile.GetInstrumentData().Model.ToString()); dictInfo.Add("name", rawFile.GetInstrumentData().Name.ToString()); dictInfo.Add("SerialNumber", rawFile.GetInstrumentData().SerialNumber.ToString()); //dictInfo.Add("mass resolution", rawFile.RunHeaderEx.MassResolution.ToString()); var trailerData = rawFile.GetTrailerExtraInformation(rawFile.RunHeaderEx.FirstSpectrum); foreach (int i in Enumerable.Range(1, trailerData.Labels.ToArray().Length)) { try { if ((trailerData.Labels[i] == "Master Scan Number:") || (trailerData.Labels[i] == "Master Scan Number") || (trailerData.Labels[i] == "Master Index:")) { this.masterScanIdx = i; } } catch { } } }
public static MsDataScan GetOneBasedScan(IRawDataPlus rawFile, IFilteringParams filteringParams, int scanNumber) { var filter = rawFile.GetFilterForScanNumber(scanNumber); string scanFilterString = filter.ToString(); int msOrder = (int)filter.MSOrder; if (msOrder < 1 || msOrder > 10) { throw new MzLibException("Unknown MS Order (" + msOrder + ") for scan number " + scanNumber); } string nativeId = "controllerType=0 controllerNumber=1 scan=" + scanNumber; MzSpectrum spectrum = GetSpectrum(rawFile, filteringParams, scanNumber, scanFilterString, msOrder); var scanStats = rawFile.GetScanStatsForScanNumber(scanNumber); double scanRangeHigh = scanStats.HighMass; double scanRangeLow = scanStats.LowMass; MzRange scanWindowRange = new MzRange(scanRangeLow, scanRangeHigh); double? ionInjectionTime = null; double? precursorSelectedMonoisotopicIonMz = null; int? selectedIonChargeState = null; double? ms2IsolationWidth = null; int? precursorScanNumber = null; double? isolationMz = null; string HcdEnergy = null; ActivationType activationType = ActivationType.Any; // thermo enum DissociationType dissociationType = DissociationType.Unknown; // mzLib enum var trailer = rawFile.GetTrailerExtraInformation(scanNumber); string[] labels = trailer.Labels; string[] values = trailer.Values; for (int i = 0; i < trailer.Labels.Length; i++) { if (labels[i].StartsWith("Ion Injection Time (ms)", StringComparison.Ordinal)) { ionInjectionTime = double.Parse(values[i], CultureInfo.InvariantCulture) == 0 ? (double?)null : double.Parse(values[i], CultureInfo.InvariantCulture); } if (msOrder < 2) { continue; } if (labels[i].StartsWith("MS" + msOrder + " Isolation Width", StringComparison.Ordinal)) { ms2IsolationWidth = double.Parse(values[i], CultureInfo.InvariantCulture) == 0 ? (double?)null : double.Parse(values[i], CultureInfo.InvariantCulture); } if (labels[i].StartsWith("Monoisotopic M/Z", StringComparison.Ordinal)) { precursorSelectedMonoisotopicIonMz = double.Parse(values[i], CultureInfo.InvariantCulture) == 0 ? (double?)null : double.Parse(values[i], CultureInfo.InvariantCulture); } if (labels[i].StartsWith("Charge State", StringComparison.Ordinal)) { selectedIonChargeState = int.Parse(values[i], CultureInfo.InvariantCulture) == 0 ? (int?)null : int.Parse(values[i], CultureInfo.InvariantCulture); } if (labels[i].StartsWith("Master Scan Number", StringComparison.Ordinal) || labels[i].StartsWith("Master Index", StringComparison.Ordinal)) { precursorScanNumber = int.Parse(values[i], CultureInfo.InvariantCulture) <= 1 ? (int?)null : int.Parse(values[i], CultureInfo.InvariantCulture); } if (labels[i].StartsWith("HCD Energy:", StringComparison.Ordinal)) { HcdEnergy = values[i]; } } if (msOrder > 1) { var scanEvent = rawFile.GetScanEventForScanNumber(scanNumber); var reaction = scanEvent.GetReaction(0); isolationMz = reaction.PrecursorMass; activationType = reaction.ActivationType; dissociationType = GetDissociationType(activationType); // thermo does not have an enum value for ETHcD, so this needs to be detected from the scan filter if (scanFilterString.Contains("@etd", StringComparison.OrdinalIgnoreCase) && scanFilterString.Contains("@hcd", StringComparison.OrdinalIgnoreCase)) { dissociationType = DissociationType.EThcD; } if (ms2IsolationWidth == null) { ms2IsolationWidth = reaction.IsolationWidth; } if (precursorScanNumber == null) { // we weren't able to get the precursor scan number, so we'll have to guess; // loop back to find precursor scan // (assumed to be the first scan before this scan with an MS order of this scan's MS order - 1) // e.g., if this is an MS2 scan, find the first MS1 scan before this and assume that's the precursor scan for (int i = scanNumber; i >= 1; i--) { var possiblePrecursorScanFilter = rawFile.GetFilterForScanNumber(i); int order = (int)possiblePrecursorScanFilter.MSOrder; if (order == msOrder - 1) { precursorScanNumber = i; break; } } if (precursorScanNumber == null) { throw new MzLibException("Could not get precursor for scan #" + scanNumber); } } } // at this point, we have the m/z value of the species that got fragmented, from the scan header // this section of the code finds that peak in the spectrum (it's actual intensity and centroided m/z values) // the intention is to remove any rounding issues caused by what is in the scan header and what is observable in the spectrum double?selectedIonIntensity = null; if (isolationMz.HasValue) { if (spectrum.Size != 0) { int closest = spectrum.GetClosestPeakIndex(isolationMz.Value); double mz = spectrum.XArray[closest]; double intensity = spectrum.YArray[closest]; if (Math.Abs(mz - isolationMz.Value) < 0.1) { selectedIonIntensity = intensity; isolationMz = mz; } } } return(new MsDataScan( massSpectrum: spectrum, oneBasedScanNumber: scanNumber, msnOrder: msOrder, isCentroid: true, polarity: GetPolarity(filter.Polarity), retentionTime: rawFile.RetentionTimeFromScanNumber(scanNumber), scanWindowRange: scanWindowRange, scanFilter: scanFilterString, mzAnalyzer: GetMassAnalyzerType(filter.MassAnalyzer), totalIonCurrent: spectrum.SumOfAllY, injectionTime: ionInjectionTime, noiseData: null, //TODO: implement reading noise data. it's unused right now, so it's just left as null nativeId: nativeId, selectedIonMz: isolationMz, selectedIonChargeStateGuess: selectedIonChargeState, selectedIonIntensity: selectedIonIntensity, isolationMZ: isolationMz, isolationWidth: ms2IsolationWidth, dissociationType: dissociationType, oneBasedPrecursorScanNumber: precursorScanNumber, selectedIonMonoisotopicGuessMz: precursorSelectedMonoisotopicIonMz, hcdEnergy: HcdEnergy)); }
/// <inheritdoc /> public override void Write(IRawDataPlus rawFile, int firstScanNumber, int lastScanNumber) { ConfigureWriter(".mgf"); using (Writer) { Log.Info("Processing " + (lastScanNumber - firstScanNumber + 1) + " scans"); var lastScanProgress = 0; for (var scanNumber = firstScanNumber; scanNumber <= lastScanNumber; scanNumber++) { if (ParseInput.LogFormat == LogFormat.DEFAULT) { var scanProgress = (int)((double)scanNumber / (lastScanNumber - firstScanNumber + 1) * 100); if (scanProgress % ProgressPercentageStep == 0) { if (scanProgress != lastScanProgress) { Console.Write("" + scanProgress + "% "); lastScanProgress = scanProgress; } } } // Get each scan from the RAW file var scan = Scan.FromFile(rawFile, scanNumber); // Check to see if the RAW file contains label (high-res) data and if it is present // then look for any data that is out of order var time = rawFile.RetentionTimeFromScanNumber(scanNumber); // Get the scan filter for this scan number var scanFilter = rawFile.GetFilterForScanNumber(scanNumber); // Get the scan event for this scan number var scanEvent = rawFile.GetScanEventForScanNumber(scanNumber); // precursor reference var spectrumRef = ""; //keeping track of precursor scan switch (scanFilter.MSOrder) { case MSOrderType.Ms: // Keep track of scan number for precursor reference _precursorMs1ScanNumber = scanNumber; break; case MSOrderType.Ms2: // Keep track of scan number and isolation m/z for precursor reference var result = Regex.Match(scanEvent.ToString(), FilterStringIsolationMzPattern); if (result.Success) { if (_precursorMs2ScanNumbers.ContainsKey(result.Groups[1].Value)) { _precursorMs2ScanNumbers.Remove(result.Groups[1].Value); } _precursorMs2ScanNumbers.Add(result.Groups[1].Value, scanNumber); } spectrumRef = ConstructSpectrumTitle((int)Device.MS, 1, _precursorMs1ScanNumber); break; case MSOrderType.Ms3: var precursorMs2ScanNumber = _precursorMs2ScanNumbers.Keys.FirstOrDefault( isolationMz => scanEvent.ToString().Contains(isolationMz)); if (!precursorMs2ScanNumber.IsNullOrEmpty()) { spectrumRef = ConstructSpectrumTitle((int)Device.MS, 1, _precursorMs2ScanNumbers[precursorMs2ScanNumber]); } else { throw new InvalidOperationException("Couldn't find a MS2 precursor scan for MS3 scan " + scanEvent); } break; default: break; } // don't include MS1 spectra if (ParseInput.MsLevel.Contains((int)scanFilter.MSOrder)) { IReaction reaction = GetReaction(scanEvent, scanNumber); Writer.WriteLine("BEGIN IONS"); if (ParseInput.MGFPrecursor) { Writer.WriteLine($"TITLE={ConstructSpectrumTitle((int)Device.MS, 1, scanNumber)} [PRECURSOR={spectrumRef}]"); } else { Writer.WriteLine($"TITLE={ConstructSpectrumTitle((int)Device.MS, 1, scanNumber)}"); } Writer.WriteLine($"SCANS={scanNumber}"); Writer.WriteLine( $"RTINSECONDS={(time * 60).ToString(CultureInfo.InvariantCulture)}"); // trailer extra data list var trailerData = rawFile.GetTrailerExtraInformation(scanNumber); int? charge = null; double?monoisotopicMz = null; double?isolationWidth = null; for (var i = 0; i < trailerData.Length; i++) { if (trailerData.Labels[i] == "Charge State:") { if (Convert.ToInt32(trailerData.Values[i]) > 0) { charge = Convert.ToInt32(trailerData.Values[i]); } } if (trailerData.Labels[i] == "Monoisotopic M/Z:") { monoisotopicMz = double.Parse(trailerData.Values[i], NumberStyles.Any, CultureInfo.CurrentCulture); } if (trailerData.Labels[i] == "MS" + (int)scanFilter.MSOrder + " Isolation Width:") { isolationWidth = double.Parse(trailerData.Values[i], NumberStyles.Any, CultureInfo.CurrentCulture); } } if (reaction != null) { var selectedIonMz = CalculateSelectedIonMz(reaction, monoisotopicMz, isolationWidth); Writer.WriteLine("PEPMASS=" + selectedIonMz.ToString(CultureInfo.InvariantCulture)); } // charge if (charge != null) { // Scan polarity var polarity = PositivePolarity; if (scanFilter.Polarity == PolarityType.Negative) { polarity = NegativePolarity; } Writer.WriteLine($"CHARGE={charge}{polarity}"); } // write the filter string //Writer.WriteLine($"SCANEVENT={scanEvent.ToString()}"); if (!ParseInput.NoPeakPicking) { // check if the scan has a centroid stream if (scan.HasCentroidStream) { if (scan.CentroidScan.Length > 0) { for (var i = 0; i < scan.CentroidScan.Length; i++) { Writer.WriteLine( scan.CentroidScan.Masses[i].ToString("0.0000000", CultureInfo.InvariantCulture) + " " + scan.CentroidScan.Intensities[i].ToString("0.0000000000", CultureInfo.InvariantCulture)); } } } else // otherwise take segmented (low res) scan data { // if the spectrum is profile perform centroiding var segmentedScan = scanEvent.ScanData == ScanDataType.Profile ? Scan.ToCentroid(scan).SegmentedScan : scan.SegmentedScan; for (var i = 0; i < segmentedScan.Positions.Length; i++) { Writer.WriteLine( segmentedScan.Positions[i].ToString("0.0000000", CultureInfo.InvariantCulture) + " " + segmentedScan.Intensities[i].ToString("0.0000000000", CultureInfo.InvariantCulture)); } } } else // use the segmented data as is { for (var i = 0; i < scan.SegmentedScan.Positions.Length; i++) { Writer.WriteLine( scan.SegmentedScan.Positions[i].ToString("0.0000000", CultureInfo.InvariantCulture) + " " + scan.SegmentedScan.Intensities[i].ToString("0.0000000000", CultureInfo.InvariantCulture)); } } Writer.WriteLine("END IONS"); Log.Debug("Spectrum written to file -- SCAN " + scanNumber); } } if (ParseInput.LogFormat == LogFormat.DEFAULT) { Console.WriteLine(); } } }
/// <inheritdoc /> public override void Write(IRawDataPlus rawFile, int firstScanNumber, int lastScanNumber) { ConfigureWriter(".mgf"); using (Writer) { Log.Info("Processing " + (lastScanNumber - firstScanNumber + 1) + " scans"); var lastScanProgress = 0; for (var scanNumber = firstScanNumber; scanNumber <= lastScanNumber; scanNumber++) { if (!ParseInput.Verbose) { var scanProgress = (int)((double)scanNumber / (lastScanNumber - firstScanNumber + 1) * 100); if (scanProgress % ProgressPercentageStep == 0) { if (scanProgress != lastScanProgress) { Console.Write("" + scanProgress + "% "); lastScanProgress = scanProgress; } } } // Get each scan from the RAW file var scan = Scan.FromFile(rawFile, scanNumber); // Check to see if the RAW file contains label (high-res) data and if it is present // then look for any data that is out of order var time = rawFile.RetentionTimeFromScanNumber(scanNumber); // Get the scan filter for this scan number var scanFilter = rawFile.GetFilterForScanNumber(scanNumber); // Get the scan event for this scan number var scanEvent = rawFile.GetScanEventForScanNumber(scanNumber); IReaction reaction = null; switch (scanFilter.MSOrder) { case MSOrderType.Ms: // Keep track of scan number for precursor reference _precursorScanNumber = scanNumber; break; case MSOrderType.Ms2: try { reaction = scanEvent.GetReaction(0); } catch (ArgumentOutOfRangeException exception) { Log.Warn("No reaction found for scan " + scanNumber); } goto default; case MSOrderType.Ms3: { try { reaction = scanEvent.GetReaction(1); } catch (ArgumentOutOfRangeException) { Log.Warn("No reaction found for scan " + scanNumber); } goto default; } default: Writer.WriteLine("BEGIN IONS"); Writer.WriteLine($"TITLE={ConstructSpectrumTitle(scanNumber)}"); Writer.WriteLine($"SCANS={scanNumber}"); Writer.WriteLine( $"RTINSECONDS={(time * 60).ToString(CultureInfo.InvariantCulture)}"); // trailer extra data list var trailerData = rawFile.GetTrailerExtraInformation(scanNumber); int? charge = null; double?monoisotopicMz = null; double?isolationWidth = null; for (var i = 0; i < trailerData.Length; i++) { if (trailerData.Labels[i] == "Charge State:") { if (Convert.ToInt32(trailerData.Values[i]) > 0) { charge = Convert.ToInt32(trailerData.Values[i]); } } if (trailerData.Labels[i] == "Monoisotopic M/Z:") { monoisotopicMz = double.Parse(trailerData.Values[i], NumberStyles.Any, CultureInfo.CurrentCulture); } if (trailerData.Labels[i] == "MS" + (int)scanFilter.MSOrder + " Isolation Width:") { isolationWidth = double.Parse(trailerData.Values[i], NumberStyles.Any, CultureInfo.CurrentCulture); } } if (reaction != null) { var selectedIonMz = CalculateSelectedIonMz(reaction, monoisotopicMz, isolationWidth); Writer.WriteLine("PEPMASS=" + selectedIonMz.ToString(CultureInfo.InvariantCulture)); } // charge if (charge != null) { // Scan polarity var polarity = PositivePolarity; if (scanFilter.Polarity == PolarityType.Negative) { polarity = NegativePolarity; } Writer.WriteLine($"CHARGE={charge}{polarity}"); } // write the filter string //Writer.WriteLine($"SCANEVENT={scanEvent.ToString()}"); // Check if the scan has a centroid stream if (scan.HasCentroidStream && (scanEvent.ScanData == ScanDataType.Centroid || (scanEvent.ScanData == ScanDataType.Profile && !ParseInput.NoPeakPicking))) { var centroidStream = rawFile.GetCentroidStream(scanNumber, false); if (scan.CentroidScan.Length > 0) { for (var i = 0; i < centroidStream.Length; i++) { Writer.WriteLine( centroidStream.Masses[i].ToString("0.0000000", CultureInfo.InvariantCulture) + " " + centroidStream.Intensities[i].ToString("0.0000000000", CultureInfo.InvariantCulture)); } } } // Otherwise take the profile data else { // Get the scan statistics from the RAW file for this scan number var scanStatistics = rawFile.GetScanStatsForScanNumber(scanNumber); // Get the segmented (low res and profile) scan data var segmentedScan = rawFile.GetSegmentedScanFromScanNumber(scanNumber, scanStatistics); for (var i = 0; i < segmentedScan.Positions.Length; i++) { Writer.WriteLine( segmentedScan.Positions[i].ToString("0.0000000", CultureInfo.InvariantCulture) + " " + segmentedScan.Intensities[i].ToString("0.0000000000", CultureInfo.InvariantCulture)); } } Writer.WriteLine("END IONS"); Log.Debug("Spectrum written to file -- SCAN " + scanNumber); break; } } if (!ParseInput.Verbose) { Console.WriteLine(); } } }
/// <summary> /// Construct a spectrum element for the given scan /// </summary> /// <param name="scanNumber">the scan number</param> /// <returns>The SpectrumType object</returns> private SpectrumType ConstructSpectrum(int scanNumber) { // Get each scan from the RAW file var scan = Scan.FromFile(_rawFile, scanNumber); // Get the scan filter for this scan number var scanFilter = _rawFile.GetFilterForScanNumber(scanNumber); // Get the scan event for this scan number var scanEvent = _rawFile.GetScanEventForScanNumber(scanNumber); var spectrum = new SpectrumType { id = ConstructSpectrumTitle(scanNumber), defaultArrayLength = 0 }; // Add the ionization type if necessary if (!_ionizationTypes.ContainsKey(scanFilter.IonizationMode)) { _ionizationTypes.Add(scanFilter.IonizationMode, OntologyMapping.IonizationTypes[scanFilter.IonizationMode]); } // Add the mass analyzer if necessary if (!_massAnalyzers.ContainsKey(scanFilter.MassAnalyzer) && OntologyMapping.MassAnalyzerTypes.ContainsKey(scanFilter.MassAnalyzer)) { _massAnalyzers.Add(scanFilter.MassAnalyzer, "IC" + (_massAnalyzers.Count + 1)); } // Keep the CV params in a list and convert to array afterwards var spectrumCvParams = new List <CVParamType> { new CVParamType { name = "ms level", accession = "MS:1000511", value = ((int)scanFilter.MSOrder).ToString(CultureInfo.InvariantCulture), cvRef = "MS" } }; // Trailer extra data list var trailerData = _rawFile.GetTrailerExtraInformation(scanNumber); int? charge = null; double?monoisotopicMass = null; for (var i = 0; i < trailerData.Length; i++) { if (trailerData.Labels[i] == "Charge State:") { if (Convert.ToInt32(trailerData.Values[i]) > 0) { charge = Convert.ToInt32(trailerData.Values[i]); } } if (trailerData.Labels[i] == "Monoisotopic M/Z:") { monoisotopicMass = double.Parse(trailerData.Values[i]); } } // Construct and set the scan list element of the spectrum var scanListType = ConstructScanList(scanNumber, scan, scanFilter, scanEvent, monoisotopicMass); spectrum.scanList = scanListType; switch (scanFilter.MSOrder) { case MSOrderType.Ms: spectrumCvParams.Add(new CVParamType { accession = "MS:1000579", cvRef = "MS", name = "MS1 spectrum", value = "" }); // Keep track of scan number for precursor reference _precursorScanNumber = scanNumber; break; case MSOrderType.Ms2: spectrumCvParams.Add(new CVParamType { accession = "MS:1000580", cvRef = "MS", name = "MSn spectrum", value = "" }); // Construct and set the precursor list element of the spectrum var precursorListType = ConstructPrecursorList(scanEvent, charge); spectrum.precursorList = precursorListType; break; case MSOrderType.Ng: break; case MSOrderType.Nl: break; case MSOrderType.Par: break; case MSOrderType.Any: break; case MSOrderType.Ms3: break; case MSOrderType.Ms4: break; case MSOrderType.Ms5: break; case MSOrderType.Ms6: break; case MSOrderType.Ms7: break; case MSOrderType.Ms8: break; case MSOrderType.Ms9: break; case MSOrderType.Ms10: break; default: throw new ArgumentOutOfRangeException(); } // Scan polarity var polarityType = scanFilter.Polarity; switch (polarityType) { case PolarityType.Positive: spectrumCvParams.Add(new CVParamType { accession = "MS:1000130", cvRef = "MS", name = "positive scan", value = "" }); break; case PolarityType.Negative: spectrumCvParams.Add(new CVParamType { accession = "MS:1000129", cvRef = "MS", name = "negative scan", value = "" }); break; case PolarityType.Any: break; default: throw new ArgumentOutOfRangeException(); } // Total ion current spectrumCvParams.Add(new CVParamType { name = "total ion current", accession = "MS:1000285", value = scan.ScanStatistics.TIC.ToString(CultureInfo.InvariantCulture), cvRef = "MS" }); double?basePeakMass = null; double?basePeakIntensity = null; double?lowestObservedMz = null; double?highestObservedMz = null; double[] masses = null; double[] intensities = null; if (scan.HasCentroidStream) { var centroidStream = _rawFile.GetCentroidStream(scanNumber, false); if (scan.CentroidScan.Length > 0) { basePeakMass = centroidStream.BasePeakMass; basePeakIntensity = centroidStream.BasePeakIntensity; lowestObservedMz = centroidStream.Masses[0]; highestObservedMz = centroidStream.Masses[centroidStream.Masses.Length - 1]; masses = centroidStream.Masses; intensities = centroidStream.Intensities; // Note that although the scan data type is profile, // centroid data might be available spectrumCvParams.Add(new CVParamType { accession = "MS:1000127", cvRef = "MS", name = "centroid spectrum", value = "" }); } } else { // Get the scan statistics from the RAW file for this scan number var scanStatistics = _rawFile.GetScanStatsForScanNumber(scanNumber); basePeakMass = scanStatistics.BasePeakMass; basePeakIntensity = scanStatistics.BasePeakIntensity; // Get the segmented (low res and profile) scan data var segmentedScan = _rawFile.GetSegmentedScanFromScanNumber(scanNumber, scanStatistics); if (segmentedScan.Positions.Length > 0) { lowestObservedMz = segmentedScan.Positions[0]; highestObservedMz = segmentedScan.Positions[segmentedScan.Positions.Length - 1]; masses = segmentedScan.Positions; intensities = segmentedScan.Intensities; spectrumCvParams.Add(new CVParamType { accession = "MS:1000128", cvRef = "MS", name = "profile spectrum", value = "" }); } } // Base peak m/z if (basePeakMass != null) { spectrumCvParams.Add(new CVParamType { name = "base peak m/z", accession = "MS:1000504", value = basePeakMass.ToString(), unitCvRef = "MS", unitName = "m/z", unitAccession = "MS:1000040", cvRef = "MS" }); } // Base peak intensity if (basePeakMass != null) { spectrumCvParams.Add(new CVParamType { name = "base peak intensity", accession = "MS:1000505", value = basePeakIntensity.ToString(), unitCvRef = "MS", unitName = "number of detector counts", unitAccession = "MS:1000131", cvRef = "MS" }); } // Lowest observed mz if (lowestObservedMz != null) { spectrumCvParams.Add(new CVParamType { name = "lowest observed m/z", accession = "MS:1000528", value = lowestObservedMz.ToString(), unitCvRef = "MS", unitAccession = "MS:1000040", unitName = "m/z", cvRef = "MS" }); } // Highest observed mz if (highestObservedMz != null) { spectrumCvParams.Add(new CVParamType { name = "highest observed m/z", accession = "MS:1000527", value = highestObservedMz.ToString(), unitAccession = "MS:1000040", unitName = "m/z", unitCvRef = "MS", cvRef = "MS" }); } // Add the CV params to the spectrum spectrum.cvParam = spectrumCvParams.ToArray(); // Binary data array list var binaryData = new List <BinaryDataArrayType>(); // M/Z Data if (!masses.IsNullOrEmpty()) { // Set the spectrum default array length spectrum.defaultArrayLength = masses.Length; var massesBinaryData = new BinaryDataArrayType { binary = GetZLib64BitArray(masses) }; massesBinaryData.encodedLength = (4 * Math.Ceiling((double)massesBinaryData .binary.Length / 3)).ToString(CultureInfo.InvariantCulture); massesBinaryData.cvParam = new CVParamType[3]; massesBinaryData.cvParam[0] = new CVParamType { accession = "MS:1000514", name = "m/z array", cvRef = "MS", unitName = "m/z", value = "", unitCvRef = "MS", unitAccession = "MS:1000040" }; massesBinaryData.cvParam[1] = new CVParamType { accession = "MS:1000523", name = "64-bit float", cvRef = "MS", value = "" }; massesBinaryData.cvParam[2] = new CVParamType { accession = "MS:1000574", name = "zlib compression", cvRef = "MS", value = "" }; binaryData.Add(massesBinaryData); } // Intensity Data if (!intensities.IsNullOrEmpty()) { // Set the spectrum default array length if necessary if (spectrum.defaultArrayLength == 0) { spectrum.defaultArrayLength = masses.Length; } var intensitiesBinaryData = new BinaryDataArrayType { binary = GetZLib64BitArray(intensities) }; intensitiesBinaryData.encodedLength = (4 * Math.Ceiling((double)intensitiesBinaryData .binary.Length / 3)).ToString(CultureInfo.InvariantCulture); intensitiesBinaryData.cvParam = new CVParamType[3]; intensitiesBinaryData.cvParam[0] = new CVParamType { accession = "MS:1000515", name = "intensity array", cvRef = "MS", unitCvRef = "MS", unitAccession = "MS:1000131", unitName = "number of counts", value = "" }; intensitiesBinaryData.cvParam[1] = new CVParamType { accession = "MS:1000523", name = "64-bit float", cvRef = "MS", value = "" }; intensitiesBinaryData.cvParam[2] = new CVParamType { accession = "MS:1000574", name = "zlib compression", cvRef = "MS", value = "" }; binaryData.Add(intensitiesBinaryData); } if (!binaryData.IsNullOrEmpty()) { spectrum.binaryDataArrayList = new BinaryDataArrayListType { count = binaryData.Count.ToString(), binaryDataArray = binaryData.ToArray() }; } return(spectrum); }
/// <summary> /// Write the RAW file metadata to file. /// <param name="rawFile">the RAW file object</param> /// <param name="firstScanNumber">the first scan number</param> /// <param name="lastScanNumber">the last scan number</param> /// </summary> public void WriteJsonMetada(IRawDataPlus rawFile, int firstScanNumber, int lastScanNumber) { // Get the start and end time from the RAW file var startTime = rawFile.RunHeaderEx.StartTime; var endTime = rawFile.RunHeaderEx.EndTime; var metadata = new Metadata(); // File Properties metadata.addFileProperty(new CVTerm("NCIT:C47922", "NCIT", "Pathname", rawFile.FileName)); metadata.addFileProperty(new CVTerm("NCIT:C25714", "NCIT", "Version", rawFile.FileHeader.Revision.ToString())); metadata.addFileProperty(new CVTerm("NCIT:C69199", "NCIT", "Content Creation Date", rawFile.FileHeader.CreationDate.ToString())); metadata.addFileProperty(new CVTerm("NCIT:C25365", "NCIT", "Description", rawFile.FileHeader.FileDescription)); metadata.addScanSetting(new CVTerm("MS:1000016", "MS", "scan start time", startTime.ToString())); metadata.addScanSetting(new CVTerm("MS:1000011", "MS", "mass resolution", rawFile.RunHeaderEx.MassResolution.ToString())); metadata.addScanSetting(new CVTerm("UO:0000002", "MS", "mass unit", rawFile.GetInstrumentData().Units.ToString())); metadata.addScanSetting(new CVTerm("PRIDE:0000478", "PRIDE", "Number of scans", rawFile.RunHeaderEx.SpectraCount.ToString())); metadata.addScanSetting(new CVTerm("PRIDE:0000479", "PRIDE", "MS scan range", firstScanNumber + ":" + lastScanNumber)); metadata.addScanSetting(new CVTerm("PRIDE:0000484", "PRIDE", "Retention time range", startTime + ":" + endTime)); metadata.addScanSetting(new CVTerm("PRIDE:0000485", "PRIDE", "Mz range", rawFile.RunHeaderEx.LowMass + ":" + rawFile.RunHeaderEx.HighMass)); metadata.addInstrumentProperty(new CVTerm("MS:1000494", "MS", "Thermo Scientific instrument model", rawFile.GetInstrumentData().Model)); metadata.addInstrumentProperty(new CVTerm("MS:1000496", "MS", "instrument attribute", rawFile.GetInstrumentData().Name)); metadata.addInstrumentProperty(new CVTerm("MS:1000529", "MS", "instrument serial number", rawFile.GetInstrumentData().SerialNumber)); var msTypes = new Dictionary <string, int>(); double minTime = 1000000000000000; double maxTime = 0; double minMz = 1000000000000000000; double maxMz = 0; double minCharge = 100000000000000; double maxCharge = 0; ICollection <CVTerm> fragmentationType = new HashSet <CVTerm>(CVTerm.CvTermComparer); for (var scanNumber = firstScanNumber; scanNumber <= lastScanNumber; scanNumber++) { var time = rawFile.RetentionTimeFromScanNumber(scanNumber); // Get the scan filter for this scan number var scanFilter = rawFile.GetFilterForScanNumber(scanNumber); // Get the scan event for this scan number var scanEvent = rawFile.GetScanEventForScanNumber(scanNumber); // Only consider MS2 spectra if (msTypes.ContainsKey(scanFilter.MSOrder.ToString())) { var value = msTypes[scanFilter.MSOrder.ToString()]; value = value + 1; msTypes[scanFilter.MSOrder.ToString()] = value; } else { msTypes.Add(scanFilter.MSOrder.ToString(), 1); } if (time > maxTime) { maxTime = time; } if (time < minTime) { minTime = time; } if (scanFilter.MSOrder == MSOrderType.Ms2) { fragmentationType.Add(ParseActivationType(scanFilter.GetActivation(0))); if (scanEvent.ScanData == ScanDataType.Centroid || (scanEvent.ScanData == ScanDataType.Profile)) { try { var reaction = scanEvent.GetReaction(0); var precursorMass = reaction.PrecursorMass; if (precursorMass > maxMz) { maxMz = precursorMass; } if (precursorMass < minMz) { minMz = precursorMass; } } catch (ArgumentOutOfRangeException) { Log.Warn("No reaction found for scan " + scanNumber); } // trailer extra data list var trailerData = rawFile.GetTrailerExtraInformation(scanNumber); for (var i = 0; i < trailerData.Length; i++) { if (trailerData.Labels[i] == "Charge State:") { if (int.Parse(trailerData.Values[i]) > maxCharge) { maxCharge = int.Parse(trailerData.Values[i]); } if (int.Parse(trailerData.Values[i]) < minCharge) { minCharge = int.Parse(trailerData.Values[i]); } } } } } } if (minCharge == 100000000000000) { minCharge = 0; } foreach (KeyValuePair <string, int> entry in msTypes) { if (entry.Key.Equals(MSOrderType.Ms.ToString())) { metadata.addMSData(new CVTerm("PRIDE:0000481", "PRIDE", "Number of MS1 spectra", entry.Value.ToString())); } if (entry.Key.Equals(MSOrderType.Ms2.ToString())) { metadata.addMSData(new CVTerm("PRIDE:0000482", "PRIDE", "Number of MS2 spectra", entry.Value.ToString())); } if (entry.Key.Equals(MSOrderType.Ms3.ToString())) { metadata.addMSData(new CVTerm("PRIDE:0000483", "PRIDE", "Number of MS3 spectra", entry.Value.ToString())); } } metadata.addScanSetting(fragmentationType); metadata.addMSData(new CVTerm("PRIDE:0000472", "PRIDE", "MS min charge", minCharge.ToString())); metadata.addMSData(new CVTerm("PRIDE:0000473", "PRIDE", "MS max charge", maxCharge.ToString())); metadata.addMSData(new CVTerm("PRIDE:0000474", "PRIDE", "MS min RT", minTime.ToString())); metadata.addMSData(new CVTerm("PRIDE:0000475", "PRIDE", "MS max RT", maxTime.ToString())); metadata.addMSData(new CVTerm("PRIDE:0000476", "PRIDE", "MS min MZ", minMz.ToString())); metadata.addMSData(new CVTerm("PRIDE:0000477", "PRIDE", "MS max MZ", maxMz.ToString())); // Write the meta data to file var json = JsonConvert.SerializeObject(metadata); json.Replace("\r\n", "\n"); string metadataOutputPath; if (_outputDirectory == null) { metadataOutputPath = _metadataFileName; } else { metadataOutputPath = _outputDirectory + "/" + _metadataFileName + "-metadata.json"; } File.WriteAllText(metadataOutputPath, json); }
/// <inheritdoc /> public override void Write(IRawDataPlus rawFile, int firstScanNumber, int lastScanNumber) { ConfigureWriter(".mgf"); using (Writer) { for (var scanNumber = firstScanNumber; scanNumber <= lastScanNumber; scanNumber++) { // Get each scan from the RAW file var scan = Scan.FromFile(rawFile, scanNumber); // Check to see if the RAW file contains label (high-res) data and if it is present // then look for any data that is out of order var time = rawFile.RetentionTimeFromScanNumber(scanNumber); // Get the scan filter for this scan number var scanFilter = rawFile.GetFilterForScanNumber(scanNumber); // Get the scan event for this scan number var scanEvent = rawFile.GetScanEventForScanNumber(scanNumber); // Only consider MS2 spectra if (scanFilter.MSOrder == MSOrderType.Ms2) { if (scanEvent.ScanData == ScanDataType.Centroid || (scanEvent.ScanData == ScanDataType.Profile && !ParseInput.ExcludeProfileData)) { Writer.WriteLine("BEGIN IONS"); Writer.WriteLine($"TITLE={ConstructSpectrumTitle(scanNumber)}"); Writer.WriteLine($"SCAN={scanNumber}"); Writer.WriteLine($"RTINSECONDS={time * 60}"); // Get the reaction information for the first precursor try { var reaction = scanEvent.GetReaction(0); var precursorMass = reaction.PrecursorMass; Writer.WriteLine($"PEPMASS={precursorMass:F7}"); } catch (ArgumentOutOfRangeException exception) { Log.Warn("No reaction found for scan " + scanNumber); } // trailer extra data list var trailerData = rawFile.GetTrailerExtraInformation(scanNumber); for (var i = 0; i < trailerData.Length; i++) { if (trailerData.Labels[i] == "Charge State:") { if (Convert.ToInt32(trailerData.Values[i]) > 0) { Writer.WriteLine($"CHARGE={trailerData.Values[i]}+"); } } } // Check if the scan has a centroid stream if (scan.HasCentroidStream) { var centroidStream = rawFile.GetCentroidStream(scanNumber, false); if (scan.CentroidScan.Length > 0) { for (var i = 0; i < centroidStream.Length; i++) { Writer.WriteLine( $"{centroidStream.Masses[i]:F7} {centroidStream.Intensities[i]:F10}"); } } } // Otherwise take the profile data else { // Get the scan statistics from the RAW file for this scan number var scanStatistics = rawFile.GetScanStatsForScanNumber(scanNumber); // Get the segmented (low res and profile) scan data var segmentedScan = rawFile.GetSegmentedScanFromScanNumber(scanNumber, scanStatistics); for (var i = 0; i < segmentedScan.Positions.Length; i++) { Writer.WriteLine( $"{segmentedScan.Positions[i]:F7} {segmentedScan.Intensities[i]:F10}"); } } Writer.WriteLine("END IONS"); } } } } }
/// <summary> /// Write the RAW file metadata to file. /// <param name="rawFile">the RAW file object</param> /// <param name="firstScanNumber">the first scan number</param> /// <param name="lastScanNumber">the last scan number</param> /// </summary> public void WriteJsonMetada(IRawDataPlus rawFile, int firstScanNumber, int lastScanNumber) { // Get the start and end time from the RAW file var startTime = rawFile.RunHeaderEx.StartTime; var endTime = rawFile.RunHeaderEx.EndTime; var metadata = new Metadata(); /** File Properties **/ metadata.addFileProperty("path", rawFile.FileName); metadata.addFileProperty("version", rawFile.FileHeader.Revision.ToString()); metadata.addFileProperty("creation-date", rawFile.FileHeader.CreationDate.ToString()); metadata.addFileProperty("number-instruments", rawFile.InstrumentCount.ToString()); metadata.addFileProperty("description", rawFile.FileHeader.FileDescription); /** Sample Properties **/ metadata.addSampleProperty("name", rawFile.SampleInformation.SampleName); metadata.addSampleProperty("id", rawFile.SampleInformation.SampleId); metadata.addSampleProperty("type", rawFile.SampleInformation.SampleType.ToString()); metadata.addSampleProperty("comment", rawFile.SampleInformation.Comment); metadata.addSampleProperty("vial", rawFile.SampleInformation.Vial); metadata.addSampleProperty("volume", rawFile.SampleInformation.SampleVolume.ToString()); metadata.addSampleProperty("injection-volume", rawFile.SampleInformation.InjectionVolume.ToString()); metadata.addSampleProperty("row-number", rawFile.SampleInformation.RowNumber.ToString()); metadata.addSampleProperty("dilution-factor", rawFile.SampleInformation.DilutionFactor.ToString()); metadata.addScanSetting("start-time", new CVTerm("MS:1000016", "MS", "scan start time", startTime.ToString())); metadata.addScanSetting("resolution", new CVTerm("MS:1000011", "MS", "mass resolution", rawFile.RunHeaderEx.MassResolution.ToString())); metadata.addScanSetting("tolerance-unit", new CVTerm("UO:0000002", "MS", "mass unit", rawFile.GetInstrumentData().Units.ToString())); metadata.addScanSetting("number-scans", rawFile.RunHeaderEx.SpectraCount.ToString()); metadata.addScanSetting("scan-range", firstScanNumber + ":" + lastScanNumber); metadata.addScanSetting("time-range", startTime + ":" + endTime); metadata.addScanSetting("mass-range", rawFile.RunHeaderEx.LowMass + ":" + rawFile.RunHeaderEx.HighMass); metadata.addInstrumentProperty("model", new CVTerm("MS:1000494", "MS", "Thermo Scientific instrument model", rawFile.GetInstrumentData().Model)); metadata.addInstrumentProperty("name", new CVTerm("MS:1000496", "MS", "instrument attribute", rawFile.GetInstrumentData().Name)); metadata.addInstrumentProperty("serial", new CVTerm("MS:1000529", "MS", "instrument serial number", rawFile.GetInstrumentData().SerialNumber)); var msTypes = new Dictionary <string, int>(); double minTime = 1000000000000000; double maxTime = 0; double minMz = 1000000000000000000; double maxMz = 0; double minCharge = 100000000000000; double maxCharge = 0; HashSet <CVTerm> fragmentationType = new HashSet <CVTerm>(CVTerm.CvTermComparer); for (var scanNumber = firstScanNumber; scanNumber <= lastScanNumber; scanNumber++) { var time = rawFile.RetentionTimeFromScanNumber(scanNumber); // Get the scan filter for this scan number var scanFilter = rawFile.GetFilterForScanNumber(scanNumber); // Get the scan event for this scan number var scanEvent = rawFile.GetScanEventForScanNumber(scanNumber); // Only consider MS2 spectra if (msTypes.ContainsKey(scanFilter.MSOrder.ToString())) { var value = msTypes[scanFilter.MSOrder.ToString()]; value = value + 1; msTypes[scanFilter.MSOrder.ToString()] = value; } else { msTypes.Add(scanFilter.MSOrder.ToString(), 1); } if (time > maxTime) { maxTime = time; } if (time < minTime) { minTime = time; } if (scanFilter.MSOrder == MSOrderType.Ms2) { fragmentationType.Add(parseActivationType(scanFilter.GetActivation(0))); if (scanEvent.ScanData == ScanDataType.Centroid || (scanEvent.ScanData == ScanDataType.Profile)) { try { var reaction = scanEvent.GetReaction(0); var precursorMass = reaction.PrecursorMass; if (precursorMass > maxMz) { maxMz = precursorMass; } if (precursorMass < minMz) { minMz = precursorMass; } } catch (ArgumentOutOfRangeException exception) { Log.Warn("No reaction found for scan " + scanNumber); } // trailer extra data list var trailerData = rawFile.GetTrailerExtraInformation(scanNumber); for (var i = 0; i < trailerData.Length; i++) { if (trailerData.Labels[i] == "Charge State:") { if (Int32.Parse(trailerData.Values[i]) > maxCharge) { maxCharge = Int32.Parse(trailerData.Values[i]); } if (Int32.Parse(trailerData.Values[i]) < minCharge) { maxCharge = Int32.Parse(trailerData.Values[i]); } } } } } } if (minCharge == 100000000000000) { minCharge = 0; } metadata.addMSData("ms-number", msTypes); metadata.addMSData("activation-ypes", fragmentationType); metadata.addMSData("min-charge", minCharge); metadata.addMSData("max-charge", maxCharge); metadata.addMSData("min-Time", minTime); metadata.addMSData("max-Time", maxTime); metadata.addMSData("min-Mz", minMz); metadata.addMSData("max-Mz", maxMz); // Write the meta data to file var json = JsonConvert.SerializeObject(metadata); json.Replace("\r\n", "\n"); File.WriteAllText(_outputDirectory + "/" + _rawFileNameWithoutExtension + "-metadata.json", json); }
/// <inheritdoc /> public override void Write(IRawDataPlus rawFile, int firstScanNumber, int lastScanNumber) { ConfigureWriter(".mgf"); using (Writer) { for (var scanNumber = firstScanNumber; scanNumber <= lastScanNumber; scanNumber++) { // Get each scan from the RAW file var scan = Scan.FromFile(rawFile, scanNumber); // Check to see if the RAW file contains label (high-res) data and if it is present // then look for any data that is out of order var time = rawFile.RetentionTimeFromScanNumber(scanNumber); // Get the scan filter for this scan number var scanFilter = rawFile.GetFilterForScanNumber(scanNumber); // Get the scan event for this scan number var scanEvent = rawFile.GetScanEventForScanNumber(scanNumber); switch (scanFilter.MSOrder) { case MSOrderType.Ms: // Keep track of scan number for precursor reference _precursorScanNumber = scanNumber; break; case MSOrderType.Ms2: { if (scanEvent.ScanData == ScanDataType.Centroid || (scanEvent.ScanData == ScanDataType.Profile && (scan.HasCentroidStream || ParseInput.OutputFormat != OutputFormat.MGFNoProfileData))) { Writer.WriteLine("BEGIN IONS"); Writer.WriteLine($"TITLE={ConstructSpectrumTitle(scanNumber)}"); Writer.WriteLine($"SCANS={scanNumber}"); Writer.WriteLine($"RTINSECONDS={(time * 60).ToString(CultureInfo.InvariantCulture)}"); // Get the reaction information for the first precursor try { var reaction = scanEvent.GetReaction(0); var precursorMass = reaction.PrecursorMass; Writer.WriteLine("PEPMASS=" + precursorMass.ToString("0.0000000", CultureInfo.InvariantCulture)); //var precursorIntensity = 0.0; //GetPrecursorIntensity(rawFile, _precursorScanNumber, precursorMass); //Writer.WriteLine(precursorIntensity != null // ? $"PEPMASS={precursorMass:F7} {precursorIntensity}" // : $"PEPMASS={precursorMass:F7}"); } catch (ArgumentOutOfRangeException exception) { Log.Warn("No reaction found for scan " + scanNumber); } // trailer extra data list var trailerData = rawFile.GetTrailerExtraInformation(scanNumber); for (var i = 0; i < trailerData.Length; i++) { if (trailerData.Labels[i] == "Charge State:") { if (Convert.ToInt32(trailerData.Values[i]) > 0) { Writer.WriteLine($"CHARGE={trailerData.Values[i]}+"); } } } // write the filter string //Writer.WriteLine($"SCANEVENT={scanEvent.ToString()}"); // Check if the scan has a centroid stream if (scan.HasCentroidStream) { var centroidStream = rawFile.GetCentroidStream(scanNumber, false); if (scan.CentroidScan.Length > 0) { for (var i = 0; i < centroidStream.Length; i++) { Writer.WriteLine( centroidStream.Masses[i].ToString("0.0000000", CultureInfo.InvariantCulture) + " " + centroidStream.Intensities[i].ToString("0.0000000", CultureInfo.InvariantCulture)); } } } // Otherwise take the profile data else { // Get the scan statistics from the RAW file for this scan number var scanStatistics = rawFile.GetScanStatsForScanNumber(scanNumber); // Get the segmented (low res and profile) scan data var segmentedScan = rawFile.GetSegmentedScanFromScanNumber(scanNumber, scanStatistics); for (var i = 0; i < segmentedScan.Positions.Length; i++) { Writer.WriteLine( segmentedScan.Positions[i].ToString("0.0000000", CultureInfo.InvariantCulture) + " " + segmentedScan.Intensities[i].ToString("0.0000000000", CultureInfo.InvariantCulture)); } } Writer.WriteLine("END IONS"); } break; } } } } }
/// <summary> /// Open the given file and import scans into the reader. /// </summary> /// <returns></returns> public System.Collections.IEnumerator GetEnumerator() { rawFile.SelectInstrument(ThermoBiz.Device.MS, 1); // Get the first and last scan from the RAW file int FirstScan = rawFile.RunHeaderEx.FirstSpectrum; int LastScan = rawFile.RunHeaderEx.LastSpectrum; for (int iScanNumber = FirstScan; iScanNumber <= LastScan; iScanNumber++) { ThermoBiz.Scan thermoScan = ThermoBiz.Scan.FromFile(rawFile, iScanNumber); IScanFilter scanFilter = rawFile.GetFilterForScanNumber(iScanNumber); IScanEvent scanEvent = rawFile.GetScanEventForScanNumber(iScanNumber); if ((int)scanFilter.MSOrder == 1) { LastMS1 = iScanNumber; } Data.Scan scan = new Data.Scan() { ScanNumber = iScanNumber, ScanEvent = (iScanNumber - LastMS1) + 1, BasePeakIntensity = thermoScan.ScanStatistics.BasePeakIntensity, BasePeakMz = thermoScan.ScanStatistics.BasePeakMass, TotalIonCurrent = thermoScan.ScanStatistics.TIC, LowestMz = thermoScan.ScanStatistics.LowMass, HighestMz = thermoScan.ScanStatistics.HighMass, StartMz = scanFilter.GetMassRange(0).Low, EndMz = scanFilter.GetMassRange(0).High, ScanType = ReadScanType(scanFilter.ToString()), MsOrder = (int)scanFilter.MSOrder, Polarity = (scanFilter.Polarity == PolarityType.Positive) ? Data.Polarity.Positive : Data.Polarity.Negative, FilterLine = scanFilter.ToString(), DetectorType = readDetectorType(scanFilter.MassAnalyzer), RetentionTime = rawFile.RetentionTimeFromScanNumber(iScanNumber) }; if (scan.MsOrder > 1) { // Get the current scan's activation method while ignoring upstream activation scan.PrecursorActivationMethod = ConvertActivationType(scanFilter.GetActivation(scan.MsOrder - 2)); // handle dependent scans and not SPS (processed below) scan.Precursors.Clear(); for (int i = 0; i < scanEvent.MassCount; ++i) { var reaction = scanEvent.GetReaction(i); scan.CollisionEnergy = reaction.CollisionEnergy; var precursor = new Data.Precursor { IsolationWidth = reaction.IsolationWidth, IsolationMz = reaction.PrecursorMass, Mz = reaction.PrecursorMass, OriginalMz = reaction.PrecursorMass }; scan.Precursors.Add(precursor); } } ThermoBiz.RunHeader runHeader = rawFile.RunHeader; ThermoBiz.LogEntry trailer = rawFile.GetTrailerExtraInformation(iScanNumber); for (int i = 0; i < trailer.Length; i++) { var value = trailer.Values[i]; if (value == null) { continue; } switch (trailer.Labels[i]) { case "Access ID": int access_id = Convert.ToInt32(value); if (access_id > 0) { scan.PrecursorMasterScanNumber = access_id; } break; case "Scan Description:": scan.Description = value.Trim(); break; case "Ion Injection Time (ms):": scan.IonInjectionTime = double.Parse(value); break; case "Elapsed Scan Time (sec):": scan.ElapsedScanTime = double.Parse(value); break; case "Charge State:": int charge = int.Parse(value); foreach (var precursor in scan.Precursors) { precursor.Charge = charge; precursor.OriginalCharge = precursor.Charge; } break; case "Master Scan Number:": scan.PrecursorMasterScanNumber = int.Parse(value); break; case "Master Index:": scan.MasterIndex = int.Parse(value); break; case "Monoisotopic M/Z:": if (Options.RawMonoMz && scan.Precursors.Count > 0) { double mz = double.Parse(value); if (mz > 0) { scan.Precursors[0].Mz = mz; } } break; case "FAIMS CV:": scan.FaimsCV = (int)double.Parse(value); break; case "FAIMS Voltage On:": scan.FaimsState = (value == "No") ? Data.TriState.Off : Data.TriState.On; break; case "SPS Masses:": string[] spsIonStringArray = value.TrimEnd(',').Split(','); if (!string.IsNullOrWhiteSpace(spsIonStringArray[0]) && spsIonStringArray.Length > 0) { scan.Precursors.Clear(); for (int spsIndex = 0; spsIndex < spsIonStringArray.Length; spsIndex++) { if (double.TryParse(spsIonStringArray[spsIndex], out double spsIon)) { scan.Precursors.Add(new Data.Precursor(spsIon, 0, 1)); } } } break; } } if (scan.PrecursorMasterScanNumber <= 0 && scan.MsOrder > 1) { // Try again to set the precursor scan. SetPrecursorScanNumber(scan); } if (scan.MsOrder > 1 && scan.PrecursorMasterScanNumber > rawFile.RunHeader.FirstSpectrum && scan.PrecursorMasterScanNumber < rawFile.RunHeader.LastSpectrum) { // Fill precursor information var parentScan = ThermoBiz.Scan.FromFile(rawFile, scan.PrecursorMasterScanNumber); if (parentScan != null) { foreach (var precursor in scan.Precursors) { precursor.Intensity = GetMaxIntensity(parentScan, precursor.IsolationMz, precursor.IsolationWidth); } } } if (thermoScan.HasCentroidStream) { // High res data CentroidsFromArrays(scan, thermoScan.CentroidScan.Masses, thermoScan.CentroidScan.Intensities, thermoScan.CentroidScan.Baselines, thermoScan.CentroidScan.Noises); } else { // Low res data CentroidsFromArrays(scan, thermoScan.PreferredMasses, thermoScan.PreferredIntensities); } if (scan.PeakCount > 0) { scan.LowestMz = scan.Centroids[0].Mz; scan.HighestMz = scan.Centroids[scan.PeakCount - 1].Mz; } yield return(scan); } }
/// <summary> /// Write the RAW files' spectra to a MGF file. /// </summary> /// <param name="rawFile">the RAW file interface</param> /// <param name="firstScanNumber">the first scan number</param> /// <param name="lastScanNumber">the last scan number</param> private void WriteSpectraToMgf(IRawDataPlus rawFile, int firstScanNumber, int lastScanNumber) { // Test centroid (high resolution/label) data using (var mgfFile = File.CreateText(outputDirectory + "//" + rawFileNameWithoutExtension + ".mgf")) { for (int scanNumber = firstScanNumber; scanNumber <= lastScanNumber; scanNumber++) { // Get each scan from the RAW file var scan = Scan.FromFile(rawFile, scanNumber); if (scan.HasCentroidStream) { // Check to see if the RAW file contains label (high-res) data and if it is present // then look for any data that is out of order double time = rawFile.RetentionTimeFromScanNumber(scanNumber); // Get the scan filter for this scan number var scanFilter = rawFile.GetFilterForScanNumber(scanNumber); // Get the scan event for this scan number var scanEvent = rawFile.GetScanEventForScanNumber(scanNumber); // Get the ionizationMode, MS2 precursor mass, collision energy, and isolation width for each scan if (scanFilter.MSOrder == ThermoFisher.CommonCore.Data.FilterEnums.MSOrderType.Ms2) { mgfFile.WriteLine("BEGIN IONS"); mgfFile.WriteLine($"TITLE={ConstructSpectrumTitle(scanNumber)}"); mgfFile.WriteLine($"SCAN={scanNumber}"); mgfFile.WriteLine($"RTINSECONDS={time * 60}"); // trailer extra data list var trailerData = rawFile.GetTrailerExtraInformation(scanNumber); for (int i = 0; i < trailerData.Length; i++) { if ((trailerData.Labels[i] == "Charge State:")) { if (Convert.ToInt32(trailerData.Values[i]) > 0) { mgfFile.WriteLine($"CHARGE={trailerData.Values[i]}+"); } } } // Get the reaction information for the first precursor var reaction = scanEvent.GetReaction(0); double precursorMass = reaction.PrecursorMass; mgfFile.WriteLine( $"PEPMASS={precursorMass:F4}"); //$"PEPMASS={precursorMass:F2} {GetPrecursorIntensity(rawFile, scanNumber)}"); double collisionEnergy = reaction.CollisionEnergy; mgfFile.WriteLine($"COLLISIONENERGY={collisionEnergy}"); var ionizationMode = scanFilter.IonizationMode; mgfFile.WriteLine($"IONMODE={ionizationMode}"); var centroidStream = rawFile.GetCentroidStream(scanNumber, false); if (scan.CentroidScan.Length > 0) { for (int i = 0; i < centroidStream.Length; i++) { mgfFile.WriteLine( $"{centroidStream.Masses[i]:F7} {centroidStream.Intensities[i]:F10}"); } } mgfFile.WriteLine("END IONS"); } } } } }
/// <inheritdoc /> public override void Write(int firstScanNumber, int lastScanNumber) { ConfigureWriter(".mgf"); using (Writer) { //Log.Info("Processing " + (lastScanNumber - firstScanNumber + 1) + " scans"); var lastScanProgress = 0; for (var scanNumber = firstScanNumber; scanNumber <= lastScanNumber; scanNumber++) { if (ParseInput.LogFormat == LogFormat.DEFAULT) { var scanProgress = (int)((double)scanNumber / (lastScanNumber - firstScanNumber + 1) * 100); if (scanProgress % ProgressPercentageStep == 0) { if (scanProgress != lastScanProgress) { Console.Write("" + scanProgress + "% "); lastScanProgress = scanProgress; } } } // Get each scan from the RAW file var scan = Scan.FromFile(_rawFile, scanNumber); // Check to see if the RAW file contains label (high-res) data and if it is present // then look for any data that is out of order var time = _rawFile.RetentionTimeFromScanNumber(scanNumber); // Get the scan filter for this scan number var scanFilter = _rawFile.GetFilterForScanNumber(scanNumber); // Get the scan event for this scan number var scanEvent = _rawFile.GetScanEventForScanNumber(scanNumber); // don't include MS1 spectra if (scanFilter.MSOrder != MSOrderType.Ms) { IReaction reaction = GetReaction(scanEvent, scanNumber); Writer.WriteLine("BEGIN IONS"); Writer.WriteLine($"TITLE={ConstructSpectrumTitle(scanNumber)}"); Writer.WriteLine($"SCANS={scanNumber}"); Writer.WriteLine( $"RTINSECONDS={(time * 60).ToString(CultureInfo.InvariantCulture)}"); // trailer extra data list var trailerData = _rawFile.GetTrailerExtraInformation(scanNumber); int? charge = null; double?monoisotopicMz = null; double?isolationWidth = null; for (var i = 0; i < trailerData.Length; i++) { if (trailerData.Labels[i] == "Charge State:") { if (Convert.ToInt32(trailerData.Values[i]) > 0) { charge = Convert.ToInt32(trailerData.Values[i]); } } if (trailerData.Labels[i] == "Monoisotopic M/Z:") { monoisotopicMz = double.Parse(trailerData.Values[i], NumberStyles.Any, CultureInfo.CurrentCulture); } if (trailerData.Labels[i] == "MS" + (int)scanFilter.MSOrder + " Isolation Width:") { isolationWidth = double.Parse(trailerData.Values[i], NumberStyles.Any, CultureInfo.CurrentCulture); } } if (reaction != null) { var selectedIonMz = CalculateSelectedIonMz(reaction, monoisotopicMz, isolationWidth); Writer.WriteLine("PEPMASS=" + selectedIonMz.ToString(CultureInfo.InvariantCulture)); } // charge if (charge != null) { // Scan polarity var polarity = PositivePolarity; if (scanFilter.Polarity == PolarityType.Negative) { polarity = NegativePolarity; } Writer.WriteLine($"CHARGE={charge}{polarity}"); } // write the filter string //Writer.WriteLine($"SCANEVENT={scanEvent.ToString()}"); if (!ParseInput.NoPeakPicking) { // check if the scan has a centroid stream if (scan.HasCentroidStream) { if (scan.CentroidScan.Length > 0) { for (var i = 0; i < scan.CentroidScan.Length; i++) { Writer.WriteLine( scan.CentroidScan.Masses[i].ToString("0.0000000", CultureInfo.InvariantCulture) + " " + scan.CentroidScan.Intensities[i].ToString("0.0000000000", CultureInfo.InvariantCulture)); } } } else // otherwise take segmented (low res) scan data { // if the spectrum is profile perform centroiding var segmentedScan = scanEvent.ScanData == ScanDataType.Profile ? Scan.ToCentroid(scan).SegmentedScan : scan.SegmentedScan; for (var i = 0; i < segmentedScan.Positions.Length; i++) { Writer.WriteLine( segmentedScan.Positions[i].ToString("0.0000000", CultureInfo.InvariantCulture) + " " + segmentedScan.Intensities[i].ToString("0.0000000000", CultureInfo.InvariantCulture)); } } } else // use the segmented data as is { for (var i = 0; i < scan.SegmentedScan.Positions.Length; i++) { Writer.WriteLine( scan.SegmentedScan.Positions[i].ToString("0.0000000", CultureInfo.InvariantCulture) + " " + scan.SegmentedScan.Intensities[i].ToString("0.0000000000", CultureInfo.InvariantCulture)); } } Writer.WriteLine("END IONS"); //Log.Debug("Spectrum written to file -- SCAN " + scanNumber); } } if (ParseInput.LogFormat == LogFormat.DEFAULT) { Console.WriteLine(); } } }
/// <summary> /// </summary> /// <param name="rawFile"></param> /// <param name="filename"></param> /// <param name="L"></param> public static void WriteSpectrumAsRcode(this IRawDataPlus rawFile, string filename, List <int> L) { int count = 1; var trailerFields = rawFile.GetTrailerExtraHeaderInformation(); int indexCharge = rawFile.GetIndexOfPattern("Charge State"); int indexMonoisotopicmZ = rawFile.GetIndexOfPattern("MonoisotopicmZ"); using (System.IO.StreamWriter file = new System.IO.StreamWriter(filename)) { foreach (int scanNumber in L) { var basepeakMass = -1.0; var basepeakIntensity = -1.0; var scanStatistics = rawFile.GetScanStatsForScanNumber(scanNumber); var centroidStream = rawFile.GetCentroidStream(scanNumber, false); var scanTrailer = rawFile.GetTrailerExtraInformation(scanNumber); var scanEvent = rawFile.GetScanEventForScanNumber(scanNumber); var scan = Scan.FromFile(rawFile, scanNumber); file.WriteLine("e$Spectrum[[{0}]] <- list(", count++); file.WriteLine("\tscan = {0},", scanNumber); try { basepeakMass = (scanStatistics.BasePeakMass); basepeakIntensity = Math.Round(scanStatistics.BasePeakIntensity); file.WriteLine("\tbasePeak = c({0}, {1}),", basepeakMass, basepeakIntensity); } catch { file.WriteLine("\tbasePeak = c(NA, NA),"); } file.WriteLine("\tTIC = {0},", scanStatistics.TIC.ToString()); file.WriteLine("\tmassRange = c({0}, {1}),", scanStatistics.LowMass.ToString(), scanStatistics.HighMass.ToString()); file.WriteLine("\tscanType = \"{0}\",", scanStatistics.ScanType.ToString()); file.WriteLine("\trtinseconds = {0},", Math.Round(scanStatistics.StartTime * 60 * 1000) / 1000); try { var reaction0 = scanEvent.GetReaction(0); file.WriteLine("\tpepmass = {0},", reaction0.PrecursorMass); } catch { file.WriteLine("\tpepmass = NA,"); } if (scanStatistics.IsCentroidScan && centroidStream.Length > 0) { // Get the centroid (label) data from the RAW file for this scan file.WriteLine("\tcentroidStream = TRUE,"); file.WriteLine("\tHasCentroidStream = '{0}, Length={1}',", scan.HasCentroidStream, scan.CentroidScan.Length); if (scan.HasCentroidStream) { file.WriteLine("\tcentroid.mZ = c(" + string.Join(", ", scan.CentroidScan.Masses.ToArray()) + "),"); file.WriteLine("\tcentroid.intensity = c(" + string.Join(", ", scan.CentroidScan.Intensities.ToArray()) + "),"); } file.WriteLine("\ttitle = \"File: {0}; SpectrumID: {1}; scans: {2}\",", Path.GetFileName(rawFile.FileName), null, scanNumber); if (indexMonoisotopicmZ > 0) { file.WriteLine("\tmonoisotopicMz = {0},", Convert.ToDouble(scanTrailer.Values.ToArray()[indexMonoisotopicmZ])); } else { file.WriteLine("\tmonoisotopicMz = NA,"); } if (indexCharge > 0) { file.WriteLine("\tcharge = {0},", int.Parse(scanTrailer.Values.ToArray()[indexCharge])); } else { file.WriteLine("\tcharge = NA,"); } file.WriteLine("\tmZ = c(" + string.Join(", ", centroidStream.Masses) + "),"); file.WriteLine("\tintensity = c(" + string.Join(", ", centroidStream.Intensities) + "),"); file.WriteLine("\tnoises = c(" + string.Join(", ", centroidStream.Noises) + "),"); file.WriteLine("\tresolutions = c(" + string.Join(", ", centroidStream.Resolutions.ToArray()) + "),"); file.WriteLine("\tcharges = c(" + string.Join(", ", centroidStream.Charges) + "),"); file.WriteLine("\tbaselines = c(" + string.Join(", ", centroidStream.Baselines) + "),"); } else { file.WriteLine("\tcentroidStream = FALSE,"); file.WriteLine("\tHasCentroidStream = '{0}, Length={1}',", scan.HasCentroidStream, scan.CentroidScan.Length); if (scan.HasCentroidStream) { file.WriteLine("\tcentroid.mZ = c(" + string.Join(",", scan.CentroidScan.Masses.ToArray()) + "),"); file.WriteLine("\tcentroid.intensity = c(" + string.Join(",", scan.CentroidScan.Intensities.ToArray()) + "),"); } file.WriteLine("\ttitle = \"File: {0}; SpectrumID: {1}; scans: {2}\",", Path.GetFileName(rawFile.FileName), null, scanNumber); if (indexCharge > 0) { file.WriteLine("\tcharge = {0},", int.Parse(scanTrailer.Values.ToArray()[indexCharge])); } else { file.WriteLine("\tcharge = NA,"); } if (indexMonoisotopicmZ > 0) { file.WriteLine("\tmonoisotopicMz = {0},", Convert.ToDouble(scanTrailer.Values.ToArray()[indexMonoisotopicmZ])); } else { file.WriteLine("\tmonoisotopicMz = NA,"); } file.WriteLine("\tmZ = c(" + string.Join(",", scan.SegmentedScan.Positions) + "),"); file.WriteLine("\tintensity = c(" + string.Join(",", scan.SegmentedScan.Intensities) + "),"); // file.WriteLine("\tnoises = c(" + string.Join(",", scan.SegmentedScan.Noises) + "),"); } // ============= Instrument Data ============= // write scan Trailer var trailerValues = scanTrailer.Values; var trailerLabels = scanTrailer.Labels; var zipTrailer = trailerLabels.ToArray().Zip(trailerValues, (a, b) => string.Format("\t\"{0}\" = \"{1}\"", a, b)); file.WriteLine(string.Join(", \n", zipTrailer)); file.WriteLine(")"); } } return; }