-
Notifications
You must be signed in to change notification settings - Fork 51
Refuse to update a spectral library when none was given #2721
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from 1 commit
6fe5e32
ab0b033
d4cf63d
a46a840
c551b16
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -174,6 +174,15 @@ protected override MyTaskResults RunSpecific(string OutputFolder, List<DbForTask | |
| // load spectral libraries | ||
| var spectralLibrary = LoadSpectralLibraries(taskId, dbFilenameList); | ||
|
|
||
| // Checked here rather than where the library is updated, which happens after the whole search: | ||
| // there is nothing to update, and reporting that once the search has finished wastes the run. | ||
| if (SearchParameters.UpdateSpectralLibrary && spectralLibrary == null) | ||
| { | ||
| throw new MetaMorpheusException( | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Worth knowing before you settle on I traced it end to end. Answering Yes composes a mailto to The house channel for refusing a bad database/task combination is Counter-argument, which is real: Either way, not something to fix silently — your call, and worth saying out loud in the PR description if you keep the throw. |
||
| "Updating a spectral library was requested, but no spectral library was given. Add one to " + | ||
| "the list of databases, or select writing a new spectral library instead of updating one."); | ||
| } | ||
|
|
||
| // write prose settings | ||
| ProseCreatedWhileRunning.Append("The following search settings were used: "); | ||
| ProseCreatedWhileRunning.Append($"{GlobalVariables.AnalyteType.GetDigestionAgentLabel()} = " + CommonParameters.DigestionParams.DigestionAgent + "; "); | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,49 @@ | ||
| using EngineLayer; | ||
| using NUnit.Framework; | ||
| using System.Collections.Generic; | ||
| using System.IO; | ||
| using TaskLayer; | ||
| using EngineLayer.DatabaseLoading; | ||
|
|
||
| namespace Test | ||
| { | ||
| [TestFixture] | ||
| public static class SpectralLibraryUpdateTests | ||
| { | ||
| /// <summary> | ||
| /// Issue #2291. Asking to update a spectral library without giving one used to run the whole search | ||
| /// and then throw NullReferenceException out of UpdateSpectralLibrary, which surfaced as the task | ||
| /// hanging on "Writing PSM results" with the exception only visible in results.txt afterwards. | ||
| /// | ||
| /// The combination is refused before searching now, so the wasted run is what this pins: reaching | ||
| /// the check costs a database load, not a search. | ||
| /// </summary> | ||
| [Test] | ||
| public static void UpdatingASpectralLibraryWithoutOneIsRefusedBeforeSearching() | ||
| { | ||
| string outputFolder = Path.Combine(TestContext.CurrentContext.TestDirectory, | ||
| "SpectralLibraryUpdateTests", "NoLibrary"); | ||
| Directory.CreateDirectory(outputFolder); | ||
|
|
||
| var task = new SearchTask(); | ||
| task.SearchParameters.UpdateSpectralLibrary = true; | ||
|
|
||
| string database = Path.Combine(TestContext.CurrentContext.TestDirectory, | ||
| "TestData", "hela_snip_for_unitTest.fasta"); | ||
| string spectra = Path.Combine(TestContext.CurrentContext.TestDirectory, | ||
| "TestData", "TaGe_SA_A549_3_snip.mzML"); | ||
|
|
||
| var thrown = Assert.Throws<MetaMorpheusException>(() => task.RunTask( | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The test name and doc comment promise "before searching"; the assertions only prove "at all". The three assertions are (To be precise about the one place it would catch: moving the throw into Cheapest fix that pins it, after the expected exception: Assert.That(Directory.GetFiles(outputFolder, "*.psmtsv", SearchOption.AllDirectories), Is.Empty,
"the refusal has to come before the search, not after it");
Assert.That(Directory.Exists(Path.Combine(outputFolder, "Individual File Results")), Is.False);Two smaller things while you're in here:
|
||
| outputFolder, | ||
| new List<DbForTask> { new DbForTask(database, false) }, | ||
| new List<string> { spectra }, | ||
| "TestUpdateWithoutLibrary")); | ||
|
|
||
| Assert.That(thrown.Message, Does.Contain("spectral library")); | ||
| Assert.That(thrown.Message, Does.Contain("no spectral library was given").IgnoreCase, | ||
| "say what is missing, not just that something went wrong"); | ||
|
|
||
| Directory.Delete(outputFolder, recursive: true); | ||
| } | ||
| } | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The check lands nine lines too late to deliver what the PR describes.
var proteinLoadingTask = dbLoader.RunAsync();already fired at line 171, andRunAsyncisTask.Run(Run)(EngineLayer/MetaMorpheusEngine.cs:318) with no cancellation token — there is noCancellationTokenoverload anywhere in TaskLayer/EngineLayer, andDatabaseLoadingEngine.RunSpecificnever checksGlobalVariables.StopLoops. Throwing here abandons that task: it runs the FASTA load, decoy generation andScrambleHomologousDecoysto completion on a thread-pool thread afterRunTaskhas unhookedFinishedSingleEngineHandler(MetaMorpheusTask.cs:685) and rethrown, and any exception it raises is never observed.The check doesn't need any of that work.
LoadSpectralLibrariesis a pure filter overdbFilenameList—dbFilenameList.Where(p => p.IsSpectralLibrary), returningnullwhen the list is empty (MetaMorpheusTask.cs:741-746), no I/O. So the whole test can move above line 170 and the cost of the mistake becomes nothing at all, rather than "a database load".In practice the leak is small (thread-pool work, and
WriteTargetDecoyFastadefaults to false so nothing is written), andSearchTaskalready abandons this task on other throw paths —:301for an unknown isobaric mass tag. So this isn't a new class of problem. But it is the one line of the PR whose placement is the whole argument, and hoisting it is free.