If seq has a dataset, dont clear it
[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     String  [] seqstrings;\r
48     SequenceI  [] seqs;\r
49 \r
50     /**\r
51      * Creates a new PCAPanel object.\r
52      *\r
53      * @param av DOCUMENT ME!\r
54      * @param s DOCUMENT ME!\r
55      */\r
56     public PCAPanel(AlignViewport av)\r
57     {\r
58         this.av = av;\r
59 \r
60         boolean sameLength = true;\r
61 \r
62         seqstrings = av.getViewAsString(true);\r
63 \r
64         if (av.getSelectionGroup() == null)\r
65         {\r
66           seqs = av.alignment.getSequencesArray();\r
67         }\r
68         else\r
69         {\r
70           seqs = av.getSelectionGroup().getSequencesInOrder(av.alignment);\r
71         }\r
72 \r
73         int length = seqs[0].getLength();\r
74 \r
75         for (int i = 0; i < seqs.length; i++)\r
76         {\r
77           if (seqs[i].getLength() != length)\r
78           {\r
79             sameLength = false;\r
80             break;\r
81           }\r
82         }\r
83 \r
84         if (!sameLength)\r
85         {\r
86           JOptionPane.showMessageDialog(Desktop.desktop,\r
87                                         "The sequences must be aligned before calculating PCA.\n" +\r
88                                         "Try using the Pad function in the edit menu,\n" +\r
89                                         "or one of the multiple sequence alignment web services.",\r
90                                         "Sequences not aligned",\r
91                                         JOptionPane.WARNING_MESSAGE);\r
92 \r
93           return;\r
94         }\r
95 \r
96 \r
97         Desktop.addInternalFrame(this, "Principal component analysis",\r
98                                400, 400);\r
99 \r
100 \r
101         rc = new RotatableCanvas(av);\r
102         this.getContentPane().add(rc, BorderLayout.CENTER);\r
103         Thread worker = new Thread(this);\r
104         worker.start();\r
105     }\r
106 \r
107     public void bgcolour_actionPerformed(ActionEvent e)\r
108     {\r
109       Color col = JColorChooser.showDialog(this, "Select Background Colour",\r
110                 rc.bgColour);\r
111 \r
112       if(col!=null)\r
113         rc.bgColour = col;\r
114       rc.repaint();\r
115     }\r
116 \r
117 \r
118 \r
119 \r
120     /**\r
121      * DOCUMENT ME!\r
122      */\r
123     public void run()\r
124     {\r
125       try{\r
126         pca = new PCA(seqstrings);\r
127         pca.run();\r
128 \r
129         // Now find the component coordinates\r
130         int ii = 0;\r
131 \r
132         while ( (ii < seqs.length) && (seqs[ii] != null))\r
133         {\r
134           ii++;\r
135         }\r
136 \r
137         double[][] comps = new double[ii][ii];\r
138 \r
139         for (int i = 0; i < ii; i++)\r
140         {\r
141           if (pca.getEigenvalue(i) > 1e-4)\r
142           {\r
143             comps[i] = pca.component(i);\r
144           }\r
145         }\r
146 \r
147         //////////////////\r
148         xCombobox.setSelectedIndex(0);\r
149         yCombobox.setSelectedIndex(1);\r
150         zCombobox.setSelectedIndex(2);\r
151 \r
152         top = pca.getM().rows - 1;\r
153 \r
154         Vector points = new Vector();\r
155         float[][] scores = pca.getComponents(top - 1, top - 2, top - 3, 100);\r
156 \r
157         for (int i = 0; i < pca.getM().rows; i++)\r
158         {\r
159           SequencePoint sp = new SequencePoint(seqs[i], scores[i]);\r
160           points.addElement(sp);\r
161         }\r
162 \r
163         rc.setPoints(points, pca.getM().rows);\r
164         rc.repaint();\r
165       }\r
166      catch(OutOfMemoryError er)\r
167       { JOptionPane.showInternalMessageDialog(Desktop.desktop,\r
168                                               "Out of memory calculating PCA!!"\r
169                                               +\r
170                                               "\nSee help files for increasing Java Virtual Machine memory."\r
171                                               , "Out of memory",\r
172                                               JOptionPane.WARNING_MESSAGE);\r
173         System.out.println("PCAPanel: "+er);\r
174         System.gc();\r
175 \r
176       }\r
177 \r
178     }\r
179 \r
180     /**\r
181      * DOCUMENT ME!\r
182      */\r
183     void doDimensionChange()\r
184     {\r
185         if (top == 0)\r
186         {\r
187             return;\r
188         }\r
189 \r
190         int dim1 = top - xCombobox.getSelectedIndex();\r
191         int dim2 = top - yCombobox.getSelectedIndex();\r
192         int dim3 = top - zCombobox.getSelectedIndex();\r
193 \r
194         float[][] scores = pca.getComponents(dim1, dim2, dim3, 100);\r
195 \r
196         for (int i = 0; i < pca.getM().rows; i++)\r
197         {\r
198             ((SequencePoint) rc.points.elementAt(i)).coord = scores[i];\r
199         }\r
200 \r
201         rc.img = null;\r
202         rc.rotmat.setIdentity();\r
203         rc.initAxes();\r
204         rc.paint(rc.getGraphics());\r
205     }\r
206 \r
207     /**\r
208      * DOCUMENT ME!\r
209      *\r
210      * @param e DOCUMENT ME!\r
211      */\r
212     protected void xCombobox_actionPerformed(ActionEvent e)\r
213     {\r
214         doDimensionChange();\r
215     }\r
216 \r
217     /**\r
218      * DOCUMENT ME!\r
219      *\r
220      * @param e DOCUMENT ME!\r
221      */\r
222     protected void yCombobox_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 zCombobox_actionPerformed(ActionEvent e)\r
233     {\r
234         doDimensionChange();\r
235     }\r
236 \r
237 \r
238     public void outputValues_actionPerformed(ActionEvent e)\r
239     {\r
240       CutAndPasteTransfer cap = new CutAndPasteTransfer();\r
241       Desktop.addInternalFrame(cap, "PCA details", 500,\r
242                 500);\r
243 \r
244       cap.setText(pca.getDetails());\r
245      }\r
246 \r
247     public void showLabels_actionPerformed(ActionEvent e)\r
248     {\r
249       rc.showLabels(showLabels.getState());\r
250     }\r
251 \r
252     public void print_actionPerformed(ActionEvent e)\r
253     {\r
254       PCAPrinter printer = new PCAPrinter();\r
255       printer.start();\r
256     }\r
257 \r
258     public void originalSeqData_actionPerformed(ActionEvent e)\r
259     {\r
260       CutAndPasteTransfer cap = new CutAndPasteTransfer();\r
261       for (int i = 0; i < seqs.length; i++)\r
262       {\r
263         cap.appendText(new jalview.util.Format("%-" + 15 + "s").form(\r
264             seqs[i].getName()));\r
265         cap.appendText(" " + seqstrings[i] + "\n");\r
266 \r
267       }\r
268 \r
269       Desktop.addInternalFrame(cap, "Original Data",\r
270           400, 400);\r
271 \r
272     }\r
273 \r
274 \r
275 \r
276     class PCAPrinter extends Thread implements Printable\r
277     {\r
278       public void run()\r
279       {\r
280         PrinterJob printJob = PrinterJob.getPrinterJob();\r
281         PageFormat pf = printJob.pageDialog(printJob.defaultPage());\r
282 \r
283         printJob.setPrintable(this, pf);\r
284 \r
285         if (printJob.printDialog())\r
286         {\r
287           try\r
288           {\r
289             printJob.print();\r
290           }\r
291           catch (Exception PrintException)\r
292           {\r
293             PrintException.printStackTrace();\r
294           }\r
295         }\r
296       }\r
297 \r
298       public int print(Graphics pg, PageFormat pf, int pi)\r
299           throws PrinterException\r
300       {\r
301         pg.translate( (int) pf.getImageableX(), (int) pf.getImageableY());\r
302 \r
303         rc.drawBackground(pg, rc.bgColour);\r
304         rc.drawScene(pg);\r
305         if (rc.drawAxes == true)\r
306         {\r
307           rc.drawAxes(pg);\r
308         }\r
309 \r
310         if (pi == 0)\r
311           return Printable.PAGE_EXISTS;\r
312         else\r
313           return Printable.NO_SUCH_PAGE;\r
314       }\r
315     }\r
316 \r
317 \r
318 \r
319     /**\r
320      * DOCUMENT ME!\r
321      *\r
322      * @param e DOCUMENT ME!\r
323      */\r
324     public void eps_actionPerformed(ActionEvent e)\r
325     {\r
326       makePCAImage(jalview.util.ImageMaker.EPS);\r
327     }\r
328 \r
329     /**\r
330      * DOCUMENT ME!\r
331      *\r
332      * @param e DOCUMENT ME!\r
333      */\r
334     public void png_actionPerformed(ActionEvent e)\r
335     {\r
336        makePCAImage(jalview.util.ImageMaker.PNG);\r
337     }\r
338 \r
339     void makePCAImage(int type)\r
340     {\r
341       int width = rc.getWidth();\r
342       int height = rc.getHeight();\r
343 \r
344       jalview.util.ImageMaker im;\r
345 \r
346       if(type == jalview.util.ImageMaker.PNG)\r
347         im = new jalview.util.ImageMaker(this,\r
348                                          jalview.util.ImageMaker.PNG,\r
349                                          "Make PNG image from PCA",\r
350                                          width, height,\r
351                                          null, null);\r
352         else\r
353           im = new jalview.util.ImageMaker(this,\r
354                                  jalview.util.ImageMaker.EPS,\r
355                                  "Make EPS file from PCA",\r
356                                  width, height,\r
357                                  null, this.getTitle());\r
358 \r
359       if(im.getGraphics()!=null)\r
360        {\r
361          rc.drawBackground(im.getGraphics(), Color.black);\r
362          rc.drawScene(im.getGraphics());\r
363          if (rc.drawAxes == true)\r
364          {\r
365            rc.drawAxes(im.getGraphics());\r
366          }\r
367          im.writeImage();\r
368        }\r
369     }\r
370   }\r