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();
149 } catch (OutOfMemoryError er)
151 new OOMWarning("calculating PCA", er);
155 progress.setProgressBar("", progId);
157 calcSettings.setEnabled(true);
159 if (getParent()==null)
162 Desktop.addInternalFrame(this, "Principal component analysis", 475, 450);
166 protected void nuclSetting_actionPerfomed(ActionEvent arg0)
168 if (!pcaModel.isNucleotide())
170 pcaModel.setNucleotide(true);
171 Thread worker = new Thread(this);
177 protected void protSetting_actionPerfomed(ActionEvent arg0)
180 if (pcaModel.isNucleotide())
182 pcaModel.setNucleotide(false);
183 Thread worker = new Thread(this);
190 void doDimensionChange()
197 int dim1 = top - xCombobox.getSelectedIndex();
198 int dim2 = top - yCombobox.getSelectedIndex();
199 int dim3 = top - zCombobox.getSelectedIndex();
200 pcaModel.updateRcView(dim1, dim2, dim3);
202 rc.rotmat.setIdentity();
204 rc.paint(rc.getGraphics());
213 protected void xCombobox_actionPerformed(ActionEvent e)
224 protected void yCombobox_actionPerformed(ActionEvent e)
235 protected void zCombobox_actionPerformed(ActionEvent e)
240 public void outputValues_actionPerformed(ActionEvent e)
242 CutAndPasteTransfer cap = new CutAndPasteTransfer();
245 cap.setText(pcaModel.getDetails());
246 Desktop.addInternalFrame(cap, "PCA details", 500, 500);
247 } catch (OutOfMemoryError oom)
249 new OOMWarning("opening PCA details", oom);
254 public void showLabels_actionPerformed(ActionEvent e)
256 rc.showLabels(showLabels.getState());
259 public void print_actionPerformed(ActionEvent e)
261 PCAPrinter printer = new PCAPrinter();
265 public void originalSeqData_actionPerformed(ActionEvent e)
267 // this was cut'n'pasted from the equivalent TreePanel method - we should
268 // make this an abstract function of all jalview analysis windows
269 if (pcaModel.getSeqtrings() == null)
271 jalview.bin.Cache.log
272 .info("Unexpected call to originalSeqData_actionPerformed - should have hidden this menu action.");
275 // decide if av alignment is sufficiently different to original data to
276 // warrant a new window to be created
277 // create new alignmnt window with hidden regions (unhiding hidden regions
278 // yields unaligned seqs)
279 // or create a selection box around columns in alignment view
280 // test Alignment(SeqCigar[])
284 // we try to get the associated view's gap character
285 // but this may fail if the view was closed...
286 gc = av.getGapCharacter();
287 } catch (Exception ex)
291 Object[] alAndColsel = pcaModel.getSeqtrings().getAlignmentAndColumnSelection(gc);
293 if (alAndColsel != null && alAndColsel[0] != null)
295 // AlignmentOrder origorder = new AlignmentOrder(alAndColsel[0]);
297 Alignment al = new Alignment((SequenceI[]) alAndColsel[0]);
298 Alignment dataset = (av != null && av.getAlignment() != null) ? av
299 .getAlignment().getDataset() : null;
302 al.setDataset(dataset);
308 AlignFrame af = new AlignFrame(al,
309 (ColumnSelection) alAndColsel[1], AlignFrame.DEFAULT_WIDTH,
310 AlignFrame.DEFAULT_HEIGHT);
312 // >>>This is a fix for the moment, until a better solution is
314 // af.getFeatureRenderer().transferSettings(alignFrame.getFeatureRenderer());
316 // af.addSortByOrderMenuItem(ServiceName + " Ordering",
319 Desktop.addInternalFrame(af, "Original Data for " + this.title,
320 AlignFrame.DEFAULT_WIDTH, AlignFrame.DEFAULT_HEIGHT);
324 * CutAndPasteTransfer cap = new CutAndPasteTransfer(); for (int i = 0; i <
325 * seqs.length; i++) { cap.appendText(new jalview.util.Format("%-" + 15 +
326 * "s").form( seqs[i].getName())); cap.appendText(" " + seqstrings[i] +
329 * Desktop.addInternalFrame(cap, "Original Data", 400, 400);
333 class PCAPrinter extends Thread implements Printable
337 PrinterJob printJob = PrinterJob.getPrinterJob();
338 PageFormat pf = printJob.pageDialog(printJob.defaultPage());
340 printJob.setPrintable(this, pf);
342 if (printJob.printDialog())
347 } catch (Exception PrintException)
349 PrintException.printStackTrace();
354 public int print(Graphics pg, PageFormat pf, int pi)
355 throws PrinterException
357 pg.translate((int) pf.getImageableX(), (int) pf.getImageableY());
359 rc.drawBackground(pg, rc.bgColour);
361 if (rc.drawAxes == true)
368 return Printable.PAGE_EXISTS;
372 return Printable.NO_SUCH_PAGE;
383 public void eps_actionPerformed(ActionEvent e)
385 makePCAImage(jalview.util.ImageMaker.EPS);
394 public void png_actionPerformed(ActionEvent e)
396 makePCAImage(jalview.util.ImageMaker.PNG);
399 void makePCAImage(int type)
401 int width = rc.getWidth();
402 int height = rc.getHeight();
404 jalview.util.ImageMaker im;
406 if (type == jalview.util.ImageMaker.PNG)
408 im = new jalview.util.ImageMaker(this, jalview.util.ImageMaker.PNG,
409 "Make PNG image from PCA", width, height, null, null);
413 im = new jalview.util.ImageMaker(this, jalview.util.ImageMaker.EPS,
414 "Make EPS file from PCA", width, height, null,
418 if (im.getGraphics() != null)
420 rc.drawBackground(im.getGraphics(), Color.black);
421 rc.drawScene(im.getGraphics());
422 if (rc.drawAxes == true)
424 rc.drawAxes(im.getGraphics());
430 public void viewMenu_menuSelected()
432 buildAssociatedViewMenu();
435 void buildAssociatedViewMenu()
437 AlignmentPanel[] aps = PaintRefresher.getAssociatedPanels(av
438 .getSequenceSetId());
439 if (aps.length == 1 && rc.av == aps[0].av)
441 associateViewsMenu.setVisible(false);
445 associateViewsMenu.setVisible(true);
447 if ((viewMenu.getItem(viewMenu.getItemCount() - 2) instanceof JMenuItem))
449 viewMenu.insertSeparator(viewMenu.getItemCount() - 1);
452 associateViewsMenu.removeAll();
454 JRadioButtonMenuItem item;
455 ButtonGroup buttonGroup = new ButtonGroup();
456 int i, iSize = aps.length;
457 final PCAPanel thisPCAPanel = this;
458 for (i = 0; i < iSize; i++)
460 final AlignmentPanel ap = aps[i];
461 item = new JRadioButtonMenuItem(ap.av.viewName, ap.av == rc.av);
462 buttonGroup.add(item);
463 item.addActionListener(new ActionListener()
465 public void actionPerformed(ActionEvent evt)
467 rc.applyToAllViews = false;
470 PaintRefresher.Register(thisPCAPanel, ap.av.getSequenceSetId());
474 associateViewsMenu.add(item);
477 final JRadioButtonMenuItem itemf = new JRadioButtonMenuItem("All Views");
479 buttonGroup.add(itemf);
481 itemf.setSelected(rc.applyToAllViews);
482 itemf.addActionListener(new ActionListener()
484 public void actionPerformed(ActionEvent evt)
486 rc.applyToAllViews = itemf.isSelected();
489 associateViewsMenu.add(itemf);
497 * jalview.jbgui.GPCAPanel#outputPoints_actionPerformed(java.awt.event.ActionEvent
500 protected void outputPoints_actionPerformed(ActionEvent e)
502 CutAndPasteTransfer cap = new CutAndPasteTransfer();
505 cap.setText(pcaModel.getPointsasCsv(false, xCombobox.getSelectedIndex(), yCombobox.getSelectedIndex(), zCombobox.getSelectedIndex()));
506 Desktop.addInternalFrame(cap, "Points for " + getTitle(), 500, 500);
507 } catch (OutOfMemoryError oom)
509 new OOMWarning("exporting PCA points", oom);
520 * jalview.jbgui.GPCAPanel#outputProjPoints_actionPerformed(java.awt.event
523 protected void outputProjPoints_actionPerformed(ActionEvent e)
525 CutAndPasteTransfer cap = new CutAndPasteTransfer();
528 cap.setText(pcaModel.getPointsasCsv(true, xCombobox.getSelectedIndex(), yCombobox.getSelectedIndex(), zCombobox.getSelectedIndex()));
529 Desktop.addInternalFrame(cap, "Transformed points for " + getTitle(),
531 } catch (OutOfMemoryError oom)
533 new OOMWarning("exporting transformed PCA points", oom);
538 // methods for implementing IProgressIndicator
539 // need to refactor to a reusable stub class
540 Hashtable progressBars, progressBarHandlers;
545 * @see jalview.gui.IProgressIndicator#setProgressBar(java.lang.String, long)
548 public void setProgressBar(String message, long id)
550 if (progressBars == null)
552 progressBars = new Hashtable();
553 progressBarHandlers = new Hashtable();
556 JPanel progressPanel;
557 Long lId = new Long(id);
558 GridLayout layout = (GridLayout) statusPanel.getLayout();
559 if (progressBars.get(lId) != null)
561 progressPanel = (JPanel) progressBars.get(new Long(id));
562 statusPanel.remove(progressPanel);
563 progressBars.remove(lId);
564 progressPanel = null;
567 statusBar.setText(message);
569 if (progressBarHandlers.contains(lId))
571 progressBarHandlers.remove(lId);
573 layout.setRows(layout.getRows() - 1);
577 progressPanel = new JPanel(new BorderLayout(10, 5));
579 JProgressBar progressBar = new JProgressBar();
580 progressBar.setIndeterminate(true);
582 progressPanel.add(new JLabel(message), BorderLayout.WEST);
583 progressPanel.add(progressBar, BorderLayout.CENTER);
585 layout.setRows(layout.getRows() + 1);
586 statusPanel.add(progressPanel);
588 progressBars.put(lId, progressPanel);
591 // setMenusForViewport();
596 public void registerHandler(final long id,
597 final IProgressIndicatorHandler handler)
599 if (progressBarHandlers == null || !progressBars.contains(new Long(id)))
602 "call setProgressBar before registering the progress bar's handler.");
604 progressBarHandlers.put(new Long(id), handler);
605 final JPanel progressPanel = (JPanel) progressBars.get(new Long(id));
606 if (handler.canCancel())
608 JButton cancel = new JButton("Cancel");
609 final IProgressIndicator us = this;
610 cancel.addActionListener(new ActionListener()
614 public void actionPerformed(ActionEvent e)
616 handler.cancelActivity(id);
619 + ((JLabel) progressPanel.getComponent(0))
623 progressPanel.add(cancel, BorderLayout.EAST);
629 * @return true if any progress bars are still active
632 public boolean operationInProgress()
634 if (progressBars != null && progressBars.size() > 0)
641 protected void resetButton_actionPerformed(ActionEvent e)
644 top=0; // ugly - prevents dimensionChanged events from being processed
645 xCombobox.setSelectedIndex(0);
646 yCombobox.setSelectedIndex(1);
648 zCombobox.setSelectedIndex(2);