2 * Jalview - A Sequence Alignment Editor and Viewer (Version 2.8.0b1)
3 * Copyright (C) 2014 The Jalview Authors
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/>.
17 * The Jalview Authors are detailed in the 'AUTHORS' file.
23 import java.awt.event.*;
24 import java.awt.print.*;
28 import jalview.datamodel.*;
29 import jalview.jbgui.*;
30 import jalview.schemes.ResidueProperties;
31 import jalview.schemes.ScoreMatrix;
32 import jalview.util.MessageManager;
33 import jalview.viewmodel.PCAModel;
41 public class PCAPanel extends GPCAPanel implements Runnable,
56 * Creates a new PCAPanel object.
63 public PCAPanel(AlignmentPanel ap)
68 boolean sameLength = true;
69 boolean selected = av.getSelectionGroup() != null
70 && av.getSelectionGroup().getSize() > 0;
71 AlignmentView seqstrings = av.getAlignmentView(selected);
72 boolean nucleotide = av.getAlignment().isNucleotide();
76 seqs = av.getAlignment().getSequencesArray();
80 seqs = av.getSelectionGroup().getSequencesInOrder(av.getAlignment());
82 SeqCigar sq[] = seqstrings.getSequences();
83 int length = sq[0].getWidth();
85 for (int i = 0; i < seqs.length; i++)
87 if (sq[i].getWidth() != length)
99 "The sequences must be aligned before calculating PCA.\n"
100 + "Try using the Pad function in the edit menu,\n"
101 + "or one of the multiple sequence alignment web services.",
102 "Sequences not aligned", JOptionPane.WARNING_MESSAGE);
106 pcaModel = new PCAModel(seqstrings, seqs, nucleotide);
107 PaintRefresher.Register(this, av.getSequenceSetId());
109 rc = new RotatableCanvas(ap);
110 this.getContentPane().add(rc, BorderLayout.CENTER);
111 Thread worker = new Thread(this);
115 protected void scoreMatrix_menuSelected()
117 scoreMatrixMenu.removeAll();
118 for (final String sm:ResidueProperties.scoreMatrices.keySet())
120 JCheckBoxMenuItem jm=new JCheckBoxMenuItem();
121 jm.setText(MessageManager.getStringOrReturn("label.score_model", sm));
122 jm.setSelected(pcaModel.getScore_matrix().equals(sm));
123 if (pcaModel.isNucleotide()==ResidueProperties.scoreMatrices.get(sm).isDNA())
125 final PCAPanel us = this;
126 jm.addActionListener(new ActionListener()
129 public void actionPerformed(ActionEvent e)
131 if (!pcaModel.getScore_matrix().equals((String) sm))
133 pcaModel.setScore_matrix((String) sm);
134 Thread worker = new Thread(us);
139 scoreMatrixMenu.add(jm);
143 public void bgcolour_actionPerformed(ActionEvent e)
145 Color col = JColorChooser.showDialog(this, "Select Background Colour",
160 long progId = System.currentTimeMillis();
161 IProgressIndicator progress = this;
162 String message = "Recalculating PCA";
163 if (getParent() == null)
165 progress = ap.alignFrame;
166 message = "Calculating PCA";
168 progress.setProgressBar(message, progId);
171 calcSettings.setEnabled(false);
174 xCombobox.setSelectedIndex(0);
175 yCombobox.setSelectedIndex(1);
176 zCombobox.setSelectedIndex(2);
178 pcaModel.updateRc(rc);
180 nuclSetting.setSelected(pcaModel.isNucleotide());
181 protSetting.setSelected(!pcaModel.isNucleotide());
182 jvVersionSetting.setSelected(pcaModel.isJvCalcMode());
183 top = pcaModel.getTop();
185 } catch (OutOfMemoryError er)
187 new OOMWarning("calculating PCA", er);
191 progress.setProgressBar("", progId);
193 calcSettings.setEnabled(true);
195 if (getParent() == null)
198 Desktop.addInternalFrame(this, MessageManager.getString("label.principal_component_analysis"), 475,
204 protected void nuclSetting_actionPerfomed(ActionEvent arg0)
206 if (!pcaModel.isNucleotide())
208 pcaModel.setNucleotide(true);
209 Thread worker = new Thread(this);
216 protected void protSetting_actionPerfomed(ActionEvent arg0)
219 if (pcaModel.isNucleotide())
221 pcaModel.setNucleotide(false);
222 Thread worker = new Thread(this);
228 protected void jvVersionSetting_actionPerfomed(ActionEvent arg0)
230 pcaModel.setJvCalcMode(jvVersionSetting.isSelected());
231 Thread worker = new Thread(this);
238 void doDimensionChange()
245 int dim1 = top - xCombobox.getSelectedIndex();
246 int dim2 = top - yCombobox.getSelectedIndex();
247 int dim3 = top - zCombobox.getSelectedIndex();
248 pcaModel.updateRcView(dim1, dim2, dim3);
250 rc.rotmat.setIdentity();
252 rc.paint(rc.getGraphics());
261 protected void xCombobox_actionPerformed(ActionEvent e)
272 protected void yCombobox_actionPerformed(ActionEvent e)
283 protected void zCombobox_actionPerformed(ActionEvent e)
288 public void outputValues_actionPerformed(ActionEvent e)
290 CutAndPasteTransfer cap = new CutAndPasteTransfer();
293 cap.setText(pcaModel.getDetails());
294 Desktop.addInternalFrame(cap, MessageManager.getString("label.pca_details"), 500, 500);
295 } catch (OutOfMemoryError oom)
297 new OOMWarning("opening PCA details", oom);
302 public void showLabels_actionPerformed(ActionEvent e)
304 rc.showLabels(showLabels.getState());
307 public void print_actionPerformed(ActionEvent e)
309 PCAPrinter printer = new PCAPrinter();
313 public void originalSeqData_actionPerformed(ActionEvent e)
315 // this was cut'n'pasted from the equivalent TreePanel method - we should
316 // make this an abstract function of all jalview analysis windows
317 if (pcaModel.getSeqtrings() == null)
319 jalview.bin.Cache.log
320 .info("Unexpected call to originalSeqData_actionPerformed - should have hidden this menu action.");
323 // decide if av alignment is sufficiently different to original data to
324 // warrant a new window to be created
325 // create new alignmnt window with hidden regions (unhiding hidden regions
326 // yields unaligned seqs)
327 // or create a selection box around columns in alignment view
328 // test Alignment(SeqCigar[])
332 // we try to get the associated view's gap character
333 // but this may fail if the view was closed...
334 gc = av.getGapCharacter();
335 } catch (Exception ex)
339 Object[] alAndColsel = pcaModel.getSeqtrings()
340 .getAlignmentAndColumnSelection(gc);
342 if (alAndColsel != null && alAndColsel[0] != null)
344 // AlignmentOrder origorder = new AlignmentOrder(alAndColsel[0]);
346 Alignment al = new Alignment((SequenceI[]) alAndColsel[0]);
347 Alignment dataset = (av != null && av.getAlignment() != null) ? av
348 .getAlignment().getDataset() : null;
351 al.setDataset(dataset);
357 AlignFrame af = new AlignFrame(al,
358 (ColumnSelection) alAndColsel[1], AlignFrame.DEFAULT_WIDTH,
359 AlignFrame.DEFAULT_HEIGHT);
361 // >>>This is a fix for the moment, until a better solution is
363 // af.getFeatureRenderer().transferSettings(alignFrame.getFeatureRenderer());
365 // af.addSortByOrderMenuItem(ServiceName + " Ordering",
368 Desktop.addInternalFrame(af, MessageManager.formatMessage("label.original_data_for_params", new String[]{this.title}),
369 AlignFrame.DEFAULT_WIDTH, AlignFrame.DEFAULT_HEIGHT);
373 * CutAndPasteTransfer cap = new CutAndPasteTransfer(); for (int i = 0; i <
374 * seqs.length; i++) { cap.appendText(new jalview.util.Format("%-" + 15 +
375 * "s").form( seqs[i].getName())); cap.appendText(" " + seqstrings[i] +
378 * Desktop.addInternalFrame(cap, "Original Data", 400, 400);
382 class PCAPrinter extends Thread implements Printable
386 PrinterJob printJob = PrinterJob.getPrinterJob();
387 PageFormat pf = printJob.pageDialog(printJob.defaultPage());
389 printJob.setPrintable(this, pf);
391 if (printJob.printDialog())
396 } catch (Exception PrintException)
398 PrintException.printStackTrace();
403 public int print(Graphics pg, PageFormat pf, int pi)
404 throws PrinterException
406 pg.translate((int) pf.getImageableX(), (int) pf.getImageableY());
408 rc.drawBackground(pg, rc.bgColour);
410 if (rc.drawAxes == true)
417 return Printable.PAGE_EXISTS;
421 return Printable.NO_SUCH_PAGE;
432 public void eps_actionPerformed(ActionEvent e)
434 makePCAImage(jalview.util.ImageMaker.EPS);
443 public void png_actionPerformed(ActionEvent e)
445 makePCAImage(jalview.util.ImageMaker.PNG);
448 void makePCAImage(int type)
450 int width = rc.getWidth();
451 int height = rc.getHeight();
453 jalview.util.ImageMaker im;
455 if (type == jalview.util.ImageMaker.PNG)
457 im = new jalview.util.ImageMaker(this, jalview.util.ImageMaker.PNG,
458 "Make PNG image from PCA", width, height, null, null);
462 im = new jalview.util.ImageMaker(this, jalview.util.ImageMaker.EPS,
463 "Make EPS file from PCA", width, height, null,
467 if (im.getGraphics() != null)
469 rc.drawBackground(im.getGraphics(), Color.black);
470 rc.drawScene(im.getGraphics());
471 if (rc.drawAxes == true)
473 rc.drawAxes(im.getGraphics());
480 public void viewMenu_menuSelected()
482 buildAssociatedViewMenu();
485 void buildAssociatedViewMenu()
487 AlignmentPanel[] aps = PaintRefresher.getAssociatedPanels(av
488 .getSequenceSetId());
489 if (aps.length == 1 && rc.av == aps[0].av)
491 associateViewsMenu.setVisible(false);
495 associateViewsMenu.setVisible(true);
497 if ((viewMenu.getItem(viewMenu.getItemCount() - 2) instanceof JMenuItem))
499 viewMenu.insertSeparator(viewMenu.getItemCount() - 1);
502 associateViewsMenu.removeAll();
504 JRadioButtonMenuItem item;
505 ButtonGroup buttonGroup = new ButtonGroup();
506 int i, iSize = aps.length;
507 final PCAPanel thisPCAPanel = this;
508 for (i = 0; i < iSize; i++)
510 final AlignmentPanel ap = aps[i];
511 item = new JRadioButtonMenuItem(ap.av.viewName, ap.av == rc.av);
512 buttonGroup.add(item);
513 item.addActionListener(new ActionListener()
515 public void actionPerformed(ActionEvent evt)
517 rc.applyToAllViews = false;
520 PaintRefresher.Register(thisPCAPanel, ap.av.getSequenceSetId());
524 associateViewsMenu.add(item);
527 final JRadioButtonMenuItem itemf = new JRadioButtonMenuItem("All Views");
529 buttonGroup.add(itemf);
531 itemf.setSelected(rc.applyToAllViews);
532 itemf.addActionListener(new ActionListener()
534 public void actionPerformed(ActionEvent evt)
536 rc.applyToAllViews = itemf.isSelected();
539 associateViewsMenu.add(itemf);
547 * jalview.jbgui.GPCAPanel#outputPoints_actionPerformed(java.awt.event.ActionEvent
550 protected void outputPoints_actionPerformed(ActionEvent e)
552 CutAndPasteTransfer cap = new CutAndPasteTransfer();
555 cap.setText(pcaModel.getPointsasCsv(false,
556 xCombobox.getSelectedIndex(), yCombobox.getSelectedIndex(),
557 zCombobox.getSelectedIndex()));
558 Desktop.addInternalFrame(cap, MessageManager.formatMessage("label.points_for_params", new String[]{this.getTitle()}), 500, 500);
559 } catch (OutOfMemoryError oom)
561 new OOMWarning("exporting PCA points", oom);
570 * jalview.jbgui.GPCAPanel#outputProjPoints_actionPerformed(java.awt.event
573 protected void outputProjPoints_actionPerformed(ActionEvent e)
575 CutAndPasteTransfer cap = new CutAndPasteTransfer();
578 cap.setText(pcaModel.getPointsasCsv(true,
579 xCombobox.getSelectedIndex(), yCombobox.getSelectedIndex(),
580 zCombobox.getSelectedIndex()));
581 Desktop.addInternalFrame(cap, MessageManager.formatMessage("label.transformed_points_for_params", new String[]{this.getTitle()}),
583 } catch (OutOfMemoryError oom)
585 new OOMWarning("exporting transformed PCA points", oom);
590 // methods for implementing IProgressIndicator
591 // need to refactor to a reusable stub class
592 Hashtable progressBars, progressBarHandlers;
597 * @see jalview.gui.IProgressIndicator#setProgressBar(java.lang.String, long)
600 public void setProgressBar(String message, long id)
602 if (progressBars == null)
604 progressBars = new Hashtable();
605 progressBarHandlers = new Hashtable();
608 JPanel progressPanel;
609 Long lId = new Long(id);
610 GridLayout layout = (GridLayout) statusPanel.getLayout();
611 if (progressBars.get(lId) != null)
613 progressPanel = (JPanel) progressBars.get(new Long(id));
614 statusPanel.remove(progressPanel);
615 progressBars.remove(lId);
616 progressPanel = null;
619 statusBar.setText(message);
621 if (progressBarHandlers.contains(lId))
623 progressBarHandlers.remove(lId);
625 layout.setRows(layout.getRows() - 1);
629 progressPanel = new JPanel(new BorderLayout(10, 5));
631 JProgressBar progressBar = new JProgressBar();
632 progressBar.setIndeterminate(true);
634 progressPanel.add(new JLabel(message), BorderLayout.WEST);
635 progressPanel.add(progressBar, BorderLayout.CENTER);
637 layout.setRows(layout.getRows() + 1);
638 statusPanel.add(progressPanel);
640 progressBars.put(lId, progressPanel);
643 // setMenusForViewport();
648 public void registerHandler(final long id,
649 final IProgressIndicatorHandler handler)
651 if (progressBarHandlers == null || !progressBars.contains(new Long(id)))
654 "call setProgressBar before registering the progress bar's handler.");
656 progressBarHandlers.put(new Long(id), handler);
657 final JPanel progressPanel = (JPanel) progressBars.get(new Long(id));
658 if (handler.canCancel())
660 JButton cancel = new JButton(MessageManager.getString("action.cancel"));
661 final IProgressIndicator us = this;
662 cancel.addActionListener(new ActionListener()
666 public void actionPerformed(ActionEvent e)
668 handler.cancelActivity(id);
671 + ((JLabel) progressPanel.getComponent(0))
675 progressPanel.add(cancel, BorderLayout.EAST);
681 * @return true if any progress bars are still active
684 public boolean operationInProgress()
686 if (progressBars != null && progressBars.size() > 0)
694 protected void resetButton_actionPerformed(ActionEvent e)
697 top = 0; // ugly - prevents dimensionChanged events from being processed
698 xCombobox.setSelectedIndex(0);
699 yCombobox.setSelectedIndex(1);
701 zCombobox.setSelectedIndex(2);