public IonFrequencyTable(IEnumerable<IonType> ionTypes, Tolerance tolerance, double relativeIntensityThreshold, bool combineCharges=false) { _ionFrequencies = new Dictionary<IonType, Probability<IonType>>(); _combineCharges = combineCharges; _ionTypes = ionTypes.ToArray(); _tolerance = tolerance; _relativeIntensityThreshold = relativeIntensityThreshold; var charges = _ionTypes.Select(ionType => ionType.Charge).ToList(); _ionTypeFactory = new IonTypeFactory(charges.Max()); }
// private const string DebugFileName = @"C:\Users\wilk011\Documents\DataFiles\TestFolder\debug_HCD_QCShew_Precursor.txt"; private IEnumerable<SpectrumMatch> InitTest() { var ionTypeFactory = new IonTypeFactory(_baseIons, _neutralLosses, MaxCharge); _ionTypes = ionTypeFactory.GetAllKnownIonTypes().ToList(); var lcms = new LazyLcMsRun(RawFile, NoiseFiltration, NoiseFiltration); var spectrumMatches = (new SpectrumMatchList(lcms, TsvFile, DataFileFormat.IcBottomUp)); return spectrumMatches; }
public PrecursorFilter(PrecursorOffsets offsets, Tolerance tolerance) { _offsets = offsets; _tolerance = tolerance; var maxCharge = offsets.Charge; BaseIonType[] baseIons = { BaseIonType.Y }; NeutralLoss[] neutralLosses = { NeutralLoss.NoLoss }; var ionTypeFactory = new IonTypeFactory(baseIons, neutralLosses, maxCharge); _precursorIonTypes = ionTypeFactory.GetAllKnownIonTypes().ToList(); }
public PrecursorOffsetFrequencyTable(double searchWidth, int charge = 1, double binWidth = 1.005) { _offsetCounts = new Histogram<double>(); _searchWidth = searchWidth; _binWidth = binWidth; Charge = charge; Total = 0; GenerateEdges(); BaseIonType[] baseIons = { BaseIonType.Y }; NeutralLoss[] neutralLosses = { NeutralLoss.NoLoss }; var ionTypeFactory = new IonTypeFactory(baseIons, neutralLosses, charge); _precursorIonTypes = ionTypeFactory.GetAllKnownIonTypes().ToList(); }
// Read Configuration file private void InitTest(ConfigFileReader reader) { // Read program variables var config = reader.GetNodes("vars").First(); _precursorCharge = Convert.ToInt32(config.Contents["precursorcharge"]); var actStr = config.Contents["activationmethod"].ToLower(); _combineCharges = (config.Contents.ContainsKey("combinecharges") && config.Contents["combinecharges"].ToLower() == "true"); _useDecoy = (config.Contents.ContainsKey("usedecoy") && config.Contents["usedecoy"].ToLower() == "true"); _relativeIntensityThreshold = Convert.ToDouble(config.Contents["relativeintensitythreshold"]); // Read ion data var ionInfo = reader.GetNodes("ion").First(); int totalCharges = Convert.ToInt32(ionInfo.Contents["totalcharges"]); var ionTypeStr = ionInfo.Contents["iontype"].Split(','); var ions = new BaseIonType[ionTypeStr.Length]; for (int i = 0; i < ionTypeStr.Length; i++) { switch (ionTypeStr[i].ToLower()) { case "a": ions[i] = BaseIonType.A; break; case "b": ions[i] = BaseIonType.B; break; case "c": ions[i] = BaseIonType.C; break; case "x": ions[i] = BaseIonType.X; break; case "y": ions[i] = BaseIonType.Y; break; case "z": ions[i] = BaseIonType.Z; break; } } var ionLossStr = ionInfo.Contents["losses"].Split(','); var ionLosses = new NeutralLoss[ionLossStr.Length]; for (int i = 0; i < ionLossStr.Length; i++) { switch (ionLossStr[i].ToLower()) { case "noloss": ionLosses[i] = NeutralLoss.NoLoss; break; case "nh3": ionLosses[i] = NeutralLoss.NH3; break; case "h2o": ionLosses[i] = NeutralLoss.H2O; break; } } _ionTypeFactory = new IonTypeFactory(ions, ionLosses, totalCharges); _ionTypes = _ionTypeFactory.GetAllKnownIonTypes().ToList(); var tempIonList = new List<IonType>(); if (ionInfo.Contents.ContainsKey("exclusions")) { var ionExclusions = ionInfo.Contents["exclusions"].Split(','); tempIonList.AddRange(_ionTypes.Where(ionType => !ionExclusions.Contains(ionType.Name))); _ionTypes = tempIonList; } // Read input and output file names var fileInfo = reader.GetNodes("fileinfo").First(); _names = fileInfo.Contents["name"].Split(','); _preTsv = fileInfo.Contents["tsvpath"]; _preRaw = fileInfo.Contents["rawpath"]; var outPathtemp = fileInfo.Contents["outpath"]; _outPre = outPathtemp; var outFiletemp = fileInfo.Contents["outfile"]; _outFileName = _outPre + outFiletemp; }
/// <summary> /// Get a <see cref="IonTypeFactory"/> for the deconvoluted versions of <paramref name="baseIons"/> and <paramref name="neutralLosses"/> /// </summary> /// <param name="baseIons"></param> /// <param name="neutralLosses"></param> /// <returns></returns> public static IonTypeFactory GetDeconvolutedIonTypeFactory(IEnumerable <BaseIonType> baseIons, IEnumerable <NeutralLoss> neutralLosses) { var ionTypeFactory = new IonTypeFactory(baseIons.Select(ion => ion.GetDeconvolutedIon()), neutralLosses, 1); return(ionTypeFactory); }
public void TestFitScoreCalculationEtd() { var methodName = MethodBase.GetCurrentMethod().Name; TestUtils.ShowStarting(methodName); if (!File.Exists(TestLcMsRun.TestTopDownRawFilePathEtd)) { Assert.Ignore(@"Skipping test " + methodName + @" since file not found: " + TestLcMsRun.TestTopDownRawFilePathCid); } var run = InMemoryLcMsRun.GetLcMsRunScanRange(TestLcMsRun.TestTopDownRawFilePathEtd, 810, 810); var spec = run.GetSpectrum(810) as ProductSpectrum; Assert.True(spec != null); const string suf54 = "ENIKTLPAKRNEQDQKQLIVPLADSLKPGTYTVDWHVVSVDGHKTKGHYTFSVK"; var suf54Comp = new AminoAcidSet().GetComposition(suf54); Assert.True(suf54Comp != null); var ionType = new IonTypeFactory(10).GetIonType("z6"); var ion = ionType.GetIon(suf54Comp); //ion.Composition.ComputeApproximateIsotopomerEnvelop(); Console.WriteLine("MonoMz: {0}, MonoMass: {1}", ion.GetMonoIsotopicMz(), ion.Composition.Mass); var fitScore = spec.GetFitScore(ion, new Tolerance(15), 0.1); Console.WriteLine("FitScore: {0}", fitScore); Assert.True(fitScore < 0.15); }
public void ReadConfigurationFile(string configurationFile) { var reader = new ConfigFileReader(configurationFile); // Read program variables var config = reader.GetNodes("vars").First(); PrecursorCharge = Convert.ToInt32(config.Contents["precursorcharge"]); PrecursorOffsetThreshold = Convert.ToDouble(config.Contents["precursoroffsetthreshold"]); WindowWidth = Convert.ToInt32(config.Contents["searchwidth"]); PrecursorOffsetWidth = Convert.ToInt32(config.Contents["precursoroffsetwidth"]); RetentionCount = Convert.ToInt32(config.Contents["retentioncount"]); RelativeIntensityThreshold = Convert.ToDouble(config.Contents["relativeintensitythreshold"]); SelectedIonThreshold = Convert.ToDouble(config.Contents["selectedionthreshold"]); MassBinSize = Convert.ToInt32(config.Contents["massbinsize"]); var actStr = config.Contents["activationmethod"].ToLower(); switch (actStr) { case "hcd": ActivationMethod = ActivationMethod.HCD; Tolerance = _defaultTolerancePpm; break; case "cid": ActivationMethod = ActivationMethod.CID; Tolerance = _defaultToleranceTh; break; case "etd": ActivationMethod = ActivationMethod.ETD; Tolerance = _defaultTolerancePpm; break; default: throw new FormatException("Invalid Activation Method."); } var acqStr = config.Contents["acquisitionmethod"].ToLower(); switch (acqStr) { case "dia": AcquisitionMethod = AcquisitionMethod.Dia; break; case "dda": AcquisitionMethod = AcquisitionMethod.Dda; break; default: throw new FormatException("Invalid Acquisition Method."); } MassErrorTolerance = _defaultToleranceTh; MaxRanks = Convert.ToInt32(config.Contents["maxranks"]); var smoothingRanksStr = config.Contents["smoothingranks"].Split(','); SmoothingRanks = new int[smoothingRanksStr.Length]; var smoothingWindowSizeStr = config.Contents["smoothingwindowsize"].Split(','); SmoothingWindowSize = new int[smoothingWindowSizeStr.Length]; if (SmoothingRanks.Length != SmoothingWindowSize.Length) throw new ArgumentException("SmoothingRanks and SmoothingWindowSize unequal lengths."); for (int i = 0; i < SmoothingRanks.Length; i++) { if (smoothingRanksStr[i] == "Max") SmoothingRanks[i] = Int32.MaxValue; else SmoothingRanks[i] = Convert.ToInt32(smoothingRanksStr[i]); SmoothingWindowSize[i] = Convert.ToInt32(smoothingWindowSizeStr[i]); } // Read ion data var ionInfo = reader.GetNodes("ion").First(); int totalCharges = Convert.ToInt32(ionInfo.Contents["totalcharges"]); var ionTypeStr = ionInfo.Contents["iontype"].Split(','); var ions = new BaseIonType[ionTypeStr.Length]; for (int i = 0; i < ionTypeStr.Length; i++) { switch (ionTypeStr[i].ToLower()) { case "a": ions[i] = BaseIonType.A; break; case "b": ions[i] = BaseIonType.B; break; case "c": ions[i] = BaseIonType.C; break; case "x": ions[i] = BaseIonType.X; break; case "y": ions[i] = BaseIonType.Y; break; case "z": ions[i] = BaseIonType.Z; break; } } var ionLossStr = ionInfo.Contents["losses"].Split(','); var ionLosses = new NeutralLoss[ionLossStr.Length]; for (int i = 0; i < ionLossStr.Length; i++) { switch (ionLossStr[i].ToLower()) { case "noloss": ionLosses[i] = NeutralLoss.NoLoss; break; case "nh3": ionLosses[i] = NeutralLoss.NH3; break; case "h2o": ionLosses[i] = NeutralLoss.H2O; break; } } _ionTypeFactory = new IonTypeFactory(ions, ionLosses, totalCharges); IonTypes = _ionTypeFactory.GetAllKnownIonTypes().ToArray(); var tempIonList = new List<IonType>(); if (ionInfo.Contents.ContainsKey("exclusions")) { var ionExclusions = ionInfo.Contents["exclusions"].Split(','); tempIonList.AddRange(IonTypes.Where(ionType => !ionExclusions.Contains(ionType.Name))); IonTypes = tempIonList.ToArray(); } // Read input and output file names var fileInfo = reader.GetNodes("fileinfo").First(); DataSets = fileInfo.Contents["name"].Split(','); var dataFormat = fileInfo.Contents["format"]; switch (dataFormat) { case "mgf": DataFormat = DataFileFormat.Mgf; break; case "icbottomup": DataFormat = DataFileFormat.IcBottomUp; break; case "dia": DataFormat = DataFileFormat.Dia; break; default: throw new FormatException("Invalid Acquisition Method."); } TsvPath = fileInfo.Contents["tsvpath"]; DataPath = fileInfo.Contents["datapath"]; var outPathtemp = fileInfo.Contents["outpath"]; OutputPath = outPathtemp; OutputFileName = OutputPath + fileInfo.Contents["outputfile"]; }
private void ReadFromFile(StreamReader file, IonTypeFactory ionTypeFactory) { var line = file.ReadLine(); while (line != null) { var parts = line.Split('\t').ToList(); var header = parts[0]; parts.RemoveAt(0); if (header == "MaxRanks") MaxRanks = Convert.ToInt32(parts[0]); else if (header == "Total") { if (MaxRanks < 0) throw new FormatException("Badly formatted rank data."); _rankTotals = new double[MaxRanks+1]; for (int i = 0; i < MaxRanks+1; i++) { _rankTotals[i] = Convert.ToInt32(parts[i]); } // reached end of rank table entry break; } else if (header == "Unexplained") {} else { if (MaxRanks < 0) throw new FormatException("Badly formatted rank data."); try { var ionType = ionTypeFactory.GetIonType(header); _rankTable.Add(ionType, new double[MaxRanks+1]); for (int i = 0; i < MaxRanks+1; i++) { _rankTable[ionType][i] = Convert.ToDouble(parts[i]); } } catch (KeyNotFoundException) { throw new FormatException("Invalid ion type: " + header); } } line = file.ReadLine(); } }
/// <summary> /// RankTable constructor for creating RankTable from taining parameter file. /// </summary> /// <param name="file">Training data file past position of RankProbabilities label.</param> /// <param name="ionTypeFactory">IonTypeFactory object with all known possible ions in training /// parameter file.</param> public RankTable(StreamReader file, IonTypeFactory ionTypeFactory) { MaxRanks = -1; _rankTable = new Dictionary<IonType, double[]>(); ReadFromFile(file, ionTypeFactory); }
private void ReadFromFile(string paramFile, Boolean verbose) { if (!File.Exists(paramFile)) return; var allIonTypes = new IonTypeFactory(); using (var reader = new JavaBinaryReader(File.Open(paramFile, FileMode.Open))) { // Version var version = reader.ReadInt32(); if(verbose) Console.WriteLine("Version: {0}", version); // Activation method var actMethod = new string(reader.ReadChars(reader.ReadByte())); // Instrument type var instType = new string(reader.ReadChars(reader.ReadByte())); // Enzyme var enzyme = new string(reader.ReadChars(reader.ReadByte())); // Protocol var len = reader.ReadByte(); var protocol = new string(reader.ReadChars(len)); if (verbose) Console.WriteLine("Spectral type: {0}_{1}_{2}{3}", actMethod, instType, enzyme, protocol.Length > 0 ? "_"+protocol : ""); // TODO: set up spectral type // Tolerance var isTolerancePpm = reader.ReadBoolean(); var mmeVal = reader.ReadSingle(); // Ignore mme //_mme = new Tolerance(mmeVal, isTolerancePpm ? ToleranceUnit.Ppm : ToleranceUnit.Da); // Deconvolution information _applyDeconvolution = reader.ReadBoolean(); _deconvolutionErrorToleranceDa = reader.ReadSingle(); if (verbose) Console.WriteLine("Apply deconvolution: {0}, Tolerance: {1}", _applyDeconvolution, _deconvolutionErrorToleranceDa); // Charge histogram if (verbose) Console.WriteLine("Charge Histogram"); var chargeHistSize = reader.ReadInt32(); _chargeHistogram = new Dictionary<int, int>(); for (var i = 0; i < chargeHistSize; i++) { var charge = reader.ReadInt32(); var numSpecs = reader.ReadInt32(); _chargeHistogram[charge] = numSpecs; if (verbose) Console.WriteLine(charge + "\t" + numSpecs); } // Partition information var numPartitions = reader.ReadInt32(); if (verbose) Console.WriteLine("Partition Information\t" + numPartitions); _numSegments = reader.ReadInt32(); _partitionSet = new SortedSet<Partition>(); for (var i = 0; i < numPartitions; i++) { var charge = reader.ReadInt32(); var neutralPeptideMass = reader.ReadSingle(); var segIndex = reader.ReadInt32(); _partitionSet.Add(new Partition(charge, neutralPeptideMass, segIndex)); if (verbose) Console.WriteLine("{0}\t{1}\t{2}", charge, neutralPeptideMass, segIndex); } // Precursor offset frequency function if (verbose) Console.WriteLine("Precursor Offset Frequency Function"); _precursorOffMap = new Dictionary<int, IList<PrecursorOffsetFrequency>>(); _numPrecursorOffsets = reader.ReadInt32(); for (var i = 0; i < _numPrecursorOffsets; i++) { var charge = reader.ReadInt32(); var reducedCharge = reader.ReadInt32(); var offset = reader.ReadSingle(); var isTolPpm = reader.ReadBoolean(); var tolVal = reader.ReadSingle(); var tolerance = new Tolerance(tolVal, isTolPpm ? ToleranceUnit.Ppm : ToleranceUnit.Da); var frequency = reader.ReadSingle(); IList<PrecursorOffsetFrequency> offList; if (!_precursorOffMap.TryGetValue(charge, out offList)) { offList = new List<PrecursorOffsetFrequency>(); _precursorOffMap[charge] = offList; } offList.Add(new PrecursorOffsetFrequency(reducedCharge, offset, frequency, tolerance)); if (verbose) Console.WriteLine("{0}\t{1}\t{2}\t{3}\t{4}", charge, reducedCharge, offset, tolerance, frequency); } // Fragment ion offset frequency function if (verbose) Console.WriteLine("Fragment Offset Frequency Function"); _fragmentOffMap = new Dictionary<Partition, IEnumerable<FragmentOffsetFrequency>>(); foreach (var partition in _partitionSet) { var numIons = reader.ReadInt32(); if (verbose) Console.WriteLine("Partition {0}\t{1}\t{2}\t{3}", partition.Charge, partition.SegmentIndex, partition.NeutralPeptideMass, numIons); var fragmentOff = new FragmentOffsetFrequency[numIons]; for (var ionIndex = 0; ionIndex < numIons; ionIndex++) { var isPrefix = reader.ReadBoolean(); var charge = reader.ReadInt32(); var offset = reader.ReadSingle(); var frequency = reader.ReadSingle(); fragmentOff[ionIndex] = new FragmentOffsetFrequency(allIonTypes.GetIonType(isPrefix, charge, offset), frequency); if(verbose) Console.WriteLine("{0}_{1}_{2}\t{3}\t{4}", isPrefix ? "P" : "S", charge, Math.Round(offset), frequency, offset); } _fragmentOffMap.Add(partition, fragmentOff); } //// TODO: determine fragment ions to be used for scoring //// Rank distributions //var maxRank = reader.ReadInt32(); //_rankDistTable = new Dictionary<Partition, Dictionary<IonType, float[]>>(); //for (var i = 0; i < numPartitions; i++) //{ // // repeat this for #Ions // for (var rank = 0; rank < maxRank + 1; rank++) // { // var frequency = reader.ReadSingle(); // } //} //// Error distributions //var errorScalingFactor = reader.ReadInt32(); //if (errorScalingFactor > 0) //{ // var numErrorBins = errorScalingFactor*2 + 1; // // Ion error distribution // for (var i = 0; i < numErrorBins; i++) // { // var ionErrorDist = reader.ReadSingle(); // } // // Noise error distribution // for (var i = 0; i < numErrorBins; i++) // { // var noiseErrorDist = reader.ReadSingle(); // } // // Ion existence table // for (var i = 0; i < 4; i++) // { // var ionExFreq = reader.ReadSingle(); // } //} //// Validation //var validationCode = reader.ReadInt32(); //if (validationCode != Int32.MaxValue) //{ // Console.WriteLine("Error while reading parameter file {0}", paramFile); // System.Environment.Exit(-1); // Error //} } }
public static IonTypeFactory GetDeconvolutedIonTypeFactory(IEnumerable<BaseIonType> baseIons, IEnumerable<NeutralLoss> neutralLosses) { var ionTypeFactory = new IonTypeFactory(baseIons.Select(ion => ion.GetDeconvolutedIon()), neutralLosses, 1); return ionTypeFactory; }
private void Read(StreamReader file) { var ionTypeFactory = new IonTypeFactory(2); var massBins = new List<double>(); var binEdges = new List<double>(); var charge = 0; var line = file.ReadLine(); while (line != null) { var parts = line.Split('\t').ToList(); var header = parts[0]; parts.RemoveAt(0); if (header == "BinSize") massBins.AddRange(parts.Select(Convert.ToDouble)); else if (header == "BinEdges") { binEdges.Add(Convert.ToDouble(parts[0])); } else if (header == "Charge") { if (binEdges.Count > 0) { _massSorter[charge].BinEdges = binEdges.ToArray(); binEdges.Clear(); } charge = Convert.ToInt32(parts[0]); if (!_charges.Contains(charge)) { _charges.Add(charge); _massSorter.Add(charge, new Histogram<double>()); _rankTables.Add(charge, new List<RankTable>()); _drankTables.Add(charge, new List<RankTable>()); _ionProbabilities.Add(charge, new List<IonFrequencyTable>()); _massErrors.Add(charge, new List<MassErrorTable>()); } } else if (header == "RankProbabilities") { if (massBins.Count == 0 || charge == 0) throw new FormatException("Badly formatted training file."); _rankTables[charge].Add(new RankTable(file, ionTypeFactory)); _drankTables[charge].Add(new RankTable(file, ionTypeFactory)); } line = file.ReadLine(); } _massSorter[charge].BinEdges = binEdges.ToArray(); }
public void TestPpmErrorCalculation(string seqText, string rawFilePath, int scanNum) { var methodName = MethodBase.GetCurrentMethod().Name; ShowStarting(methodName, rawFilePath); var tolerance = new Tolerance(10, ToleranceUnit.Ppm); const int maxCharge = 15; const double relIntThres = 0.1; if (!File.Exists(rawFilePath)) { Assert.Ignore(@"Skipping test {0} since file not found: {1}", methodName, rawFilePath); } // init var sequence = Sequence.GetSequenceFromMsGfPlusPeptideStr(seqText); var lcms = PbfLcMsRun.GetLcMsRun(rawFilePath); var spectrum = lcms.GetSpectrum(scanNum); var ionTypeFactory = new IonTypeFactory(maxCharge); var iontypes = ionTypeFactory.GetAllKnownIonTypes(); foreach (var iontype in iontypes) { var ion = iontype.GetIon(sequence.Composition); var obsPeaks = spectrum.GetAllIsotopePeaks(ion, tolerance, relIntThres); if (obsPeaks == null) continue; var isotopes = ion.GetIsotopes(relIntThres).ToArray(); for (int i = 0; i < isotopes.Length; i++) { if (obsPeaks[i] == null) continue; var obsMz = obsPeaks[i].Mz; var theoMz = ion.GetIsotopeMz(isotopes[i].Index); var ppmError = (obsMz - theoMz)/theoMz*1e6; Assert.True(ppmError <= tolerance.GetValue()); } } }
public void TestIonTypeFactory() { var methodName = MethodBase.GetCurrentMethod().Name; ShowStarting(methodName); const string sequenceStr = "PEPTIDE"; var aminoAcidSet = new AminoAcidSet(); var sequence = new Sequence(sequenceStr, aminoAcidSet); var compositionOfFirstPrefix = sequence.GetComposition(0, 2); Console.WriteLine("{0}\t{1}", compositionOfFirstPrefix, compositionOfFirstPrefix.Mass); var ionTypeFactory = new IonTypeFactory(new[] { BaseIonType.B, BaseIonType.Y }, new[] { NeutralLoss.NoLoss }, 10); var bIon = ionTypeFactory.GetIonType("b"); var yIon = ionTypeFactory.GetIonType("y2"); Console.WriteLine("{0}\t{1}\t{2}", bIon, bIon.OffsetComposition, bIon.OffsetComposition.Mass); Console.WriteLine("{0}\t{1}\t{2}", yIon, yIon.OffsetComposition, yIon.OffsetComposition.Mass); // Compute mass of y2 = AveragineMass(DE) + OffsetY var compositionOfSecondSuffix = sequence.GetComposition(sequenceStr.Length - 2, sequenceStr.Length); var y2Ion = yIon.GetIon(compositionOfSecondSuffix); Console.WriteLine("m/z of y++: {0}", y2Ion.GetMonoIsotopicMz()); }
public void TestIonTypeGeneration() { var methodName = MethodBase.GetCurrentMethod().Name; ShowStarting(methodName); var ionTypeFactory = new IonTypeFactory(); int index = 0; foreach (var ionType in ionTypeFactory.GetAllKnownIonTypes()) { Console.WriteLine(++index + ": " + ionType); } var yIon = ionTypeFactory.GetIonType("y2-H2O"); Console.WriteLine(yIon.GetMz(0)); }
public void TestGetProductIons() { var methodName = MethodBase.GetCurrentMethod().Name; ShowStarting(methodName); var aaSet = new AminoAcidSet(Modification.Carbamidomethylation); var sequence = new Sequence("CCAADDKEACFAVEGPK", aaSet); var ionTypeFactory = new IonTypeFactory( new[] {BaseIonType.B, BaseIonType.Y}, new[] {NeutralLoss.NoLoss, NeutralLoss.H2O}, maxCharge: 2); Console.WriteLine("Precursor Ion: {0}\t{1}", sequence.GetPrecursorIon(2).Composition, sequence.GetPrecursorIon(2).GetMonoIsotopicMz()); Console.WriteLine("Product ions: "); var productIons = sequence.GetProductIons(ionTypeFactory.GetAllKnownIonTypes()); foreach (var theoIon in productIons) { var ionTypeAndIndex = theoIon.Key; var ionType = ionTypeAndIndex.Item1; var index = ionTypeAndIndex.Item2; var ion = theoIon.Value; Console.WriteLine("{0}\t{1}\t{2}\t{3}\t{4}", ionType.Name, index, ion.Composition, ion.Charge, ion.GetMonoIsotopicMz()); } }