Merge branch 'jims/feature/JAL-4159_pasimap' into feature/JAL-4159_pasimap
[jalview.git] / src / jalview / gui / PaSiMapPanel.java
1 /*
2  * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
3  * Copyright (C) $$Year-Rel$$ 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.gui;
22
23 import jalview.analysis.scoremodels.ScoreModels;
24 import jalview.api.AlignViewportI;
25 import jalview.api.analysis.ScoreModelI;
26 import jalview.api.analysis.SimilarityParamsI;
27 import jalview.bin.Console;
28 import jalview.datamodel.Alignment;
29 import jalview.datamodel.AlignmentI;
30 import jalview.datamodel.AlignmentView;
31 import jalview.datamodel.HiddenColumns;
32 import jalview.datamodel.SequenceGroup;
33 import jalview.datamodel.SequenceI;
34 import jalview.gui.ImageExporter.ImageWriterI;
35 import jalview.gui.JalviewColourChooser.ColourChooserListener;
36 import jalview.jbgui.GPaSiMapPanel;
37 import jalview.math.RotatableMatrix.Axis;
38 import jalview.util.ImageMaker;
39 import jalview.util.MessageManager;
40 import jalview.viewmodel.AlignmentViewport;
41 import jalview.viewmodel.PaSiMapModel;
42
43 import java.awt.BorderLayout;
44 import java.awt.Color;
45 import java.awt.Dimension;
46 import java.awt.Graphics;
47 import java.awt.event.ActionEvent;
48 import java.awt.event.ActionListener;
49 import java.awt.print.PageFormat;
50 import java.awt.print.Printable;
51 import java.awt.print.PrinterException;
52 import java.awt.print.PrinterJob;
53 import java.beans.PropertyChangeEvent;
54 import java.beans.PropertyChangeListener;
55
56 import javax.swing.ButtonGroup;
57 import javax.swing.JMenuItem;
58 import javax.swing.JProgressBar;
59 import javax.swing.JRadioButtonMenuItem;
60 import javax.swing.event.InternalFrameAdapter;
61 import javax.swing.event.InternalFrameEvent;
62
63 /**
64  * The panel holding the Pairwise Similarity Map 3-D visualisation
65  */
66 public class PaSiMapPanel extends GPaSiMapPanel
67         implements Runnable, IProgressIndicator
68 {
69   private static final int MIN_WIDTH = 470;
70
71   private static final int MIN_HEIGHT = 250;
72
73   private static final int MAX_PASIMAP_SEQ = 20000;
74
75   private final int GAP_OPEN_COST = 100;
76
77   private final int GAP_EXTEND_COST = 5;
78
79   private RotatableCanvas rc;
80
81   AlignmentPanel ap;
82
83   AlignmentViewport av;
84
85   private PaSiMapModel pasimapModel;
86
87   private int top = 0;
88
89   private IProgressIndicator progressBar;
90
91   private long progId;
92
93   private boolean working;
94
95   /**
96    * Constructor given sequence data, a similarity (or distance) score model
97    * name, and score calculation parameters
98    * 
99    * @param alignPanel
100    * @param modelName
101    */
102   public PaSiMapPanel(AlignmentPanel alignPanel, String modelName)
103   {
104     super(8);   // dim = 8
105     this.av = alignPanel.av;
106     this.ap = alignPanel;
107     boolean nucleotide = av.getAlignment().isNucleotide();
108
109     //progressBar = new ProgressBar(statusPanel, statusBar);
110
111     addInternalFrameListener(new InternalFrameAdapter()
112     {
113       @Override
114       public void internalFrameClosed(InternalFrameEvent e)
115       {
116         close_actionPerformed();
117       }
118     });
119
120     boolean selected = av.getSelectionGroup() != null
121             && av.getSelectionGroup().getSize() > 0;
122     SequenceI[] seqs;
123     if (!selected)
124     {
125       seqs = av.getAlignment().getSequencesArray();
126     }
127     else
128     {
129       seqs = av.getSelectionGroup().getSequencesInOrder(av.getAlignment());
130     }
131
132     ScoreModelI scoreModel = ScoreModels.getInstance()
133             .getScoreModel(modelName, ap);
134     setPasimapModel(
135             new PaSiMapModel(av, seqs, nucleotide, scoreModel));
136     PaintRefresher.Register(this, av.getSequenceSetId());
137
138     setRotatableCanvas(new RotatableCanvas(alignPanel));
139     this.getContentPane().add(getRotatableCanvas(), BorderLayout.CENTER);
140
141     addKeyListener(getRotatableCanvas());
142     validate();
143   }
144
145   /**
146    * Ensure references to potentially very large objects (the PaSiMap matrices) are
147    * nulled when the frame is closed
148    */
149   protected void close_actionPerformed()
150   {
151     setPasimapModel(null);
152     if (this.rc != null)
153     {
154       this.rc.sequencePoints = null;
155       this.rc.setAxisEndPoints(null);
156       this.rc = null;
157     }
158   }
159
160   @Override
161   protected void bgcolour_actionPerformed()
162   {
163     String ttl = MessageManager.getString("label.select_background_colour");
164     ColourChooserListener listener = new ColourChooserListener()
165     {
166       @Override
167       public void colourSelected(Color c)
168       {
169         rc.setBgColour(c);
170         rc.repaint();
171       }
172     };
173     JalviewColourChooser.showColourChooser(this, ttl, rc.getBgColour(),
174             listener);
175   }
176
177   /**
178    * Calculates the PaSiMap and displays the results
179    */
180   @Override
181   public void run()
182   {
183     working = true;
184     progId = System.currentTimeMillis();
185     progressBar = this;
186     String message = MessageManager
187             .getString("label.pasimap_recalculating");
188     if (getParent() == null)
189     {
190       progressBar = ap.alignFrame;
191       message = MessageManager.getString("label.pasimap_calculating");
192     }
193     progressBar.setProgressBar(message, progId);
194     try
195     {
196       SequenceGroup selGroup=av.getSelectionGroup();
197       
198       if (selGroup==null)
199       {
200         selGroup = new SequenceGroup(av.getAlignment().getSequences());
201         selGroup.setStartRes(0);
202         selGroup.setEndRes(av.getAlignment().getWidth()-1);
203       }
204       
205       if (selGroup.getSize()>MAX_PASIMAP_SEQ)
206       {
207         int start = selGroup.getStartRes(),end=selGroup.getEndRes();
208           selGroup = new SequenceGroup(selGroup.getSequences().subList(0, MAX_PASIMAP_SEQ));
209           selGroup.setStartRes(start);
210           selGroup.setEndRes(end);
211           Console.warn("Truncated input sequences for PASIMAP analysis to "+MAX_PASIMAP_SEQ);
212       }
213       
214       PairwiseAlignPanel pap = new PairwiseAlignPanel(av, selGroup, true,
215               GAP_OPEN_COST, GAP_EXTEND_COST, false);
216       System.out.println(pap != null);
217       setPairwiseAlignPanel(pap);
218       getPasimapModel().calculate(pap);
219
220       xCombobox.setSelectedIndex(0);
221       yCombobox.setSelectedIndex(1);
222       zCombobox.setSelectedIndex(2);
223
224       getPasimapModel().updateRc(getRotatableCanvas());
225       // rc.invalidate();
226       setTop(getPasimapModel().getTop());
227
228     } catch (OutOfMemoryError er)
229     {
230       new OOMWarning("calculating PaSiMap", er);
231       working = false;
232       return;
233     } finally
234     {
235       progressBar.setProgressBar("", progId);
236     }
237
238     repaint();
239     if (getParent() == null)
240     {
241       Desktop.addInternalFrame(
242               this, MessageManager.formatMessage("label.calc_title",
243                       "PaSiMap", ap.alignFrame.getTitle()),
244               475, 450);
245       this.setMinimumSize(new Dimension(MIN_WIDTH, MIN_HEIGHT));
246     }
247     working = false;
248   }
249
250   /**
251    * Updates the PaSiMap display after a change of component to use for x, y or z
252    * axis
253    */
254   @Override
255   protected void doDimensionChange()
256   {
257     if (getTop() == 0)
258     {
259       return;
260     }
261
262     int dim1 = getTop() - xCombobox.getSelectedIndex();
263     int dim2 = getTop() - yCombobox.getSelectedIndex();
264     int dim3 = getTop() - zCombobox.getSelectedIndex();
265     getPasimapModel().updateRcView(dim1, dim2, dim3);
266     getRotatableCanvas().resetView();
267   }
268
269   /**
270    * Sets the selected checkbox item index for PaSiMap dimension (1, 2, 3...) for
271    * the given axis (X/Y/Z)
272    * 
273    * @param index
274    * @param axis
275    */
276   public void setSelectedDimensionIndex(int index, Axis axis)
277   {
278     switch (axis)
279     {
280     case X:
281       xCombobox.setSelectedIndex(index);
282       break;
283     case Y:
284       yCombobox.setSelectedIndex(index);
285       break;
286     case Z:
287       zCombobox.setSelectedIndex(index);
288       break;
289     default:
290     }
291   }
292
293   @Override
294   protected void outputValues_actionPerformed()
295   {
296     CutAndPasteTransfer cap = new CutAndPasteTransfer();
297     try
298     {
299       cap.setText(getPasimapModel().getDetails());
300       Desktop.addInternalFrame(cap,
301               MessageManager.getString("label.pasimap_details"), 500, 500);
302     } catch (OutOfMemoryError oom)
303     {
304       new OOMWarning("opening PaSiMap details", oom);
305       cap.dispose();
306     }
307   }
308
309   @Override
310   protected void showLabels_actionPerformed()
311   {
312     getRotatableCanvas().showLabels(showLabels.getState());
313   }
314
315   @Override
316   protected void print_actionPerformed()
317   {
318     PaSiMapPrinter printer = new PaSiMapPrinter();
319     printer.start();
320   }
321
322   /**
323    * If available, shows the data which formed the inputs for the PaSiMap as a new
324    * alignment
325    */
326   @Override
327   public void originalSeqData_actionPerformed()
328   {
329     // JAL-2647 disabled after load from project (until save to project done)
330     if (getPasimapModel().getInputData() == null)
331     {
332       Console.info(
333               "Unexpected call to originalSeqData_actionPerformed - should have hidden this menu action.");
334       return;
335     }
336     // decide if av alignment is sufficiently different to original data to
337     // warrant a new window to be created
338     // create new alignment window with hidden regions (unhiding hidden regions
339     // yields unaligned seqs)
340     // or create a selection box around columns in alignment view
341     // test Alignment(SeqCigar[])
342     char gc = '-';
343     try
344     {
345       // we try to get the associated view's gap character
346       // but this may fail if the view was closed...
347       gc = av.getGapCharacter();
348     } catch (Exception ex)
349     {
350     }
351
352     Object[] alAndColsel = getPasimapModel().getInputData()
353             .getAlignmentView(false).getAlignmentAndHiddenColumns(gc);
354
355     if (alAndColsel != null && alAndColsel[0] != null)
356     {
357       // AlignmentOrder origorder = new AlignmentOrder(alAndColsel[0]);
358
359       AlignmentI al = new Alignment((SequenceI[]) alAndColsel[0]);
360       AlignmentI dataset = (av != null && av.getAlignment() != null)
361               ? av.getAlignment().getDataset()
362               : null;
363       if (dataset != null)
364       {
365         al.setDataset(dataset);
366       }
367
368       if (true)
369       {
370         // make a new frame!
371         AlignFrame af = new AlignFrame(al, (HiddenColumns) alAndColsel[1],
372                 AlignFrame.DEFAULT_WIDTH, AlignFrame.DEFAULT_HEIGHT);
373
374         // >>>This is a fix for the moment, until a better solution is
375         // found!!<<<
376         // af.getFeatureRenderer().transferSettings(alignFrame.getFeatureRenderer());
377
378         // af.addSortByOrderMenuItem(ServiceName + " Ordering",
379         // msaorder);
380
381         Desktop.addInternalFrame(af, MessageManager.formatMessage(
382                 "label.original_data_for_params", new String[]
383                 { this.title }), AlignFrame.DEFAULT_WIDTH,
384                 AlignFrame.DEFAULT_HEIGHT);
385       }
386     }
387     /*
388      * CutAndPasteTransfer cap = new CutAndPasteTransfer(); for (int i = 0; i <
389      * seqs.length; i++) { cap.appendText(new jalview.util.Format("%-" + 15 +
390      * "s").form( seqs[i].getName())); cap.appendText(" " + seqstrings[i] +
391      * "\n"); }
392      * 
393      * Desktop.addInternalFrame(cap, "Original Data", 400, 400);
394      */
395   }
396
397   class PaSiMapPrinter extends Thread implements Printable
398   {
399     @Override
400     public void run()
401     {
402       PrinterJob printJob = PrinterJob.getPrinterJob();
403       PageFormat defaultPage = printJob.defaultPage();
404       PageFormat pf = printJob.pageDialog(defaultPage);
405
406       if (defaultPage == pf)
407       {
408         /*
409          * user cancelled
410          */
411         return;
412       }
413
414       printJob.setPrintable(this, pf);
415
416       if (printJob.printDialog())
417       {
418         try
419         {
420           printJob.print();
421         } catch (Exception PrintException)
422         {
423           PrintException.printStackTrace();
424         }
425       }
426     }
427
428     @Override
429     public int print(Graphics pg, PageFormat pf, int pi)
430             throws PrinterException
431     {
432       pg.translate((int) pf.getImageableX(), (int) pf.getImageableY());
433
434       getRotatableCanvas().drawBackground(pg);
435       getRotatableCanvas().drawScene(pg);
436       if (getRotatableCanvas().drawAxes)
437       {
438         getRotatableCanvas().drawAxes(pg);
439       }
440
441       if (pi == 0)
442       {
443         return Printable.PAGE_EXISTS;
444       }
445       else
446       {
447         return Printable.NO_SUCH_PAGE;
448       }
449     }
450   }
451
452   public void makePaSiMapImage(ImageMaker.TYPE type)  throws Exception
453   {
454     int width = getRotatableCanvas().getWidth();
455     int height = getRotatableCanvas().getHeight();
456     ImageWriterI writer = new ImageWriterI()
457     {
458       @Override
459       public void exportImage(Graphics g) throws Exception
460       {
461         RotatableCanvas canvas = getRotatableCanvas();
462         canvas.drawBackground(g);
463         canvas.drawScene(g);
464         if (canvas.drawAxes)
465         {
466           canvas.drawAxes(g);
467         }
468       }
469     };
470     String pasimap = MessageManager.getString("label.pasimap");
471     ImageExporter exporter = new ImageExporter(writer, null, type, pasimap);
472     exporter.doExport(null, this, width, height, pasimap);
473   }
474
475   @Override
476   protected void viewMenu_menuSelected()
477   {
478     buildAssociatedViewMenu();
479   }
480
481   /**
482    * Builds the menu showing the choice of possible views (for the associated
483    * sequence data) to which the PaSiMap may be linked
484    */
485   void buildAssociatedViewMenu()
486   {
487     AlignmentPanel[] aps = PaintRefresher
488             .getAssociatedPanels(av.getSequenceSetId());
489     if (aps.length == 1 && getRotatableCanvas().av == aps[0].av)
490     {
491       associateViewsMenu.setVisible(false);
492       return;
493     }
494
495     associateViewsMenu.setVisible(true);
496
497     if ((viewMenu
498             .getItem(viewMenu.getItemCount() - 2) instanceof JMenuItem))
499     {
500       viewMenu.insertSeparator(viewMenu.getItemCount() - 1);
501     }
502
503     associateViewsMenu.removeAll();
504
505     JRadioButtonMenuItem item;
506     ButtonGroup buttonGroup = new ButtonGroup();
507     int iSize = aps.length;
508
509     for (int i = 0; i < iSize; i++)
510     {
511       final AlignmentPanel panel = aps[i];
512       item = new JRadioButtonMenuItem(panel.av.getViewName(),
513               panel.av == getRotatableCanvas().av);
514       buttonGroup.add(item);
515       item.addActionListener(new ActionListener()
516       {
517         @Override
518         public void actionPerformed(ActionEvent evt)
519         {
520           selectAssociatedView(panel);
521         }
522       });
523
524       associateViewsMenu.add(item);
525     }
526
527     final JRadioButtonMenuItem itemf = new JRadioButtonMenuItem(
528             "All Views");
529
530     buttonGroup.add(itemf);
531
532     itemf.setSelected(getRotatableCanvas().isApplyToAllViews());
533     itemf.addActionListener(new ActionListener()
534     {
535       @Override
536       public void actionPerformed(ActionEvent evt)
537       {
538         getRotatableCanvas().setApplyToAllViews(itemf.isSelected());
539       }
540     });
541     associateViewsMenu.add(itemf);
542
543   }
544
545   /*
546    * (non-Javadoc)
547    * 
548    * @see
549    * jalview.jbgui.GPaSiMapPanel#outputPoints_actionPerformed(java.awt.event.ActionEvent
550    * )
551    */
552   @Override
553   protected void outputPoints_actionPerformed()
554   {
555     CutAndPasteTransfer cap = new CutAndPasteTransfer();
556     try
557     {
558       cap.setText(getPasimapModel().getPointsasCsv(false,
559               xCombobox.getSelectedIndex(), yCombobox.getSelectedIndex(),
560               zCombobox.getSelectedIndex()));
561       Desktop.addInternalFrame(cap, MessageManager
562               .formatMessage("label.points_for_params", new String[]
563               { this.getTitle() }), 500, 500);
564     } catch (OutOfMemoryError oom)
565     {
566       new OOMWarning("exporting PaSiMap points", oom);
567       cap.dispose();
568     }
569   }
570
571   /*
572    * (non-Javadoc)
573    * 
574    * @see
575    * jalview.jbgui.GPaSiMapPanel#outputProjPoints_actionPerformed(java.awt.event
576    * .ActionEvent)
577    */
578   @Override
579   protected void outputProjPoints_actionPerformed()
580   {
581     CutAndPasteTransfer cap = new CutAndPasteTransfer();
582     try
583     {
584       cap.setText(getPasimapModel().getPointsasCsv(true,
585               xCombobox.getSelectedIndex(), yCombobox.getSelectedIndex(),
586               zCombobox.getSelectedIndex()));
587       Desktop.addInternalFrame(cap, MessageManager.formatMessage(
588               "label.transformed_points_for_params", new String[]
589               { this.getTitle() }), 500, 500);
590     } catch (OutOfMemoryError oom)
591     {
592       new OOMWarning("exporting transformed PaSiMap points", oom);
593       cap.dispose();
594     }
595   }
596
597   /*
598    * (non-Javadoc)
599    * 
600    * @see
601    * jalview.jbgui.GPaSiMapPanel#outputAlignment_actionPerformed(java.awt.event
602    * .ActionEvent)
603    */
604   @Override
605   protected void outputAlignment_actionPerformed()
606   {
607     CutAndPasteTransfer cap = new CutAndPasteTransfer();
608     try
609     {
610       cap.setText(getPasimapModel().getAlignmentOutput());
611       Desktop.addInternalFrame(cap, MessageManager.formatMessage(
612         "label.pairwise_alignment_for_params", new String[] { this.getTitle() }), 500, 500);
613     } catch (OutOfMemoryError oom)
614     {
615       new OOMWarning("exporting pairwise alignments", oom);
616       cap.dispose();
617     }
618   }
619
620   /*
621    * (non-Javadoc)
622    * 
623    * @see jalview.gui.IProgressIndicator#setProgressBar(java.lang.String, long)
624    */
625   @Override
626   public void setProgressBar(String message, long id)
627   {
628     progressBar.setProgressBar(message, id);
629     // if (progressBars == null)
630     // {
631     // progressBars = new Hashtable();
632     // progressBarHandlers = new Hashtable();
633     // }
634     //
635     // JPanel progressPanel;
636     // Long lId = Long.valueOf(id);
637     // GridLayout layout = (GridLayout) statusPanel.getLayout();
638     // if (progressBars.get(lId) != null)
639     // {
640     // progressPanel = (JPanel) progressBars.get(Long.valueOf(id));
641     // statusPanel.remove(progressPanel);
642     // progressBars.remove(lId);
643     // progressPanel = null;
644     // if (message != null)
645     // {
646     // statusBar.setText(message);
647     // }
648     // if (progressBarHandlers.contains(lId))
649     // {
650     // progressBarHandlers.remove(lId);
651     // }
652     // layout.setRows(layout.getRows() - 1);
653     // }
654     // else
655     // {
656     // progressPanel = new JPanel(new BorderLayout(10, 5));
657     //
658     // JProgressBar progressBar = new JProgressBar();
659     // progressBar.setIndeterminate(true);
660     //
661     // progressPanel.add(new JLabel(message), BorderLayout.WEST);
662     // progressPanel.add(progressBar, BorderLayout.CENTER);
663     //
664     // layout.setRows(layout.getRows() + 1);
665     // statusPanel.add(progressPanel);
666     //
667     // progressBars.put(lId, progressPanel);
668     // }
669     // // update GUI
670     // // setMenusForViewport();
671     // validate();
672   }
673
674   /*
675    * make the progressBar determinate and update its progress
676   */
677   public void updateProgressBar(int lengthOfTask, int progress)
678   {
679     JProgressBar pBar = progressBar.getProgressBar(progId);
680     if (pBar==null)
681     {
682       return;
683     }
684     if (pBar.isIndeterminate())
685     {
686       pBar.setMaximum(lengthOfTask);
687       pBar.setValue(0);
688       pBar.setIndeterminate(false);
689     }
690     updateProgressBar(progress);
691   }
692   public void updateProgressBar(int progress)
693   {
694     JProgressBar pBar = progressBar.getProgressBar(progId);
695     
696     if (pBar==null)
697     {
698       return;
699     }
700     
701     pBar.setValue(progress);
702     pBar.repaint();
703   }
704
705   //&!
706   public void setPairwiseAlignPanel(PairwiseAlignPanel pap)
707   {
708     pap.addPropertyChangeListener(new PropertyChangeListener()
709     {
710       @Override
711       public void propertyChange(PropertyChangeEvent pcEvent)
712       {
713         if (PairwiseAlignPanel.PROGRESS.equals(pcEvent.getPropertyName()))
714         {
715           updateProgressBar((int) pcEvent.getNewValue());
716         } else if (PairwiseAlignPanel.TOTAL.equals(pcEvent.getPropertyName())) {
717           updateProgressBar((int) pcEvent.getNewValue(), 0);
718         }
719       }
720     });
721   }
722
723   @Override
724   public void registerHandler(final long id,
725           final IProgressIndicatorHandler handler)
726   {
727     progressBar.registerHandler(id, handler);
728     // if (progressBarHandlers == null ||
729     // !progressBars.contains(Long.valueOf(id)))
730     // {
731     // throw new
732     // Error(MessageManager.getString("error.call_setprogressbar_before_registering_handler"));
733     // }
734     // progressBarHandlers.put(Long.valueOf(id), handler);
735     // final JPanel progressPanel = (JPanel) progressBars.get(Long.valueOf(id));
736     // if (handler.canCancel())
737     // {
738     // JButton cancel = new JButton(
739     // MessageManager.getString("action.cancel"));
740     // final IProgressIndicator us = this;
741     // cancel.addActionListener(new ActionListener()
742     // {
743     //
744     // @Override
745     // public void actionPerformed(ActionEvent e)
746     // {
747     // handler.cancelActivity(id);
748     // us.setProgressBar(MessageManager.formatMessage("label.cancelled_params",
749     // new String[]{((JLabel) progressPanel.getComponent(0)).getText()}), id);
750     // }
751     // });
752     // progressPanel.add(cancel, BorderLayout.EAST);
753     // }
754   }
755
756   /**
757    * 
758    * @return true if any progress bars are still active
759    */
760   @Override
761   public boolean operationInProgress()
762   {
763     return progressBar.operationInProgress();
764   }
765
766   @Override
767   protected void resetButton_actionPerformed()
768   {
769     int t = getTop();
770     setTop(0); // ugly - prevents dimensionChanged events from being processed
771     xCombobox.setSelectedIndex(0);
772     yCombobox.setSelectedIndex(1);
773     setTop(t);
774     zCombobox.setSelectedIndex(2);
775   }
776
777   /**
778    * Answers true if PaSiMap calculation is in progress, else false
779    * 
780    * @return
781    */
782   public boolean isWorking()
783   {
784     return working;
785   }
786
787   /**
788    * Answers the selected checkbox item index for PaSiMap dimension for the X, Y or
789    * Z axis of the display
790    * 
791    * @param axis
792    * @return
793    */
794   public int getSelectedDimensionIndex(Axis axis)
795   {
796     switch (axis)
797     {
798     case X:
799       return xCombobox.getSelectedIndex();
800     case Y:
801       return yCombobox.getSelectedIndex();
802     default:
803       return zCombobox.getSelectedIndex();
804     }
805   }
806
807   public void setShowLabels(boolean show)
808   {
809     showLabels.setSelected(show);
810   }
811
812   /**
813    * Sets the input data used to calculate the PaSiMap. This is provided for
814    * 'restore from project', which does not currently support this (AL-2647), so
815    * sets the value to null, and hides the menu option for "Input Data...". J
816    * 
817    * @param data
818    */
819   public void setInputData(AlignmentViewport data)
820   {
821     getPasimapModel().setInputData(data);
822     originalSeqData.setVisible(data != null);
823   }
824
825   public AlignViewportI getAlignViewport()
826   {
827     return av;
828   }
829
830   public PaSiMapModel getPasimapModel()
831   {
832     return pasimapModel;
833   }
834
835   public void setPasimapModel(PaSiMapModel pasimapModel)
836   {
837     this.pasimapModel = pasimapModel;
838   }
839
840   public RotatableCanvas getRotatableCanvas()
841   {
842     return rc;
843   }
844
845   public void setRotatableCanvas(RotatableCanvas rc)
846   {
847     this.rc = rc;
848   }
849
850   public int getTop()
851   {
852     return top;
853   }
854
855   public void setTop(int top)
856   {
857     this.top = top;
858   }
859
860   /**
861    * set the associated view for this PaSiMap.
862    * 
863    * @param panel
864    */
865   public void selectAssociatedView(AlignmentPanel panel)
866   {
867     getRotatableCanvas().setApplyToAllViews(false);
868
869     ap = panel;
870     av = panel.av;
871
872     getRotatableCanvas().av = panel.av;
873     getRotatableCanvas().ap = panel;
874     PaintRefresher.Register(PaSiMapPanel.this, panel.av.getSequenceSetId());
875   }
876
877   @Override
878   public JProgressBar getProgressBar(long id)
879   {
880     return progressBar.getProgressBar(id);
881   }
882 }