Can specify PDB chain to map sequence to - only used by applet so far
[jalview.git] / src / jalview / bin / JalviewLite.java
1 /*
2  * Jalview - A Sequence Alignment Editor and Viewer
3  * Copyright (C) 2007 AM Waterhouse, J Procter, G Barton, M Clamp, S Searle
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License
7  * as published by the Free Software Foundation; either version 2
8  * of the License, or (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
18  */
19 package jalview.bin;
20
21 import java.applet.*;
22
23 import java.awt.*;
24 import java.awt.event.*;
25 import java.util.*;
26
27 import jalview.appletgui.*;
28 import jalview.datamodel.*;
29 import jalview.io.*;
30
31 /**
32  * Jalview Applet. Runs in Java 1.18 runtime
33  *
34  * @author $author$
35  * @version $Revision$
36  */
37 public class JalviewLite
38     extends Applet
39 {
40
41
42
43   ///////////////////////////////////////////
44   //The following public methods maybe called
45   //externally, eg via javascript in HTML page
46
47   public String getSelectedSequences()
48   {
49     StringBuffer result = new StringBuffer("");
50
51     if (initialAlignFrame.viewport.getSelectionGroup() != null)
52     {
53       SequenceI[] seqs = initialAlignFrame.viewport.getSelectionGroup().
54           getSequencesInOrder(
55               initialAlignFrame.viewport.getAlignment());
56
57       for (int i = 0; i < seqs.length; i++)
58       {
59         result.append(seqs[i].getName() + "¬");
60       }
61     }
62
63     return result.toString();
64   }
65
66   public String getAlignment(String format)
67   {
68     return getAlignment(format, "true");
69   }
70
71   public String getAlignment(String format, String suffix)
72   {
73     try
74     {
75       boolean seqlimits = suffix.equalsIgnoreCase("true");
76
77       String reply = new AppletFormatAdapter().formatSequences(format,
78           currentAlignFrame.viewport.getAlignment(), seqlimits);
79       return reply;
80     }
81     catch (Exception ex)
82     {
83       ex.printStackTrace();
84       return "Error retrieving alignment in " + format + " format. ";
85     }
86   }
87
88   public void loadAnnotation(String annotation)
89   {
90     if (new AnnotationFile().readAnnotationFile(
91         currentAlignFrame.getAlignViewport().getAlignment(), annotation,
92         AppletFormatAdapter.PASTE))
93     {
94       currentAlignFrame.alignPanel.fontChanged();
95       currentAlignFrame.alignPanel.setScrollValues(0, 0);
96     }
97     else
98     {
99       currentAlignFrame.parseFeaturesFile(annotation, AppletFormatAdapter.PASTE);
100     }
101   }
102
103   public String getFeatures(String format)
104   {
105     return currentAlignFrame.outputFeatures(false, format);
106   }
107
108   public String getAnnotation()
109   {
110     return currentAlignFrame.outputAnnotations(false);
111   }
112
113   public void loadAlignment(String text, String title)
114   {
115     Alignment al = null;
116     String format = new IdentifyFile().Identify(text, AppletFormatAdapter.PASTE);
117     try
118     {
119       al = new AppletFormatAdapter().readFile(text,
120                                               AppletFormatAdapter.PASTE,
121                                               format);
122       if (al.getHeight() > 0)
123       {
124         new AlignFrame(al, this, title, false);
125       }
126     }
127     catch (java.io.IOException ex)
128     {
129       ex.printStackTrace();
130     }
131   }
132
133   ////////////////////////////////////////////////
134   ////////////////////////////////////////////////
135
136
137
138   static int lastFrameX = 200;
139   static int lastFrameY = 200;
140   boolean fileFound = true;
141   String file = "No file";
142   Button launcher = new Button("Start Jalview");
143
144   //The currentAlignFrame is static, it will change
145   //if and when the user selects a new window
146   public static AlignFrame currentAlignFrame;
147
148   //This is the first frame to be displayed, and does not change
149   AlignFrame initialAlignFrame;
150
151   boolean embedded = false;
152
153   public boolean jmolAvailable = false;
154
155   /**
156    * init method for Jalview Applet
157    */
158   public void init()
159   {
160     int r = 255;
161     int g = 255;
162     int b = 255;
163     String param = getParameter("RGB");
164
165     if (param != null)
166     {
167       try
168       {
169         r = Integer.parseInt(param.substring(0, 2), 16);
170         g = Integer.parseInt(param.substring(2, 4), 16);
171         b = Integer.parseInt(param.substring(4, 6), 16);
172       }
173       catch (Exception ex)
174       {
175         r = 255;
176         g = 255;
177         b = 255;
178       }
179     }
180
181     param = getParameter("label");
182     if (param != null)
183     {
184       launcher.setLabel(param);
185     }
186
187     this.setBackground(new Color(r, g, b));
188
189     file = getParameter("file");
190
191     if (file == null)
192     {
193       //Maybe the sequences are added as parameters
194       StringBuffer data = new StringBuffer("PASTE");
195       int i = 1;
196       while ( (file = getParameter("sequence" + i)) != null)
197       {
198         data.append(file.toString() + "\n");
199         i++;
200       }
201       if (data.length() > 5)
202       {
203         file = data.toString();
204       }
205     }
206
207     LoadJmolThread jmolAvailable = new LoadJmolThread();
208     jmolAvailable.start();
209
210     final JalviewLite applet = this;
211     if (getParameter("embedded") != null
212         && getParameter("embedded").equalsIgnoreCase("true"))
213     {
214       embedded = true;
215       LoadingThread loader = new LoadingThread(file, applet);
216       loader.start();
217     }
218     else if (file != null)
219     {
220       add(launcher);
221
222       launcher.addActionListener(new java.awt.event.ActionListener()
223       {
224         public void actionPerformed(ActionEvent e)
225         {
226           LoadingThread loader = new LoadingThread(file,
227               applet);
228           loader.start();
229         }
230       });
231     }
232     else
233     {
234       file = "NO FILE";
235       fileFound = false;
236     }
237   }
238
239
240   /**
241    * Initialises and displays a new java.awt.Frame
242    *
243    * @param frame java.awt.Frame to be displayed
244    * @param title title of new frame
245    * @param width width if new frame
246    * @param height height of new frame
247    */
248   public static void addFrame(final Frame frame, String title, int width,
249                               int height)
250   {
251     frame.setLocation(lastFrameX, lastFrameY);
252     lastFrameX += 40;
253     lastFrameY += 40;
254     frame.setSize(width, height);
255     frame.setTitle(title);
256     frame.addWindowListener(new WindowAdapter()
257     {
258       public void windowClosing(WindowEvent e)
259       {
260         if (frame instanceof AlignFrame)
261         {
262           ( (AlignFrame) frame).closeMenuItem_actionPerformed();
263         }
264         if (currentAlignFrame == frame)
265         {
266           currentAlignFrame = null;
267         }
268         lastFrameX -= 40;
269         lastFrameY -= 40;
270         frame.setMenuBar(null);
271         frame.dispose();
272       }
273
274       public void windowActivated(WindowEvent e)
275       {
276         if (frame instanceof AlignFrame)
277         {
278           currentAlignFrame = (AlignFrame) frame;
279         }
280       }
281
282     });
283     frame.setVisible(true);
284   }
285
286   /**
287    * This paints the background surrounding the "Launch Jalview button"
288    * <br>
289    * <br>If file given in parameter not found, displays error message
290    *
291    * @param g graphics context
292    */
293   public void paint(Graphics g)
294   {
295     if (!fileFound)
296     {
297       g.setColor(new Color(200, 200, 200));
298       g.setColor(Color.cyan);
299       g.fillRect(0, 0, getSize().width, getSize().height);
300       g.setColor(Color.red);
301       g.drawString("Jalview can't open file", 5, 15);
302       g.drawString("\"" + file + "\"", 5, 30);
303     }
304     else if (embedded)
305     {
306       g.setColor(Color.black);
307       g.setFont(new Font("Arial", Font.BOLD, 24));
308       g.drawString("Jalview Applet", 50, this.getSize().height / 2 - 30);
309       g.drawString("Loading Data...", 50, this.getSize().height / 2);
310     }
311   }
312
313
314   class LoadJmolThread extends Thread
315   {
316     public void run()
317     {
318       try
319       {
320         if (!System.getProperty("java.version").startsWith("1.1"))
321         {
322           Class.forName("org.jmol.adapter.smarter.SmarterJmolAdapter");
323           jmolAvailable = true;
324           System.out.println("JMOL FOUND");
325         }
326       }
327       catch (java.lang.ClassNotFoundException ex)
328       {
329         System.out.println("Jmol not available - Using MCview for structures");
330       }
331     }
332   }
333
334
335   class LoadingThread
336       extends Thread
337   {
338     String file;
339     String protocol;
340     String format;
341     JalviewLite applet;
342
343     public LoadingThread(String _file,
344                          JalviewLite _applet)
345     {
346       file = _file;
347       if (file.startsWith("PASTE"))
348       {
349         file = file.substring(5);
350         protocol = AppletFormatAdapter.PASTE;
351       }
352       else if (inArchive(file))
353       {
354         protocol = AppletFormatAdapter.CLASSLOADER;
355       }
356       else
357       {
358         file = addProtocol(file);
359         protocol = AppletFormatAdapter.URL;
360       }
361       format = new jalview.io.IdentifyFile().Identify(file, protocol);
362       applet = _applet;
363     }
364
365     public void run()
366     {
367       startLoading();
368     }
369
370     private void startLoading()
371     {
372       Alignment al = null;
373       try
374       {
375         al = new AppletFormatAdapter().readFile(file, protocol,
376                                                 format);
377       }
378       catch (java.io.IOException ex)
379       {
380         ex.printStackTrace();
381       }
382       if ( (al != null) && (al.getHeight() > 0))
383       {
384         currentAlignFrame = new AlignFrame(al,
385                                            applet,
386                                            file,
387                                            embedded);
388
389         if (protocol == jalview.io.AppletFormatAdapter.PASTE)
390         {
391           currentAlignFrame.setTitle("Sequences from " + getDocumentBase());
392         }
393
394         initialAlignFrame = currentAlignFrame;
395
396         currentAlignFrame.statusBar.setText("Successfully loaded file " + file);
397
398         String treeFile = applet.getParameter("tree");
399         if (treeFile == null)
400         {
401           treeFile = applet.getParameter("treeFile");
402         }
403
404         if (treeFile != null)
405         {
406           try
407           {
408             if (inArchive(treeFile))
409             {
410               protocol = AppletFormatAdapter.CLASSLOADER;
411             }
412             else
413             {
414               protocol = AppletFormatAdapter.URL;
415               treeFile = addProtocol(treeFile);
416             }
417
418             jalview.io.NewickFile fin = new jalview.io.NewickFile(treeFile,
419                 protocol);
420
421             fin.parse();
422
423             if (fin.getTree() != null)
424             {
425               currentAlignFrame.loadTree(fin, treeFile);
426             }
427           }
428           catch (Exception ex)
429           {
430             ex.printStackTrace();
431           }
432         }
433
434         String param = getParameter("features");
435         if (param != null)
436         {
437           if (!inArchive(param))
438           {
439             param = addProtocol(param);
440           }
441
442           currentAlignFrame.parseFeaturesFile(param, protocol);
443         }
444
445         param = getParameter("showFeatureSettings");
446         if (param != null && param.equalsIgnoreCase("true"))
447         {
448           currentAlignFrame.viewport.showSequenceFeatures(true);
449           new FeatureSettings(currentAlignFrame.alignPanel);
450         }
451
452         param = getParameter("annotations");
453         if (param != null)
454         {
455           if (!inArchive(param))
456           {
457             param = addProtocol(param);
458           }
459
460           new AnnotationFile().readAnnotationFile(
461               currentAlignFrame.viewport.getAlignment(),
462               param,
463               protocol);
464
465           currentAlignFrame.alignPanel.fontChanged();
466           currentAlignFrame.alignPanel.setScrollValues(0, 0);
467
468         }
469
470         param = getParameter("jnetfile");
471         if (param != null)
472         {
473           try
474           {
475             if (inArchive(param))
476             {
477               protocol = AppletFormatAdapter.CLASSLOADER;
478             }
479             else
480             {
481               protocol = AppletFormatAdapter.URL;
482               param = addProtocol(param);
483             }
484
485             jalview.io.JPredFile predictions = new jalview.io.JPredFile(
486                 param, protocol);
487             new JnetAnnotationMaker().add_annotation(predictions,
488                 currentAlignFrame.viewport.getAlignment(),
489                 0, false); // do not add sequence profile from concise output
490             currentAlignFrame.alignPanel.fontChanged();
491             currentAlignFrame.alignPanel.setScrollValues(0, 0);
492           }
493           catch (Exception ex)
494           {
495             ex.printStackTrace();
496           }
497         }
498
499         /*
500          <param name="PDBfile" value="1gaq.txt PDB|1GAQ|1GAQ|A PDB|1GAQ|1GAQ|B PDB|1GAQ|1GAQ|C">
501
502          <param name="PDBfile2" value="1gaq.txt A=SEQA B=SEQB C=SEQB">
503
504          <param name="PDBfile3" value="1q0o Q45135_9MICO">
505         */
506
507
508         int pdbFileCount = 0;
509         do{
510           if (pdbFileCount > 0)
511             param = getParameter("PDBFILE" + pdbFileCount);
512           else
513             param = getParameter("PDBFILE");
514
515           if (param != null)
516           {
517             PDBEntry pdb = new PDBEntry();
518
519             String seqstring;
520             SequenceI[] seqs = null;
521             String [] chains = null;
522
523             StringTokenizer st = new StringTokenizer(param, " ");
524
525             if (st.countTokens() < 2)
526             {
527               String sequence = applet.getParameter("PDBSEQ");
528               if (sequence != null)
529                 seqs = new SequenceI[]
530                     {
531                     (Sequence) currentAlignFrame.
532                     getAlignViewport().getAlignment().
533                     findName(sequence)};
534
535             }
536             else
537             {
538               param = st.nextToken();
539               Vector tmp = new Vector();
540               Vector tmp2 = new Vector();
541
542               while (st.hasMoreTokens())
543               {
544                 seqstring = st.nextToken();
545                 StringTokenizer st2 = new StringTokenizer(seqstring,"=");
546                 if(st2.countTokens()>1)
547                 {
548                   //This is the chain
549                   tmp2.addElement(st2.nextToken());
550                   seqstring = st2.nextToken();
551                 }
552                 tmp.addElement( (Sequence) currentAlignFrame.
553                                  getAlignViewport().getAlignment().
554                                  findName(seqstring));
555               }
556
557               seqs = new SequenceI[tmp.size()];
558               tmp.copyInto(seqs);
559               if(tmp2.size()==tmp.size())
560               {
561                 chains = new String[tmp2.size()];
562                 tmp2.copyInto(chains);
563               }
564             }
565
566             param = addProtocol(param);
567             pdb.setFile(param);
568
569             if(seqs!=null)
570             {
571               for (int i = 0; i < seqs.length; i++)
572               {
573                 ( (Sequence) seqs[i]).addPDBId(pdb);
574               }
575
576               if (jmolAvailable)
577               {
578                 new jalview.appletgui.AppletJmol(pdb,
579                                                  seqs,
580                                                  chains,
581                                                  currentAlignFrame.alignPanel,
582                                                  protocol);
583                 lastFrameX += 40;
584                 lastFrameY+=40;
585               }
586               else
587                     new MCview.AppletPDBViewer(pdb,
588                                            seqs,
589                                            chains,
590                                            currentAlignFrame.alignPanel,
591                                            protocol);
592             }
593           }
594
595           pdbFileCount++;
596         }
597         while(pdbFileCount < 10);
598
599       }
600       else
601       {
602         fileFound = false;
603         remove(launcher);
604         repaint();
605       }
606     }
607
608     /**
609      * Discovers whether the given file is in the Applet Archive
610      * @param file String
611      * @return boolean
612      */
613     boolean inArchive(String file)
614     {
615       //This might throw a security exception in certain browsers
616       //Netscape Communicator for instance.
617       try
618       {
619         return (getClass().getResourceAsStream("/" + file) != null);
620       }
621       catch (Exception ex)
622       {
623         System.out.println("Exception checking resources: " + file + " " + ex);
624         return false;
625       }
626     }
627
628     String addProtocol(String file)
629     {
630       if (file.indexOf("://") == -1)
631       {
632         file = getCodeBase() + file;
633       }
634
635       return file;
636     }
637   }
638 }