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