1 package jalview.ext.archaeopteryx;
3 import jalview.analysis.TreeBuilder;
4 import jalview.bin.Cache;
5 import jalview.datamodel.SequenceI;
6 import jalview.ext.treeviewer.ExternalTreeBuilderI;
7 import jalview.ext.treeviewer.ExternalTreeViewerBindingI;
8 import jalview.gui.Desktop;
9 import jalview.gui.JvOptionPane;
10 import jalview.util.MessageManager;
11 import jalview.viewmodel.AlignmentViewport;
13 import java.awt.Component;
14 import java.awt.Dimension;
16 import java.io.FileNotFoundException;
17 import java.io.IOException;
18 import java.net.MalformedURLException;
20 import java.util.HashMap;
23 import javax.swing.JMenu;
24 import javax.swing.JMenuBar;
25 import javax.swing.JMenuItem;
26 import javax.swing.JSeparator;
28 import org.forester.archaeopteryx.AptxUtil;
29 import org.forester.archaeopteryx.Archaeopteryx;
30 import org.forester.archaeopteryx.Configuration;
31 import org.forester.archaeopteryx.MainFrame;
32 import org.forester.archaeopteryx.webservices.PhylogeniesWebserviceClient;
33 import org.forester.archaeopteryx.webservices.WebserviceUtil;
34 import org.forester.io.parsers.PhylogenyParser;
35 import org.forester.io.parsers.nexus.NexusPhylogeniesParser;
36 import org.forester.io.parsers.nhx.NHXParser;
37 import org.forester.io.parsers.phyloxml.PhyloXmlDataFormatException;
38 import org.forester.io.parsers.phyloxml.PhyloXmlParser;
39 import org.forester.io.parsers.tol.TolParser;
40 import org.forester.io.parsers.util.ParserUtils;
41 import org.forester.phylogeny.Phylogeny;
42 import org.forester.phylogeny.PhylogenyMethods;
43 import org.forester.phylogeny.PhylogenyNode;
44 import org.forester.phylogeny.data.Identifier;
45 import org.forester.util.ForesterUtil;
48 * Static class for creating Archaeopteryx tree viewer instances from calculated
49 * trees and letting them be bound to Jalview.
51 * @author kjvanderheide
54 public final class AptxInit
56 // yet to add user preferred config
57 private final static Configuration APTX_CONFIG = new Configuration(
58 Cache.getDefault("APTXCONFIG",
59 Desktop.instance.getClass()
61 "/_aptx_jalview_configuration_file.txt")
65 private final static boolean VALIDATE_PHYLOXML_XSD = APTX_CONFIG
66 .isValidatePhyloXmlAgainstSchema();
68 private final static boolean REPLACE_NHX_UNDERSCORES = APTX_CONFIG
69 .isReplaceUnderscoresInNhParsing();
71 private final static boolean INTERNAL_NUMBERS_AS_CONFIDENCE = APTX_CONFIG
72 .isInternalNumberAreConfidenceForNhParsing();
74 private final static boolean MIDPOINT_REROOT = APTX_CONFIG
77 private final static NHXParser.TAXONOMY_EXTRACTION TAXONOMY_EXTRACTION = APTX_CONFIG
78 .getTaxonomyExtraction();
80 private static Map<MainFrame, JalviewBinding> activeAptx = new HashMap<>();
84 public static MainFrame createInstanceFromCalculation(
85 final TreeBuilder calculatedTree)
87 ExternalTreeBuilderI<Phylogeny, PhylogenyNode> aptxTreeBuilder = new AptxTreeBuilder(
90 Phylogeny aptxTree = aptxTreeBuilder.buildTree();
92 MainFrame aptxApp = createAptxFrame(aptxTree,
93 calculatedTree.getAvport(), null);
99 * Refactored from Archaeopteryx.main
104 * @throws IOException
105 * @throws FileNotFoundException
107 public static MainFrame[] createInstancesFromFile(String filePath,
108 AlignmentViewport viewport)
109 throws FileNotFoundException, IOException
111 File treeFile = new File(filePath);
112 final String err = ForesterUtil.isReadableFile(treeFile);
113 if (!ForesterUtil.isEmpty(err))
115 JvOptionPane.showMessageDialog(Desktop.desktop, err,
116 MessageManager.getString("label.problem_reading_tree_file"),
117 JvOptionPane.WARNING_MESSAGE);
120 if (Desktop.instance != null)
122 Desktop.instance.startLoading(filePath);
124 boolean nhx_or_nexus = false;
125 final PhylogenyParser parser = ParserUtils.createParserDependingOnFileType(
126 treeFile, VALIDATE_PHYLOXML_XSD);
127 if (parser instanceof NHXParser)
130 final NHXParser nhx = (NHXParser) parser;
131 nhx.setReplaceUnderscores(REPLACE_NHX_UNDERSCORES);
132 nhx.setIgnoreQuotes(false);
133 nhx.setTaxonomyExtraction(TAXONOMY_EXTRACTION);
135 else if (parser instanceof NexusPhylogeniesParser)
138 final NexusPhylogeniesParser nex = (NexusPhylogeniesParser) parser;
139 nex.setReplaceUnderscores(REPLACE_NHX_UNDERSCORES);
140 nex.setIgnoreQuotes(false);
142 else if (parser instanceof PhyloXmlParser)
144 if (VALIDATE_PHYLOXML_XSD == false)
146 JvOptionPane.showInternalMessageDialog(Desktop.desktop,
147 MessageManager.getString("error.phyloxml_validation"),
148 MessageManager.getString("label.file_open_error"),
149 JvOptionPane.WARNING_MESSAGE );
152 Phylogeny[] trees = PhylogenyMethods.readPhylogenies(parser, treeFile);
153 MainFrame[] aptxFrames = new MainFrame[trees.length];
156 for (int i = 0; i < trees.length; i++)
158 Phylogeny tree = trees[i];
160 if (nhx_or_nexus && INTERNAL_NUMBERS_AS_CONFIDENCE)
162 PhylogenyMethods.transferInternalNodeNamesToConfidence(tree, "");
164 String treeTitle = treeFile.getName() + "[" + i + "]";
165 tree.setName(treeTitle);
166 aptxFrames[i] = createAptxFrame(tree, viewport, treeTitle);
169 if (Desktop.instance != null)
171 Desktop.instance.stopLoading();
177 public static MainFrame[] createInstancesFromUrl(URL treeUrl,
178 AlignmentViewport viewport)
179 throws FileNotFoundException, IOException, RuntimeException
182 String treeTitle = treeUrl.getFile();
183 if (Desktop.instance != null)
185 Desktop.instance.startLoading(treeTitle);
187 Phylogeny[] trees = AptxUtil.readPhylogeniesFromUrl(treeUrl,
188 VALIDATE_PHYLOXML_XSD,
189 REPLACE_NHX_UNDERSCORES, INTERNAL_NUMBERS_AS_CONFIDENCE,
190 TAXONOMY_EXTRACTION, MIDPOINT_REROOT);
192 MainFrame[] aptxFrames = new MainFrame[trees.length];
193 for (int i = 0; i < trees.length; i++)
195 Phylogeny tree = trees[i];
196 aptxFrames[i] = createAptxFrame(tree, viewport, treeTitle);
199 if (Desktop.instance != null)
201 Desktop.instance.stopLoading();
209 * Refactored from Forester's UrlTreeReader, this can be more efficient
211 * @param databaseIndex
215 public static MainFrame[] createInstancesFromDb(
216 PhylogeniesWebserviceClient treeDbClient, String identifier,
217 AlignmentViewport viewport)
221 Phylogeny[] trees = null;
223 if ((identifier != null) && (identifier.trim().length() > 0))
225 if (Desktop.instance != null)
227 Desktop.instance.startLoading(identifier);
230 identifier = identifier.trim();
231 if (treeDbClient.isQueryInteger())
233 identifier = identifier.replaceAll("^\\D+", "");
238 id = Integer.parseInt(identifier);
239 } catch (final NumberFormatException e)
241 JvOptionPane.showInternalMessageDialog(Desktop.desktop,
242 MessageManager.formatMessage(
243 "error.database_id_has_letters", new String[]
245 MessageManager.getString("label.invalid_url"),
246 JvOptionPane.ERROR_MESSAGE);
247 return new MainFrame[0];
249 identifier = id + "";
251 boolean exception = false;
254 String url_str = treeDbClient.getUrl();
255 url_str = url_str.replaceFirst(
256 PhylogeniesWebserviceClient.QUERY_PLACEHOLDER, identifier);
257 url = new URL(url_str);
258 PhylogenyParser parser = null;
259 switch (treeDbClient.getReturnFormat())
261 case TOL_XML_RESPONSE:
262 parser = new TolParser();
265 parser = new NexusPhylogeniesParser();
266 ((NexusPhylogeniesParser) parser).setReplaceUnderscores(true);
269 parser = new NexusPhylogeniesParser();
270 ((NexusPhylogeniesParser) parser).setReplaceUnderscores(true);
271 ((NexusPhylogeniesParser) parser)
272 .setTaxonomyExtraction(NHXParser.TAXONOMY_EXTRACTION.NO);
275 parser = new NexusPhylogeniesParser();
276 ((NexusPhylogeniesParser) parser).setReplaceUnderscores(true);
277 ((NexusPhylogeniesParser) parser)
278 .setTaxonomyExtraction(NHXParser.TAXONOMY_EXTRACTION.NO);
281 parser = new NHXParser();
283 .setTaxonomyExtraction(NHXParser.TAXONOMY_EXTRACTION.NO);
284 ((NHXParser) parser).setReplaceUnderscores(true);
285 ((NHXParser) parser).setGuessRootedness(true);
287 case NH_EXTRACT_TAXONOMY:
288 parser = new NHXParser();
289 ((NHXParser) parser).setTaxonomyExtraction(
290 NHXParser.TAXONOMY_EXTRACTION.AGGRESSIVE);
291 ((NHXParser) parser).setReplaceUnderscores(false);
292 ((NHXParser) parser).setGuessRootedness(true);
295 parser = new NHXParser();
296 ((NHXParser) parser).setTaxonomyExtraction(
297 NHXParser.TAXONOMY_EXTRACTION.PFAM_STYLE_STRICT);
298 ((NHXParser) parser).setReplaceUnderscores(false);
299 ((NHXParser) parser).setGuessRootedness(true);
302 parser = new NHXParser();
304 .setTaxonomyExtraction(NHXParser.TAXONOMY_EXTRACTION.NO);
305 ((NHXParser) parser).setReplaceUnderscores(false);
306 ((NHXParser) parser).setGuessRootedness(true);
309 parser = PhyloXmlParser.createPhyloXmlParserXsdValidating();
312 throw new IllegalArgumentException(
313 "unknown format: " + treeDbClient.getReturnFormat());
316 // if (_main_frame.getMainPanel().getCurrentTreePanel() != null)
318 // _main_frame.getMainPanel().getCurrentTreePanel().setWaitCursor();
322 // _main_frame.getMainPanel().setWaitCursor();
324 trees = ForesterUtil.readPhylogeniesFromUrl(url, parser);
325 } catch (final MalformedURLException e)
328 JvOptionPane.showInternalMessageDialog(Desktop.desktop,
329 MessageManager.formatMessage(
330 "exception.unable_to_launch_url", new String[]
332 MessageManager.getString("label.invalid_url"),
333 JvOptionPane.ERROR_MESSAGE);
334 System.err.println(e.getLocalizedMessage());
335 } catch (final IOException e)
338 JvOptionPane.showInternalMessageDialog(Desktop.desktop,
339 "Could not read from " + url + "\n"
340 + e.getLocalizedMessage(),
341 "Failed to read tree from " + treeDbClient.getName() + " for "
343 JvOptionPane.ERROR_MESSAGE);
344 System.err.println(e.getLocalizedMessage());
345 } catch (final NumberFormatException e)
348 JvOptionPane.showInternalMessageDialog(Desktop.desktop,
349 "Could not read from " + url + "\n"
350 + e.getLocalizedMessage(),
351 "Failed to read tree from " + treeDbClient.getName() + " for "
353 JvOptionPane.ERROR_MESSAGE);
354 System.err.println(e.getLocalizedMessage());
355 } catch (final Exception e)
359 JvOptionPane.showInternalMessageDialog(Desktop.desktop,
360 e.getLocalizedMessage(), "Unexpected Exception",
361 JvOptionPane.ERROR_MESSAGE);
362 System.err.println(e.getLocalizedMessage());
364 if ((trees != null) && (trees.length > 0))
366 for (final Phylogeny phylogeny : trees)
368 if (!phylogeny.isEmpty())
370 if (treeDbClient.getName().equals(WebserviceUtil.TREE_FAM_NAME))
372 phylogeny.setRerootable(false);
373 phylogeny.setRooted(true);
375 if (treeDbClient.getProcessingInstructions() != null)
379 WebserviceUtil.processInstructions(treeDbClient, phylogeny);
380 } catch (final PhyloXmlDataFormatException e)
382 JvOptionPane.showInternalMessageDialog(Desktop.desktop,
383 "Error:\n" + e.getLocalizedMessage(), "Error",
384 JvOptionPane.ERROR_MESSAGE);
387 if (treeDbClient.getNodeField() != null)
391 PhylogenyMethods.transferNodeNameToField(phylogeny,
392 treeDbClient.getNodeField(), false);
393 } catch (final PhyloXmlDataFormatException e)
395 JvOptionPane.showInternalMessageDialog(Desktop.desktop,
396 "Error:\n" + e.getLocalizedMessage(), "Error",
397 JvOptionPane.ERROR_MESSAGE);
400 phylogeny.setIdentifier(
401 new Identifier(identifier, treeDbClient.getName()));
402 // _main_frame.getJMenuBar().remove(_main_frame.getHelpMenu());
403 // _main_frame.getMenuBarOfMainFrame()
404 // .add(_main_frame.getHelpMenu());
405 // _main_frame.getMainPanel().addPhylogenyInNewTab(phylogeny,
406 // _main_frame.getConfiguration(),
407 // new File(url.getFile()).getName(), url.toString());
409 MainFrame aptxApp = createAptxFrame(phylogeny, viewport,
411 String my_name_for_file = "";
412 if (!ForesterUtil.isEmpty(phylogeny.getName()))
414 my_name_for_file = new String(phylogeny.getName())
415 .replaceAll(" ", "_");
417 else if (phylogeny.getIdentifier() != null)
419 final StringBuffer sb = new StringBuffer();
421 .isEmpty(phylogeny.getIdentifier().getProvider()))
423 sb.append(phylogeny.getIdentifier().getProvider());
426 sb.append(phylogeny.getIdentifier().getValue());
427 my_name_for_file = new String(
428 sb.toString().replaceAll(" ", "_"));
430 aptxApp.getMainPanel().getCurrentTreePanel()
431 .setTreeFile(new File(my_name_for_file));
432 AptxUtil.lookAtSomeTreePropertiesForAptxControlSettings(
433 phylogeny, aptxApp.getMainPanel().getControlPanel(),
435 // _main_frame.getMainPanel().getControlPanel().showWhole();
437 aptxApp.activateSaveAllIfNeeded();
441 else if (!exception) // ..what?
443 JvOptionPane.showMessageDialog(null,
444 ForesterUtil.wordWrap(
445 "Failed to read in tree(s) from [" + url + "]", 80),
446 "Error", JvOptionPane.ERROR_MESSAGE);
448 if ((trees != null) && (trees.length > 0))
452 JvOptionPane.showMessageDialog(null,
453 ForesterUtil.wordWrap("Successfully read in "
454 + trees.length + " tree(s) from [" + url + "]",
456 "Success", JvOptionPane.INFORMATION_MESSAGE);
457 } catch (final Exception e)
459 // Not important if this fails, do nothing.
461 // _main_frame.getContentPane().repaint();
468 if (Desktop.instance != null)
470 Desktop.instance.stopLoading();
481 public static MainFrame createAptxFrame(
482 final Phylogeny aptxTree,
483 final AlignmentViewport jalviewAlignport, String treeTitle)
485 if (APTX_CONFIG == null || APTX_CONFIG.isCouldReadConfigFile() == false)
487 int keepGoing = JvOptionPane.showConfirmDialog(Desktop.desktop,
488 MessageManager.getString("label.aptx_config_not_found"),
489 MessageManager.formatMessage("label.couldnt_locate",
491 { "_aptx_jalview_configuration_file" }),
492 JvOptionPane.YES_NO_CANCEL_OPTION);
494 if (keepGoing == JvOptionPane.CANCEL_OPTION
495 || keepGoing == JvOptionPane.CLOSED_OPTION
496 || keepGoing == JvOptionPane.NO_OPTION)
502 MainFrame aptxApp = Archaeopteryx.createApplication(aptxTree,
503 APTX_CONFIG, treeTitle);
506 LoadedTreeSequenceAssociation bindAptxNodes = new LoadedTreeSequenceAssociation(
507 jalviewAlignport.getAlignment().getSequencesArray(), aptxTree);
508 bindAptxNodes.associateLeavesToSequences();
510 bindNodesToJalviewSequences(aptxApp, jalviewAlignport,
511 bindAptxNodes.getAlignmentWithNodes(),
512 bindAptxNodes.getNodesWithAlignment());
513 bindTreeViewFrameToJalview(aptxApp);
515 adaptAptxGui(aptxApp);
520 public static ExternalTreeViewerBindingI<?> bindNodesToJalviewSequences(
521 final MainFrame aptxApp,
522 final AlignmentViewport jalviewAlignViewport,
523 final Map<SequenceI, PhylogenyNode> alignMappedToNodes,
524 final Map<PhylogenyNode, SequenceI> nodesMappedToAlign)
526 JalviewBinding treeBinding = new JalviewBinding(aptxApp,
527 jalviewAlignViewport,
528 alignMappedToNodes, nodesMappedToAlign);
529 activeAptx.put(aptxApp, treeBinding);
534 public static MainFrame bindTreeViewFrameToJalview(
535 final MainFrame aptxApp)
539 aptxApp.setMinimumSize(new Dimension(width, height));
540 // aptxApp.setFont(Desktop.instance.getFont());
541 // aptxApp.getMainPanel().setFont(Desktop.instance.getFont());
542 String frameTitle = MessageManager.getString("label.aptx_title");
543 File treeFile = aptxApp.getMainPanel().getCurrentTreePanel()
545 if (treeFile != null)
547 frameTitle += MessageManager.formatMessage("label.aptx_title_append",
549 { treeFile.getAbsolutePath() });
551 Desktop.addInternalFrame(aptxApp, frameTitle, true, width, height, true,
558 * Hides certain redundant Archaeopteryx GUI elements such as the menu items
559 * for reading in trees and adds extra items related to Jalview such as the
565 private static void adaptAptxGui(MainFrame aptxFrame)
567 JMenuBar frameBar = aptxFrame.getJMenuBar();
569 for (int i = 0; i < frameBar.getMenuCount();i++) {
570 JMenu menu = frameBar.getMenu(i);
572 if (menu.getText().contains("File"))
574 // hide all "Read from ..." and "New" menu items and any Separators that
575 // come directly after them
576 Component previousMenuItem = null;
577 for (Component menuItem : menu.getMenuComponents()) {
578 if (previousMenuItem instanceof JMenuItem)
580 if (((JMenuItem) previousMenuItem).getText().startsWith("Read")
581 || ((JMenuItem) previousMenuItem).getText()
584 previousMenuItem.setVisible(false);
586 if (menuItem instanceof JSeparator)
588 menuItem.setVisible(false);
592 previousMenuItem = menuItem;
595 else if (menu.getText().contains("Inference"))
597 menu.setVisible(false);
599 else if (menu.getText().contains("View"))
602 JMenuItem sortByTree = new JMenuItem("Sort alignment by tree");
603 JMenuItem refreshJalview = new JMenuItem(
604 "Filter alignment to show only currently visible sequences");
606 refreshJalview.setFont(menu.getFont());
608 menu.add(sortByTree);
609 menu.add(refreshJalview);
611 sortByTree.setFont(menu.getFont());
612 sortByTree.setVisible(false); // don't show unless it's actually
615 refreshJalview.addActionListener(activeAptx.get(aptxFrame));
621 aptxFrame.validate();
624 public static Map<MainFrame, JalviewBinding> getAllAptxFrames()