Esempio n. 1
0
        private void VerifyFoldChanges(SrmDocument testDocument, GroupComparisonDef groupComparisonDef,
                                       IDictionary <string, LinearFitResult> expectedResults)
        {
            var groupComparer = new GroupComparer(groupComparisonDef, testDocument, new QrFactorizationCache());

            foreach (var protein in testDocument.MoleculeGroups)
            {
                var             groupComparisonResult = groupComparer.CalculateFoldChanges(protein, null).FirstOrDefault();
                LinearFitResult expectedResult;
                if (expectedResults.TryGetValue(protein.Name, out expectedResult))
                {
                    Assert.IsNotNull(groupComparisonResult);
                    var foldChange = groupComparisonResult.LinearFitResult;
                    Assert.AreEqual(expectedResult.EstimatedValue, foldChange.EstimatedValue, 1E-5);
                    Assert.AreEqual(expectedResult.DegreesOfFreedom, foldChange.DegreesOfFreedom);
                    Assert.AreEqual(expectedResult.StandardError, foldChange.StandardError, 1E-5);
                    Assert.AreEqual(expectedResult.TValue, foldChange.TValue, 1E-5);
                    Assert.AreEqual(expectedResult.PValue, foldChange.PValue, 1E-5);
                }
                else if (!SrmDocument.IsSpecialNonProteomicTestDocNode(protein)) // Avoid the special small molecule test nodes
                {
                    Assert.IsNull(groupComparisonResult);
                    var standardPeptides = protein.Molecules.Where(mol => null != mol.GlobalStandardType).ToArray();
                    Assert.AreNotEqual(0, standardPeptides.Length);
                }
            }
        }
