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