JAL-1517 fix copyright for 2.8.2
[jalview.git] / src / jalview / appletgui / PCAPanel.java
1 /*
2  * Jalview - A Sequence Alignment Editor and Viewer (Version 2.8.2)
3  * Copyright (C) 2014 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 java.awt.*;
24 import java.awt.event.*;
25
26 import jalview.datamodel.*;
27 import jalview.util.MessageManager;
28 import jalview.viewmodel.PCAModel;
29
30 public class PCAPanel extends EmbmenuFrame implements Runnable,
31         ActionListener, ItemListener
32 {
33   RotatableCanvas rc;
34
35   AlignViewport av;
36
37   PCAModel pcaModel;
38
39   int top = 0;
40
41   public PCAPanel(AlignViewport av)
42   {
43     try
44     {
45       jbInit();
46     } catch (Exception e)
47     {
48       e.printStackTrace();
49     }
50
51     for (int i = 1; i < 8; i++)
52     {
53       xCombobox.addItem("dim " + i);
54       yCombobox.addItem("dim " + i);
55       zCombobox.addItem("dim " + i);
56     }
57
58     this.av = av;
59     boolean selected = av.getSelectionGroup() != null
60             && av.getSelectionGroup().getSize() > 0;
61     AlignmentView seqstrings = av.getAlignmentView(selected);
62     boolean nucleotide = av.getAlignment().isNucleotide();
63     SequenceI[] seqs;
64     if (!selected)
65     {
66       seqs = av.getAlignment().getSequencesArray();
67     }
68     else
69     {
70       seqs = av.getSelectionGroup().getSequencesInOrder(av.getAlignment());
71     }
72     SeqCigar sq[] = seqstrings.getSequences();
73     int length = sq[0].getWidth();
74
75     for (int i = 0; i < seqs.length; i++)
76     {
77       if (sq[i].getWidth() != length)
78       {
79         System.out
80                 .println("Sequences must be equal length for PCA analysis");
81         return;
82       }
83     }
84     pcaModel = new PCAModel(seqstrings, seqs, nucleotide);
85
86     rc = new RotatableCanvas(av);
87     embedMenuIfNeeded(rc);
88     add(rc, BorderLayout.CENTER);
89
90     jalview.bin.JalviewLite.addFrame(this, MessageManager.getString("label.principal_component_analysis"),
91             475, 400);
92
93     Thread worker = new Thread(this);
94     worker.start();
95   }
96
97   /**
98    * DOCUMENT ME!
99    */
100   public void run()
101   {
102     // TODO progress indicator
103     calcSettings.setEnabled(false);
104     rc.setEnabled(false);
105     try
106     {
107       nuclSetting.setState(pcaModel.isNucleotide());
108       protSetting.setState(!pcaModel.isNucleotide());
109       pcaModel.run();
110       // ////////////////
111       xCombobox.select(0);
112       yCombobox.select(1);
113       zCombobox.select(2);
114
115       pcaModel.updateRc(rc);
116       // rc.invalidate();
117       top = pcaModel.getTop();
118     } catch (OutOfMemoryError x)
119     {
120       System.err.println("Out of memory when calculating PCA.");
121       return;
122     }
123     calcSettings.setEnabled(true);
124
125     // TODO revert progress indicator
126     rc.setEnabled(true);
127     rc.repaint();
128     this.repaint();
129   }
130
131   void doDimensionChange()
132   {
133     if (top == 0)
134     {
135       return;
136     }
137
138     int dim1 = top - xCombobox.getSelectedIndex();
139     int dim2 = top - yCombobox.getSelectedIndex();
140     int dim3 = top - zCombobox.getSelectedIndex();
141     pcaModel.updateRcView(dim1, dim2, dim3);
142     rc.img = null;
143     rc.rotmat.setIdentity();
144     rc.initAxes();
145     rc.paint(rc.getGraphics());
146   }
147
148   public void actionPerformed(ActionEvent evt)
149   {
150     if (evt.getSource() == inputData)
151     {
152       showOriginalData();
153     }
154     if (evt.getSource() == resetButton)
155     {
156       xCombobox.select(0);
157       yCombobox.select(1);
158       zCombobox.select(2);
159       doDimensionChange();
160     }
161     if (evt.getSource() == values)
162     {
163       values_actionPerformed();
164     }
165   }
166
167   public void itemStateChanged(ItemEvent evt)
168   {
169     if (evt.getSource() == xCombobox)
170     {
171       xCombobox_actionPerformed();
172     }
173     else if (evt.getSource() == yCombobox)
174     {
175       yCombobox_actionPerformed();
176     }
177     else if (evt.getSource() == zCombobox)
178     {
179       zCombobox_actionPerformed();
180     }
181     else if (evt.getSource() == labels)
182     {
183       labels_itemStateChanged(evt);
184     }
185     else if (evt.getSource() == nuclSetting)
186     {
187       if (!pcaModel.isNucleotide())
188       {
189         pcaModel.setNucleotide(true);
190         new Thread(this).start();
191       }
192     }
193     else if (evt.getSource() == protSetting)
194     {
195       if (pcaModel.isNucleotide())
196       {
197         pcaModel.setNucleotide(false);
198         new Thread(this).start();
199       }
200     }
201   }
202
203   protected void xCombobox_actionPerformed()
204   {
205     doDimensionChange();
206   }
207
208   protected void yCombobox_actionPerformed()
209   {
210     doDimensionChange();
211   }
212
213   protected void zCombobox_actionPerformed()
214   {
215     doDimensionChange();
216   }
217
218   public void values_actionPerformed()
219   {
220
221     CutAndPasteTransfer cap = new CutAndPasteTransfer(false, null);
222     Frame frame = new Frame();
223     frame.add(cap);
224     jalview.bin.JalviewLite.addFrame(frame, MessageManager.getString("label.pca_details"), 500, 500);
225
226     cap.setText(pcaModel.getDetails());
227   }
228
229   void showOriginalData()
230   {
231     // decide if av alignment is sufficiently different to original data to
232     // warrant a new window to be created
233     // create new alignmnt window with hidden regions (unhiding hidden regions
234     // yields unaligned seqs)
235     // or create a selection box around columns in alignment view
236     // test Alignment(SeqCigar[])
237     char gc = '-';
238     try
239     {
240       // we try to get the associated view's gap character
241       // but this may fail if the view was closed...
242       gc = av.getGapCharacter();
243     } catch (Exception ex)
244     {
245     }
246     ;
247     Object[] alAndColsel = pcaModel.getSeqtrings()
248             .getAlignmentAndColumnSelection(gc);
249
250     if (alAndColsel != null && alAndColsel[0] != null)
251     {
252       Alignment al = new Alignment((SequenceI[]) alAndColsel[0]);
253       AlignFrame af = new AlignFrame(al, av.applet,
254               "Original Data for PCA", false);
255
256       af.viewport.setHiddenColumns((ColumnSelection) alAndColsel[1]);
257     }
258   }
259
260   public void labels_itemStateChanged(ItemEvent itemEvent)
261   {
262     rc.showLabels(labels.getState());
263   }
264
265   Panel jPanel2 = new Panel();
266
267   Label jLabel1 = new Label();
268
269   Label jLabel2 = new Label();
270
271   Label jLabel3 = new Label();
272
273   protected Choice xCombobox = new Choice();
274
275   protected Choice yCombobox = new Choice();
276
277   protected Choice zCombobox = new Choice();
278
279   protected Button resetButton = new Button();
280
281   FlowLayout flowLayout1 = new FlowLayout();
282
283   BorderLayout borderLayout1 = new BorderLayout();
284
285   MenuBar menuBar1 = new MenuBar();
286
287   Menu menu1 = new Menu();
288
289   Menu menu2 = new Menu();
290
291   Menu calcSettings = new Menu();
292
293   protected CheckboxMenuItem labels = new CheckboxMenuItem();
294
295   protected CheckboxMenuItem protSetting = new CheckboxMenuItem();
296
297   protected CheckboxMenuItem nuclSetting = new CheckboxMenuItem();
298
299   MenuItem values = new MenuItem();
300
301   MenuItem inputData = new MenuItem();
302
303   private void jbInit() throws Exception
304   {
305     this.setLayout(borderLayout1);
306     jPanel2.setLayout(flowLayout1);
307     jLabel1.setFont(new java.awt.Font("Verdana", 0, 12));
308     jLabel1.setText("x=");
309     jLabel2.setFont(new java.awt.Font("Verdana", 0, 12));
310     jLabel2.setText("y=");
311     jLabel3.setFont(new java.awt.Font("Verdana", 0, 12));
312     jLabel3.setText("z=");
313     jPanel2.setBackground(Color.white);
314     zCombobox.setFont(new java.awt.Font("Verdana", 0, 12));
315     zCombobox.addItemListener(this);
316     yCombobox.setFont(new java.awt.Font("Verdana", 0, 12));
317     yCombobox.addItemListener(this);
318     xCombobox.setFont(new java.awt.Font("Verdana", 0, 12));
319     xCombobox.addItemListener(this);
320     resetButton.setFont(new java.awt.Font("Verdana", 0, 12));
321     resetButton.setLabel(MessageManager.getString("action.reset"));
322     resetButton.addActionListener(this);
323     this.setMenuBar(menuBar1);
324     menu1.setLabel(MessageManager.getString("action.file"));
325     menu2.setLabel(MessageManager.getString("action.view"));
326     calcSettings.setLabel(MessageManager.getString("action.change_params"));
327     labels.setLabel(MessageManager.getString("label.labels"));
328     labels.addItemListener(this);
329     values.setLabel(MessageManager.getString("label.output_values"));
330     values.addActionListener(this);
331     inputData.setLabel(MessageManager.getString("label.input_data"));
332     nuclSetting.setLabel(MessageManager.getString("label.nucleotide_matrix"));
333     nuclSetting.addItemListener(this);
334     protSetting.setLabel(MessageManager.getString("label.protein_matrix"));
335     protSetting.addItemListener(this);
336     this.add(jPanel2, BorderLayout.SOUTH);
337     jPanel2.add(jLabel1, null);
338     jPanel2.add(xCombobox, null);
339     jPanel2.add(jLabel2, null);
340     jPanel2.add(yCombobox, null);
341     jPanel2.add(jLabel3, null);
342     jPanel2.add(zCombobox, null);
343     jPanel2.add(resetButton, null);
344     menuBar1.add(menu1);
345     menuBar1.add(menu2);
346     menuBar1.add(calcSettings);
347     menu2.add(labels);
348     menu1.add(values);
349     menu1.add(inputData);
350     calcSettings.add(nuclSetting);
351     calcSettings.add(protSetting);
352     inputData.addActionListener(this);
353   }
354
355 }