diff --git a/MetaMorpheus/CMD/CMD.csproj b/MetaMorpheus/CMD/CMD.csproj
index 927a97c0d..becf89ce6 100644
--- a/MetaMorpheus/CMD/CMD.csproj
+++ b/MetaMorpheus/CMD/CMD.csproj
@@ -24,7 +24,7 @@
-
+
diff --git a/MetaMorpheus/EngineLayer/AnalyteType.cs b/MetaMorpheus/EngineLayer/AnalyteType.cs
new file mode 100644
index 000000000..8b8d754ce
--- /dev/null
+++ b/MetaMorpheus/EngineLayer/AnalyteType.cs
@@ -0,0 +1,56 @@
+using System.Collections.Generic;
+
+namespace EngineLayer
+{
+ public enum AnalyteType
+ {
+ Peptide,
+ Proteoform,
+ Oligo
+ }
+
+ ///
+ /// Accessor methods for specific information about certain analyte types
+ ///
+ public static class AnalyteTypeExtensions
+ {
+ private static readonly Dictionary AnalyteTypes = new()
+ {
+ { AnalyteType.Peptide, new AnalyteTypeData("PSM", "Peptide", "Protein", "psmtsv") },
+ { AnalyteType.Proteoform, new AnalyteTypeData("PSM", "Proteoform", "Protein", "psmtsv") },
+ { AnalyteType.Oligo, new AnalyteTypeData("OSM", "Oligo", "Transcript", "osmtsv") },
+ };
+
+ public static string GetSpectralMatchLabel(this AnalyteType analyteType) => AnalyteTypes[analyteType].SpectralMatchLabel;
+ public static string GetSpectralMatchExtension(this AnalyteType analyteType) => AnalyteTypes[analyteType].SpectralMatchExtension;
+ public static string GetUniqueFormLabel(this AnalyteType analyteType) => AnalyteTypes[analyteType].UniqueFormLabel;
+ public static string GetBioPolymerLabel(this AnalyteType analyteType) => AnalyteTypes[analyteType].BioPolymerLabel;
+ }
+
+ ///
+ /// Represents an analyte type and is used to determine the output format of the analyte type.
+ ///
+ internal class AnalyteTypeData(string spectralMatchLabel, string uniqueFormLabel, string bioPolymerLabel, string spectralMatchExtension)
+ {
+ ///
+ /// Gets or sets the label for spectral matches (e.g. PSM).
+ ///
+ internal string SpectralMatchLabel { get; init; } = spectralMatchLabel;
+
+ ///
+ /// Extension for spectral matches (e.g. psmtsv).
+ ///
+ internal string SpectralMatchExtension { get; init; } = spectralMatchExtension;
+
+ ///
+ /// Gets or sets the label for unique forms (e.g. Peptide).
+ ///
+ internal string UniqueFormLabel { get; init; } = uniqueFormLabel;
+
+ ///
+ /// Gets or sets the label for grouped forms (e.g. Protein).
+ ///
+ internal string BioPolymerLabel { get; init; } = bioPolymerLabel;
+ }
+}
+
diff --git a/MetaMorpheus/EngineLayer/EngineLayer.csproj b/MetaMorpheus/EngineLayer/EngineLayer.csproj
index f937bdc7f..c0aa4ef10 100644
--- a/MetaMorpheus/EngineLayer/EngineLayer.csproj
+++ b/MetaMorpheus/EngineLayer/EngineLayer.csproj
@@ -21,7 +21,7 @@
-
+
diff --git a/MetaMorpheus/EngineLayer/GlobalVariables.cs b/MetaMorpheus/EngineLayer/GlobalVariables.cs
index 96efe5960..51bfc06eb 100644
--- a/MetaMorpheus/EngineLayer/GlobalVariables.cs
+++ b/MetaMorpheus/EngineLayer/GlobalVariables.cs
@@ -34,7 +34,7 @@ public static class GlobalVariables
private static char[] _InvalidAminoAcids;
// this affects output labels, etc. and can be changed to "Proteoform" for top-down searches
- public static string AnalyteType;
+ public static AnalyteType AnalyteType;
public static List ErrorsReadingMods;
@@ -65,7 +65,7 @@ public static void SetUpGlobalVariables()
Loaders.LoadElements();
AcceptedDatabaseFormats = new List { ".fasta", ".fa", ".xml", ".msp" };
AcceptedSpectraFormats = new List { ".raw", ".mzml", ".mgf" };
- AnalyteType = "Peptide";
+ AnalyteType = AnalyteType.Peptide;
_InvalidAminoAcids = new char[] { 'X', 'B', 'J', 'Z', ':', '|', ';', '[', ']', '{', '}', '(', ')', '+', '-' };
ExperimentalDesignFileName = "ExperimentalDesign.tsv";
SeparationTypes = new List { { "HPLC" }, { "CZE" } };
diff --git a/MetaMorpheus/EngineLayer/NonSpecificEnzymeSearch/NonSpecificEnzymeSearchEngine.cs b/MetaMorpheus/EngineLayer/NonSpecificEnzymeSearch/NonSpecificEnzymeSearchEngine.cs
index 4c23fa7d2..ff18c3c27 100644
--- a/MetaMorpheus/EngineLayer/NonSpecificEnzymeSearch/NonSpecificEnzymeSearchEngine.cs
+++ b/MetaMorpheus/EngineLayer/NonSpecificEnzymeSearch/NonSpecificEnzymeSearchEngine.cs
@@ -377,7 +377,7 @@ private Tuple Accepts(List fragments,
updatedMods.Add(key, mod.Value);
}
}
- if (terminalMod != null)
+ if (terminalMod != null && !updatedMods.Keys.Contains(startResidue - 1))
{
updatedMods.Add(startResidue - 1, terminalMod);
}
diff --git a/MetaMorpheus/GUI/GUI.csproj b/MetaMorpheus/GUI/GUI.csproj
index 0db67590d..0ac630833 100644
--- a/MetaMorpheus/GUI/GUI.csproj
+++ b/MetaMorpheus/GUI/GUI.csproj
@@ -55,7 +55,7 @@
-
+
diff --git a/MetaMorpheus/GUI/TaskWindows/GPTMDTaskWindow.xaml b/MetaMorpheus/GUI/TaskWindows/GPTMDTaskWindow.xaml
index bfb5d6c8a..2341862a1 100644
--- a/MetaMorpheus/GUI/TaskWindows/GPTMDTaskWindow.xaml
+++ b/MetaMorpheus/GUI/TaskWindows/GPTMDTaskWindow.xaml
@@ -48,34 +48,7 @@
-
-
-
-
-
- Use the charge states and precursor masses determined by the instrument controller.
-
-
-
-
-
-
- Additionally searches for coisolated peptides, allowing for multiple peptides to be identified from a single MS2.
-
-
-
-
-
-
-
-
- The maximum charge state that deconvolution should allow. Minimum is 1.
-
-
-
-
-
-
+
diff --git a/MetaMorpheus/GUI/TaskWindows/GPTMDTaskWindow.xaml.cs b/MetaMorpheus/GUI/TaskWindows/GPTMDTaskWindow.xaml.cs
index 4c3449f93..37d595cfa 100644
--- a/MetaMorpheus/GUI/TaskWindows/GPTMDTaskWindow.xaml.cs
+++ b/MetaMorpheus/GUI/TaskWindows/GPTMDTaskWindow.xaml.cs
@@ -29,6 +29,7 @@ public partial class GptmdTaskWindow : Window
private readonly ObservableCollection GptmdModTypeForTreeViewObservableCollection = new ObservableCollection();
private bool AutomaticallyAskAndOrUpdateParametersBasedOnProtease = true;
private CustomFragmentationWindow CustomFragmentationWindow;
+ private DeconHostViewModel DeconHostViewModel;
public GptmdTaskWindow(GptmdTask myGPTMDtask)
{
@@ -39,6 +40,7 @@ public GptmdTaskWindow(GptmdTask myGPTMDtask)
PopulateChoices();
UpdateFieldsFromTask(TheTask);
AutomaticallyAskAndOrUpdateParametersBasedOnProtease = true;
+ DeisotopingControl.DataContext = DeconHostViewModel;
if (myGPTMDtask == null)
{
@@ -62,10 +64,10 @@ private void Row_DoubleClick(object sender, MouseButtonEventArgs e)
private void UpdateFieldsFromTask(GptmdTask task)
{
+ DeconHostViewModel = new DeconHostViewModel(TheTask.CommonParameters.PrecursorDeconvolutionParameters,
+ TheTask.CommonParameters.ProductDeconvolutionParameters,
+ TheTask.CommonParameters.UseProvidedPrecursorInfo, TheTask.CommonParameters.DoPrecursorDeconvolution);
ProteaseComboBox.SelectedItem = task.CommonParameters.DigestionParams.Protease; //protease needs to come first or recommended settings can overwrite the actual settings
- UseProvidedPrecursor.IsChecked = task.CommonParameters.UseProvidedPrecursorInfo;
- DeconvolutePrecursors.IsChecked = task.CommonParameters.DoPrecursorDeconvolution;
- DeconvolutionMaxAssumedChargeStateTextBox.Text = task.CommonParameters.DeconvolutionMaxAssumedChargeState.ToString();
MissedCleavagesTextBox.Text = task.CommonParameters.DigestionParams.MaxMissedCleavages == int.MaxValue ? "" : task.CommonParameters.DigestionParams.MaxMissedCleavages.ToString(CultureInfo.InvariantCulture);
MinPeptideLengthTextBox.Text = task.CommonParameters.DigestionParams.MinPeptideLength.ToString(CultureInfo.InvariantCulture);
MaxPeptideLengthTextBox.Text = task.CommonParameters.DigestionParams.MaxPeptideLength == int.MaxValue ? "" : task.CommonParameters.DigestionParams.MaxPeptideLength.ToString(CultureInfo.InvariantCulture);
@@ -260,8 +262,8 @@ private void ProteaseSpecificUpdate(object sender, SelectionChangedEventArgs e)
case "top-down":
if (UpdateGUISettings.UseTopDownRecommendedSettings())
{
- UseProvidedPrecursor.IsChecked = false;
- DeconvolutionMaxAssumedChargeStateTextBox.Text = "60";
+ DeconHostViewModel.UseProvidedPrecursors = false;
+ DeconHostViewModel.PrecursorDeconvolutionParameters.MaxAssumedChargeState = 60;
TrimMsMs.IsChecked = false;
//uncheck all variable mods
foreach (var mod in VariableModTypeForTreeViewObservableCollection)
@@ -354,7 +356,7 @@ private void SaveButton_Click(object sender, RoutedEventArgs e)
if (!GlobalGuiSettings.CheckTaskSettingsValidity(PrecursorMassToleranceTextBox.Text, ProductMassToleranceTextBox.Text, MissedCleavagesTextBox.Text,
MaxModificationIsoformsTextBox.Text, MinPeptideLengthTextBox.Text, MaxPeptideLengthTextBox.Text, MaxThreadsTextBox.Text, MinScoreAllowed.Text,
- fieldNotUsed, fieldNotUsed, DeconvolutionMaxAssumedChargeStateTextBox.Text, NumberOfPeaksToKeepPerWindowTextBox.Text, MinimumAllowedIntensityRatioToBasePeakTexBox.Text,
+ fieldNotUsed, fieldNotUsed, DeconHostViewModel.PrecursorDeconvolutionParameters.MaxAssumedChargeState.ToString(), NumberOfPeaksToKeepPerWindowTextBox.Text, MinimumAllowedIntensityRatioToBasePeakTexBox.Text,
null, null, fieldNotUsed, fieldNotUsed, fieldNotUsed, null, null, null))
{
return;
@@ -441,10 +443,14 @@ private void SaveButton_Click(object sender, RoutedEventArgs e)
}
bool parseMaxThreadsPerFile = int.Parse(MaxThreadsTextBox.Text, CultureInfo.InvariantCulture) <= Environment.ProcessorCount && int.Parse(MaxThreadsTextBox.Text, CultureInfo.InvariantCulture) > 0;
+ DeconvolutionParameters precursorDeconvolutionParameters = DeconHostViewModel.PrecursorDeconvolutionParameters.Parameters;
+ DeconvolutionParameters productDeconvolutionParameters = DeconHostViewModel.ProductDeconvolutionParameters.Parameters;
+ bool useProvidedPrecursorInfo = DeconHostViewModel.UseProvidedPrecursors;
+ bool doPrecursorDeconvolution = DeconHostViewModel.DoPrecursorDeconvolution;
+
CommonParameters commonParamsToSave = new CommonParameters(
- useProvidedPrecursorInfo: UseProvidedPrecursor.IsChecked.Value,
- deconvolutionMaxAssumedChargeState: int.Parse(DeconvolutionMaxAssumedChargeStateTextBox.Text, CultureInfo.InvariantCulture),
- doPrecursorDeconvolution: DeconvolutePrecursors.IsChecked.Value,
+ useProvidedPrecursorInfo: useProvidedPrecursorInfo,
+ doPrecursorDeconvolution: doPrecursorDeconvolution,
taskDescriptor: OutputFileNameTextBox.Text != "" ? OutputFileNameTextBox.Text : "GPTMDTask",
maxThreadsToUsePerFile: parseMaxThreadsPerFile ? int.Parse(MaxThreadsTextBox.Text, CultureInfo.InvariantCulture) : new CommonParameters().MaxThreadsToUsePerFile,
digestionParams: new DigestionParams(
@@ -468,7 +474,9 @@ private void SaveButton_Click(object sender, RoutedEventArgs e)
assumeOrphanPeaksAreZ1Fragments: protease.Name != "top-down",
addCompIons: AddCompIonCheckBox.IsChecked.Value,
minVariantDepth: minVariantDepth,
- maxHeterozygousVariants: maxHeterozygousVariants);
+ maxHeterozygousVariants: maxHeterozygousVariants,
+ precursorDeconParams: precursorDeconvolutionParameters,
+ productDeconParams: productDeconvolutionParameters);
TheTask.GptmdParameters.ListOfModsGptmd = new List<(string, string)>();
foreach (var heh in GptmdModTypeForTreeViewObservableCollection)
diff --git a/MetaMorpheus/GUI/TaskWindows/GlycoSearchTaskWindow.xaml b/MetaMorpheus/GUI/TaskWindows/GlycoSearchTaskWindow.xaml
index 7be5c8b7d..5e546dc80 100644
--- a/MetaMorpheus/GUI/TaskWindows/GlycoSearchTaskWindow.xaml
+++ b/MetaMorpheus/GUI/TaskWindows/GlycoSearchTaskWindow.xaml
@@ -159,20 +159,7 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
diff --git a/MetaMorpheus/GUI/TaskWindows/GlycoSearchTaskWindow.xaml.cs b/MetaMorpheus/GUI/TaskWindows/GlycoSearchTaskWindow.xaml.cs
index e63556f94..59034fe9c 100644
--- a/MetaMorpheus/GUI/TaskWindows/GlycoSearchTaskWindow.xaml.cs
+++ b/MetaMorpheus/GUI/TaskWindows/GlycoSearchTaskWindow.xaml.cs
@@ -29,6 +29,7 @@ public partial class GlycoSearchTaskWindow : Window
private readonly ObservableCollection FixedModTypeForTreeViewObservableCollection = new ObservableCollection();
private readonly ObservableCollection VariableModTypeForTreeViewObservableCollection = new ObservableCollection();
private CustomFragmentationWindow CustomFragmentationWindow;
+ private DeconHostViewModel DeconHostViewModel;
public GlycoSearchTaskWindow() : this(null)
{
@@ -40,6 +41,7 @@ public GlycoSearchTaskWindow(GlycoSearchTask task)
PopulateChoices();
TheTask = task ?? new GlycoSearchTask();
UpdateFieldsFromTask(TheTask);
+ DeisotopingControl.DataContext = DeconHostViewModel;
if (task == null)
{
@@ -159,8 +161,9 @@ private void UpdateFieldsFromTask(GlycoSearchTask task)
CheckBoxDecoy.IsChecked = task._glycoSearchParameters.DecoyType != DecoyType.None;
RadioButtonReverseDecoy.IsChecked = task._glycoSearchParameters.DecoyType == DecoyType.Reverse;
RadioButtonSlideDecoy.IsChecked = task._glycoSearchParameters.DecoyType == DecoyType.Slide;
- deconvolutePrecursors.IsChecked = task.CommonParameters.DoPrecursorDeconvolution;
- useProvidedPrecursor.IsChecked = task.CommonParameters.UseProvidedPrecursorInfo;
+ DeconHostViewModel = new DeconHostViewModel(TheTask.CommonParameters.PrecursorDeconvolutionParameters,
+ TheTask.CommonParameters.ProductDeconvolutionParameters,
+ TheTask.CommonParameters.UseProvidedPrecursorInfo, TheTask.CommonParameters.DoPrecursorDeconvolution);
missedCleavagesTextBox.Text = task.CommonParameters.DigestionParams.MaxMissedCleavages.ToString(CultureInfo.InvariantCulture);
MinPeptideLengthTextBox.Text = task.CommonParameters.DigestionParams.MinPeptideLength.ToString(CultureInfo.InvariantCulture);
MaxPeptideLengthTextBox.Text = task.CommonParameters.DigestionParams.MaxPeptideLength == int.MaxValue ? "" : task.CommonParameters.DigestionParams.MaxPeptideLength.ToString(CultureInfo.InvariantCulture);
@@ -243,7 +246,7 @@ private void SaveButton_Click(object sender, RoutedEventArgs e)
if (!GlobalGuiSettings.CheckTaskSettingsValidity(PrecusorMsTlTextBox.Text, productMassToleranceTextBox.Text, missedCleavagesTextBox.Text,
maxModificationIsoformsTextBox.Text, MinPeptideLengthTextBox.Text, MaxPeptideLengthTextBox.Text, maxThreadsTextBox.Text, minScoreAllowed.Text,
- fieldNotUsed, fieldNotUsed, fieldNotUsed, TopNPeaksTextBox.Text, MinRatioTextBox.Text, null, null, numberOfDatabaseSearchesTextBox.Text, TxtBoxMaxModPerPep.Text,
+ fieldNotUsed, fieldNotUsed, DeconHostViewModel.PrecursorDeconvolutionParameters.MaxAssumedChargeState.ToString(), TopNPeaksTextBox.Text, MinRatioTextBox.Text, null, null, numberOfDatabaseSearchesTextBox.Text, TxtBoxMaxModPerPep.Text,
fieldNotUsed, null, null, null))
{
return;
@@ -369,12 +372,17 @@ private void SaveButton_Click(object sender, RoutedEventArgs e)
listOfModsFixed.AddRange(heh.Children.Where(b => b.Use).Select(b => (b.Parent.DisplayName, b.ModName)));
}
+ DeconvolutionParameters precursorDeconvolutionParameters = DeconHostViewModel.PrecursorDeconvolutionParameters.Parameters;
+ DeconvolutionParameters productDeconvolutionParameters = DeconHostViewModel.ProductDeconvolutionParameters.Parameters;
+ bool useProvidedPrecursorInfo = DeconHostViewModel.UseProvidedPrecursors;
+ bool doPrecursorDeconvolution = DeconHostViewModel.DoPrecursorDeconvolution;
+
CommonParameters commonParamsToSave = new CommonParameters(
precursorMassTolerance: PrecursorMassTolerance,
taskDescriptor: OutputFileNameTextBox.Text != "" ? OutputFileNameTextBox.Text : "GlycoSearchTask",
productMassTolerance: ProductMassTolerance,
- doPrecursorDeconvolution: deconvolutePrecursors.IsChecked.Value,
- useProvidedPrecursorInfo: useProvidedPrecursor.IsChecked.Value,
+ doPrecursorDeconvolution: doPrecursorDeconvolution,
+ useProvidedPrecursorInfo: useProvidedPrecursorInfo,
digestionParams: digestionParamsToSave,
trimMs1Peaks: trimMs1.IsChecked.Value,
trimMsMsPeaks: trimMsMs.IsChecked.Value,
@@ -387,7 +395,9 @@ private void SaveButton_Click(object sender, RoutedEventArgs e)
maxThreadsToUsePerFile: int.Parse(maxThreadsTextBox.Text, CultureInfo.InvariantCulture),
listOfModsVariable: listOfModsVariable,
listOfModsFixed: listOfModsFixed,
- assumeOrphanPeaksAreZ1Fragments: protease.Name != "top-down");
+ assumeOrphanPeaksAreZ1Fragments: protease.Name != "top-down",
+ precursorDeconParams: precursorDeconvolutionParameters,
+ productDeconParams: productDeconvolutionParameters);
TheTask.CommonParameters = commonParamsToSave;
diff --git a/MetaMorpheus/GUI/TaskWindows/SearchTaskWindow.xaml b/MetaMorpheus/GUI/TaskWindows/SearchTaskWindow.xaml
index 98514670c..3b0914ecf 100644
--- a/MetaMorpheus/GUI/TaskWindows/SearchTaskWindow.xaml
+++ b/MetaMorpheus/GUI/TaskWindows/SearchTaskWindow.xaml
@@ -661,41 +661,7 @@
-
-
-
-
-
-
- Use the charge states and precursor masses determined by the instrument controller.
-
-
-
-
-
-
-
-
-
-
- Additionally searches for coisolated peptides, allowing for multiple peptides to be identified from a single MS2.
-
-
-
-
-
-
-
-
-
-
- The maximum charge state that deconvolution should allow. Minimum is 1.
-
-
-
-
-
-
+
diff --git a/MetaMorpheus/GUI/TaskWindows/SearchTaskWindow.xaml.cs b/MetaMorpheus/GUI/TaskWindows/SearchTaskWindow.xaml.cs
index 1767492b3..124ceebd5 100644
--- a/MetaMorpheus/GUI/TaskWindows/SearchTaskWindow.xaml.cs
+++ b/MetaMorpheus/GUI/TaskWindows/SearchTaskWindow.xaml.cs
@@ -39,6 +39,7 @@ public partial class SearchTaskWindow : Window
private bool AutomaticallyAskAndOrUpdateParametersBasedOnProtease = true;
private CustomFragmentationWindow CustomFragmentationWindow;
private string _defaultMultiplexType = "TMT10";
+ private DeconHostViewModel DeconHostViewModel;
internal SearchTask TheTask { get; private set; }
@@ -51,6 +52,7 @@ public SearchTaskWindow(SearchTask task)
PopulateChoices();
UpdateFieldsFromTask(TheTask);
AutomaticallyAskAndOrUpdateParametersBasedOnProtease = true;
+ DeisotopingControl.DataContext = DeconHostViewModel;
if (task == null)
{
@@ -285,18 +287,19 @@ private void UpdateFieldsFromTask(SearchTask task)
PrecursorMassToleranceComboBox.SelectedIndex = task.CommonParameters.PrecursorMassTolerance is AbsoluteTolerance ? 0 : 1;
AddCompIonCheckBox.IsChecked = task.CommonParameters.AddCompIons;
NumberOfDatabaseSearchesTextBox.Text = task.CommonParameters.TotalPartitions.ToString(CultureInfo.InvariantCulture);
- DeconvolutePrecursors.IsChecked = task.CommonParameters.DoPrecursorDeconvolution;
- UseProvidedPrecursor.IsChecked = task.CommonParameters.UseProvidedPrecursorInfo;
RemoveContaminantRadioBox.IsChecked = task.SearchParameters.TCAmbiguity == TargetContaminantAmbiguity.RemoveContaminant;
RemoveTargetRadioBox.IsChecked = task.SearchParameters.TCAmbiguity == TargetContaminantAmbiguity.RemoveTarget;
RenameTCProteinsRadioBox.IsChecked = task.SearchParameters.TCAmbiguity == TargetContaminantAmbiguity.RenameProtein;
AllAmbiguity.IsChecked = task.CommonParameters.ReportAllAmbiguity;
- DeconvolutionMaxAssumedChargeStateTextBox.Text = task.CommonParameters.DeconvolutionMaxAssumedChargeState.ToString();
MinScoreAllowed.Text = task.CommonParameters.ScoreCutoff.ToString(CultureInfo.InvariantCulture);
TrimMs1.IsChecked = task.CommonParameters.TrimMs1Peaks;
TrimMsMs.IsChecked = task.CommonParameters.TrimMsMsPeaks;
AddTruncationsCheckBox.IsChecked = task.CommonParameters.AddTruncations;
+ DeconHostViewModel = new DeconHostViewModel(TheTask.CommonParameters.PrecursorDeconvolutionParameters,
+ TheTask.CommonParameters.ProductDeconvolutionParameters,
+ TheTask.CommonParameters.UseProvidedPrecursorInfo, TheTask.CommonParameters.DoPrecursorDeconvolution);
+
NumberOfPeaksToKeepPerWindowTextBox.Text = task.CommonParameters.NumberOfPeaksToKeepPerWindow == int.MaxValue || !task.CommonParameters.NumberOfPeaksToKeepPerWindow.HasValue ? "" : task.CommonParameters.NumberOfPeaksToKeepPerWindow.Value.ToString(CultureInfo.InvariantCulture);
MinimumAllowedIntensityRatioToBasePeakTexBox.Text = task.CommonParameters.MinimumAllowedIntensityRatioToBasePeak == double.MaxValue || !task.CommonParameters.MinimumAllowedIntensityRatioToBasePeak.HasValue ? "" : task.CommonParameters.MinimumAllowedIntensityRatioToBasePeak.Value.ToString(CultureInfo.InvariantCulture);
WindowWidthThomsonsTextBox.Text = task.CommonParameters.WindowWidthThomsons == double.MaxValue || !task.CommonParameters.WindowWidthThomsons.HasValue ? "" : task.CommonParameters.WindowWidthThomsons.Value.ToString(CultureInfo.InvariantCulture);
@@ -425,6 +428,7 @@ private void SaveButton_Click(object sender, RoutedEventArgs e)
CleavageSpecificity searchModeType = GetSearchModeType(); //change search type to semi or non if selected
SnesUpdates(searchModeType); //decide on singleN/C, make comp ion changes
+ // TODO: Reconcile Isodec params with Mass difference acceptor
if (!GlobalGuiSettings.CheckTaskSettingsValidity(
PrecursorMassToleranceTextBox.Text,
ProductMassToleranceTextBox.Text,
@@ -436,7 +440,7 @@ private void SaveButton_Click(object sender, RoutedEventArgs e)
MinScoreAllowed.Text,
PeakFindingToleranceTextBox.Text,
HistogramBinWidthTextBox.Text,
- DeconvolutionMaxAssumedChargeStateTextBox.Text,
+ DeconHostViewModel.PrecursorDeconvolutionParameters.MaxAssumedChargeState.ToString(),
NumberOfPeaksToKeepPerWindowTextBox.Text,
MinimumAllowedIntensityRatioToBasePeakTexBox.Text,
WindowWidthThomsonsTextBox.Text,
@@ -567,14 +571,19 @@ private void SaveButton_Click(object sender, RoutedEventArgs e)
bool parseMaxThreadsPerFile = !MaxThreadsTextBox.Text.Equals("") && (int.Parse(MaxThreadsTextBox.Text) <= Environment.ProcessorCount && int.Parse(MaxThreadsTextBox.Text) > 0);
+
+ DeconvolutionParameters precursorDeconvolutionParameters = DeconHostViewModel.PrecursorDeconvolutionParameters.Parameters;
+ DeconvolutionParameters productDeconvolutionParameters = DeconHostViewModel.ProductDeconvolutionParameters.Parameters;
+ bool useProvidedPrecursorInfo = DeconHostViewModel.UseProvidedPrecursors;
+ bool doPrecursorDeconvolution = DeconHostViewModel.DoPrecursorDeconvolution;
+
CommonParameters commonParamsToSave = new CommonParameters(
taskDescriptor: OutputFileNameTextBox.Text != "" ? OutputFileNameTextBox.Text : "SearchTask",
maxThreadsToUsePerFile: parseMaxThreadsPerFile ? int.Parse(MaxThreadsTextBox.Text, CultureInfo.InvariantCulture) : new CommonParameters().MaxThreadsToUsePerFile,
reportAllAmbiguity: AllAmbiguity.IsChecked.Value,
- deconvolutionMaxAssumedChargeState: int.Parse(DeconvolutionMaxAssumedChargeStateTextBox.Text, CultureInfo.InvariantCulture),
totalPartitions: int.Parse(NumberOfDatabaseSearchesTextBox.Text, CultureInfo.InvariantCulture),
- doPrecursorDeconvolution: DeconvolutePrecursors.IsChecked.Value,
- useProvidedPrecursorInfo: UseProvidedPrecursor.IsChecked.Value,
+ doPrecursorDeconvolution: doPrecursorDeconvolution,
+ useProvidedPrecursorInfo: useProvidedPrecursorInfo,
qValueThreshold: !PepQValueThresholdCheckbox.IsChecked.Value ? double.Parse(QValueThresholdTextBox.Text, CultureInfo.InvariantCulture) : 1.0,
pepQValueThreshold: PepQValueThresholdCheckbox.IsChecked.Value ? double.Parse(PepQValueThresholdTextBox.Text, CultureInfo.InvariantCulture) : 1.0,
scoreCutoff: double.Parse(MinScoreAllowed.Text, CultureInfo.InvariantCulture),
@@ -596,7 +605,9 @@ private void SaveButton_Click(object sender, RoutedEventArgs e)
addCompIons: AddCompIonCheckBox.IsChecked.Value,
assumeOrphanPeaksAreZ1Fragments: protease.Name != "top-down",
minVariantDepth: MinVariantDepth,
- maxHeterozygousVariants: MaxHeterozygousVariants);
+ maxHeterozygousVariants: MaxHeterozygousVariants,
+ precursorDeconParams: precursorDeconvolutionParameters,
+ productDeconParams: productDeconvolutionParameters);
if (ClassicSearchRadioButton.IsChecked.Value)
{
@@ -880,8 +891,8 @@ private void ProteaseSpecificUpdate(object sender, SelectionChangedEventArgs e)
case "top-down":
if (UpdateGUISettings.UseTopDownRecommendedSettings())
{
- UseProvidedPrecursor.IsChecked = false;
- DeconvolutionMaxAssumedChargeStateTextBox.Text = "60";
+ DeconHostViewModel.DoPrecursorDeconvolution = true;
+ DeconHostViewModel.PrecursorDeconvolutionParameters.MaxAssumedChargeState = 60;
TrimMsMs.IsChecked = false;
CheckBoxNoQuant.IsChecked = true;
MassDiffAccept3mm.IsChecked = true;
diff --git a/MetaMorpheus/GUI/TaskWindows/XLSearchTaskWindow.xaml b/MetaMorpheus/GUI/TaskWindows/XLSearchTaskWindow.xaml
index 81de1944f..9de85d76b 100644
--- a/MetaMorpheus/GUI/TaskWindows/XLSearchTaskWindow.xaml
+++ b/MetaMorpheus/GUI/TaskWindows/XLSearchTaskWindow.xaml
@@ -147,20 +147,7 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
diff --git a/MetaMorpheus/GUI/TaskWindows/XLSearchTaskWindow.xaml.cs b/MetaMorpheus/GUI/TaskWindows/XLSearchTaskWindow.xaml.cs
index 42eac5f43..47c07d2cb 100644
--- a/MetaMorpheus/GUI/TaskWindows/XLSearchTaskWindow.xaml.cs
+++ b/MetaMorpheus/GUI/TaskWindows/XLSearchTaskWindow.xaml.cs
@@ -29,6 +29,7 @@ public partial class XLSearchTaskWindow : Window
private readonly ObservableCollection FixedModTypeForTreeViewObservableCollection = new ObservableCollection();
private readonly ObservableCollection VariableModTypeForTreeViewObservableCollection = new ObservableCollection();
private CustomFragmentationWindow CustomFragmentationWindow;
+ private DeconHostViewModel DeconHostViewModel;
public XLSearchTaskWindow(XLSearchTask task)
{
@@ -36,6 +37,7 @@ public XLSearchTaskWindow(XLSearchTask task)
PopulateChoices();
TheTask = task ?? new XLSearchTask();
UpdateFieldsFromTask(TheTask);
+ DeisotopingControl.DataContext = DeconHostViewModel;
if (task == null)
{
@@ -150,8 +152,9 @@ private void UpdateFieldsFromTask(XLSearchTask task)
}
checkBoxDecoy.IsChecked = task.XlSearchParameters.DecoyType != DecoyType.None;
- deconvolutePrecursors.IsChecked = task.CommonParameters.DoPrecursorDeconvolution;
- useProvidedPrecursor.IsChecked = task.CommonParameters.UseProvidedPrecursorInfo;
+ DeconHostViewModel = new DeconHostViewModel(TheTask.CommonParameters.PrecursorDeconvolutionParameters,
+ TheTask.CommonParameters.ProductDeconvolutionParameters,
+ TheTask.CommonParameters.UseProvidedPrecursorInfo, TheTask.CommonParameters.DoPrecursorDeconvolution);
missedCleavagesTextBox.Text = task.CommonParameters.DigestionParams.MaxMissedCleavages.ToString(CultureInfo.InvariantCulture);
MinPeptideLengthTextBox.Text = task.CommonParameters.DigestionParams.MinPeptideLength.ToString(CultureInfo.InvariantCulture);
MaxPeptideLengthTextBox.Text = task.CommonParameters.DigestionParams.MaxPeptideLength == int.MaxValue ? "" : task.CommonParameters.DigestionParams.MaxPeptideLength.ToString(CultureInfo.InvariantCulture);
@@ -235,7 +238,7 @@ private void SaveButton_Click(object sender, RoutedEventArgs e)
if (!GlobalGuiSettings.CheckTaskSettingsValidity(XLPrecusorMsTlTextBox.Text, productMassToleranceTextBox.Text, missedCleavagesTextBox.Text,
maxModificationIsoformsTextBox.Text, MinPeptideLengthTextBox.Text, MaxPeptideLengthTextBox.Text, maxThreadsTextBox.Text, minScoreAllowed.Text,
- fieldNotUsed, fieldNotUsed, fieldNotUsed, TopNPeaksTextBox.Text, MinRatioTextBox.Text, null, null, numberOfDatabaseSearchesTextBox.Text,
+ fieldNotUsed, fieldNotUsed, DeconHostViewModel.PrecursorDeconvolutionParameters.MaxAssumedChargeState.ToString(), TopNPeaksTextBox.Text, MinRatioTextBox.Text, null, null, numberOfDatabaseSearchesTextBox.Text,
fieldNotUsed, fieldNotUsed, null, null, null))
{
return;
@@ -317,12 +320,17 @@ private void SaveButton_Click(object sender, RoutedEventArgs e)
}
bool _addCompIons = ckbAddCompIon.IsChecked.Value;
+ DeconvolutionParameters precursorDeconvolutionParameters = DeconHostViewModel.PrecursorDeconvolutionParameters.Parameters;
+ DeconvolutionParameters productDeconvolutionParameters = DeconHostViewModel.ProductDeconvolutionParameters.Parameters;
+ bool useProvidedPrecursorInfo = DeconHostViewModel.UseProvidedPrecursors;
+ bool doPrecursorDeconvolution = DeconHostViewModel.DoPrecursorDeconvolution;
+
CommonParameters commonParamsToSave = new CommonParameters(
precursorMassTolerance: PrecursorMassTolerance,
taskDescriptor: OutputFileNameTextBox.Text != "" ? OutputFileNameTextBox.Text : "XLSearchTask",
productMassTolerance: ProductMassTolerance,
- doPrecursorDeconvolution: deconvolutePrecursors.IsChecked.Value,
- useProvidedPrecursorInfo: useProvidedPrecursor.IsChecked.Value,
+ doPrecursorDeconvolution: doPrecursorDeconvolution,
+ useProvidedPrecursorInfo: useProvidedPrecursorInfo,
digestionParams: digestionParamsToSave,
trimMs1Peaks: trimMs1.IsChecked.Value,
trimMsMsPeaks: trimMsMs.IsChecked.Value,
@@ -338,7 +346,9 @@ private void SaveButton_Click(object sender, RoutedEventArgs e)
totalPartitions: int.Parse(numberOfDatabaseSearchesTextBox.Text, CultureInfo.InvariantCulture),
listOfModsVariable: listOfModsVariable,
listOfModsFixed: listOfModsFixed,
- assumeOrphanPeaksAreZ1Fragments: protease.Name != "top-down");
+ assumeOrphanPeaksAreZ1Fragments: protease.Name != "top-down",
+ precursorDeconParams: precursorDeconvolutionParameters,
+ productDeconParams: productDeconvolutionParameters);
TheTask.CommonParameters = commonParamsToSave;
diff --git a/MetaMorpheus/GUI/Util/Converters/DeconvolutionTypeToControlConverter.cs b/MetaMorpheus/GUI/Util/Converters/DeconvolutionTypeToControlConverter.cs
new file mode 100644
index 000000000..1daf97137
--- /dev/null
+++ b/MetaMorpheus/GUI/Util/Converters/DeconvolutionTypeToControlConverter.cs
@@ -0,0 +1,53 @@
+using System;
+using System.Globalization;
+using GuiFunctions;
+using MassSpectrometry;
+
+namespace MetaMorpheusGUI
+{
+ ///
+ /// Converts a DeconvolutionType to a corresponding control.
+ ///
+ public class DeconvolutionTypeToControlConverter : BaseValueConverter
+ {
+ ///
+ /// Converts a DeconvolutionType to a corresponding control.
+ ///
+ /// The value to convert, expected to be of type DeconParamsViewModel.
+ /// The type of the target property.
+ /// Optional parameter to be used in the converter logic.
+ /// The culture to use in the converter.
+ /// A control corresponding to the DeconvolutionType.
+ /// Thrown when the value is not of type DeconParamsViewModel or the DeconvolutionType is invalid.
+ public override object Convert(object value, Type targetType, object parameter, CultureInfo culture)
+ {
+ // Assuming value is of an enum type DeconvolutionType
+ if (value is not DeconParamsViewModel viewModel)
+ throw new ArgumentException("Invalid value type", nameof(value));
+
+ switch (viewModel.DeconvolutionType)
+ {
+ case DeconvolutionType.ClassicDeconvolution:
+ return new ClassicDeconParamsControl() { DataContext = value as ClassicDeconParamsViewModel };
+
+ case DeconvolutionType.ExampleNewDeconvolutionTemplate:
+ default:
+ throw new ArgumentException("Invalid DeconvolutionType", nameof(value));
+ }
+ }
+
+ ///
+ /// Converts a value back to its source type. Not implemented.
+ ///
+ /// The value produced by the binding target.
+ /// The type to convert to.
+ /// Optional parameter to be used in the converter logic.
+ /// The culture to use in the converter.
+ /// Throws NotImplementedException.
+ /// Always thrown as this method is not implemented.
+ public override object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
+ {
+ throw new NotImplementedException();
+ }
+ }
+}
diff --git a/MetaMorpheus/GUI/Views/Deconvolution/ClassicDeconParamsControl.xaml b/MetaMorpheus/GUI/Views/Deconvolution/ClassicDeconParamsControl.xaml
new file mode 100644
index 000000000..dcd2e62ba
--- /dev/null
+++ b/MetaMorpheus/GUI/Views/Deconvolution/ClassicDeconParamsControl.xaml
@@ -0,0 +1,40 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ The maximum charge state that deconvolution should allow. Minimum is 1 for positive mode and -1 for negative mode.
+
+
+
+
+
+
+
+
+ The minimum charge state that deconvolution should allow.
+
+
+
+
+
diff --git a/MetaMorpheus/GUI/Views/Deconvolution/ClassicDeconParamsControl.xaml.cs b/MetaMorpheus/GUI/Views/Deconvolution/ClassicDeconParamsControl.xaml.cs
new file mode 100644
index 000000000..c866b44c9
--- /dev/null
+++ b/MetaMorpheus/GUI/Views/Deconvolution/ClassicDeconParamsControl.xaml.cs
@@ -0,0 +1,15 @@
+using System.Windows.Controls;
+
+namespace MetaMorpheusGUI
+{
+ ///
+ /// Interaction logic for ClassicDeconParamsControl.xaml
+ ///
+ public partial class ClassicDeconParamsControl : UserControl
+ {
+ public ClassicDeconParamsControl()
+ {
+ InitializeComponent();
+ }
+ }
+}
diff --git a/MetaMorpheus/GUI/Views/Deconvolution/HostDeconParamControl.xaml b/MetaMorpheus/GUI/Views/Deconvolution/HostDeconParamControl.xaml
new file mode 100644
index 000000000..ca2a2f1fe
--- /dev/null
+++ b/MetaMorpheus/GUI/Views/Deconvolution/HostDeconParamControl.xaml
@@ -0,0 +1,112 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Use the charge states and precursor masses determined by the instrument controller.
+
+
+
+
+
+
+
+
+
+
+ Additionally searches for coisolated peptides, allowing for multiple peptides to be identified from a single MS2.
+
+
+
+
+
+
+
+
+
+
+ The type of deconvolution to perform.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/MetaMorpheus/GUI/Views/Deconvolution/HostDeconParamControl.xaml.cs b/MetaMorpheus/GUI/Views/Deconvolution/HostDeconParamControl.xaml.cs
new file mode 100644
index 000000000..3c4c7f862
--- /dev/null
+++ b/MetaMorpheus/GUI/Views/Deconvolution/HostDeconParamControl.xaml.cs
@@ -0,0 +1,15 @@
+using System.Windows.Controls;
+
+namespace MetaMorpheusGUI
+{
+ ///
+ /// Interaction logic for HostDeconParamControl.xaml
+ ///
+ public partial class HostDeconParamControl : UserControl
+ {
+ public HostDeconParamControl()
+ {
+ InitializeComponent();
+ }
+ }
+}
diff --git a/MetaMorpheus/GuiFunctions/GuiFunctions.csproj b/MetaMorpheus/GuiFunctions/GuiFunctions.csproj
index e18966830..3eafcfea2 100644
--- a/MetaMorpheus/GuiFunctions/GuiFunctions.csproj
+++ b/MetaMorpheus/GuiFunctions/GuiFunctions.csproj
@@ -16,7 +16,7 @@
-
+
diff --git a/MetaMorpheus/GuiFunctions/MetaDraw/DrawnSequence.cs b/MetaMorpheus/GuiFunctions/MetaDraw/DrawnSequence.cs
index 1dfb9f5fa..11009fb7d 100644
--- a/MetaMorpheus/GuiFunctions/MetaDraw/DrawnSequence.cs
+++ b/MetaMorpheus/GuiFunctions/MetaDraw/DrawnSequence.cs
@@ -381,25 +381,26 @@ public static void ClearCanvas(Canvas cav)
public static SolidColorBrush ParseColorBrushFromOxyColor(OxyColor color)
{
- var colorVal = color.ToByteString().Split(',');
- return new SolidColorBrush(System.Windows.Media.Color.FromArgb(Byte.Parse(colorVal[0]), Byte.Parse(colorVal[1]), Byte.Parse(colorVal[2]), Byte.Parse(colorVal[3])));
+ return new SolidColorBrush(Color.FromArgb(color.A, color.R, color.G, color.B));
}
public static SolidColorBrush ParseColorBrushFromName(string name)
{
- OxyColor color = MetaDrawSettings.PossibleColors.Keys.Where(p => p.GetColorName().Equals(name.Replace(" ", ""))).First();
- return ParseColorBrushFromOxyColor(color);
+ string cleanedName = name.Replace(" ", "");
+ var foundColor = MetaDrawSettings.PossibleColors.FirstOrDefault(p => p.Value == cleanedName).Key;
+ return ParseColorBrushFromOxyColor(foundColor == default ? MetaDrawSettings.FallbackColor : foundColor);
}
public static OxyColor ParseOxyColorFromName(string name)
{
- return MetaDrawSettings.PossibleColors.Keys.Where(p => p.GetColorName().Equals(name.Replace(" ", ""))).First();
+ string cleanedName = name.Replace(" ", "");
+ var foundColor = MetaDrawSettings.PossibleColors.FirstOrDefault(p => p.Value == cleanedName).Key;
+ return foundColor == default ? MetaDrawSettings.FallbackColor : foundColor;
}
public static Color ParseColorFromOxyColor(OxyColor color)
{
- var colorVal = color.ToByteString().Split(',');
- return System.Windows.Media.Color.FromArgb(Byte.Parse(colorVal[0]), Byte.Parse(colorVal[1]), Byte.Parse(colorVal[2]), Byte.Parse(colorVal[3]));
+ return Color.FromArgb(color.A, color.R, color.G, color.B);
}
///
diff --git a/MetaMorpheus/GuiFunctions/MetaDraw/MetaDrawSettings.cs b/MetaMorpheus/GuiFunctions/MetaDraw/MetaDrawSettings.cs
index a38b939b7..e6607cd0f 100644
--- a/MetaMorpheus/GuiFunctions/MetaDraw/MetaDrawSettings.cs
+++ b/MetaMorpheus/GuiFunctions/MetaDraw/MetaDrawSettings.cs
@@ -37,6 +37,7 @@ public static class MetaDrawSettings
public static bool AnnotationBold { get; set; } = false;
public static bool DisplayInternalIons { get; set; } = true;
public static bool DisplayInternalIonAnnotations { get; set; }= true;
+ public static OxyColor FallbackColor { get; } = OxyColors.Aqua;
public static Dictionary PossibleColors { get; set; }
public static Dictionary ProductTypeToColor { get; set; }
public static Dictionary BetaProductTypeToColor { get; set; }
diff --git a/MetaMorpheus/GuiFunctions/MzLibExtensions.cs b/MetaMorpheus/GuiFunctions/MzLibExtensions.cs
new file mode 100644
index 000000000..07fc8fc60
--- /dev/null
+++ b/MetaMorpheus/GuiFunctions/MzLibExtensions.cs
@@ -0,0 +1,36 @@
+using System;
+using MassSpectrometry;
+
+namespace GuiFunctions
+{
+ ///
+ /// Provides additional functionality for the MzLib library.
+ ///
+ public static class MzLibExtensions
+ {
+
+ ///
+ /// Converts the given to a .
+ ///
+ /// The deconvolution parameters to convert.
+ /// A representing the given parameters.
+ ///
+ /// Thrown when the type of is not supported.
+ ///
+ public static DeconParamsViewModel ToViewModel(this DeconvolutionParameters parameters)
+ {
+ if (parameters is ClassicDeconvolutionParameters classicParams)
+ {
+ return new ClassicDeconParamsViewModel(classicParams);
+ }
+ //else if (parameters is IsoDeconvolutionParameters isoParams)
+ //{
+ // return new IsoDecDeconParamsViewModel(isoParams);
+ //}
+ else
+ {
+ throw new NotImplementedException();
+ }
+ }
+ }
+}
diff --git a/MetaMorpheus/GuiFunctions/ViewModels/CoverageTypeForTreeViewModel.cs b/MetaMorpheus/GuiFunctions/ViewModels/CoverageTypeForTreeViewModel.cs
index 72914c988..5ecee4abb 100644
--- a/MetaMorpheus/GuiFunctions/ViewModels/CoverageTypeForTreeViewModel.cs
+++ b/MetaMorpheus/GuiFunctions/ViewModels/CoverageTypeForTreeViewModel.cs
@@ -51,7 +51,7 @@ public CoverageTypeForTreeViewModel(string name)
{
Name = name;
OxyColor color = MetaDrawSettings.CoverageTypeToColor[name];
- SelectedColor = AddSpaces(color.GetColorName());
+ SelectedColor = AddSpaces(MetaDrawSettings.PossibleColors[color]);
ColorBrush = DrawnSequence.ParseColorBrushFromOxyColor(color);
}
diff --git a/MetaMorpheus/GuiFunctions/ViewModels/Deconvolution/ClassicDeconParamsViewModel.cs b/MetaMorpheus/GuiFunctions/ViewModels/Deconvolution/ClassicDeconParamsViewModel.cs
new file mode 100644
index 000000000..87374963f
--- /dev/null
+++ b/MetaMorpheus/GuiFunctions/ViewModels/Deconvolution/ClassicDeconParamsViewModel.cs
@@ -0,0 +1,44 @@
+using MassSpectrometry;
+
+namespace GuiFunctions;
+
+public sealed class ClassicDeconParamsViewModel : DeconParamsViewModel
+{
+ private ClassicDeconvolutionParameters _parameters;
+ public override DeconvolutionParameters Parameters
+ {
+ get => _parameters;
+ protected set
+ {
+ _parameters = (ClassicDeconvolutionParameters)value;
+ OnPropertyChanged(nameof(Parameters));
+ }
+ }
+
+ public ClassicDeconParamsViewModel(ClassicDeconvolutionParameters parameters)
+ {
+ Parameters = parameters;
+ }
+
+ public double DeconvolutionTolerancePpm
+ {
+ get => _parameters.DeconvolutionTolerancePpm;
+ set
+ {
+ _parameters.DeconvolutionTolerancePpm = value;
+ OnPropertyChanged(nameof(DeconvolutionTolerancePpm));
+ }
+ }
+
+ public double IntensityRatioLimit
+ {
+ get => _parameters.IntensityRatioLimit;
+ set
+ {
+ _parameters.IntensityRatioLimit = value;
+ OnPropertyChanged(nameof(IntensityRatioLimit));
+ }
+ }
+
+ public override string ToString() => "Classic";
+}
\ No newline at end of file
diff --git a/MetaMorpheus/GuiFunctions/ViewModels/Deconvolution/DeconHostViewModel.cs b/MetaMorpheus/GuiFunctions/ViewModels/Deconvolution/DeconHostViewModel.cs
new file mode 100644
index 000000000..411f572c7
--- /dev/null
+++ b/MetaMorpheus/GuiFunctions/ViewModels/Deconvolution/DeconHostViewModel.cs
@@ -0,0 +1,188 @@
+#nullable enable
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Diagnostics.CodeAnalysis;
+using System.Linq;
+using Easy.Common.Extensions;
+using EngineLayer;
+using MassSpectrometry;
+
+namespace GuiFunctions;
+
+///
+/// This class holds all of the information in the Deconvolution tab of the GUI
+/// One instance will be create per Task Window
+///
+/// The Task window will populate this view model with the appropriate parameters from
+/// The user can then modify these parameters as needed via the gui
+/// The Task window will use the PrecursorDeconvolutionParameters and teh ProductDeconvolutionParameters to create a new object
+///
+public class DeconHostViewModel : BaseViewModel
+{
+ ///
+ /// This is where default deconvolution parameters are set for GUI display
+ ///
+ /// precursor params to display first
+ /// product params to display first
+ ///
+ ///
+ ///
+ public DeconHostViewModel(DeconvolutionParameters? initialPrecursorParameters = null, DeconvolutionParameters? initialProductParameters = null,
+ bool useProvidedPrecursor = false, bool deconvolutePrecursors = true)
+ {
+ UseProvidedPrecursors = useProvidedPrecursor;
+ DoPrecursorDeconvolution = deconvolutePrecursors;
+
+ // Order matters here, construct the lists before setting the selected parameters
+ PrecursorDeconvolutionParametersList = new ObservableCollection();
+ ProductDeconvolutionParametersList = new ObservableCollection();
+
+ // populate the lists by adding the default parameters for each deconvolution type or the provided parameters
+ foreach (var deconType in Enum.GetValues())
+ {
+ switch (deconType)
+ {
+ case DeconvolutionType.ExampleNewDeconvolutionTemplate:
+ continue;
+
+ case DeconvolutionType.ClassicDeconvolution:
+
+ if (initialPrecursorParameters is { DeconvolutionType: DeconvolutionType.ClassicDeconvolution })
+ PrecursorDeconvolutionParametersList.Add(initialPrecursorParameters.ToViewModel());
+ else
+ {
+ var toAdd = GlobalVariables.AnalyteType switch
+ {
+ AnalyteType.Peptide => new ClassicDeconvolutionParameters(1, 12, 4, 3),
+ AnalyteType.Proteoform => new ClassicDeconvolutionParameters(1, 60, 4, 3),
+ AnalyteType.Oligo => new ClassicDeconvolutionParameters(-20, -1, 4, 3),
+ _ => throw new ArgumentOutOfRangeException()
+ };
+ PrecursorDeconvolutionParametersList.Add(toAdd.ToViewModel());
+ }
+
+ if (initialProductParameters is { DeconvolutionType: DeconvolutionType.ClassicDeconvolution })
+ ProductDeconvolutionParametersList.Add(initialProductParameters.ToViewModel());
+ else
+ {
+ var toAdd = GlobalVariables.AnalyteType switch
+ {
+ AnalyteType.Peptide => new ClassicDeconvolutionParameters(1, 10, 4, 3),
+ AnalyteType.Proteoform => new ClassicDeconvolutionParameters(1, 10, 4, 3),
+ AnalyteType.Oligo => new ClassicDeconvolutionParameters(-10, -1, 4, 3),
+ _ => throw new ArgumentOutOfRangeException()
+ };
+ ProductDeconvolutionParametersList.Add(toAdd.ToViewModel());
+ }
+
+ break;
+
+ case DeconvolutionType.IsoDecDeconvolution:
+ // TODO: fill in IsoDec region in follow-up pull request
+ break;
+
+ default: // This will only be hit if a new deconvolution type is added to mzlib and not handled here
+ throw new ArgumentOutOfRangeException();
+ }
+ }
+
+ // If deconvolution parameters are not set, default to MetaMorpheus defaults
+ PrecursorDeconvolutionParameters = initialPrecursorParameters is null
+ ? PrecursorDeconvolutionParametersList.First(x => x.DeconvolutionType == DeconvolutionType.ClassicDeconvolution)
+ : PrecursorDeconvolutionParametersList.First(x => x.Parameters == initialPrecursorParameters);
+
+ ProductDeconvolutionParameters = initialProductParameters is null
+ ? ProductDeconvolutionParametersList.First(x => x.DeconvolutionType == DeconvolutionType.ClassicDeconvolution)
+ : ProductDeconvolutionParametersList.First(x => x.Parameters == initialProductParameters);
+ }
+
+ #region Common Parameters
+
+ private bool _useProvidedPrecursors;
+ public bool UseProvidedPrecursors
+ {
+ get => _useProvidedPrecursors;
+ set
+ {
+ _useProvidedPrecursors = value;
+ OnPropertyChanged(nameof(UseProvidedPrecursors));
+ }
+ }
+
+ private bool _doPrecursorDeconvolution;
+ public bool DoPrecursorDeconvolution
+ {
+ get => _doPrecursorDeconvolution;
+ set
+ {
+ _doPrecursorDeconvolution = value;
+ OnPropertyChanged(nameof(DoPrecursorDeconvolution));
+ }
+ }
+
+ #endregion
+
+ ///
+ /// All of the possible precursor deconvolution parameters that can be selected
+ ///
+ /// Their ToString() method sets the name of the combo box
+ /// Stored in memory while task window is open, only the selected one is used for
+ /// This enables the user to set parameters, switch to another, and switch back without losing their settings
+ ///
+ public ObservableCollection PrecursorDeconvolutionParametersList { get; protected set; }
+ private DeconParamsViewModel? _precursorDeconvolutionParameters;
+
+ ///
+ /// The selected precursor deconvolution parameters
+ ///
+ public DeconParamsViewModel PrecursorDeconvolutionParameters
+ {
+ get => _precursorDeconvolutionParameters!;
+ set
+ {
+ _precursorDeconvolutionParameters = value;
+ OnPropertyChanged(nameof(PrecursorDeconvolutionParameters));
+ }
+ }
+
+ ///
+ /// All of the possible product deconvolution parameters that can be selected
+ ///
+ /// Their ToString() method sets the name of the combo box
+ /// Stored in memory while task window is open, only the selected one is used for
+ /// This enables the user to set parameters, switch to another, and switch back without losing their settings
+ ///
+ public ObservableCollection ProductDeconvolutionParametersList { get; protected set; }
+ private DeconParamsViewModel? _productDeconvolutionParameters;
+
+ ///
+ /// The selected product deconvolution parameters
+ ///
+ public DeconParamsViewModel ProductDeconvolutionParameters
+ {
+ get => _productDeconvolutionParameters!;
+ set
+ {
+ _productDeconvolutionParameters = value;
+ OnPropertyChanged(nameof(ProductDeconvolutionParameters));
+ }
+ }
+
+ ///
+ /// Hides the decon type selection combo box if only one options is present
+ ///
+ public bool DisplayDeconSelectionComboBox => PrecursorDeconvolutionParametersList.Count > 1 || ProductDeconvolutionParametersList.Count > 1;
+}
+
+[ExcludeFromCodeCoverage] // Model used only for visualizing the view in visual studio
+public class DeconHostModel : DeconHostViewModel
+{
+ public static DeconHostModel Instance => new DeconHostModel();
+
+ public DeconHostModel() : base (DeconParamsModel.Instance.Parameters, DeconParamsModel.Instance.Parameters)
+ {
+ UseProvidedPrecursors = false;
+ DoPrecursorDeconvolution = true;
+ }
+}
\ No newline at end of file
diff --git a/MetaMorpheus/GuiFunctions/ViewModels/Deconvolution/DeconParamsViewModel.cs b/MetaMorpheus/GuiFunctions/ViewModels/Deconvolution/DeconParamsViewModel.cs
new file mode 100644
index 000000000..a09e00169
--- /dev/null
+++ b/MetaMorpheus/GuiFunctions/ViewModels/Deconvolution/DeconParamsViewModel.cs
@@ -0,0 +1,178 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics.CodeAnalysis;
+using MassSpectrometry;
+
+namespace GuiFunctions;
+
+///
+/// Base Deconvolution Parameters view model
+/// Used to wrap the DeconvolutionParameters object
+/// Contains only shared information between different DeconvolutionParameters
+///
+public abstract class DeconParamsViewModel : BaseViewModel, IEquatable
+{
+
+ private int _previousMinAssumedChargeState;
+ private int _previousMaxAssumedChargeState;
+
+ public DeconvolutionType DeconvolutionType => Parameters.DeconvolutionType;
+ public abstract DeconvolutionParameters Parameters { get; protected set; }
+
+
+ ///
+ /// Gets or sets the minimum assumed charge state.
+ /// Ensures the value is within valid range based on the polarity.
+ ///
+ public int MinAssumedChargeState
+ {
+ get => Parameters.MinAssumedChargeState;
+ set
+ {
+ if (value == 0)
+ return;
+ switch (Polarity)
+ {
+ case Polarity.Positive when value < 0:
+ case Polarity.Positive when value > MaxAssumedChargeState:
+ case Polarity.Negative when value > 0:
+ case Polarity.Negative when value > MaxAssumedChargeState:
+ return;
+
+ default:
+ _previousMinAssumedChargeState = Parameters.MinAssumedChargeState;
+ Parameters.MinAssumedChargeState = value;
+ OnPropertyChanged(nameof(MinAssumedChargeState));
+ break;
+ }
+ }
+ }
+
+
+ ///
+ /// Gets or sets the maximum assumed charge state.
+ /// Ensures the value is within valid range based on the polarity.
+ ///
+ public int MaxAssumedChargeState
+ {
+ get => Parameters.MaxAssumedChargeState;
+ set
+ {
+ if (value == 0)
+ return;
+ switch (Polarity)
+ {
+ case Polarity.Positive when value < 0:
+ case Polarity.Positive when value < MinAssumedChargeState:
+ case Polarity.Negative when value > 0:
+ case Polarity.Negative when value < MinAssumedChargeState:
+ return;
+
+ default:
+ _previousMaxAssumedChargeState = Parameters.MaxAssumedChargeState;
+ Parameters.MaxAssumedChargeState = value;
+ OnPropertyChanged(nameof(MaxAssumedChargeState));
+ break;
+ }
+ }
+ }
+
+ // TODO: When RNA is added to MetaMorpheus, add the polarity to the GUI
+ public Polarity Polarity
+ {
+ get => Parameters.Polarity;
+ set
+ {
+ // Update based upon the new polarity
+ Parameters.Polarity = value;
+ OnPropertyChanged(nameof(Polarity));
+
+ // Update min and max charge to be valid with the new polarity
+ // switch from negative to positive
+ if (value == Polarity.Positive)
+ {
+ if (MaxAssumedChargeState < 0)
+ {
+ if (_previousMaxAssumedChargeState > 0)
+ MaxAssumedChargeState = _previousMaxAssumedChargeState;
+ else
+ MaxAssumedChargeState = 12;
+ }
+
+ if (MinAssumedChargeState < 1)
+ {
+ if (_previousMinAssumedChargeState > 0 && _previousMinAssumedChargeState < MaxAssumedChargeState)
+ MinAssumedChargeState = _previousMinAssumedChargeState;
+ else
+ MinAssumedChargeState = 1;
+ }
+ }
+
+ // switch from positive to negative
+ if (value == Polarity.Negative)
+ {
+ if (MinAssumedChargeState > 0)
+ {
+ if (_previousMinAssumedChargeState < 0)
+ MinAssumedChargeState = _previousMinAssumedChargeState;
+ else
+ MinAssumedChargeState = -20;
+ }
+
+ if (MaxAssumedChargeState > 0)
+ {
+ if (_previousMaxAssumedChargeState < 0 && _previousMaxAssumedChargeState > MinAssumedChargeState)
+ MaxAssumedChargeState = _previousMaxAssumedChargeState;
+ else
+ MaxAssumedChargeState = -1;
+ }
+ }
+
+ }
+ }
+
+ public override string ToString() => DeconvolutionType.ToString();
+
+ public bool Equals(DeconParamsViewModel other)
+ {
+ if (ReferenceEquals(null, other)) return false;
+ if (ReferenceEquals(this, other)) return true;
+
+ if (Parameters.DeconvolutionType != other.Parameters.DeconvolutionType)
+ return false;
+ if (Parameters.Polarity != other.Parameters.Polarity)
+ return false;
+ if (Parameters.MinAssumedChargeState != other.Parameters.MinAssumedChargeState)
+ return false;
+ if (Parameters.MaxAssumedChargeState != other.Parameters.MaxAssumedChargeState)
+ return false;
+ return true;
+ }
+
+ public override bool Equals(object obj)
+ {
+ if (ReferenceEquals(null, obj)) return false;
+ if (ReferenceEquals(this, obj)) return true;
+ if (obj.GetType() != this.GetType()) return false;
+ return Equals((DeconParamsViewModel)obj);
+ }
+
+ public override int GetHashCode()
+ {
+ return (Parameters != null ? Parameters.DeconvolutionType.GetHashCode() + Parameters.Polarity.GetHashCode() + MaxAssumedChargeState.GetHashCode() : 0);
+ }
+}
+
+
+[ExcludeFromCodeCoverage] // Model used only for visualizing the view in visual studio
+public class DeconParamsModel : DeconParamsViewModel
+{
+ public static DeconParamsModel Instance => new DeconParamsModel();
+
+ public sealed override DeconvolutionParameters Parameters { get; protected set; }
+
+ public DeconParamsModel()
+ {
+ Parameters = new ClassicDeconvolutionParameters(1, 20, 5, 3, Polarity.Negative);
+ }
+}
\ No newline at end of file
diff --git a/MetaMorpheus/GuiFunctions/ViewModels/Deconvolution/IsoDecDeconParamsViewModel.cs b/MetaMorpheus/GuiFunctions/ViewModels/Deconvolution/IsoDecDeconParamsViewModel.cs
new file mode 100644
index 000000000..1a09d8090
--- /dev/null
+++ b/MetaMorpheus/GuiFunctions/ViewModels/Deconvolution/IsoDecDeconParamsViewModel.cs
@@ -0,0 +1,20 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics.CodeAnalysis;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using MassSpectrometry;
+
+namespace GuiFunctions
+{
+ // Coming Soon
+ [ExcludeFromCodeCoverage]
+ public sealed class IsoDecDeconParamsViewModel : DeconParamsViewModel
+ {
+ public override DeconvolutionParameters Parameters { get; protected set; }
+
+
+ public override string ToString() => "IsoDec";
+ }
+}
diff --git a/MetaMorpheus/GuiFunctions/ViewModels/IonForTreeViewModel.cs b/MetaMorpheus/GuiFunctions/ViewModels/IonForTreeViewModel.cs
index cdc3cf98d..843c23a67 100644
--- a/MetaMorpheus/GuiFunctions/ViewModels/IonForTreeViewModel.cs
+++ b/MetaMorpheus/GuiFunctions/ViewModels/IonForTreeViewModel.cs
@@ -66,7 +66,7 @@ public IonForTreeViewModel(ProductType type, bool beta)
color = MetaDrawSettings.BetaProductTypeToColor[IonType];
else
color = MetaDrawSettings.ProductTypeToColor[IonType];
- SelectedColor = AddSpaces(color.GetColorName());
+ SelectedColor = AddSpaces(MetaDrawSettings.PossibleColors[color]);
ColorBrush = DrawnSequence.ParseColorBrushFromOxyColor(color);
}
diff --git a/MetaMorpheus/GuiFunctions/ViewModels/ModForTreeViewModel.cs b/MetaMorpheus/GuiFunctions/ViewModels/ModForTreeViewModel.cs
index b1f4080e4..2ee06aa00 100644
--- a/MetaMorpheus/GuiFunctions/ViewModels/ModForTreeViewModel.cs
+++ b/MetaMorpheus/GuiFunctions/ViewModels/ModForTreeViewModel.cs
@@ -14,6 +14,7 @@ public class ModForTreeViewModel : BaseViewModel
private bool _isChecked;
private string _selectedColor;
private SolidColorBrush _colorBrush;
+ private bool _colorDataLoaded;
#endregion
@@ -23,10 +24,7 @@ public class ModForTreeViewModel : BaseViewModel
public bool Use
{
- get
- {
- return _isChecked;
- }
+ get => _isChecked;
set
{
_isChecked = value;
@@ -40,17 +38,26 @@ public bool Use
public Brush Background { get; }
public string SelectedColor
{
- get { return _selectedColor; }
+ get
+ {
+ EnsureColorDataLoaded();
+ return _selectedColor;
+ }
set
{
_selectedColor = value;
ColorBrush = DrawnSequence.ParseColorBrushFromName(_selectedColor);
+ _colorDataLoaded = true;
OnPropertyChanged(nameof(SelectedColor));
}
}
public SolidColorBrush ColorBrush
{
- get { return _colorBrush; }
+ get
+ {
+ EnsureColorDataLoaded();
+ return _colorBrush;
+ }
set
{
_colorBrush = value;
@@ -69,16 +76,6 @@ public ModForTreeViewModel(string toolTip, bool use, string modName, bool bad, M
Use = use;
ModName = modName;
DisplayName = modName;
- if (MetaDrawSettings.ModificationTypeToColor != null)
- {
- // This if statement prevents a crash from loading a search task modifications not found on launch
- // This can occur due to new custom modifications or a mod in the xml database that was not in our initial list
- if (!MetaDrawSettings.ModificationTypeToColor.TryGetValue(modName, out OxyColor color))
- color = OxyColors.Aqua;
- SelectedColor = AddSpaces(color.GetColorName());
- ColorBrush = DrawnSequence.ParseColorBrushFromOxyColor(color);
- }
-
if (toolTip.ToLower().Contains("terminal"))
{
@@ -104,6 +101,27 @@ public ModForTreeViewModel(string toolTip, bool use, string modName, bool bad, M
#endregion
+ ///
+ /// Ensures the color data is loaded. This is necessary because the color data is not loaded until the first time it is accessed.
+ /// This enables the use of the same control in MetaDraw and Task Windows without loading the color data for task windows.
+ ///
+ private void EnsureColorDataLoaded()
+ {
+ if (!_colorDataLoaded)
+ {
+ if (MetaDrawSettings.ModificationTypeToColor != null)
+ {
+ // This if statement prevents a crash from loading a search task modifications not found on launch
+ // This can occur due to new custom modifications or a mod in the xml database that was not in our initial list
+ if (!MetaDrawSettings.ModificationTypeToColor.TryGetValue(ModName, out OxyColor color))
+ color = MetaDrawSettings.FallbackColor;
+ _selectedColor = AddSpaces(MetaDrawSettings.PossibleColors[color]);
+ _colorBrush = DrawnSequence.ParseColorBrushFromOxyColor(color);
+ }
+ _colorDataLoaded = true;
+ }
+ }
+
public void SelectionChanged(string newColor)
{
SelectedColor = newColor;
diff --git a/MetaMorpheus/MetaMorpheus.sln.DotSettings b/MetaMorpheus/MetaMorpheus.sln.DotSettings
index 3cb2a8c2a..2b8fe6816 100644
--- a/MetaMorpheus/MetaMorpheus.sln.DotSettings
+++ b/MetaMorpheus/MetaMorpheus.sln.DotSettings
@@ -1,4 +1,5 @@
+ True
True
True
True
@@ -6,6 +7,8 @@
True
True
True
+ True
+ True
True
True
True
@@ -20,9 +23,11 @@
True
True
True
+ True
True
True
True
+ True
True
True
True
diff --git a/MetaMorpheus/MetaMorpheusSetup/Product.wxs b/MetaMorpheus/MetaMorpheusSetup/Product.wxs
index fc7b69b92..3bbf33f48 100644
--- a/MetaMorpheus/MetaMorpheusSetup/Product.wxs
+++ b/MetaMorpheus/MetaMorpheusSetup/Product.wxs
@@ -315,6 +315,9 @@
+
+
+
diff --git a/MetaMorpheus/TaskLayer/MetaMorpheusTask.cs b/MetaMorpheus/TaskLayer/MetaMorpheusTask.cs
index 16c86ad4b..44bb83da6 100644
--- a/MetaMorpheus/TaskLayer/MetaMorpheusTask.cs
+++ b/MetaMorpheus/TaskLayer/MetaMorpheusTask.cs
@@ -1143,11 +1143,11 @@ public static void DetermineAnalyteType(CommonParameters commonParameters)
&& commonParameters.DigestionParams.Protease != null
&& commonParameters.DigestionParams.Protease.Name == "top-down")
{
- GlobalVariables.AnalyteType = "Proteoform";
+ GlobalVariables.AnalyteType = AnalyteType.Proteoform;
}
else
{
- GlobalVariables.AnalyteType = "Peptide";
+ GlobalVariables.AnalyteType = AnalyteType.Peptide;
}
}
diff --git a/MetaMorpheus/TaskLayer/SearchTask/PostSearchAnalysisTask.cs b/MetaMorpheus/TaskLayer/SearchTask/PostSearchAnalysisTask.cs
index e30b4549a..bf6734e70 100644
--- a/MetaMorpheus/TaskLayer/SearchTask/PostSearchAnalysisTask.cs
+++ b/MetaMorpheus/TaskLayer/SearchTask/PostSearchAnalysisTask.cs
@@ -136,11 +136,11 @@ private void CalculatePsmAndPeptideFdr(List psms, string analysis
// for example, here it may be treated as a decoy PSM, where as in parsimony it will be determined by the parsimony algorithm which is agnostic of target/decoy assignments
// this could cause weird PSM FDR issues
- Status("Estimating PSM FDR...", Parameters.SearchTaskId);
+ Status($"Estimating {GlobalVariables.AnalyteType.GetSpectralMatchLabel()} FDR...", Parameters.SearchTaskId);
new FdrAnalysisEngine(psms, Parameters.NumNotches, CommonParameters, this.FileSpecificParameters,
new List { Parameters.SearchTaskId }, analysisType: analysisType, doPEP: doPep, outputFolder: Parameters.OutputFolder).Run();
- Status("Done estimating PSM FDR!", Parameters.SearchTaskId);
+ Status($"Done estimating {GlobalVariables.AnalyteType.GetSpectralMatchLabel()} FDR!", Parameters.SearchTaskId);
}
private void ProteinAnalysis()
@@ -150,7 +150,7 @@ private void ProteinAnalysis()
return;
}
- Status("Constructing protein groups...", Parameters.SearchTaskId);
+ Status($"Constructing {GlobalVariables.AnalyteType.GetBioPolymerLabel().ToLower()} groups...", Parameters.SearchTaskId);
//if SILAC, modify the proteins to appear only light (we want a protein sequence to look like PROTEINK instead of PROTEINa)
if (Parameters.SearchParameters.SilacLabels != null && Parameters.AllPsms.First() is PeptideSpectralMatch)
@@ -178,7 +178,7 @@ private void ProteinAnalysis()
ProteinGroups = proteinScoringAndFdrResults.SortedAndScoredProteinGroups;
- Status("Done constructing protein groups!", Parameters.SearchTaskId);
+ Status($"Done constructing {GlobalVariables.AnalyteType.GetBioPolymerLabel().ToLower()} groups!", Parameters.SearchTaskId);
}
private void DoMassDifferenceLocalizationAnalysis()
@@ -593,7 +593,7 @@ protected void WritePsmsToTsv(IEnumerable psms, string filePath,
}
private void WritePsmResults()
{
- Status("Writing PSM results...", Parameters.SearchTaskId);
+ Status($"Writing {GlobalVariables.AnalyteType.GetSpectralMatchLabel()} results...", Parameters.SearchTaskId);
var psmsForPsmResults = FilteredPsms.Filter(Parameters.AllPsms,
CommonParameters,
includeDecoys: Parameters.SearchParameters.WriteDecoys,
@@ -602,13 +602,13 @@ private void WritePsmResults()
includeHighQValuePsms: Parameters.SearchParameters.WriteHighQValuePsms);
// write PSMs
- string writtenFile = Path.Combine(Parameters.OutputFolder, "AllPSMs.psmtsv");
+ string writtenFile = Path.Combine(Parameters.OutputFolder, $"All{GlobalVariables.AnalyteType.GetSpectralMatchLabel()}s.{GlobalVariables.AnalyteType.GetSpectralMatchExtension()}");
WritePsmsToTsv(psmsForPsmResults.OrderByDescending(p=>p).ToList(), writtenFile, writePeptideLevelResults: false);
FinishedWritingFile(writtenFile, new List { Parameters.SearchTaskId });
// write PSMs for percolator
// percolator native read format is .tab
- writtenFile = Path.Combine(Parameters.OutputFolder, "AllPSMs_FormattedForPercolator.tab");
+ writtenFile = Path.Combine(Parameters.OutputFolder, $"All{GlobalVariables.AnalyteType.GetSpectralMatchLabel()}s_FormattedForPercolator.tab");
WritePsmsForPercolator(psmsForPsmResults.OrderByDescending(p=>p).ToList(), writtenFile);
FinishedWritingFile(writtenFile, new List { Parameters.SearchTaskId });
@@ -617,16 +617,16 @@ private void WritePsmResults()
{
Parameters.SearchTaskResults.AddPsmPeptideProteinSummaryText(
- "PEP could not be calculated due to an insufficient number of PSMs. Results were filtered by q-value." +
+ $"PEP could not be calculated due to an insufficient number of {GlobalVariables.AnalyteType.GetSpectralMatchLabel()}s. Results were filtered by q-value." +
Environment.NewLine);
}
- string psmResultsText = "All target PSMs with " + psmsForPsmResults.GetFilterTypeString() + " <= " + Math.Round(psmsForPsmResults.FilterThreshold, 2) + ": " +
+ string psmResultsText = $"All target {GlobalVariables.AnalyteType.GetSpectralMatchLabel()}s with " + psmsForPsmResults.GetFilterTypeString() + " <= " + Math.Round(psmsForPsmResults.FilterThreshold, 2) + ": " +
psmsForPsmResults.TargetPsmsAboveThreshold;
- ResultsDictionary[("All", "PSMs")] = psmResultsText;
+ ResultsDictionary[("All", $"{GlobalVariables.AnalyteType.GetSpectralMatchLabel()}s")] = psmResultsText;
}
private void WritePeptideResults()
{
- Status("Writing peptide results...", Parameters.SearchTaskId);
+ Status($"Writing {GlobalVariables.AnalyteType.GetUniqueFormLabel().ToLower()} results...", Parameters.SearchTaskId);
var peptidesForPeptideResults = FilteredPsms.Filter(Parameters.AllPsms,
CommonParameters,
@@ -637,7 +637,7 @@ private void WritePeptideResults()
filterAtPeptideLevel: true);
// write PSMs
- string writtenFile = Path.Combine(Parameters.OutputFolder, $"All{GlobalVariables.AnalyteType}s.psmtsv");
+ string writtenFile = Path.Combine(Parameters.OutputFolder, $"All{GlobalVariables.AnalyteType}s.{GlobalVariables.AnalyteType.GetSpectralMatchExtension()}");
WritePsmsToTsv(peptidesForPeptideResults.OrderByDescending(p => p).ToList(), writtenFile, writePeptideLevelResults: true);
FinishedWritingFile(writtenFile, new List { Parameters.SearchTaskId });
@@ -645,16 +645,16 @@ private void WritePeptideResults()
if (peptidesForPeptideResults.FilteringNotPerformed)
{
Parameters.SearchTaskResults.AddPsmPeptideProteinSummaryText(
- "PEP could not be calculated due to an insufficient number of PSMs. Results were filtered by q-value." + Environment.NewLine);
+ $"PEP could not be calculated due to an insufficient number of {GlobalVariables.AnalyteType.GetSpectralMatchLabel()}s. Results were filtered by q-value." + Environment.NewLine);
}
- string peptideResultsText = $"All target {GlobalVariables.AnalyteType.ToLower()}s with " + peptidesForPeptideResults.GetFilterTypeString() + " <= " + Math.Round(peptidesForPeptideResults.FilterThreshold, 2) + ": " +
+ string peptideResultsText = $"All target {GlobalVariables.AnalyteType.GetUniqueFormLabel().ToLower()}s with " + peptidesForPeptideResults.GetFilterTypeString() + " <= " + Math.Round(peptidesForPeptideResults.FilterThreshold, 2) + ": " +
peptidesForPeptideResults.TargetPsmsAboveThreshold;
- ResultsDictionary[("All", GlobalVariables.AnalyteType)] = peptideResultsText;
+ ResultsDictionary[("All", GlobalVariables.AnalyteType.GetUniqueFormLabel())] = peptideResultsText;
}
private void WriteIndividualPsmResults()
{
- Status("Writing Individual PSM results...", Parameters.SearchTaskId);
+ Status($"Writing Individual {GlobalVariables.AnalyteType.GetSpectralMatchLabel()} results...", Parameters.SearchTaskId);
var psmsGroupedByFile = Parameters.AllPsms.GroupBy(p => p.FullFilePath);
foreach (var psmFileGroup in psmsGroupedByFile)
@@ -674,24 +674,24 @@ private void WriteIndividualPsmResults()
int count = psmsToWrite.Where(psm => psm.PsmFdrInfo.PEP <= 0.01).Count();
// write PSMs
- string writtenFile = Path.Combine(Parameters.IndividualResultsOutputFolder, strippedFileName + "_PSMs.psmtsv");
+ string writtenFile = Path.Combine(Parameters.IndividualResultsOutputFolder, strippedFileName + $"_{GlobalVariables.AnalyteType.GetSpectralMatchLabel()}s.{GlobalVariables.AnalyteType.GetSpectralMatchExtension()}");
WritePsmsToTsv(psmsToWrite, writtenFile);
FinishedWritingFile(writtenFile, new List { Parameters.SearchTaskId, "Individual Spectra Files", psmFileGroup.Key });
// write PSMs for percolator
- writtenFile = Path.Combine(Parameters.IndividualResultsOutputFolder, strippedFileName + "_PSMsFormattedForPercolator.tab");
+ writtenFile = Path.Combine(Parameters.IndividualResultsOutputFolder, strippedFileName + $"_{GlobalVariables.AnalyteType.GetSpectralMatchLabel()}sFormattedForPercolator.tab");
WritePsmsForPercolator(psmsToWrite.FilteredPsmsList, writtenFile);
FinishedWritingFile(writtenFile, new List { Parameters.SearchTaskId, "Individual Spectra Files", psmFileGroup.Key });
// write summary text
- string psmResultsText = strippedFileName + " - Target PSMs with " + psmsToWrite.GetFilterTypeString() + " <= " + Math.Round(psmsToWrite.FilterThreshold, 2) + ": " +
+ string psmResultsText = strippedFileName + $" - Target {GlobalVariables.AnalyteType.GetSpectralMatchLabel()}s with " + psmsToWrite.GetFilterTypeString() + " <= " + Math.Round(psmsToWrite.FilterThreshold, 2) + ": " +
psmsToWrite.TargetPsmsAboveThreshold;
- ResultsDictionary[(strippedFileName, "PSMs")] = psmResultsText;
+ ResultsDictionary[(strippedFileName, $"{GlobalVariables.AnalyteType.GetSpectralMatchLabel()}s")] = psmResultsText;
}
}
private void WriteIndividualPeptideResults()
{
- Status("Writing Individual Peptide results...", Parameters.SearchTaskId);
+ Status($"Writing Individual {GlobalVariables.AnalyteType} results...", Parameters.SearchTaskId);
var peptidesGroupedByFile = Parameters.AllPsms.GroupBy(p => p.FullFilePath);
foreach (var psmFileGroup in peptidesGroupedByFile)
@@ -715,14 +715,14 @@ private void WriteIndividualPeptideResults()
filterAtPeptideLevel: true);
// write PSMs
- string writtenFile = Path.Combine(Parameters.IndividualResultsOutputFolder, strippedFileName + $"_{GlobalVariables.AnalyteType}s.psmtsv");
+ string writtenFile = Path.Combine(Parameters.IndividualResultsOutputFolder, strippedFileName + $"_{GlobalVariables.AnalyteType}s.{GlobalVariables.AnalyteType.GetSpectralMatchExtension()}");
WritePsmsToTsv(peptidesToWrite, writtenFile, writePeptideLevelResults: true);
FinishedWritingFile(writtenFile, new List { Parameters.SearchTaskId, "Individual Spectra Files", psmFileGroup.Key });
// write summary text
- string peptideResultsText = strippedFileName + $" - Target {GlobalVariables.AnalyteType.ToLower()}s with " + peptidesToWrite.GetFilterTypeString() + " <= " + Math.Round(peptidesToWrite.FilterThreshold, 2) + ": " +
+ string peptideResultsText = strippedFileName + $" - Target {GlobalVariables.AnalyteType.GetUniqueFormLabel().ToLower()}s with " + peptidesToWrite.GetFilterTypeString() + " <= " + Math.Round(peptidesToWrite.FilterThreshold, 2) + ": " +
peptidesToWrite.TargetPsmsAboveThreshold;
- ResultsDictionary[(strippedFileName, GlobalVariables.AnalyteType)] = peptideResultsText;
+ ResultsDictionary[(strippedFileName, GlobalVariables.AnalyteType.GetUniqueFormLabel())] = peptideResultsText;
}
}
@@ -835,14 +835,14 @@ private void WriteProteinResults()
}
else
{
- string proteinResultsText = "All target protein groups with q-value <= 0.01 (1% FDR): " + ProteinGroups.Count(b => b.QValue <= 0.01 && !b.IsDecoy);
- ResultsDictionary[("All", "Proteins")] = proteinResultsText;
+ string proteinResultsText = $"All target {GlobalVariables.AnalyteType.GetBioPolymerLabel().ToLower()} groups with q-value <= 0.01 (1% FDR): " + ProteinGroups.Count(b => b.QValue <= 0.01 && !b.IsDecoy);
+ ResultsDictionary[("All", $"{GlobalVariables.AnalyteType.GetBioPolymerLabel()}s")] = proteinResultsText;
}
- string fileName = "AllProteinGroups.tsv";
+ string fileName = $"All{GlobalVariables.AnalyteType.GetBioPolymerLabel()}Groups.tsv";
if (Parameters.SearchParameters.DoLabelFreeQuantification)
{
- fileName = "AllQuantifiedProteinGroups.tsv";
+ fileName = $"AllQuantified{GlobalVariables.AnalyteType.GetBioPolymerLabel()}Groups.tsv";
}
//set peptide output values
@@ -909,10 +909,10 @@ private void WriteProteinResults()
{
// write summary text
string proteinResultsText = strippedFileName + " - Target protein groups within 1 % FDR: " + subsetProteinGroupsForThisFile.Count(b => b.QValue <= 0.01 && !b.IsDecoy);
- ResultsDictionary[(strippedFileName, "Proteins")] = proteinResultsText;
+ ResultsDictionary[(strippedFileName, $"{GlobalVariables.AnalyteType.GetBioPolymerLabel()}s")] = proteinResultsText;
// write result files
- writtenFile = Path.Combine(Parameters.IndividualResultsOutputFolder, strippedFileName + "_ProteinGroups.tsv");
+ writtenFile = Path.Combine(Parameters.IndividualResultsOutputFolder, strippedFileName + $"_{GlobalVariables.AnalyteType.GetBioPolymerLabel()}Groups.tsv");
WriteProteinGroupsToTsv(subsetProteinGroupsForThisFile, writtenFile, new List { Parameters.SearchTaskId, "Individual Spectra Files", fullFilePath });
}
@@ -1790,7 +1790,7 @@ private static void WritePsmsForPercolator(List psmList, string w
string header = "SpecId\tLabel\tScanNr\t";
header += String.Join("\t", PsmData.trainingInfos[searchType]);
- header += "\tPeptide\tProteins";
+ header += $"\t{GlobalVariables.AnalyteType.GetUniqueFormLabel()}s\t{GlobalVariables.AnalyteType.GetBioPolymerLabel()}s";
output.WriteLine(header);
@@ -1860,8 +1860,8 @@ private void ConstructResultsDictionary()
{
ResultsDictionary = new()
{
- { ("All", "PSMs"), "" },
- { ("All", GlobalVariables.AnalyteType), "" }
+ { ("All", $"{GlobalVariables.AnalyteType.GetSpectralMatchLabel()}s"), "" },
+ { ("All", GlobalVariables.AnalyteType.GetUniqueFormLabel()), "" }
};
if (Parameters.CurrentRawFileList.Count > 1 && Parameters.SearchParameters.WriteIndividualFiles)
@@ -1869,20 +1869,20 @@ private void ConstructResultsDictionary()
foreach (var rawFile in Parameters.CurrentRawFileList)
{
string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(rawFile);
- ResultsDictionary.Add((fileNameWithoutExtension, "PSMs"), "");
- ResultsDictionary.Add((fileNameWithoutExtension, GlobalVariables.AnalyteType), "");
+ ResultsDictionary.Add((fileNameWithoutExtension, $"{GlobalVariables.AnalyteType.GetSpectralMatchLabel()}s"), "");
+ ResultsDictionary.Add((fileNameWithoutExtension, GlobalVariables.AnalyteType.GetUniqueFormLabel()), "");
}
}
if (Parameters.SearchParameters.DoParsimony)
{
- ResultsDictionary.Add(("All", "Proteins"), "");
+ ResultsDictionary.Add(("All", $"{GlobalVariables.AnalyteType.GetBioPolymerLabel()}s"), "");
if (Parameters.CurrentRawFileList.Count > 1 && Parameters.SearchParameters.WriteIndividualFiles)
{
foreach (var rawFile in Parameters.CurrentRawFileList)
{
string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(rawFile);
- ResultsDictionary.Add((fileNameWithoutExtension, "Proteins"), "");
+ ResultsDictionary.Add((fileNameWithoutExtension, $"{GlobalVariables.AnalyteType.GetBioPolymerLabel()}s"), "");
}
}
}
diff --git a/MetaMorpheus/TaskLayer/TaskLayer.csproj b/MetaMorpheus/TaskLayer/TaskLayer.csproj
index 8a7446de9..0cf7bb570 100644
--- a/MetaMorpheus/TaskLayer/TaskLayer.csproj
+++ b/MetaMorpheus/TaskLayer/TaskLayer.csproj
@@ -21,7 +21,7 @@
-
+
diff --git a/MetaMorpheus/Test/AveragingTests.cs b/MetaMorpheus/Test/AveragingTests.cs
index 64a567b98..948849f05 100644
--- a/MetaMorpheus/Test/AveragingTests.cs
+++ b/MetaMorpheus/Test/AveragingTests.cs
@@ -7,6 +7,7 @@
using FlashLFQ;
using MassSpectrometry;
using NUnit.Framework;
+using NUnit.Framework.Legacy;
using SpectralAveraging;
using TaskLayer;
using Mzml = IO.MzML.Mzml;
@@ -160,7 +161,17 @@ public static void TestAveragingDdaScans()
Assert.That(originalMs1Scans.Count == averagedMs1Scans.Count);
for (var i = 0; i < averagedMs2Scans.Count; i++)
{
- Assert.That(originalMs2Scans[i].MassSpectrum.Equals(averagedMs2Scans[i].MassSpectrum));
+ CollectionAssert.AreEqual(originalMs2Scans[i].MassSpectrum.YArray, averagedMs2Scans[i].MassSpectrum.YArray);
+
+ var originalX = originalMs2Scans[i].MassSpectrum.XArray;
+ var averagedX = averagedMs2Scans[i].MassSpectrum.XArray;
+ Assert.That(originalX.Length, Is.EqualTo(averagedX.Length));
+
+ // check that the x values are the same within mzLib writer rounding toleranceS
+ for (var j = 0; j < originalX.Length; j++)
+ {
+ Assert.That(originalX[j], Is.EqualTo(averagedX[j]).Within(0.0001));
+ }
}
Directory.Delete(testPath, true);
diff --git a/MetaMorpheus/Test/GlobalVariablesTest.cs b/MetaMorpheus/Test/GlobalVariablesTest.cs
index 88bf0f1fb..4ad665468 100644
--- a/MetaMorpheus/Test/GlobalVariablesTest.cs
+++ b/MetaMorpheus/Test/GlobalVariablesTest.cs
@@ -79,5 +79,40 @@ public static void TestCustomFileExtensionGetter()
Assert.That(GlobalVariables.GetFileExtension(test7, getUncompressedExtension: true) == ".fasta");
Assert.That(GlobalVariables.GetFilenameWithoutExtension(test7) == "my.Fi.le");
}
+
+ [Test]
+ public static void TestGetSpectralMatchLabel()
+ {
+ Assert.That(AnalyteType.Peptide.GetSpectralMatchLabel(), Is.EqualTo("PSM"));
+ Assert.That(AnalyteType.Proteoform.GetSpectralMatchLabel(), Is.EqualTo("PSM"));
+ Assert.That(AnalyteType.Oligo.GetSpectralMatchLabel(), Is.EqualTo("OSM"));
+ }
+
+ [Test]
+ public static void TestGetSpectralMatchExtension()
+ {
+ Assert.That(AnalyteType.Peptide.GetSpectralMatchExtension(), Is.EqualTo("psmtsv"));
+ Assert.That(AnalyteType.Proteoform.GetSpectralMatchExtension(), Is.EqualTo("psmtsv"));
+ Assert.That(AnalyteType.Oligo.GetSpectralMatchExtension(), Is.EqualTo("osmtsv"));
+ }
+
+ [Test]
+ public static void TestGetUniqueFormLabel()
+ {
+ Assert.That(AnalyteType.Peptide.GetUniqueFormLabel(), Is.EqualTo("Peptide"));
+ Assert.That(AnalyteType.Peptide.ToString(), Is.EqualTo("Peptide"));
+ Assert.That(AnalyteType.Proteoform.GetUniqueFormLabel(), Is.EqualTo("Proteoform"));
+ Assert.That(AnalyteType.Proteoform.ToString(), Is.EqualTo("Proteoform"));
+ Assert.That(AnalyteType.Oligo.GetUniqueFormLabel(), Is.EqualTo("Oligo"));
+ Assert.That(AnalyteType.Oligo.ToString(), Is.EqualTo("Oligo"));
+ }
+
+ [Test]
+ public static void TestGetBioPolymerLabel()
+ {
+ Assert.That(AnalyteType.Peptide.GetBioPolymerLabel(), Is.EqualTo("Protein"));
+ Assert.That(AnalyteType.Proteoform.GetBioPolymerLabel(), Is.EqualTo("Protein"));
+ Assert.That(AnalyteType.Oligo.GetBioPolymerLabel(), Is.EqualTo("Transcript"));
+ }
}
}
diff --git a/MetaMorpheus/Test/GuiTests/ClassicDeconParamsViewModelTest.cs b/MetaMorpheus/Test/GuiTests/ClassicDeconParamsViewModelTest.cs
new file mode 100644
index 000000000..4d8a6c112
--- /dev/null
+++ b/MetaMorpheus/Test/GuiTests/ClassicDeconParamsViewModelTest.cs
@@ -0,0 +1,43 @@
+using GuiFunctions;
+using MassSpectrometry;
+using NUnit.Framework;
+
+namespace Test.GuiTests;
+
+[TestFixture]
+public class ClassicDeconParamsViewModelTest
+{
+ private ClassicDeconParamsViewModel _viewModel;
+ private ClassicDeconvolutionParameters _parameters;
+
+ [SetUp]
+ public void SetUp()
+ {
+ _parameters = new ClassicDeconvolutionParameters(1, 12, 10, 0.5);
+ _viewModel = new ClassicDeconParamsViewModel(_parameters);
+ }
+
+ [Test]
+ public void TestDeconvolutionTolerancePpm()
+ {
+ Assert.That(_viewModel.DeconvolutionTolerancePpm, Is.EqualTo(10.0));
+ _viewModel.DeconvolutionTolerancePpm = 20.0;
+ Assert.That(_viewModel.DeconvolutionTolerancePpm, Is.EqualTo(20.0));
+ Assert.That(_parameters.DeconvolutionTolerancePpm, Is.EqualTo(20.0));
+ }
+
+ [Test]
+ public void TestIntensityRatioLimit()
+ {
+ Assert.That(_viewModel.IntensityRatioLimit, Is.EqualTo(0.5));
+ _viewModel.IntensityRatioLimit = 1.0;
+ Assert.That(_viewModel.IntensityRatioLimit, Is.EqualTo(1.0));
+ Assert.That(_parameters.IntensityRatioLimit, Is.EqualTo(1.0));
+ }
+
+ [Test]
+ public void TestToString()
+ {
+ Assert.That(_viewModel.ToString(), Is.EqualTo("Classic"));
+ }
+}
\ No newline at end of file
diff --git a/MetaMorpheus/Test/GuiTests/DeconHostViewModelTest.cs b/MetaMorpheus/Test/GuiTests/DeconHostViewModelTest.cs
new file mode 100644
index 000000000..abb4c905c
--- /dev/null
+++ b/MetaMorpheus/Test/GuiTests/DeconHostViewModelTest.cs
@@ -0,0 +1,224 @@
+using System;
+using System.Linq;
+using EngineLayer;
+using GuiFunctions;
+using MassSpectrometry;
+using NUnit.Framework;
+
+namespace Test.GuiTests;
+
+[TestFixture]
+public class DeconHostViewModelTests
+{
+ internal ClassicDeconvolutionParameters ClassicPrecursorDeconvolutionParameters = new ClassicDeconvolutionParameters(1, 12, 4, 3);
+ internal ClassicDeconvolutionParameters ClassicProductDeconvolutionParameters = new ClassicDeconvolutionParameters(1, 10, 4, 3);
+
+ [Test]
+ public void Constructor_DefaultParameters_ShouldInitializeCorrectly()
+ {
+ // Arrange
+ var initialPrecursorParameters = ClassicPrecursorDeconvolutionParameters;
+ var initialProductParameters = ClassicProductDeconvolutionParameters;
+
+ // Act
+ var viewModel = new DeconHostViewModel(initialPrecursorParameters, initialProductParameters);
+
+ // Assert
+ Assert.That(viewModel.UseProvidedPrecursors, Is.False);
+ Assert.That(viewModel.DoPrecursorDeconvolution, Is.True);
+ Assert.That(viewModel.PrecursorDeconvolutionParametersList, Is.Not.Null);
+ Assert.That(viewModel.ProductDeconvolutionParametersList, Is.Not.Null);
+ Assert.That(viewModel.PrecursorDeconvolutionParametersList.Any(), Is.True);
+ Assert.That(viewModel.ProductDeconvolutionParametersList.Any(), Is.True);
+ }
+
+ [Test]
+ public void Constructor_WithProvidedParameters_ShouldSetCorrectly()
+ {
+ // Arrange
+ var initialPrecursorParameters = ClassicPrecursorDeconvolutionParameters;
+ var initialProductParameters = ClassicProductDeconvolutionParameters;
+
+ // Act
+ var viewModel = new DeconHostViewModel(initialPrecursorParameters, initialProductParameters, true, false);
+
+ // Assert
+ Assert.That(viewModel.UseProvidedPrecursors, Is.True);
+ Assert.That(viewModel.DoPrecursorDeconvolution, Is.False);
+ Assert.That(viewModel.PrecursorDeconvolutionParameters, Is.EqualTo(initialPrecursorParameters.ToViewModel()));
+ Assert.That(viewModel.ProductDeconvolutionParameters, Is.EqualTo(initialProductParameters.ToViewModel()));
+ }
+
+ [Test]
+ public void TestDeconHostViewModel_DefaultParameters()
+ {
+ // Arrange
+ DeconHostViewModel viewModel = new DeconHostViewModel(null, null);
+
+ // Act
+ var precursorParams = viewModel.PrecursorDeconvolutionParameters;
+ var productParams = viewModel.ProductDeconvolutionParameters;
+
+ // Assert
+ Assert.That(precursorParams, Is.Not.Null);
+ Assert.That(productParams, Is.Not.Null);
+ Assert.That(precursorParams.DeconvolutionType, Is.EqualTo(DeconvolutionType.ClassicDeconvolution));
+ Assert.That(productParams.DeconvolutionType, Is.EqualTo(DeconvolutionType.ClassicDeconvolution));
+ }
+
+ [Test]
+ public void PrecursorDeconvolutionParameters_Setter_ShouldTriggerPropertyChanged()
+ {
+ // Arrange
+ var viewModel = new DeconHostViewModel();
+ var newParameters = new ClassicDeconParamsViewModel(ClassicPrecursorDeconvolutionParameters);
+ bool propertyChangedTriggered = false;
+ viewModel.PropertyChanged += (sender, args) =>
+ {
+ if (args.PropertyName == nameof(viewModel.PrecursorDeconvolutionParameters))
+ propertyChangedTriggered = true;
+ };
+
+ // Act
+ viewModel.PrecursorDeconvolutionParameters = newParameters;
+
+ // Assert
+ Assert.That(propertyChangedTriggered, Is.True);
+ }
+
+ [Test]
+ public void ProductDeconvolutionParameters_Setter_ShouldTriggerPropertyChanged()
+ {
+ // Arrange
+ var viewModel = new DeconHostViewModel();
+ var newParameters = new ClassicDeconParamsViewModel(ClassicProductDeconvolutionParameters);
+ bool propertyChangedTriggered = false;
+ viewModel.PropertyChanged += (sender, args) =>
+ {
+ if (args.PropertyName == nameof(viewModel.ProductDeconvolutionParameters))
+ propertyChangedTriggered = true;
+ };
+
+ // Act
+ viewModel.ProductDeconvolutionParameters = newParameters;
+
+ // Assert
+ Assert.That(propertyChangedTriggered, Is.True);
+ }
+
+
+ [Test]
+ [NonParallelizable]
+ public void TestDeconHostViewModel_GlobalVariables_Proteoform()
+ {
+ // Arrange
+ GlobalVariables.AnalyteType = AnalyteType.Proteoform;
+ DeconHostViewModel viewModel = new DeconHostViewModel(null, null);
+
+ // Act
+ var precursorParams = viewModel.PrecursorDeconvolutionParameters;
+ var productParams = viewModel.ProductDeconvolutionParameters;
+
+ // Assert
+ Assert.That(precursorParams, Is.Not.Null);
+ Assert.That(productParams, Is.Not.Null);
+ Assert.That(precursorParams.DeconvolutionType, Is.EqualTo(DeconvolutionType.ClassicDeconvolution));
+ Assert.That(productParams.DeconvolutionType, Is.EqualTo(DeconvolutionType.ClassicDeconvolution));
+ Assert.That(precursorParams.Parameters, Is.InstanceOf());
+ Assert.That(productParams.Parameters, Is.InstanceOf());
+ Assert.That(((ClassicDeconvolutionParameters)precursorParams.Parameters).MaxAssumedChargeState, Is.EqualTo(60));
+ Assert.That(((ClassicDeconvolutionParameters)productParams.Parameters).MaxAssumedChargeState, Is.EqualTo(10));
+
+ // Revert back to default
+ GlobalVariables.AnalyteType = AnalyteType.Peptide;
+ }
+
+ [Test]
+ [NonParallelizable]
+ public void TestDeconHostViewModel_GlobalVariables_Oligo()
+ {
+ // Arrange
+ GlobalVariables.AnalyteType = AnalyteType.Oligo;
+ DeconHostViewModel viewModel = new DeconHostViewModel(null, null);
+
+ // Act
+ var precursorParams = viewModel.PrecursorDeconvolutionParameters;
+ var productParams = viewModel.ProductDeconvolutionParameters;
+
+ // Assert
+ Assert.That(precursorParams, Is.Not.Null);
+ Assert.That(productParams, Is.Not.Null);
+ Assert.That(precursorParams.DeconvolutionType, Is.EqualTo(DeconvolutionType.ClassicDeconvolution));
+ Assert.That(productParams.DeconvolutionType, Is.EqualTo(DeconvolutionType.ClassicDeconvolution));
+ Assert.That(precursorParams.Parameters, Is.InstanceOf());
+ Assert.That(productParams.Parameters, Is.InstanceOf());
+ Assert.That(((ClassicDeconvolutionParameters)precursorParams.Parameters).MinAssumedChargeState, Is.EqualTo(-20));
+ Assert.That(((ClassicDeconvolutionParameters)productParams.Parameters).MinAssumedChargeState, Is.EqualTo(-10));
+
+ // Revert back to default
+ GlobalVariables.AnalyteType = AnalyteType.Peptide;
+ }
+
+ [Test]
+ [NonParallelizable]
+ public void TestDeconHostViewModel_GlobalVariables_Unknown()
+ {
+ // Arrange
+ GlobalVariables.AnalyteType = (AnalyteType)(-1);
+
+ // Act & Assert
+ Assert.Throws(() =>
+ {
+ var deconHostViewModel = new DeconHostViewModel(null, null);
+ });
+
+ Assert.Throws(() =>
+ {
+ var deconHostViewModel = new DeconHostViewModel(ClassicPrecursorDeconvolutionParameters, null);
+ });
+
+ // Revert back to default
+ GlobalVariables.AnalyteType = AnalyteType.Peptide;
+ }
+
+ [Test]
+ public void TestDisplayDeconSelectionComboBox_MultipleOptions_Precursor()
+ {
+ // Arrange
+ var viewModel = new DeconHostViewModel();
+ viewModel.PrecursorDeconvolutionParametersList.Add(ClassicPrecursorDeconvolutionParameters.ToViewModel());
+
+ // Act
+ var result = viewModel.DisplayDeconSelectionComboBox;
+
+ // Assert
+ Assert.That(result, Is.True);
+ }
+
+ [Test]
+ public void TestDisplayDeconSelectionComboBox_MultipleOptions_Product()
+ {
+ // Arrange
+ var viewModel = new DeconHostViewModel();
+ viewModel.ProductDeconvolutionParametersList.Add(ClassicProductDeconvolutionParameters.ToViewModel());
+
+ // Act
+ var result = viewModel.DisplayDeconSelectionComboBox;
+
+ // Assert
+ Assert.That(result, Is.True);
+ }
+
+ [Test]
+ public void TestDisplayDeconSelectionComboBox_SingleOption()
+ {
+ // Arrange
+ var viewModel = new DeconHostViewModel();
+
+ // Act
+ var result = viewModel.DisplayDeconSelectionComboBox;
+
+ // Assert
+ Assert.That(result, Is.False);
+ }
+}
\ No newline at end of file
diff --git a/MetaMorpheus/Test/GuiTests/DeconParamsViewModelTest.cs b/MetaMorpheus/Test/GuiTests/DeconParamsViewModelTest.cs
new file mode 100644
index 000000000..1093d9d1e
--- /dev/null
+++ b/MetaMorpheus/Test/GuiTests/DeconParamsViewModelTest.cs
@@ -0,0 +1,267 @@
+using GuiFunctions;
+using MassSpectrometry;
+using NUnit.Framework;
+
+namespace Test.GuiTests;
+
+[TestFixture]
+public class DeconParamsViewModelTest
+{
+ private class TestDeconParamsViewModel : DeconParamsViewModel
+ {
+ public sealed override DeconvolutionParameters Parameters { get; protected set; }
+
+ public TestDeconParamsViewModel(DeconvolutionParameters parameters)
+ {
+ Parameters = parameters;
+ }
+ }
+
+ private DeconvolutionParameters _negativeModeParameters;
+ private TestDeconParamsViewModel _negativeModeViewModel;
+ private DeconvolutionParameters _positiveModeParameters;
+ private TestDeconParamsViewModel _positiveModeViewModel;
+
+ [SetUp]
+ public void SetUp()
+ {
+ _negativeModeParameters = new ClassicDeconvolutionParameters(-20, -2, 5, 3, Polarity.Negative);
+ _negativeModeViewModel = new TestDeconParamsViewModel(_negativeModeParameters);
+
+ _positiveModeParameters = new ClassicDeconvolutionParameters(2, 20, 5, 3, Polarity.Positive);
+ _positiveModeViewModel = new TestDeconParamsViewModel(_positiveModeParameters);
+ }
+
+ [TestCase(0, false, TestName = "MinAssumedChargeState_SetToZero_DoesNotChange")]
+ [TestCase(-1, false, TestName = "MinAssumedChargeState_SetToNegativeInPositiveMode_DoesNotChange")]
+ [TestCase(21, false, TestName = "MinAssumedChargeState_SetAboveMaxInPositiveMode_DoesNotChange")]
+ [TestCase(3, true, TestName = "MinAssumedChargeState_SetToValidPositiveValue_Changes")]
+ public void TestMinAssumedChargeState_PositiveMode(int newValue, bool shouldChange)
+ {
+ _positiveModeViewModel.MinAssumedChargeState = newValue;
+ if (shouldChange)
+ {
+ Assert.That(_positiveModeViewModel.MinAssumedChargeState, Is.EqualTo(newValue));
+ }
+ else
+ {
+ Assert.That(_positiveModeViewModel.MinAssumedChargeState, Is.EqualTo(2));
+ }
+ }
+
+ [TestCase(0, false, TestName = "MaxAssumedChargeState_SetToZero_DoesNotChange")]
+ [TestCase(-4, false, TestName = "MaxAssumedChargeState_SetToNegativeInPositiveMode_DoesNotChange")]
+ [TestCase(1, false, TestName = "MaxAssumedChargeState_SetBelowMinInPositiveMode_DoesNotChange")]
+ [TestCase(25, true, TestName = "MaxAssumedChargeState_SetToValidPositiveValue_Changes")]
+ public void TestMaxAssumedChargeState_PositiveMode(int newValue, bool shouldChange)
+ {
+ _positiveModeViewModel.MaxAssumedChargeState = newValue;
+ if (shouldChange)
+ {
+ Assert.That(_positiveModeViewModel.MaxAssumedChargeState, Is.EqualTo(newValue));
+ }
+ else
+ {
+ Assert.That(_positiveModeViewModel.MaxAssumedChargeState, Is.EqualTo(20));
+ }
+ }
+
+ [TestCase(0, false, TestName = "MinAssumedChargeState_SetToZero_DoesNotChange")]
+ [TestCase(1, false, TestName = "MinAssumedChargeState_SetToPositiveInNegativeMode_DoesNotChange")]
+ [TestCase(-1, false, TestName = "MinAssumedChargeState_SetAboveMaxInNegativeMode_DoesNotChange")]
+ [TestCase(-21, true, TestName = "MinAssumedChargeState_SetToValidNegativeValue_Changes")]
+ public void TestMinAssumedChargeState_NegativeMode(int newValue, bool shouldChange)
+ {
+ _negativeModeViewModel.MinAssumedChargeState = newValue;
+ if (shouldChange)
+ {
+ Assert.That(_negativeModeViewModel.MinAssumedChargeState, Is.EqualTo(newValue));
+ }
+ else
+ {
+ Assert.That(_negativeModeViewModel.MinAssumedChargeState, Is.EqualTo(-20));
+ }
+ }
+
+ [TestCase(0, false, TestName = "MaxAssumedChargeState_SetToZero_DoesNotChange")]
+ [TestCase(1, false, TestName = "MaxAssumedChargeState_SetToPositiveInNegativeMode_DoesNotChange")]
+ [TestCase(-21, false, TestName = "MaxAssumedChargeState_SetBelowMinInNegativeMode_DoesNotChange")]
+ [TestCase(-1, true, TestName = "MaxAssumedChargeState_SetToValidNegativeValue_Changes")]
+ public void TestMaxAssumedChargeState_NegativeMode(int newValue, bool shouldChange)
+ {
+ _negativeModeViewModel.MaxAssumedChargeState = newValue;
+ if (shouldChange)
+ {
+ Assert.That(_negativeModeViewModel.MaxAssumedChargeState, Is.EqualTo(newValue));
+ }
+ else
+ {
+ Assert.That(_negativeModeViewModel.MaxAssumedChargeState, Is.EqualTo(-2));
+ }
+ }
+
+ [TestCase(Polarity.Positive, Polarity.Positive, 5, 12, TestName = "Polarity_SwitchFromPositiveToPositive_NoChange")]
+ [TestCase(Polarity.Negative, Polarity.Negative, -25, -5, TestName = "Polarity_SwitchFromNegativeToNegative_NoChange")]
+ [TestCase(Polarity.Positive, Polarity.Negative, -20, -1, TestName = "Polarity_SwitchFromPositiveToNegative_UpdatesChargeStates")]
+ [TestCase(Polarity.Negative, Polarity.Positive, 1, 12, TestName = "Polarity_SwitchFromNegativeToPositive_UpdatesChargeStates")]
+ public void TestPolaritySwitch(Polarity initialPolarity, Polarity newPolarity, int expectedMinChargeState, int expectedMaxChargeState)
+ {
+ var parameters = new ClassicDeconvolutionParameters(initialPolarity == Polarity.Positive ? 5 : -25, initialPolarity == Polarity.Positive ? 12 : -5, 5, 3, initialPolarity);
+ var viewModel = new TestDeconParamsViewModel(parameters);
+
+ viewModel.Polarity = newPolarity;
+
+ Assert.That(viewModel.Polarity, Is.EqualTo(newPolarity));
+ Assert.That(viewModel.MinAssumedChargeState, Is.EqualTo(expectedMinChargeState));
+ Assert.That(viewModel.MaxAssumedChargeState, Is.EqualTo(expectedMaxChargeState));
+ }
+
+ [Test]
+ public void TestPolaritySwitchWithPreviousValues_PositiveMode()
+ {
+ // Initial setup with positive polarity
+ var parameters = new ClassicDeconvolutionParameters(1, 12, 5, 3, Polarity.Positive);
+ var viewModel = new TestDeconParamsViewModel(parameters);
+
+ // Set previous values
+ viewModel.MinAssumedChargeState = 5;
+ viewModel.MaxAssumedChargeState = 10;
+
+ // Change to negative polarity
+ viewModel.Polarity = Polarity.Negative;
+
+ // Check that defaults got set properly
+ Assert.That(viewModel.MinAssumedChargeState, Is.EqualTo(-20));
+ Assert.That(viewModel.MaxAssumedChargeState, Is.EqualTo(-1));
+
+ // Change back to positive polarity
+ viewModel.Polarity = Polarity.Positive;
+
+ // Assert that previous values are restored correctly
+ Assert.That(viewModel.MinAssumedChargeState, Is.EqualTo(5));
+ Assert.That(viewModel.MaxAssumedChargeState, Is.EqualTo(10));
+ }
+
+ [Test]
+ public void TestPolaritySwitchWithPreviousValues_NegativeMode()
+ {
+ // Initial setup with negative polarity
+ var parameters = new ClassicDeconvolutionParameters(-20, -1, 5, 3, Polarity.Negative);
+ var viewModel = new TestDeconParamsViewModel(parameters);
+
+ // Set previous values
+ viewModel.MinAssumedChargeState = -10;
+ viewModel.MaxAssumedChargeState = -5;
+
+ // Change to positive polarity
+ viewModel.Polarity = Polarity.Positive;
+
+ // Check that defaults got set properly
+ Assert.That(viewModel.MinAssumedChargeState, Is.EqualTo(1));
+ Assert.That(viewModel.MaxAssumedChargeState, Is.EqualTo(12));
+
+ // Change back to negative polarity
+ viewModel.Polarity = Polarity.Negative;
+
+ // Assert that previous values are restored correctly
+ Assert.That(viewModel.MinAssumedChargeState, Is.EqualTo(-10));
+ Assert.That(viewModel.MaxAssumedChargeState, Is.EqualTo(-5));
+ }
+
+ [Test]
+ public void TestToString()
+ {
+ var parameters = new ClassicDeconvolutionParameters(1, 12, 5, 3, Polarity.Positive);
+ var viewModel = new TestDeconParamsViewModel(parameters);
+ Assert.That(viewModel.ToString(), Is.EqualTo(parameters.DeconvolutionType.ToString()));
+ }
+
+ [Test]
+ public void TestEquals_SameObject()
+ {
+ var parameters = new ClassicDeconvolutionParameters(1, 12, 5, 3, Polarity.Positive);
+ var viewModel = new TestDeconParamsViewModel(parameters);
+ Assert.That(viewModel.Equals(viewModel), Is.True);
+ Assert.That(viewModel.Equals((object)viewModel), Is.True);
+ }
+
+ [Test]
+ public void TestEquals_NullObject()
+ {
+ var parameters = new ClassicDeconvolutionParameters(1, 12, 5, 3, Polarity.Positive);
+ var viewModel = new TestDeconParamsViewModel(parameters);
+ Assert.That(viewModel.Equals(null), Is.False);
+ Assert.That(viewModel.Equals((object)null), Is.False);
+ }
+
+ [Test]
+ public void TestEquals_DifferentType()
+ {
+ var parameters = new ClassicDeconvolutionParameters(1, 12, 5, 3, Polarity.Positive);
+ var viewModel = new TestDeconParamsViewModel(parameters);
+ Assert.That(viewModel.Equals(new object()), Is.False);
+ Assert.That(viewModel.Equals((object)new BaseViewModel()), Is.False);
+ }
+
+ [Test]
+ [TestCase(1, 15, Polarity.Negative, TestName = "MinChargeDiffers_NotEqual")]
+ [TestCase(2, 12, Polarity.Negative, TestName = "MaxChargeDiffers_NotEqual")]
+ [TestCase(2, 15, Polarity.Positive, TestName = "PolarityDiffers_NotEqual")]
+ public void TestEquals_DifferentParameters(int minCharge, int maxCharge, Polarity polarity)
+ {
+ var parameters1 = new ClassicDeconvolutionParameters(minCharge, maxCharge, 5, 3, polarity);
+ var viewModel1 = new TestDeconParamsViewModel(parameters1);
+
+ var parameters2 = new ClassicDeconvolutionParameters(2, 15, 5, 3, Polarity.Negative);
+ var viewModel2 = new TestDeconParamsViewModel(parameters2);
+ Assert.That(viewModel1.Equals(viewModel2), Is.False);
+ Assert.That(viewModel1.Equals(null), Is.False);
+ }
+
+ [Test]
+ [TestCase(1, 15, Polarity.Negative, TestName = "MinChargeDiffers_NotEqual")]
+ [TestCase(2, 12, Polarity.Negative, TestName = "MaxChargeDiffers_NotEqual")]
+ [TestCase(2, 15, Polarity.Positive, TestName = "PolarityDiffers_NotEqual")]
+ public void TestEquals_DifferentParameters_obj(int minCharge, int maxCharge, Polarity polarity)
+ {
+ var parameters1 = new ClassicDeconvolutionParameters(minCharge, maxCharge, 5, 3, polarity);
+ var viewModel1 = new TestDeconParamsViewModel(parameters1);
+
+ var parameters2 = new ClassicDeconvolutionParameters(2, 15, 5, 3, Polarity.Negative);
+ var viewModel2 = new TestDeconParamsViewModel(parameters2);
+ Assert.That(viewModel1.Equals((object)viewModel2), Is.False);
+ Assert.That(viewModel1.Equals((object)null), Is.False);
+ }
+
+ [Test]
+ public void TestEquals_SameParameters()
+ {
+ var parameters1 = new ClassicDeconvolutionParameters(1, 12, 5, 3, Polarity.Positive);
+ var viewModel1 = new TestDeconParamsViewModel(parameters1);
+ var parameters2 = new ClassicDeconvolutionParameters(1, 12, 5, 3, Polarity.Positive);
+ var viewModel2 = new TestDeconParamsViewModel(parameters2);
+ Assert.That(viewModel1.Equals(viewModel2), Is.True);
+ }
+
+ [Test]
+ public void TestEquals_SameParameters_Obj()
+ {
+ var parameters1 = new ClassicDeconvolutionParameters(1, 12, 5, 3, Polarity.Positive);
+ var viewModel1 = new TestDeconParamsViewModel(parameters1);
+ var parameters2 = new ClassicDeconvolutionParameters(1, 12, 5, 3, Polarity.Positive);
+ var viewModel2 = new TestDeconParamsViewModel(parameters2);
+ Assert.That(viewModel1.Equals((object)viewModel2), Is.True);
+ }
+
+ [Test]
+ public void TestGetHashCode()
+ {
+ var parameters = new ClassicDeconvolutionParameters(1, 12, 5, 3, Polarity.Positive);
+ var viewModel = new TestDeconParamsViewModel(parameters);
+ var expectedHashCode = parameters.DeconvolutionType.GetHashCode() + parameters.Polarity.GetHashCode() + parameters.MaxAssumedChargeState.GetHashCode();
+ Assert.That(viewModel.GetHashCode(), Is.EqualTo(expectedHashCode));
+
+ viewModel = new TestDeconParamsViewModel(null);
+ Assert.That(viewModel.GetHashCode(), Is.EqualTo(0));
+ }
+}
\ No newline at end of file
diff --git a/MetaMorpheus/Test/GuiFunctionsTest.cs b/MetaMorpheus/Test/GuiTests/GuiFunctionsTest.cs
similarity index 94%
rename from MetaMorpheus/Test/GuiFunctionsTest.cs
rename to MetaMorpheus/Test/GuiTests/GuiFunctionsTest.cs
index 5bc8f7687..1ee503eb8 100644
--- a/MetaMorpheus/Test/GuiFunctionsTest.cs
+++ b/MetaMorpheus/Test/GuiTests/GuiFunctionsTest.cs
@@ -8,7 +8,7 @@
using System.Threading.Tasks;
using UsefulProteomicsDatabases;
-namespace Test
+namespace Test.GuiTests
{
[TestFixture]
public static class GuiFunctionsTest
@@ -28,7 +28,7 @@ public static class GuiFunctionsTest
[TestCase("UP000000625", false, false, false, false, "\\UP000000625_withUnreviewed.fasta")]
public static void TestGetUniprotFilename(string proteomeID, bool reviewed, bool isoforms, bool xmlFormat, bool compressed, string expectedResult)
{
- if(expectedResult.Equals("\\UP000000625_reviewed.xml.gz") && isoforms) // This should only be written once, during the first test case
+ if (expectedResult.Equals("\\UP000000625_reviewed.xml.gz") && isoforms) // This should only be written once, during the first test case
{
Console.WriteLine("Beginning Uniprot database test.");
}
@@ -101,12 +101,12 @@ public static async Task UniprotHtmlQueryTest(string proteomeID, bool reviewed,
File.Delete(filePath);
- if(testName.Equals("11.fasta")) // only triggers for last test cases
+ if (testName.Equals("11.fasta")) // only triggers for last test cases
{
Console.WriteLine("Finished with Uniprot HTML query test.");
}
- Assert.That(reader.Count == listCount);
+ NUnit.Framework.Assert.That(reader.Count == listCount);
}
}
}
\ No newline at end of file
diff --git a/MetaMorpheus/Test/GuiTests/MzLibExtensionsTests.cs b/MetaMorpheus/Test/GuiTests/MzLibExtensionsTests.cs
new file mode 100644
index 000000000..6d063bbba
--- /dev/null
+++ b/MetaMorpheus/Test/GuiTests/MzLibExtensionsTests.cs
@@ -0,0 +1,34 @@
+using System;
+using GuiFunctions;
+using MassSpectrometry;
+using NUnit.Framework;
+using Assert = NUnit.Framework.Assert;
+
+namespace Test.GuiTests;
+
+[TestFixture]
+public class MzLibExtensionsTests
+{
+ [Test]
+ public void ToViewModel_WithClassicDeconvolutionParameters_ReturnsClassicDeconParamsViewModel()
+ {
+ // Arrange
+ var classicParams = new ClassicDeconvolutionParameters(1, 12, 10, 1);
+
+ // Act
+ var result = classicParams.ToViewModel();
+
+ // Assert
+ Assert.That(result, Is.InstanceOf());
+ }
+
+ [Test]
+ public void ToViewModel_WithUnsupportedParameters_ThrowsNotImplementedException()
+ {
+ // Arrange
+ var unsupportedParams = new ExampleNewDeconvolutionParametersTemplate(1, 20);
+
+ // Act & Assert
+ Assert.That(() => unsupportedParams.ToViewModel(), Throws.TypeOf());
+ }
+}
\ No newline at end of file
diff --git a/MetaMorpheus/Test/MatchIonsOfAllCharges.cs b/MetaMorpheus/Test/MatchIonsOfAllCharges.cs
index 49de53381..7388b3d02 100644
--- a/MetaMorpheus/Test/MatchIonsOfAllCharges.cs
+++ b/MetaMorpheus/Test/MatchIonsOfAllCharges.cs
@@ -132,7 +132,7 @@ public static void TestMatchIonsOfAllChargesTopDown()
MetaMorpheusTask.DetermineAnalyteType(CommonParameters);
// test output file name (should be proteoform and not peptide)
- Assert.That(GlobalVariables.AnalyteType == "Proteoform");
+ Assert.That(GlobalVariables.AnalyteType.ToString() == "Proteoform");
var variableModifications = new List();
var fixedModifications = new List();
diff --git a/MetaMorpheus/Test/MetaDraw/MetaDrawSettingsAndViewsTest.cs b/MetaMorpheus/Test/MetaDraw/MetaDrawSettingsAndViewsTest.cs
index 9e9bfbf6c..91d9ba161 100644
--- a/MetaMorpheus/Test/MetaDraw/MetaDrawSettingsAndViewsTest.cs
+++ b/MetaMorpheus/Test/MetaDraw/MetaDrawSettingsAndViewsTest.cs
@@ -595,9 +595,13 @@ public static void TestDrawnSequenceColorConversions()
var colorBrushfromName = DrawnSequence.ParseColorBrushFromName(oxyBlue.GetColorName());
Assert.That(colorBrushfromName.Color == brushBlue.Color);
+ var colorBrushfromNameBad = DrawnSequence.ParseColorBrushFromName("humbug");
+ Assert.That(colorBrushfromNameBad.Color == Colors.Aqua);
var oxyFromName = DrawnSequence.ParseOxyColorFromName(oxyBlue.GetColorName());
Assert.That(oxyFromName == oxyBlue);
+ var oxyFromNameBad = DrawnSequence.ParseOxyColorFromName("gobbledygook");
+ Assert.That(oxyFromNameBad == MetaDrawSettings.FallbackColor);
var colorFromOxy = DrawnSequence.ParseColorFromOxyColor(oxyBlue);
Assert.That(colorFromOxy == colorBlue);
diff --git a/MetaMorpheus/Test/SearchEngineTests.cs b/MetaMorpheus/Test/SearchEngineTests.cs
index abc83c43a..7f7446c9d 100644
--- a/MetaMorpheus/Test/SearchEngineTests.cs
+++ b/MetaMorpheus/Test/SearchEngineTests.cs
@@ -979,6 +979,29 @@ public static void TestNonSpecificEnzymeSearchEngineSingleN()
Assert.That(allPsmsArray[0].BaseSequence, Is.EqualTo("QQQGGGG"));
}
+ [Test]
+ public static void TestNonSpecificEnzymeSearchEngine()
+ {
+ var myTomlPath = Path.Combine(TestContext.CurrentContext.TestDirectory, @"TestData\NonSpecificSearchToml.toml");
+ var searchTaskLoaded = Toml.ReadFile(myTomlPath, MetaMorpheusTask.tomlConfig);
+ string outputFolder = Path.Combine(TestContext.CurrentContext.TestDirectory, @"TestData\NonSpecificSearchTest");
+ Directory.CreateDirectory(outputFolder);
+ string myFile = Path.Combine(TestContext.CurrentContext.TestDirectory, @"TestData\TaGe_SA_A549_3_snip.mzML");
+ string myDatabase = Path.Combine(TestContext.CurrentContext.TestDirectory, @"TestData\bosTaurusEnamPruned.xml");
+
+ var engineToml = new EverythingRunnerEngine(new List<(string, MetaMorpheusTask)> { ("SearchTOML", searchTaskLoaded) }, new List { myFile }, new List { new DbForTask(myDatabase, false) }, outputFolder);
+ engineToml.Run();
+
+ string psmFile = Path.Combine(outputFolder, @"SearchTOML\AllPSMs.psmtsv");
+
+ List parsedPsms = PsmTsvReader.ReadTsv(psmFile, out var warnings);
+
+ Assert.That(parsedPsms.Count, Is.EqualTo(38)); //total psm count
+
+ Directory.Delete(outputFolder, true);
+
+ }
+
[Test]
public static void TestNonSpecificEnzymeSearchEngineSingleNLowCID()
diff --git a/MetaMorpheus/Test/Test.csproj b/MetaMorpheus/Test/Test.csproj
index 3c3e7e879..acf1fbba5 100644
--- a/MetaMorpheus/Test/Test.csproj
+++ b/MetaMorpheus/Test/Test.csproj
@@ -24,7 +24,7 @@
-
+
@@ -217,6 +217,9 @@
Always
+
+ Always
+
Always
@@ -325,6 +328,9 @@
Always
+
+ Always
+
Always
diff --git a/MetaMorpheus/Test/TestData/NonSpecificSearchToml.toml b/MetaMorpheus/Test/TestData/NonSpecificSearchToml.toml
new file mode 100644
index 000000000..368d88329
--- /dev/null
+++ b/MetaMorpheus/Test/TestData/NonSpecificSearchToml.toml
@@ -0,0 +1,100 @@
+TaskType = "Search"
+
+[SearchParameters]
+DisposeOfFileWhenDone = true
+DoParsimony = true
+ModPeptidesAreDifferent = false
+NoOneHitWonders = false
+MatchBetweenRuns = false
+Normalize = false
+QuantifyPpmTol = 5.0
+DoHistogramAnalysis = false
+SearchTarget = true
+DecoyType = "Reverse"
+MassDiffAcceptorType = "OneMM"
+WritePrunedDatabase = true
+KeepAllUniprotMods = true
+DoLocalizationAnalysis = false
+DoLabelFreeQuantification = false
+UseSharedPeptidesForLFQ = false
+DoMultiplexQuantification = false
+MultiplexModId = "TMT10"
+DoSpectralRecovery = false
+SearchType = "NonSpecific"
+LocalFdrCategories = ["FullySpecific", "SemiSpecific", "NonSpecific"]
+MaxFragmentSize = 10800.0
+MinAllowedInternalFragmentLength = 0
+HistogramBinTolInDaltons = 0.003
+MaximumMassThatFragmentIonScoreIsDoubled = 0.0
+WriteMzId = true
+WritePepXml = false
+WriteHighQValuePsms = true
+WriteDecoys = true
+WriteContaminants = true
+WriteIndividualFiles = true
+WriteSpectralLibrary = false
+UpdateSpectralLibrary = false
+CompressIndividualFiles = false
+TCAmbiguity = "RemoveContaminant"
+IncludeModMotifInMzid = false
+
+[SearchParameters.ModsToWriteSelection]
+'N-linked glycosylation' = 3
+'O-linked glycosylation' = 3
+'Other glycosylation' = 3
+'Common Biological' = 3
+'Less Common' = 3
+Metal = 3
+'2+ nucleotide substitution' = 3
+'1 nucleotide substitution' = 3
+UniProt = 2
+
+[CommonParameters]
+TaskDescriptor = "SearchTask"
+MaxThreadsToUsePerFile = 63
+ListOfModsFixed = ""
+ListOfModsVariable = "Common Variable\tOxidation on M"
+DoPrecursorDeconvolution = true
+UseProvidedPrecursorInfo = true
+DeconvolutionMaxAssumedChargeState = 12
+TotalPartitions = 1
+ProductMassTolerance = "±20.0000 PPM"
+PrecursorMassTolerance = "±15.0000 PPM"
+AddCompIons = true
+QValueThreshold = 0.01
+PepQValueThreshold = 1.0
+ScoreCutoff = 5.0
+QValueCutoffForPepCalculation = 0.005
+ReportAllAmbiguity = true
+NumberOfPeaksToKeepPerWindow = 200
+MinimumAllowedIntensityRatioToBasePeak = 0.01
+NormalizePeaksAccrossAllWindows = false
+TrimMs1Peaks = false
+TrimMsMsPeaks = true
+CustomIons = []
+AssumeOrphanPeaksAreZ1Fragments = true
+MaxHeterozygousVariants = 4
+MinVariantDepth = 1
+AddTruncations = false
+DissociationType = "HCD"
+SeparationType = "HPLC"
+MS2ChildScanDissociationType = "Unknown"
+MS3ChildScanDissociationType = "Unknown"
+UseMostAbundantPrecursorIntensity = true
+
+[CommonParameters.DigestionParams]
+InitiatorMethionineBehavior = "Variable"
+MaxMissedCleavages = 35
+MaxModificationIsoforms = 1024
+SearchModeType = "None"
+FragmentationTerminus = "C"
+SpecificProtease = "singleC"
+GeneratehUnlabeledProteinsForSilac = true
+KeepNGlycopeptide = false
+KeepOGlycopeptide = false
+Protease = "singleC"
+MinPeptideLength = 7
+MaxPeptideLength = 36
+MaxModsForPeptide = 2
+
+[[FileSpecificParameters]]
diff --git a/MetaMorpheus/Test/TestData/bosTaurusEnamPruned.xml b/MetaMorpheus/Test/TestData/bosTaurusEnamPruned.xml
new file mode 100644
index 000000000..9a5508e6c
--- /dev/null
+++ b/MetaMorpheus/Test/TestData/bosTaurusEnamPruned.xml
@@ -0,0 +1,5181 @@
+
+
+ ID Acetylation on K
+MT Common Biological
+TG K
+PP Anywhere.
+CF C2H2O
+MM 42.010564684
+DR Unimod; 1
+NL ETD:45.0204
+DI HCD:125.084063979
+
+//
+ ID ADP-ribosylation on S
+MT Common Biological
+TG S
+PP Anywhere.
+CF C15H21N5O13P2
+MM 541.06110975
+DR Unimod; 213
+
+//
+ ID Ammonia loss on N
+MT Common Artifact
+TG N
+PP Anywhere.
+CF H-3N-1
+MM -17.026549101
+DR Unimod; 385
+
+//
+ ID Butyrylation on K
+MT Common Biological
+TG K
+PP Anywhere.
+CF C4H6O
+MM 70.041864813
+DR Unimod; 1289
+DI HCD:153.115323533
+
+//
+ ID Calcium on E
+MT Metal
+TG E
+PP Anywhere.
+CF H-2Ca
+MM 37.946940799
+DR Unimod; 951
+
+//
+ ID Carbamyl on K
+MT Common Artifact
+TG K
+PP Anywhere.
+CF CHNO
+MM 43.005813656
+DR Unimod; 5
+
+//
+ ID Carbamyl on M
+MT Common Artifact
+TG M
+PP Anywhere.
+CF CHNO
+MM 43.005813656
+DR Unimod; 5
+
+//
+ ID Carbamyl on R
+MT Common Artifact
+TG R
+PP Anywhere.
+CF CHNO
+MM 43.005813656
+DR Unimod; 5
+
+//
+ ID Carbamyl on X
+MT Common Artifact
+TG X
+PP Peptide N-terminal.
+CF CHNO
+MM 43.005813656
+DR Unimod; 5
+
+//
+ ID Carboxylation on D
+MT Common Biological
+TG D
+PP Anywhere.
+CF CO2
+MM 43.989829239
+DR Unimod; 299
+
+//
+ ID Carboxylation on E
+MT Common Biological
+TG E
+PP Anywhere.
+CF CO2
+MM 43.989829239
+DR Unimod; 299
+
+//
+ ID Carboxylation on K
+MT Common Biological
+TG K
+PP Anywhere.
+CF CO2
+MM 43.989829239
+DR Unimod; 299
+
+//
+ ID Citrullination on R
+MT Common Biological
+TG R
+PP Anywhere.
+CF H-1N-1O
+MM 0.984015583
+DR Unimod; 7
+NL HCD:43.0058
+DI HCD:129.090223533
+
+//
+ ID Cu[I] on D
+MT Metal
+TG D
+PP Anywhere.
+CF H-1Cu
+MM 61.921772688
+DR Unimod; 531
+
+//
+ ID Cu[I] on E
+MT Metal
+TG E
+PP Anywhere.
+CF H-1Cu
+MM 61.921772688
+DR Unimod; 531
+
+//
+ ID Deamidation on N
+MT Common Artifact
+TG N
+PP Anywhere.
+CF H-1N-1O
+MM 0.984015583
+DR Unimod; 7
+
+//
+ ID Deamidation on Q
+MT Common Artifact
+TG Q
+PP Anywhere.
+CF H-1N-1O
+MM 0.984015583
+DR Unimod; 7
+
+//
+ ID Dimethylation on K
+MT Common Biological
+TG K
+PP Anywhere.
+CF C2H4
+MM 28.031300129
+DR Unimod; 36
+
+//
+ ID Dimethylation on R
+MT Common Biological
+TG R
+PP Anywhere.
+CF C2H4
+MM 28.031300129
+DR Unimod; 36
+NL ETD:31.0422 or ETD:45.0579
+
+//
+ ID Fe[II] on D
+MT Metal
+TG D
+PP Anywhere.
+CF H-2Fe
+MM 53.919286266
+DR Unimod; 952
+
+//
+ ID Fe[II] on E
+MT Metal
+TG E
+PP Anywhere.
+CF H-2Fe
+MM 53.919286266
+DR Unimod; 952
+
+//
+ ID Formylation on K
+MT Common Biological
+TG K
+PP Anywhere.
+CF CO
+MM 27.99491462
+DR Unimod; 122
+DI HCD:111.068423533
+
+//
+ ID Glutarylation on K
+MT Common Biological
+TG K
+PP Anywhere.
+CF C5H6O3
+MM 114.031694052
+DR Unimod; 1848
+NL ETD:115.0395
+DI HCD:181.110323533
+
+//
+ ID HexNAc on Nxs
+MT Common Biological
+TG Nxs
+PP Anywhere.
+CF C8H13NO5
+MM 203.079372521
+DR Unimod; 43
+NL AnyActivationType:203.079372521
+
+//
+ ID HexNAc on S
+MT Common Biological
+TG S
+PP Anywhere.
+CF C8H13NO5
+MM 203.079372521
+DR Unimod; 43
+NL AnyActivationType:203.079372521
+
+//
+ ID HexNAc on T
+MT Common Biological
+TG T
+PP Anywhere.
+CF C8H13NO5
+MM 203.079372521
+DR Unimod; 43
+NL AnyActivationType:203.079372521
+
+//
+ ID Hydroxybutyrylation on K
+MT Common Biological
+TG K
+PP Anywhere.
+CF C4H6O2
+MM 86.036779433
+DI HCD:169.110323533
+
+//
+ ID Hydroxylation on K
+MT Common Biological
+TG K
+PP Anywhere.
+CF O
+MM 15.99491462
+DR Unimod; 35
+
+//
+ ID Hydroxylation on N
+MT Common Biological
+TG N
+PP Anywhere.
+CF O
+MM 15.99491462
+DR Unimod; 35
+
+//
+ ID Hydroxylation on P
+MT Common Biological
+TG P
+PP Anywhere.
+CF O
+MM 15.99491462
+DR Unimod; 35
+DI HCD:170.069143
+
+//
+ ID Magnesium on D
+MT Metal
+TG D
+PP Anywhere.
+CF H-2Mg
+MM 21.969391633
+DR Unimod; 956
+
+//
+ ID Magnesium on E
+MT Metal
+TG E
+PP Anywhere.
+CF H-2Mg
+MM 21.969391633
+DR Unimod; 956
+
+//
+ ID Malonylation on K
+MT Common Biological
+TG K
+PP Anywhere.
+CF C3H2O3
+MM 86.000393923
+DR Unimod; 747
+NL ETD:87.0082
+NL HCD:43.9898
+DI HCD:125.084063979 or HCD:169.073923533
+
+//
+ ID Methylation on K
+MT Common Biological
+TG K
+PP Anywhere.
+CF CH2
+MM 14.015650064
+DR Unimod; 34
+
+//
+ ID Methylation on R
+MT Common Biological
+TG R
+PP Anywhere.
+CF CH2
+MM 14.015650064
+DR Unimod; 34
+
+//
+ ID Phosphorylation on S
+MT Common Biological
+TG S
+PP Anywhere.
+CF HO3P
+MM 79.966330889
+DR Unimod; 21
+NL HCD:0 or HCD:97.976895573
+
+//
+ ID Phosphorylation on T
+MT Common Biological
+TG T
+PP Anywhere.
+CF HO3P
+MM 79.966330889
+DR Unimod; 21
+NL HCD:0 or HCD:97.976895573
+
+//
+ ID Phosphorylation on Y
+MT Common Biological
+TG Y
+PP Anywhere.
+CF HO3P
+MM 79.966330889
+DR Unimod; 21
+NL HCD:0 or HCD:97.976895573
+DI HCD:215.034744803
+
+//
+ ID Potassium on E
+MT Metal
+TG E
+PP Anywhere.
+CF H-1K
+MM 37.955881454
+DR Unimod; 530
+
+//
+ ID Pyridoxal phosphate on K
+MT Common Biological
+TG K
+PP Anywhere.
+CF C8H8NO5P
+MM 229.014009359
+DR Unimod; 46
+
+//
+ ID Sodium on D
+MT Metal
+TG D
+PP Anywhere.
+CF H-1Na
+MM 21.98194425
+DR Unimod; 30
+
+//
+ ID Sodium on E
+MT Metal
+TG E
+PP Anywhere.
+CF H-1Na
+MM 21.98194425
+DR Unimod; 30
+
+//
+ ID Succinylation on K
+MT Common Biological
+TG K
+PP Anywhere.
+CF C4H4O3
+MM 100.016043988
+DR Unimod; 64
+NL ETD:101.0239
+DI HCD:183.089523533
+
+//
+ ID Sulfonation on Y
+MT Common Biological
+TG Y
+PP Anywhere.
+CF O3S
+MM 79.956815033
+DR Unimod; 40
+NL AnyActivationType:79.956815033
+
+//
+ ID Trimethylation on K
+MT Common Biological
+TG K
+PP Anywhere.
+CF C3H6
+MM 42.046950193
+DR Unimod; 37
+NL ETD:45.0204
+
+//
+ ID Water Loss on E
+MT Common Artifact
+TG E
+PP Peptide N-terminal.
+CF H-2O-1
+MM -18.010564684
+DR Unimod; 23
+
+//
+ ID Zinc on D
+MT Metal
+TG D
+PP Anywhere.
+CF H-2Zn
+MM 61.913491946
+DR Unimod; 954
+
+//
+ ID Zinc on E
+MT Metal
+TG E
+PP Anywhere.
+CF H-2Zn
+MM 61.913491946
+DR Unimod; 954
+
+//
+
+ Q9XSX7
+ Ameloblastin
+
+
+ Ameloblastin
+
+
+
+ AMBN
+
+
+ Bos taurus
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ MPALKIPLFKMKDMILILCLLKMSSAVPAFPQQPGIPGMASLSLETMRQLGSLQGLNLLSQYSRFGFGKSFNSLWMNGLLPPHSSFPWMRPREHETQQPSLQPQQPGQKPFLQPTVVTSMQNAVQKGVPQPPIYQGHPPLQQAEGPMVEQQVAPSEKPPTTELPGMDFADLQDPPMFPIAHLISRGPMPQNKPSQLYPGIFYVTYGANQLGGRGDPLAYGAIFPGFGGMRPRLGGMPHNPDMGGDFTLEFDSPVAATKGPEKGEGGAQDSPVPEAHLADPESPALLSELAPGALEGLLANPEGNIPNLARGPAGRSRGFLRGVTPAAADPLMTPGLAEVYETYGADETTTLGLQEETTVDSTATPDTQHTLMPRNKAQQPQIKHDAWHFQEP
+
+
+ P02817
+ Amelogenin, X isoform
+
+
+ Amelogenin, X isoform
+
+
+
+ AMELX
+
+
+ Bos taurus
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ MGTWILFACLLGAAFSMPLPPHPGHPGYINFSYEVLTPLKWYQSMIRHPYPSYGYEPMGGWLHHQIIPVVSQQTPQNHALQPHHHIPMVPAQQPVVPQQPMMPVPGQHSMTPTQHHQPNLPLPAQQPFQPQSIQPQPHQPLQPHQPLQPMQPMQPLQPLQPLQPQPPVHPIQPLPPQPPLPPIFPMQPLPPMLPDLPLEAWPATDKTKREEVD
+
+
+ Q99004
+ Amelogenin, Y isoform
+
+
+ Amelogenin, Y isoform
+
+
+
+ AMELY
+
+
+ Bos taurus
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ MGTWILFACLLGAAYSMPLPPHPGHPGYINFSYEVLTPLKWYQNMLRYPYPSYGYEPVGGWLHHQIIPVVSQQSPQNHALQPHHHNPMVPAQQPVVPQQPMMPVPGQHSMTPIQHHQPNLPLPAQQSFQPQPIQPQPHQPLQPQPPVHPIQRLPPQPPLPPIFPMQPLPPVLPDLPLEAWPATDKTKREEVD
+
+
+ F1MKR5
+ Enamelin
+
+
+ Enamelin
+
+
+
+ ENAM
+
+
+ Bos taurus
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ KMLLQCRHEASSPKLDYLVPSGKMKILLVFLSLLGYSIAMPLQMHMPRIPGFSSKSEEMMRYGHFNFMNFPHLAHLSPFYGNGIQLPQLFPQYQMPMWPQPPPNKKSPQKPSSPAAPKQTDQAPETPSPNQPQPTDSPPNQHLKQPSTTTAQPQEEETQTPQAFPPFGNGLFPYQQPPWHIPHVSIPPGFGRPPGSNEEGGNPFFGFFGYHGFGGRPPYYSEEMFEDFEKPKEEDPPKTETPATDPSVNSTVPETNSTQPGAPSPRAGQGGNDTSPAGNNGQDPNTVSNPTVQNNPVVNVSGQGVPRSQTPWRPSQTNIHENYPYPNIRNFPAGRQWHPTGTSMGNRRNGPFYRNQQIQRAPRWNSFVLEGKQAIRLGYPIYRRAYASTVRGNYPNYAGNPVNFRRKPEGPSKQPEGTIAPLGPKHGTTGHNENIQNPKEKPVSQKERIVIPTRDPNGPWRNSQDYGVTKSNYKLPHPEGNILVPNFNSIDQHENSYYPRGDSRGTPNSNGQTQSQNLPKGIILEPRRIPYESEINQPEIKHSTHQPVYPEGSPSPARERFPAGRNTWNQQEISPPFKEDPGRKEEHLPHPSLGSRGRIYYTDYNPYDRRENPPYLRSNSWDERNDPPNTMGQSENPHYPMNTPDPKETIPYNEEGPADPTGDETFPGQTRWSVDESNFKTAPTARYEGKQYTSNQPKEYSPYSLDNLPKPREYFPYGEFYPWSPDENFPSYNTAPTIPLLVENRGYYPTNAVGQEENTMFPSWNSWDHMVQVQGQKERRPYFTRTFWGQPTNLPKAPASPPYHKENQPYFSNSPTGLQKDPTWHEGENLNYGMQITRLNSPEGGHLAFPDLIPPHYPGSQKETRLFHLSQRGPCCAGGSIGPKDNPLALQDYTLFFGLAPGENQDTSPLYTEDSHTKHERYTISPTSILPGQRNSSEKRLPGESQNPSPFRDDVSTLRRNTPCSINNQLSQRGIRPLPEASSLQSKNIPCLKSDLEDGNHVLEQTLEGNQLNERPVDLTPEQLVMDTPDEGPKPEGIPSEVQGNGGKRQQQRPSTILKLPCFDSKLTKYYTSSTGTPSSLGRQGSFDGDPIMPTEIPNSLAELATGAQFQNINVDPLNADDHTPFDPLQVGTNPQDQVQDCLLLQA
+
+
+ O18767
+ Matrix metalloproteinase-20
+
+
+ Matrix metalloproteinase-20
+
+
+
+ MMP20
+
+
+ Bos taurus
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ MLPASGLAVLLVTALKFSTAAPSLPAASPRTSRNNYRLAQAYLDKYYTKKGGPQIGEMVARGGNSTVKKIKELQEFFGLRVTGKLDRATMDVIKRPRCGVPDVANYRLFPGEPKWKKNTLTYRISKYTPSMTPAEVDRAMEMALRAWSSAVPLNFVRINAGEADIMISFETGDHGDSYPFDGPRGTLAHAFAPGEGLGGDTHFDNAEKWTMGTNGFNLFTVAAHEFGHALGLAHSTDPSALMFPTYKYQNPYGFRLPKDDVKGIQALYGPRRAFSGKPTAPHGPPHNPSIPDLCDSNLSFDAVTMLGKELLLFRDRIFWRRQVHLMSGIRPSTITSSFPQLMSNVDAAYEVAERGTAYFFKGPHYWITRGFQMQGPPRTIYDFGFPRYVQRIDAAVYLKDAQKTLFFVGDEYYSYDERKRKMEKDYPKSTEEEFSGVNGQIDAAVELNGYIYFFSGPKAYKSDTEKEDVVSELKSSSWIGC
+
+
+ F1MLB5
+ Kallikrein B1
+
+
+ Kallikrein B1
+
+
+
+ KLK4
+
+
+ Bos taurus
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ MTTAGNSWGWFLGHLLLSVTGSLAWGGSSRIINGEDCRPHSQPWQAALFLENEFFCGGVLVHPQWVLSAAHCFQKSYTIGLGLHSLEADQEPGSQMIEAHLSIQHPEYNKPSLANDLMLIKLEESVPPSDTIQDISIASQCPAAGGDSCLVSGWGRLVNGKLPKVLQCVNISVVSEKICSELYAHVYHPSMFCAGGGQDQKDSCHGDSGGPLVCNGSLQGLVSFGQAQCGQPYVPSVYTNLCKFTDWIQKTIQAS
+
+
+ A1YQ93
+ Odontogenic ameloblast-associated protein
+
+
+ Odontogenic ameloblast-associated protein
+
+
+
+ ODAM
+
+
+ Bos taurus
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ MRTLILLGILGATMSAPLIPQHLMSASNSNELLLNLNNAQLRPLQLQGPFNSWFPPFPGILQQQQQNQVPGLSPFSLSTREWFAGLVPNQIFVPGQVSFAQGTQAGQLDPSQPQTPQQTQRGPKNVMPSVFFKMPQEQAQMLQYYPVYMFLPWEQPQQTVAQSPPQTREQLFEKQMPFYTEFGYIPQQVEPVMPVEQQQPVFDPFLGTAPEIAAMPAEVSPYLQKEMINFQHTNAGIFIPSTSQKPSTTIFFTSAVDPIITRELTEKKAKTDSLKEP
+
+
\ No newline at end of file
diff --git a/MetaMorpheus/Test/TestTopDown.cs b/MetaMorpheus/Test/TestTopDown.cs
index c76f95057..13b5e4c8a 100644
--- a/MetaMorpheus/Test/TestTopDown.cs
+++ b/MetaMorpheus/Test/TestTopDown.cs
@@ -30,7 +30,7 @@ public static void TestClassicSearchEngineTopDown()
MetaMorpheusTask.DetermineAnalyteType(CommonParameters);
// test output file name (should be proteoform and not peptide)
- Assert.That(GlobalVariables.AnalyteType == "Proteoform");
+ Assert.That(GlobalVariables.AnalyteType == AnalyteType.Proteoform);
var variableModifications = new List();
var fixedModifications = new List();