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
57 private static Map<MainFrame, JalviewBinding> activeAptx = new HashMap<>();
61 public static MainFrame createInstanceFromCalculation(
62 final TreeBuilder calculatedTree)
64 ExternalTreeBuilderI<Phylogeny, PhylogenyNode> aptxTreeBuilder = new AptxTreeBuilder(
67 Phylogeny aptxTree = aptxTreeBuilder.buildTree();
69 MainFrame aptxApp = createAptxFrame(aptxTree,
70 calculatedTree.getAvport(), null);
76 * Refactored from Archaeopteryx.main
82 * @throws FileNotFoundException
84 public static MainFrame[] createInstancesFromFile(String filePath,
85 AlignmentViewport viewport)
86 throws FileNotFoundException, IOException
88 Configuration APTX_CONFIG = new Configuration(Cache.getDefault(
90 Desktop.instance.getClass()
91 .getResource("/_aptx_jalview_configuration_file.txt")
94 File treeFile = new File(filePath);
95 final String err = ForesterUtil.isReadableFile(treeFile);
96 if (!ForesterUtil.isEmpty(err))
98 JvOptionPane.showMessageDialog(Desktop.desktop, err,
99 MessageManager.getString("label.problem_reading_tree_file"),
100 JvOptionPane.WARNING_MESSAGE);
103 if (Desktop.instance != null)
105 Desktop.instance.startLoading(filePath);
107 boolean nhx_or_nexus = false;
108 final PhylogenyParser parser = ParserUtils.createParserDependingOnFileType(
110 APTX_CONFIG.isValidatePhyloXmlAgainstSchema());
111 if (parser instanceof NHXParser)
114 final NHXParser nhx = (NHXParser) parser;
115 nhx.setReplaceUnderscores(
116 APTX_CONFIG.isReplaceUnderscoresInNhParsing());
117 nhx.setIgnoreQuotes(false);
118 nhx.setTaxonomyExtraction(APTX_CONFIG.getTaxonomyExtraction());
120 else if (parser instanceof NexusPhylogeniesParser)
123 final NexusPhylogeniesParser nex = (NexusPhylogeniesParser) parser;
124 nex.setReplaceUnderscores(
125 APTX_CONFIG.isReplaceUnderscoresInNhParsing());
126 nex.setIgnoreQuotes(false);
128 else if (parser instanceof PhyloXmlParser)
130 if (APTX_CONFIG.isValidatePhyloXmlAgainstSchema() == false)
132 JvOptionPane.showInternalMessageDialog(Desktop.desktop,
133 MessageManager.getString("error.phyloxml_validation"),
134 MessageManager.getString("label.file_open_error"),
135 JvOptionPane.WARNING_MESSAGE );
138 Phylogeny[] trees = PhylogenyMethods.readPhylogenies(parser, treeFile);
139 MainFrame[] aptxFrames = new MainFrame[trees.length];
142 for (int i = 0; i < trees.length; i++)
144 Phylogeny tree = trees[i];
147 && APTX_CONFIG.isInternalNumberAreConfidenceForNhParsing())
149 PhylogenyMethods.transferInternalNodeNamesToConfidence(tree, "");
151 String treeTitle = treeFile.getName() + "[" + i + "]";
152 tree.setName(treeTitle);
153 aptxFrames[i] = createAptxFrame(tree, viewport, treeTitle);
156 if (Desktop.instance != null)
158 Desktop.instance.stopLoading();
164 public static MainFrame[] createInstancesFromUrl(URL treeUrl,
165 AlignmentViewport viewport)
166 throws FileNotFoundException, IOException, RuntimeException
168 Configuration APTX_CONFIG = new Configuration(Cache.getDefault(
170 Desktop.instance.getClass()
171 .getResource("/_aptx_jalview_configuration_file.txt")
173 false, false, false);
174 String treeTitle = treeUrl.getFile();
175 if (Desktop.instance != null)
177 Desktop.instance.startLoading(treeTitle);
179 Phylogeny[] trees = AptxUtil.readPhylogeniesFromUrl(treeUrl,
180 APTX_CONFIG.isValidatePhyloXmlAgainstSchema(),
181 APTX_CONFIG.isReplaceUnderscoresInNhParsing(),
182 APTX_CONFIG.isInternalNumberAreConfidenceForNhParsing(),
183 APTX_CONFIG.getTaxonomyExtraction(),
184 APTX_CONFIG.isMidpointReroot());
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)
213 Configuration APTX_CONFIG = new Configuration(Cache.getDefault(
215 Desktop.instance.getClass()
216 .getResource("/_aptx_jalview_configuration_file.txt")
218 false, false, false);
220 Phylogeny[] trees = null;
222 if ((identifier != null) && (identifier.trim().length() > 0))
224 if (Desktop.instance != null)
226 Desktop.instance.startLoading(identifier);
229 identifier = identifier.trim();
230 if (treeDbClient.isQueryInteger())
232 identifier = identifier.replaceAll("^\\D+", "");
237 id = Integer.parseInt(identifier);
238 } catch (final NumberFormatException e)
240 JvOptionPane.showInternalMessageDialog(Desktop.desktop,
241 MessageManager.formatMessage(
242 "error.database_id_has_letters", new String[]
244 MessageManager.getString("label.invalid_url"),
245 JvOptionPane.ERROR_MESSAGE);
246 return new MainFrame[0];
248 identifier = id + "";
250 boolean exception = false;
253 String url_str = treeDbClient.getUrl();
254 url_str = url_str.replaceFirst(
255 PhylogeniesWebserviceClient.QUERY_PLACEHOLDER, identifier);
256 url = new URL(url_str);
257 PhylogenyParser parser = null;
258 switch (treeDbClient.getReturnFormat())
260 case TOL_XML_RESPONSE:
261 parser = new TolParser();
264 parser = new NexusPhylogeniesParser();
265 ((NexusPhylogeniesParser) parser).setReplaceUnderscores(true);
268 parser = new NexusPhylogeniesParser();
269 ((NexusPhylogeniesParser) parser).setReplaceUnderscores(true);
270 ((NexusPhylogeniesParser) parser)
271 .setTaxonomyExtraction(NHXParser.TAXONOMY_EXTRACTION.NO);
274 parser = new NexusPhylogeniesParser();
275 ((NexusPhylogeniesParser) parser).setReplaceUnderscores(true);
276 ((NexusPhylogeniesParser) parser)
277 .setTaxonomyExtraction(NHXParser.TAXONOMY_EXTRACTION.NO);
280 parser = new NHXParser();
282 .setTaxonomyExtraction(NHXParser.TAXONOMY_EXTRACTION.NO);
283 ((NHXParser) parser).setReplaceUnderscores(true);
284 ((NHXParser) parser).setGuessRootedness(true);
286 case NH_EXTRACT_TAXONOMY:
287 parser = new NHXParser();
288 ((NHXParser) parser).setTaxonomyExtraction(
289 NHXParser.TAXONOMY_EXTRACTION.AGGRESSIVE);
290 ((NHXParser) parser).setReplaceUnderscores(false);
291 ((NHXParser) parser).setGuessRootedness(true);
294 parser = new NHXParser();
295 ((NHXParser) parser).setTaxonomyExtraction(
296 NHXParser.TAXONOMY_EXTRACTION.PFAM_STYLE_STRICT);
297 ((NHXParser) parser).setReplaceUnderscores(false);
298 ((NHXParser) parser).setGuessRootedness(true);
301 parser = new NHXParser();
303 .setTaxonomyExtraction(NHXParser.TAXONOMY_EXTRACTION.NO);
304 ((NHXParser) parser).setReplaceUnderscores(false);
305 ((NHXParser) parser).setGuessRootedness(true);
308 parser = PhyloXmlParser.createPhyloXmlParserXsdValidating();
311 throw new IllegalArgumentException(
312 "unknown format: " + treeDbClient.getReturnFormat());
315 // if (_main_frame.getMainPanel().getCurrentTreePanel() != null)
317 // _main_frame.getMainPanel().getCurrentTreePanel().setWaitCursor();
321 // _main_frame.getMainPanel().setWaitCursor();
323 trees = ForesterUtil.readPhylogeniesFromUrl(url, parser);
324 } catch (final MalformedURLException e)
327 JvOptionPane.showInternalMessageDialog(Desktop.desktop,
328 MessageManager.formatMessage(
329 "exception.unable_to_launch_url", new String[]
331 MessageManager.getString("label.invalid_url"),
332 JvOptionPane.ERROR_MESSAGE);
333 System.err.println(e.getLocalizedMessage());
334 } catch (final IOException e)
337 JvOptionPane.showInternalMessageDialog(Desktop.desktop,
338 "Could not read from " + url + "\n"
339 + e.getLocalizedMessage(),
340 "Failed to read tree from " + treeDbClient.getName() + " for "
342 JvOptionPane.ERROR_MESSAGE);
343 System.err.println(e.getLocalizedMessage());
344 } catch (final NumberFormatException e)
347 JvOptionPane.showInternalMessageDialog(Desktop.desktop,
348 "Could not read from " + url + "\n"
349 + e.getLocalizedMessage(),
350 "Failed to read tree from " + treeDbClient.getName() + " for "
352 JvOptionPane.ERROR_MESSAGE);
353 System.err.println(e.getLocalizedMessage());
354 } catch (final Exception e)
358 JvOptionPane.showInternalMessageDialog(Desktop.desktop,
359 e.getLocalizedMessage(), "Unexpected Exception",
360 JvOptionPane.ERROR_MESSAGE);
361 System.err.println(e.getLocalizedMessage());
363 if ((trees != null) && (trees.length > 0))
365 for (final Phylogeny phylogeny : trees)
367 if (!phylogeny.isEmpty())
369 if (treeDbClient.getName().equals(WebserviceUtil.TREE_FAM_NAME))
371 phylogeny.setRerootable(false);
372 phylogeny.setRooted(true);
374 if (treeDbClient.getProcessingInstructions() != null)
378 WebserviceUtil.processInstructions(treeDbClient, phylogeny);
379 } catch (final PhyloXmlDataFormatException e)
381 JvOptionPane.showInternalMessageDialog(Desktop.desktop,
382 "Error:\n" + e.getLocalizedMessage(), "Error",
383 JvOptionPane.ERROR_MESSAGE);
386 if (treeDbClient.getNodeField() != null)
390 PhylogenyMethods.transferNodeNameToField(phylogeny,
391 treeDbClient.getNodeField(), false);
392 } catch (final PhyloXmlDataFormatException e)
394 JvOptionPane.showInternalMessageDialog(Desktop.desktop,
395 "Error:\n" + e.getLocalizedMessage(), "Error",
396 JvOptionPane.ERROR_MESSAGE);
399 phylogeny.setIdentifier(
400 new Identifier(identifier, treeDbClient.getName()));
401 // _main_frame.getJMenuBar().remove(_main_frame.getHelpMenu());
402 // _main_frame.getMenuBarOfMainFrame()
403 // .add(_main_frame.getHelpMenu());
404 // _main_frame.getMainPanel().addPhylogenyInNewTab(phylogeny,
405 // _main_frame.getConfiguration(),
406 // new File(url.getFile()).getName(), url.toString());
408 MainFrame aptxApp = createAptxFrame(phylogeny, viewport,
410 String my_name_for_file = "";
411 if (!ForesterUtil.isEmpty(phylogeny.getName()))
413 my_name_for_file = new String(phylogeny.getName())
414 .replaceAll(" ", "_");
416 else if (phylogeny.getIdentifier() != null)
418 final StringBuffer sb = new StringBuffer();
420 .isEmpty(phylogeny.getIdentifier().getProvider()))
422 sb.append(phylogeny.getIdentifier().getProvider());
425 sb.append(phylogeny.getIdentifier().getValue());
426 my_name_for_file = new String(
427 sb.toString().replaceAll(" ", "_"));
429 aptxApp.getMainPanel().getCurrentTreePanel()
430 .setTreeFile(new File(my_name_for_file));
431 AptxUtil.lookAtSomeTreePropertiesForAptxControlSettings(
432 phylogeny, aptxApp.getMainPanel().getControlPanel(),
434 // _main_frame.getMainPanel().getControlPanel().showWhole();
436 aptxApp.activateSaveAllIfNeeded();
440 else if (!exception) // ..what?
442 JvOptionPane.showMessageDialog(null,
443 ForesterUtil.wordWrap(
444 "Failed to read in tree(s) from [" + url + "]", 80),
445 "Error", JvOptionPane.ERROR_MESSAGE);
447 if ((trees != null) && (trees.length > 0))
451 JvOptionPane.showMessageDialog(null,
452 ForesterUtil.wordWrap("Successfully read in "
453 + trees.length + " tree(s) from [" + url + "]",
455 "Success", JvOptionPane.INFORMATION_MESSAGE);
456 } catch (final Exception e)
458 // Not important if this fails, do nothing.
460 // _main_frame.getContentPane().repaint();
467 if (Desktop.instance != null)
469 Desktop.instance.stopLoading();
480 public static MainFrame createAptxFrame(
481 final Phylogeny aptxTree,
482 final AlignmentViewport jalviewAlignport, String treeTitle)
484 Configuration APTX_CONFIG = new Configuration(Cache.getDefault(
486 Desktop.instance.getClass()
487 .getResource("/_aptx_jalview_configuration_file.txt")
489 false, false, false);
490 if (APTX_CONFIG == null || APTX_CONFIG.isCouldReadConfigFile() == false)
492 int keepGoing = JvOptionPane.showConfirmDialog(Desktop.desktop,
493 MessageManager.getString("label.aptx_config_not_found"),
494 MessageManager.formatMessage("label.couldnt_locate",
496 { "_aptx_jalview_configuration_file" }),
497 JvOptionPane.YES_NO_CANCEL_OPTION);
499 if (keepGoing == JvOptionPane.CANCEL_OPTION
500 || keepGoing == JvOptionPane.CLOSED_OPTION
501 || keepGoing == JvOptionPane.NO_OPTION)
507 MainFrame aptxApp = Archaeopteryx.createApplication(aptxTree,
508 APTX_CONFIG, treeTitle);
511 LoadedTreeSequenceAssociation bindAptxNodes = new LoadedTreeSequenceAssociation(
512 jalviewAlignport.getAlignment().getSequencesArray(), aptxTree);
513 bindAptxNodes.associateLeavesToSequences();
515 bindNodesToJalviewSequences(aptxApp, jalviewAlignport,
516 bindAptxNodes.getAlignmentWithNodes(),
517 bindAptxNodes.getNodesWithAlignment());
518 bindTreeViewFrameToJalview(aptxApp);
520 adaptAptxGui(aptxApp);
525 public static ExternalTreeViewerBindingI<?> bindNodesToJalviewSequences(
526 final MainFrame aptxApp,
527 final AlignmentViewport jalviewAlignViewport,
528 final Map<SequenceI, PhylogenyNode> alignMappedToNodes,
529 final Map<PhylogenyNode, SequenceI> nodesMappedToAlign)
531 JalviewBinding treeBinding = new JalviewBinding(aptxApp,
532 jalviewAlignViewport,
533 alignMappedToNodes, nodesMappedToAlign);
534 activeAptx.put(aptxApp, treeBinding);
539 public static MainFrame bindTreeViewFrameToJalview(
540 final MainFrame aptxApp)
544 aptxApp.setMinimumSize(new Dimension(width, height));
545 // aptxApp.setFont(Desktop.instance.getFont());
546 // aptxApp.getMainPanel().setFont(Desktop.instance.getFont());
547 String frameTitle = MessageManager.getString("label.aptx_title");
548 File treeFile = aptxApp.getMainPanel().getCurrentTreePanel()
550 if (treeFile != null)
552 frameTitle += MessageManager.formatMessage("label.aptx_title_append",
554 { treeFile.getAbsolutePath() });
556 Desktop.addInternalFrame(aptxApp, frameTitle, true, width, height, true,
563 * Hides certain redundant Archaeopteryx GUI elements such as the menu items
564 * for reading in trees and adds extra items related to Jalview such as the
570 private static void adaptAptxGui(MainFrame aptxFrame)
572 JMenuBar frameBar = aptxFrame.getJMenuBar();
574 for (int i = 0; i < frameBar.getMenuCount();i++) {
575 JMenu menu = frameBar.getMenu(i);
577 if (menu.getText().contains("File"))
579 // hide all "Read from ..." and "New" menu items and any Separators that
580 // come directly after them
581 Component previousMenuItem = null;
582 for (Component menuItem : menu.getMenuComponents()) {
583 if (previousMenuItem instanceof JMenuItem)
585 if (((JMenuItem) previousMenuItem).getText().startsWith("Read")
586 || ((JMenuItem) previousMenuItem).getText()
589 previousMenuItem.setVisible(false);
591 if (menuItem instanceof JSeparator)
593 menuItem.setVisible(false);
597 previousMenuItem = menuItem;
600 else if (menu.getText().contains("Inference"))
602 menu.setVisible(false);
604 else if (menu.getText().contains("View"))
607 JMenuItem sortByTree = new JMenuItem("Sort alignment by tree");
608 JMenuItem refreshJalview = new JMenuItem(
609 "Filter alignment to show only currently visible sequences");
611 refreshJalview.setFont(menu.getFont());
613 menu.add(sortByTree);
614 menu.add(refreshJalview);
616 sortByTree.setFont(menu.getFont());
617 sortByTree.setVisible(false); // don't show unless it's actually
620 refreshJalview.addActionListener(activeAptx.get(aptxFrame));
626 aptxFrame.validate();
629 public static Map<MainFrame, JalviewBinding> getAllAptxFrames()