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