Esempio n. 2
0
        protected override void DoTest()
        {
            // Formerly this little .sky file would not update its (unsearchable) protein metdata on load
            RunUI(() => SkylineWindow.OpenFile(TestFilesDir.GetTestPath("Mutant Peptides  with Braf AG A00Y - Cut Down.sky")));
            var doc      = WaitForDocumentLoaded();
            var nodeProt = doc.MoleculeGroups.First();
            var metadata = nodeProt.ProteinMetadata;

            Assert.IsFalse(metadata.NeedsSearch());

            RunUI(() => SkylineWindow.OpenFile(TestFilesDir.GetTestPath("ProteinMetadataFunctionalTests.sky")));

            doc      = WaitForDocumentLoaded();
            nodeProt = doc.MoleculeGroups.First();
            metadata = nodeProt.ProteinMetadata;

            // Examine the various View | Targets | By* modes
            foreach (ProteinMetadataManager.ProteinDisplayMode mode in Enum.GetValues(typeof(ProteinMetadataManager.ProteinDisplayMode)))
            {
                ProteinMetadataManager.ProteinDisplayMode arg = mode;
                RunUI(() => SkylineWindow.UpdateTargetsDisplayMode(arg)); // This should alter the text displayed by the node in the sequence tree view
                WaitForConditionUI(() =>
                {
                    var displayText = SkylineWindow.SequenceTree.GetSequenceNodes().First().Text;
                    if (arg != ProteinMetadataManager.ProteinDisplayMode.ByName &&
                        Equals(displayText, GetDisplayText(ProteinMetadataManager.ProteinDisplayMode.ByName, metadata)))
                    {
                        return(false);
                    }
                    return(Equals(displayText, GetDisplayText(arg, metadata)));
                });
            }

            // Examine the various Edit | Refine | Sort Proteins | By* modes
            Assert.AreEqual("YIL075C", nodeProt.Name); // unsorted
            foreach (ProteinMetadataManager.ProteinDisplayMode mode in Enum.GetValues(typeof(ProteinMetadataManager.ProteinDisplayMode)))
            {
                string expectedTopName = null;
                switch (mode)
                {
                case ProteinMetadataManager.ProteinDisplayMode.ByName:
                    expectedTopName = "YAL003W";
                    RunUI(() => SkylineWindow.sortProteinsByNameToolStripMenuItem_Click(null, null));
                    break;

                case ProteinMetadataManager.ProteinDisplayMode.ByAccession:
                    expectedTopName = TestSmallMolecules ? "ZZZTESTINGNONPROTEOMICMOLECULEGROUP" : "YFL038C";
                    RunUI(() => SkylineWindow.sortProteinsByAccessionToolStripMenuItem_Click(null, null));
                    break;

                case ProteinMetadataManager.ProteinDisplayMode.ByPreferredName:
                    RunUI(() => SkylineWindow.sortProteinsByPreferredNameToolStripMenuItem_Click(null, null));
                    expectedTopName = TestSmallMolecules ? "ZZZTESTINGNONPROTEOMICMOLECULEGROUP" : "YAL016W";
                    break;

                case ProteinMetadataManager.ProteinDisplayMode.ByGene:
                    RunUI(() => SkylineWindow.sortProteinsByGeneToolStripMenuItem_Click(null, null));
                    expectedTopName = TestSmallMolecules ? "ZZZTESTINGNONPROTEOMICMOLECULEGROUP" : "YGL234W";
                    break;
                }
                var actualTopName = WaitForDocumentLoaded().MoleculeGroups.First().Name.ToUpperInvariant();
                Assert.AreEqual(expectedTopName, actualTopName);
            }

            // Now paste in our fake fasta test data, and handle it with our fake webaccess handler
            var protdbLoader = SkylineWindow.BackgroundProteomeManager;

            protdbLoader.FastaImporter = new WebEnabledFastaImporter(new CommonTest.FastaImporterTest.PlaybackProvider());
            var treeLoader = SkylineWindow.ProteinMetadataManager;

            treeLoader.FastaImporter = new WebEnabledFastaImporter(new CommonTest.FastaImporterTest.PlaybackProvider());

            const int maxEntries = 5;
            var       fastaText  = CommonTest.FastaImporterTest.GetFastaTestText(maxEntries); // Just get the first few

            SetClipboardTextUI(fastaText);
            var pasteDlg = ShowDialog <PasteDlg>(SkylineWindow.ShowPasteFastaDlg); // Show the paste dialog

            RunDlg <EmptyProteinsDlg>(() =>                                        // Anticpate the EmptyProteinsDialog as a side effect
            {
                pasteDlg.PasteFasta();                                             // Doing this in pastDlg...
                pasteDlg.OkDialog();
            },
                                      dlg =>
            {
                Assert.AreEqual(maxEntries, dlg.EmptyProteins);
                dlg.KeepEmptyProteins();
                dlg.OkDialog();     // ... will cause EmptyProteinsDlg to pop up, so OK it.
            });

            // Check that IPI:IPI00197700.1 got an accession number P04638
            WaitForCondition(() => SkylineWindow.Document.MoleculeGroups.Any(pg => Equals("IPI:IPI00197700.1", pg.Name)));
            doc      = WaitForDocumentLoaded();
            nodeProt = doc.MoleculeGroups.First(pg => Equals("IPI:IPI00197700.1", pg.Name));
            Assert.AreEqual("P04638", nodeProt.ProteinMetadata.Accession);

            // Now make our fake fasta into a protdb file, and check statement completion against that
            const string basename   = "fake.fasta";
            var          protdbPath = TestFilesDir.GetTestPath(basename + ProteomeDb.EXT_PROTDB);
            var          fastapath  = TestFilesDir.GetTestPath(basename);

            using (StreamWriter outfile = new StreamWriter(fastapath))
            {
                outfile.Write(CommonTest.FastaImporterTest.GetFastaTestText()); // write them all
            }
            BackgroundProteomeTest.CreateBackgroundProteome(protdbPath, basename, fastapath);
            doc = WaitForDocumentChange(doc);

            // Test for getting accession info from protdb
            RunUI(() =>
            {
                SequenceTree sequenceTree = SkylineWindow.SequenceTree;
                SkylineWindow.SequenceTree.SelectedNode = SkylineWindow.SequenceTree.Nodes[SkylineWindow.SequenceTree.Nodes.Count - 1]; // Select the creation node
                sequenceTree.BeginEdit(false);
                // ReSharper disable LocalizableElement
                sequenceTree.StatementCompletionEditBox.TextBox.Text = "NP_313205";
                // ReSharper restore LocalizableElement
                sequenceTree.CommitEditBox(false);
            });
            doc      = WaitForDocumentChange(doc);
            nodeProt = doc.MoleculeGroups.First(pg => Equals("NP_313205", pg.Name));
            Assert.AreEqual("P0A7T9", nodeProt.ProteinMetadata.Accession);

            var snapshot = SkylineWindow.Document;

            // Test for getting protein from protdb by preferredName
            const string uniRef100A5Di11 = "UniRef100_A5DI11";
            const string a5Di11          = "A5DI11";

            RunUI(() =>
            {
                SequenceTree sequenceTree = SkylineWindow.SequenceTree;
                SkylineWindow.SequenceTree.SelectedNode = SkylineWindow.SequenceTree.Nodes[SkylineWindow.SequenceTree.Nodes.Count - 1]; // Select the creation node
                sequenceTree.BeginEdit(false);
                // ReSharper disable LocalizableElement
                sequenceTree.StatementCompletionEditBox.TextBox.Text = "EF2_PICGU"; // PreferredName for UniRef100_A5DI11
                // ReSharper restore LocalizableElement
                sequenceTree.CommitEditBox(false);
            });
            WaitForCondition(() => SkylineWindow.Document.MoleculeGroups.Any(pg => Equals(uniRef100A5Di11, pg.Name)));
            doc      = WaitForDocumentChange(doc);
            nodeProt = doc.MoleculeGroups.First(pg => Equals(uniRef100A5Di11, pg.Name));
            Assert.AreEqual(a5Di11, nodeProt.ProteinMetadata.Accession);

            // Paste in some junk and make sure we handle the View Targets By* gracefully
            const string badname = "badname";

            RunUI(() =>
            {
                SequenceTree sequenceTree = SkylineWindow.SequenceTree;
                SkylineWindow.SequenceTree.SelectedNode = SkylineWindow.SequenceTree.Nodes[SkylineWindow.SequenceTree.Nodes.Count - 1]; // Select the creation node
                sequenceTree.BeginEdit(false);
                sequenceTree.StatementCompletionEditBox.TextBox.Text = badname;
                sequenceTree.CommitEditBox(false);
            });
            doc = WaitForDocumentChange(doc);
            var nodeText = SkylineWindow.SequenceTree.GetSequenceNodes().Last(n => !SrmDocument.IsSpecialNonProteomicTestDocNode(n.DocNode)).Text;
            var failsafe = String.Format(Resources.PeptideGroupTreeNode_ProteinModalDisplayText__name___0__, badname);  // As in PeptideGroupTreeNode.cs

            Assert.AreEqual(failsafe, nodeText);


            // Revert those changes, so we can insert another way
            Assert.IsTrue(SkylineWindow.SetDocument(snapshot, doc));
            WaitForCondition(() => !SkylineWindow.Document.MoleculeGroups.Any(pg => Equals(uniRef100A5Di11, pg.Name)));
            doc = SkylineWindow.Document;

            // Test for pasting accession number in protein paste dialog, and having it populate with correct name
            SetClipboardTextUI(a5Di11);
            PasteDlg pasteProteinsDlgA = ShowDialog <PasteDlg>(SkylineWindow.ShowPasteProteinsDlg);

            RunUI(() =>
            {
                var selectedNode = SkylineWindow.SequenceTree.Nodes[SkylineWindow.SequenceTree.Nodes.Count - 1];
                SkylineWindow.SequenceTree.SelectedNode = selectedNode;
                pasteProteinsDlgA.SelectedPath          = SkylineWindow.SequenceTree.SelectedPath;
                pasteProteinsDlgA.PasteProteins();
            });
            OkDialog(pasteProteinsDlgA, pasteProteinsDlgA.OkDialog);
            WaitForCondition(() => SkylineWindow.Document.MoleculeGroups.Any(pg => Equals(uniRef100A5Di11, pg.Name)));
            doc      = WaitForDocumentChange(doc);
            nodeProt = doc.MoleculeGroups.First(pg => Equals(uniRef100A5Di11, pg.Name));
            Assert.AreEqual(a5Di11, nodeProt.ProteinMetadata.Accession);

            // See what happens when you paste in a gene name shared by a couple of proteins
            const string dupeGene    = "Apoa2";
            const string ipi00197700 = "IPI:IPI00197700.1";

            SetClipboardTextUI(dupeGene);
            PasteDlg pasteProteinsDlgB = ShowDialog <PasteDlg>(SkylineWindow.ShowPasteProteinsDlg);

            RunUI(() =>
            {
                var selectedNode = SkylineWindow.SequenceTree.Nodes[SkylineWindow.SequenceTree.Nodes.Count - 1];
                SkylineWindow.SequenceTree.SelectedNode = selectedNode;
                pasteProteinsDlgB.SelectedPath          = SkylineWindow.SequenceTree.SelectedPath;
                pasteProteinsDlgB.PasteProteins();
            });
            OkDialog(pasteProteinsDlgB, pasteProteinsDlgB.OkDialog);
            WaitForCondition(() => SkylineWindow.Document.MoleculeGroups.Any(pg => Equals(ipi00197700, pg.Name)));
            doc      = WaitForDocumentChange(doc);
            nodeProt = doc.MoleculeGroups.First(pg => Equals(ipi00197700, pg.Name));
            Assert.AreEqual(dupeGene, nodeProt.ProteinMetadata.Gene);

            // Test for pasting in protein PasteDlg with sequence and metadata - metadata values are same as DocumentGrid column names
            const string pasteProteinName          = "Protein";
            const string pasteProteinDescription   = "Description";
            const string pasteProteinAccession     = "Accession";
            const string pasteProteinPreferredName = "PreferredName";
            const string pasteProteinGene          = "Gene";
            const string pasteProteinSpecies       = "Species";
            var          pasteProteinText          = String.Join("\t", pasteProteinName, pasteProteinDescription,
                                                                 "MFEQFDLDSELLASINK   IGYTKPTSIQELVIPQAMV", pasteProteinAccession, pasteProteinPreferredName, // Note the whitespace embedded in the sequence - UI should deal with that
                                                                 pasteProteinGene, pasteProteinSpecies);

            SetClipboardTextUI(pasteProteinText);
            PasteDlg pasteProteinsDlg = ShowDialog <PasteDlg>(SkylineWindow.ShowPasteProteinsDlg);

            RunUI(() =>
            {
                var selectedNode = SkylineWindow.SequenceTree.Nodes[SkylineWindow.SequenceTree.Nodes.Count - 1];
                SkylineWindow.SequenceTree.SelectedNode = selectedNode;
                pasteProteinsDlg.SelectedPath           = SkylineWindow.SequenceTree.SelectedPath;
                pasteProteinsDlg.PasteProteins();
            });
            OkDialog(pasteProteinsDlg, pasteProteinsDlg.OkDialog);
            WaitForCondition(() => SkylineWindow.Document.MoleculeGroups.Any(pg => Equals(pasteProteinName, pg.Name)));
            doc      = WaitForDocumentChange(doc);
            nodeProt = doc.MoleculeGroups.First(pg => Equals(pasteProteinName, pg.Name));
            Assert.AreEqual(pasteProteinAccession, nodeProt.ProteinMetadata.Accession);

            // Verify DocumentGrid's use of protein metadata - last line should agree with var pasteProteinText
            var documentGrid = ShowDialog <DocumentGridForm>(() => SkylineWindow.ShowDocumentGrid(true));

            RunUI(() => documentGrid.ChooseView(Resources.SkylineViewContext_GetDocumentGridRowSources_Proteins));
            WaitForCondition(() => (documentGrid.RowCount > 0));  // Let it initialize
            foreach (var colName in new[]
            {
                pasteProteinAccession,
                pasteProteinPreferredName,
                pasteProteinGene,
                pasteProteinSpecies
            })
            {   // Column content should match column name, for pasteProteinText as input
                string value = null;
                string name  = colName;
                RunUI(() =>
                {
                    var col = documentGrid.FindColumn(PropertyPath.Parse(name));
                    value   =
                        documentGrid.DataGridView.Rows[documentGrid.RowCount - 1].Cells[col.Index].Value.ToString();
                });
                Assert.AreEqual(colName, value);
            }
        }
