e680ddeab3fcb15970cd0817878fad8521c221a2
[jalview.git] / src / jalview / gui / PCAPanel.java
1 /*\r
2  * Jalview - A Sequence Alignment Editor and Viewer\r
3  * Copyright (C) 2005 AM Waterhouse, J Procter, G Barton, M Clamp, S Searle\r
4  *\r
5  * This program is free software; you can redistribute it and/or\r
6  * modify it under the terms of the GNU General Public License\r
7  * as published by the Free Software Foundation; either version 2\r
8  * of the License, or (at your option) any later version.\r
9  *\r
10  * This program is distributed in the hope that it will be useful,\r
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
13  * GNU General Public License for more details.\r
14  *\r
15  * You should have received a copy of the GNU General Public License\r
16  * along with this program; if not, write to the Free Software\r
17  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA\r
18  */\r
19 package jalview.gui;\r
20 \r
21 import jalview.analysis.*;\r
22 \r
23 import jalview.datamodel.*;\r
24 \r
25 import jalview.jbgui.*;\r
26 \r
27 import java.awt.*;\r
28 import java.awt.event.*;\r
29 \r
30 import java.util.*;\r
31 import javax.swing.*;\r
32 import java.awt.print.*;\r
33 \r
34 \r
35 /**\r
36  * DOCUMENT ME!\r
37  *\r
38  * @author $author$\r
39  * @version $Revision$\r
40  */\r
41 public class PCAPanel extends GPCAPanel implements Runnable\r
42 {\r
43     PCA pca;\r
44     int top;\r
45     RotatableCanvas rc;\r
46     AlignViewport av;\r
47     SequenceI [] seqs;\r
48 \r
49     /**\r
50      * Creates a new PCAPanel object.\r
51      *\r
52      * @param av DOCUMENT ME!\r
53      * @param s DOCUMENT ME!\r
54      */\r
55     public PCAPanel(AlignViewport av)\r
56     {\r
57         this.av = av;\r
58 \r
59         boolean sameLength = true;\r
60 \r
61         if ((av.getSelectionGroup() != null) &&\r
62                 (av.getSelectionGroup().getSize() > 3))\r
63         {\r
64             seqs = new Sequence[av.getSelectionGroup().getSize()];\r
65             int length = av.getSelectionGroup().getSequenceAt(0).getLength();\r
66             for (int i = 0; i < av.getSelectionGroup().getSize(); i++)\r
67             {\r
68                 seqs[i] = av.getSelectionGroup().getSequenceAt(i);\r
69                 if(seqs[i].getLength()!=length)\r
70                 {\r
71                   sameLength = false;\r
72                   break;\r
73                 }\r
74             }\r
75         }\r
76         else\r
77         {\r
78             seqs = new Sequence[av.getAlignment().getHeight()];\r
79             int length = av.alignment.getSequenceAt(0).getLength();\r
80 \r
81             for (int i = 0; i < av.getAlignment().getHeight(); i++)\r
82             {\r
83                 seqs[i] = av.getAlignment().getSequenceAt(i);\r
84                 if(seqs[i].getLength()!=length)\r
85                {\r
86                  sameLength = false;\r
87                  break;\r
88                }\r
89 \r
90             }\r
91         }\r
92 \r
93         if (!sameLength)\r
94         {\r
95           JOptionPane.showMessageDialog(Desktop.desktop,\r
96                                         "The sequences must be aligned before calculating PCA.\n" +\r
97                                         "Try using the Pad function in the edit menu,\n" +\r
98                                         "or one of the multiple sequence alignment web services.",\r
99                                         "Sequences not aligned",\r
100                                         JOptionPane.WARNING_MESSAGE);\r
101 \r
102           return;\r
103         }\r
104 \r
105 \r
106         Desktop.addInternalFrame(this, "Principal component analysis",\r
107                                400, 400);\r
108 \r
109 \r
110         rc = new RotatableCanvas(av);\r
111         this.getContentPane().add(rc, BorderLayout.CENTER);\r
112         Thread worker = new Thread(this);\r
113         worker.start();\r
114     }\r
115 \r
116     public void bgcolour_actionPerformed(ActionEvent e)\r
117     {\r
118       Color col = JColorChooser.showDialog(this, "Select Background Colour",\r
119                 rc.bgColour);\r
120 \r
121       if(col!=null)\r
122         rc.bgColour = col;\r
123       rc.repaint();\r
124     }\r
125 \r
126 \r
127 \r
128 \r
129     /**\r
130      * DOCUMENT ME!\r
131      */\r
132     public void run()\r
133     {\r
134       try{\r
135         pca = new PCA(seqs);\r
136         pca.run();\r
137 \r
138         // Now find the component coordinates\r
139         int ii = 0;\r
140 \r
141         while ( (ii < seqs.length) && (seqs[ii] != null))\r
142         {\r
143           ii++;\r
144         }\r
145 \r
146         double[][] comps = new double[ii][ii];\r
147 \r
148         for (int i = 0; i < ii; i++)\r
149         {\r
150           if (pca.getEigenvalue(i) > 1e-4)\r
151           {\r
152             comps[i] = pca.component(i);\r
153           }\r
154         }\r
155 \r
156         //////////////////\r
157         xCombobox.setSelectedIndex(0);\r
158         yCombobox.setSelectedIndex(1);\r
159         zCombobox.setSelectedIndex(2);\r
160 \r
161         top = pca.getM().rows - 1;\r
162 \r
163         Vector points = new Vector();\r
164         float[][] scores = pca.getComponents(top - 1, top - 2, top - 3, 100);\r
165 \r
166         for (int i = 0; i < pca.getM().rows; i++)\r
167         {\r
168           SequencePoint sp = new SequencePoint(seqs[i], scores[i]);\r
169           points.addElement(sp);\r
170         }\r
171 \r
172         rc.setPoints(points, pca.getM().rows);\r
173         rc.repaint();\r
174         seqs = null;\r
175       }\r
176      catch(OutOfMemoryError er)\r
177       { JOptionPane.showInternalMessageDialog(Desktop.desktop,\r
178                                               "Out of memory calculating PCA!!"\r
179                                               +\r
180                                               "\nSee help files for increasing Java Virtual Machine memory."\r
181                                               , "Out of memory",\r
182                                               JOptionPane.WARNING_MESSAGE);\r
183         System.out.println("PCAPanel: "+er);\r
184         System.gc();\r
185 \r
186       }\r
187 \r
188     }\r
189 \r
190     /**\r
191      * DOCUMENT ME!\r
192      */\r
193     void doDimensionChange()\r
194     {\r
195         if (top == 0)\r
196         {\r
197             return;\r
198         }\r
199 \r
200         int dim1 = top - xCombobox.getSelectedIndex();\r
201         int dim2 = top - yCombobox.getSelectedIndex();\r
202         int dim3 = top - zCombobox.getSelectedIndex();\r
203 \r
204         float[][] scores = pca.getComponents(dim1, dim2, dim3, 100);\r
205 \r
206         for (int i = 0; i < pca.getM().rows; i++)\r
207         {\r
208             ((SequencePoint) rc.points.elementAt(i)).coord = scores[i];\r
209         }\r
210 \r
211         rc.img = null;\r
212         rc.rotmat.setIdentity();\r
213         rc.initAxes();\r
214         rc.paint(rc.getGraphics());\r
215     }\r
216 \r
217     /**\r
218      * DOCUMENT ME!\r
219      *\r
220      * @param e DOCUMENT ME!\r
221      */\r
222     protected void xCombobox_actionPerformed(ActionEvent e)\r
223     {\r
224         doDimensionChange();\r
225     }\r
226 \r
227     /**\r
228      * DOCUMENT ME!\r
229      *\r
230      * @param e DOCUMENT ME!\r
231      */\r
232     protected void yCombobox_actionPerformed(ActionEvent e)\r
233     {\r
234         doDimensionChange();\r
235     }\r
236 \r
237     /**\r
238      * DOCUMENT ME!\r
239      *\r
240      * @param e DOCUMENT ME!\r
241      */\r
242     protected void zCombobox_actionPerformed(ActionEvent e)\r
243     {\r
244         doDimensionChange();\r
245     }\r
246 \r
247 \r
248     public void outputValues_actionPerformed(ActionEvent e)\r
249     {\r
250       CutAndPasteTransfer cap = new CutAndPasteTransfer();\r
251       Desktop.addInternalFrame(cap, "PCA details", 500,\r
252                 500);\r
253 \r
254       cap.setText(pca.getDetails());\r
255      }\r
256 \r
257     public void showLabels_actionPerformed(ActionEvent e)\r
258     {\r
259       rc.showLabels(showLabels.getState());\r
260     }\r
261 \r
262     public void print_actionPerformed(ActionEvent e)\r
263     {\r
264       PCAPrinter printer = new PCAPrinter();\r
265       printer.start();\r
266     }\r
267 \r
268 \r
269     class PCAPrinter extends Thread implements Printable\r
270     {\r
271       public void run()\r
272       {\r
273         PrinterJob printJob = PrinterJob.getPrinterJob();\r
274         PageFormat pf = printJob.pageDialog(printJob.defaultPage());\r
275 \r
276         printJob.setPrintable(this, pf);\r
277 \r
278         if (printJob.printDialog())\r
279         {\r
280           try\r
281           {\r
282             printJob.print();\r
283           }\r
284           catch (Exception PrintException)\r
285           {\r
286             PrintException.printStackTrace();\r
287           }\r
288         }\r
289       }\r
290 \r
291       public int print(Graphics pg, PageFormat pf, int pi)\r
292           throws PrinterException\r
293       {\r
294         pg.translate( (int) pf.getImageableX(), (int) pf.getImageableY());\r
295 \r
296         rc.drawBackground(pg, rc.bgColour);\r
297         rc.drawScene(pg);\r
298         if (rc.drawAxes == true)\r
299         {\r
300           rc.drawAxes(pg);\r
301         }\r
302 \r
303         if (pi == 0)\r
304           return Printable.PAGE_EXISTS;\r
305         else\r
306           return Printable.NO_SUCH_PAGE;\r
307       }\r
308     }\r
309 \r
310 \r
311 \r
312     /**\r
313      * DOCUMENT ME!\r
314      *\r
315      * @param e DOCUMENT ME!\r
316      */\r
317     public void eps_actionPerformed(ActionEvent e)\r
318     {\r
319       makePCAImage(jalview.util.ImageMaker.EPS);\r
320     }\r
321 \r
322     /**\r
323      * DOCUMENT ME!\r
324      *\r
325      * @param e DOCUMENT ME!\r
326      */\r
327     public void png_actionPerformed(ActionEvent e)\r
328     {\r
329        makePCAImage(jalview.util.ImageMaker.PNG);\r
330     }\r
331 \r
332     void makePCAImage(int type)\r
333     {\r
334       int width = rc.getWidth();\r
335       int height = rc.getHeight();\r
336 \r
337       jalview.util.ImageMaker im;\r
338 \r
339       if(type == jalview.util.ImageMaker.PNG)\r
340         im = new jalview.util.ImageMaker(this,\r
341                                          jalview.util.ImageMaker.PNG,\r
342                                          "Make PNG image from PCA",\r
343                                          width, height,\r
344                                          null, null);\r
345         else\r
346           im = new jalview.util.ImageMaker(this,\r
347                                  jalview.util.ImageMaker.EPS,\r
348                                  "Make EPS file from PCA",\r
349                                  width, height,\r
350                                  null, this.getTitle());\r
351 \r
352       if(im.getGraphics()!=null)\r
353        {\r
354          rc.drawBackground(im.getGraphics(), Color.black);\r
355          rc.drawScene(im.getGraphics());\r
356          if (rc.drawAxes == true)\r
357          {\r
358            rc.drawAxes(im.getGraphics());\r
359          }\r
360          im.writeImage();\r
361        }\r
362     }\r
363   }\r