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