JAL-1953 attempt at changing Aptx's font to Jalview's
[jalview.git] / src / jalview / ext / archaeopteryx / AptxInit.java
1 package jalview.ext.archaeopteryx;
2
3 import jalview.analysis.TreeBuilder;
4 import jalview.datamodel.SequenceI;
5 import jalview.ext.forester.UtilityMethods;
6 import jalview.ext.treeviewer.ExternalLoadedTreeAssociationI;
7 import jalview.ext.treeviewer.ExternalTreeBuilderI;
8 import jalview.ext.treeviewer.ExternalTreeFrame;
9 import jalview.ext.treeviewer.ExternalTreeI;
10 import jalview.ext.treeviewer.ExternalTreeNodeI;
11 import jalview.ext.treeviewer.ExternalTreeViewerBindingI;
12 import jalview.ext.treeviewer.LoadedTreeSequenceAssociation;
13 import jalview.gui.Desktop;
14 import jalview.gui.JvOptionPane;
15 import jalview.util.MessageManager;
16 import jalview.viewmodel.AlignmentViewport;
17
18 import java.awt.Dimension;
19 import java.io.File;
20 import java.io.FileNotFoundException;
21 import java.io.IOException;
22 import java.net.MalformedURLException;
23 import java.net.URL;
24 import java.util.HashMap;
25 import java.util.Map;
26
27 import org.forester.archaeopteryx.AptxUtil;
28 import org.forester.archaeopteryx.Configuration;
29 import org.forester.archaeopteryx.webservices.PhylogeniesWebserviceClient;
30 import org.forester.archaeopteryx.webservices.WebserviceUtil;
31 import org.forester.io.parsers.PhylogenyParser;
32 import org.forester.io.parsers.nexus.NexusPhylogeniesParser;
33 import org.forester.io.parsers.nhx.NHXParser;
34 import org.forester.io.parsers.phyloxml.PhyloXmlDataFormatException;
35 import org.forester.io.parsers.phyloxml.PhyloXmlParser;
36 import org.forester.io.parsers.tol.TolParser;
37 import org.forester.io.parsers.util.ParserUtils;
38 import org.forester.phylogeny.Phylogeny;
39 import org.forester.phylogeny.PhylogenyMethods;
40 import org.forester.phylogeny.data.Identifier;
41 import org.forester.util.ForesterUtil;
42
43 /**
44  * Static class for creating Archaeopteryx tree viewer instances from calculated
45  * trees and letting them be bound to Jalview.
46  * 
47  * @author kjvanderheide
48  *
49  */
50 public final class AptxInit
51 {
52   public final static Configuration APTX_CONFIG = new Configuration(
53           "_aptx_jalview_configuration_file",
54             false, false, false);
55   // static
56   // {
57   // APTX_CONFIG.setBaseFontFamilyName(
58   // Desktop.instance.getFont().getFamily().replaceAll(" ", "_"));
59   // APTX_CONFIG.setBaseFontSize(Desktop.instance.getFont().getSize());
60   // }
61
62   private final static boolean VALIDATE_PHYLOXML_XSD = APTX_CONFIG
63           .isValidatePhyloXmlAgainstSchema();
64
65   private final static boolean REPLACE_NHX_UNDERSCORES = APTX_CONFIG
66           .isReplaceUnderscoresInNhParsing();
67
68   private final static boolean INTERNAL_NUMBERS_AS_CONFIDENCE = APTX_CONFIG
69           .isInternalNumberAreConfidenceForNhParsing();
70
71   private final static boolean MIDPOINT_REROOT = APTX_CONFIG
72           .isMidpointReroot();
73
74   private final static NHXParser.TAXONOMY_EXTRACTION TAXONOMY_EXTRACTION = APTX_CONFIG
75           .getTaxonomyExtraction();
76
77   private static Map<ExternalTreeFrame, ExternalTreeViewerBindingI> activeAptx = new HashMap<>();
78
79
80
81
82   public static ExternalTreeFrame createInstanceFromCalculation(
83           final TreeBuilder calculatedTree)
84   {
85     ExternalTreeBuilderI aptxTreeBuilder = new AptxTreeBuilder(
86             calculatedTree);
87
88     ExternalTreeI aptxTree = aptxTreeBuilder.buildTree();
89
90     ExternalTreeFrame aptxApp = createAptxFrame(aptxTree,
91             calculatedTree.getAvport(), null);
92             
93     return aptxApp;
94   }
95
96
97   /**
98    * Refactored from Archaeopteryx.main
99    * 
100    * @param filePath
101    * @param viewport
102    * @return
103    * @throws IOException
104    * @throws FileNotFoundException
105    */
106   public static ExternalTreeFrame[] createInstancesFromFile(
107           String filePath,
108           AlignmentViewport viewport)
109           throws FileNotFoundException, IOException
110   {
111     File treeFile = new File(filePath);
112     ExternalTreeFrame[] aptxFrames = null;
113     if (UtilityMethods.canForesterReadFile(treeFile))
114     {
115
116     if (Desktop.instance != null)
117     {
118       Desktop.instance.startLoading(filePath);
119     }
120     boolean nhx_or_nexus = false;
121     final PhylogenyParser parser = ParserUtils
122             .createParserDependingOnFileType(
123             treeFile, VALIDATE_PHYLOXML_XSD);
124     if (parser instanceof NHXParser)
125     {
126       nhx_or_nexus = true;
127       final NHXParser nhx = (NHXParser) parser;
128       nhx.setReplaceUnderscores(REPLACE_NHX_UNDERSCORES);
129       nhx.setIgnoreQuotes(false);
130       nhx.setTaxonomyExtraction(TAXONOMY_EXTRACTION);
131     }
132     else if (parser instanceof NexusPhylogeniesParser)
133     {
134       nhx_or_nexus = true;
135       final NexusPhylogeniesParser nex = (NexusPhylogeniesParser) parser;
136       nex.setReplaceUnderscores(REPLACE_NHX_UNDERSCORES);
137       nex.setIgnoreQuotes(false);
138     }
139     else if (parser instanceof PhyloXmlParser)
140     {
141       if (VALIDATE_PHYLOXML_XSD == false)
142       {
143         JvOptionPane.showInternalMessageDialog(Desktop.desktop,
144                 MessageManager.getString("error.phyloxml_validation"),
145                 MessageManager.getString("label.file_open_error"),
146                                        JvOptionPane.WARNING_MESSAGE );
147       }
148     }
149     Phylogeny[] trees = PhylogenyMethods.readPhylogenies(parser,
150             treeFile);
151       aptxFrames = new ExternalTreeFrame[trees.length];
152
153
154     for (int i = 0; i < trees.length; i++)
155       {
156       Phylogeny aptxPhylogeny = trees[i];
157
158       if (nhx_or_nexus && INTERNAL_NUMBERS_AS_CONFIDENCE)
159       {
160         PhylogenyMethods.transferInternalNodeNamesToConfidence(aptxPhylogeny,
161                 "");
162       }
163       String treeTitle = treeFile.getName() + "[" + i + "]";
164       aptxPhylogeny.setName(treeTitle);
165         aptxFrames[i] = createAptxFrame(aptxPhylogeny, viewport, treeTitle);
166
167     }
168     if (Desktop.instance != null)
169     {
170       Desktop.instance.stopLoading();
171       }
172     }
173     return aptxFrames;
174     }
175
176
177   public static ExternalTreeFrame[] createInstancesFromUrl(URL treeUrl,
178           AlignmentViewport viewport)
179           throws FileNotFoundException, IOException, RuntimeException
180   {
181     
182     String treeTitle = treeUrl.getFile();
183     if (Desktop.instance != null)
184     {
185       Desktop.instance.startLoading(treeTitle);
186     }
187     Phylogeny[] trees = AptxUtil.readPhylogeniesFromUrl(treeUrl,
188             VALIDATE_PHYLOXML_XSD,
189              REPLACE_NHX_UNDERSCORES, INTERNAL_NUMBERS_AS_CONFIDENCE,
190             TAXONOMY_EXTRACTION, MIDPOINT_REROOT);
191
192     ExternalTreeFrame[] aptxFrames = new ExternalTreeFrame[trees.length];
193     for (int i = 0; i < trees.length; i++)
194     {
195       Phylogeny aptxTree = trees[i];
196       aptxFrames[i] = createAptxFrame(aptxTree, viewport, treeTitle);
197     }
198
199     if (Desktop.instance != null)
200     {
201       Desktop.instance.stopLoading();
202     }
203
204     return aptxFrames;
205
206   }
207
208   /**
209    * Refactored from Forester's UrlTreeReader, this can be more efficient
210    * 
211    * @param databaseIndex
212    * @param viewport
213    * @return
214    */
215   public static ExternalTreeFrame[] createInstancesFromDb(
216           PhylogeniesWebserviceClient treeDbClient, String identifier,
217           AlignmentViewport viewport)
218   {
219
220     URL url = null;
221     Phylogeny[] trees = null;
222     ExternalTreeFrame[] aptxFrames = null;
223
224     if ((identifier != null) && (identifier.trim().length() > 0))
225     {
226       if (Desktop.instance != null)
227       {
228         Desktop.instance.startLoading(identifier);
229       }
230
231       identifier = identifier.trim();
232       if (treeDbClient.isQueryInteger())
233       {
234         identifier = identifier.replaceAll("^\\D+", "");
235
236         int id;
237         try
238         {
239           id = Integer.parseInt(identifier);
240         } catch (final NumberFormatException e)
241         {
242           JvOptionPane.showInternalMessageDialog(Desktop.desktop,
243                   MessageManager.formatMessage(
244                           "error.database_id_has_letters", new String[]
245                           { identifier }),
246                   MessageManager.getString("label.invalid_url"),
247                   JvOptionPane.ERROR_MESSAGE);
248           return new ExternalTreeFrame[0];
249         }
250         identifier = id + "";
251       }
252       boolean exception = false;
253       try
254       {
255         String url_str = treeDbClient.getUrl();
256         url_str = url_str.replaceFirst(
257                 PhylogeniesWebserviceClient.QUERY_PLACEHOLDER, identifier);
258         url = new URL(url_str);
259         PhylogenyParser parser = null;
260         switch (treeDbClient.getReturnFormat())
261         {
262         case TOL_XML_RESPONSE:
263           parser = new TolParser();
264           break;
265         case NEXUS:
266           parser = new NexusPhylogeniesParser();
267           ((NexusPhylogeniesParser) parser).setReplaceUnderscores(true);
268           break;
269         case TREEBASE_TREE:
270           parser = new NexusPhylogeniesParser();
271           ((NexusPhylogeniesParser) parser).setReplaceUnderscores(true);
272           ((NexusPhylogeniesParser) parser)
273                   .setTaxonomyExtraction(NHXParser.TAXONOMY_EXTRACTION.NO);
274           break;
275         case TREEBASE_STUDY:
276           parser = new NexusPhylogeniesParser();
277           ((NexusPhylogeniesParser) parser).setReplaceUnderscores(true);
278           ((NexusPhylogeniesParser) parser)
279                   .setTaxonomyExtraction(NHXParser.TAXONOMY_EXTRACTION.NO);
280           break;
281         case NH:
282           parser = new NHXParser();
283           ((NHXParser) parser)
284                   .setTaxonomyExtraction(NHXParser.TAXONOMY_EXTRACTION.NO);
285           ((NHXParser) parser).setReplaceUnderscores(true);
286           ((NHXParser) parser).setGuessRootedness(true);
287           break;
288         case NH_EXTRACT_TAXONOMY:
289           parser = new NHXParser();
290           ((NHXParser) parser).setTaxonomyExtraction(
291                   NHXParser.TAXONOMY_EXTRACTION.AGGRESSIVE);
292           ((NHXParser) parser).setReplaceUnderscores(false);
293           ((NHXParser) parser).setGuessRootedness(true);
294           break;
295         case PFAM:
296           parser = new NHXParser();
297           ((NHXParser) parser).setTaxonomyExtraction(
298                   NHXParser.TAXONOMY_EXTRACTION.PFAM_STYLE_STRICT);
299           ((NHXParser) parser).setReplaceUnderscores(false);
300           ((NHXParser) parser).setGuessRootedness(true);
301           break;
302         case NHX:
303           parser = new NHXParser();
304           ((NHXParser) parser)
305                   .setTaxonomyExtraction(NHXParser.TAXONOMY_EXTRACTION.NO);
306           ((NHXParser) parser).setReplaceUnderscores(false);
307           ((NHXParser) parser).setGuessRootedness(true);
308           break;
309         case PHYLOXML:
310           parser = PhyloXmlParser.createPhyloXmlParserXsdValidating();
311           break;
312         default:
313           throw new IllegalArgumentException(
314                   "unknown format: " + treeDbClient.getReturnFormat());
315         }
316         //
317         // if (_main_frame.getMainPanel().getCurrentTreePanel() != null)
318         // {
319         // _main_frame.getMainPanel().getCurrentTreePanel().setWaitCursor();
320         // }
321         // else
322         // {
323         // _main_frame.getMainPanel().setWaitCursor();
324         // }
325         trees = ForesterUtil.readPhylogeniesFromUrl(url, parser);
326         aptxFrames = new ExternalTreeFrame[trees.length];
327       } catch (final MalformedURLException e)
328       {
329         exception = true;
330         JvOptionPane.showInternalMessageDialog(Desktop.desktop,
331                 MessageManager.formatMessage(
332                         "exception.unable_to_launch_url", new String[]
333                         { url.toString() }),
334                 MessageManager.getString("label.invalid_url"),
335                 JvOptionPane.ERROR_MESSAGE);
336         System.err.println(e.getLocalizedMessage());
337       } catch (final IOException e)
338       {
339         exception = true;
340         JvOptionPane.showInternalMessageDialog(Desktop.desktop,
341                 "Could not read from " + url + "\n"
342                         + e.getLocalizedMessage(),
343                 "Failed to read tree from " + treeDbClient.getName() + " for "
344                         + identifier,
345                 JvOptionPane.ERROR_MESSAGE);
346         System.err.println(e.getLocalizedMessage());
347       } catch (final NumberFormatException e)
348       {
349         exception = true;
350         JvOptionPane.showInternalMessageDialog(Desktop.desktop,
351                 "Could not read from " + url + "\n"
352                         + e.getLocalizedMessage(),
353                 "Failed to read tree from " + treeDbClient.getName() + " for "
354                         + identifier,
355                 JvOptionPane.ERROR_MESSAGE);
356         System.err.println(e.getLocalizedMessage());
357       } catch (final Exception e)
358       {
359         exception = true;
360         e.printStackTrace();
361         JvOptionPane.showInternalMessageDialog(Desktop.desktop,
362                 e.getLocalizedMessage(), "Unexpected Exception",
363                 JvOptionPane.ERROR_MESSAGE);
364         System.err.println(e.getLocalizedMessage());
365       }
366       if ((trees != null) && (trees.length > 0))
367       {
368         int i = 0;
369         for (final Phylogeny aptxTree : trees)
370         {
371           if (!aptxTree.isEmpty())
372           {
373             if (treeDbClient.getName().equals(WebserviceUtil.TREE_FAM_NAME))
374             {
375               aptxTree.setRerootable(false);
376               aptxTree.setRooted(true);
377             }
378             if (treeDbClient.getProcessingInstructions() != null)
379             {
380               try
381               {
382                 WebserviceUtil.processInstructions(treeDbClient,
383                         aptxTree);
384               } catch (final PhyloXmlDataFormatException e)
385               {
386                 JvOptionPane.showInternalMessageDialog(Desktop.desktop,
387                         "Error:\n" + e.getLocalizedMessage(), "Error",
388                         JvOptionPane.ERROR_MESSAGE);
389               }
390             }
391             if (treeDbClient.getNodeField() != null)
392             {
393               try
394               {
395                 PhylogenyMethods.transferNodeNameToField(aptxTree,
396                         treeDbClient.getNodeField(), false);
397               } catch (final PhyloXmlDataFormatException e)
398               {
399                 JvOptionPane.showInternalMessageDialog(Desktop.desktop,
400                         "Error:\n" + e.getLocalizedMessage(), "Error",
401                         JvOptionPane.ERROR_MESSAGE);
402               }
403             }
404             aptxTree.setIdentifier(
405                     new Identifier(identifier, treeDbClient.getName()));
406             // _main_frame.getJMenuBar().remove(_main_frame.getHelpMenu());
407             // _main_frame.getMenuBarOfExternalTreeFrameI()
408             // .add(_main_frame.getHelpMenu());
409             // _main_frame.getMainPanel().addExternalTreeIInNewTab(ExternalTreeI,
410             // _main_frame.getConfiguration(),
411             // new File(url.getFile()).getName(), url.toString());
412
413
414             ExternalTreeFrame aptxApp = createAptxFrame(aptxTree,
415                     viewport,
416                     url.getFile());
417             String my_name_for_file = "";
418             if (!ForesterUtil.isEmpty(aptxTree.getName()))
419             {
420               my_name_for_file = new String(aptxTree.getName())
421                       .replaceAll(" ", "_");
422             }
423             else if (aptxTree.getIdentifier() != null)
424             {
425               final StringBuffer sb = new StringBuffer();
426               if (!ForesterUtil
427                       .isEmpty(aptxTree.getIdentifier().getProvider()))
428               {
429                 sb.append(aptxTree.getIdentifier().getProvider());
430                 sb.append("_");
431               }
432               sb.append(aptxTree.getIdentifier().getValue());
433               my_name_for_file = new String(
434                       sb.toString().replaceAll(" ", "_"));
435             }
436             aptxApp.getTreePanel()
437                     .setTreeFile(new File(my_name_for_file));
438             // AptxUtil.lookAtSomeTreePropertiesForAptxControlSettings(
439             // aptxTree, aptxApp.getMainPanel().getControlPanel(),
440             // APTX_CONFIG);
441             aptxApp.getTreeControls().displayEntireTree();
442
443             aptxApp.checkMultipleTrees();
444             aptxFrames[i++] = aptxApp;
445           }
446         }
447       }
448       else if (!exception) // ..what?
449       {
450         JvOptionPane.showMessageDialog(null,
451                 ForesterUtil.wordWrap(
452                         "Failed to read in tree(s) from [" + url + "]", 80),
453                 "Error", JvOptionPane.ERROR_MESSAGE);
454       }
455       if ((trees != null) && (trees.length > 0))
456       {
457         try
458         {
459           JvOptionPane.showMessageDialog(null,
460                   ForesterUtil.wordWrap("Successfully read in "
461                           + trees.length + " tree(s) from [" + url + "]",
462                           80),
463                   "Success", JvOptionPane.INFORMATION_MESSAGE);
464         } catch (final Exception e)
465         {
466           // Not important if this fails, do nothing.
467         }
468         // _main_frame.getContentPane().repaint();
469       }
470     }
471
472     System.gc();
473
474
475     if (Desktop.instance != null)
476     {
477       Desktop.instance.stopLoading();
478     }
479     return aptxFrames;
480
481
482   }
483
484
485
486   public static ExternalTreeFrame createAptxFrame(ExternalTreeI aptxTree,
487           AlignmentViewport jalviewAlignport, String treeTitle)
488   {
489     validateConfig(APTX_CONFIG);
490     ExternalTreeFrame aptxApp = aptxTree
491             .createTreeViewerFromTree(treeTitle);
492     ExternalTreeI jalviewTree = aptxApp.getTree();
493     ExternalLoadedTreeAssociationI bindAptxNodes = new LoadedTreeSequenceAssociation(
494             jalviewAlignport.getAlignment().getSequencesArray(),
495             jalviewTree);
496     bindAptxNodes.associateLeavesToSequences();
497
498     bindNodesToJalviewSequences(aptxApp, jalviewAlignport,
499             bindAptxNodes.getAlignmentWithNodes(),
500             bindAptxNodes.getNodesWithAlignment());
501     bindTreeViewFrameToJalview(aptxApp);
502
503     // adaptAptxGui(aptxApp); //moved to AptxFrame
504     return aptxApp;
505   }
506
507
508   protected static ExternalTreeFrame createAptxFrame(
509           final Phylogeny aptxTree,
510           final AlignmentViewport jalviewAlignport, String treeTitle)
511   {
512     validateConfig(APTX_CONFIG);
513     ExternalTreeFrame aptxApp = new AptxFrame(aptxTree, APTX_CONFIG,
514             treeTitle);
515     ExternalTreeI jalviewTree = aptxApp.getTree();
516     ExternalLoadedTreeAssociationI bindAptxNodes = new LoadedTreeSequenceAssociation(
517             jalviewAlignport.getAlignment().getSequencesArray(),
518             jalviewTree);
519     bindAptxNodes.associateLeavesToSequences();
520
521     bindNodesToJalviewSequences(aptxApp, jalviewAlignport,
522             bindAptxNodes.getAlignmentWithNodes(),
523             bindAptxNodes.getNodesWithAlignment());
524     bindTreeViewFrameToJalview(aptxApp);
525
526     // adaptAptxGui(aptxApp); //moved to AptxFrame
527     return aptxApp;
528   }
529
530
531   protected static ExternalTreeViewerBindingI bindNodesToJalviewSequences(
532           final ExternalTreeFrame aptxApp,
533           final AlignmentViewport jalviewAlignViewport,
534           final Map<SequenceI, ExternalTreeNodeI> alignMappedToNodes,
535           final Map<ExternalTreeNodeI, SequenceI> nodesMappedToAlign)
536   {
537     ExternalTreeViewerBindingI treeBinding = new JalviewBinding(aptxApp,
538             jalviewAlignViewport,
539             alignMappedToNodes, nodesMappedToAlign);
540     activeAptx.put(aptxApp, treeBinding);
541     return treeBinding;
542   }
543
544
545   protected static ExternalTreeFrame bindTreeViewFrameToJalview(
546           final ExternalTreeFrame aptxApp)
547   {
548     int width = 400;
549     int height = 550;
550     aptxApp.setMinimumSize(new Dimension(width, height));
551     // aptxApp.setFont(Desktop.instance.getFont());
552     // aptxApp.getMainPanel().setFont(Desktop.instance.getFont());
553     String frameTitle = MessageManager.getString("label.aptx_title");
554     File treeFile = aptxApp.getTreePanel().getTreeFile();
555     if (treeFile != null)
556     {
557       frameTitle += MessageManager.formatMessage("label.aptx_title_append",
558               new String[]
559               { treeFile.getAbsolutePath() });
560     }
561     aptxApp.addFrameToJalview(frameTitle, true, width, height, true,
562             true);
563     return aptxApp;
564
565   }
566
567   private static boolean validateConfig(Configuration aptxConfig)
568   {
569     if (aptxConfig == null || aptxConfig.isCouldReadConfigFile() == false)
570     {
571       int keepGoing = JvOptionPane.showConfirmDialog(Desktop.desktop,
572               MessageManager.getString("label.aptx_config_not_found"),
573               MessageManager.formatMessage("label.couldnt_locate",
574                       new String[]
575                       { "_aptx_jalview_configuration_file" }),
576               JvOptionPane.YES_NO_CANCEL_OPTION);
577
578       if (keepGoing == JvOptionPane.CANCEL_OPTION
579               || keepGoing == JvOptionPane.CLOSED_OPTION
580               || keepGoing == JvOptionPane.NO_OPTION)
581       {
582         return false;
583       }
584
585     }
586     return true;
587   }
588
589
590
591   public static Map<ExternalTreeFrame, ExternalTreeViewerBindingI> getAllAptxFrames()
592   {
593     return activeAptx;
594   }
595
596
597 }