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