Sequences must be aligned before PCA
[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.JOptionPane;\r
32 import javax.swing.JInternalFrame;\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         JInternalFrame frame = new JInternalFrame();\r
106         frame.setContentPane(this);\r
107         Desktop.addInternalFrame(frame, "Principal component analysis",\r
108                                400, 400);\r
109 \r
110 \r
111         rc = new RotatableCanvas(av);\r
112         add(rc, BorderLayout.CENTER);\r
113         Thread worker = new Thread(this);\r
114         worker.start();\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(seqs);\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         seqs = null;\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