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;
15 import java.io.FileNotFoundException;
16 import java.io.IOException;
17 import java.net.MalformedURLException;
19 import java.util.HashMap;
22 import javax.swing.JMenu;
23 import javax.swing.JMenuBar;
24 import javax.swing.JMenuItem;
25 import javax.swing.JSeparator;
27 import org.forester.archaeopteryx.AptxUtil;
28 import org.forester.archaeopteryx.Archaeopteryx;
29 import org.forester.archaeopteryx.Configuration;
30 import org.forester.archaeopteryx.MainFrame;
31 import org.forester.archaeopteryx.webservices.PhylogeniesWebserviceClient;
32 import org.forester.archaeopteryx.webservices.WebserviceUtil;
33 import org.forester.io.parsers.PhylogenyParser;
34 import org.forester.io.parsers.nexus.NexusPhylogeniesParser;
35 import org.forester.io.parsers.nhx.NHXParser;
36 import org.forester.io.parsers.phyloxml.PhyloXmlDataFormatException;
37 import org.forester.io.parsers.phyloxml.PhyloXmlParser;
38 import org.forester.io.parsers.tol.TolParser;
39 import org.forester.io.parsers.util.ParserUtils;
40 import org.forester.phylogeny.Phylogeny;
41 import org.forester.phylogeny.PhylogenyMethods;
42 import org.forester.phylogeny.PhylogenyNode;
43 import org.forester.phylogeny.data.Identifier;
44 import org.forester.util.ForesterUtil;
47 * Static class for creating Archaeopteryx tree viewer instances from calculated
48 * trees and letting them be bound to Jalview.
50 * @author kjvanderheide
53 public final class AptxInit
55 private final static Configuration APTX_CONFIG = new Configuration(
56 "_aptx_jalview_configuration_file",
59 private final static boolean VALIDATE_PHYLOXML_XSD = APTX_CONFIG
60 .isValidatePhyloXmlAgainstSchema();
62 private final static boolean REPLACE_NHX_UNDERSCORES = APTX_CONFIG
63 .isReplaceUnderscoresInNhParsing();
65 private final static boolean INTERNAL_NUMBERS_AS_CONFIDENCE = APTX_CONFIG
66 .isInternalNumberAreConfidenceForNhParsing();
68 private final static boolean MIDPOINT_REROOT = APTX_CONFIG
71 private final static NHXParser.TAXONOMY_EXTRACTION TAXONOMY_EXTRACTION = APTX_CONFIG
72 .getTaxonomyExtraction();
74 private static Map<MainFrame, JalviewBinding> activeAptx = new HashMap<>();
78 public static MainFrame createInstanceFromCalculation(
79 final TreeBuilder calculatedTree)
81 ExternalTreeBuilderI<Phylogeny, PhylogenyNode> aptxTreeBuilder = new AptxTreeBuilder(
84 Phylogeny aptxTree = aptxTreeBuilder.buildTree();
86 MainFrame aptxApp = createAptxFrame(aptxTree,
87 calculatedTree.getAvport(), null);
93 * Refactored from Archaeopteryx.main
99 * @throws FileNotFoundException
101 public static MainFrame[] createInstancesFromFile(String filePath,
102 AlignmentViewport viewport)
103 throws FileNotFoundException, IOException
105 File treeFile = new File(filePath);
106 final String err = ForesterUtil.isReadableFile(treeFile);
107 if (!ForesterUtil.isEmpty(err))
109 JvOptionPane.showMessageDialog(Desktop.desktop, err,
110 MessageManager.getString("label.problem_reading_tree_file"),
111 JvOptionPane.WARNING_MESSAGE);
114 if (Desktop.instance != null)
116 Desktop.instance.startLoading(filePath);
118 boolean nhx_or_nexus = false;
119 final PhylogenyParser parser = ParserUtils.createParserDependingOnFileType(
120 treeFile, VALIDATE_PHYLOXML_XSD);
121 if (parser instanceof NHXParser)
124 final NHXParser nhx = (NHXParser) parser;
125 nhx.setReplaceUnderscores(REPLACE_NHX_UNDERSCORES);
126 nhx.setIgnoreQuotes(false);
127 nhx.setTaxonomyExtraction(TAXONOMY_EXTRACTION);
129 else if (parser instanceof NexusPhylogeniesParser)
132 final NexusPhylogeniesParser nex = (NexusPhylogeniesParser) parser;
133 nex.setReplaceUnderscores(REPLACE_NHX_UNDERSCORES);
134 nex.setIgnoreQuotes(false);
136 else if (parser instanceof PhyloXmlParser)
138 if (VALIDATE_PHYLOXML_XSD == false)
140 JvOptionPane.showInternalMessageDialog(Desktop.desktop,
141 MessageManager.getString("error.phyloxml_validation"),
142 MessageManager.getString("label.file_open_error"),
143 JvOptionPane.WARNING_MESSAGE );
146 Phylogeny[] trees = PhylogenyMethods.readPhylogenies(parser, treeFile);
147 MainFrame[] aptxFrames = new MainFrame[trees.length];
150 for (int i = 0; i < trees.length; i++)
152 Phylogeny tree = trees[i];
154 if (nhx_or_nexus && INTERNAL_NUMBERS_AS_CONFIDENCE)
156 PhylogenyMethods.transferInternalNodeNamesToConfidence(tree, "");
158 String treeTitle = treeFile.getName() + "[" + i + "]";
159 tree.setName(treeTitle);
160 aptxFrames[i] = createAptxFrame(tree, viewport, treeTitle);
163 if (Desktop.instance != null)
165 Desktop.instance.stopLoading();
171 public static MainFrame[] createInstancesFromUrl(URL treeUrl,
172 AlignmentViewport viewport)
173 throws FileNotFoundException, IOException, RuntimeException
176 String treeTitle = treeUrl.getFile();
177 if (Desktop.instance != null)
179 Desktop.instance.startLoading(treeTitle);
181 Phylogeny[] trees = AptxUtil.readPhylogeniesFromUrl(treeUrl,
182 VALIDATE_PHYLOXML_XSD,
183 REPLACE_NHX_UNDERSCORES, INTERNAL_NUMBERS_AS_CONFIDENCE,
184 TAXONOMY_EXTRACTION, MIDPOINT_REROOT);
186 MainFrame[] aptxFrames = new MainFrame[trees.length];
187 for (int i = 0; i < trees.length; i++)
189 Phylogeny tree = trees[i];
190 aptxFrames[i] = createAptxFrame(tree, viewport, treeTitle);
193 if (Desktop.instance != null)
195 Desktop.instance.stopLoading();
203 * Refactored from Forester's UrlTreeReader, this can be more efficient
205 * @param databaseIndex
209 public static MainFrame[] createInstancesFromDb(
210 PhylogeniesWebserviceClient treeDbClient, String identifier,
211 AlignmentViewport viewport)
215 Phylogeny[] trees = null;
217 if ((identifier != null) && (identifier.trim().length() > 0))
219 if (Desktop.instance != null)
221 Desktop.instance.startLoading(identifier);
224 identifier = identifier.trim();
225 if (treeDbClient.isQueryInteger())
227 identifier = identifier.replaceAll("^\\D+", "");
232 id = Integer.parseInt(identifier);
233 } catch (final NumberFormatException e)
235 JvOptionPane.showInternalMessageDialog(Desktop.desktop,
236 MessageManager.formatMessage(
237 "error.database_id_has_letters", new String[]
239 MessageManager.getString("label.invalid_url"),
240 JvOptionPane.ERROR_MESSAGE);
241 return new MainFrame[0];
243 identifier = id + "";
245 boolean exception = false;
248 String url_str = treeDbClient.getUrl();
249 url_str = url_str.replaceFirst(
250 PhylogeniesWebserviceClient.QUERY_PLACEHOLDER, identifier);
251 url = new URL(url_str);
252 PhylogenyParser parser = null;
253 switch (treeDbClient.getReturnFormat())
255 case TOL_XML_RESPONSE:
256 parser = new TolParser();
259 parser = new NexusPhylogeniesParser();
260 ((NexusPhylogeniesParser) parser).setReplaceUnderscores(true);
263 parser = new NexusPhylogeniesParser();
264 ((NexusPhylogeniesParser) parser).setReplaceUnderscores(true);
265 ((NexusPhylogeniesParser) parser)
266 .setTaxonomyExtraction(NHXParser.TAXONOMY_EXTRACTION.NO);
269 parser = new NexusPhylogeniesParser();
270 ((NexusPhylogeniesParser) parser).setReplaceUnderscores(true);
271 ((NexusPhylogeniesParser) parser)
272 .setTaxonomyExtraction(NHXParser.TAXONOMY_EXTRACTION.NO);
275 parser = new NHXParser();
277 .setTaxonomyExtraction(NHXParser.TAXONOMY_EXTRACTION.NO);
278 ((NHXParser) parser).setReplaceUnderscores(true);
279 ((NHXParser) parser).setGuessRootedness(true);
281 case NH_EXTRACT_TAXONOMY:
282 parser = new NHXParser();
283 ((NHXParser) parser).setTaxonomyExtraction(
284 NHXParser.TAXONOMY_EXTRACTION.AGGRESSIVE);
285 ((NHXParser) parser).setReplaceUnderscores(false);
286 ((NHXParser) parser).setGuessRootedness(true);
289 parser = new NHXParser();
290 ((NHXParser) parser).setTaxonomyExtraction(
291 NHXParser.TAXONOMY_EXTRACTION.PFAM_STYLE_STRICT);
292 ((NHXParser) parser).setReplaceUnderscores(false);
293 ((NHXParser) parser).setGuessRootedness(true);
296 parser = new NHXParser();
298 .setTaxonomyExtraction(NHXParser.TAXONOMY_EXTRACTION.NO);
299 ((NHXParser) parser).setReplaceUnderscores(false);
300 ((NHXParser) parser).setGuessRootedness(true);
303 parser = PhyloXmlParser.createPhyloXmlParserXsdValidating();
306 throw new IllegalArgumentException(
307 "unknown format: " + treeDbClient.getReturnFormat());
310 // if (_main_frame.getMainPanel().getCurrentTreePanel() != null)
312 // _main_frame.getMainPanel().getCurrentTreePanel().setWaitCursor();
316 // _main_frame.getMainPanel().setWaitCursor();
318 trees = ForesterUtil.readPhylogeniesFromUrl(url, parser);
319 } catch (final MalformedURLException e)
322 JvOptionPane.showInternalMessageDialog(Desktop.desktop,
323 MessageManager.formatMessage(
324 "exception.unable_to_launch_url", new String[]
326 MessageManager.getString("label.invalid_url"),
327 JvOptionPane.ERROR_MESSAGE);
328 System.err.println(e.getLocalizedMessage());
329 } catch (final IOException e)
332 JvOptionPane.showInternalMessageDialog(Desktop.desktop,
333 "Could not read from " + url + "\n"
334 + e.getLocalizedMessage(),
335 "Failed to read tree from " + treeDbClient.getName() + " for "
337 JvOptionPane.ERROR_MESSAGE);
338 System.err.println(e.getLocalizedMessage());
339 } catch (final NumberFormatException e)
342 JvOptionPane.showInternalMessageDialog(Desktop.desktop,
343 "Could not read from " + url + "\n"
344 + e.getLocalizedMessage(),
345 "Failed to read tree from " + treeDbClient.getName() + " for "
347 JvOptionPane.ERROR_MESSAGE);
348 System.err.println(e.getLocalizedMessage());
349 } catch (final Exception e)
353 JvOptionPane.showInternalMessageDialog(Desktop.desktop,
354 e.getLocalizedMessage(), "Unexpected Exception",
355 JvOptionPane.ERROR_MESSAGE);
356 System.err.println(e.getLocalizedMessage());
358 if ((trees != null) && (trees.length > 0))
360 for (final Phylogeny phylogeny : trees)
362 if (!phylogeny.isEmpty())
364 if (treeDbClient.getName().equals(WebserviceUtil.TREE_FAM_NAME))
366 phylogeny.setRerootable(false);
367 phylogeny.setRooted(true);
369 if (treeDbClient.getProcessingInstructions() != null)
373 WebserviceUtil.processInstructions(treeDbClient, phylogeny);
374 } catch (final PhyloXmlDataFormatException e)
376 JvOptionPane.showInternalMessageDialog(Desktop.desktop,
377 "Error:\n" + e.getLocalizedMessage(), "Error",
378 JvOptionPane.ERROR_MESSAGE);
381 if (treeDbClient.getNodeField() != null)
385 PhylogenyMethods.transferNodeNameToField(phylogeny,
386 treeDbClient.getNodeField(), false);
387 } catch (final PhyloXmlDataFormatException e)
389 JvOptionPane.showInternalMessageDialog(Desktop.desktop,
390 "Error:\n" + e.getLocalizedMessage(), "Error",
391 JvOptionPane.ERROR_MESSAGE);
394 phylogeny.setIdentifier(
395 new Identifier(identifier, treeDbClient.getName()));
396 // _main_frame.getJMenuBar().remove(_main_frame.getHelpMenu());
397 // _main_frame.getMenuBarOfMainFrame()
398 // .add(_main_frame.getHelpMenu());
399 // _main_frame.getMainPanel().addPhylogenyInNewTab(phylogeny,
400 // _main_frame.getConfiguration(),
401 // new File(url.getFile()).getName(), url.toString());
403 MainFrame aptxApp = createAptxFrame(phylogeny, viewport,
405 String my_name_for_file = "";
406 if (!ForesterUtil.isEmpty(phylogeny.getName()))
408 my_name_for_file = new String(phylogeny.getName())
409 .replaceAll(" ", "_");
411 else if (phylogeny.getIdentifier() != null)
413 final StringBuffer sb = new StringBuffer();
415 .isEmpty(phylogeny.getIdentifier().getProvider()))
417 sb.append(phylogeny.getIdentifier().getProvider());
420 sb.append(phylogeny.getIdentifier().getValue());
421 my_name_for_file = new String(
422 sb.toString().replaceAll(" ", "_"));
424 aptxApp.getMainPanel().getCurrentTreePanel()
425 .setTreeFile(new File(my_name_for_file));
426 AptxUtil.lookAtSomeTreePropertiesForAptxControlSettings(
427 phylogeny, aptxApp.getMainPanel().getControlPanel(),
429 // _main_frame.getMainPanel().getControlPanel().showWhole();
431 aptxApp.activateSaveAllIfNeeded();
435 else if (!exception) // ..what?
437 JvOptionPane.showMessageDialog(null,
438 ForesterUtil.wordWrap(
439 "Failed to read in tree(s) from [" + url + "]", 80),
440 "Error", JvOptionPane.ERROR_MESSAGE);
442 if ((trees != null) && (trees.length > 0))
446 JvOptionPane.showMessageDialog(null,
447 ForesterUtil.wordWrap("Successfully read in "
448 + trees.length + " tree(s) from [" + url + "]",
450 "Success", JvOptionPane.INFORMATION_MESSAGE);
451 } catch (final Exception e)
453 // Not important if this fails, do nothing.
455 // _main_frame.getContentPane().repaint();
462 if (Desktop.instance != null)
464 Desktop.instance.stopLoading();
475 public static MainFrame createAptxFrame(
476 final Phylogeny aptxTree,
477 final AlignmentViewport jalviewAlignport, String treeTitle)
479 if (APTX_CONFIG == null || APTX_CONFIG.isCouldReadConfigFile() == false)
481 int keepGoing = JvOptionPane.showConfirmDialog(Desktop.desktop,
482 MessageManager.getString("label.aptx_config_not_found"),
483 MessageManager.formatMessage("label.couldnt_locate",
485 { "_aptx_jalview_configuration_file" }),
486 JvOptionPane.YES_NO_CANCEL_OPTION);
488 if (keepGoing == JvOptionPane.CANCEL_OPTION
489 || keepGoing == JvOptionPane.CLOSED_OPTION
490 || keepGoing == JvOptionPane.NO_OPTION)
496 MainFrame aptxApp = Archaeopteryx.createApplication(aptxTree,
497 APTX_CONFIG, treeTitle);
499 adaptAptxGui(aptxApp);
500 LoadedTreeSequenceAssociation bindAptxNodes = new LoadedTreeSequenceAssociation(
501 jalviewAlignport.getAlignment().getSequencesArray(), aptxTree);
502 bindAptxNodes.associateLeavesToSequences();
504 bindNodesToJalviewSequences(aptxApp, jalviewAlignport,
505 bindAptxNodes.getAlignmentWithNodes(),
506 bindAptxNodes.getNodesWithAlignment());
507 bindTreeViewFrameToJalview(aptxApp);
513 public static ExternalTreeViewerBindingI<?> bindNodesToJalviewSequences(
514 final MainFrame aptxApp,
515 final AlignmentViewport jalviewAlignViewport,
516 final Map<SequenceI, PhylogenyNode> alignMappedToNodes,
517 final Map<PhylogenyNode, SequenceI> nodesMappedToAlign)
519 JalviewBinding treeBinding = new JalviewBinding(aptxApp,
520 jalviewAlignViewport,
521 alignMappedToNodes, nodesMappedToAlign);
522 activeAptx.put(aptxApp, treeBinding);
527 public static MainFrame bindTreeViewFrameToJalview(
528 final MainFrame aptxApp)
532 aptxApp.setMinimumSize(new Dimension(width, height));
533 // aptxApp.setFont(Desktop.instance.getFont());
534 // aptxApp.getMainPanel().setFont(Desktop.instance.getFont());
535 String frameTitle = MessageManager.getString("label.aptx_title");
536 File treeFile = aptxApp.getMainPanel().getCurrentTreePanel()
538 if (treeFile != null)
540 frameTitle += MessageManager.formatMessage("label.aptx_title_append",
542 { treeFile.getAbsolutePath() });
544 Desktop.addInternalFrame(aptxApp, frameTitle, true, width, height, true,
551 * Hides certain redundant Archaeopteryx GUI elements such as the menu items
552 * for reading in trees and adds extra items related to Jalview such as the
558 private static void adaptAptxGui(MainFrame aptxFrame)
560 JMenuBar frameBar = aptxFrame.getJMenuBar();
562 for (int i = 0; i < frameBar.getMenuCount();i++) {
563 JMenu menu = frameBar.getMenu(i);
565 if (menu.getText().contains("File"))
567 // hide all "Read from ..." and "New" menu items and any Separators that
568 // come directly after them
569 Component previousMenuItem = null;
570 for (Component menuItem : menu.getMenuComponents()) {
571 if (previousMenuItem instanceof JMenuItem)
573 if (((JMenuItem) previousMenuItem).getText().startsWith("Read")
574 || ((JMenuItem) previousMenuItem).getText()
577 previousMenuItem.setVisible(false);
579 if (menuItem instanceof JSeparator)
581 menuItem.setVisible(false);
585 previousMenuItem = menuItem;
588 else if (menu.getText().contains("Inference"))
590 menu.setVisible(false);
592 else if (menu.getText().contains("View"))
595 menu.add(new JMenuItem("Sort alignment by tree"));
599 aptxFrame.validate();
602 public static Map<MainFrame, JalviewBinding> getAllAptxFrames()