1 package jalview.ext.archaeopteryx;
3 import jalview.analysis.TreeBuilder;
4 import jalview.datamodel.SequenceI;
5 import jalview.ext.treeviewer.ExternalTreeBuilderI;
6 import jalview.ext.treeviewer.ExternalTreeViewerBindingI;
7 import jalview.gui.Desktop;
8 import jalview.gui.JvOptionPane;
9 import jalview.util.MessageManager;
10 import jalview.viewmodel.AlignmentViewport;
12 import java.awt.Component;
13 import java.awt.Dimension;
14 import java.awt.event.ActionEvent;
15 import java.awt.event.ActionListener;
17 import java.io.FileNotFoundException;
18 import java.io.IOException;
19 import java.net.MalformedURLException;
21 import java.util.HashMap;
24 import javax.swing.JMenu;
25 import javax.swing.JMenuBar;
26 import javax.swing.JMenuItem;
27 import javax.swing.JSeparator;
29 import org.forester.archaeopteryx.AptxUtil;
30 import org.forester.archaeopteryx.Archaeopteryx;
31 import org.forester.archaeopteryx.Configuration;
32 import org.forester.archaeopteryx.MainFrame;
33 import org.forester.archaeopteryx.webservices.PhylogeniesWebserviceClient;
34 import org.forester.archaeopteryx.webservices.WebserviceUtil;
35 import org.forester.io.parsers.PhylogenyParser;
36 import org.forester.io.parsers.nexus.NexusPhylogeniesParser;
37 import org.forester.io.parsers.nhx.NHXParser;
38 import org.forester.io.parsers.phyloxml.PhyloXmlDataFormatException;
39 import org.forester.io.parsers.phyloxml.PhyloXmlParser;
40 import org.forester.io.parsers.tol.TolParser;
41 import org.forester.io.parsers.util.ParserUtils;
42 import org.forester.phylogeny.Phylogeny;
43 import org.forester.phylogeny.PhylogenyMethods;
44 import org.forester.phylogeny.PhylogenyNode;
45 import org.forester.phylogeny.data.Identifier;
46 import org.forester.util.ForesterUtil;
49 * Static class for creating Archaeopteryx tree viewer instances from calculated
50 * trees and letting them be bound to Jalview.
52 * @author kjvanderheide
55 public final class AptxInit
57 private final static Configuration APTX_CONFIG = new Configuration(
58 "_aptx_jalview_configuration_file",
61 private final static boolean VALIDATE_PHYLOXML_XSD = APTX_CONFIG
62 .isValidatePhyloXmlAgainstSchema();
64 private final static boolean REPLACE_NHX_UNDERSCORES = APTX_CONFIG
65 .isReplaceUnderscoresInNhParsing();
67 private final static boolean INTERNAL_NUMBERS_AS_CONFIDENCE = APTX_CONFIG
68 .isInternalNumberAreConfidenceForNhParsing();
70 private final static boolean MIDPOINT_REROOT = APTX_CONFIG
73 private final static NHXParser.TAXONOMY_EXTRACTION TAXONOMY_EXTRACTION = APTX_CONFIG
74 .getTaxonomyExtraction();
76 private static Map<MainFrame, JalviewBinding> activeAptx = new HashMap<>();
80 public static MainFrame createInstanceFromCalculation(
81 final TreeBuilder calculatedTree)
83 ExternalTreeBuilderI<Phylogeny, PhylogenyNode> aptxTreeBuilder = new AptxTreeBuilder(
86 Phylogeny aptxTree = aptxTreeBuilder.buildTree();
88 MainFrame aptxApp = createAptxFrame(aptxTree,
89 calculatedTree.getAvport(), null);
95 * Refactored from Archaeopteryx.main
100 * @throws IOException
101 * @throws FileNotFoundException
103 public static MainFrame[] createInstancesFromFile(String filePath,
104 AlignmentViewport viewport)
105 throws FileNotFoundException, IOException
107 File treeFile = new File(filePath);
108 final String err = ForesterUtil.isReadableFile(treeFile);
109 if (!ForesterUtil.isEmpty(err))
111 JvOptionPane.showMessageDialog(Desktop.desktop, err,
112 MessageManager.getString("label.problem_reading_tree_file"),
113 JvOptionPane.WARNING_MESSAGE);
116 if (Desktop.instance != null)
118 Desktop.instance.startLoading(filePath);
120 boolean nhx_or_nexus = false;
121 final PhylogenyParser parser = ParserUtils.createParserDependingOnFileType(
122 treeFile, VALIDATE_PHYLOXML_XSD);
123 if (parser instanceof NHXParser)
126 final NHXParser nhx = (NHXParser) parser;
127 nhx.setReplaceUnderscores(REPLACE_NHX_UNDERSCORES);
128 nhx.setIgnoreQuotes(false);
129 nhx.setTaxonomyExtraction(TAXONOMY_EXTRACTION);
131 else if (parser instanceof NexusPhylogeniesParser)
134 final NexusPhylogeniesParser nex = (NexusPhylogeniesParser) parser;
135 nex.setReplaceUnderscores(REPLACE_NHX_UNDERSCORES);
136 nex.setIgnoreQuotes(false);
138 else if (parser instanceof PhyloXmlParser)
140 if (VALIDATE_PHYLOXML_XSD == false)
142 JvOptionPane.showInternalMessageDialog(Desktop.desktop,
143 MessageManager.getString("error.phyloxml_validation"),
144 MessageManager.getString("label.file_open_error"),
145 JvOptionPane.WARNING_MESSAGE );
148 Phylogeny[] trees = PhylogenyMethods.readPhylogenies(parser, treeFile);
149 MainFrame[] aptxFrames = new MainFrame[trees.length];
152 for (int i = 0; i < trees.length; i++)
154 Phylogeny tree = trees[i];
156 if (nhx_or_nexus && INTERNAL_NUMBERS_AS_CONFIDENCE)
158 PhylogenyMethods.transferInternalNodeNamesToConfidence(tree, "");
160 String treeTitle = treeFile.getName() + "[" + i + "]";
161 tree.setName(treeTitle);
162 aptxFrames[i] = createAptxFrame(tree, viewport, treeTitle);
165 if (Desktop.instance != null)
167 Desktop.instance.stopLoading();
173 public static MainFrame[] createInstancesFromUrl(URL treeUrl,
174 AlignmentViewport viewport)
175 throws FileNotFoundException, IOException, RuntimeException
178 String treeTitle = treeUrl.getFile();
179 if (Desktop.instance != null)
181 Desktop.instance.startLoading(treeTitle);
183 Phylogeny[] trees = AptxUtil.readPhylogeniesFromUrl(treeUrl,
184 VALIDATE_PHYLOXML_XSD,
185 REPLACE_NHX_UNDERSCORES, INTERNAL_NUMBERS_AS_CONFIDENCE,
186 TAXONOMY_EXTRACTION, MIDPOINT_REROOT);
188 MainFrame[] aptxFrames = new MainFrame[trees.length];
189 for (int i = 0; i < trees.length; i++)
191 Phylogeny tree = trees[i];
192 aptxFrames[i] = createAptxFrame(tree, viewport, treeTitle);
195 if (Desktop.instance != null)
197 Desktop.instance.stopLoading();
205 * Refactored from Forester's UrlTreeReader, this can be more efficient
207 * @param databaseIndex
211 public static MainFrame[] createInstancesFromDb(
212 PhylogeniesWebserviceClient treeDbClient, String identifier,
213 AlignmentViewport viewport)
217 Phylogeny[] trees = null;
219 if ((identifier != null) && (identifier.trim().length() > 0))
221 if (Desktop.instance != null)
223 Desktop.instance.startLoading(identifier);
226 identifier = identifier.trim();
227 if (treeDbClient.isQueryInteger())
229 identifier = identifier.replaceAll("^\\D+", "");
234 id = Integer.parseInt(identifier);
235 } catch (final NumberFormatException e)
237 JvOptionPane.showInternalMessageDialog(Desktop.desktop,
238 MessageManager.formatMessage(
239 "error.database_id_has_letters", new String[]
241 MessageManager.getString("label.invalid_url"),
242 JvOptionPane.ERROR_MESSAGE);
243 return new MainFrame[0];
245 identifier = id + "";
247 boolean exception = false;
250 String url_str = treeDbClient.getUrl();
251 url_str = url_str.replaceFirst(
252 PhylogeniesWebserviceClient.QUERY_PLACEHOLDER, identifier);
253 url = new URL(url_str);
254 PhylogenyParser parser = null;
255 switch (treeDbClient.getReturnFormat())
257 case TOL_XML_RESPONSE:
258 parser = new TolParser();
261 parser = new NexusPhylogeniesParser();
262 ((NexusPhylogeniesParser) parser).setReplaceUnderscores(true);
265 parser = new NexusPhylogeniesParser();
266 ((NexusPhylogeniesParser) parser).setReplaceUnderscores(true);
267 ((NexusPhylogeniesParser) parser)
268 .setTaxonomyExtraction(NHXParser.TAXONOMY_EXTRACTION.NO);
271 parser = new NexusPhylogeniesParser();
272 ((NexusPhylogeniesParser) parser).setReplaceUnderscores(true);
273 ((NexusPhylogeniesParser) parser)
274 .setTaxonomyExtraction(NHXParser.TAXONOMY_EXTRACTION.NO);
277 parser = new NHXParser();
279 .setTaxonomyExtraction(NHXParser.TAXONOMY_EXTRACTION.NO);
280 ((NHXParser) parser).setReplaceUnderscores(true);
281 ((NHXParser) parser).setGuessRootedness(true);
283 case NH_EXTRACT_TAXONOMY:
284 parser = new NHXParser();
285 ((NHXParser) parser).setTaxonomyExtraction(
286 NHXParser.TAXONOMY_EXTRACTION.AGGRESSIVE);
287 ((NHXParser) parser).setReplaceUnderscores(false);
288 ((NHXParser) parser).setGuessRootedness(true);
291 parser = new NHXParser();
292 ((NHXParser) parser).setTaxonomyExtraction(
293 NHXParser.TAXONOMY_EXTRACTION.PFAM_STYLE_STRICT);
294 ((NHXParser) parser).setReplaceUnderscores(false);
295 ((NHXParser) parser).setGuessRootedness(true);
298 parser = new NHXParser();
300 .setTaxonomyExtraction(NHXParser.TAXONOMY_EXTRACTION.NO);
301 ((NHXParser) parser).setReplaceUnderscores(false);
302 ((NHXParser) parser).setGuessRootedness(true);
305 parser = PhyloXmlParser.createPhyloXmlParserXsdValidating();
308 throw new IllegalArgumentException(
309 "unknown format: " + treeDbClient.getReturnFormat());
312 // if (_main_frame.getMainPanel().getCurrentTreePanel() != null)
314 // _main_frame.getMainPanel().getCurrentTreePanel().setWaitCursor();
318 // _main_frame.getMainPanel().setWaitCursor();
320 trees = ForesterUtil.readPhylogeniesFromUrl(url, parser);
321 } catch (final MalformedURLException e)
324 JvOptionPane.showInternalMessageDialog(Desktop.desktop,
325 MessageManager.formatMessage(
326 "exception.unable_to_launch_url", new String[]
328 MessageManager.getString("label.invalid_url"),
329 JvOptionPane.ERROR_MESSAGE);
330 System.err.println(e.getLocalizedMessage());
331 } catch (final IOException e)
334 JvOptionPane.showInternalMessageDialog(Desktop.desktop,
335 "Could not read from " + url + "\n"
336 + e.getLocalizedMessage(),
337 "Failed to read tree from " + treeDbClient.getName() + " for "
339 JvOptionPane.ERROR_MESSAGE);
340 System.err.println(e.getLocalizedMessage());
341 } catch (final NumberFormatException e)
344 JvOptionPane.showInternalMessageDialog(Desktop.desktop,
345 "Could not read from " + url + "\n"
346 + e.getLocalizedMessage(),
347 "Failed to read tree from " + treeDbClient.getName() + " for "
349 JvOptionPane.ERROR_MESSAGE);
350 System.err.println(e.getLocalizedMessage());
351 } catch (final Exception e)
355 JvOptionPane.showInternalMessageDialog(Desktop.desktop,
356 e.getLocalizedMessage(), "Unexpected Exception",
357 JvOptionPane.ERROR_MESSAGE);
358 System.err.println(e.getLocalizedMessage());
360 if ((trees != null) && (trees.length > 0))
362 for (final Phylogeny phylogeny : trees)
364 if (!phylogeny.isEmpty())
366 if (treeDbClient.getName().equals(WebserviceUtil.TREE_FAM_NAME))
368 phylogeny.setRerootable(false);
369 phylogeny.setRooted(true);
371 if (treeDbClient.getProcessingInstructions() != null)
375 WebserviceUtil.processInstructions(treeDbClient, phylogeny);
376 } catch (final PhyloXmlDataFormatException e)
378 JvOptionPane.showInternalMessageDialog(Desktop.desktop,
379 "Error:\n" + e.getLocalizedMessage(), "Error",
380 JvOptionPane.ERROR_MESSAGE);
383 if (treeDbClient.getNodeField() != null)
387 PhylogenyMethods.transferNodeNameToField(phylogeny,
388 treeDbClient.getNodeField(), false);
389 } catch (final PhyloXmlDataFormatException e)
391 JvOptionPane.showInternalMessageDialog(Desktop.desktop,
392 "Error:\n" + e.getLocalizedMessage(), "Error",
393 JvOptionPane.ERROR_MESSAGE);
396 phylogeny.setIdentifier(
397 new Identifier(identifier, treeDbClient.getName()));
398 // _main_frame.getJMenuBar().remove(_main_frame.getHelpMenu());
399 // _main_frame.getMenuBarOfMainFrame()
400 // .add(_main_frame.getHelpMenu());
401 // _main_frame.getMainPanel().addPhylogenyInNewTab(phylogeny,
402 // _main_frame.getConfiguration(),
403 // new File(url.getFile()).getName(), url.toString());
405 MainFrame aptxApp = createAptxFrame(phylogeny, viewport,
407 String my_name_for_file = "";
408 if (!ForesterUtil.isEmpty(phylogeny.getName()))
410 my_name_for_file = new String(phylogeny.getName())
411 .replaceAll(" ", "_");
413 else if (phylogeny.getIdentifier() != null)
415 final StringBuffer sb = new StringBuffer();
417 .isEmpty(phylogeny.getIdentifier().getProvider()))
419 sb.append(phylogeny.getIdentifier().getProvider());
422 sb.append(phylogeny.getIdentifier().getValue());
423 my_name_for_file = new String(
424 sb.toString().replaceAll(" ", "_"));
426 aptxApp.getMainPanel().getCurrentTreePanel()
427 .setTreeFile(new File(my_name_for_file));
428 AptxUtil.lookAtSomeTreePropertiesForAptxControlSettings(
429 phylogeny, aptxApp.getMainPanel().getControlPanel(),
431 // _main_frame.getMainPanel().getControlPanel().showWhole();
433 aptxApp.activateSaveAllIfNeeded();
437 else if (!exception) // ..what?
439 JvOptionPane.showMessageDialog(null,
440 ForesterUtil.wordWrap(
441 "Failed to read in tree(s) from [" + url + "]", 80),
442 "Error", JvOptionPane.ERROR_MESSAGE);
444 if ((trees != null) && (trees.length > 0))
448 JvOptionPane.showMessageDialog(null,
449 ForesterUtil.wordWrap("Successfully read in "
450 + trees.length + " tree(s) from [" + url + "]",
452 "Success", JvOptionPane.INFORMATION_MESSAGE);
453 } catch (final Exception e)
455 // Not important if this fails, do nothing.
457 // _main_frame.getContentPane().repaint();
464 if (Desktop.instance != null)
466 Desktop.instance.stopLoading();
477 public static MainFrame createAptxFrame(
478 final Phylogeny aptxTree,
479 final AlignmentViewport jalviewAlignport, String treeTitle)
481 if (APTX_CONFIG == null || APTX_CONFIG.isCouldReadConfigFile() == false)
483 int keepGoing = JvOptionPane.showConfirmDialog(Desktop.desktop,
484 MessageManager.getString("label.aptx_config_not_found"),
485 MessageManager.formatMessage("label.couldnt_locate",
487 { "_aptx_jalview_configuration_file" }),
488 JvOptionPane.YES_NO_CANCEL_OPTION);
490 if (keepGoing == JvOptionPane.CANCEL_OPTION
491 || keepGoing == JvOptionPane.CLOSED_OPTION
492 || keepGoing == JvOptionPane.NO_OPTION)
498 MainFrame aptxApp = Archaeopteryx.createApplication(aptxTree,
499 APTX_CONFIG, treeTitle);
502 LoadedTreeSequenceAssociation bindAptxNodes = new LoadedTreeSequenceAssociation(
503 jalviewAlignport.getAlignment().getSequencesArray(), aptxTree);
504 bindAptxNodes.associateLeavesToSequences();
506 bindNodesToJalviewSequences(aptxApp, jalviewAlignport,
507 bindAptxNodes.getAlignmentWithNodes(),
508 bindAptxNodes.getNodesWithAlignment());
509 bindTreeViewFrameToJalview(aptxApp);
511 adaptAptxGui(aptxApp);
516 public static ExternalTreeViewerBindingI<?> bindNodesToJalviewSequences(
517 final MainFrame aptxApp,
518 final AlignmentViewport jalviewAlignViewport,
519 final Map<SequenceI, PhylogenyNode> alignMappedToNodes,
520 final Map<PhylogenyNode, SequenceI> nodesMappedToAlign)
522 JalviewBinding treeBinding = new JalviewBinding(aptxApp,
523 jalviewAlignViewport,
524 alignMappedToNodes, nodesMappedToAlign);
525 activeAptx.put(aptxApp, treeBinding);
530 public static MainFrame bindTreeViewFrameToJalview(
531 final MainFrame aptxApp)
535 aptxApp.setMinimumSize(new Dimension(width, height));
536 // aptxApp.setFont(Desktop.instance.getFont());
537 // aptxApp.getMainPanel().setFont(Desktop.instance.getFont());
538 String frameTitle = MessageManager.getString("label.aptx_title");
539 File treeFile = aptxApp.getMainPanel().getCurrentTreePanel()
541 if (treeFile != null)
543 frameTitle += MessageManager.formatMessage("label.aptx_title_append",
545 { treeFile.getAbsolutePath() });
547 Desktop.addInternalFrame(aptxApp, frameTitle, true, width, height, true,
554 * Hides certain redundant Archaeopteryx GUI elements such as the menu items
555 * for reading in trees and adds extra items related to Jalview such as the
561 private static void adaptAptxGui(MainFrame aptxFrame)
563 JMenuBar frameBar = aptxFrame.getJMenuBar();
564 boolean epsAdded = false;
565 for (int i = 0; i < frameBar.getMenuCount();i++) {
566 JMenu menu = frameBar.getMenu(i);
567 int menuCount = menu.getMenuComponentCount();
569 if (menu.getText().contains("File"))
571 // hide all "Read from ..." and "New" menu items and any Separators that
572 // come directly after them
573 Component previousComp = null;
574 for (int x = 0; x < menuCount; x++)
576 Component menuItem = menu.getMenuComponent(x);
577 if (previousComp instanceof JMenuItem)
579 JMenuItem previousMenuItem = (JMenuItem) previousComp;
580 if (previousMenuItem.getText().startsWith("Read")
581 || previousMenuItem.getText()
583 || previousMenuItem.getText()
584 .startsWith("Close Tab"))
586 previousComp.setVisible(false);
588 if (menuItem instanceof JSeparator)
590 menuItem.setVisible(false);
595 if ((!epsAdded) && previousMenuItem.getText()
596 .startsWith("Export to"))
598 JMenuItem exportEps = new JMenuItem("Export to EPS file...");
599 menu.add(exportEps, x);
600 exportEps.addActionListener(new ActionListener()
604 public void actionPerformed(ActionEvent e)
606 // TODO Auto-generated method stub
615 previousComp = menuItem;
618 else if (menu.getText().contains("Inference"))
620 menu.setVisible(false);
622 else if (menu.getText().contains("View"))
625 JMenuItem sortByTree = new JMenuItem("Sort alignment by tree");
626 JMenuItem refreshJalview = new JMenuItem(
627 "Filter alignment to show only currently visible sequences");
629 refreshJalview.setFont(menu.getFont());
631 menu.add(sortByTree);
632 menu.add(refreshJalview);
634 sortByTree.setFont(menu.getFont());
635 refreshJalview.addActionListener(activeAptx.get(aptxFrame));
641 aptxFrame.validate();
644 public static Map<MainFrame, JalviewBinding> getAllAptxFrames()