2 * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
3 * Copyright (C) $$Year-Rel$$ The Jalview Authors
5 * This file is part of Jalview.
7 * Jalview is free software: you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation, either version 3
10 * of the License, or (at your option) any later version.
12 * Jalview is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty
14 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15 * PURPOSE. See the GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with Jalview. If not, see <http://www.gnu.org/licenses/>.
19 * The Jalview Authors are detailed in the 'AUTHORS' file.
23 import jalview.analysis.CrossRef;
24 import jalview.api.AlignmentViewPanel;
25 import jalview.datamodel.AlignedCodonFrame;
26 import jalview.datamodel.AlignmentI;
27 import jalview.datamodel.AlignmentTest;
28 import jalview.datamodel.SequenceI;
29 import jalview.gui.AlignFrame;
30 import jalview.gui.CrossRefAction;
31 import jalview.gui.Desktop;
32 import jalview.gui.Jalview2XML;
33 import jalview.gui.JvOptionPane;
36 import java.io.IOException;
37 import java.util.ArrayList;
38 import java.util.HashMap;
39 import java.util.List;
41 import org.testng.Assert;
42 import org.testng.annotations.BeforeClass;
43 import org.testng.annotations.Test;
45 @Test(singleThreaded = true)
46 public class CrossRef2xmlTests extends Jalview2xmlBase
50 @BeforeClass(alwaysRun = true)
51 public void setUpJvOptionPane()
53 JvOptionPane.setInteractiveMode(false);
54 JvOptionPane.setMockResponse(JvOptionPane.CANCEL_OPTION);
58 * test store and recovery of all reachable cross refs from all reachable
59 * crossrefs for one or more fetched db refs. Currently, this test has a known
64 @Test(groups = { "Operational" }, enabled = true)
65 public void testRetrieveAndShowCrossref() throws Exception
68 List<String> failedDBRetr = new ArrayList<String>();
69 List<String> failedXrefMenuItems = new ArrayList<String>();
70 List<String> failedProjectRecoveries = new ArrayList<String>();
72 // for every set of db queries
74 // verify presence of expected xrefs
75 // show xrefs - verify expected type of frame is shown for each xref
77 // - verify original -> xref -> xref(original) recovers frame containing at
78 // least the first retrieved sequence
81 // 2. individual frames
82 // 3. load each one back and verify
83 // . aligned sequences (.toString() )
84 // . xrefs (.toString() )
88 HashMap<String, String> dbtoviewBit = new HashMap<String, String>();
89 List<String> keyseq = new ArrayList<String>();
90 HashMap<String, File> savedProjects = new HashMap<String, File>();
92 for (String[] did : new String[][] { { "ENSEMBL", "ENSG00000157764" },
93 { "UNIPROT", "P01731" } })
95 // pass counters - 0 - first pass, 1 means retrieve project rather than
97 int pass1 = 0, pass2 = 0, pass3 = 0;
98 // each do loop performs two iterations in the first outer loop pass, but
99 // only performs one iteration on the second outer loop
100 // ie. pass 1 = 0 {pass 2= 0 { pass 3 = 0,1 }, pass 2=1 { pass 3 = 0 }}, 1
101 // { pass 2 = 0 { pass 3 = 0 } }
104 String first = did[0] + " " + did[1];
105 AlignFrame af = null;
110 List<String> ptypes = null;
115 List<AlignFrame> afs = jalview.gui.SequenceFetcher.fetchAndShow(
119 failedDBRetr.add("Didn't retrieve " + first);
125 // verify references for retrieved data
126 AlignmentTest.assertAlignmentDatasetRefs(af.getViewport()
127 .getAlignment(), "Pass (" + pass1 + "," + pass2 + ","
128 + pass3 + "): Fetch " + first + ":");
129 assertDatasetIsNormalisedKnownDefect(af.getViewport()
130 .getAlignment(), "Pass (" + pass1 + "," + pass2 + ","
131 + pass3 + "): Fetch " + first + ":");
132 dna = af.getViewport().getAlignment().isNucleotide();
133 retral = af.getViewport().getAlignment();
134 dataset = retral.getDataset();
135 seqs = retral.getSequencesArray();
140 Desktop.instance.closeAll_actionPerformed(null);
141 // recover stored project
142 af = new FileLoader(false).LoadFileWaitTillLoaded(savedProjects
143 .get(first).toString(), DataSourceType.FILE);
144 System.out.println("Recovered view for '" + first + "' from '"
145 + savedProjects.get(first).toString() + "'");
146 dna = af.getViewport().getAlignment().isNucleotide();
147 retral = af.getViewport().getAlignment();
148 dataset = retral.getDataset();
149 seqs = retral.getSequencesArray();
151 // verify references for recovered data
152 AlignmentTest.assertAlignmentDatasetRefs(af.getViewport()
153 .getAlignment(), "Pass (" + pass1 + "," + pass2 + ","
154 + pass3 + "): Recover " + first + ":");
155 assertDatasetIsNormalisedKnownDefect(af.getViewport()
156 .getAlignment(), "Pass (" + pass1 + "," + pass2 + ","
157 + pass3 + "): Recover " + first + ":");
161 // store project on first pass, compare next pass
162 stringify(dbtoviewBit, savedProjects, first, af.alignPanel);
164 ptypes = (seqs == null || seqs.length == 0) ? null : new CrossRef(
165 seqs, dataset).findXrefSourcesForSequences(dna);
167 // start of pass2: retrieve each cross-ref for fetched or restored
169 do // first cross ref and recover crossref loop
172 for (String db : ptypes)
174 // counter for splitframe views retrieved via crossref
176 // build next key so we an retrieve all views
177 String nextxref = first + " -> " + db + "{" + firstcr_ap + "}";
178 // perform crossref action, or retrieve stored project
179 List<AlignmentViewPanel> cra_views = new ArrayList<AlignmentViewPanel>();
180 CrossRefAction cra = null;
183 { // retrieve and show cross-refs in this thread
184 cra = new CrossRefAction(af, seqs, dna, db);
186 if (cra.getXrefViews().size() == 0)
188 failedXrefMenuItems.add("No crossrefs retrieved for "
189 + first + " -> " + db);
192 cra_views = cra.getXrefViews();
193 assertNucleotide(cra_views.get(0),
194 "Nucleotide panel included proteins for " + first
196 assertProtein(cra_views.get(1),
197 "Protein panel included nucleotides for " + first
202 Desktop.instance.closeAll_actionPerformed(null);
204 // recover stored project
205 File storedProject = savedProjects.get(nextxref);
206 if (storedProject == null)
208 failedProjectRecoveries.add("Failed to store a view for '"
213 // recover stored project
214 AlignFrame af2 = new FileLoader(false)
215 .LoadFileWaitTillLoaded(savedProjects.get(nextxref)
216 .toString(), DataSourceType.FILE);
217 System.out.println("Recovered view for '" + nextxref
218 + "' from '" + savedProjects.get(nextxref).toString()
220 // gymnastics to recover the alignPanel/Complementary alignPanel
221 if (af2.getViewport().isNucleotide())
223 // top view, then bottom
224 cra_views.add(af2.getViewport().getAlignPanel());
225 cra_views.add(((jalview.gui.AlignViewport) af2
226 .getViewport().getCodingComplement())
232 // bottom view, then top
233 cra_views.add(((jalview.gui.AlignViewport) af2
234 .getViewport().getCodingComplement())
236 cra_views.add(af2.getViewport().getAlignPanel());
240 HashMap<String, List<String>> xrptypes = new HashMap<String, List<String>>();
241 // first save/verify views.
242 for (AlignmentViewPanel avp : cra_views)
244 nextxref = first + " -> " + db + "{" + firstcr_ap++ + "}";
245 // verify references for this panel
246 AlignmentTest.assertAlignmentDatasetRefs(avp.getAlignment(),
247 "Pass (" + pass1 + "," + pass2 + "," + pass3
248 + "): before start of pass3: " + nextxref
250 assertDatasetIsNormalisedKnownDefect(avp.getAlignment(),
251 "Pass (" + pass1 + "," + pass2 + "," + pass3
252 + "): before start of pass3: " + nextxref
255 SequenceI[] xrseqs = avp.getAlignment().getSequencesArray();
257 List<String> _xrptypes = (seqs == null || seqs.length == 0) ? null
258 : new CrossRef(xrseqs, dataset)
259 .findXrefSourcesForSequences(avp
260 .getAlignViewport().isNucleotide());
262 stringify(dbtoviewBit, savedProjects, nextxref, avp);
263 xrptypes.put(nextxref, _xrptypes);
267 // now do the second xref pass starting from either saved or just
268 // recovered split pane, in sequence
269 do // retrieve second set of cross refs or recover and verify
272 for (AlignmentViewPanel avp : cra_views)
274 nextxref = first + " -> " + db + "{" + firstcr_ap++ + "}";
275 for (String xrefdb : xrptypes.get(nextxref))
277 List<AlignmentViewPanel> cra_views2 = new ArrayList<AlignmentViewPanel>();
279 String nextnextxref = nextxref + " -> " + xrefdb + "{"
285 SequenceI[] xrseqs = avp.getAlignment()
286 .getSequencesArray();
287 AlignFrame nextaf = Desktop.getAlignFrameFor(avp
288 .getAlignViewport());
290 cra = new CrossRefAction(nextaf, xrseqs, avp
291 .getAlignViewport().isNucleotide(), xrefdb);
293 if (cra.getXrefViews().size() == 0)
296 .add("No crossrefs retrieved for '"
297 + nextxref + "' to " + xrefdb
298 + " via '" + nextaf.getTitle() + "'");
301 cra_views2 = cra.getXrefViews();
302 assertNucleotide(cra_views2.get(0),
303 "Nucleotide panel included proteins for '"
304 + nextxref + "' to " + xrefdb
305 + " via '" + nextaf.getTitle() + "'");
306 assertProtein(cra_views2.get(1),
307 "Protein panel included nucleotides for '"
308 + nextxref + "' to " + xrefdb
309 + " via '" + nextaf.getTitle() + "'");
314 Desktop.instance.closeAll_actionPerformed(null);
315 // recover stored project
316 File storedProject = savedProjects.get(nextnextxref);
317 if (storedProject == null)
319 failedProjectRecoveries
320 .add("Failed to store a view for '"
321 + nextnextxref + "'");
324 AlignFrame af2 = new FileLoader(false)
325 .LoadFileWaitTillLoaded(
326 savedProjects.get(nextnextxref)
328 DataSourceType.FILE);
329 System.out.println("Recovered view for '"
330 + nextnextxref + "' from '"
331 + savedProjects.get(nextnextxref).toString()
333 // gymnastics to recover the alignPanel/Complementary
335 if (af2.getViewport().isNucleotide())
337 // top view, then bottom
338 cra_views2.add(af2.getViewport().getAlignPanel());
339 cra_views2.add(((jalview.gui.AlignViewport) af2
340 .getViewport().getCodingComplement())
346 // bottom view, then top
347 cra_views2.add(((jalview.gui.AlignViewport) af2
348 .getViewport().getCodingComplement())
350 cra_views2.add(af2.getViewport().getAlignPanel());
352 Assert.assertEquals(cra_views2.size(), 2);
353 Assert.assertNotNull(cra_views2.get(0));
354 Assert.assertNotNull(cra_views2.get(1));
357 for (AlignmentViewPanel nextavp : cra_views2)
359 nextnextxref = nextxref + " -> " + xrefdb + "{" + q++
362 // verify references for this panel
363 AlignmentTest.assertAlignmentDatasetRefs(
364 nextavp.getAlignment(), "" + "Pass (" + pass1
365 + "," + pass2 + "): For "
366 + nextnextxref + ":");
367 assertDatasetIsNormalisedKnownDefect(
368 nextavp.getAlignment(), "" + "Pass (" + pass1
369 + "," + pass2 + "): For "
370 + nextnextxref + ":");
372 stringify(dbtoviewBit, savedProjects, nextnextxref,
374 keyseq.add(nextnextxref);
376 } // end of loop around showing all xrefdb for crossrf2
378 } // end of loop around all viewpanels from crossrf1
379 } while (pass2 == 2 && pass3++ < 2);
380 // fetchdb->crossref1->crossref-2->verify for xrefs we
381 // either loop twice when pass2=0, or just once when pass2=1
382 // (recovered project from previous crossref)
384 } // end of loop over db-xrefs for crossref-2
386 // fetchdb-->crossref1
387 // for each xref we try to retrieve xref, store and verify when
388 // pass1=0, or just retrieve and verify when pass1=1
389 } while (pass1 == 1 && pass2++ < 2);
392 // loop twice: first, do the retrieve, second recover from saved project
394 // increment pass counters, so we repeat traversal starting from the
395 // oldest saved project first.
398 // verify stored projects for first set of cross references
400 // and verify cross-references retrieved from stored projects
410 if (failedXrefMenuItems.size() > 0)
412 for (String s : failedXrefMenuItems)
414 System.err.println(s);
416 Assert.fail("Faulty xref menu (" + failedXrefMenuItems.size()
419 if (failedProjectRecoveries.size() > 0)
422 for (String s : failedProjectRecoveries)
424 System.err.println(s);
426 Assert.fail("Didn't recover projects for some retrievals (did they retrieve ?) ("
427 + failedProjectRecoveries.size() + " counts)");
429 if (failedDBRetr.size() > 0)
431 for (String s : failedProjectRecoveries)
433 System.err.println(s);
435 Assert.fail("Didn't retrieve some db refs for checking cross-refs ("
436 + failedDBRetr.size() + " counts)");
441 * wrapper to trap known defect for AH002001 testcase
446 private void assertDatasetIsNormalisedKnownDefect(AlignmentI al,
451 AlignmentTest.assertDatasetIsNormalised(al, message);
452 } catch (AssertionError ae)
454 if (!ae.getMessage().endsWith("EMBL|AH002001"))
461 .println("Ignored exception for known defect: JAL-2179 : "
468 private void assertProtein(AlignmentViewPanel alignmentViewPanel,
471 assertType(true, alignmentViewPanel, message);
474 private void assertNucleotide(AlignmentViewPanel alignmentViewPanel,
477 assertType(false, alignmentViewPanel, message);
480 private void assertType(boolean expectProtein,
481 AlignmentViewPanel alignmentViewPanel, String message)
483 List<SequenceI> nonType = new ArrayList<SequenceI>();
484 for (SequenceI sq : alignmentViewPanel.getAlignViewport()
485 .getAlignment().getSequences())
487 if (sq.isProtein() != expectProtein)
492 if (nonType.size() > 0)
494 Assert.fail(message + " [ "
495 + (expectProtein ? "nucleotides were " : "proteins were ")
496 + nonType.toString() + " ]");
501 * first time called, record strings derived from alignment and
502 * alignedcodonframes, and save view to a project file. Second time called,
503 * compare strings to existing ones. org.testng.Assert.assertTrue on
507 * map between xrefpath and view string
508 * @param savedProjects
509 * - map from xrefpath to saved project filename (createTempFile)
511 * - xrefpath - unique ID for this context (composed of sequence of
512 * db-fetch/cross-ref actions preceeding state)
514 * - viewpanel to store (for viewpanels in splitframe, the same
515 * project should be written for both panels, only one needs
516 * recovering for comparison on the next stringify call, but each
517 * viewpanel needs to be called with a distinct xrefpath to ensure
518 * each one's strings are compared)
520 private void stringify(HashMap<String, String> dbtoviewBit,
521 HashMap<String, File> savedProjects, String xrefpath,
522 AlignmentViewPanel avp)
524 if (savedProjects != null)
526 if (savedProjects.get(xrefpath) == null)
528 // write a project file for this view. On the second pass, this will be
529 // recovered and cross-references verified
532 File prfile = File.createTempFile("crossRefTest", ".jvp");
533 AlignFrame af = Desktop.getAlignFrameFor(avp.getAlignViewport());
534 new Jalview2XML(false).saveAlignment(af, prfile.toString(),
536 System.out.println("Written view from '" + xrefpath + "' as '"
537 + prfile.getAbsolutePath() + "'");
538 savedProjects.put(xrefpath, prfile);
539 } catch (IOException q)
541 Assert.fail("Unexpected IO Exception", q);
546 System.out.println("Stringify check on view from '" + xrefpath
547 + "' [ possibly retrieved from '"
548 + savedProjects.get(xrefpath).getAbsolutePath() + "' ]");
553 StringBuilder sbr = new StringBuilder();
554 sbr.append(avp.getAlignment().toString());
556 sbr.append("<End of alignment>");
558 sbr.append(avp.getAlignment().getDataset());
560 sbr.append("<End of dataset>");
563 if (avp.getAlignment().getCodonFrames() != null)
565 for (AlignedCodonFrame ac : avp.getAlignment().getCodonFrames())
567 sbr.append("<AlignedCodonFrame " + p++ + ">");
569 sbr.append(ac.toString());
573 String dbt = dbtoviewBit.get(xrefpath);
576 dbtoviewBit.put(xrefpath, sbr.toString());
580 Assert.assertEquals(sbr.toString(), dbt, "stringify mismatch for "