protected override void DoTest() { // Create the modification and library spec used in this test var phosphoLossMod = new StaticMod("Phospho Loss", "S, T", null, true, "HPO3", LabelAtoms.None, RelativeRT.Matching, null, null, new[] { new FragmentLoss("H3PO4"), }); var multipleLossMod = new StaticMod("Multiple Loss-only", "D", null, false, null, LabelAtoms.None, RelativeRT.Matching, null, null, new[] { new FragmentLoss("NH3"), new FragmentLoss("H2O"), new FragmentLoss(null, 20, 25) }); var heavyKMod = new StaticMod("Heavy K", "K", ModTerminus.C, null, LabelAtoms.C13 | LabelAtoms.N15, null, null); var librarySpec = new BiblioSpecLiteSpec("Phospho Library", TestFilesDir.GetTestPath("phospho_30882_v2.blib")); // Prepare settings for this test Settings.Default.StaticModList.Clear(); Settings.Default.StaticModList.AddRange(StaticModList.GetDefaultsOn()); Settings.Default.StaticModList.Add(phosphoLossMod); Settings.Default.HeavyModList.Clear(); Settings.Default.HeavyModList.Add(heavyKMod); Settings.Default.SpectralLibraryList.Clear(); Settings.Default.SpectralLibraryList.Add(librarySpec); // Prepare document settings for this test const int countIons = 6; var settings = SrmSettingsList.GetDefault() .ChangePeptideModifications(mods => mods.ChangeStaticModifications(new List <StaticMod>(mods.StaticModifications) { phosphoLossMod })) .ChangePeptideLibraries(lib => lib.ChangeLibrarySpecs(new[] { librarySpec })) .ChangeTransitionLibraries(tlib => tlib.ChangeIonCount(countIons)); RunUI(() => SkylineWindow.ModifyDocument("Set test settings", doc => doc.ChangeSettings(settings))); WaitForDocumentLoaded(); // Add FASTA sequence RunUI(() => SkylineWindow.Paste(TEXT_FASTA_SPROT)); var docLibLoss = SkylineWindow.Document; AssertEx.IsDocumentState(docLibLoss, null, 3, 4, 24); Assert.AreEqual(7, GetLossCount(docLibLoss, 1)); string lossLabel = "-" + Math.Round(phosphoLossMod.Losses[0].MonoisotopicMass, 1); for (int i = 0; i < docLibLoss.PeptideTransitionGroupCount; i++) { var pathTranGroup = docLibLoss.GetPathTo((int)SrmDocument.Level.TransitionGroups, i); var nodeGroup = (TransitionGroupDocNode)docLibLoss.FindNode(pathTranGroup); if (!nodeGroup.Children.Contains(child => ((TransitionDocNode)child).HasLoss)) { continue; } // Select the transition groups that contain loss ions SelectNode(SrmDocument.Level.TransitionGroups, i); WaitForGraphs(); // Make sure the spectrum graph contains some -98 ions RunUI(() => Assert.IsTrue(SkylineWindow.GraphSpectrum.IonLabels.Contains(label => label.Contains(lossLabel)), string.Format("Missing loss labels in spectrum graph for {0}", nodeGroup.TransitionGroup.Peptide.Target))); // Make sure the transition tree nodes contain -98 ions RunUI(() => Assert.IsTrue(GetChildLabels(SkylineWindow.SelectedNode).Contains(label => label.Contains(lossLabel)), string.Format("Missing loss labels in transition tree nodes for {0}", nodeGroup.TransitionGroup.Peptide.Target))); } // Make the settings significantly more complex // - 2 neutral losses // - a second modification with 3 potential neutral losses // - a heavy labeling modification // - only ions between precursor m/z and last ion // - allow both y- and b- ions // - no proline peaks // - only use filtered ions to match library RunUI(() => SkylineWindow.ModifyDocument("Set test settings", doc => doc.ChangeSettings(doc.Settings.ChangePeptideModifications(mod => mod.ChangeMaxNeutralLosses(2) .ChangeStaticModifications(new List <StaticMod>(mod.StaticModifications) { multipleLossMod }) .ChangeModifications(IsotopeLabelType.heavy, new[] { heavyKMod })) .ChangeTransitionFilter(filter => filter.ChangeFragmentRangeFirstName("m/z > precursor") .ChangeFragmentRangeLastName("last ion") .ChangePeptideIonTypes(new[] { IonType.y, IonType.b }) .ChangeMeasuredIons(new MeasuredIon[0])) .ChangeTransitionLibraries(lib => lib.ChangePick(TransitionLibraryPick.filter))))); var docComplex = WaitForDocumentChange(docLibLoss); // The document has 2 variable mod peptides at the protein terminus Assert.AreEqual(docLibLoss.PeptideTransitionGroupCount * 2 - 2, docComplex.PeptideTransitionGroupCount); Assert.AreEqual(4, GetLossCount(docComplex, 2)); Assert.AreEqual(16, GetLossCount(docComplex, 1)); foreach (var nodePep in docComplex.Peptides) { if (nodePep.Children.Count != 2) { continue; } var nodeGroup1 = (TransitionGroupDocNode)nodePep.Children[0]; var nodeGroup2 = (TransitionGroupDocNode)nodePep.Children[1]; Assert.IsTrue(nodeGroup1.EquivalentChildren(nodeGroup2)); } // CONSIDER: Can't check cloned because of libraries. Maybe add a new method for this // AssertEx.Serializable(docComplex, AssertEx.DocumentCloned); SelectNode(SrmDocument.Level.Molecules, 1); WaitForGraphs(); // Verify that the ion labels in the graph match those in the tree view RunUI(() => { var nodePepSelected = (PeptideDocNode)docComplex.FindNode(SkylineWindow.SelectedPath); string[] ionLabels = SkylineWindow.GraphSpectrum.IonLabels.ToArray(); foreach (TransitionGroupDocNode nodeGroup in nodePepSelected.Children) { var setSeenRanks = new HashSet <int>(); foreach (TransitionDocNode nodeTran in nodeGroup.Children) { Assert.IsTrue(nodeTran.HasLibInfo); // Make sure the rank has not been seen int rankTran = nodeTran.LibInfo.Rank; Assert.IsFalse(setSeenRanks.Contains(rankTran)); setSeenRanks.Add(rankTran); // And it is within the expected range Assert.IsTrue(1 <= rankTran && rankTran <= countIons); // Make sure there is a matching label in the spectrum graph var regexRank = nodeTran.HasLoss ? new Regex(string.Format(@"(\w)(\d+) -([^ +]+).* \({0}\)", string.Format(Resources.AbstractSpectrumGraphItem_GetLabel_rank__0__, rankTran))) : new Regex(string.Format(@"(\w)(\d+).* \({0}\)", string.Format(Resources.AbstractSpectrumGraphItem_GetLabel_rank__0__, rankTran))); int iLabel = ionLabels.IndexOf(regexRank.IsMatch); Assert.IsTrue(iLabel != -1); var match = regexRank.Match(ionLabels[iLabel]); Assert.AreEqual(nodeTran.Transition.IonType.ToString(), match.Groups[1].Value); Assert.AreEqual(nodeTran.Transition.Ordinal, int.Parse(match.Groups[2].Value)); if (nodeTran.HasLoss) { Assert.AreEqual(nodeTran.Losses.Mass, double.Parse(match.Groups[3].Value), 0.1); } } } }); // Make sure setting losses as included Never works { var docBeforeNever = SkylineWindow.Document; var peptideSettingsUINever = ShowDialog <PeptideSettingsUI>(() => SkylineWindow.ShowPeptideSettingsUI(PeptideSettingsUI.TABS.Modifications)); var editModsDlgNever = ShowEditStaticModsDlg(peptideSettingsUINever); RunUI(() => editModsDlgNever.SelectItem(phosphoLossMod.Name)); var editModDlgNever = ShowDialog <EditStaticModDlg>(editModsDlgNever.EditItem); RunUI(() => editModDlgNever.LossSelectedIndex = 0); RunDlg <EditFragmentLossDlg>(editModDlgNever.EditLoss, dlg => { dlg.Inclusion = LossInclusion.Never; dlg.OkDialog(); }); RunDlg <MultiButtonMsgDlg>(editModDlgNever.OkDialog, dlg => dlg.Btn1Click()); OkDialog(editModsDlgNever, editModsDlgNever.OkDialog); OkDialog(peptideSettingsUINever, peptideSettingsUINever.OkDialog); var docAfterNever = WaitForDocumentChange(docBeforeNever); Assert.AreEqual(0, GetLossCount(docAfterNever, 1)); } }
public void TestModificationMatcher() { InitSeqs(); var carbC = StaticModList.GetDefaultsOn()[0]; // Test exception thrown if unable to match - mass. UpdateMatcherFail(STR_FAIL_MASS); UpdateMatcherFail(STR_FAIL_NOT_A_NUMBER); // Test exception thrown if unable to match - name. UpdateMatcherFail(STR_FAIL_NAME); // Can't match empty modifications. UpdateMatcherFail(STR_FAIL_EMPTY_MOD); UpdateMatcherFail(STR_FAIL_EMPTY_MOD2); // Can't match double modifications. UpdateMatcherFail(STR_FAIL_DOUBLE_MOD); // Test exception thrown if unimod not specified correctly UpdateMatcherFail(STR_FAIL_UNIMOD); UpdateMatcherFail(STR_UNKNOWN_UNIMOD); // Can't phosphorylate tryptophan UpdateMatcherFail(STR_FAIL_WRONG_AA_UNIMOD); // Can't put C-terminal modification in middle of peptide UpdateMatcherFail(STR_FAIL_UNIMOD_TERMINUS); // Test mods in UniMod match correctly. UpdateMatcher(StaticModList.GetDefaultsOn(), HeavyModList.GetDefaultsOn(), null, null); // A sequence with no modifications should not be explicitly modified. Assert.IsFalse(MATCHER.GetModifiedNode(STR_NO_MODS).HasExplicitMods); var nodeCysOxi = MATCHER.GetModifiedNode(STR_CYS_AND_OXI); Assert.IsTrue(nodeCysOxi.HasExplicitMods); Assert.IsFalse(nodeCysOxi.ExplicitMods.HasHeavyModifications); // Modifications should match by name. Assert.IsTrue(MATCHER.GetModifiedNode(STR_MOD_BY_NAME).ExplicitMods.StaticModifications.Contains(mod => Equals(mod.Modification.Name, "Phospho (ST)"))); // Test can find terminal modification Assert.IsTrue(MATCHER.GetModifiedNode(STR_TERM_ONLY).ExplicitMods.HeavyModifications.Contains(mod => mod.Modification.EquivalentAll(UniMod.GetModification("Label:13C(6) (C-term R)", false)))); // Test can find matches on terminus that are not terminal Assert.IsTrue(MATCHER.GetModifiedNode(STR_MOD_BY_NAME).ExplicitMods.StaticModifications.Contains(mod => mod.Modification.Terminus == null)); // Test matching negative masses Assert.IsTrue(MATCHER.GetModifiedNode(STR_AMMONIA_LOSS).ExplicitMods.StaticModifications.Contains(mod => mod.Modification.EquivalentAll(UniMod.GetModification("Ammonia-loss (N-term C)", true)))); // General and specific // If all AAs modified, try for most general modification. Assert.IsTrue(MATCHER.GetModifiedNode(STR_HEAVY_15) .ExplicitMods.HeavyModifications.Contains(mod => mod.Modification.Equivalent(LABEL15_N))); // Updating the settings. // Peptide settings should change to include new mods. var docNew = new SrmDocument(SrmSettingsList.GetDefault()); IdentityPath firstAdded; IdentityPath nextAdded; docNew = docNew.AddPeptideGroups(new[] { new PeptideGroupDocNode(new PeptideGroup(), "PepGroup1", "", new[] { MATCHER.GetModifiedNode(STR_MOD_BY_NAME) }) }, true, null, out firstAdded, out nextAdded); var pepSetNew = MATCHER.GetDocModifications(docNew); Assert.IsTrue(pepSetNew.StaticModifications.Contains(UniMod.GetModification("Phospho (ST)", true).ChangeExplicit(true))); // Update the document to the new settings. var pepSetNew1 = pepSetNew; var settingsNew2 = docNew.Settings.ChangePeptideModifications(mods => pepSetNew1); var lightGlobalMods = new MappedList <string, StaticMod>(); lightGlobalMods.AddRange(settingsNew2.PeptideSettings.Modifications.StaticModifications); var heavyGlobalMods = new MappedList <string, StaticMod>(); heavyGlobalMods.AddRange(settingsNew2.PeptideSettings.Modifications.AllHeavyModifications); // Match again. Test FoundMatches string should now be empty. MATCHER.CreateMatches(docNew.Settings.ChangePeptideModifications(mods => pepSetNew1), new List <string> { STR_MOD_BY_NAME }, lightGlobalMods, heavyGlobalMods); Assert.IsTrue(string.IsNullOrEmpty(MATCHER.FoundMatches)); // Adding 15N to the settings. UpdateMatcher(new[] { carbC }, new[] { LABEL15_N }, null, null); // Test sequences with only explicit heavy mods should not have explicit light mods Assert.IsNull(MATCHER.GetModifiedNode(STR_HEAVY_ONLY).ExplicitMods.StaticModifications); // Test sequences with only explicit light mods should not have explicit heavy mods Assert.IsFalse(MATCHER.GetModifiedNode(STR_LIGHT_ONLY).ExplicitMods.HasHeavyModifications); // Test global mods take precendence over UniMod UpdateMatcher(new[] { carbC }, null, new[] { OXIDATION_M_GLOBAL }, new[] { LABEL15_N }); Assert.IsTrue(MATCHER.GetModifiedNode(STR_CYS_AND_OXI).ExplicitMods.StaticModifications .Contains(mod => Equals(mod.Modification, OXIDATION_M_GLOBAL))); // Test document mods take precendence over UniMod UpdateMatcher(new[] { carbC, METHIONINE_OXIDATION }, null, new[] { OXIDATION_M_GLOBAL }, new[] { LABEL15_N }); Assert.IsFalse(MATCHER.GetModifiedNode(STR_CYS_AND_OXI).HasExplicitMods); // Test exception thrown if match doesn't make sense - wrong AA. UpdateMatcherFail(STR_FAIL_OX_ON_D); // Test exception thrown if match doesn't make sense - wrong terminus. _seqs.Add(STR_FAIL_OX_TERM); AssertEx.ThrowsException <FormatException>(() => UpdateMatcher(new[] { OXIDATION_M_C_TERM }, null, null, null)); _seqs.Remove(STR_FAIL_OX_TERM); // Heavy 15N - All AAs. UpdateMatcher(new[] { carbC, METHIONINE_OXIDATION }, new[] { LABEL15_N }, null, null); // Node should be created from document settings if possible. Assert.IsNull(MATCHER.GetModifiedNode(STR_HEAVY_15).ExplicitMods); // Heavy 15N - specific AA. // If only a specific AA is modified, there must be an explicit mod. Assert.IsTrue(MATCHER.GetModifiedNode(STR_HEAVY_15_F).HasExplicitMods); // Test variable mods match correctly. // Put variable mod in global mod and not on doc - make sure don't get variable mod, // should get explicit mod in that case. var variableMetOx = METHIONINE_OXIDATION.ChangeVariable(true); UpdateMatcher(new[] { carbC }, null, new[] { variableMetOx }, null); Assert.IsTrue(MATCHER.GetModifiedNode(STR_CYS_AND_OXI).HasExplicitMods); Assert.IsFalse(MATCHER.GetModifiedNode(STR_CYS_OXI_PHOS).ExplicitMods.IsVariableStaticMods); Assert.IsFalse(MATCHER.GetModifiedNode(STR_CYS_OXI_PHOS_CAP).ExplicitMods.IsVariableStaticMods); // Add variable mod to doc UpdateMatcher(new[] { carbC, variableMetOx }, null, null, null); // Mod can be created by the settings. Assert.IsTrue(MATCHER.GetModifiedNode(STR_CYS_AND_OXI).HasExplicitMods); Assert.IsTrue(MATCHER.GetModifiedNode(STR_CYS_AND_OXI).ExplicitMods.IsVariableStaticMods); // Mod cannot be created by the settings. Assert.IsFalse(MATCHER.GetModifiedNode(STR_CYS_OXI_PHOS).ExplicitMods.IsVariableStaticMods); Assert.IsFalse(MATCHER.GetModifiedNode(STR_CYS_OXI_PHOS_CAP).ExplicitMods.IsVariableStaticMods); // Add Met Ox to global. Test: +16 finds it. UpdateMatcher(new[] { carbC }, null, new[] { MET_OX_ROUNDED }, null); Assert.IsTrue(MATCHER.GetModifiedNode(STR_CYS_AND_OXI). ExplicitMods.StaticModifications.Contains(mod => Equals(mod.Modification, MET_OX_ROUNDED))); // Test: +15.99 finds UniMod. Assert.IsFalse(MATCHER.GetModifiedNode(STR_HEAVY_15). ExplicitMods.StaticModifications.Contains(mod => Equals(mod.Modification, MET_OX_ROUNDED))); // Add Methionine Oxidation before Met Ox. Test: +16 finds it. UpdateMatcher(new[] { carbC }, null, new[] { METHIONINE_OXIDATION, MET_OX_ROUNDED }, null); Assert.IsFalse(MATCHER.GetModifiedNode(STR_CYS_AND_OXI). ExplicitMods.StaticModifications.Contains(mod => Equals(mod.Modification, MET_OX_ROUNDED))); Assert.IsTrue(MATCHER.GetModifiedNode(STR_CYS_AND_OXI). ExplicitMods.StaticModifications.Contains(mod => Equals(mod.Modification, METHIONINE_OXIDATION))); // Test long masses rounded. Assert.IsTrue(MATCHER.GetModifiedNode(STR_METOX_LONG_MASS).ExplicitMods.StaticModifications.Contains(mod => Equals(mod.Modification, METHIONINE_OXIDATION))); // Test UniMod label types var node = MATCHER.GetModifiedNode(STR_UNIMOD_LABEL); Assert.IsNotNull(node); Assert.IsNull(node.ExplicitMods.StaticModifications); Assert.IsTrue(node.ExplicitMods.HeavyModifications.Contains(mod => Equals(mod.Modification, N_TERM_LABEL))); UpdateMatcherWithNoSequences(new[] { carbC }, new[] { N_TERM_LABEL }, new[] { METHIONINE_OXIDATION, MET_OX_ROUNDED }, null); var nodeNew = MATCHER.GetModifiedNode(STR_UNIMOD_LABEL); Assert.IsNotNull(nodeNew); Assert.IsTrue(nodeNew.TransitionGroups.Any(group => Equals(group.TransitionGroup.LabelType, IsotopeLabelType.heavy))); UpdateMatcher(new[] { carbC }, null, new[] { METHIONINE_OXIDATION, MET_OX_ROUNDED }, null); // Test case where there are lots of unimod labels var nodeUniAll = MATCHER.GetModifiedNode(STR_UNIMOD_ALL); Assert.AreEqual(nodeUniAll.ExplicitMods.HeavyModifications.Count, 10); Assert.IsNull(nodeUniAll.ExplicitMods.StaticModifications); foreach (var mod in nodeUniAll.ExplicitMods.HeavyModifications) { Assert.AreEqual(mod.Modification.ShortName, "+01"); Assert.AreEqual(mod.Modification.UnimodId, 994); } // Test unimod terminal label var nodeUniTerm = MATCHER.GetModifiedNode(STR_UNIMOD_TERMINUS); Assert.AreEqual(nodeUniTerm.ExplicitMods.HeavyModifications.Count, 1); Assert.IsNull(nodeUniTerm.ExplicitMods.StaticModifications); Assert.AreEqual(nodeUniTerm.ExplicitMods.HeavyModifications[0].Modification.Terminus, ModTerminus.C); Assert.AreEqual(nodeUniTerm.ExplicitMods.HeavyModifications[0].Modification.UnimodId, 298); // Basic multi-label test var heavyLabelType2 = new IsotopeLabelType("Heavy2", 1); var typedMod = new TypedModifications(heavyLabelType2, new List <StaticMod> { LABEL15_N }); var peptideMods = new PeptideModifications(new List <StaticMod>(), new List <TypedModifications> { typedMod }); var settingsMultiLabel = SrmSettingsList.GetDefault().ChangePeptideModifications(mods => peptideMods); var defSetSetLight = new MappedList <string, StaticMod>(); defSetSetLight.AddRange(StaticModList.GetDefaultsOn()); var defSetHeavy = new MappedList <string, StaticMod>(); defSetHeavy.AddRange(HeavyModList.GetDefaultsOn()); defSetHeavy.Add(LABEL15_N); MATCHER.CreateMatches(settingsMultiLabel, new List <string> { STR_HEAVY_15_F }, defSetSetLight, defSetHeavy); Assert.IsTrue(MATCHER.GetModifiedNode(STR_HEAVY_15_F).ExplicitMods.GetHeavyModifications().Contains(mod => Equals(mod.LabelType, heavyLabelType2))); // Peptide settings should not change. var docNew0 = new SrmDocument(settingsMultiLabel).AddPeptideGroups(new[] { new PeptideGroupDocNode(new PeptideGroup(), "PepGroup1", "", new[] { MATCHER.GetModifiedNode(STR_HEAVY_15_F) }) }, true, null, out firstAdded, out nextAdded); var settingsNew = MATCHER.GetDocModifications(docNew0); Assert.AreEqual(settingsMultiLabel.PeptideSettings.Modifications.ChangeHasHeavyModifications(false), settingsNew.ChangeHasHeavyModifications(false)); // Finding specific modifications. // If only specific AA modified, try for most specific modification. UpdateMatcher(null, null, null, null, new[] { STR_HEAVY_15_F }); Assert.IsTrue(MATCHER.GetModifiedNode(STR_HEAVY_15_F) .ExplicitMods.HeavyModifications.Contains(mod => mod.Modification.AminoAcids.Contains(c => c == 'F'))); // If only some AAs modified, try for most specific modifications. UpdateMatcher(null, null, null, null, new[] { STR_HEAVY_15_NOT_ALL }); Assert.IsTrue(MATCHER.GetModifiedNode(STR_HEAVY_15_NOT_ALL) .ExplicitMods.HeavyModifications.Contains(mod => mod.Modification.AminoAcids.Contains(c => c == 'I'))); using (var testDir = new TestFilesDir(TestContext, ZIP_FILE)) using (var modMatchDocContainer = InitMatchDocContainer(testDir)) { var libkeyModMatcher = new LibKeyModificationMatcher(); var anlLibSpec = new BiblioSpecLiteSpec("ANL_Combo", testDir.GetTestPath("ANL_Combined.blib")); var yeastLibSpec = new BiblioSpecLiteSpec("Yeast", testDir.GetTestPath("Yeast_atlas_small.blib")); modMatchDocContainer.ChangeLibSpecs(new[] { anlLibSpec, yeastLibSpec }); var docLibraries = modMatchDocContainer.Document.Settings.PeptideSettings.Libraries.Libraries; int anlLibIndex = docLibraries.IndexOf(library => Equals(library.Name, anlLibSpec.Name)); int yeastLibIndex = docLibraries.IndexOf(library => Equals(library.Name, yeastLibSpec.Name)); libkeyModMatcher.CreateMatches(modMatchDocContainer.Document.Settings, docLibraries[anlLibIndex].Keys, defSetSetLight, defSetHeavy); // Test can match 15N Assert.IsTrue(libkeyModMatcher.Matches.Values.Contains(match => match.HeavyMod != null && match.HeavyMod.Equivalent(LABEL15_N))); var uniModMetOx = UniMod.GetModification("Oxidation (M)", true); // Test can match Met Ox Assert.IsTrue(libkeyModMatcher.Matches.Values.Contains(match => match.StructuralMod != null && match.StructuralMod.Equivalent(uniModMetOx))); // Test can match 15N and Met ox! Assert.IsTrue(libkeyModMatcher.Matches.Contains(match => match.Key.Mass == 17 && match.Value.StructuralMod != null && match.Value.StructuralMod.Equivalent(uniModMetOx) && match.Value.HeavyMod != null && match.Value.HeavyMod.Equivalent(LABEL15_N))); // Test can match Cysteine (Implicit) and Met Ox (variable) libkeyModMatcher.CreateMatches(modMatchDocContainer.Document.Settings, docLibraries[yeastLibIndex].Keys, defSetSetLight, defSetHeavy); Assert.IsTrue(libkeyModMatcher.MatcherPepMods.StaticModifications.Contains(mod => mod.Formula.Equals(UniMod.GetModification(StaticModList.DEFAULT_NAME, true).Formula) && !mod.IsVariable)); Assert.IsTrue(libkeyModMatcher.MatcherPepMods.StaticModifications.Contains(mod => mod.Formula.Equals("O") && mod.IsVariable)); } }
protected override void DoTest() { // Create modifications used in this test var aquaMod = new StaticMod("Aqua 13C", "K, R", ModTerminus.C, null, LabelAtoms.C13 | LabelAtoms.N15, null, null); var phosphoLossMod = new StaticMod("Phospho Loss", "S, T, Y", null, false, "HPO3", LabelAtoms.None, RelativeRT.Matching, null, null, new[] { new FragmentLoss("H3PO4"), }); var multipleLossMod = new StaticMod("Multiple Loss-only", "A", null, false, null, LabelAtoms.None, RelativeRT.Matching, null, null, new[] { new FragmentLoss("NH3"), new FragmentLoss("H2O") }); var explicitMassesLossMod = new StaticMod("Explicit Mass Loss", "N", null, false, null, LabelAtoms.None, RelativeRT.Matching, null, null, new[] { new FragmentLoss(null, 5, 10) }); var variableLossMod = new StaticMod("Methionine Oxidized Loss", "M", null, true, "O", LabelAtoms.None, RelativeRT.Matching, null, null, new[] { new FragmentLoss("CH3O") }); Settings.Default.HeavyModList.Clear(); Settings.Default.HeavyModList.Add(aquaMod); Settings.Default.StaticModList.Clear(); Settings.Default.StaticModList.AddRange(StaticModList.GetDefaultsOn()); Settings.Default.StaticModList.Add(variableLossMod); // Bump up the max mz a bit var transitionSettingsUI = ShowDialog <TransitionSettingsUI>(SkylineWindow.ShowTransitionSettingsUI); RunUI(() => { transitionSettingsUI.SelectedTab = TransitionSettingsUI.TABS.Instrument; transitionSettingsUI.MaxMz = 1510; }); OkDialog(transitionSettingsUI, transitionSettingsUI.OkDialog); // Bring up add modification dialog var peptideSettingsUI = ShowDialog <PeptideSettingsUI>(() => SkylineWindow.ShowPeptideSettingsUI(PeptideSettingsUI.TABS.Modifications)); var editModsDlg = ShowEditStaticModsDlg(peptideSettingsUI); var addModDlg = ShowAddModDlg(editModsDlg); // Try a few things with new loss UI on the phospho loss modification RunUI(() => { addModDlg.Modification = phosphoLossMod; Assert.IsTrue(addModDlg.GetLossText(0).EndsWith(phosphoLossMod.Losses[0].Formula)); addModDlg.LossSelectedIndex = 0; addModDlg.DeleteLoss(); }); // Add back the original loss with the new loss editor dialog RunDlg <EditFragmentLossDlg>(addModDlg.AddLoss, dlg => { dlg.Loss = phosphoLossMod.Losses[0]; dlg.OkDialog(); }); // Add a smaller formula loss with the new loss editor dialog var fragmentLossWater = new FragmentLoss("H2O"); RunDlg <EditFragmentLossDlg>(addModDlg.AddLoss, dlg => { dlg.Loss = fragmentLossWater; dlg.OkDialog(); }); // Add an explicit mass loss with the new loss editor dialog var fragmentLossConstants = new FragmentLoss(null, 20, 25); RunDlg <EditFragmentLossDlg>(addModDlg.AddLoss, dlg => { dlg.Loss = fragmentLossConstants; dlg.OkDialog(); }); // Check the added losses, and remove all but the original loss RunUI(() => { VerifyLossText(addModDlg.GetLossText(0), fragmentLossWater); VerifyLossText(addModDlg.GetLossText(1), fragmentLossConstants); VerifyLossText(addModDlg.GetLossText(2), phosphoLossMod.Losses[0]); addModDlg.LossSelectedIndex = 0; addModDlg.DeleteLoss(); addModDlg.DeleteLoss(); }); OkDialog(addModDlg, addModDlg.OkDialog); // Add a loss modification with 2 losses and no formula RunDlg <EditStaticModDlg>(editModsDlg.AddItem, dlg => { dlg.Modification = multipleLossMod; VerifyLossText(dlg.GetLossText(0), multipleLossMod.Losses[0]); VerifyLossText(dlg.GetLossText(1), multipleLossMod.Losses[1]); dlg.OkDialog(); }); // Add a loss modification with explicit numeric losses and no formula // starting with no losses var addExplicitLossDlg = ShowAddModDlg(editModsDlg); RunUI(() => { addExplicitLossDlg.Modification = explicitMassesLossMod; addExplicitLossDlg.ShowLoss = true; VerifyLossText(addExplicitLossDlg.GetLossText(0), explicitMassesLossMod.Losses[0]); addExplicitLossDlg.LossSelectedIndex = 0; addExplicitLossDlg.DeleteLoss(); }); // Add the explicit numeric loss RunDlg <EditFragmentLossDlg>(addExplicitLossDlg.AddLoss, dlg => { dlg.Loss = fragmentLossConstants; dlg.OkDialog(); }); OkDialog(addExplicitLossDlg, addExplicitLossDlg.OkDialog); OkDialog(editModsDlg, editModsDlg.OkDialog); // Check the phospho loss modification RunUI(() => peptideSettingsUI.PickedStaticMods = new List <string>(peptideSettingsUI.PickedStaticMods) { phosphoLossMod.Name }.ToArray()); WaitForOpenForm <PeptideSettingsUI>(); // Show Modifications tab for form testing OkDialog(peptideSettingsUI, peptideSettingsUI.OkDialog); // Add FASTA sequence RunUI(() => SkylineWindow.Paste(TEXT_FASTA_YEAST_7)); // Losses not added by default without a library Assert.AreEqual(0, GetLossCount(SkylineWindow.Document, 1)); // Make sure setting losses as included Always works { var docBeforeAlways = SkylineWindow.Document; var peptideSettingsUIAlways = ShowDialog <PeptideSettingsUI>(() => SkylineWindow.ShowPeptideSettingsUI(PeptideSettingsUI.TABS.Modifications)); var editModsDlgAlways = ShowEditStaticModsDlg(peptideSettingsUIAlways); RunUI(() => editModsDlgAlways.SelectItem(phosphoLossMod.Name)); var editModDlgAlways = ShowDialog <EditStaticModDlg>(editModsDlgAlways.EditItem); RunUI(() => editModDlgAlways.LossSelectedIndex = 0); RunDlg <EditFragmentLossDlg>(editModDlgAlways.EditLoss, dlg => { dlg.Inclusion = LossInclusion.Always; dlg.OkDialog(); }); OkDialog(editModDlgAlways, editModDlgAlways.OkDialog); OkDialog(editModsDlgAlways, editModsDlgAlways.OkDialog); OkDialog(peptideSettingsUIAlways, peptideSettingsUIAlways.OkDialog); var docAfterAlways = WaitForDocumentChange(docBeforeAlways); Assert.AreEqual(5, GetLossCount(docAfterAlways, 1)); AssertEx.Serializable(docAfterAlways); // Undo and revert to original phospo loss modification definition RunUI(SkylineWindow.Undo); Settings.Default.StaticModList.SetValue(phosphoLossMod); } // Show losses in the pick list var docFasta = WaitForProteinMetadataBackgroundLoaderCompletedUI(); SelectNode(SrmDocument.Level.TransitionGroups, 0); RunDlg <PopupPickList>(SkylineWindow.ShowPickChildrenInTest, dlg => { dlg.ApplyFilter(false); var losses = GetLossGroups(dlg.ItemNames).ToArray(); Assert.AreEqual(1, losses.Length); VerifyLossGroup(losses, 0, 98, 124); dlg.ToggleFind(); dlg.SearchString = "-98"; dlg.ToggleItem(0); dlg.ToggleItem(1); dlg.OnOk(); }); var docLoss = WaitForDocumentChange(docFasta); // Make sure two losses were added Assert.AreEqual(2, GetLossCount(docLoss, 1)); // Allow 2 neutral losses per fragment RunDlg <PeptideSettingsUI>(SkylineWindow.ShowPeptideSettingsUI, dlg => { dlg.MaxNeutralLosses = 2; dlg.OkDialog(); }); var docLoss2 = WaitForDocumentChange(docLoss); // Make sure 2 phospho losses are now possible IGrouping <double, string>[] losses1 = null; RunDlg <PopupPickList>(SkylineWindow.ShowPickChildrenInTest, dlg => { dlg.ApplyFilter(false); losses1 = GetLossGroups(dlg.ItemNames).ToArray(); Assert.AreEqual(2, losses1.Length); VerifyLossGroup(losses1, 0, 98, 124); VerifyLossGroup(losses1, 1, 196, 109); dlg.OnCancel(); }); // Add a modification with multiple possible losses RunDlg <PeptideSettingsUI>(SkylineWindow.ShowPeptideSettingsUI, dlg => { dlg.PickedStaticMods = new List <string>(dlg.PickedStaticMods) { multipleLossMod.Name }.ToArray(); dlg.OkDialog(); }); var docLossMulti = WaitForDocumentChange(docLoss2); // Make sure all combinations of 2 except 2 of the multiple // losses are possible, since only one amino acid A exists in this // peptide. RunDlg <PopupPickList>(SkylineWindow.ShowPickChildrenInTest, dlg => { dlg.ApplyFilter(false); var losses = GetLossGroups(dlg.ItemNames).ToArray(); Assert.AreEqual(6, losses.Length); VerifyLossGroup(losses, 0, 17, 66); VerifyLossGroup(losses, 1, 18, 66); VerifyLossGroup(losses, 2, 98, 124); VerifyLossGroup(losses, 3, 115, 61); VerifyLossGroup(losses, 4, 116, 61); VerifyLossGroup(losses, 5, 196, 109); AssertEx.NoDiff(TextUtil.LineSeparate(losses1[0].ToArray()), TextUtil.LineSeparate(losses[2].ToArray())); AssertEx.NoDiff(TextUtil.LineSeparate(losses1[1].ToArray()), TextUtil.LineSeparate(losses[5].ToArray())); // Add new neutral loss transitions to the document dlg.ToggleFind(); dlg.SearchString = "-17]"; dlg.ToggleItem(0); dlg.SearchString = "-115]"; dlg.ToggleItem(0); dlg.OnOk(); }); var docLossMultiAdded = WaitForDocumentChange(docLossMulti); Assert.AreEqual(1, GetLossCount(docLossMultiAdded, 2)); // Add heavy modifications and make sure transition group is added with losses RunDlg <PeptideSettingsUI>(SkylineWindow.ShowPeptideSettingsUI, dlg => { dlg.PickedHeavyMods = new[] { aquaMod.Name }; dlg.OkDialog(); }); var docLossMultiHeavy = WaitForDocumentChange(docLossMultiAdded); Assert.AreEqual(4, docLossMultiHeavy.PeptideTransitionGroupCount); Assert.AreEqual(8, GetLossCount(docLossMultiHeavy, 1)); Assert.AreEqual(2, GetLossCount(docLossMultiHeavy, 2)); // Make sure this document is serializable AssertEx.Serializable(docLossMultiHeavy, AssertEx.DocumentCloned); // Reset to just 1 neutral loss per fragment, and turn off heavy mod RunDlg <PeptideSettingsUI>(SkylineWindow.ShowPeptideSettingsUI, dlg => { dlg.PickedHeavyMods = new string[0]; dlg.MaxNeutralLosses = 1; dlg.OkDialog(); }); var docLossMulti1 = WaitForDocumentChange(docLossMultiHeavy); Assert.AreEqual(3, GetLossCount(docLossMulti1, 1)); Assert.AreEqual(0, GetLossCount(docLossMulti1, 2)); // Remove all neutral loss modifications currently on the document // and add the constant numeric loss RunDlg <PeptideSettingsUI>(SkylineWindow.ShowPeptideSettingsUI, dlg => { dlg.PickedStaticMods = new[] { explicitMassesLossMod.Name }; dlg.OkDialog(); }); var docNoLoss2 = WaitForDocumentChange(docLossMulti1); Assert.AreEqual(0, GetLossCount(docNoLoss2, 1)); // Add a neutral loss transition with constant numeric loss RunDlg <PopupPickList>(SkylineWindow.ShowPickChildrenInTest, dlg => { dlg.ApplyFilter(false); var losses = GetLossGroups(dlg.ItemNames).ToArray(); Assert.AreEqual(1, losses.Length); VerifyLossGroup(losses, 0, 20, 85); // Add new neutral loss transitions to the document dlg.ToggleFind(); dlg.SearchString = "-20"; dlg.ToggleItem(0); dlg.OnOk(); }); // Verify that the expected loss was added to the document var docConstantMono = WaitForDocumentChange(docNoLoss2); Assert.AreEqual(1, GetLossCount(docConstantMono, 1)); var pathTranLoss = docConstantMono.GetPathTo((int)SrmDocument.Level.Transitions, 0); var nodeTranLos = (TransitionDocNode)docConstantMono.FindNode(pathTranLoss); Assert.AreEqual(IonType.precursor.GetLocalizedString() + " -20", nodeTranLos.FragmentIonName); // Switch mass type to average RunDlg <TransitionSettingsUI>(SkylineWindow.ShowTransitionSettingsUI, dlg => { dlg.FragmentMassType = MassType.Average; dlg.OkDialog(); }); // Make sure neutral loss changes as expected var docConstantAverage = WaitForDocumentChange(docConstantMono); Assert.AreEqual(1, GetLossCount(docConstantAverage, 1)); nodeTranLos = (TransitionDocNode)docConstantAverage.FindNode(pathTranLoss); Assert.AreEqual(IonType.precursor.GetLocalizedString() + " -25", nodeTranLos.FragmentIonName); // Make sure the resulting document is serializable AssertEx.Serializable(docConstantAverage, AssertEx.DocumentCloned); }
protected override void DoTest() { // Clean-up before running the test RunUI(() => SkylineWindow.ModifyDocument("Set default settings", doc => doc.ChangeSettings(SrmSettingsList.GetDefault()))); Settings.Default.HeavyModList.Clear(); Settings.Default.StaticModList.Clear(); Settings.Default.StaticModList.AddRange(StaticModList.GetDefaultsOn()); // Show dialog asking user if text is FASTA or peptide list RunDlg <PasteTypeDlg>(() => SkylineWindow.Paste(TextUtil.LineSeparate("QFVLSCVILQFVLSCVILQFVLSCVILQFVLSCVILR", "DIEVYCDGAITTKDIEVYCDGAITTKDIEVYCDGAITTK")), dlg => dlg.CancelDialog()); // Add two peptides const string pepSequence1 = "QFVLSCVILR"; const string pepSequence2 = "DIEVYCDGAITTK"; RunUI(() => SkylineWindow.Paste(string.Join("\n", new[] { pepSequence1, pepSequence2 }))); // Check and save original document information var docOrig = WaitForProteinMetadataBackgroundLoaderCompletedUI(); var pathPeptide = docOrig.GetPathTo((int)SrmDocument.Level.Molecules, 1); var peptideImplicit = (PeptideDocNode)docOrig.FindNode(pathPeptide); Assert.AreEqual(1, peptideImplicit.Children.Count); Assert.IsNull(peptideImplicit.ExplicitMods); // Add a new static modification on cysteine var peptideSettingsUI = ShowPeptideSettings(); var modStatic = new StaticMod("Another Cysteine", "C", null, "CO8N2"); AddStaticMod(modStatic, peptideSettingsUI); RunUI(peptideSettingsUI.OkDialog); WaitForClosedForm(peptideSettingsUI); // Select the peptide of interest RunUI(() => SkylineWindow.SequenceTree.SelectedPath = pathPeptide); Assert.AreSame(docOrig, SkylineWindow.Document); // Explicitly add the new modification var modifyPeptideDlg = ShowModifyPeptide(); RunUI(() => { modifyPeptideDlg.SelectModification(IsotopeLabelType.light, pepSequence2.IndexOf('C'), modStatic.Name); modifyPeptideDlg.OkDialog(); }); // Check for correct response to modification var docExplicit = WaitForDocumentChange(docOrig); var peptideExplicit = (PeptideDocNode)docExplicit.FindNode(pathPeptide); Assert.AreEqual(1, peptideExplicit.Children.Count); // Precursor m/z value should have increased Assert.IsTrue(((TransitionGroupDocNode)peptideExplicit.Children[0]).PrecursorMz > ((TransitionGroupDocNode)peptideImplicit.Children[0]).PrecursorMz); var mods = peptideExplicit.ExplicitMods; Assert.IsNotNull(mods); Assert.IsTrue(mods.IsModified(IsotopeLabelType.light)); // Heavy should not be explicitly modified Assert.IsFalse(mods.IsModified(IsotopeLabelType.heavy)); // Add new label types peptideSettingsUI = ShowPeptideSettings(); string[] heavyLabelNames = { "heavy AA", "heavy All" }; SetHeavyLabelNames(peptideSettingsUI, heavyLabelNames); // Make sure label type list edit worked IsotopeLabelType[] heavyLabelTypes = peptideSettingsUI.LabelTypes.ToArray(); Assert.AreEqual(2, heavyLabelTypes.Length); var labelTypeAa = heavyLabelTypes[0]; var labelTypeAll = heavyLabelTypes[1]; Assert.AreEqual(heavyLabelNames.Length, heavyLabelTypes.Length); for (int i = 0; i < heavyLabelTypes.Length; i++) { Assert.AreEqual(heavyLabelNames[i], heavyLabelTypes[i].Name); } // Add new heavy modifications var mod15N = new StaticMod("Label:15N", null, null, null, LabelAtoms.N15, null, null); AddHeavyMod(mod15N, peptideSettingsUI); // var mod13C = new StaticMod("All 13C", null, null, null, LabelAtoms.C13, null, null); // AddHeavyMod(mod13C, peptideSettingsUI); var modK13C = new StaticMod("Label:13C(6) (C-term K)", "K", ModTerminus.C, null, LabelAtoms.C13, null, null); AddHeavyMod(modK13C, peptideSettingsUI); var modR13C = new StaticMod("Label:13C(6) (C-term R)", "R", ModTerminus.C, null, LabelAtoms.C13, null, null); AddHeavyMod(modR13C, peptideSettingsUI); var modV13C = new StaticMod("Label:13C(5)15N(1) (V)", "V", null, null, LabelAtoms.C13 | LabelAtoms.N15, null, null); AddHeavyMod(modV13C, peptideSettingsUI); // Set heavy modification for the peptides RunUI(() => { peptideSettingsUI.SelectedLabelTypeName = heavyLabelNames[1]; peptideSettingsUI.PickedHeavyMods = new[] { mod15N.Name }; peptideSettingsUI.SelectedLabelTypeName = heavyLabelNames[0]; peptideSettingsUI.PickedHeavyMods = new[] { modK13C.Name, modR13C.Name }; peptideSettingsUI.OkDialog(); }); // Make sure the document was updated as expected. Explicit modification // should not keep new types from adding precursors to both peptides. var docMultiType = WaitForDocumentChange(docExplicit); foreach (var nodePep in docMultiType.Peptides) { Assert.AreEqual(3, nodePep.Children.Count); TransitionGroupDocNode nodeGroupLast = null; foreach (TransitionGroupDocNode nodeGroup in nodePep.Children) { if (nodeGroupLast != null) { Assert.IsTrue(nodeGroup.PrecursorMz > nodeGroupLast.PrecursorMz); } nodeGroupLast = nodeGroup; var labelType = nodeGroup.TransitionGroup.LabelType; if (!labelType.IsLight) { Assert.IsTrue(heavyLabelTypes.Contains(labelType)); } } } // Get the modified peptide in the new document peptideExplicit = (PeptideDocNode)docMultiType.FindNode(pathPeptide); // Explicitly set the heavy All modification to match the heavy AA modification var modifyPeptideMultiDlg = ShowModifyPeptide(); RunUI(() => { for (int i = 0; i < pepSequence2.Length - 1; i++) { modifyPeptideMultiDlg.SelectModification(labelTypeAll, i, ""); } modifyPeptideMultiDlg.SelectModification(labelTypeAll, pepSequence2.Length - 1, modK13C.Name); modifyPeptideMultiDlg.OkDialog(); }); // Make sure both heavy types have precursor m/z value that match the original var docModMatch = WaitForDocumentChange(docMultiType); var peptideMatch = (PeptideDocNode)docModMatch.FindNode(pathPeptide); AssertPrecursorMzAreEqaul(peptideExplicit, 1, peptideMatch, 1); AssertPrecursorMzAreEqaul(peptideExplicit, 1, peptideMatch, 2); // Remove the modification on K for heavyAA, and make sure this gets rid of the precursor var modifyPeptideEmptyDlg = ShowModifyPeptide(); RunUI(() => { modifyPeptideEmptyDlg.SelectModification(labelTypeAa, pepSequence2.Length - 1, ""); modifyPeptideEmptyDlg.OkDialog(); }); var docModRemoved = WaitForDocumentChange(docModMatch); var peptideRemoved = (PeptideDocNode)docModRemoved.FindNode(pathPeptide); Assert.AreEqual(2, peptideRemoved.Children.Count); // Reset the modifications var modifyPeptideResetDlg = ShowModifyPeptide(); RunUI(() => { modifyPeptideResetDlg.ResetMods(); modifyPeptideResetDlg.OkDialog(); }); // Make sure this removes the explicit modification and adds back the removed precursor var docModReset = WaitForDocumentChange(docModRemoved); peptideImplicit = (PeptideDocNode)docModReset.FindNode(pathPeptide); Assert.IsNull(peptideImplicit.ExplicitMods); Assert.AreEqual(3, peptideImplicit.Children.Count); // Explicitly set the heavy All modification to match the heavy AA modification var modifyPeptideMatchDlg = ShowModifyPeptide(); RunUI(() => { for (int i = 0; i < pepSequence2.Length - 1; i++) { modifyPeptideMatchDlg.SelectModification(labelTypeAll, i, ""); } modifyPeptideMatchDlg.SelectModification(labelTypeAll, pepSequence2.Length - 1, modK13C.Name); modifyPeptideMatchDlg.OkDialog(); }); var docModAA = WaitForDocumentChange(docModReset); // Change implicit static modification and heavy AA var peptideSettingsUIChange = ShowPeptideSettings(); RunUI(() => { peptideSettingsUIChange.PickedStaticMods = new[] { modStatic.Name }; peptideSettingsUIChange.PickedHeavyMods = new[] { modV13C.Name }; peptideSettingsUIChange.OkDialog(); }); var docModImplicitStatic = WaitForDocumentChange(docModAA); var peptideMatch2 = (PeptideDocNode)docModImplicitStatic.FindNode(pathPeptide); Assert.IsNotNull(peptideMatch2.ExplicitMods); Assert.IsFalse(peptideMatch2.ExplicitMods.IsModified(heavyLabelTypes[0])); Assert.IsTrue(peptideMatch2.ExplicitMods.IsModified(heavyLabelTypes[1])); AssertPrecursorMzAreEqaul(peptideMatch, 0, peptideMatch2, 0); AssertPrecursorMzAreNotEqaul(peptideMatch, 1, peptideMatch2, 1); AssertPrecursorMzAreEqaul(peptideMatch, 2, peptideMatch2, 2); // Remove the heavy All type, which should remove the only explicit modification var peptideSettingsUIRemove = ShowPeptideSettings(); SetHeavyLabelNames(peptideSettingsUIRemove, new[] { heavyLabelNames[0] }); RunUI(peptideSettingsUIRemove.OkDialog); var docModRemoveType = WaitForDocumentChange(docModImplicitStatic); foreach (var nodePep in docModRemoveType.Peptides) { Assert.IsNull(nodePep.ExplicitMods); Assert.AreEqual(2, nodePep.Children.Count); } // Undo, and add an explicit modification to the heavy AA type RunUI(SkylineWindow.Undo); Assert.AreSame(docModImplicitStatic, SkylineWindow.Document); var modifyPeptideAADlg = ShowModifyPeptide(); RunUI(() => { modifyPeptideAADlg.SelectModification(labelTypeAa, pepSequence2.IndexOf('V'), ""); modifyPeptideAADlg.SelectModification(labelTypeAa, pepSequence2.Length - 1, modK13C.Name); modifyPeptideAADlg.OkDialog(); }); var docModExplicitStatic = WaitForDocumentChange(docModImplicitStatic); // Remove the heavy All label type again peptideSettingsUIRemove = ShowPeptideSettings(); SetHeavyLabelNames(peptideSettingsUIRemove, new[] { heavyLabelNames[0] }); OkDialog(peptideSettingsUIRemove, peptideSettingsUIRemove.OkDialog); var docMultiExplicit = WaitForDocumentChange(docModExplicitStatic); var peptideStillExplicit = (PeptideDocNode)docMultiExplicit.FindNode(pathPeptide); Assert.IsNotNull(peptideStillExplicit.ExplicitMods); Assert.IsTrue(peptideStillExplicit.ExplicitMods.IsModified(labelTypeAa)); Assert.IsFalse(peptideStillExplicit.ExplicitMods.IsModified(labelTypeAll)); AssertPrecursorMzAreEqaul(peptideMatch, 1, peptideStillExplicit, 1); }
protected override void DoTest() { // Create modifications used in this test var aquaMods = new[] { new StaticMod("Heavy K", "K", ModTerminus.C, null, LabelAtoms.C13 | LabelAtoms.N15, null, null), new StaticMod("Heavy R", "R", ModTerminus.C, null, LabelAtoms.C13 | LabelAtoms.N15, null, null) }; var explicitMod = new StaticMod("13C L", "L", null, null, LabelAtoms.C13, null, null); var variableMod = new StaticMod("Methionine Oxidized", "M", null, true, "O", LabelAtoms.None, RelativeRT.Matching, null, null, null); Settings.Default.HeavyModList.Clear(); Settings.Default.HeavyModList.AddRange(aquaMods); Settings.Default.HeavyModList.Add(explicitMod); Settings.Default.StaticModList.Clear(); Settings.Default.StaticModList.AddRange(StaticModList.GetDefaultsOn()); var carbMod = Settings.Default.StaticModList[0]; Settings.Default.StaticModList.Add(variableMod); // Clean-up before running the test var settings = SrmSettingsList.GetDefault().ChangePeptideModifications(mod => mod.ChangeHeavyModifications(aquaMods)); RunUI(() => SkylineWindow.ModifyDocument("Set test settings", doc => doc.ChangeSettings(settings))); // Add FASTA sequence RunUI(() => SkylineWindow.Paste(TEXT_FASTA_YEAST_39)); // Check and save original document information var docOrig = WaitForProteinMetadataBackgroundLoaderCompletedUI(); var pathPeptide = docOrig.GetPathTo((int)SrmDocument.Level.Molecules, docOrig.PeptideCount - 3); var peptideOrig = (PeptideDocNode)docOrig.FindNode(pathPeptide); Assert.AreEqual(2, peptideOrig.Children.Count); Assert.IsNull(peptideOrig.ExplicitMods); // Add methionine oxidation variable modification SetStaticModifications(names => new List <string>(names) { variableMod.Name }); var docVarMod = WaitForDocumentChange(docOrig); // Check that variable modification worked, and that the peptide of // interest is variably modified. Assert.IsTrue(docOrig.PeptideCount < docVarMod.PeptideCount); pathPeptide = docVarMod.GetPathTo((int)SrmDocument.Level.Molecules, docVarMod.PeptideCount - 4); var peptideVarMod = (PeptideDocNode)docVarMod.FindNode(pathPeptide); Assert.AreEqual(2, peptideVarMod.Children.Count); Assert.IsTrue(peptideVarMod.HasVariableMods, string.Format("No variable modifications found on the peptide {0}", peptideVarMod.Peptide.Sequence)); Assert.IsFalse(peptideVarMod.ExplicitMods.IsModified(IsotopeLabelType.heavy)); AssertPrecursorMzIsModified(peptideVarMod, 0, peptideVarMod, 1, -5, 0.2); // Select the peptide of interest RunUI(() => SkylineWindow.SequenceTree.SelectedPath = pathPeptide); // Make sure the explicit modifications dialog does not modify the // peptide when nothing is changed. string sequence = peptideVarMod.Peptide.Sequence; RunDlg <EditPepModsDlg>(SkylineWindow.ModifyPeptide, dlg => { for (int i = 0; i < sequence.Length; i++) { dlg.SelectModification(IsotopeLabelType.light, i, ""); dlg.SelectModification(IsotopeLabelType.heavy, i, ""); } dlg.ResetMods(); dlg.OkDialog(); }); Assert.AreSame(docVarMod, SkylineWindow.Document); // Explicitly change the heavy modification RunDlg <EditPepModsDlg>(SkylineWindow.ModifyPeptide, dlg => { dlg.SelectModification(IsotopeLabelType.heavy, sequence.Length - 1, ""); dlg.SelectModification(IsotopeLabelType.heavy, sequence.LastIndexOf('L'), explicitMod.Name); dlg.OkDialog(); }); // Check for correct response to modification var docExplicit = WaitForDocumentChange(docOrig); var peptideExplicit = (PeptideDocNode)docExplicit.FindNode(pathPeptide); Assert.AreEqual(2, peptideExplicit.Children.Count); // Precursor m/z for light should be same AssertPrecursorMzAreEqaul(peptideVarMod, 0, peptideExplicit, 0); // Heavy should have changed AssertPrecursorMzIsModified(peptideExplicit, 0, peptideExplicit, 1, -3, 0.2); // Heavy should now be explicitly modified Assert.IsTrue(peptideExplicit.ExplicitMods.IsModified(IsotopeLabelType.heavy)); // Remove carbamidomethyl cysteine implicit modification SetStaticModifications(names => new[] { variableMod.Name }); var docNoImplicit = WaitForDocumentChange(docExplicit); var peptideNoImplicit = (PeptideDocNode)docNoImplicit.FindNode(pathPeptide); // Light should have gotten 57.0 lighter const double modCarbMz = 57.0 / 2; AssertPrecursorMzIsModified(peptideExplicit, 0, peptideNoImplicit, 0, modCarbMz, 0.1); // Heavy delta should not have changed AssertPrecursorMzIsModified(peptideNoImplicit, 0, peptideNoImplicit, 1, -3, 0.2); // Reset should still return to implicit heavy mods without removing // variable mods. RunDlg <EditPepModsDlg>(SkylineWindow.ModifyPeptide, dlg => { dlg.ResetMods(); dlg.OkDialog(); }); var docReset = WaitForDocumentChange(docNoImplicit); var peptideReset = (PeptideDocNode)docReset.FindNode(pathPeptide); Assert.IsTrue(peptideReset.HasExplicitMods); Assert.IsFalse(peptideReset.ExplicitMods.IsModified(IsotopeLabelType.heavy)); AssertPrecursorMzIsModified(peptideReset, 0, peptideReset, 1, -5, 0.2); // Explicitly add back the Carbamidomethyl Cysteine // Reset should still return to implicit heavy mods RunDlg <EditPepModsDlg>(SkylineWindow.ModifyPeptide, dlg => { dlg.SelectModification(IsotopeLabelType.light, sequence.IndexOf('C'), carbMod.Name); dlg.OkDialog(); }); var docExCarb = WaitForDocumentChange(docReset); var peptideExCarb = (PeptideDocNode)docExCarb.FindNode(pathPeptide); Assert.IsTrue(peptideExCarb.HasExplicitMods); Assert.IsFalse(peptideExCarb.HasVariableMods); AssertPrecursorMzAreEqaul(peptideVarMod, 0, peptideExCarb, 0); AssertPrecursorMzAreEqaul(peptideVarMod, 1, peptideExCarb, 1); // Reset at this point should completely remove explicit modifications // including oxidized M. RunDlg <EditPepModsDlg>(SkylineWindow.ModifyPeptide, dlg => { dlg.ResetMods(); dlg.OkDialog(); }); var docResetImplicit = WaitForDocumentChange(docExCarb); var peptideResetImplicit = (PeptideDocNode)docResetImplicit.FindNode(pathPeptide); Assert.IsFalse(peptideResetImplicit.HasExplicitMods); AssertPrecursorMzIsModified(peptideOrig, 0, peptideResetImplicit, 0, modCarbMz, 0.1); AssertPrecursorMzIsModified(peptideOrig, 1, peptideResetImplicit, 1, modCarbMz, 0.1); // Turn off the variable modifications and explicitly modify using a variable mod RunDlg <PeptideSettingsUI>(SkylineWindow.ShowPeptideSettingsUI, dlg => { dlg.PickedStaticMods = new string[0]; dlg.OkDialog(); }); var docNoStaticMods = WaitForDocumentChange(docResetImplicit); // Explicitly modify the first peptide var pathPeptideFirst = docNoStaticMods.GetPathTo((int)SrmDocument.Level.Molecules, 0); var peptideUnmod = (PeptideDocNode)docNoStaticMods.FindNode(pathPeptideFirst); RunUI(() => SkylineWindow.SelectedPath = pathPeptideFirst); RunDlg <EditPepModsDlg>(SkylineWindow.ModifyPeptide, dlg => { var sequenceUnmod = peptideUnmod.Peptide.Sequence; dlg.SelectModification(IsotopeLabelType.light, sequenceUnmod.IndexOf('M'), variableMod.Name); dlg.OkDialog(); }); var docExplicitVarMod = WaitForDocumentChange(docNoStaticMods); var peptideExplicitVarMod = (PeptideDocNode)docExplicitVarMod.FindNode(pathPeptideFirst); Assert.IsTrue(peptideExplicitVarMod.HasExplicitMods); if (peptideExplicitVarMod.ExplicitMods.StaticModifications == null) { Assert.IsNotNull(peptideExplicitVarMod.ExplicitMods.StaticModifications); return; // For ReSharper } var varModPeptide = peptideExplicitVarMod.ExplicitMods.StaticModifications[0].Modification; Assert.AreEqual(variableMod.Name, varModPeptide.Name); // The modification instance on the peptide should not be marked as variable Assert.IsFalse(varModPeptide.IsVariable); var varModSettings = docExplicitVarMod.Settings.PeptideSettings.Modifications.StaticModifications[0]; Assert.AreEqual(variableMod.Name, varModSettings.Name); Assert.IsTrue(varModSettings.IsExplicit); Assert.IsFalse(varModSettings.IsVariable); // Make sure this did not turn on the variable modification in the settings UI RunDlg <PeptideSettingsUI>(SkylineWindow.ShowPeptideSettingsUI, dlg => { Assert.AreEqual(0, dlg.PickedStaticMods.Length); dlg.OkDialog(); }); Directory.CreateDirectory(TestContext.TestDir); string saveFilePath = TestContext.GetTestPath("TestExplicitVariable.sky"); WaitForProteinMetadataBackgroundLoaderCompletedUI(); // make sure doc is complete before save RunUI(() => { Assert.IsTrue(SkylineWindow.SaveDocument(saveFilePath)); SkylineWindow.NewDocument(); Assert.IsTrue(SkylineWindow.OpenFile(saveFilePath)); }); WaitForProteinMetadataBackgroundLoaderCompletedUI(); var docRestored = SkylineWindow.Document; var pathPeptideFirstNew = docRestored.GetPathTo((int)SrmDocument.Level.Molecules, 0); var peptideExplicitVarModNew = docRestored.FindNode(pathPeptideFirstNew); Assert.AreEqual(peptideExplicitVarMod, peptideExplicitVarModNew, "Saved peptide with explicit variable modification was not restored correctly."); Assert.IsTrue(Settings.Default.StaticModList.Contains(variableMod), "Expected variable modification has been removed from the global list."); }