Use selection area with hidden columns in calculations
[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.getSelectionAsString();\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           cap.appendText(seqs[i].getName()+"\t"\r
263                          +seqstrings[i]+"\n");\r
264 \r
265       Desktop.addInternalFrame(cap, "Original Data",\r
266           400, 400);\r
267 \r
268     }\r
269 \r
270 \r
271 \r
272     class PCAPrinter extends Thread implements Printable\r
273     {\r
274       public void run()\r
275       {\r
276         PrinterJob printJob = PrinterJob.getPrinterJob();\r
277         PageFormat pf = printJob.pageDialog(printJob.defaultPage());\r
278 \r
279         printJob.setPrintable(this, pf);\r
280 \r
281         if (printJob.printDialog())\r
282         {\r
283           try\r
284           {\r
285             printJob.print();\r
286           }\r
287           catch (Exception PrintException)\r
288           {\r
289             PrintException.printStackTrace();\r
290           }\r
291         }\r
292       }\r
293 \r
294       public int print(Graphics pg, PageFormat pf, int pi)\r
295           throws PrinterException\r
296       {\r
297         pg.translate( (int) pf.getImageableX(), (int) pf.getImageableY());\r
298 \r
299         rc.drawBackground(pg, rc.bgColour);\r
300         rc.drawScene(pg);\r
301         if (rc.drawAxes == true)\r
302         {\r
303           rc.drawAxes(pg);\r
304         }\r
305 \r
306         if (pi == 0)\r
307           return Printable.PAGE_EXISTS;\r
308         else\r
309           return Printable.NO_SUCH_PAGE;\r
310       }\r
311     }\r
312 \r
313 \r
314 \r
315     /**\r
316      * DOCUMENT ME!\r
317      *\r
318      * @param e DOCUMENT ME!\r
319      */\r
320     public void eps_actionPerformed(ActionEvent e)\r
321     {\r
322       makePCAImage(jalview.util.ImageMaker.EPS);\r
323     }\r
324 \r
325     /**\r
326      * DOCUMENT ME!\r
327      *\r
328      * @param e DOCUMENT ME!\r
329      */\r
330     public void png_actionPerformed(ActionEvent e)\r
331     {\r
332        makePCAImage(jalview.util.ImageMaker.PNG);\r
333     }\r
334 \r
335     void makePCAImage(int type)\r
336     {\r
337       int width = rc.getWidth();\r
338       int height = rc.getHeight();\r
339 \r
340       jalview.util.ImageMaker im;\r
341 \r
342       if(type == jalview.util.ImageMaker.PNG)\r
343         im = new jalview.util.ImageMaker(this,\r
344                                          jalview.util.ImageMaker.PNG,\r
345                                          "Make PNG image from PCA",\r
346                                          width, height,\r
347                                          null, null);\r
348         else\r
349           im = new jalview.util.ImageMaker(this,\r
350                                  jalview.util.ImageMaker.EPS,\r
351                                  "Make EPS file from PCA",\r
352                                  width, height,\r
353                                  null, this.getTitle());\r
354 \r
355       if(im.getGraphics()!=null)\r
356        {\r
357          rc.drawBackground(im.getGraphics(), Color.black);\r
358          rc.drawScene(im.getGraphics());\r
359          if (rc.drawAxes == true)\r
360          {\r
361            rc.drawAxes(im.getGraphics());\r
362          }\r
363          im.writeImage();\r
364        }\r
365     }\r
366   }\r