set seqColours null
[jalview.git] / src / jalview / gui / PCAPanel.java
1 /*\r
2  * Jalview - A Sequence Alignment Editor and Viewer\r
3  * Copyright (C) 2006 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     AlignmentView 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.getAlignmentView(av.getSelectionGroup()!=null);\r
63         if(av.getSelectionGroup()==null)\r
64         {\r
65           seqs = av.alignment.getSequencesArray();\r
66         }\r
67         else\r
68         {\r
69           seqs = av.getSelectionGroup().getSequencesInOrder(av.alignment);\r
70         }\r
71         SeqCigar sq[]=seqstrings.getSequences();\r
72         int length = sq[0].getWidth();\r
73 \r
74         for (int i = 0; i < seqs.length; i++)\r
75         {\r
76           if (sq[i].getWidth() != length)\r
77           {\r
78             sameLength = false;\r
79             break;\r
80           }\r
81         }\r
82 \r
83         if (!sameLength)\r
84         {\r
85           JOptionPane.showMessageDialog(Desktop.desktop,\r
86                                         "The sequences must be aligned before calculating PCA.\n" +\r
87                                         "Try using the Pad function in the edit menu,\n" +\r
88                                         "or one of the multiple sequence alignment web services.",\r
89                                         "Sequences not aligned",\r
90                                         JOptionPane.WARNING_MESSAGE);\r
91 \r
92           return;\r
93         }\r
94 \r
95 \r
96         Desktop.addInternalFrame(this, "Principal component analysis",\r
97                                400, 400);\r
98 \r
99 \r
100         rc = new RotatableCanvas(av);\r
101         this.getContentPane().add(rc, BorderLayout.CENTER);\r
102         Thread worker = new Thread(this);\r
103         worker.start();\r
104     }\r
105 \r
106     public void bgcolour_actionPerformed(ActionEvent e)\r
107     {\r
108       Color col = JColorChooser.showDialog(this, "Select Background Colour",\r
109                 rc.bgColour);\r
110 \r
111       if(col!=null)\r
112         rc.bgColour = col;\r
113       rc.repaint();\r
114     }\r
115 \r
116 \r
117 \r
118 \r
119     /**\r
120      * DOCUMENT ME!\r
121      */\r
122     public void run()\r
123     {\r
124       try{\r
125         pca = new PCA(seqstrings.getSequenceStrings(' '));\r
126         pca.run();\r
127 \r
128         // Now find the component coordinates\r
129         int ii = 0;\r
130 \r
131         while ( (ii < seqs.length) && (seqs[ii] != null))\r
132         {\r
133           ii++;\r
134         }\r
135 \r
136         double[][] comps = new double[ii][ii];\r
137 \r
138         for (int i = 0; i < ii; i++)\r
139         {\r
140           if (pca.getEigenvalue(i) > 1e-4)\r
141           {\r
142             comps[i] = pca.component(i);\r
143           }\r
144         }\r
145 \r
146         //////////////////\r
147         xCombobox.setSelectedIndex(0);\r
148         yCombobox.setSelectedIndex(1);\r
149         zCombobox.setSelectedIndex(2);\r
150 \r
151         top = pca.getM().rows - 1;\r
152 \r
153         Vector points = new Vector();\r
154         float[][] scores = pca.getComponents(top - 1, top - 2, top - 3, 100);\r
155 \r
156         for (int i = 0; i < pca.getM().rows; i++)\r
157         {\r
158           SequencePoint sp = new SequencePoint(seqs[i], scores[i]);\r
159           points.addElement(sp);\r
160         }\r
161 \r
162         rc.setPoints(points, pca.getM().rows);\r
163         rc.repaint();\r
164 \r
165         addKeyListener(rc);\r
166 \r
167       }\r
168      catch(OutOfMemoryError er)\r
169       { JOptionPane.showInternalMessageDialog(Desktop.desktop,\r
170                                               "Out of memory calculating PCA!!"\r
171                                               +\r
172                                               "\nSee help files for increasing Java Virtual Machine memory."\r
173                                               , "Out of memory",\r
174                                               JOptionPane.WARNING_MESSAGE);\r
175         System.out.println("PCAPanel: "+er);\r
176         System.gc();\r
177 \r
178       }\r
179 \r
180     }\r
181 \r
182     /**\r
183      * DOCUMENT ME!\r
184      */\r
185     void doDimensionChange()\r
186     {\r
187         if (top == 0)\r
188         {\r
189             return;\r
190         }\r
191 \r
192         int dim1 = top - xCombobox.getSelectedIndex();\r
193         int dim2 = top - yCombobox.getSelectedIndex();\r
194         int dim3 = top - zCombobox.getSelectedIndex();\r
195 \r
196         float[][] scores = pca.getComponents(dim1, dim2, dim3, 100);\r
197 \r
198         for (int i = 0; i < pca.getM().rows; i++)\r
199         {\r
200             ((SequencePoint) rc.points.elementAt(i)).coord = scores[i];\r
201         }\r
202 \r
203         rc.img = null;\r
204         rc.rotmat.setIdentity();\r
205         rc.initAxes();\r
206         rc.paint(rc.getGraphics());\r
207     }\r
208 \r
209     /**\r
210      * DOCUMENT ME!\r
211      *\r
212      * @param e DOCUMENT ME!\r
213      */\r
214     protected void xCombobox_actionPerformed(ActionEvent e)\r
215     {\r
216         doDimensionChange();\r
217     }\r
218 \r
219     /**\r
220      * DOCUMENT ME!\r
221      *\r
222      * @param e DOCUMENT ME!\r
223      */\r
224     protected void yCombobox_actionPerformed(ActionEvent e)\r
225     {\r
226         doDimensionChange();\r
227     }\r
228 \r
229     /**\r
230      * DOCUMENT ME!\r
231      *\r
232      * @param e DOCUMENT ME!\r
233      */\r
234     protected void zCombobox_actionPerformed(ActionEvent e)\r
235     {\r
236         doDimensionChange();\r
237     }\r
238 \r
239 \r
240     public void outputValues_actionPerformed(ActionEvent e)\r
241     {\r
242       CutAndPasteTransfer cap = new CutAndPasteTransfer();\r
243       Desktop.addInternalFrame(cap, "PCA details", 500,\r
244                 500);\r
245 \r
246       cap.setText(pca.getDetails());\r
247      }\r
248 \r
249     public void showLabels_actionPerformed(ActionEvent e)\r
250     {\r
251       rc.showLabels(showLabels.getState());\r
252     }\r
253 \r
254     public void print_actionPerformed(ActionEvent e)\r
255     {\r
256       PCAPrinter printer = new PCAPrinter();\r
257       printer.start();\r
258     }\r
259 \r
260     public void originalSeqData_actionPerformed(ActionEvent e)\r
261     {\r
262       // this was cut'n'pasted from the equivalent TreePanel method - we should make this an abstract function of all jalview analysis windows\r
263       if (seqstrings==null)\r
264       {\r
265         jalview.bin.Cache.log.info("Unexpected call to originalSeqData_actionPerformed - should have hidden this menu action.");\r
266         return;\r
267       }\r
268       // decide if av alignment is sufficiently different to original data to warrant a new window to be created\r
269       // create new alignmnt window with hidden regions (unhiding hidden regions yields unaligned seqs)\r
270       // or create a selection box around columns in alignment view\r
271       // test Alignment(SeqCigar[])\r
272       Object[] alAndColsel = seqstrings.getAlignmentAndColumnSelection(av.\r
273           getGapCharacter());\r
274 \r
275 \r
276       if (alAndColsel != null && alAndColsel[0]!=null)\r
277       {\r
278           // AlignmentOrder origorder = new AlignmentOrder(alAndColsel[0]);\r
279 \r
280           Alignment al = new Alignment((SequenceI[]) alAndColsel[0]);\r
281           Alignment dataset = av.getAlignment().getDataset();\r
282           if (dataset != null)\r
283           {\r
284             al.setDataset(dataset);\r
285           }\r
286 \r
287           if (true)\r
288           {\r
289               // make a new frame!\r
290               AlignFrame af = new AlignFrame(al, (ColumnSelection) alAndColsel[1],\r
291                                            AlignFrame.DEFAULT_WIDTH,\r
292                                            AlignFrame.DEFAULT_HEIGHT\r
293 );\r
294 \r
295               //>>>This is a fix for the moment, until a better solution is found!!<<<\r
296               // af.getFeatureRenderer().transferSettings(alignFrame.getFeatureRenderer());\r
297 \r
298               //           af.addSortByOrderMenuItem(ServiceName + " Ordering",\r
299               //                                     msaorder);\r
300 \r
301               Desktop.addInternalFrame(af, "Original Data for " + this.title,\r
302                                        AlignFrame.DEFAULT_WIDTH,\r
303                                        AlignFrame.DEFAULT_HEIGHT);\r
304             }\r
305           }\r
306           /*      CutAndPasteTransfer cap = new CutAndPasteTransfer();\r
307                  for (int i = 0; i < seqs.length; i++)\r
308                  {\r
309                    cap.appendText(new jalview.util.Format("%-" + 15 + "s").form(\r
310             seqs[i].getName()));\r
311                    cap.appendText(" " + seqstrings[i] + "\n");\r
312 \r
313                  }\r
314 \r
315                  Desktop.addInternalFrame(cap, "Original Data",\r
316                      400, 400);\r
317            */\r
318     }\r
319 \r
320 \r
321 \r
322     class PCAPrinter extends Thread implements Printable\r
323     {\r
324       public void run()\r
325       {\r
326         PrinterJob printJob = PrinterJob.getPrinterJob();\r
327         PageFormat pf = printJob.pageDialog(printJob.defaultPage());\r
328 \r
329         printJob.setPrintable(this, pf);\r
330 \r
331         if (printJob.printDialog())\r
332         {\r
333           try\r
334           {\r
335             printJob.print();\r
336           }\r
337           catch (Exception PrintException)\r
338           {\r
339             PrintException.printStackTrace();\r
340           }\r
341         }\r
342       }\r
343 \r
344       public int print(Graphics pg, PageFormat pf, int pi)\r
345           throws PrinterException\r
346       {\r
347         pg.translate( (int) pf.getImageableX(), (int) pf.getImageableY());\r
348 \r
349         rc.drawBackground(pg, rc.bgColour);\r
350         rc.drawScene(pg);\r
351         if (rc.drawAxes == true)\r
352         {\r
353           rc.drawAxes(pg);\r
354         }\r
355 \r
356         if (pi == 0)\r
357           return Printable.PAGE_EXISTS;\r
358         else\r
359           return Printable.NO_SUCH_PAGE;\r
360       }\r
361     }\r
362 \r
363 \r
364 \r
365     /**\r
366      * DOCUMENT ME!\r
367      *\r
368      * @param e DOCUMENT ME!\r
369      */\r
370     public void eps_actionPerformed(ActionEvent e)\r
371     {\r
372       makePCAImage(jalview.util.ImageMaker.EPS);\r
373     }\r
374 \r
375     /**\r
376      * DOCUMENT ME!\r
377      *\r
378      * @param e DOCUMENT ME!\r
379      */\r
380     public void png_actionPerformed(ActionEvent e)\r
381     {\r
382        makePCAImage(jalview.util.ImageMaker.PNG);\r
383     }\r
384 \r
385     void makePCAImage(int type)\r
386     {\r
387       int width = rc.getWidth();\r
388       int height = rc.getHeight();\r
389 \r
390       jalview.util.ImageMaker im;\r
391 \r
392       if(type == jalview.util.ImageMaker.PNG)\r
393         im = new jalview.util.ImageMaker(this,\r
394                                          jalview.util.ImageMaker.PNG,\r
395                                          "Make PNG image from PCA",\r
396                                          width, height,\r
397                                          null, null);\r
398         else\r
399           im = new jalview.util.ImageMaker(this,\r
400                                  jalview.util.ImageMaker.EPS,\r
401                                  "Make EPS file from PCA",\r
402                                  width, height,\r
403                                  null, this.getTitle());\r
404 \r
405       if(im.getGraphics()!=null)\r
406        {\r
407          rc.drawBackground(im.getGraphics(), Color.black);\r
408          rc.drawScene(im.getGraphics());\r
409          if (rc.drawAxes == true)\r
410          {\r
411            rc.drawAxes(im.getGraphics());\r
412          }\r
413          im.writeImage();\r
414        }\r
415     }\r
416   }\r