internal static void AddMatchedIonsData(Dictionary <string, string> s, List <MatchedFragmentIon> matchedIons) { bool nullPsm = matchedIons == null; StringBuilder seriesStringBuilder = new StringBuilder(); StringBuilder mzStringBuilder = new StringBuilder(); StringBuilder fragmentDaErrorStringBuilder = new StringBuilder(); StringBuilder fragmentPpmErrorStringBuilder = new StringBuilder(); StringBuilder fragmentIntensityStringBuilder = new StringBuilder(); List <StringBuilder> stringBuilders = new List <StringBuilder> { seriesStringBuilder, mzStringBuilder, fragmentDaErrorStringBuilder, fragmentPpmErrorStringBuilder, fragmentIntensityStringBuilder }; if (!nullPsm) { // using ", " instead of "," improves human readability const string delimiter = ", "; var matchedIonsGroupedByProductType = matchedIons.GroupBy(x => new { x.NeutralTheoreticalProduct.ProductType, x.NeutralTheoreticalProduct.SecondaryProductType }).ToList(); foreach (var productType in matchedIonsGroupedByProductType) { var products = productType.OrderBy(p => p.NeutralTheoreticalProduct.FragmentNumber) .ToList(); stringBuilders.ForEach(p => p.Append("[")); for (int i = 0; i < products.Count; i++) { MatchedFragmentIon ion = products[i]; string ionLabel; double massError = ion.Mz.ToMass(ion.Charge) - ion.NeutralTheoreticalProduct.NeutralMass; double ppmMassError = massError / ion.NeutralTheoreticalProduct.NeutralMass * 1e6; ionLabel = ion.Annotation; // append ion label seriesStringBuilder.Append(ionLabel); // append experimental m/z mzStringBuilder.Append(ionLabel + ":" + ion.Mz.ToString("F5")); // append absolute mass error fragmentDaErrorStringBuilder.Append(ionLabel + ":" + massError.ToString("F5")); // append ppm mass error fragmentPpmErrorStringBuilder.Append(ionLabel + ":" + ppmMassError.ToString("F2")); // append fragment ion intensity fragmentIntensityStringBuilder.Append(ionLabel + ":" + ion.Intensity.ToString("F0")); // append delimiter ", " if (i < products.Count - 1) { stringBuilders.ForEach(p => p.Append(delimiter)); } } // append product type delimiter stringBuilders.ForEach(p => p.Append("];")); } } // save ion series strings to output dictionary s[PsmTsvHeader.MatchedIonSeries] = nullPsm ? " " : seriesStringBuilder.ToString().TrimEnd(';'); s[PsmTsvHeader.MatchedIonMzRatios] = nullPsm ? " " : mzStringBuilder.ToString().TrimEnd(';'); s[PsmTsvHeader.MatchedIonMassDiffDa] = nullPsm ? " " : fragmentDaErrorStringBuilder.ToString().TrimEnd(';'); s[PsmTsvHeader.MatchedIonMassDiffPpm] = nullPsm ? " " : fragmentPpmErrorStringBuilder.ToString().TrimEnd(';'); s[PsmTsvHeader.MatchedIonIntensities] = nullPsm ? " " : fragmentIntensityStringBuilder.ToString().TrimEnd(';'); // number of matched ions s[PsmTsvHeader.MatchedIonCounts] = nullPsm ? " " : matchedIons.Count.ToString(); }
protected void AnnotatePeak(MatchedFragmentIon matchedIon, bool isBetaPeptide, bool useLiteralPassedValues = false) { OxyColor ionColor; if (SpectrumMatch.VariantCrossingIons.Contains(matchedIon)) { ionColor = MetaDrawSettings.VariantCrossColor; } else { if (isBetaPeptide) { ionColor = MetaDrawSettings.BetaProductTypeToColor[matchedIon.NeutralTheoreticalProduct.ProductType]; } else { ionColor = MetaDrawSettings.ProductTypeToColor[matchedIon.NeutralTheoreticalProduct.ProductType]; } } int i = Scan.MassSpectrum.GetClosestPeakIndex(matchedIon.NeutralTheoreticalProduct.NeutralMass.ToMz(matchedIon.Charge)); double mz = Scan.MassSpectrum.XArray[i]; double intensity = Scan.MassSpectrum.YArray[i]; if (useLiteralPassedValues) { mz = matchedIon.Mz; intensity = matchedIon.Intensity; } // peak annotation string prefix = ""; if (SpectrumMatch.BetaPeptideBaseSequence != null) { if (isBetaPeptide) { //prefix = "β"; prefix = "B-"; } else { //prefix = "α"; prefix = "A-"; } } string productType = matchedIon.NeutralTheoreticalProduct.ProductType.ToString() //.Replace("star", "*", StringComparison.OrdinalIgnoreCase) //.Replace("degree", "°", StringComparison.OrdinalIgnoreCase) //.Replace("dot", "·", StringComparison.OrdinalIgnoreCase) ; string productNumber = matchedIon.NeutralTheoreticalProduct.FragmentNumber.ToString(); string peakAnnotationText = prefix + productType + productNumber; if (matchedIon.NeutralTheoreticalProduct.NeutralLoss != 0) { peakAnnotationText += "-" + matchedIon.NeutralTheoreticalProduct.NeutralLoss.ToString("F2"); } if (MetaDrawSettings.AnnotateCharges) { peakAnnotationText += "+" + matchedIon.Charge; } if (MetaDrawSettings.AnnotateMzValues) { peakAnnotationText += " (" + matchedIon.Mz.ToString("F3") + ")"; } var peakAnnotation = new TextAnnotation(); peakAnnotation.Font = "Arial"; peakAnnotation.FontSize = MetaDrawSettings.AnnotatedFontSize; peakAnnotation.FontWeight = MetaDrawSettings.AnnotationBold ? OxyPlot.FontWeights.Bold : 2.0; peakAnnotation.TextColor = ionColor; peakAnnotation.StrokeThickness = 0; peakAnnotation.Text = peakAnnotationText; peakAnnotation.TextPosition = new DataPoint(mz, intensity); peakAnnotation.TextVerticalAlignment = intensity < 0 ? OxyPlot.VerticalAlignment.Top : OxyPlot.VerticalAlignment.Bottom; peakAnnotation.TextHorizontalAlignment = OxyPlot.HorizontalAlignment.Center; if (!MetaDrawSettings.DisplayIonAnnotations) { peakAnnotation.Text = string.Empty; } DrawPeak(mz, intensity, MetaDrawSettings.StrokeThicknessAnnotated, ionColor, peakAnnotation); }