public static void CalculateSpectralAngles(SpectralLibrary spectralLibrary, PeptideSpectralMatch[] peptideSpectralMatches, Ms2ScanWithSpecificMass[] arrayOfSortedMs2Scans, CommonParameters commonParameters) { foreach (PeptideSpectralMatch psm in peptideSpectralMatches.Where(p => p != null)) { Ms2ScanWithSpecificMass scan = arrayOfSortedMs2Scans[psm.ScanIndex]; //TODO: spectral angle could be used to disambiguate PSMs. right now for ambiguous PSMs, the spectral angle for only one peptide option is saved foreach (var peptide in psm.PeptidesToMatchingFragments) { if (spectralLibrary == null || !spectralLibrary.TryGetSpectrum(peptide.Key.FullSequence, scan.PrecursorCharge, out var librarySpectrum)) { continue; } double spectralAngle = CalculateNormalizedSpectralAngle(librarySpectrum.MatchedFragmentIons, scan.TheScan, commonParameters); psm.SpectralAngle = spectralAngle; } } }
public void DisplaySpectrumMatch(PlotView plotView, Canvas canvas, PsmFromTsv psm, ParentChildScanPlotsView parentChildScanPlotsView, out List <string> errors) { errors = null; // clear old parent/child scans parentChildScanPlotsView.Plots.Clear(); CurrentlyDisplayedPlots.Clear(); // get the scan if (!MsDataFiles.TryGetValue(psm.FileNameWithoutExtension, out DynamicDataConnection spectraFile)) { errors = new List <string>(); errors.Add("The spectra file could not be found for this PSM: " + psm.FileNameWithoutExtension); return; } MsDataScan scan = spectraFile.GetOneBasedScanFromDynamicConnection(psm.Ms2ScanNumber); LibrarySpectrum librarySpectrum = null; // plot the annotated spectrum match PeptideSpectrumMatchPlot plot; if (psm.BetaPeptideBaseSequence == null) { // get the library spectrum if relevant if (SpectralLibrary != null) { SpectralLibrary.TryGetSpectrum(psm.FullSequence, psm.PrecursorCharge, out var librarySpectrum1); librarySpectrum = librarySpectrum1; } plot = new PeptideSpectrumMatchPlot(plotView, canvas, psm, scan, psm.MatchedIons, librarySpectrum: librarySpectrum); } else { plot = new CrosslinkSpectrumMatchPlot(plotView, canvas, psm, scan); } CurrentlyDisplayedPlots.Add(plot); // plot parent/child scans if (psm.ChildScanMatchedIons != null) { // draw parent scan string parentAnnotation = "Scan: " + scan.OneBasedScanNumber + " Dissociation Type: " + scan.DissociationType + " MsOrder: " + scan.MsnOrder + " Selected Mz: " + scan.SelectedIonMZ.Value.ToString("0.##") + " Retention Time: " + scan.RetentionTime.ToString("0.##"); var parentPlotView = new PlotView(); // placeholder var parentCanvas = new Canvas(); var item = new ParentChildScanPlotTemplate() { Plot = new PeptideSpectrumMatchPlot(parentPlotView, parentCanvas, psm, scan, psm.MatchedIons), SpectrumLabel = parentAnnotation, TheCanvas = parentCanvas }; parentChildScanPlotsView.Plots.Add(item); // remove model from placeholder (the model can only be referenced by 1 plotview at a time) parentPlotView.Model = null; // draw child scans HashSet <int> scansDrawn = new HashSet <int>(); var allChildScanMatchedIons = psm.ChildScanMatchedIons; if (psm.BetaPeptideChildScanMatchedIons != null) { allChildScanMatchedIons = allChildScanMatchedIons.Concat(psm.BetaPeptideChildScanMatchedIons) .GroupBy(p => p.Key) .ToDictionary(p => p.Key, q => q.SelectMany(p => p.Value).ToList()); } foreach (var childScanMatchedIons in allChildScanMatchedIons) { int childScanNumber = childScanMatchedIons.Key; if (scansDrawn.Contains(childScanNumber)) { continue; } scansDrawn.Add(childScanNumber); List <MatchedFragmentIon> matchedIons = childScanMatchedIons.Value; MsDataScan childScan = spectraFile.GetOneBasedScanFromDynamicConnection(childScanNumber); string childAnnotation = "Scan: " + childScan.OneBasedScanNumber + " Dissociation Type: " + childScan.DissociationType + " MsOrder: " + childScan.MsnOrder + " Selected Mz: " + childScan.SelectedIonMZ.Value.ToString("0.##") + " RetentionTime: " + childScan.RetentionTime.ToString("0.##"); Canvas childCanvas = new Canvas(); PlotView childPlotView = new PlotView(); // placeholder // make the plot var childPlot = new PeptideSpectrumMatchPlot(childPlotView, childCanvas, psm, childScan, matchedIons, annotateProperties: false); childPlot.Model.Title = null; childPlot.Model.Subtitle = null; item = new ParentChildScanPlotTemplate() { Plot = childPlot, SpectrumLabel = childAnnotation, TheCanvas = childCanvas }; // remove model from placeholder (the model can only be referenced by 1 plotview at a time) childPlotView.Model = null; parentChildScanPlotsView.Plots.Add(item); CurrentlyDisplayedPlots.Add(childPlot); } } }
public static void CalculateSpectralAngles(SpectralLibrary spectralLibrary, PeptideSpectralMatch[] psms, Ms2ScanWithSpecificMass[] arrayOfSortedMs2Scans, CommonParameters commonParameters) { if (spectralLibrary != null) { // one lock for each MS2 scan; a scan can only be accessed by one thread at a time var myLocks = new object[psms.Length]; for (int i = 0; i < myLocks.Length; i++) { myLocks[i] = new object(); } int maxThreadsPerFile = commonParameters.MaxThreadsToUsePerFile; int[] threads = Enumerable.Range(0, maxThreadsPerFile).ToArray(); Parallel.ForEach(threads, (i) => { // Stop loop if canceled if (GlobalVariables.StopLoops) { return; } for (; i < psms.Length; i += maxThreadsPerFile) { lock (myLocks[i]) { if (psms[i] != null) { Ms2ScanWithSpecificMass scan = arrayOfSortedMs2Scans[psms[i].ScanIndex]; List <(int, PeptideWithSetModifications)> pwsms = new(); List <double> pwsmSpectralAngles = new(); foreach (var(Notch, Peptide) in psms[i].BestMatchingPeptides) { //if peptide is target, directly look for the target's spectrum in the spectral library if (!Peptide.Protein.IsDecoy && spectralLibrary.TryGetSpectrum(Peptide.FullSequence, scan.PrecursorCharge, out var librarySpectrum)) { SpectralSimilarity s = new SpectralSimilarity(scan.TheScan.MassSpectrum, librarySpectrum.XArray, librarySpectrum.YArray, SpectralSimilarity.SpectrumNormalizationScheme.squareRootSpectrumSum, commonParameters.ProductMassTolerance.Value, false); if (s.SpectralContrastAngle().HasValue) { pwsms.Add((Notch, Peptide)); pwsmSpectralAngles.Add((double)s.SpectralContrastAngle()); } } //if peptide is decoy, look for the decoy's corresponding target's spectrum in the spectral library and generate decoy spectrum by function GetDecoyLibrarySpectrumFromTargetByRevers else if (Peptide.Protein.IsDecoy && spectralLibrary.TryGetSpectrum(Peptide.PeptideDescription, scan.PrecursorCharge, out var targetlibrarySpectrum)) { var decoyPeptideTheorProducts = new List <Product>(); Peptide.Fragment(commonParameters.DissociationType, commonParameters.DigestionParams.FragmentationTerminus, decoyPeptideTheorProducts); var decoylibrarySpectrum = GetDecoyLibrarySpectrumFromTargetByReverse(targetlibrarySpectrum, decoyPeptideTheorProducts); SpectralSimilarity s = new SpectralSimilarity(scan.TheScan.MassSpectrum, decoylibrarySpectrum.Select(x => x.Mz).ToArray(), decoylibrarySpectrum.Select(x => x.Intensity).ToArray(), SpectralSimilarity.SpectrumNormalizationScheme.squareRootSpectrumSum, commonParameters.ProductMassTolerance.Value, false); if (s.SpectralContrastAngle().HasValue) { pwsms.Add((Notch, Peptide)); pwsmSpectralAngles.Add((double)s.SpectralContrastAngle()); } } } if (pwsmSpectralAngles.Count > 0 && !pwsmSpectralAngles.Max().Equals(null)) { psms[i].SpectralAngle = pwsmSpectralAngles.Max(); } else { psms[i].SpectralAngle = -1; } } }