Class |
Line # |
Actions |
|||
---|---|---|---|---|---|
PCAPanel | 51 | 149 | 33 |
1 | /* | |
2 | * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$) | |
3 | * Copyright (C) $$Year-Rel$$ The Jalview Authors | |
4 | * | |
5 | * This file is part of Jalview. | |
6 | * | |
7 | * Jalview is free software: you can redistribute it and/or | |
8 | * modify it under the terms of the GNU General Public License | |
9 | * as published by the Free Software Foundation, either version 3 | |
10 | * of the License, or (at your option) any later version. | |
11 | * | |
12 | * Jalview is distributed in the hope that it will be useful, but | |
13 | * WITHOUT ANY WARRANTY; without even the implied warranty | |
14 | * of MERCHANTABILITY or FITNESS FOR A PARTICULAR | |
15 | * PURPOSE. See the GNU General Public License for more details. | |
16 | * | |
17 | * You should have received a copy of the GNU General Public License | |
18 | * along with Jalview. If not, see <http://www.gnu.org/licenses/>. | |
19 | * The Jalview Authors are detailed in the 'AUTHORS' file. | |
20 | */ | |
21 | package jalview.appletgui; | |
22 | ||
23 | import jalview.analysis.scoremodels.ScoreModels; | |
24 | import jalview.analysis.scoremodels.SimilarityParams; | |
25 | import jalview.api.analysis.ScoreModelI; | |
26 | import jalview.datamodel.Alignment; | |
27 | import jalview.datamodel.AlignmentView; | |
28 | import jalview.datamodel.HiddenColumns; | |
29 | import jalview.datamodel.SeqCigar; | |
30 | import jalview.datamodel.SequenceI; | |
31 | import jalview.util.MessageManager; | |
32 | import jalview.viewmodel.PCAModel; | |
33 | ||
34 | import java.awt.BorderLayout; | |
35 | import java.awt.Button; | |
36 | import java.awt.CheckboxMenuItem; | |
37 | import java.awt.Choice; | |
38 | import java.awt.Color; | |
39 | import java.awt.FlowLayout; | |
40 | import java.awt.Frame; | |
41 | import java.awt.Label; | |
42 | import java.awt.Menu; | |
43 | import java.awt.MenuBar; | |
44 | import java.awt.MenuItem; | |
45 | import java.awt.Panel; | |
46 | import java.awt.event.ActionEvent; | |
47 | import java.awt.event.ActionListener; | |
48 | import java.awt.event.ItemEvent; | |
49 | import java.awt.event.ItemListener; | |
50 | ||
51 | public class PCAPanel extends EmbmenuFrame | |
52 | implements Runnable, ActionListener, ItemListener | |
53 | { | |
54 | RotatableCanvas rc; | |
55 | ||
56 | AlignViewport av; | |
57 | ||
58 | PCAModel pcaModel; | |
59 | ||
60 | int top = 0; | |
61 | ||
62 | 0 | public PCAPanel(AlignViewport viewport) |
63 | { | |
64 | 0 | try |
65 | { | |
66 | 0 | jbInit(); |
67 | } catch (Exception e) | |
68 | { | |
69 | 0 | e.printStackTrace(); |
70 | } | |
71 | ||
72 | 0 | for (int i = 1; i < 8; i++) |
73 | { | |
74 | 0 | xCombobox.addItem("dim " + i); |
75 | 0 | yCombobox.addItem("dim " + i); |
76 | 0 | zCombobox.addItem("dim " + i); |
77 | } | |
78 | ||
79 | 0 | this.av = viewport; |
80 | 0 | boolean selected = viewport.getSelectionGroup() != null |
81 | && viewport.getSelectionGroup().getSize() > 0; | |
82 | 0 | AlignmentView seqstrings = viewport.getAlignmentView(selected); |
83 | 0 | boolean nucleotide = viewport.getAlignment().isNucleotide(); |
84 | 0 | SequenceI[] seqs; |
85 | 0 | if (!selected) |
86 | { | |
87 | 0 | seqs = viewport.getAlignment().getSequencesArray(); |
88 | } | |
89 | else | |
90 | { | |
91 | 0 | seqs = viewport.getSelectionGroup() |
92 | .getSequencesInOrder(viewport.getAlignment()); | |
93 | } | |
94 | 0 | SeqCigar sq[] = seqstrings.getSequences(); |
95 | 0 | int length = sq[0].getWidth(); |
96 | ||
97 | 0 | for (int i = 0; i < seqs.length; i++) |
98 | { | |
99 | 0 | if (sq[i].getWidth() != length) |
100 | { | |
101 | 0 | System.out |
102 | .println("Sequences must be equal length for PCA analysis"); | |
103 | 0 | return; |
104 | } | |
105 | } | |
106 | ||
107 | 0 | ScoreModelI scoreModel = ScoreModels.getInstance() |
108 | .getDefaultModel(!nucleotide); | |
109 | 0 | pcaModel = new PCAModel(seqstrings, seqs, nucleotide, scoreModel, |
110 | SimilarityParams.SeqSpace); | |
111 | ||
112 | 0 | rc = new RotatableCanvas(viewport); |
113 | 0 | embedMenuIfNeeded(rc); |
114 | 0 | add(rc, BorderLayout.CENTER); |
115 | ||
116 | 0 | jalview.bin.JalviewLite.addFrame(this, |
117 | MessageManager.getString("label.principal_component_analysis"), | |
118 | 475, 400); | |
119 | ||
120 | 0 | Thread worker = new Thread(this); |
121 | 0 | worker.start(); |
122 | } | |
123 | ||
124 | /** | |
125 | * DOCUMENT ME! | |
126 | */ | |
127 | 0 | @Override |
128 | public void run() | |
129 | { | |
130 | // TODO progress indicator | |
131 | 0 | calcSettings.setEnabled(false); |
132 | 0 | rc.setEnabled(false); |
133 | 0 | try |
134 | { | |
135 | 0 | nuclSetting.setState(pcaModel.isNucleotide()); |
136 | 0 | protSetting.setState(!pcaModel.isNucleotide()); |
137 | 0 | pcaModel.calculate(); |
138 | // //////////////// | |
139 | 0 | xCombobox.select(0); |
140 | 0 | yCombobox.select(1); |
141 | 0 | zCombobox.select(2); |
142 | ||
143 | 0 | pcaModel.updateRc(rc); |
144 | // rc.invalidate(); | |
145 | 0 | top = pcaModel.getTop(); |
146 | } catch (OutOfMemoryError x) | |
147 | { | |
148 | 0 | jalview.bin.Console.errPrintln("Out of memory when calculating PCA."); |
149 | 0 | return; |
150 | } | |
151 | 0 | calcSettings.setEnabled(true); |
152 | ||
153 | // TODO revert progress indicator | |
154 | 0 | rc.setEnabled(true); |
155 | 0 | rc.repaint(); |
156 | 0 | this.repaint(); |
157 | } | |
158 | ||
159 | 0 | void doDimensionChange() |
160 | { | |
161 | 0 | if (top == 0) |
162 | { | |
163 | 0 | return; |
164 | } | |
165 | ||
166 | 0 | int dim1 = top - xCombobox.getSelectedIndex(); |
167 | 0 | int dim2 = top - yCombobox.getSelectedIndex(); |
168 | 0 | int dim3 = top - zCombobox.getSelectedIndex(); |
169 | 0 | pcaModel.updateRcView(dim1, dim2, dim3); |
170 | 0 | rc.resetView(); |
171 | 0 | rc.paint(rc.getGraphics()); |
172 | } | |
173 | ||
174 | 0 | @Override |
175 | public void actionPerformed(ActionEvent evt) | |
176 | { | |
177 | 0 | if (evt.getSource() == inputData) |
178 | { | |
179 | 0 | showOriginalData(); |
180 | } | |
181 | 0 | if (evt.getSource() == resetButton) |
182 | { | |
183 | 0 | xCombobox.select(0); |
184 | 0 | yCombobox.select(1); |
185 | 0 | zCombobox.select(2); |
186 | 0 | doDimensionChange(); |
187 | } | |
188 | 0 | if (evt.getSource() == values) |
189 | { | |
190 | 0 | values_actionPerformed(); |
191 | } | |
192 | } | |
193 | ||
194 | 0 | @Override |
195 | public void itemStateChanged(ItemEvent evt) | |
196 | { | |
197 | 0 | if (evt.getSource() == xCombobox) |
198 | { | |
199 | 0 | xCombobox_actionPerformed(); |
200 | } | |
201 | 0 | else if (evt.getSource() == yCombobox) |
202 | { | |
203 | 0 | yCombobox_actionPerformed(); |
204 | } | |
205 | 0 | else if (evt.getSource() == zCombobox) |
206 | { | |
207 | 0 | zCombobox_actionPerformed(); |
208 | } | |
209 | 0 | else if (evt.getSource() == labels) |
210 | { | |
211 | 0 | labels_itemStateChanged(evt); |
212 | } | |
213 | 0 | else if (evt.getSource() == nuclSetting) |
214 | { | |
215 | 0 | if (!pcaModel.isNucleotide()) |
216 | { | |
217 | 0 | pcaModel.setNucleotide(true); |
218 | 0 | ScoreModelI scoreModel = ScoreModels.getInstance() |
219 | .getDefaultModel(false); | |
220 | 0 | pcaModel.setScoreModel(scoreModel); |
221 | 0 | new Thread(this).start(); |
222 | } | |
223 | } | |
224 | 0 | else if (evt.getSource() == protSetting) |
225 | { | |
226 | 0 | if (pcaModel.isNucleotide()) |
227 | { | |
228 | 0 | pcaModel.setNucleotide(false); |
229 | 0 | ScoreModelI scoreModel = ScoreModels.getInstance() |
230 | .getDefaultModel(true); | |
231 | 0 | pcaModel.setScoreModel(scoreModel); |
232 | 0 | new Thread(this).start(); |
233 | } | |
234 | } | |
235 | } | |
236 | ||
237 | 0 | protected void xCombobox_actionPerformed() |
238 | { | |
239 | 0 | doDimensionChange(); |
240 | } | |
241 | ||
242 | 0 | protected void yCombobox_actionPerformed() |
243 | { | |
244 | 0 | doDimensionChange(); |
245 | } | |
246 | ||
247 | 0 | protected void zCombobox_actionPerformed() |
248 | { | |
249 | 0 | doDimensionChange(); |
250 | } | |
251 | ||
252 | 0 | public void values_actionPerformed() |
253 | { | |
254 | ||
255 | 0 | CutAndPasteTransfer cap = new CutAndPasteTransfer(false, null); |
256 | 0 | Frame frame = new Frame(); |
257 | 0 | frame.add(cap); |
258 | 0 | jalview.bin.JalviewLite.addFrame(frame, |
259 | MessageManager.getString("label.pca_details"), 500, 500); | |
260 | ||
261 | 0 | cap.setText(pcaModel.getDetails()); |
262 | } | |
263 | ||
264 | 0 | void showOriginalData() |
265 | { | |
266 | // decide if av alignment is sufficiently different to original data to | |
267 | // warrant a new window to be created | |
268 | // create new alignmnt window with hidden regions (unhiding hidden regions | |
269 | // yields unaligned seqs) | |
270 | // or create a selection box around columns in alignment view | |
271 | // test Alignment(SeqCigar[]) | |
272 | 0 | char gc = '-'; |
273 | 0 | try |
274 | { | |
275 | // we try to get the associated view's gap character | |
276 | // but this may fail if the view was closed... | |
277 | 0 | gc = av.getGapCharacter(); |
278 | } catch (Exception ex) | |
279 | { | |
280 | } | |
281 | 0 | ; |
282 | 0 | Object[] alAndColsel = pcaModel.getInputData() |
283 | .getAlignmentAndHiddenColumns(gc); | |
284 | ||
285 | 0 | if (alAndColsel != null && alAndColsel[0] != null) |
286 | { | |
287 | 0 | Alignment al = new Alignment((SequenceI[]) alAndColsel[0]); |
288 | 0 | AlignFrame af = new AlignFrame(al, av.applet, "Original Data for PCA", |
289 | false); | |
290 | ||
291 | 0 | af.viewport.getAlignment() |
292 | .setHiddenColumns((HiddenColumns) alAndColsel[1]); | |
293 | } | |
294 | } | |
295 | ||
296 | 0 | public void labels_itemStateChanged(ItemEvent itemEvent) |
297 | { | |
298 | 0 | rc.showLabels(labels.getState()); |
299 | } | |
300 | ||
301 | Panel jPanel2 = new Panel(); | |
302 | ||
303 | Label jLabel1 = new Label(); | |
304 | ||
305 | Label jLabel2 = new Label(); | |
306 | ||
307 | Label jLabel3 = new Label(); | |
308 | ||
309 | protected Choice xCombobox = new Choice(); | |
310 | ||
311 | protected Choice yCombobox = new Choice(); | |
312 | ||
313 | protected Choice zCombobox = new Choice(); | |
314 | ||
315 | protected Button resetButton = new Button(); | |
316 | ||
317 | FlowLayout flowLayout1 = new FlowLayout(); | |
318 | ||
319 | BorderLayout borderLayout1 = new BorderLayout(); | |
320 | ||
321 | MenuBar menuBar1 = new MenuBar(); | |
322 | ||
323 | Menu menu1 = new Menu(); | |
324 | ||
325 | Menu menu2 = new Menu(); | |
326 | ||
327 | Menu calcSettings = new Menu(); | |
328 | ||
329 | protected CheckboxMenuItem labels = new CheckboxMenuItem(); | |
330 | ||
331 | protected CheckboxMenuItem protSetting = new CheckboxMenuItem(); | |
332 | ||
333 | protected CheckboxMenuItem nuclSetting = new CheckboxMenuItem(); | |
334 | ||
335 | MenuItem values = new MenuItem(); | |
336 | ||
337 | MenuItem inputData = new MenuItem(); | |
338 | ||
339 | 0 | private void jbInit() throws Exception |
340 | { | |
341 | 0 | this.setLayout(borderLayout1); |
342 | 0 | jPanel2.setLayout(flowLayout1); |
343 | 0 | jLabel1.setFont(new java.awt.Font("Verdana", 0, 12)); |
344 | 0 | jLabel1.setText("x="); |
345 | 0 | jLabel2.setFont(new java.awt.Font("Verdana", 0, 12)); |
346 | 0 | jLabel2.setText("y="); |
347 | 0 | jLabel3.setFont(new java.awt.Font("Verdana", 0, 12)); |
348 | 0 | jLabel3.setText("z="); |
349 | 0 | jPanel2.setBackground(Color.white); |
350 | 0 | zCombobox.setFont(new java.awt.Font("Verdana", 0, 12)); |
351 | 0 | zCombobox.addItemListener(this); |
352 | 0 | yCombobox.setFont(new java.awt.Font("Verdana", 0, 12)); |
353 | 0 | yCombobox.addItemListener(this); |
354 | 0 | xCombobox.setFont(new java.awt.Font("Verdana", 0, 12)); |
355 | 0 | xCombobox.addItemListener(this); |
356 | 0 | resetButton.setFont(new java.awt.Font("Verdana", 0, 12)); |
357 | 0 | resetButton.setLabel(MessageManager.getString("action.reset")); |
358 | 0 | resetButton.addActionListener(this); |
359 | 0 | this.setMenuBar(menuBar1); |
360 | 0 | menu1.setLabel(MessageManager.getString("action.file")); |
361 | 0 | menu2.setLabel(MessageManager.getString("action.view")); |
362 | 0 | calcSettings.setLabel(MessageManager.getString("action.change_params")); |
363 | 0 | labels.setLabel(MessageManager.getString("label.labels")); |
364 | 0 | labels.addItemListener(this); |
365 | 0 | values.setLabel(MessageManager.getString("label.output_values")); |
366 | 0 | values.addActionListener(this); |
367 | 0 | inputData.setLabel(MessageManager.getString("label.input_data")); |
368 | 0 | nuclSetting |
369 | .setLabel(MessageManager.getString("label.nucleotide_matrix")); | |
370 | 0 | nuclSetting.addItemListener(this); |
371 | 0 | protSetting.setLabel(MessageManager.getString("label.protein_matrix")); |
372 | 0 | protSetting.addItemListener(this); |
373 | 0 | this.add(jPanel2, BorderLayout.SOUTH); |
374 | 0 | jPanel2.add(jLabel1, null); |
375 | 0 | jPanel2.add(xCombobox, null); |
376 | 0 | jPanel2.add(jLabel2, null); |
377 | 0 | jPanel2.add(yCombobox, null); |
378 | 0 | jPanel2.add(jLabel3, null); |
379 | 0 | jPanel2.add(zCombobox, null); |
380 | 0 | jPanel2.add(resetButton, null); |
381 | 0 | menuBar1.add(menu1); |
382 | 0 | menuBar1.add(menu2); |
383 | 0 | menuBar1.add(calcSettings); |
384 | 0 | menu2.add(labels); |
385 | 0 | menu1.add(values); |
386 | 0 | menu1.add(inputData); |
387 | 0 | calcSettings.add(nuclSetting); |
388 | 0 | calcSettings.add(protSetting); |
389 | 0 | inputData.addActionListener(this); |
390 | } | |
391 | ||
392 | } |