2 * Jalview - A Sequence Alignment Editor and Viewer (Version 2.7)
3 * Copyright (C) 2011 J Procter, AM Waterhouse, J Engelhardt, LM Lui, G Barton, M Clamp, S Searle
5 * This file is part of Jalview.
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 of the License, or (at your option) any later version.
11 * Jalview is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty
13 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR
14 * PURPOSE. See the GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License along with Jalview. If not, see <http://www.gnu.org/licenses/>.
23 import java.awt.event.*;
24 import java.awt.print.*;
27 import jalview.analysis.*;
28 import jalview.datamodel.*;
29 import jalview.jbgui.*;
30 import jalview.viewmodel.PCAModel;
38 public class PCAPanel extends GPCAPanel implements Runnable, IProgressIndicator
51 * Creates a new PCAPanel object.
58 public PCAPanel(AlignmentPanel ap)
63 boolean sameLength = true;
65 AlignmentView seqstrings = av.getAlignmentView(av.getSelectionGroup() != null);
66 boolean nucleotide=av.getAlignment().isNucleotide();
68 if (av.getSelectionGroup() == null)
70 seqs = av.getAlignment().getSequencesArray();
74 seqs = av.getSelectionGroup().getSequencesInOrder(av.getAlignment());
76 SeqCigar sq[] = seqstrings.getSequences();
77 int length = sq[0].getWidth();
79 for (int i = 0; i < seqs.length; i++)
81 if (sq[i].getWidth() != length)
93 "The sequences must be aligned before calculating PCA.\n"
94 + "Try using the Pad function in the edit menu,\n"
95 + "or one of the multiple sequence alignment web services.",
96 "Sequences not aligned", JOptionPane.WARNING_MESSAGE);
100 pcaModel = new PCAModel(seqstrings, seqs, nucleotide);
101 PaintRefresher.Register(this, av.getSequenceSetId());
103 rc = new RotatableCanvas(ap);
104 this.getContentPane().add(rc, BorderLayout.CENTER);
105 Thread worker = new Thread(this);
109 public void bgcolour_actionPerformed(ActionEvent e)
111 Color col = JColorChooser.showDialog(this, "Select Background Colour",
126 long progId=System.currentTimeMillis();
127 IProgressIndicator progress=this;
128 String message="Recalculating PCA";
129 if (getParent()==null) {
130 progress=ap.alignFrame;
131 message = "Calculating PCA";
133 progress.setProgressBar(message, progId);
136 calcSettings.setEnabled(false);
139 xCombobox.setSelectedIndex(0);
140 yCombobox.setSelectedIndex(1);
141 zCombobox.setSelectedIndex(2);
143 pcaModel.updateRc(rc);
145 nuclSetting.setSelected(pcaModel.isNucleotide());
146 protSetting.setSelected(!pcaModel.isNucleotide());
147 top=pcaModel.getTop();
148 jvVersionSetting.setSelected(pcaModel.isJvCalcMode());
150 } catch (OutOfMemoryError er)
152 new OOMWarning("calculating PCA", er);
156 progress.setProgressBar("", progId);
158 calcSettings.setEnabled(true);
160 if (getParent()==null)
163 Desktop.addInternalFrame(this, "Principal component analysis", 475, 450);
167 protected void nuclSetting_actionPerfomed(ActionEvent arg0)
169 if (!pcaModel.isNucleotide())
171 pcaModel.setNucleotide(true);
172 Thread worker = new Thread(this);
178 protected void protSetting_actionPerfomed(ActionEvent arg0)
181 if (pcaModel.isNucleotide())
183 pcaModel.setNucleotide(false);
184 Thread worker = new Thread(this);
190 protected void jvVersionSetting_actionPerfomed(ActionEvent arg0)
192 pcaModel.setJvCalcMode(jvVersionSetting.isSelected());
193 Thread worker = new Thread(this);
200 void doDimensionChange()
207 int dim1 = top - xCombobox.getSelectedIndex();
208 int dim2 = top - yCombobox.getSelectedIndex();
209 int dim3 = top - zCombobox.getSelectedIndex();
210 pcaModel.updateRcView(dim1, dim2, dim3);
212 rc.rotmat.setIdentity();
214 rc.paint(rc.getGraphics());
223 protected void xCombobox_actionPerformed(ActionEvent e)
234 protected void yCombobox_actionPerformed(ActionEvent e)
245 protected void zCombobox_actionPerformed(ActionEvent e)
250 public void outputValues_actionPerformed(ActionEvent e)
252 CutAndPasteTransfer cap = new CutAndPasteTransfer();
255 cap.setText(pcaModel.getDetails());
256 Desktop.addInternalFrame(cap, "PCA details", 500, 500);
257 } catch (OutOfMemoryError oom)
259 new OOMWarning("opening PCA details", oom);
264 public void showLabels_actionPerformed(ActionEvent e)
266 rc.showLabels(showLabels.getState());
269 public void print_actionPerformed(ActionEvent e)
271 PCAPrinter printer = new PCAPrinter();
275 public void originalSeqData_actionPerformed(ActionEvent e)
277 // this was cut'n'pasted from the equivalent TreePanel method - we should
278 // make this an abstract function of all jalview analysis windows
279 if (pcaModel.getSeqtrings() == null)
281 jalview.bin.Cache.log
282 .info("Unexpected call to originalSeqData_actionPerformed - should have hidden this menu action.");
285 // decide if av alignment is sufficiently different to original data to
286 // warrant a new window to be created
287 // create new alignmnt window with hidden regions (unhiding hidden regions
288 // yields unaligned seqs)
289 // or create a selection box around columns in alignment view
290 // test Alignment(SeqCigar[])
294 // we try to get the associated view's gap character
295 // but this may fail if the view was closed...
296 gc = av.getGapCharacter();
297 } catch (Exception ex)
301 Object[] alAndColsel = pcaModel.getSeqtrings().getAlignmentAndColumnSelection(gc);
303 if (alAndColsel != null && alAndColsel[0] != null)
305 // AlignmentOrder origorder = new AlignmentOrder(alAndColsel[0]);
307 Alignment al = new Alignment((SequenceI[]) alAndColsel[0]);
308 Alignment dataset = (av != null && av.getAlignment() != null) ? av
309 .getAlignment().getDataset() : null;
312 al.setDataset(dataset);
318 AlignFrame af = new AlignFrame(al,
319 (ColumnSelection) alAndColsel[1], AlignFrame.DEFAULT_WIDTH,
320 AlignFrame.DEFAULT_HEIGHT);
322 // >>>This is a fix for the moment, until a better solution is
324 // af.getFeatureRenderer().transferSettings(alignFrame.getFeatureRenderer());
326 // af.addSortByOrderMenuItem(ServiceName + " Ordering",
329 Desktop.addInternalFrame(af, "Original Data for " + this.title,
330 AlignFrame.DEFAULT_WIDTH, AlignFrame.DEFAULT_HEIGHT);
334 * CutAndPasteTransfer cap = new CutAndPasteTransfer(); for (int i = 0; i <
335 * seqs.length; i++) { cap.appendText(new jalview.util.Format("%-" + 15 +
336 * "s").form( seqs[i].getName())); cap.appendText(" " + seqstrings[i] +
339 * Desktop.addInternalFrame(cap, "Original Data", 400, 400);
343 class PCAPrinter extends Thread implements Printable
347 PrinterJob printJob = PrinterJob.getPrinterJob();
348 PageFormat pf = printJob.pageDialog(printJob.defaultPage());
350 printJob.setPrintable(this, pf);
352 if (printJob.printDialog())
357 } catch (Exception PrintException)
359 PrintException.printStackTrace();
364 public int print(Graphics pg, PageFormat pf, int pi)
365 throws PrinterException
367 pg.translate((int) pf.getImageableX(), (int) pf.getImageableY());
369 rc.drawBackground(pg, rc.bgColour);
371 if (rc.drawAxes == true)
378 return Printable.PAGE_EXISTS;
382 return Printable.NO_SUCH_PAGE;
393 public void eps_actionPerformed(ActionEvent e)
395 makePCAImage(jalview.util.ImageMaker.EPS);
404 public void png_actionPerformed(ActionEvent e)
406 makePCAImage(jalview.util.ImageMaker.PNG);
409 void makePCAImage(int type)
411 int width = rc.getWidth();
412 int height = rc.getHeight();
414 jalview.util.ImageMaker im;
416 if (type == jalview.util.ImageMaker.PNG)
418 im = new jalview.util.ImageMaker(this, jalview.util.ImageMaker.PNG,
419 "Make PNG image from PCA", width, height, null, null);
423 im = new jalview.util.ImageMaker(this, jalview.util.ImageMaker.EPS,
424 "Make EPS file from PCA", width, height, null,
428 if (im.getGraphics() != null)
430 rc.drawBackground(im.getGraphics(), Color.black);
431 rc.drawScene(im.getGraphics());
432 if (rc.drawAxes == true)
434 rc.drawAxes(im.getGraphics());
440 public void viewMenu_menuSelected()
442 buildAssociatedViewMenu();
445 void buildAssociatedViewMenu()
447 AlignmentPanel[] aps = PaintRefresher.getAssociatedPanels(av
448 .getSequenceSetId());
449 if (aps.length == 1 && rc.av == aps[0].av)
451 associateViewsMenu.setVisible(false);
455 associateViewsMenu.setVisible(true);
457 if ((viewMenu.getItem(viewMenu.getItemCount() - 2) instanceof JMenuItem))
459 viewMenu.insertSeparator(viewMenu.getItemCount() - 1);
462 associateViewsMenu.removeAll();
464 JRadioButtonMenuItem item;
465 ButtonGroup buttonGroup = new ButtonGroup();
466 int i, iSize = aps.length;
467 final PCAPanel thisPCAPanel = this;
468 for (i = 0; i < iSize; i++)
470 final AlignmentPanel ap = aps[i];
471 item = new JRadioButtonMenuItem(ap.av.viewName, ap.av == rc.av);
472 buttonGroup.add(item);
473 item.addActionListener(new ActionListener()
475 public void actionPerformed(ActionEvent evt)
477 rc.applyToAllViews = false;
480 PaintRefresher.Register(thisPCAPanel, ap.av.getSequenceSetId());
484 associateViewsMenu.add(item);
487 final JRadioButtonMenuItem itemf = new JRadioButtonMenuItem("All Views");
489 buttonGroup.add(itemf);
491 itemf.setSelected(rc.applyToAllViews);
492 itemf.addActionListener(new ActionListener()
494 public void actionPerformed(ActionEvent evt)
496 rc.applyToAllViews = itemf.isSelected();
499 associateViewsMenu.add(itemf);
507 * jalview.jbgui.GPCAPanel#outputPoints_actionPerformed(java.awt.event.ActionEvent
510 protected void outputPoints_actionPerformed(ActionEvent e)
512 CutAndPasteTransfer cap = new CutAndPasteTransfer();
515 cap.setText(pcaModel.getPointsasCsv(false, xCombobox.getSelectedIndex(), yCombobox.getSelectedIndex(), zCombobox.getSelectedIndex()));
516 Desktop.addInternalFrame(cap, "Points for " + getTitle(), 500, 500);
517 } catch (OutOfMemoryError oom)
519 new OOMWarning("exporting PCA points", oom);
530 * jalview.jbgui.GPCAPanel#outputProjPoints_actionPerformed(java.awt.event
533 protected void outputProjPoints_actionPerformed(ActionEvent e)
535 CutAndPasteTransfer cap = new CutAndPasteTransfer();
538 cap.setText(pcaModel.getPointsasCsv(true, xCombobox.getSelectedIndex(), yCombobox.getSelectedIndex(), zCombobox.getSelectedIndex()));
539 Desktop.addInternalFrame(cap, "Transformed points for " + getTitle(),
541 } catch (OutOfMemoryError oom)
543 new OOMWarning("exporting transformed PCA points", oom);
548 // methods for implementing IProgressIndicator
549 // need to refactor to a reusable stub class
550 Hashtable progressBars, progressBarHandlers;
555 * @see jalview.gui.IProgressIndicator#setProgressBar(java.lang.String, long)
558 public void setProgressBar(String message, long id)
560 if (progressBars == null)
562 progressBars = new Hashtable();
563 progressBarHandlers = new Hashtable();
566 JPanel progressPanel;
567 Long lId = new Long(id);
568 GridLayout layout = (GridLayout) statusPanel.getLayout();
569 if (progressBars.get(lId) != null)
571 progressPanel = (JPanel) progressBars.get(new Long(id));
572 statusPanel.remove(progressPanel);
573 progressBars.remove(lId);
574 progressPanel = null;
577 statusBar.setText(message);
579 if (progressBarHandlers.contains(lId))
581 progressBarHandlers.remove(lId);
583 layout.setRows(layout.getRows() - 1);
587 progressPanel = new JPanel(new BorderLayout(10, 5));
589 JProgressBar progressBar = new JProgressBar();
590 progressBar.setIndeterminate(true);
592 progressPanel.add(new JLabel(message), BorderLayout.WEST);
593 progressPanel.add(progressBar, BorderLayout.CENTER);
595 layout.setRows(layout.getRows() + 1);
596 statusPanel.add(progressPanel);
598 progressBars.put(lId, progressPanel);
601 // setMenusForViewport();
606 public void registerHandler(final long id,
607 final IProgressIndicatorHandler handler)
609 if (progressBarHandlers == null || !progressBars.contains(new Long(id)))
612 "call setProgressBar before registering the progress bar's handler.");
614 progressBarHandlers.put(new Long(id), handler);
615 final JPanel progressPanel = (JPanel) progressBars.get(new Long(id));
616 if (handler.canCancel())
618 JButton cancel = new JButton("Cancel");
619 final IProgressIndicator us = this;
620 cancel.addActionListener(new ActionListener()
624 public void actionPerformed(ActionEvent e)
626 handler.cancelActivity(id);
629 + ((JLabel) progressPanel.getComponent(0))
633 progressPanel.add(cancel, BorderLayout.EAST);
639 * @return true if any progress bars are still active
642 public boolean operationInProgress()
644 if (progressBars != null && progressBars.size() > 0)
651 protected void resetButton_actionPerformed(ActionEvent e)
654 top=0; // ugly - prevents dimensionChanged events from being processed
655 xCombobox.setSelectedIndex(0);
656 yCombobox.setSelectedIndex(1);
658 zCombobox.setSelectedIndex(2);