Esempio n. 3
0
        public void ImportFastaTest()
        {
            SrmDocument  document = new SrmDocument(SrmSettingsList.GetDefault0_6());
            IdentityPath path     = IdentityPath.ROOT;
            SrmDocument  docFasta = document.ImportFasta(new StringReader(ExampleText.TEXT_FASTA_YEAST), false, path, out path);

            AssertEx.IsDocumentState(docFasta, 1, 2, 98, 311);
            Assert.AreEqual("YAL001C", ((PeptideGroupDocNode)docFasta.Children[0]).Name);
            Assert.AreEqual("YAL002W", ((PeptideGroupDocNode)docFasta.Children[1]).Name);
            Assert.AreEqual(1, path.Length);
            Assert.IsInstanceOfType(path.GetIdentity(0), typeof(FastaSequence));
            Assert.AreEqual("YAL001C", ((FastaSequence)path.GetIdentity(0)).Name);
            int maxMz = docFasta.Settings.TransitionSettings.Instrument.MaxMz - 120;

            foreach (PeptideGroupDocNode nodeGroup in docFasta.Children)
            {
                if (SrmDocument.IsSpecialNonProteomicTestDocNode(nodeGroup))
                {
                    continue;
                }

                Assert.IsInstanceOfType(nodeGroup.Id, typeof(FastaSequence));

                int lastEnd = docFasta.Settings.PeptideSettings.Filter.ExcludeNTermAAs - 1;

                foreach (PeptideDocNode nodePeptide in nodeGroup.Children)
                {
                    Peptide peptide = nodePeptide.Peptide;
                    char    prev    = peptide.PrevAA;
                    if (prev != 'K' && prev != 'R')
                    {
                        Assert.Fail("Unexpected preceding cleavage at {0}", prev);
                    }
                    string seq  = peptide.Sequence;
                    char   last = seq[seq.Length - 1];
                    if (last != 'K' && last != 'R' && peptide.NextAA != '-')
                    {
                        Assert.Fail("Unexpected cleavage at {0}", last);
                    }
                    Assert.IsNotNull(peptide.Begin);
                    Assert.IsNotNull(peptide.End);

                    // Make sure peptides are ordered, and not overlapping
                    if (peptide.Begin.Value < lastEnd)
                    {
                        Assert.Fail("Begin {0} less than last end {1}.", peptide.Begin.Value, lastEnd);
                    }
                    lastEnd = peptide.End.Value;

                    IList <DocNode> nodesTrans = ((DocNodeParent)nodePeptide.Children[0]).Children;
                    int             trans      = nodesTrans.Count;
                    if (trans < 3)
                    {
                        // Might have been cut off by the instrument limit.
                        if ((trans == 0 && ((TransitionGroupDocNode)nodePeptide.Children[0]).PrecursorMz < maxMz) ||
                            (trans > 0 && ((TransitionDocNode)nodesTrans[0]).Mz < maxMz))
                        {
                            Assert.Fail("Found {0} transitions, expecting 3.", trans);
                        }
                    }
                    // Might have extra proline transitions
                    else if (trans > 3 && peptide.Sequence.IndexOf('P') == -1)
                    {
                        Assert.Fail("Found {0} transitions, expecting 3.", trans);
                    }

                    // Make sure transitions are ordered correctly
                    IonType lastType   = IonType.a;
                    int     lastOffset = -1;
                    foreach (TransitionDocNode nodeTran in nodesTrans)
                    {
                        Transition transition = nodeTran.Transition;
                        if (lastType == transition.IonType)
                        {
                            Assert.IsTrue(transition.CleavageOffset > lastOffset);
                        }
                        else
                        {
                            Assert.IsTrue(((int)transition.IonType) > ((int)lastType));
                        }
                        lastType   = transition.IonType;
                        lastOffset = transition.CleavageOffset;
                    }
                }
            }

            // Make sure old document is unmodified.
            Assert.AreEqual(0, document.RevisionIndex);
            Assert.AreEqual(0, document.PeptideTransitionCount);

            // Re-paste of fasta should have no impact.
            // path = IdentityPath.ROOT; use null as substitute for Root
            SrmDocument docFasta2 = docFasta.ImportFasta(new StringReader(ExampleText.TEXT_FASTA_YEAST), false, null, out path);

            // Returns the original document to avoid adding undo record in running app
            Assert.AreSame(docFasta, docFasta2);
            Assert.IsNull(path);

            // Discard double-insert document, and add peptides list into previous document
            path = IdentityPath.ROOT;
            SrmDocument docPeptides = docFasta.ImportFasta(new StringReader(TEXT_BOVINE_PEPTIDES1), true, path, out path);

            AssertEx.IsDocumentState(docPeptides, 2, 3, 111, 352);
            Assert.AreEqual(1, path.Length);
            Assert.IsNotInstanceOfType(path.GetIdentity(0), typeof(FastaSequence));
            Assert.AreEqual("Peptides1", ((PeptideGroupDocNode)docPeptides.FindNode(path)).Name);
            PeptideGroupDocNode nodePepList = (PeptideGroupDocNode)docPeptides.Children[2];

            Assert.IsNotInstanceOfType(nodePepList.Id, typeof(FastaSequence));
            // Make sure other two nodes are unchanged
            Assert.AreSame(docFasta.Children[0], docPeptides.Children[0]);
            Assert.AreSame(docFasta.Children[1], docPeptides.Children[1]);

            foreach (PeptideDocNode nodePeptide in nodePepList.Children)
            {
                if (SrmDocument.IsSpecialNonProteomicTestDocNode(nodePeptide))
                {
                    continue;
                }
                char prev = nodePeptide.Peptide.PrevAA;
                char next = nodePeptide.Peptide.NextAA;
                if (prev != 'X' || next != 'X')
                {
                    Assert.Fail("Expected amino acids X, but found {0} or {1}", prev, next);
                }
                string seq  = nodePeptide.Peptide.Sequence;
                char   last = seq[seq.Length - 1];
                // Just because they are tryptic peptides in the list
                if (last != 'K' && last != 'R' && nodePeptide.Peptide.NextAA != '-')
                {
                    Assert.Fail("Unexpected cleavage at {0}", last);
                }
                Assert.IsNull(nodePeptide.Peptide.Begin);
                Assert.IsNull(nodePeptide.Peptide.End);

                IList <DocNode> nodesTrans = ((DocNodeParent)nodePeptide.Children[0]).Children;
                int             trans      = nodesTrans.Count;
                if (trans < 3)
                {
                    // Might have been cut off by the instrument limit.
                    if ((trans == 0 && ((TransitionGroupDocNode)nodePeptide.Children[0]).PrecursorMz < maxMz) ||
                        (trans > 0 && ((TransitionDocNode)nodesTrans[0]).Mz < maxMz))
                    {
                        Assert.Fail("Found {0} transitions, expecting 3.", trans);
                    }
                }
                // Might have extra proline transitions
                else if (trans > 3 && nodePeptide.Peptide.Sequence.IndexOf('P') == -1)
                {
                    Assert.Fail("Found {0} transitions, expecting 3.", trans);
                }
            }

            // Make sure old documents are unmodified.
            AssertEx.IsDocumentState(document, 0, 0, 0, 0);
            AssertEx.IsDocumentState(docFasta, 1, 2, 98, 311);
            AssertEx.IsDocumentState(docPeptides, 2, 3, 111, 352);

            // Add peptides in all possible locations.
            // 1. Root (already done)
            // 1. Before another group
            path = docPeptides.GetPathTo(0);
            SrmDocument docPeptides2 = docPeptides.ImportFasta(new StringReader(TEXT_BOVINE_PEPTIDES1), true, path, out path);

            AssertEx.IsDocumentState(docPeptides2, 3, 4, 124, 393);
            Assert.IsNotInstanceOfType(docPeptides2.Children[0].Id, typeof(FastaSequence));
            Assert.AreEqual(docPeptides2.Children[0].Id, path.GetIdentity(0));
            Assert.IsInstanceOfType(docPeptides2.Children[1].Id, typeof(FastaSequence));
            // Make sure previously existing groups are unchanged
            Assert.AreSame(docPeptides.Children[0], docPeptides2.Children[1]);
            Assert.AreSame(docPeptides.Children[1], docPeptides2.Children[2]);
            Assert.AreSame(docPeptides.Children[2], docPeptides2.Children[3]);

            // 2. Inside a FASTA group
            path = docPeptides2.GetPathTo((int)SrmDocument.Level.Transitions, 100);
            SrmDocument docPeptides3 = docPeptides2.ImportFasta(new StringReader(TEXT_BOVINE_PEPTIDES1), true, path, out path);

            AssertEx.IsDocumentState(docPeptides3, 4, 5, 137, 434);
            Assert.AreEqual(2, docPeptides3.FindNodeIndex(path));
            // Make sure previously existing groups are unchanged
            Assert.AreSame(docPeptides2.Children[1], docPeptides3.Children[1]);
            Assert.AreSame(docPeptides2.Children[2], docPeptides3.Children[3]);

            // 3. To a peptide list
            //    a. Same peptides
            path         = docPeptides2.GetPathTo(0);
            docPeptides3 = docPeptides2.ImportFasta(new StringReader(TEXT_BOVINE_PEPTIDES1), true, path, out path);
            // No longer filter repeated peptides, because they are useful for explicit modifictations.
            Assert.AreNotSame(docPeptides2, docPeptides3);
            Assert.IsNotNull(path);

            //    b. Different paptides
            path = docPeptides2.GetPathTo(0);
            IdentityPath pathFirstPep = docPeptides3.GetPathTo((int)SrmDocument.Level.Molecules, 0);

            docPeptides3 = docPeptides2.ImportFasta(new StringReader(TEXT_BOVINE_PEPTIDES2), true, path, out path);
            AssertEx.IsDocumentState(docPeptides3, 4, 4, 140, 448);
            Assert.AreSame(docPeptides2.Children[0].Id, docPeptides3.Children[0].Id);
            Assert.AreNotSame(docPeptides2.Children[0], docPeptides3.Children[0]);
            Assert.AreEqual("LVTDLTK", ((PeptideDocNode)docPeptides3.FindNode(path)).Peptide.Sequence);
            int          index         = docPeptides3.FindNodeIndex(path);
            IdentityPath pathPreceding = docPeptides3.GetPathTo(path.Depth, index - 1);

            Assert.AreEqual("IVGYLDEEGVLDQNR", ((PeptideDocNode)docPeptides3.FindNode(pathPreceding)).Peptide.Sequence);
            Assert.AreEqual(0, docPeptides3.FindNodeIndex(pathFirstPep));

            // 4. At a peptide in a peptide list
            path         = docPeptides2.GetPathTo((int)SrmDocument.Level.Molecules, 0);
            docPeptides3 = docPeptides2.ImportFasta(new StringReader(TEXT_BOVINE_PEPTIDES2), true, path, out path);
            AssertEx.IsDocumentState(docPeptides3, 4, 4, 140, 448);
            Assert.AreSame(docPeptides2.Children[0].Id, docPeptides3.Children[0].Id);
            Assert.AreNotSame(docPeptides2.Children[0], docPeptides3.Children[0]);
            Assert.AreEqual(0, docPeptides3.FindNodeIndex(path));
            Assert.AreEqual(16, docPeptides3.FindNodeIndex(pathFirstPep));

            // 5. Inside a peptide in a peptide list
            path         = docPeptides2.GetPathTo((int)SrmDocument.Level.Transitions, 0);
            docPeptides3 = docPeptides2.ImportFasta(new StringReader(TEXT_BOVINE_PEPTIDES2), true, path, out path);
            AssertEx.IsDocumentState(docPeptides3, 4, 4, 140, 448);
            Assert.AreSame(docPeptides2.Children[0].Id, docPeptides3.Children[0].Id);
            Assert.AreNotSame(docPeptides2.Children[0], docPeptides3.Children[0]);
            Assert.AreEqual(1, docPeptides3.FindNodeIndex(path));
            Assert.AreEqual(0, docPeptides3.FindNodeIndex(pathFirstPep));
        }