recovery of identical dataset sequence object on undo (rather than creation of a...
[jalview.git] / src / jalview / appletgui / PCAPanel.java
1 /*\r
2  * Jalview - A Sequence Alignment Editor and Viewer\r
3  * Copyright (C) 2007 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 \r
20 package jalview.appletgui;\r
21 \r
22 import java.util.*;\r
23 \r
24 import java.awt.*;\r
25 import java.awt.event.*;\r
26 \r
27 import jalview.analysis.*;\r
28 import jalview.datamodel.*;\r
29 \r
30 public class PCAPanel\r
31     extends Frame implements Runnable, ActionListener, ItemListener\r
32 {\r
33   PCA pca;\r
34   int top;\r
35   RotatableCanvas rc;\r
36   AlignViewport av;\r
37   SequenceI[] seqs;\r
38   AlignmentView seqstrings;\r
39 \r
40   public PCAPanel(AlignViewport av)\r
41   {\r
42     try\r
43     {\r
44       jbInit();\r
45     }\r
46     catch (Exception e)\r
47     {\r
48       e.printStackTrace();\r
49     }\r
50 \r
51     for (int i = 1; i < 8; i++)\r
52     {\r
53       xCombobox.addItem("dim " + i);\r
54       yCombobox.addItem("dim " + i);\r
55       zCombobox.addItem("dim " + i);\r
56     }\r
57 \r
58     this.av = av;\r
59     seqstrings = av.getAlignmentView(av.getSelectionGroup() != null);\r
60     if (av.getSelectionGroup() == null)\r
61     {\r
62       seqs = av.alignment.getSequencesArray();\r
63     }\r
64     else\r
65     {\r
66       seqs = av.getSelectionGroup().getSequencesInOrder(av.alignment);\r
67     }\r
68     SeqCigar sq[] = seqstrings.getSequences();\r
69     int length = sq[0].getWidth();\r
70 \r
71     for (int i = 0; i < seqs.length; i++)\r
72     {\r
73       if (sq[i].getWidth() != length)\r
74       {\r
75         System.out.println("Sequences must be equal length for PCA analysis");\r
76         return;\r
77       }\r
78     }\r
79 \r
80     rc = new RotatableCanvas(av);\r
81     add(rc, BorderLayout.CENTER);\r
82 \r
83     jalview.bin.JalviewLite.addFrame(this, "Principal component analysis",\r
84                                      400, 400);\r
85 \r
86     Thread worker = new Thread(this);\r
87     worker.start();\r
88   }\r
89 \r
90   /**\r
91    * DOCUMENT ME!\r
92    */\r
93   public void run()\r
94   {\r
95     pca = new PCA(seqstrings.getSequenceStrings(' '));\r
96     pca.run();\r
97 \r
98     // Now find the component coordinates\r
99     int ii = 0;\r
100 \r
101     while ( (ii < seqs.length) && (seqs[ii] != null))\r
102     {\r
103       ii++;\r
104     }\r
105 \r
106     double[][] comps = new double[ii][ii];\r
107 \r
108     for (int i = 0; i < ii; i++)\r
109     {\r
110       if (pca.getEigenvalue(i) > 1e-4)\r
111       {\r
112         comps[i] = pca.component(i);\r
113       }\r
114     }\r
115 \r
116     //////////////////\r
117     xCombobox.select(0);\r
118     yCombobox.select(1);\r
119     zCombobox.select(2);\r
120 \r
121     top = pca.getM().rows - 1;\r
122 \r
123     Vector points = new Vector();\r
124     float[][] scores = pca.getComponents(top - 1, top - 2, top - 3, 100);\r
125 \r
126     for (int i = 0; i < pca.getM().rows; i++)\r
127     {\r
128       SequencePoint sp = new SequencePoint(seqs[i], scores[i]);\r
129       points.addElement(sp);\r
130     }\r
131 \r
132     rc.setPoints(points, pca.getM().rows);\r
133     rc.repaint();\r
134     seqs = null;\r
135     this.repaint();\r
136   }\r
137 \r
138   void doDimensionChange()\r
139   {\r
140     if (top == 0)\r
141     {\r
142       return;\r
143     }\r
144 \r
145     int dim1 = top - xCombobox.getSelectedIndex();\r
146     int dim2 = top - yCombobox.getSelectedIndex();\r
147     int dim3 = top - zCombobox.getSelectedIndex();\r
148 \r
149     float[][] scores = pca.getComponents(dim1, dim2, dim3, 100);\r
150     for (int i = 0; i < pca.getM().rows; i++)\r
151     {\r
152       ( (SequencePoint) rc.points.elementAt(i)).coord = scores[i];\r
153     }\r
154 \r
155     rc.img = null;\r
156     rc.rotmat.setIdentity();\r
157     rc.initAxes();\r
158     rc.paint(rc.getGraphics());\r
159   }\r
160 \r
161   public void actionPerformed(ActionEvent evt)\r
162   {\r
163     if (evt.getSource() == inputData)\r
164     {\r
165       showOriginalData();\r
166     }\r
167     else\r
168     {\r
169       values_actionPerformed();\r
170     }\r
171   }\r
172 \r
173   public void itemStateChanged(ItemEvent evt)\r
174   {\r
175     if (evt.getSource() == xCombobox)\r
176     {\r
177       xCombobox_actionPerformed();\r
178     }\r
179     else if (evt.getSource() == yCombobox)\r
180     {\r
181       yCombobox_actionPerformed();\r
182     }\r
183     else if (evt.getSource() == zCombobox)\r
184     {\r
185       zCombobox_actionPerformed();\r
186     }\r
187   }\r
188 \r
189   protected void xCombobox_actionPerformed()\r
190   {\r
191     doDimensionChange();\r
192   }\r
193 \r
194   protected void yCombobox_actionPerformed()\r
195   {\r
196     doDimensionChange();\r
197   }\r
198 \r
199   protected void zCombobox_actionPerformed()\r
200   {\r
201     doDimensionChange();\r
202   }\r
203 \r
204   public void values_actionPerformed()\r
205   {\r
206 \r
207     CutAndPasteTransfer cap = new CutAndPasteTransfer(false, null);\r
208     Frame frame = new Frame();\r
209     frame.add(cap);\r
210     jalview.bin.JalviewLite.addFrame(frame, "PCA details", 500, 500);\r
211 \r
212     cap.setText(pca.getDetails());\r
213   }\r
214 \r
215   void showOriginalData()\r
216   {\r
217     // decide if av alignment is sufficiently different to original data to warrant a new window to be created\r
218     // create new alignmnt window with hidden regions (unhiding hidden regions yields unaligned seqs)\r
219     // or create a selection box around columns in alignment view\r
220     // test Alignment(SeqCigar[])\r
221     Object[] alAndColsel = seqstrings.getAlignmentAndColumnSelection(av.\r
222         getGapCharacter());\r
223 \r
224     if (alAndColsel != null && alAndColsel[0] != null)\r
225     {\r
226       Alignment al = new Alignment( (SequenceI[]) alAndColsel[0]);\r
227       AlignFrame af = new AlignFrame(al,\r
228                                      av.applet,\r
229                                      "Original Data for PCA",\r
230                                      false);\r
231 \r
232       af.viewport.setHiddenColumns( (ColumnSelection) alAndColsel[1]);\r
233     }\r
234   }\r
235 \r
236   public void labels_itemStateChanged(ItemEvent itemEvent)\r
237   {\r
238     rc.showLabels(labels.getState());\r
239   }\r
240 \r
241   Panel jPanel2 = new Panel();\r
242   Label jLabel1 = new Label();\r
243   Label jLabel2 = new Label();\r
244   Label jLabel3 = new Label();\r
245   protected Choice xCombobox = new Choice();\r
246   protected Choice yCombobox = new Choice();\r
247   protected Choice zCombobox = new Choice();\r
248   FlowLayout flowLayout1 = new FlowLayout();\r
249   BorderLayout borderLayout1 = new BorderLayout();\r
250   MenuBar menuBar1 = new MenuBar();\r
251   Menu menu1 = new Menu();\r
252   Menu menu2 = new Menu();\r
253   protected CheckboxMenuItem labels = new CheckboxMenuItem();\r
254   MenuItem values = new MenuItem();\r
255   MenuItem inputData = new MenuItem();\r
256 \r
257   private void jbInit()\r
258       throws Exception\r
259   {\r
260     this.setLayout(borderLayout1);\r
261     jPanel2.setLayout(flowLayout1);\r
262     jLabel1.setFont(new java.awt.Font("Verdana", 0, 12));\r
263     jLabel1.setText("x=");\r
264     jLabel2.setFont(new java.awt.Font("Verdana", 0, 12));\r
265     jLabel2.setText("y=");\r
266     jLabel3.setFont(new java.awt.Font("Verdana", 0, 12));\r
267     jLabel3.setText("z=");\r
268     jPanel2.setBackground(Color.white);\r
269     zCombobox.setFont(new java.awt.Font("Verdana", 0, 12));\r
270     zCombobox.addItemListener(this);\r
271     yCombobox.setFont(new java.awt.Font("Verdana", 0, 12));\r
272     yCombobox.addItemListener(this);\r
273     xCombobox.setFont(new java.awt.Font("Verdana", 0, 12));\r
274     xCombobox.addItemListener(this);\r
275     this.setMenuBar(menuBar1);\r
276     menu1.setLabel("File");\r
277     menu2.setLabel("View");\r
278     labels.setLabel("Labels");\r
279     labels.addItemListener(this);\r
280     values.setLabel("Output Values...");\r
281     values.addActionListener(this);\r
282     inputData.setLabel("Input Data...");\r
283     this.add(jPanel2, BorderLayout.SOUTH);\r
284     jPanel2.add(jLabel1, null);\r
285     jPanel2.add(xCombobox, null);\r
286     jPanel2.add(jLabel2, null);\r
287     jPanel2.add(yCombobox, null);\r
288     jPanel2.add(jLabel3, null);\r
289     jPanel2.add(zCombobox, null);\r
290     menuBar1.add(menu1);\r
291     menuBar1.add(menu2);\r
292     menu2.add(labels);\r
293     menu1.add(values);\r
294     menu1.add(inputData);\r
295     inputData.addActionListener(this);\r
296   }\r
297 \r
298 }\r