diff --git a/MetaMorpheus/EngineLayer/FdrAnalysis/FdrAnalysisEngine.cs b/MetaMorpheus/EngineLayer/FdrAnalysis/FdrAnalysisEngine.cs index 3784795a2..bd7048b00 100644 --- a/MetaMorpheus/EngineLayer/FdrAnalysis/FdrAnalysisEngine.cs +++ b/MetaMorpheus/EngineLayer/FdrAnalysis/FdrAnalysisEngine.cs @@ -1,6 +1,8 @@ using System; using System.Collections.Generic; using System.Linq; +using EngineLayer; +using EngineLayer.FdrAnalysis; namespace EngineLayer.FdrAnalysis { @@ -10,13 +12,13 @@ public class FdrAnalysisEngine : MetaMorpheusEngine private readonly int MassDiffAcceptorNumNotches; private readonly double ScoreCutoff; private readonly string AnalysisType; - private readonly string OutputFolder; // used for storing PEP training models + private readonly string OutputFolder; // used for storing PEP training models private readonly bool DoPEP; public FdrAnalysisEngine(List psms, int massDiffAcceptorNumNotches, CommonParameters commonParameters, List<(string fileName, CommonParameters fileSpecificParameters)> fileSpecificParameters, List nestedIds, string analysisType = "PSM", bool doPEP = true, string outputFolder = null) : base(commonParameters, fileSpecificParameters, nestedIds) { - AllPsms = psms.OrderByDescending(p=>p).ToList(); + AllPsms = psms.OrderByDescending(p => p).ToList(); MassDiffAcceptorNumNotches = massDiffAcceptorNumNotches; ScoreCutoff = commonParameters.ScoreCutoff; AnalysisType = analysisType; @@ -52,50 +54,14 @@ private void DoFalseDiscoveryRateAnalysis(FdrAnalysisResults myAnalysisResults) QValueTraditional(psms); if (psms.Count > 100) { - QValueInverted(psms); - } - - // set q-value thresholds such that a lower scoring PSM can't have - // a higher confidence than a higher scoring PSM - //Populate min qValues - double qValueThreshold = 1.0; - double[] qValueNotchThreshold = new double[MassDiffAcceptorNumNotches + 1]; - for (int i = 0; i < qValueNotchThreshold.Length; i++) - { - qValueNotchThreshold[i] = 1.0; - } - - for (int i = psms.Count - 1; i >= 0; i--) - { - SpectralMatch psm = psms[i]; - - // threshold q-values - if (psm.FdrInfo.QValue > qValueThreshold) + if (DoPEP) { - psm.FdrInfo.QValue = qValueThreshold; - } - else if (psm.FdrInfo.QValue < qValueThreshold) - { - qValueThreshold = psm.FdrInfo.QValue; - } - - // threshold notch q-values - int notch = psm.Notch ?? MassDiffAcceptorNumNotches; - if (psm.FdrInfo.QValueNotch > qValueNotchThreshold[notch]) - { - psm.FdrInfo.QValueNotch = qValueNotchThreshold[notch]; - } - else if (psm.FdrInfo.QValueNotch < qValueNotchThreshold[notch]) - { - qValueNotchThreshold[notch] = psm.FdrInfo.QValueNotch; + Compute_PEPValue(myAnalysisResults); } + QValueInverted(psms); } + CountPsm(psms); } - if (DoPEP) - { - Compute_PEPValue(myAnalysisResults); - } - CountPsm(); } private static void QValueInverted(List psms) @@ -194,7 +160,6 @@ public void Compute_PEPValue(FdrAnalysisResults myAnalysisResults) Compute_PEPValue_Based_QValue(AllPsms); } - CountPsm(); // recounting Psm's after PEP based disambiguation } if (AnalysisType == "Peptide") @@ -223,35 +188,31 @@ public static void Compute_PEPValue_Based_QValue(List psms) psms[psmsArrayIndicies[i]].FdrInfo.PEP_QValue = Math.Round(qValue, 6); } } - - public void CountPsm() + /// + /// This method gets the count of PSMs with the same full sequence (with q-value < 0.01) to include in the psmtsv output + /// + public void CountPsm(List proteasePsms) { - var psmsGroupedByProtease = AllPsms.GroupBy(p => p.DigestionParams.Protease); + // exclude ambiguous psms and has a fdr cutoff = 0.01 + var allUnambiguousPsms = proteasePsms.Where(psm => psm.FullSequence != null).ToList(); - foreach (var proteasePsms in psmsGroupedByProtease) - { - // exclude ambiguous psms and has a fdr cutoff = 0.01 - var allUnambiguousProteasePsms = proteasePsms.Where(p => p.FullSequence != null).ToList(); + var unambiguousPsmsLessThanOnePercentFdr = allUnambiguousPsms.Where(psm => + psm.FdrInfo.QValue <= 0.01 + && psm.FdrInfo.QValueNotch <= 0.01) + .GroupBy(p => p.FullSequence); - var fullSequenceGroups = allUnambiguousProteasePsms.Where(p => p.FdrInfo.QValue < 0.01 && p.FdrInfo.QValueNotch < 0.01) - .Select(p => p.FullSequence).GroupBy(s => s); + Dictionary sequenceToPsmCount = new Dictionary(); - Dictionary sequenceToPsmCount = new Dictionary(); - foreach (var fullSequence in fullSequenceGroups) - { - sequenceToPsmCount.Add(fullSequence.Key, fullSequence.Count()); - } + foreach (var sequenceGroup in unambiguousPsmsLessThanOnePercentFdr) + { + sequenceToPsmCount.TryAdd(sequenceGroup.First().FullSequence, sequenceGroup.Count()); + } - foreach (SpectralMatch psm in allUnambiguousProteasePsms) + foreach (SpectralMatch psm in allUnambiguousPsms) + { + if (sequenceToPsmCount.TryGetValue(psm.FullSequence, out int count)) { - if (sequenceToPsmCount.TryGetValue(psm.FullSequence, out int count)) - { - psm.PsmCount = count; - } - else - { - psm.PsmCount = 0; - } + psm.PsmCount = count; } } } diff --git a/MetaMorpheus/EngineLayer/PsmTsv/PsmTsvWriter.cs b/MetaMorpheus/EngineLayer/PsmTsv/PsmTsvWriter.cs index 07ec02dd0..0c304095f 100644 --- a/MetaMorpheus/EngineLayer/PsmTsv/PsmTsvWriter.cs +++ b/MetaMorpheus/EngineLayer/PsmTsv/PsmTsvWriter.cs @@ -10,6 +10,7 @@ using Omics; using Omics.Modifications; + namespace EngineLayer { public static class PsmTsvWriter @@ -216,7 +217,7 @@ internal static void AddPeptideSequenceData(Dictionary s, Spectr .Where(d => Includes(b, d)) .Select(d => $"{d.OneBasedBeginPosition.ToString()}-{d.OneBasedEndPosition.ToString()}")))).ResolvedString; } - + s[PsmTsvHeader.Contaminant] = pepWithModsIsNull ? " " : Resolve(pepsWithMods.Select(b => b.Parent.IsContaminant ? "Y" : "N")).ResolvedString; s[PsmTsvHeader.Decoy] = pepWithModsIsNull ? " " : Resolve(pepsWithMods.Select(b => b.Parent.IsDecoy ? "Y" : "N")).ResolvedString; s[PsmTsvHeader.PeptideDesicription] = pepWithModsIsNull ? " " : Resolve(pepsWithMods.Select(b => b.Description)).ResolvedString; diff --git a/MetaMorpheus/Test/MultiProteaseParsimonyTest.cs b/MetaMorpheus/Test/MultiProteaseParsimonyTest.cs index 5865d0a67..2cea5a6f0 100644 --- a/MetaMorpheus/Test/MultiProteaseParsimonyTest.cs +++ b/MetaMorpheus/Test/MultiProteaseParsimonyTest.cs @@ -990,7 +990,7 @@ public static void MultiProteaseParsimony_TestingGreedyAlgorithm() } /// - /// This test ensures that FDR for each psm is calculated accoriding to its protease + /// This test ensures that FDR for each psm is calculated according to its protease /// [Test] public static void MultiProteaseParsimony_TestingProteaseSpecificFDRCalculations() @@ -1032,16 +1032,15 @@ public static void MultiProteaseParsimony_TestingProteaseSpecificFDRCalculations new FdrAnalysisEngine(psms, 0, new CommonParameters(), fsp, new List()).Run(); psms = psms.OrderByDescending(p => p.Score).ToList(); - Assert.AreEqual(0.00, Math.Round(psms[0].FdrInfo.QValue, 2)); Assert.AreEqual(0.00, Math.Round(psms[1].FdrInfo.QValue, 2)); Assert.AreEqual(0.00, Math.Round(psms[2].FdrInfo.QValue, 2)); Assert.AreEqual(0.00, Math.Round(psms[3].FdrInfo.QValue, 2)); - Assert.AreEqual(0.33, Math.Round(psms[4].FdrInfo.QValue, 2)); + Assert.AreEqual(0.5, Math.Round(psms[4].FdrInfo.QValue, 2)); Assert.AreEqual(0.33, Math.Round(psms[5].FdrInfo.QValue, 2)); Assert.AreEqual(0.00, Math.Round(psms[6].FdrInfo.QValue, 2)); Assert.AreEqual(0.33, Math.Round(psms[7].FdrInfo.QValue, 2)); - Assert.AreEqual(0.50, Math.Round(psms[8].FdrInfo.QValue, 2)); - Assert.AreEqual(0.50, Math.Round(psms[9].FdrInfo.QValue, 2)); + Assert.AreEqual(0.67, Math.Round(psms[8].FdrInfo.QValue, 2)); + Assert.AreEqual(0.5, Math.Round(psms[9].FdrInfo.QValue, 2)); } } } \ No newline at end of file diff --git a/MetaMorpheus/Test/PeptideSpectralMatchTest.cs b/MetaMorpheus/Test/PeptideSpectralMatchTest.cs new file mode 100644 index 000000000..6d3f3cd5e --- /dev/null +++ b/MetaMorpheus/Test/PeptideSpectralMatchTest.cs @@ -0,0 +1,102 @@ +using EngineLayer; +using MassSpectrometry; +using NUnit.Framework; +using Proteomics.ProteolyticDigestion; +using Proteomics; +using System; +using System.Collections.Generic; +using Omics.Digestion; +using Omics.Fragmentation; +using Omics.Modifications; + +namespace Test +{ + [TestFixture] + internal class PeptideSpectralMatchTest + { + [Test] + public static void GetAminoAcidCoverageTest() + { + CommonParameters commonParams = new CommonParameters(digestionParams: new DigestionParams(protease: "trypsin", minPeptideLength: 1)); + + MsDataScan scanNumberOne = new MsDataScan(new MzSpectrum(new double[] { 10 }, new double[] { 1 }, false), 1, 2, true, Polarity.Positive, double.NaN, null, null, MZAnalyzerType.Orbitrap, double.NaN, null, null, "scan=1", 10, 2, 100, double.NaN, null, DissociationType.AnyActivationType, 0, null); + + Ms2ScanWithSpecificMass ms2ScanOneMzTen = new Ms2ScanWithSpecificMass(scanNumberOne, 10, 2, "File", new CommonParameters()); + + string sequence = ""; + Dictionary allKnownMods = new(); + int numFixedMods = 0; + DigestionParams digestionParams = new DigestionParams(); + Protein myProtein = new Protein(sequence, "ACCESSION"); + int oneBasedStartResidueInProtein = 0; + int oneBasedEndResidueInProtein = Math.Max(sequence.Length, 0); + int missedCleavages = 0; + CleavageSpecificity cleavageSpecificity = CleavageSpecificity.Full; + string peptideDescription = null; + int? pairedTargetDecoyHash = null; + + PeptideWithSetModifications pwsmNoBaseSequence = new(sequence, allKnownMods, numFixedMods, digestionParams, myProtein, + oneBasedStartResidueInProtein, oneBasedEndResidueInProtein, missedCleavages, cleavageSpecificity, + peptideDescription, pairedTargetDecoyHash); + PeptideSpectralMatch psmNoBaseSequenceNoMFI = new(pwsmNoBaseSequence, 0, 10, 0, ms2ScanOneMzTen, commonParams, + new List()); + psmNoBaseSequenceNoMFI.ResolveAllAmbiguities(); + + //PSM has neither sequence nor matched fragment ions + var b = psmNoBaseSequenceNoMFI.BaseSequence; + Assert.AreEqual("", b); + var m = psmNoBaseSequenceNoMFI.MatchedFragmentIons; + Assert.AreEqual(0, m.Count); + psmNoBaseSequenceNoMFI.GetAminoAcidCoverage(); + + sequence = "PEPTIDE"; + oneBasedEndResidueInProtein = Math.Max(sequence.Length, 0); + myProtein = new Protein(sequence, "ACCESSION"); + PeptideWithSetModifications pwsmBaseSequence = new(sequence, allKnownMods, numFixedMods, digestionParams, myProtein, + oneBasedStartResidueInProtein, oneBasedEndResidueInProtein, missedCleavages, cleavageSpecificity, + peptideDescription, pairedTargetDecoyHash); + PeptideSpectralMatch psmBaseSequenceNoMFI = new(pwsmBaseSequence, 0, 10, 0, ms2ScanOneMzTen, commonParams, + new List()); + + //PSM has sequence but does not have matched fragment ions + psmBaseSequenceNoMFI.ResolveAllAmbiguities(); + b = psmBaseSequenceNoMFI.BaseSequence; + Assert.AreEqual(sequence, b); + m = psmBaseSequenceNoMFI.MatchedFragmentIons; + Assert.AreEqual(0, m.Count); + psmBaseSequenceNoMFI.GetAminoAcidCoverage(); + + //PSM has no sequence but does have matched fragment ions + Product ntProduct = new Product(ProductType.y, FragmentationTerminus.N, 1, 1, 1, 0); + MatchedFragmentIon mfi = new(ntProduct, 1, 1, 1); + List mfiList = new List() { mfi }; + PeptideSpectralMatch psmNoBaseSequenceMFI = new(pwsmNoBaseSequence, 0, 10, 0, ms2ScanOneMzTen, commonParams, + mfiList); + psmNoBaseSequenceMFI.ResolveAllAmbiguities(); + + b = psmNoBaseSequenceMFI.BaseSequence; + Assert.AreEqual("", b); + m = psmNoBaseSequenceMFI.MatchedFragmentIons; + Assert.AreEqual(1, m.Count); + psmNoBaseSequenceMFI.GetAminoAcidCoverage(); + + //PSM has sequence and matched fragment ions + PeptideSpectralMatch psmBaseSequenceMFI = new(pwsmBaseSequence, 0, 10, 0, ms2ScanOneMzTen, commonParams, + mfiList); + psmBaseSequenceMFI.ResolveAllAmbiguities(); + + b = psmBaseSequenceMFI.BaseSequence; + Assert.AreEqual("PEPTIDE", b); + m = psmBaseSequenceMFI.MatchedFragmentIons; + Assert.AreEqual(1, m.Count); + psmBaseSequenceMFI.GetAminoAcidCoverage(); + + List psms = new List() { psmNoBaseSequenceNoMFI, psmBaseSequenceNoMFI, psmNoBaseSequenceMFI, psmBaseSequenceMFI }; + + foreach (var psm in psms) + { + psm.ToString(); + } + } + } +} \ No newline at end of file diff --git a/MetaMorpheus/Test/PostSearchAnalysisTaskTests.cs b/MetaMorpheus/Test/PostSearchAnalysisTaskTests.cs index 7b20f2fe2..140903d0a 100644 --- a/MetaMorpheus/Test/PostSearchAnalysisTaskTests.cs +++ b/MetaMorpheus/Test/PostSearchAnalysisTaskTests.cs @@ -34,7 +34,7 @@ public static void AllResultsAndResultsTxtTests() // identified across all files. int TaGe_SA_A549_3_snip_2ExpectedPsms = 214; int TaGe_SA_A549_3_snip_2ExpectedPeptides = 174; - + Assert.AreEqual("All target PSMs with q-value = 0.01: 428", allResults[12]); Assert.AreEqual("All target peptides with q-value = 0.01 : 174", allResults[13]); @@ -42,7 +42,7 @@ public static void AllResultsAndResultsTxtTests() Assert.AreEqual("TaGe_SA_A549_3_snip target PSMs with q-value = 0.01: 214", allResults[18]); Assert.AreEqual("Target protein groups within 1 % FDR in TaGe_SA_A549_3_snip: 165", allResults[24]); Assert.AreEqual("TaGe_SA_A549_3_snip Target peptides with q-value = 0.01 : 174", allResults[26]); - + Assert.AreEqual("TaGe_SA_A549_3_snip_2 target PSMs with q-value = 0.01: " + TaGe_SA_A549_3_snip_2ExpectedPsms, allResults[22]); Assert.AreEqual("TaGe_SA_A549_3_snip_2 Target peptides with q-value = 0.01 : " + TaGe_SA_A549_3_snip_2ExpectedPeptides, allResults[28]); Assert.AreEqual("Target protein groups within 1 % FDR in TaGe_SA_A549_3_snip_2: 165", allResults[25]); @@ -59,7 +59,7 @@ public static void AllResultsAndResultsTxtTests() Assert.AreEqual("TaGe_SA_A549_3_snip_2 target PSMs with q-value = 0.01: " + TaGe_SA_A549_3_snip_2ExpectedPsms, results[17]); Assert.AreEqual("TaGe_SA_A549_3_snip_2 Target peptides with q-value = 0.01 : " + TaGe_SA_A549_3_snip_2ExpectedPeptides, results[23]); - + Directory.Delete(outputFolder, true); @@ -71,9 +71,9 @@ public static void AllResultsAndResultsTxtTests() engineToml.Run(); string[] singleFileResults = File.ReadAllLines(resultsFile); - Assert.AreEqual("All target PSMs with q-value = 0.01: " + TaGe_SA_A549_3_snip_2ExpectedPsms, singleFileResults[7]); - Assert.AreEqual("All target peptides with q-value = 0.01 : " + TaGe_SA_A549_3_snip_2ExpectedPeptides, singleFileResults[8]); - Assert.AreEqual("All target protein groups with q-value = 0.01 (1% FDR): 165", singleFileResults[9]); + Assert.AreEqual("All target PSMs with q-value = 0.01: " + TaGe_SA_A549_3_snip_2ExpectedPsms, singleFileResults[7]); + Assert.AreEqual("All target peptides with q-value = 0.01 : " + TaGe_SA_A549_3_snip_2ExpectedPeptides, singleFileResults[8]); + Assert.AreEqual("All target protein groups with q-value = 0.01 (1% FDR): 165", singleFileResults[9]); //Second test that AllResults and Results display correct numbers of peptides and psms with PEP q-value filter on myTomlPath = Path.Combine(TestContext.CurrentContext.TestDirectory, @"TestData\Task2-SearchTaskconfig.toml"); @@ -83,30 +83,30 @@ public static void AllResultsAndResultsTxtTests() allResultsFile = Path.Combine(outputFolder, "allResults.txt"); allResults = File.ReadAllLines(allResultsFile); - Assert.AreEqual("All target PSMs with pep q-value = 0.01: 499", allResults[12]); - Assert.AreEqual("All target peptides with pep q-value = 0.01 : 179", allResults[13]); + Assert.AreEqual("All target PSMs with pep q-value = 0.01: 501", allResults[12]); + Assert.AreEqual("All target peptides with pep q-value = 0.01 : 182", allResults[13]); Assert.AreEqual("All target protein groups with q-value = 0.01 (1% FDR): 165", allResults[14]); - Assert.AreEqual("TaGe_SA_A549_3_snip target PSMs with pep q-value = 0.01: 230", allResults[18]); - Assert.AreEqual("TaGe_SA_A549_3_snip_2 target PSMs with pep q-value = 0.01: 230", allResults[22]); + Assert.AreEqual("TaGe_SA_A549_3_snip target PSMs with pep q-value = 0.01: 233", allResults[18]); + Assert.AreEqual("TaGe_SA_A549_3_snip_2 target PSMs with pep q-value = 0.01: 233", allResults[22]); Assert.AreEqual("Target protein groups within 1 % FDR in TaGe_SA_A549_3_snip: 165", allResults[24]); Assert.AreEqual("Target protein groups within 1 % FDR in TaGe_SA_A549_3_snip_2: 165", allResults[25]); - Assert.AreEqual("TaGe_SA_A549_3_snip Target peptides with pep q-value = 0.01 : 179", allResults[26]); - Assert.AreEqual("TaGe_SA_A549_3_snip_2 Target peptides with pep q-value = 0.01 : 179", allResults[28]); + Assert.AreEqual("TaGe_SA_A549_3_snip Target peptides with pep q-value = 0.01 : 182", allResults[26]); + Assert.AreEqual("TaGe_SA_A549_3_snip_2 Target peptides with pep q-value = 0.01 : 182", allResults[28]); resultsFile = Path.Combine(outputFolder, @"postSearchAnalysisTaskTestOutput\results.txt"); results = File.ReadAllLines(resultsFile); - Assert.AreEqual("All target PSMs with pep q-value = 0.01: 499", results[7]); - Assert.AreEqual("All target peptides with pep q-value = 0.01 : 179", results[8]); + Assert.AreEqual("All target PSMs with pep q-value = 0.01: 501", results[7]); + Assert.AreEqual("All target peptides with pep q-value = 0.01 : 182", results[8]); Assert.AreEqual("All target protein groups with q-value = 0.01 (1% FDR): 165", results[9]); - Assert.AreEqual("TaGe_SA_A549_3_snip target PSMs with pep q-value = 0.01: 230", results[13]); - Assert.AreEqual("TaGe_SA_A549_3_snip_2 target PSMs with pep q-value = 0.01: 230", results[17]); + Assert.AreEqual("TaGe_SA_A549_3_snip target PSMs with pep q-value = 0.01: 233", results[13]); + Assert.AreEqual("TaGe_SA_A549_3_snip_2 target PSMs with pep q-value = 0.01: 233", results[17]); Assert.AreEqual("Target protein groups within 1 % FDR in TaGe_SA_A549_3_snip: 165", results[19]); Assert.AreEqual("Target protein groups within 1 % FDR in TaGe_SA_A549_3_snip_2: 165", results[20]); - Assert.AreEqual("TaGe_SA_A549_3_snip Target peptides with pep q-value = 0.01 : 179", results[21]); - Assert.AreEqual("TaGe_SA_A549_3_snip_2 Target peptides with pep q-value = 0.01 : 179", results[23]); + Assert.AreEqual("TaGe_SA_A549_3_snip Target peptides with pep q-value = 0.01 : 182", results[21]); + Assert.AreEqual("TaGe_SA_A549_3_snip_2 Target peptides with pep q-value = 0.01 : 182", results[23]); Directory.Delete(outputFolder, true); } } -} +} \ No newline at end of file diff --git a/MetaMorpheus/Test/PsvTsvTest.cs b/MetaMorpheus/Test/PsvTsvTest.cs index 55fd5c5f0..8e9daac6c 100644 --- a/MetaMorpheus/Test/PsvTsvTest.cs +++ b/MetaMorpheus/Test/PsvTsvTest.cs @@ -1,7 +1,13 @@ using EngineLayer; using GuiFunctions; +using MassSpectrometry; using NUnit.Framework; +using Omics.Digestion; using Omics.Fragmentation; +using Omics.Modifications; +using Proteomics; +using Proteomics.ProteolyticDigestion; +using System; using System.Collections.Generic; using System.IO; using System.Linq; @@ -222,7 +228,7 @@ public static void TestToString() } [Test] - public static void TestSimpleToLibrarySpectrum() + public static void TestSimpleToLibrarySpectrum() { string psmTsvPath = Path.Combine(TestContext.CurrentContext.TestDirectory, @"TopDownTestData\TDGPTMDSearchResults.psmtsv"); List warnings = new(); @@ -236,7 +242,7 @@ public static void TestSimpleToLibrarySpectrum() //not a great way to test equality but we are experiencing a great deal of 10th digit rounding differences Assert.AreEqual(Regex.Matches(expectedLibrarySpectrum, "ppm").Count, Regex.Matches(librarySpectrum, "ppm").Count); - + //the code below tests the addition and correct output for neutral loss fragments Product p = new Product(ProductType.bWaterLoss, FragmentationTerminus.N, 1, 1, 1, 18); MatchedFragmentIon matchedIon = new(p, 1, 1, 1); @@ -245,5 +251,101 @@ public static void TestSimpleToLibrarySpectrum() Assert.That(librarySpectrumWithNeutralLoss.Contains("WaterLoss")); } + [Test] + public static void TestPsmSortFunction() + { + string[] sequences = { + "ABCKPEPR", + "BRPEPR", + "ARPEPR", + "PEPPER", + "PEPTIDE", + "PRTIEN" + }; + + var p = new List(); + List> gn = new List>(); + for (int i = 0; i < sequences.Length; i++) + { + p.Add(new Protein(sequences[i], (i + 1).ToString(), null, gn, new Dictionary>())); + } + + CommonParameters commonParams = new CommonParameters(digestionParams: new DigestionParams(protease: "trypsin", minPeptideLength: 1)); + + PeptideWithSetModifications pepOne = new PeptideWithSetModifications(protein: p.ElementAt(0), digestionParams: commonParams.DigestionParams, oneBasedStartResidueInProtein: 5, oneBasedEndResidueInProtein: 8, cleavageSpecificity: CleavageSpecificity.Full, peptideDescription: "ABCKPEPR", missedCleavages: 0, allModsOneIsNterminus: new Dictionary(), numFixedMods: 0); + PeptideWithSetModifications pepTwo = new PeptideWithSetModifications(protein: p.ElementAt(1), digestionParams: commonParams.DigestionParams, oneBasedStartResidueInProtein: 3, oneBasedEndResidueInProtein: 6, cleavageSpecificity: CleavageSpecificity.Full, peptideDescription: "BRPEPR", missedCleavages: 0, allModsOneIsNterminus: new Dictionary(), numFixedMods: 0); + PeptideWithSetModifications pepThree = new PeptideWithSetModifications(protein: p.ElementAt(2), digestionParams: commonParams.DigestionParams, oneBasedStartResidueInProtein: 3, oneBasedEndResidueInProtein: 6, cleavageSpecificity: CleavageSpecificity.Full, peptideDescription: "ARPEPR", missedCleavages: 0, allModsOneIsNterminus: new Dictionary(), numFixedMods: 0); + PeptideWithSetModifications pepFour = new PeptideWithSetModifications(protein: p.ElementAt(3), digestionParams: commonParams.DigestionParams, oneBasedStartResidueInProtein: 1, oneBasedEndResidueInProtein: 3, cleavageSpecificity: CleavageSpecificity.Full, peptideDescription: "PEPPER", missedCleavages: 0, allModsOneIsNterminus: new Dictionary(), numFixedMods: 0); + PeptideWithSetModifications pepFive = new PeptideWithSetModifications(protein: p.ElementAt(4), digestionParams: commonParams.DigestionParams, oneBasedStartResidueInProtein: 3, oneBasedEndResidueInProtein: 6, cleavageSpecificity: CleavageSpecificity.Full, peptideDescription: "PEPTIDE", missedCleavages: 0, allModsOneIsNterminus: new Dictionary(), numFixedMods: 0); + PeptideWithSetModifications pepSix = new PeptideWithSetModifications(protein: p.ElementAt(5), digestionParams: commonParams.DigestionParams, oneBasedStartResidueInProtein: 3, oneBasedEndResidueInProtein: 6, cleavageSpecificity: CleavageSpecificity.Full, peptideDescription: "PRTIEN", missedCleavages: 0, allModsOneIsNterminus: new Dictionary(), numFixedMods: 0); + + MsDataScan scanNumberOne = new MsDataScan(new MzSpectrum(new double[] { 10 }, new double[] { 1 }, false), 1, 2, true, Polarity.Positive, double.NaN, null, null, MZAnalyzerType.Orbitrap, double.NaN, null, null, "scan=1", 10, 2, 100, double.NaN, null, DissociationType.AnyActivationType, 0, null); + MsDataScan scanNumberTwo = new MsDataScan(new MzSpectrum(new double[] { 20 }, new double[] { 1 }, false), 2, 2, true, Polarity.Positive, double.NaN, null, null, MZAnalyzerType.Orbitrap, double.NaN, null, null, "scan=2", 20, 2, 100, double.NaN, null, DissociationType.AnyActivationType, 0, null); + MsDataScan scanNumberThree = new MsDataScan(new MzSpectrum(new double[] { 20 }, new double[] { 1 }, false), 3, 2, true, Polarity.Positive, double.NaN, null, null, MZAnalyzerType.Orbitrap, double.NaN, null, null, "scan=3", 20, 2, 100, double.NaN, null, DissociationType.AnyActivationType, 0, null); + + Ms2ScanWithSpecificMass ms2ScanOneMzTen = new Ms2ScanWithSpecificMass(scanNumberOne, 10, 2, "File", new CommonParameters()); + Ms2ScanWithSpecificMass ms2ScanOneMzTwenty = new Ms2ScanWithSpecificMass(scanNumberTwo, 20, 2, "File", new CommonParameters()); + Ms2ScanWithSpecificMass ms2ScanTwoMzTwenty = new Ms2ScanWithSpecificMass(scanNumberTwo, 20, 2, "File", new CommonParameters()); + Ms2ScanWithSpecificMass ms2ScanThreeMzTwenty = new Ms2ScanWithSpecificMass(scanNumberThree, 20, 2, "File", new CommonParameters()); + + //highest score + PeptideSpectralMatch psmOne = new(pepOne, 0, 10, 0, ms2ScanOneMzTen, commonParams, + new List()); + + //second highest score 9. delta score 1 + PeptideSpectralMatch psmTwo = new(pepOne, 0, 8, 0, ms2ScanOneMzTen, commonParams, + new List()); + psmTwo.AddOrReplace(pepTwo, 9, 0, true, new List(), 0); + + //second highest score 9. delta score 0.1 + PeptideSpectralMatch psmThree = new(pepOne, 0, 8.90000000000000000000000000000, 0, ms2ScanOneMzTen, commonParams, + new List()); + psmThree.AddOrReplace(pepTwo, 9, 0, true, new List(), 0); + + //third highest score delta score 1. ppm error -888657.54 low + PeptideSpectralMatch psmFour = new(pepOne, 0, 7, 0, ms2ScanOneMzTwenty, commonParams, + new List()); + psmFour.AddOrReplace(pepFour, 8, 0, true, new List(), 0); + + //third highest score 8. delta score 1. ppm error -947281.29 high + PeptideSpectralMatch psmFive = new(pepOne, 0, 7, 0, ms2ScanOneMzTen, commonParams, + new List()); + psmFive.AddOrReplace(pepFour, 8, 0, true, new List(), 0); + + //fourth highest score 7. delta score 1. same ppm error + PeptideSpectralMatch psmSix = new(pepOne, 0, 6, 0, ms2ScanTwoMzTwenty, commonParams, + new List()); + psmSix.AddOrReplace(pepSix, 7, 0, true, new List(), 0); + + //fourth highest score 7. delta score 1. same ppm error + PeptideSpectralMatch psmSeven = new(pepOne, 0, 6, 0, ms2ScanThreeMzTwenty, commonParams, + new List()); + psmSeven.AddOrReplace(pepSix, 7, 0, true, new List(), 0); + + List psms = new List { psmFour, psmOne, psmThree, psmSeven, psmTwo, psmFive, psmSix }; + psms.ForEach(j => j.ResolveAllAmbiguities()); + psms.ForEach(j => j.SetFdrValues(1, 0, 0, 1, 0, 0, 0, 0)); + + List orderedPsms = psms.OrderByDescending(p => p).ToList(); + + Assert.AreEqual(10, orderedPsms[0].Score); + Assert.AreEqual(9, orderedPsms[1].Score); + Assert.AreEqual(9, orderedPsms[2].Score); + Assert.AreEqual(8, orderedPsms[3].Score); + Assert.AreEqual(8, orderedPsms[4].Score); + Assert.AreEqual(7, orderedPsms[5].Score); + Assert.AreEqual(7, orderedPsms[6].Score); + + Assert.AreEqual(5, orderedPsms[0].RunnerUpScore); + Assert.AreEqual(8.9, orderedPsms[1].RunnerUpScore); + Assert.AreEqual(8, orderedPsms[2].RunnerUpScore); + Assert.AreEqual(7, orderedPsms[3].RunnerUpScore); + Assert.AreEqual(7, orderedPsms[4].RunnerUpScore); + Assert.AreEqual(6, orderedPsms[5].RunnerUpScore); + Assert.AreEqual(6, orderedPsms[6].RunnerUpScore); + + Assert.IsTrue(Math.Abs(orderedPsms[3].PrecursorMassErrorPpm.First()) < Math.Abs(orderedPsms[4].PrecursorMassErrorPpm.First())); + Assert.IsTrue(orderedPsms[5].ScanNumber < orderedPsms[6].ScanNumber); + } } } \ No newline at end of file diff --git a/MetaMorpheus/Test/SearchTaskTest.cs b/MetaMorpheus/Test/SearchTaskTest.cs index cce514a40..9a88b00a9 100644 --- a/MetaMorpheus/Test/SearchTaskTest.cs +++ b/MetaMorpheus/Test/SearchTaskTest.cs @@ -386,7 +386,7 @@ public static void PeptideFDRTest() // test that the final q-value follows the (target / decoy) formula // intermediate q-values no longer always follow this formula, so I'm not testing them here - Assert.AreEqual(cumDecoys / (double)cumTargets, finalQValue, 0.0001); + Assert.That((double)cumDecoys / (double)cumTargets, Is.EqualTo(finalQValue).Within(.0005)); Directory.Delete(folderPath, true); } diff --git a/MetaMorpheus/Test/TestPsm.cs b/MetaMorpheus/Test/TestPsm.cs index 1db813ce2..1ba07b76a 100644 --- a/MetaMorpheus/Test/TestPsm.cs +++ b/MetaMorpheus/Test/TestPsm.cs @@ -6,19 +6,19 @@ using MzLibUtil; using NUnit.Framework; using Proteomics; -using Omics.Fragmentation; using Proteomics.ProteolyticDigestion; using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Reflection; -using Omics.Digestion; -using Omics.Modifications; using TaskLayer; using UsefulProteomicsDatabases; using PsmFromTsv = EngineLayer.PsmFromTsv; using Omics; +using Omics.Digestion; +using Omics.Fragmentation; +using Omics.Modifications; namespace Test { @@ -126,7 +126,7 @@ public static void TestPpmAndDaMassErrors() CommonParameters, fsp, new List()).Run()); var nonNullPsms = allPsmsArray.Where(p => p != null).ToList(); - foreach (SpectralMatch psm in nonNullPsms) + foreach (PeptideSpectralMatch psm in nonNullPsms) { double daError = Math.Round(psm.ScanPrecursorMass - psm.BestMatchingBioPolymersWithSetMods.First().Peptide.MonoisotopicMass, 5); @@ -154,7 +154,7 @@ public static void TestLongestFragmentIonSequence() var listOfSortedms2Scans = MetaMorpheusTask.GetMs2Scans(myMsDataFile, null, new CommonParameters()).OrderBy(b => b.PrecursorMass).ToArray(); SpectralMatch[] allPsmsArray = new SpectralMatch[listOfSortedms2Scans.Length]; bool writeSpetralLibrary = false; - new ClassicSearchEngine(allPsmsArray, listOfSortedms2Scans, variableModifications, fixedModifications, null, null, null, proteinList, searchModes, + new ClassicSearchEngine(allPsmsArray, listOfSortedms2Scans, variableModifications, fixedModifications, null, null, null, proteinList, searchModes, new CommonParameters(), null, null, new List(), writeSpetralLibrary).Run(); List longestSeriesObserved = new List(); @@ -346,7 +346,7 @@ public static void TestPsmCount() var fdrEngine = new FdrAnalysisEngine(allPsms, 0, new CommonParameters(), fsp, new List()); - fdrEngine.CountPsm(); + fdrEngine.CountPsm(allPsms); var psmGroups = allPsms.Where(psm => psm.FullSequence != null && psm.PsmCount > 0).GroupBy(p => p.FullSequence).ToList(); Assert.That(psmGroups.First().Count() == 2); Assert.That(psmGroups.First().First().PsmCount == 1); @@ -354,7 +354,7 @@ public static void TestPsmCount() psm2.SetFdrValues(0, 0, 0, 0, 0, 0, 0, 0); psm3.ResolveAllAmbiguities(); - fdrEngine.CountPsm(); + fdrEngine.CountPsm(allPsms); psmGroups = allPsms.Where(psm => psm.FullSequence != null && psm.PsmCount > 0).GroupBy(p => p.FullSequence).ToList(); Assert.That(psmGroups.First().Count() == 3); } @@ -390,9 +390,7 @@ public static void TestPsmCount2() } var psmsFromTsv = PsmTsvReader.ReadTsv(Path.Combine(outputFolder, @"AllPSMs.psmtsv"), out var warnings); - var allUnambiguousPsms = psmsFromTsv.Where(psm => psm.FullSequence != null); - var unambiguousPsmsLessThanOnePercentFdr = allUnambiguousPsms.Where(psm => psm.QValue <= 0.01) .GroupBy(p => p.FullSequence).ToList(); @@ -514,7 +512,7 @@ public static void TestPSMFragmentCoverage() Protein p2 = new Protein("GGGGGGGGGGGGGGKPEPTIDEPEPTIDE", null); PeptideWithSetModifications pep2 = p2.Digest(commonParameters.DigestionParams, new List(), new List()).ToList()[1]; - TestDataFile t = new TestDataFile(new List { pep1, pep2}); + TestDataFile t = new TestDataFile(new List { pep1, pep2 }); //psm 1 - test first and last amino acid positions, along with one internal Amino Acid position Product productC3 = new Product(ProductType.y, FragmentationTerminus.C, 0, 3, 12, 0); @@ -535,7 +533,7 @@ public static void TestPSMFragmentCoverage() MatchedFragmentIon mfiN6 = new MatchedFragmentIon(productN6, 0, 0, 1); MatchedFragmentIon mfiN8 = new MatchedFragmentIon(productN8, 0, 0, 1); MatchedFragmentIon mfiN13 = new MatchedFragmentIon(productN13, 0, 0, 1); - List mfis1 = new List { mfiC3, mfiC4, mfiC7, mfiC13, mfiN3, mfiN4, mfiN6, mfiN8, mfiN13}; + List mfis1 = new List { mfiC3, mfiC4, mfiC7, mfiC13, mfiN3, mfiN4, mfiN6, mfiN8, mfiN13 }; MsDataScan mzLibScan1 = t.GetOneBasedScan(2); Ms2ScanWithSpecificMass scan1 = new Ms2ScanWithSpecificMass(mzLibScan1, 0, 1, null, new CommonParameters()); SpectralMatch psm1 = new PeptideSpectralMatch(pep1, 0, 0, 0, scan1, commonParameters, mfis1);