diff --git a/MetaMorpheus/EngineLayer/FdrAnalysis/FdrAnalysisEngine.cs b/MetaMorpheus/EngineLayer/FdrAnalysis/FdrAnalysisEngine.cs index e75e91b19..b3c55ccd2 100644 --- a/MetaMorpheus/EngineLayer/FdrAnalysis/FdrAnalysisEngine.cs +++ b/MetaMorpheus/EngineLayer/FdrAnalysis/FdrAnalysisEngine.cs @@ -39,6 +39,10 @@ private void AddPsmAndPeptideFdrInfoIfNotPresent() foreach (var psm in AllPsms.Where(p => p.PeptideFdrInfo == null)) { psm.PeptideFdrInfo = new FdrInfo(); + // If peptide level Q-values default to zero, it is hard to determine which PSMs have a legitimate peptide-level Q-value of zero and + // which just weren't included in peptide-level calculations. Hence, we set q values to one here. + psm.PeptideFdrInfo.QValue = 1; + psm.PeptideFdrInfo.PEP_QValue = 1; } } diff --git a/MetaMorpheus/GUI/TaskWindows/SearchTaskWindow.xaml b/MetaMorpheus/GUI/TaskWindows/SearchTaskWindow.xaml index 9f3205c57..cb1a18934 100644 --- a/MetaMorpheus/GUI/TaskWindows/SearchTaskWindow.xaml +++ b/MetaMorpheus/GUI/TaskWindows/SearchTaskWindow.xaml @@ -544,6 +544,24 @@ + + + + + + + + + + + + + + + + + + diff --git a/MetaMorpheus/GUI/TaskWindows/SearchTaskWindow.xaml.cs b/MetaMorpheus/GUI/TaskWindows/SearchTaskWindow.xaml.cs index 678e1392c..9bacbf2ad 100644 --- a/MetaMorpheus/GUI/TaskWindows/SearchTaskWindow.xaml.cs +++ b/MetaMorpheus/GUI/TaskWindows/SearchTaskWindow.xaml.cs @@ -190,6 +190,7 @@ private void UpdateFieldsFromTask(SearchTask task) CheckBoxNoQuant.IsChecked = !task.SearchParameters.DoLabelFreeQuantification; CheckBoxLFQ.IsChecked = task.SearchParameters.DoLabelFreeQuantification; CheckBoxUseSharedPeptidesForQuant.IsChecked = task.SearchParameters.UseSharedPeptidesForLFQ; + CheckBoxOnlyQuantifyConfidentPeptides.IsChecked = task.SearchParameters.OnlyQuantifyConfidentPeptides; CheckBoxMultiplex.IsChecked = task.SearchParameters.DoMultiplexQuantification; MultiplexComboBox.SelectedItem = task.SearchParameters.MultiplexModId ?? _defaultMultiplexType; // If Spectral Recovery is enabled @@ -628,6 +629,7 @@ private void SaveButton_Click(object sender, RoutedEventArgs e) TheTask.SearchParameters.NoOneHitWonders = CheckBoxNoOneHitWonders.IsChecked.Value; TheTask.SearchParameters.DoLabelFreeQuantification = !CheckBoxNoQuant.IsChecked.Value; TheTask.SearchParameters.UseSharedPeptidesForLFQ = CheckBoxUseSharedPeptidesForQuant.IsChecked.Value; + TheTask.SearchParameters.OnlyQuantifyConfidentPeptides = CheckBoxOnlyQuantifyConfidentPeptides.IsChecked.Value; TheTask.SearchParameters.DoSpectralRecovery = CheckBoxLFQwSpectralRecovery.IsChecked.Value; TheTask.SearchParameters.DoMultiplexQuantification = CheckBoxMultiplex.IsChecked.Value; TheTask.SearchParameters.MultiplexModId = (string)MultiplexComboBox.SelectedItem; diff --git a/MetaMorpheus/TaskLayer/FilteredPsms.cs b/MetaMorpheus/TaskLayer/FilteredPsms.cs index 81e80c0fa..53f5170f1 100644 --- a/MetaMorpheus/TaskLayer/FilteredPsms.cs +++ b/MetaMorpheus/TaskLayer/FilteredPsms.cs @@ -95,7 +95,7 @@ public static FilteredPsms Filter(IEnumerable psms, pepQValueThreshold ??= commonParams.PepQValueThreshold; double filterThreshold = Math.Min((double)qValueThreshold, (double)pepQValueThreshold); bool filteringNotPerformed = false; - List filteredPsms = new List(); + List filteredPsms = new(); // set the filter type FilterType filterType = FilterType.QValue; diff --git a/MetaMorpheus/TaskLayer/SearchTask/PostSearchAnalysisTask.cs b/MetaMorpheus/TaskLayer/SearchTask/PostSearchAnalysisTask.cs index 69e73a402..15bbc44f2 100644 --- a/MetaMorpheus/TaskLayer/SearchTask/PostSearchAnalysisTask.cs +++ b/MetaMorpheus/TaskLayer/SearchTask/PostSearchAnalysisTask.cs @@ -501,8 +501,23 @@ private void QuantificationAnalysis() } } + // Determine if only select, high confidence peptides will be used for quant + List peptideSequencesForQuantification = null; + if (Parameters.SearchParameters.SilacLabels == null && Parameters.SearchParameters.OnlyQuantifyConfidentPeptides) + { + peptideSequencesForQuantification = FilteredPsms.Filter(Parameters.AllPsms, + CommonParameters, + includeDecoys: false, + includeContaminants: true, + includeAmbiguous: false, + includeAmbiguousMods: false, + includeHighQValuePsms: false, + filterAtPeptideLevel: true) + .Select(pep => pep.FullSequence).Distinct().ToList(); + } + // run FlashLFQ - var flashLfqEngine = new FlashLfqEngine( + var flashLfqEngine = new FlashLfqEngine( allIdentifications: flashLFQIdentifications, normalize: Parameters.SearchParameters.Normalize, ppmTolerance: Parameters.SearchParameters.QuantifyPpmTol, @@ -510,7 +525,8 @@ private void QuantificationAnalysis() matchBetweenRuns: Parameters.SearchParameters.MatchBetweenRuns, useSharedPeptidesForProteinQuant: Parameters.SearchParameters.UseSharedPeptidesForLFQ, silent: true, - maxThreads: CommonParameters.MaxThreadsToUsePerFile); + maxThreads: CommonParameters.MaxThreadsToUsePerFile, + peptideSequencesToUse: peptideSequencesForQuantification); if (flashLFQIdentifications.Any()) { diff --git a/MetaMorpheus/TaskLayer/SearchTask/SearchParameters.cs b/MetaMorpheus/TaskLayer/SearchTask/SearchParameters.cs index 080ee2c6d..c3d8bee93 100644 --- a/MetaMorpheus/TaskLayer/SearchTask/SearchParameters.cs +++ b/MetaMorpheus/TaskLayer/SearchTask/SearchParameters.cs @@ -17,6 +17,7 @@ public SearchParameters() ModPeptidesAreDifferent = false; DoLabelFreeQuantification = true; UseSharedPeptidesForLFQ = false; + OnlyQuantifyConfidentPeptides = true; DoSpectralRecovery = false; QuantifyPpmTol = 5; SearchTarget = true; @@ -69,6 +70,7 @@ public SearchParameters() public bool MatchBetweenRuns { get; set; } public bool Normalize { get; set; } public double QuantifyPpmTol { get; set; } + public bool OnlyQuantifyConfidentPeptides { get; set; } public bool DoHistogramAnalysis { get; set; } public bool SearchTarget { get; set; } public DecoyType DecoyType { get; set; } diff --git a/MetaMorpheus/Test/EverythingRunnerEngineTestCase.cs b/MetaMorpheus/Test/EverythingRunnerEngineTestCase.cs index a907b3f5d..fdf8f9e39 100644 --- a/MetaMorpheus/Test/EverythingRunnerEngineTestCase.cs +++ b/MetaMorpheus/Test/EverythingRunnerEngineTestCase.cs @@ -126,6 +126,7 @@ static EverythingRunnerEngineTestCase() @"TestData\TaGe_SA_A549_3_snip_2.mzML"); string myDatabase = Path.Combine(TestContext.CurrentContext.TestDirectory, @"TestData\TaGe_SA_A549_3_snip.fasta"); + searchTaskLoaded.SearchParameters.OnlyQuantifyConfidentPeptides = true; _cases.Add(EverythingRunnerEngineTestCases.BottomUpQValue, new EverythingRunnerEngineTestCase(EverythingRunnerEngineTestCases.BottomUpQValue, new List<(string, MetaMorpheusTask)> { ("postSearchAnalysisTaskTestOutput", searchTaskLoaded) }, diff --git a/MetaMorpheus/Test/FdrTest.cs b/MetaMorpheus/Test/FdrTest.cs index 73bb1af82..e6f5faf2f 100644 --- a/MetaMorpheus/Test/FdrTest.cs +++ b/MetaMorpheus/Test/FdrTest.cs @@ -96,19 +96,19 @@ public static void FdrTestMethod() fdr.Run(); Assert.AreEqual(2, searchModes.NumNotches); - Assert.AreEqual(0, newPsms[0].FdrInfo.CumulativeDecoyNotch); - Assert.AreEqual(1, newPsms[0].FdrInfo.CumulativeTargetNotch); - Assert.AreEqual(0, newPsms[1].FdrInfo.CumulativeDecoyNotch); - Assert.AreEqual(1, newPsms[1].FdrInfo.CumulativeTargetNotch); - Assert.AreEqual(0, newPsms[2].FdrInfo.CumulativeDecoyNotch); - Assert.AreEqual(1, newPsms[2].FdrInfo.CumulativeTargetNotch); - - Assert.AreEqual(0, newPsms[0].FdrInfo.CumulativeDecoy); - Assert.AreEqual(1, newPsms[0].FdrInfo.CumulativeTarget); - Assert.AreEqual(0, newPsms[1].FdrInfo.CumulativeDecoy); - Assert.AreEqual(2, newPsms[1].FdrInfo.CumulativeTarget); - Assert.AreEqual(0, newPsms[2].FdrInfo.CumulativeDecoy); - Assert.AreEqual(3, newPsms[2].FdrInfo.CumulativeTarget); + Assert.AreEqual(0, newPsms[0].PsmFdrInfo.CumulativeDecoyNotch); + Assert.AreEqual(1, newPsms[0].PsmFdrInfo.CumulativeTargetNotch); + Assert.AreEqual(0, newPsms[1].PsmFdrInfo.CumulativeDecoyNotch); + Assert.AreEqual(1, newPsms[1].PsmFdrInfo.CumulativeTargetNotch); + Assert.AreEqual(0, newPsms[2].PsmFdrInfo.CumulativeDecoyNotch); + Assert.AreEqual(1, newPsms[2].PsmFdrInfo.CumulativeTargetNotch); + + Assert.AreEqual(0, newPsms[0].PsmFdrInfo.CumulativeDecoy); + Assert.AreEqual(1, newPsms[0].PsmFdrInfo.CumulativeTarget); + Assert.AreEqual(0, newPsms[1].PsmFdrInfo.CumulativeDecoy); + Assert.AreEqual(2, newPsms[1].PsmFdrInfo.CumulativeTarget); + Assert.AreEqual(0, newPsms[2].PsmFdrInfo.CumulativeDecoy); + Assert.AreEqual(3, newPsms[2].PsmFdrInfo.CumulativeTarget); } [Test] @@ -266,7 +266,7 @@ public static void TestComputePEPValue() foreach (var item in allPsmsArray.Where(p => p != null)) { - var b = item.FdrInfo.PEP; + var b = item.PsmFdrInfo.PEP; if (b >= 0.5) { trueCount++; @@ -349,7 +349,7 @@ public static void TestComputePEPValue() foreach (var item in psmCopyForCZETest.Where(p => p != null)) { - var b = item.FdrInfo.PEP; + var b = item.PsmFdrInfo.PEP; if (b >= 0.5) { trueCount++; diff --git a/MetaMorpheus/Test/MultiProteaseParsimonyTest.cs b/MetaMorpheus/Test/MultiProteaseParsimonyTest.cs index d44d3226c..76a448955 100644 --- a/MetaMorpheus/Test/MultiProteaseParsimonyTest.cs +++ b/MetaMorpheus/Test/MultiProteaseParsimonyTest.cs @@ -710,7 +710,7 @@ public static void TestPSMFdrFiltering_Simulated() var fdrFilteredPsms = new List(); foreach (SpectralMatch psm in psms) { - if (psm != null && psm.FdrInfo.QValue <= 0.0100 && psm.FdrInfo.QValueNotch <= 0.0100) + if (psm != null && psm.PsmFdrInfo.QValue <= 0.0100 && psm.PsmFdrInfo.QValueNotch <= 0.0100) { fdrFilteredPsms.Add(psm); } diff --git a/MetaMorpheus/Test/PostSearchAnalysisTaskTests.cs b/MetaMorpheus/Test/PostSearchAnalysisTaskTests.cs index f01117297..94b3d874b 100644 --- a/MetaMorpheus/Test/PostSearchAnalysisTaskTests.cs +++ b/MetaMorpheus/Test/PostSearchAnalysisTaskTests.cs @@ -101,6 +101,16 @@ public static void AllResultsAndResultsTxtContainsCorrectValues_PepQValue_Bottom Assert.AreEqual("TaGe_SA_A549_3_snip_2 - Target protein groups within 1 % FDR: 140", results[15]); } + [Test] + public static void TestPeptideQuantificationResults() + { + EverythingRunnerEngineTestCase.TryGetTestCase(EverythingRunnerEngineTestCases.BottomUpQValue, out var testCase); + + string peptideQuantFile = Path.Combine(testCase.OutputDirectory, @"postSearchAnalysisTaskTestOutput\AllQuantifiedPeptides.tsv"); + string[] peptideQuant = File.ReadAllLines(peptideQuantFile); + Assert.AreEqual(175, peptideQuant.Length); // 174 peptides + header. Make sure that we're quantifying only those peptides with q-value <= 0.01 + } + /// /// Ensures that there is the proper ratio of summary and individual lines in the result.txt file and that peptides and proteoforms are distinct /// diff --git a/MetaMorpheus/Test/SearchEngineTests.cs b/MetaMorpheus/Test/SearchEngineTests.cs index fc4d3c62f..180604e0f 100644 --- a/MetaMorpheus/Test/SearchEngineTests.cs +++ b/MetaMorpheus/Test/SearchEngineTests.cs @@ -553,13 +553,13 @@ public static void TestModernSearchEngineLowResOneRealSpectrum() // Single search mode Assert.AreEqual(12, allPsmsArray.Length); - var goodPsm = nonNullPsms.Where(p => p.FdrInfo.QValue <= 0.01).ToList(); + var goodPsm = nonNullPsms.Where(p => p.PsmFdrInfo.QValue <= 0.01).ToList(); var myMatchedIons = goodPsm[0].MatchedFragmentIons; Assert.AreEqual(47, myMatchedIons.Count()); - var goodScore = nonNullPsms.Where(p => p.FdrInfo.QValue <= 0.01).Select(s => s.Score).ToList(); + var goodScore = nonNullPsms.Where(p => p.PsmFdrInfo.QValue <= 0.01).Select(s => s.Score).ToList(); goodScore.Sort(); Assert.AreEqual(2, goodPsm.Count()); } @@ -656,7 +656,7 @@ public static void TestClassicSearchEngineLowResSimple() // Single search mode Assert.AreEqual(535, allPsmsArray.Length); - var goodScore = nonNullPsms.Where(p => p.FdrInfo.QValue <= 0.01).Select(s => s.Score).ToList(); + var goodScore = nonNullPsms.Where(p => p.PsmFdrInfo.QValue <= 0.01).Select(s => s.Score).ToList(); Assert.AreEqual(181, goodScore.Count()); Directory.Delete(outputFolder, true); @@ -748,7 +748,7 @@ public static void TestModernSearchEngineLowResSimple() // Single search mode Assert.AreEqual(535, allPsmsArray.Length); - var goodScore = nonNullPsms.Where(p => p.FdrInfo.QValue <= 0.01).Select(s => s.Score).ToList(); + var goodScore = nonNullPsms.Where(p => p.PsmFdrInfo.QValue <= 0.01).Select(s => s.Score).ToList(); Assert.AreEqual(181, goodScore.Count()); } diff --git a/MetaMorpheus/Test/SpectralRecoveryTest.cs b/MetaMorpheus/Test/SpectralRecoveryTest.cs index c69e03aa2..7ffd90289 100644 --- a/MetaMorpheus/Test/SpectralRecoveryTest.cs +++ b/MetaMorpheus/Test/SpectralRecoveryTest.cs @@ -167,10 +167,8 @@ public static void SpectralRecoveryPostSearchAnalysisTest() List matches02ng = mbrPsms.Where(p => p.FileNameWithoutExtension == "K13_02ng_1min_frac1").ToList(); List expectedMatches = mbrPsms.Select(p => p.BaseSeq).Intersect(expectedMbrPsms.Select(p => p.BaseSeq).ToList()).ToList(); - // Changing Q-value calculation methods results in more PSMs being discovered, and so fewer spectra are available to be "recovered" - // (as they were identified in the orignal search) - Assert.That(matches2ng.Count >= 3); - Assert.That(matches02ng.Count >= 10); + Assert.That(matches2ng.Count >= 2); + Assert.That(matches02ng.Count >= 7); // AS: 6/17/24 - Fewer quantification events (8 -> 7) because one of the peptides doesn't clear peptide level FDR threshold Assert.That(expectedMatches.Count >= 2); // FlashLFQ doesn't find all 6 expected peaks, only 3. MbrAnalysis finds these three peaks //TODO: Add test for recovering fdrInfo from original. Currently, PsmTsvReader doesn't support the new columns, so it's hard to test diff --git a/MetaMorpheus/Test/Test.csproj b/MetaMorpheus/Test/Test.csproj index a4d8b9f5c..5b128a546 100644 --- a/MetaMorpheus/Test/Test.csproj +++ b/MetaMorpheus/Test/Test.csproj @@ -322,6 +322,12 @@ Always + + Always + + + Always + Always diff --git a/MetaMorpheus/Test/TestData/Task1-SearchTaskconfig.toml b/MetaMorpheus/Test/TestData/Task1-SearchTaskconfig.toml index 1b1b8022c..90806b529 100644 --- a/MetaMorpheus/Test/TestData/Task1-SearchTaskconfig.toml +++ b/MetaMorpheus/Test/TestData/Task1-SearchTaskconfig.toml @@ -15,7 +15,7 @@ MassDiffAcceptorType = "Exact" WritePrunedDatabase = false KeepAllUniprotMods = true DoLocalizationAnalysis = true -DoQuantification = false +DoQuantification = true SearchType = "Classic" LocalFdrCategories = ["FullySpecific"] MaxFragmentSize = 30000.0 diff --git a/MetaMorpheus/Test/TestPsm.cs b/MetaMorpheus/Test/TestPsm.cs index f3921c997..315d03196 100644 --- a/MetaMorpheus/Test/TestPsm.cs +++ b/MetaMorpheus/Test/TestPsm.cs @@ -305,7 +305,7 @@ public static void TestPsmMatchingToTargetAndDecoyWithDifferentSequences() List<(string fileName, CommonParameters fileSpecificParameters)> fsp = new List<(string fileName, CommonParameters fileSpecificParameters)> { ("filename", commonParameters) }; new FdrAnalysisEngine(new List { psm }, 1, new CommonParameters(), fsp, new List()).Run(); - Assert.AreEqual(0.5, psm.FdrInfo.CumulativeDecoy); + Assert.AreEqual(0.5, psm.PsmFdrInfo.CumulativeDecoy); } [Test] diff --git a/MetaMorpheus/Test/XLTest.cs b/MetaMorpheus/Test/XLTest.cs index 5de9a1e65..406f00a19 100644 --- a/MetaMorpheus/Test/XLTest.cs +++ b/MetaMorpheus/Test/XLTest.cs @@ -374,7 +374,8 @@ public static void XlTest_MoreComprehensive() var xlSearchParameters = new XlSearchParameters { - CrosslinkAtCleavageSite = true + CrosslinkAtCleavageSite = true, + WritePepXml = true }; //Create databases contain two protein. @@ -579,7 +580,7 @@ public static void XlTest_MoreComprehensive() deadendNH2 = 0; deadendTris = 0; - foreach (CrosslinkSpectralMatch csm in firstCsmsFromListsOfCsms.Where(c => c.FdrInfo.QValue <= 0.01).ToList()) + foreach (CrosslinkSpectralMatch csm in firstCsmsFromListsOfCsms.Where(c => c.PsmFdrInfo.QValue <= 0.01).ToList()) { switch (csm.CrossType) { @@ -776,7 +777,7 @@ public static void XlTest_MoreComprehensive() deadendNH2 = 0; deadendTris = 0; - foreach (CrosslinkSpectralMatch csm in firstCsmsFromListsOfCsms.Where(c => c.FdrInfo.QValue <= 0.01).ToList()) + foreach (CrosslinkSpectralMatch csm in firstCsmsFromListsOfCsms.Where(c => c.PsmFdrInfo.QValue <= 0.01).ToList()) { switch (csm.CrossType) {