2 * Jalview - A Sequence Alignment Editor and Viewer (Version 2.8)
3 * Copyright (C) 2012 J Procter, AM Waterhouse, LM Lui, J Engelhardt, 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.datamodel.*;
28 import jalview.jbgui.*;
29 import jalview.viewmodel.PCAModel;
37 public class PCAPanel extends GPCAPanel implements Runnable,
52 * Creates a new PCAPanel object.
59 public PCAPanel(AlignmentPanel ap)
64 boolean sameLength = true;
65 boolean selected = av.getSelectionGroup() != null
66 && av.getSelectionGroup().getSize() > 0;
67 AlignmentView seqstrings = av.getAlignmentView(selected);
68 boolean nucleotide = av.getAlignment().isNucleotide();
72 seqs = av.getAlignment().getSequencesArray();
76 seqs = av.getSelectionGroup().getSequencesInOrder(av.getAlignment());
78 SeqCigar sq[] = seqstrings.getSequences();
79 int length = sq[0].getWidth();
81 for (int i = 0; i < seqs.length; i++)
83 if (sq[i].getWidth() != length)
95 "The sequences must be aligned before calculating PCA.\n"
96 + "Try using the Pad function in the edit menu,\n"
97 + "or one of the multiple sequence alignment web services.",
98 "Sequences not aligned", JOptionPane.WARNING_MESSAGE);
102 pcaModel = new PCAModel(seqstrings, seqs, nucleotide);
103 PaintRefresher.Register(this, av.getSequenceSetId());
105 rc = new RotatableCanvas(ap);
106 this.getContentPane().add(rc, BorderLayout.CENTER);
107 Thread worker = new Thread(this);
111 public void bgcolour_actionPerformed(ActionEvent e)
113 Color col = JColorChooser.showDialog(this, "Select Background Colour",
128 long progId = System.currentTimeMillis();
129 IProgressIndicator progress = this;
130 String message = "Recalculating PCA";
131 if (getParent() == null)
133 progress = ap.alignFrame;
134 message = "Calculating PCA";
136 progress.setProgressBar(message, progId);
139 calcSettings.setEnabled(false);
142 xCombobox.setSelectedIndex(0);
143 yCombobox.setSelectedIndex(1);
144 zCombobox.setSelectedIndex(2);
146 pcaModel.updateRc(rc);
148 nuclSetting.setSelected(pcaModel.isNucleotide());
149 protSetting.setSelected(!pcaModel.isNucleotide());
150 jvVersionSetting.setSelected(pcaModel.isJvCalcMode());
151 top = pcaModel.getTop();
153 } catch (OutOfMemoryError er)
155 new OOMWarning("calculating PCA", er);
159 progress.setProgressBar("", progId);
161 calcSettings.setEnabled(true);
163 if (getParent() == null)
166 Desktop.addInternalFrame(this, "Principal component analysis", 475,
172 protected void nuclSetting_actionPerfomed(ActionEvent arg0)
174 if (!pcaModel.isNucleotide())
176 pcaModel.setNucleotide(true);
177 Thread worker = new Thread(this);
184 protected void protSetting_actionPerfomed(ActionEvent arg0)
187 if (pcaModel.isNucleotide())
189 pcaModel.setNucleotide(false);
190 Thread worker = new Thread(this);
196 protected void jvVersionSetting_actionPerfomed(ActionEvent arg0)
198 pcaModel.setJvCalcMode(jvVersionSetting.isSelected());
199 Thread worker = new Thread(this);
206 void doDimensionChange()
213 int dim1 = top - xCombobox.getSelectedIndex();
214 int dim2 = top - yCombobox.getSelectedIndex();
215 int dim3 = top - zCombobox.getSelectedIndex();
216 pcaModel.updateRcView(dim1, dim2, dim3);
218 rc.rotmat.setIdentity();
220 rc.paint(rc.getGraphics());
229 protected void xCombobox_actionPerformed(ActionEvent e)
240 protected void yCombobox_actionPerformed(ActionEvent e)
251 protected void zCombobox_actionPerformed(ActionEvent e)
256 public void outputValues_actionPerformed(ActionEvent e)
258 CutAndPasteTransfer cap = new CutAndPasteTransfer();
261 cap.setText(pcaModel.getDetails());
262 Desktop.addInternalFrame(cap, "PCA details", 500, 500);
263 } catch (OutOfMemoryError oom)
265 new OOMWarning("opening PCA details", oom);
270 public void showLabels_actionPerformed(ActionEvent e)
272 rc.showLabels(showLabels.getState());
275 public void print_actionPerformed(ActionEvent e)
277 PCAPrinter printer = new PCAPrinter();
281 public void originalSeqData_actionPerformed(ActionEvent e)
283 // this was cut'n'pasted from the equivalent TreePanel method - we should
284 // make this an abstract function of all jalview analysis windows
285 if (pcaModel.getSeqtrings() == null)
287 jalview.bin.Cache.log
288 .info("Unexpected call to originalSeqData_actionPerformed - should have hidden this menu action.");
291 // decide if av alignment is sufficiently different to original data to
292 // warrant a new window to be created
293 // create new alignmnt window with hidden regions (unhiding hidden regions
294 // yields unaligned seqs)
295 // or create a selection box around columns in alignment view
296 // test Alignment(SeqCigar[])
300 // we try to get the associated view's gap character
301 // but this may fail if the view was closed...
302 gc = av.getGapCharacter();
303 } catch (Exception ex)
307 Object[] alAndColsel = pcaModel.getSeqtrings()
308 .getAlignmentAndColumnSelection(gc);
310 if (alAndColsel != null && alAndColsel[0] != null)
312 // AlignmentOrder origorder = new AlignmentOrder(alAndColsel[0]);
314 Alignment al = new Alignment((SequenceI[]) alAndColsel[0]);
315 Alignment dataset = (av != null && av.getAlignment() != null) ? av
316 .getAlignment().getDataset() : null;
319 al.setDataset(dataset);
325 AlignFrame af = new AlignFrame(al,
326 (ColumnSelection) alAndColsel[1], AlignFrame.DEFAULT_WIDTH,
327 AlignFrame.DEFAULT_HEIGHT);
329 // >>>This is a fix for the moment, until a better solution is
331 // af.getFeatureRenderer().transferSettings(alignFrame.getFeatureRenderer());
333 // af.addSortByOrderMenuItem(ServiceName + " Ordering",
336 Desktop.addInternalFrame(af, "Original Data for " + this.title,
337 AlignFrame.DEFAULT_WIDTH, AlignFrame.DEFAULT_HEIGHT);
341 * CutAndPasteTransfer cap = new CutAndPasteTransfer(); for (int i = 0; i <
342 * seqs.length; i++) { cap.appendText(new jalview.util.Format("%-" + 15 +
343 * "s").form( seqs[i].getName())); cap.appendText(" " + seqstrings[i] +
346 * Desktop.addInternalFrame(cap, "Original Data", 400, 400);
350 class PCAPrinter extends Thread implements Printable
354 PrinterJob printJob = PrinterJob.getPrinterJob();
355 PageFormat pf = printJob.pageDialog(printJob.defaultPage());
357 printJob.setPrintable(this, pf);
359 if (printJob.printDialog())
364 } catch (Exception PrintException)
366 PrintException.printStackTrace();
371 public int print(Graphics pg, PageFormat pf, int pi)
372 throws PrinterException
374 pg.translate((int) pf.getImageableX(), (int) pf.getImageableY());
376 rc.drawBackground(pg, rc.bgColour);
378 if (rc.drawAxes == true)
385 return Printable.PAGE_EXISTS;
389 return Printable.NO_SUCH_PAGE;
400 public void eps_actionPerformed(ActionEvent e)
402 makePCAImage(jalview.util.ImageMaker.EPS);
411 public void png_actionPerformed(ActionEvent e)
413 makePCAImage(jalview.util.ImageMaker.PNG);
416 void makePCAImage(int type)
418 int width = rc.getWidth();
419 int height = rc.getHeight();
421 jalview.util.ImageMaker im;
423 if (type == jalview.util.ImageMaker.PNG)
425 im = new jalview.util.ImageMaker(this, jalview.util.ImageMaker.PNG,
426 "Make PNG image from PCA", width, height, null, null);
430 im = new jalview.util.ImageMaker(this, jalview.util.ImageMaker.EPS,
431 "Make EPS file from PCA", width, height, null,
435 if (im.getGraphics() != null)
437 rc.drawBackground(im.getGraphics(), Color.black);
438 rc.drawScene(im.getGraphics());
439 if (rc.drawAxes == true)
441 rc.drawAxes(im.getGraphics());
447 public void viewMenu_menuSelected()
449 buildAssociatedViewMenu();
452 void buildAssociatedViewMenu()
454 AlignmentPanel[] aps = PaintRefresher.getAssociatedPanels(av
455 .getSequenceSetId());
456 if (aps.length == 1 && rc.av == aps[0].av)
458 associateViewsMenu.setVisible(false);
462 associateViewsMenu.setVisible(true);
464 if ((viewMenu.getItem(viewMenu.getItemCount() - 2) instanceof JMenuItem))
466 viewMenu.insertSeparator(viewMenu.getItemCount() - 1);
469 associateViewsMenu.removeAll();
471 JRadioButtonMenuItem item;
472 ButtonGroup buttonGroup = new ButtonGroup();
473 int i, iSize = aps.length;
474 final PCAPanel thisPCAPanel = this;
475 for (i = 0; i < iSize; i++)
477 final AlignmentPanel ap = aps[i];
478 item = new JRadioButtonMenuItem(ap.av.viewName, ap.av == rc.av);
479 buttonGroup.add(item);
480 item.addActionListener(new ActionListener()
482 public void actionPerformed(ActionEvent evt)
484 rc.applyToAllViews = false;
487 PaintRefresher.Register(thisPCAPanel, ap.av.getSequenceSetId());
491 associateViewsMenu.add(item);
494 final JRadioButtonMenuItem itemf = new JRadioButtonMenuItem("All Views");
496 buttonGroup.add(itemf);
498 itemf.setSelected(rc.applyToAllViews);
499 itemf.addActionListener(new ActionListener()
501 public void actionPerformed(ActionEvent evt)
503 rc.applyToAllViews = itemf.isSelected();
506 associateViewsMenu.add(itemf);
514 * jalview.jbgui.GPCAPanel#outputPoints_actionPerformed(java.awt.event.ActionEvent
517 protected void outputPoints_actionPerformed(ActionEvent e)
519 CutAndPasteTransfer cap = new CutAndPasteTransfer();
522 cap.setText(pcaModel.getPointsasCsv(false,
523 xCombobox.getSelectedIndex(), yCombobox.getSelectedIndex(),
524 zCombobox.getSelectedIndex()));
525 Desktop.addInternalFrame(cap, "Points for " + getTitle(), 500, 500);
526 } catch (OutOfMemoryError oom)
528 new OOMWarning("exporting PCA points", oom);
537 * jalview.jbgui.GPCAPanel#outputProjPoints_actionPerformed(java.awt.event
540 protected void outputProjPoints_actionPerformed(ActionEvent e)
542 CutAndPasteTransfer cap = new CutAndPasteTransfer();
545 cap.setText(pcaModel.getPointsasCsv(true,
546 xCombobox.getSelectedIndex(), yCombobox.getSelectedIndex(),
547 zCombobox.getSelectedIndex()));
548 Desktop.addInternalFrame(cap, "Transformed points for " + getTitle(),
550 } catch (OutOfMemoryError oom)
552 new OOMWarning("exporting transformed PCA points", oom);
557 // methods for implementing IProgressIndicator
558 // need to refactor to a reusable stub class
559 Hashtable progressBars, progressBarHandlers;
564 * @see jalview.gui.IProgressIndicator#setProgressBar(java.lang.String, long)
567 public void setProgressBar(String message, long id)
569 if (progressBars == null)
571 progressBars = new Hashtable();
572 progressBarHandlers = new Hashtable();
575 JPanel progressPanel;
576 Long lId = new Long(id);
577 GridLayout layout = (GridLayout) statusPanel.getLayout();
578 if (progressBars.get(lId) != null)
580 progressPanel = (JPanel) progressBars.get(new Long(id));
581 statusPanel.remove(progressPanel);
582 progressBars.remove(lId);
583 progressPanel = null;
586 statusBar.setText(message);
588 if (progressBarHandlers.contains(lId))
590 progressBarHandlers.remove(lId);
592 layout.setRows(layout.getRows() - 1);
596 progressPanel = new JPanel(new BorderLayout(10, 5));
598 JProgressBar progressBar = new JProgressBar();
599 progressBar.setIndeterminate(true);
601 progressPanel.add(new JLabel(message), BorderLayout.WEST);
602 progressPanel.add(progressBar, BorderLayout.CENTER);
604 layout.setRows(layout.getRows() + 1);
605 statusPanel.add(progressPanel);
607 progressBars.put(lId, progressPanel);
610 // setMenusForViewport();
615 public void registerHandler(final long id,
616 final IProgressIndicatorHandler handler)
618 if (progressBarHandlers == null || !progressBars.contains(new Long(id)))
621 "call setProgressBar before registering the progress bar's handler.");
623 progressBarHandlers.put(new Long(id), handler);
624 final JPanel progressPanel = (JPanel) progressBars.get(new Long(id));
625 if (handler.canCancel())
627 JButton cancel = new JButton("Cancel");
628 final IProgressIndicator us = this;
629 cancel.addActionListener(new ActionListener()
633 public void actionPerformed(ActionEvent e)
635 handler.cancelActivity(id);
638 + ((JLabel) progressPanel.getComponent(0))
642 progressPanel.add(cancel, BorderLayout.EAST);
648 * @return true if any progress bars are still active
651 public boolean operationInProgress()
653 if (progressBars != null && progressBars.size() > 0)
661 protected void resetButton_actionPerformed(ActionEvent e)
664 top = 0; // ugly - prevents dimensionChanged events from being processed
665 xCombobox.setSelectedIndex(0);
666 yCombobox.setSelectedIndex(1);
668 zCombobox.setSelectedIndex(2);