2 * Jalview - A Sequence Alignment Editor and Viewer (Version 2.8.2)
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
10 * of the License, or (at your option) any later version.
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.
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.
22 * Jalview - A Sequence Alignment Editor and Viewer
23 * Copyright (C) 2007 AM Waterhouse, J Procter, G Barton, M Clamp, S Searle
25 * This program is free software; you can redistribute it and/or
26 * modify it under the terms of the GNU General Public License
27 * as published by the Free Software Foundation; either version 2
28 * of the License, or (at your option) any later version.
30 * This program is distributed in the hope that it will be useful,
31 * but WITHOUT ANY WARRANTY; without even the implied warranty of
32 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
33 * GNU General Public License for more details.
35 * You should have received a copy of the GNU General Public License
36 * along with this program; if not, write to the Free Software
37 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
41 import jalview.analysis.AnnotationSorter.SequenceAnnotationOrder;
42 import jalview.analysis.NJTree;
43 import jalview.api.AlignViewportI;
44 import jalview.bin.Cache;
45 import jalview.datamodel.AlignmentAnnotation;
46 import jalview.datamodel.AlignmentI;
47 import jalview.datamodel.Annotation;
48 import jalview.datamodel.ColumnSelection;
49 import jalview.datamodel.PDBEntry;
50 import jalview.datamodel.Sequence;
51 import jalview.datamodel.SequenceGroup;
52 import jalview.datamodel.SequenceI;
53 import jalview.schemes.ColourSchemeProperty;
54 import jalview.schemes.UserColourScheme;
55 import jalview.structure.SelectionSource;
56 import jalview.structure.StructureSelectionManager;
57 import jalview.structure.VamsasSource;
58 import jalview.viewmodel.AlignmentViewport;
59 import jalview.ws.params.AutoCalcSetting;
61 import java.awt.Color;
62 import java.awt.Container;
64 import java.awt.Rectangle;
65 import java.util.ArrayList;
66 import java.util.Hashtable;
67 import java.util.Stack;
68 import java.util.Vector;
74 * @version $Revision: 1.141 $
76 public class AlignViewport extends AlignmentViewport implements
77 SelectionSource, VamsasSource, AlignViewportI
87 boolean showJVSuffix = true;
89 boolean showText = true;
91 boolean showColourText = false;
93 boolean showBoxes = true;
95 boolean wrapAlignment = false;
97 boolean renderGaps = true;
99 boolean showAnnotation = true;
101 SequenceAnnotationOrder sortAnnotationsBy = null;
107 boolean validCharWidth;
113 boolean seqNameItalics;
115 NJTree currentTree = null;
117 boolean scaleAboveWrapped = false;
119 boolean scaleLeftWrapped = true;
121 boolean scaleRightWrapped = true;
123 boolean showHiddenMarkers = true;
125 boolean cursorMode = false;
127 boolean antiAlias = false;
129 Rectangle explodedPosition;
133 boolean gatherViewsHere = false;
135 Stack historyList = new Stack();
137 Stack redoList = new Stack();
139 int thresholdTextColour = 0;
141 Color textColour = Color.black;
143 Color textColour2 = Color.white;
145 boolean rightAlignIds = false;
148 * Creates a new AlignViewport object.
153 public AlignViewport(AlignmentI al)
160 * Create a new AlignViewport object with a specific sequence set ID
164 * (may be null - but potential for ambiguous constructor exception)
166 public AlignViewport(AlignmentI al, String seqsetid)
168 this(al, seqsetid, null);
171 public AlignViewport(AlignmentI al, String seqsetid, String viewid)
173 sequenceSetID = seqsetid;
175 // TODO remove these once 2.4.VAMSAS release finished
176 if (Cache.log != null && Cache.log.isDebugEnabled() && seqsetid != null)
178 Cache.log.debug("Setting viewport's sequence set id : "
181 if (Cache.log != null && Cache.log.isDebugEnabled() && viewId != null)
183 Cache.log.debug("Setting viewport's view id : " + viewId);
190 * Create a new AlignViewport with hidden regions
194 * @param hiddenColumns
197 public AlignViewport(AlignmentI al, ColumnSelection hiddenColumns)
200 if (hiddenColumns != null)
202 this.colSel = hiddenColumns;
203 if (hiddenColumns.getHiddenColumns() != null
204 && hiddenColumns.getHiddenColumns().size() > 0)
206 hasHiddenColumns = true;
210 hasHiddenColumns = false;
217 * New viewport with hidden columns and an existing sequence set id
220 * @param hiddenColumns
224 public AlignViewport(AlignmentI al, ColumnSelection hiddenColumns,
227 this(al, hiddenColumns, seqsetid, null);
231 * New viewport with hidden columns and an existing sequence set id and viewid
234 * @param hiddenColumns
240 public AlignViewport(AlignmentI al, ColumnSelection hiddenColumns,
241 String seqsetid, String viewid)
243 sequenceSetID = seqsetid;
245 // TODO remove these once 2.4.VAMSAS release finished
246 if (Cache.log != null && Cache.log.isDebugEnabled() && seqsetid != null)
248 Cache.log.debug("Setting viewport's sequence set id : "
251 if (Cache.log != null && Cache.log.isDebugEnabled() && viewId != null)
253 Cache.log.debug("Setting viewport's view id : " + viewId);
256 if (hiddenColumns != null)
258 this.colSel = hiddenColumns;
259 if (hiddenColumns.getHiddenColumns() != null
260 && hiddenColumns.getHiddenColumns().size() > 0)
262 hasHiddenColumns = true;
266 hasHiddenColumns = false;
275 this.endRes = alignment.getWidth() - 1;
277 this.endSeq = alignment.getHeight() - 1;
279 antiAlias = Cache.getDefault("ANTI_ALIAS", false);
281 showJVSuffix = Cache.getDefault("SHOW_JVSUFFIX", true);
282 showAnnotation = Cache.getDefault("SHOW_ANNOTATIONS", true);
284 rightAlignIds = Cache.getDefault("RIGHT_ALIGN_IDS", false);
285 centreColumnLabels = Cache.getDefault("CENTRE_COLUMN_LABELS", false);
286 autoCalculateConsensus = Cache.getDefault("AUTO_CALC_CONSENSUS", true);
288 setPadGaps(Cache.getDefault("PAD_GAPS", true));
289 shownpfeats = Cache.getDefault("SHOW_NPFEATS_TOOLTIP", true);
290 showdbrefs = Cache.getDefault("SHOW_DBREFS_TOOLTIP", true);
292 String fontName = Cache.getDefault("FONT_NAME", "SansSerif");
293 String fontStyle = Cache.getDefault("FONT_STYLE", Font.PLAIN + "");
294 String fontSize = Cache.getDefault("FONT_SIZE", "10");
296 seqNameItalics = Cache.getDefault("ID_ITALICS", true);
300 if (fontStyle.equals("bold"))
304 else if (fontStyle.equals("italic"))
309 setFont(new Font(fontName, style, Integer.parseInt(fontSize)));
312 .setGapCharacter(Cache.getDefault("GAP_SYMBOL", "-").charAt(0));
314 // We must set conservation and consensus before setting colour,
315 // as Blosum and Clustal require this to be done
316 if (hconsensus == null && !isDataset)
318 if (!alignment.isNucleotide())
320 showConservation = Cache.getDefault("SHOW_CONSERVATION", true);
321 showQuality = Cache.getDefault("SHOW_QUALITY", true);
322 showGroupConservation = Cache.getDefault("SHOW_GROUP_CONSERVATION",
325 showConsensusHistogram = Cache.getDefault("SHOW_CONSENSUS_HISTOGRAM",
327 showSequenceLogo = Cache.getDefault("SHOW_CONSENSUS_LOGO", false);
328 normaliseSequenceLogo = Cache.getDefault("NORMALISE_CONSENSUS_LOGO",
330 showGroupConsensus = Cache.getDefault("SHOW_GROUP_CONSENSUS", false);
331 showConsensus = Cache.getDefault("SHOW_IDENTITY", true);
332 consensus = new AlignmentAnnotation("Consensus", "PID",
333 new Annotation[1], 0f, 100f, AlignmentAnnotation.BAR_GRAPH);
334 consensus.hasText = true;
335 consensus.autoCalculated = true;
337 initAutoAnnotation();
338 if (jalview.bin.Cache.getProperty("DEFAULT_COLOUR") != null)
340 globalColourScheme = ColourSchemeProperty.getColour(alignment,
341 jalview.bin.Cache.getProperty("DEFAULT_COLOUR"));
343 if (globalColourScheme instanceof UserColourScheme)
345 globalColourScheme = UserDefinedColours.loadDefaultColours();
346 ((UserColourScheme) globalColourScheme).setThreshold(0,
347 getIgnoreGapsConsensus());
350 if (globalColourScheme != null)
352 globalColourScheme.setConsensus(hconsensus);
356 wrapAlignment = Cache.getDefault("WRAP_ALIGNMENT", false);
357 showUnconserved = Cache.getDefault("SHOW_UNCONSERVED", false);
358 sortByTree = Cache.getDefault("SORT_BY_TREE", false);
359 followSelection = Cache.getDefault("FOLLOW_SELECTIONS", true);
360 sortAnnotationsBy = SequenceAnnotationOrder.valueOf(Cache.getDefault(
361 Preferences.SORT_ANNOTATIONS,
362 SequenceAnnotationOrder.NONE.name()));
363 showAutocalculatedAbove = Cache.getDefault(
364 Preferences.SHOW_AUTOCALC_ABOVE, false);
368 * centre columnar annotation labels in displayed alignment annotation TODO:
369 * add to jalviewXML and annotation display settings
371 boolean centreColumnLabels = false;
373 private boolean showdbrefs;
375 private boolean shownpfeats;
377 // --------END Structure Conservation
380 * get the consensus sequence as displayed under the PID consensus annotation
383 * @return consensus sequence as a new sequence object
385 public SequenceI getConsensusSeq()
387 if (consensus == null)
389 updateConsensus(null);
391 if (consensus == null)
395 StringBuffer seqs = new StringBuffer();
396 for (int i = 0; i < consensus.annotations.length; i++)
398 if (consensus.annotations[i] != null)
400 if (consensus.annotations[i].description.charAt(0) == '[')
402 seqs.append(consensus.annotations[i].description.charAt(1));
406 seqs.append(consensus.annotations[i].displayCharacter);
411 SequenceI sq = new Sequence("Consensus", seqs.toString());
412 sq.setDescription("Percentage Identity Consensus "
413 + ((ignoreGapsInConsensusCalculation) ? " without gaps" : ""));
420 * @return DOCUMENT ME!
422 public int getStartRes()
430 * @return DOCUMENT ME!
432 public int getEndRes()
440 * @return DOCUMENT ME!
442 public int getStartSeq()
453 public void setStartRes(int res)
464 public void setStartSeq(int seq)
475 public void setEndRes(int res)
477 if (res > (alignment.getWidth() - 1))
479 // log.System.out.println(" Corrected res from " + res + " to maximum " +
480 // (alignment.getWidth()-1));
481 res = alignment.getWidth() - 1;
498 public void setEndSeq(int seq)
500 if (seq > alignment.getHeight())
502 seq = alignment.getHeight();
516 * @return DOCUMENT ME!
518 public int getEndSeq()
529 public void setFont(Font f)
533 Container c = new Container();
535 java.awt.FontMetrics fm = c.getFontMetrics(font);
536 setCharHeight(fm.getHeight());
537 setCharWidth(fm.charWidth('M'));
538 validCharWidth = true;
544 * @return DOCUMENT ME!
546 public Font getFont()
557 public void setCharWidth(int w)
565 * @return DOCUMENT ME!
567 public int getCharWidth()
578 public void setCharHeight(int h)
586 * @return DOCUMENT ME!
588 public int getCharHeight()
599 public void setWrappedWidth(int w)
601 this.wrappedWidth = w;
607 * @return DOCUMENT ME!
609 public int getWrappedWidth()
617 * @return DOCUMENT ME!
619 public AlignmentI getAlignment()
630 public void setAlignment(AlignmentI align)
632 if (alignment != null && alignment.getCodonFrames() != null)
634 StructureSelectionManager.getStructureSelectionManager(
635 Desktop.instance).removeMappings(alignment.getCodonFrames());
637 this.alignment = align;
638 if (alignment != null && alignment.getCodonFrames() != null)
640 StructureSelectionManager.getStructureSelectionManager(
641 Desktop.instance).addMappings(alignment.getCodonFrames());
651 public void setWrapAlignment(boolean state)
653 wrapAlignment = state;
662 public void setShowText(boolean state)
673 public void setRenderGaps(boolean state)
681 * @return DOCUMENT ME!
683 public boolean getColourText()
685 return showColourText;
694 public void setColourText(boolean state)
696 showColourText = state;
705 public void setShowBoxes(boolean state)
713 * @return DOCUMENT ME!
715 public boolean getWrapAlignment()
717 return wrapAlignment;
723 * @return DOCUMENT ME!
725 public boolean getShowText()
733 * @return DOCUMENT ME!
735 public boolean getShowBoxes()
743 * @return DOCUMENT ME!
745 public char getGapCharacter()
747 return getAlignment().getGapCharacter();
756 public void setGapCharacter(char gap)
758 if (getAlignment() != null)
760 getAlignment().setGapCharacter(gap);
767 * @return DOCUMENT ME!
769 public ColumnSelection getColumnSelection()
780 public void setCurrentTree(NJTree tree)
788 * @return DOCUMENT ME!
790 public NJTree getCurrentTree()
798 * @return DOCUMENT ME!
800 public boolean getShowJVSuffix()
811 public void setShowJVSuffix(boolean b)
819 * @return DOCUMENT ME!
821 public boolean getShowAnnotation()
823 return showAnnotation;
832 public void setShowAnnotation(boolean b)
840 * @return DOCUMENT ME!
842 public boolean getScaleAboveWrapped()
844 return scaleAboveWrapped;
850 * @return DOCUMENT ME!
852 public boolean getScaleLeftWrapped()
854 return scaleLeftWrapped;
860 * @return DOCUMENT ME!
862 public boolean getScaleRightWrapped()
864 return scaleRightWrapped;
873 public void setScaleAboveWrapped(boolean b)
875 scaleAboveWrapped = b;
884 public void setScaleLeftWrapped(boolean b)
886 scaleLeftWrapped = b;
895 public void setScaleRightWrapped(boolean b)
897 scaleRightWrapped = b;
900 public void setDataset(boolean b)
905 public boolean isDataset()
910 public boolean getShowHiddenMarkers()
912 return showHiddenMarkers;
915 public void setShowHiddenMarkers(boolean show)
917 showHiddenMarkers = show;
921 * returns the visible column regions of the alignment
923 * @param selectedRegionOnly
924 * true to just return the contigs intersecting with the selected
928 public int[] getViewAsVisibleContigs(boolean selectedRegionOnly)
930 int[] viscontigs = null;
931 int start = 0, end = 0;
932 if (selectedRegionOnly && selectionGroup != null)
934 start = selectionGroup.getStartRes();
935 end = selectionGroup.getEndRes() + 1;
939 end = alignment.getWidth();
941 viscontigs = colSel.getVisibleContigs(start, end);
946 * get hash of undo and redo list for the alignment
948 * @return long[] { historyList.hashCode, redoList.hashCode };
950 public long[] getUndoRedoHash()
953 if (historyList == null || redoList == null)
959 { historyList.hashCode(), this.redoList.hashCode() };
963 * test if a particular set of hashcodes are different to the hashcodes for
964 * the undo and redo list.
967 * the stored set of hashcodes as returned by getUndoRedoHash
968 * @return true if the hashcodes differ (ie the alignment has been edited) or
969 * the stored hashcode array differs in size
971 public boolean isUndoRedoHashModified(long[] undoredo)
973 if (undoredo == null)
977 long[] cstate = getUndoRedoHash();
978 if (cstate.length != undoredo.length)
983 for (int i = 0; i < cstate.length; i++)
985 if (cstate[i] != undoredo[i])
993 public boolean getCentreColumnLabels()
995 return centreColumnLabels;
998 public void setCentreColumnLabels(boolean centrecolumnlabels)
1000 centreColumnLabels = centrecolumnlabels;
1004 * enable or disable the display of Database Cross References in the sequence
1007 public void setShowDbRefs(boolean show)
1014 * @return true if Database References are to be displayed on tooltips.
1016 public boolean isShowDbRefs()
1023 * @return true if Non-positional features are to be displayed on tooltips.
1025 public boolean isShowNpFeats()
1031 * enable or disable the display of Non-Positional sequence features in the
1032 * sequence ID tooltip
1036 public void setShowNpFeats(boolean show)
1043 * @return true if view has hidden rows
1045 public boolean hasHiddenRows()
1047 return hasHiddenRows;
1052 * @return true if view has hidden columns
1054 public boolean hasHiddenColumns()
1056 return hasHiddenColumns;
1060 * when set, view will scroll to show the highlighted position
1062 public boolean followHighlight = true;
1065 * @return true if view should scroll to show the highlighted region of a
1069 public boolean getFollowHighlight()
1071 return followHighlight;
1074 public boolean followSelection = true;
1077 * @return true if view selection should always follow the selections
1078 * broadcast by other selection sources
1080 public boolean getFollowSelection()
1082 return followSelection;
1085 public void sendSelection()
1087 jalview.structure.StructureSelectionManager
1088 .getStructureSelectionManager(Desktop.instance).sendSelection(
1089 new SequenceGroup(getSelectionGroup()),
1090 new ColumnSelection(getColumnSelection()), this);
1094 * return the alignPanel containing the given viewport. Use this to get the
1095 * components currently handling the given viewport.
1098 * @return null or an alignPanel guaranteed to have non-null alignFrame
1101 public AlignmentPanel getAlignPanel()
1103 AlignmentPanel[] aps = PaintRefresher.getAssociatedPanels(this
1104 .getSequenceSetId());
1105 AlignmentPanel ap = null;
1106 for (int p = 0; aps != null && p < aps.length; p++)
1108 if (aps[p].av == this)
1116 public boolean getSortByTree()
1121 public void setSortByTree(boolean sort)
1127 * synthesize a column selection if none exists so it covers the given
1128 * selection group. if wholewidth is false, no column selection is made if the
1129 * selection group covers the whole alignment width.
1134 public void expandColSelection(SequenceGroup sg, boolean wholewidth)
1138 && (sgs = sg.getStartRes()) >= 0
1139 && sg.getStartRes() <= (sge = sg.getEndRes())
1140 && (colSel == null || colSel.getSelected() == null || colSel
1141 .getSelected().size() == 0))
1143 if (!wholewidth && alignment.getWidth() == (1 + sge - sgs))
1150 colSel = new ColumnSelection();
1152 for (int cspos = sg.getStartRes(); cspos <= sg.getEndRes(); cspos++)
1154 colSel.addElement(cspos);
1159 public StructureSelectionManager getStructureSelectionManager()
1161 return StructureSelectionManager
1162 .getStructureSelectionManager(Desktop.instance);
1168 * @return a series of SequenceI arrays, one for each PDBEntry, listing which
1169 * sequence in the alignment holds a reference to it
1171 public SequenceI[][] collateForPDB(PDBEntry[] pdbEntries)
1173 ArrayList<SequenceI[]> seqvectors = new ArrayList<SequenceI[]>();
1174 for (PDBEntry pdb : pdbEntries)
1176 ArrayList<SequenceI> seqs = new ArrayList<SequenceI>();
1177 for (int i = 0; i < alignment.getHeight(); i++)
1179 Vector pdbs = alignment.getSequenceAt(i).getDatasetSequence()
1186 for (int p = 0; p < pdbs.size(); p++)
1188 PDBEntry p1 = (PDBEntry) pdbs.elementAt(p);
1189 if (p1.getId().equals(pdb.getId()))
1191 if (!seqs.contains(sq = alignment.getSequenceAt(i)))
1200 seqvectors.add(seqs.toArray(new SequenceI[seqs.size()]));
1202 return seqvectors.toArray(new SequenceI[seqvectors.size()][]);
1205 public boolean isNormaliseSequenceLogo()
1207 return normaliseSequenceLogo;
1210 public void setNormaliseSequenceLogo(boolean state)
1212 normaliseSequenceLogo = state;
1217 * @return true if alignment characters should be displayed
1219 public boolean isValidCharWidth()
1221 return validCharWidth;
1224 private Hashtable<String, AutoCalcSetting> calcIdParams = new Hashtable<String, AutoCalcSetting>();
1226 private boolean showAutocalculatedAbove;
1228 public AutoCalcSetting getCalcIdSettingsFor(String calcId)
1230 return calcIdParams.get(calcId);
1233 public void setCalcIdSettingsFor(String calcId, AutoCalcSetting settings,
1234 boolean needsUpdate)
1236 calcIdParams.put(calcId, settings);
1237 // TODO: create a restart list to trigger any calculations that need to be
1238 // restarted after load
1239 // calculator.getRegisteredWorkersOfClass(settings.getWorkerClass())
1242 Cache.log.debug("trigger update for " + calcId);
1246 protected SequenceAnnotationOrder getSortAnnotationsBy()
1248 return sortAnnotationsBy;
1251 protected void setSortAnnotationsBy(SequenceAnnotationOrder sortAnnotationsBy)
1253 this.sortAnnotationsBy = sortAnnotationsBy;
1256 protected boolean isShowAutocalculatedAbove()
1258 return showAutocalculatedAbove;
1261 protected void setShowAutocalculatedAbove(boolean showAutocalculatedAbove)
1263 this.showAutocalculatedAbove = showAutocalculatedAbove;