<file-match-pattern match-pattern="src/.*.java" include-pattern="true"/>
<file-match-pattern match-pattern="resources/.*.properties" include-pattern="true"/>
</fileset>
- <filter name="NonSrcDirs" enabled="false"/>
</fileset-config>
--- /dev/null
+/*
+ * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
+ * Copyright (C) $$Year-Rel$$ The Jalview Authors
+ *
+ * This file is part of Jalview.
+ *
+ * Jalview is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, either version 3
+ * of the License, or (at your option) any later version.
+ *
+ * Jalview is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Jalview. If not, see <http://www.gnu.org/licenses/>.
+ * The Jalview Authors are detailed in the 'AUTHORS' file.
+ */
+
+import jalview.analysis.scoremodels.ScoreModels
+import jalview.analysis.scoremodels.SimilarityParams
+
+// generate matrix for current selection using standard Jalview PID
+
+printSimilarityMatrix(true,true,SimilarityParams.Jalview)
+
+/**
+ * this function prints a sequence similarity matrix in PHYLIP format.
+ * printSimilarityMatrix(selected-only, include-ids, pidMethod)
+ *
+ * Allowed values for pidMethod:
+ *
+ * Jalview's Comparison.PID method includes matching gaps
+ * and counts over the length of the shorter gapped sequence
+ * SimilarityParams.Jalview;
+ *
+ * 'SeqSpace' mode PCA calculation does not count matching
+ * gaps but uses longest gapped sequence length
+ * SimilarityParams.SeqSpace;
+ *
+ * PID calcs from the Raghava-Barton paper
+ * SimilarityParams.PID1: ignores gap-gap, does not score gap-residue,
+ * includes gap-residue in lengths, matches on longer of two sequences.
+ *
+ * SimilarityParams.PID2: ignores gap-gap,ignores gap-residue,
+ * matches on longer of two sequences
+ *
+ * SimilarityParams.PID3: ignores gap-gap,ignores gap-residue,
+ * matches on shorter of sequences only
+ *
+ * SimilarityParams.PID4: ignores gap-gap,does not score gap-residue,
+ * includes gap-residue in lengths,matches on shorter of sequences only.
+ */
+
+void printSimilarityMatrix(boolean selview=false, boolean includeids=true, SimilarityParams pidMethod) {
+
+ def currentAlignFrame = jalview.bin.Jalview.getCurrentAlignFrame()
+
+ jalview.gui.AlignViewport av = currentAlignFrame.getCurrentView()
+
+ jalview.datamodel.AlignmentView seqStrings = av.getAlignmentView(selview)
+
+ if (!selview || av.getSelectionGroup()==null) {
+ start = 0
+ end = av.getAlignment().getWidth()
+ seqs = av.getAlignment().getSequencesArray()
+ } else {
+ start = av.getSelectionGroup().getStartRes()
+ end = av.getSelectionGroup().getEndRes() + 1
+ seqs = av.getSelectionGroup().getSequencesInOrder(av.getAlignment())
+ }
+
+ distanceCalc = ScoreModels.getInstance().getScoreModel("PID",
+ (jalview.api.AlignmentViewPanel) currentAlignFrame.alignPanel)
+
+ def distance=distanceCalc.findSimilarities(
+ seqStrings.getSequenceStrings(jalview.util.Comparison.GAP_DASH),pidMethod)
+
+ // output the PHYLIP Matrix
+
+ print distance.width()+" "+distance.height()+"\n"
+
+ p = 0
+
+ for (v in 1..distance.height()) {
+
+ if (includeids) {
+ print seqs[p++].getDisplayId(false)+" "
+ }
+
+ for (r in 1..distance.width()) {
+ print distance.getValue(v-1,r-1)+" "
+ }
+
+ print "\n"
+ }
+}
\ No newline at end of file
<!-- JAL-2446 -->Faster and more efficient management and
rendering of sequence features
</li>
+ <li>
+ <!-- JAL 2523-->More reliable Ensembl fetching with HTTP
+ 429 rate limit request hander
+ </li>
+ <li>
+ <!-- JAL-2773 -->Structure views don't get updated unless
+ their colours have changed
+ </li>
</ul>
+ <ul><li>Example groovy script for generating a matrix of percent identity scores for current alignment.</li></ul>
</td>
<td><div align="left">
<em></em>
<ul>
+ <li><!-- JAL-2777 -->Structures with whitespace chainCode cannot be viewed in Chimera</li>
<li><!-- JAL-2728 -->Protein annotation panel too high in CDS/Protein view
</li>
+ <li><!-- JAL-2757 -->Can't edit the query after the server error warning icon is shown in Uniprot and PDB Free Text Search Dialogs
+ </li>
+ <li><!-- JAL-2253 -->Slow EnsemblGenome ID lookup</li>
+ <li><!-- JAL-2682 -->Race condition when parsing sequence ID strings in parallel</li>
+ <li><!-- JAL-2739 -->Hidden column marker in last column not rendered when switching back from Wrapped to normal view</li>
+ <li><!-- JAL-2768 -->Annotation display corrupted when scrolling right in unwapped alignment view</li>
</ul>
</td>
</tr>
public void splitInsertionCode(String residue)
{
// OK, split the index into number and insertion code
+ // JBPNote - m.matches() can be true even if there is no resnum - this can
+ // cause NumberFormatExceptions below
Pattern p = Pattern.compile("(\\d*)([A-Z]?)");
Matcher m = p.matcher(residue);
if (m.matches())
import jalview.datamodel.AlignmentAnnotation;
import jalview.datamodel.AlignmentI;
import jalview.datamodel.AlignmentView;
-import jalview.datamodel.CigarArray;
import jalview.datamodel.ColumnSelection;
import jalview.datamodel.ProfilesI;
import jalview.datamodel.SearchResultsI;
void clearSequenceColours();
/**
- * This method returns the visible alignment as text, as seen on the GUI, ie
- * if columns are hidden they will not be returned in the result. Use this for
- * calculating trees, PCA, redundancy etc on views which contain hidden
- * columns.
- *
- * @return String[]
- */
- CigarArray getViewAsCigars(boolean selectedRegionOnly);
-
- /**
* return a compact representation of the current alignment selection to pass
* to an analysis function
*
*
* @return
*/
+ @Override
boolean isProteinFontAsCdna();
/**
*
* @return
*/
+ @Override
void setProteinFontAsCdna(boolean b);
}
*
* @param updateOverview
* - if true, the overview panel will also be updated and repainted
+ * @param updateStructures
+ * - if true then any linked structure views will also be updated
*/
-
- void paintAlignment(boolean updateOverview);
+ void paintAlignment(boolean updateOverview, boolean updateStructures);
/**
* automatically adjust annotation panel height for new annotation whilst
void addFeatureLinks(final SequenceI seq, List<String> links)
{
Menu linkMenu = new Menu(MessageManager.getString("action.link"));
- Map<String, List<String>> linkset = new LinkedHashMap<String, List<String>>();
+ Map<String, List<String>> linkset = new LinkedHashMap<>();
for (String link : links)
{
* Temporary store to hold distinct calcId / type pairs for the tooltip.
* Using TreeMap means calcIds are shown in alphabetical order.
*/
- SortedMap<String, String> tipEntries = new TreeMap<String, String>();
- final Map<SequenceI, List<AlignmentAnnotation>> candidates = new LinkedHashMap<SequenceI, List<AlignmentAnnotation>>();
+ SortedMap<String, String> tipEntries = new TreeMap<>();
+ final Map<SequenceI, List<AlignmentAnnotation>> candidates = new LinkedHashMap<>();
AlignmentI al = this.ap.av.getAlignment();
AlignmentUtils.findAddableReferenceAnnotations(forSequences, tipEntries,
candidates, al);
}
int gSize = sg.getSize();
- List<SequenceI> seqs = new ArrayList<SequenceI>();
- List<SequenceFeature> features = new ArrayList<SequenceFeature>();
+ List<SequenceI> seqs = new ArrayList<>();
+ List<SequenceFeature> features = new ArrayList<>();
for (int i = 0; i < gSize; i++)
{
{
seq.setName(dialog.getName());
seq.setDescription(dialog.getDescription());
- ap.paintAlignment(false);
+ ap.paintAlignment(false, false);
}
}
void refresh()
{
- ap.paintAlignment(true);
+ ap.paintAlignment(true, true);
}
protected void clustalColour_actionPerformed()
SequenceGroup sg = ap.av.getSelectionGroup();
ap.av.getAlignment().deleteGroup(sg);
ap.av.setSelectionGroup(null);
- ap.paintAlignment(true);
+ ap.paintAlignment(true, true);
}
void createGroupMenuItem_actionPerformed()
* the insertion order, which is the order of the annotations on the
* alignment.
*/
- Map<String, List<List<String>>> shownTypes = new LinkedHashMap<String, List<List<String>>>();
- Map<String, List<List<String>>> hiddenTypes = new LinkedHashMap<String, List<List<String>>>();
+ Map<String, List<List<String>>> shownTypes = new LinkedHashMap<>();
+ Map<String, List<List<String>>> hiddenTypes = new LinkedHashMap<>();
AlignmentAnnotationUtils.getShownHiddenTypes(shownTypes, hiddenTypes,
AlignmentAnnotationUtils.asList(annotations), forSequences);
createAlignFrameWindow(embedded);
validate();
alignPanel.adjustAnnotationHeight();
- alignPanel.paintAlignment(true);
+ alignPanel.paintAlignment(true, true);
}
public AlignViewport getAlignViewport()
{
viewport.featureSettings.refreshTable();
}
- alignPanel.paintAlignment(true);
+ alignPanel.paintAlignment(true, true);
statusBar.setText(MessageManager
.getString("label.successfully_added_features_alignment"));
}
break;
}
- alignPanel.paintAlignment(true);
+ // TODO: repaint flags set only if the keystroke warrants it
+ alignPanel.paintAlignment(true, true);
}
/**
{
applyAutoAnnotationSettings_actionPerformed();
}
- alignPanel.paintAlignment(true);
+ // TODO: repaint flags set only if warranted
+ alignPanel.paintAlignment(true, true);
}
/**
else if (source == invertColSel)
{
viewport.invertColumnSelection();
- alignPanel.paintAlignment(true);
+ alignPanel.paintAlignment(false, false);
viewport.sendSelection();
}
else if (source == remove2LeftMenuItem)
else if (source == showColumns)
{
viewport.showAllHiddenColumns();
- alignPanel.paintAlignment(true);
+ alignPanel.paintAlignment(true, true);
viewport.sendSelection();
}
else if (source == showSeqs)
{
viewport.showAllHiddenSeqs();
- alignPanel.paintAlignment(true);
+ alignPanel.paintAlignment(true, true);
// uncomment if we want to slave sequence selections in split frame
// viewport.sendSelection();
}
else if (source == hideColumns)
{
viewport.hideSelectedColumns();
- alignPanel.paintAlignment(true);
+ alignPanel.paintAlignment(true, true);
viewport.sendSelection();
}
else if (source == hideSequences
&& viewport.getSelectionGroup() != null)
{
viewport.hideAllSelectedSeqs();
- alignPanel.paintAlignment(true);
+ alignPanel.paintAlignment(true, true);
// uncomment if we want to slave sequence selections in split frame
// viewport.sendSelection();
}
else if (source == hideAllButSelection)
{
toggleHiddenRegions(false, false);
- alignPanel.paintAlignment(true);
+ alignPanel.paintAlignment(true, true);
viewport.sendSelection();
}
else if (source == hideAllSelection)
viewport.expandColSelection(sg, false);
viewport.hideAllSelectedSeqs();
viewport.hideSelectedColumns();
- alignPanel.paintAlignment(true);
+ alignPanel.paintAlignment(true, true);
viewport.sendSelection();
}
else if (source == showAllHidden)
{
viewport.showAllHiddenColumns();
viewport.showAllHiddenSeqs();
- alignPanel.paintAlignment(true);
+ alignPanel.paintAlignment(true, true);
viewport.sendSelection();
}
else if (source == showGroupConsensus)
}
viewport.getAlignment().moveSelectedSequencesByOne(sg,
up ? null : viewport.getHiddenRepSequences(), up);
- alignPanel.paintAlignment(true);
+ alignPanel.paintAlignment(true, false);
/*
* Also move cDNA/protein complement sequences
viewport, complement);
complement.getAlignment().moveSelectedSequencesByOne(mappedSelection,
up ? null : complement.getHiddenRepSequences(), up);
- getSplitFrame().getComplement(this).alignPanel.paintAlignment(true);
+ getSplitFrame().getComplement(this).alignPanel.paintAlignment(true,
+ false);
}
}
{
PaintRefresher.Refresh(this, viewport.getSequenceSetId());
alignPanel.updateAnnotation();
- alignPanel.paintAlignment(true);
+ alignPanel.paintAlignment(true, true);
}
}
// JAL-2034 - should delegate to
// alignPanel to decide if overview needs
// updating.
- alignPanel.paintAlignment(false);
+ alignPanel.paintAlignment(false, false);
PaintRefresher.Refresh(alignPanel, viewport.getSequenceSetId());
viewport.sendSelection();
}
// JAL-2034 - should delegate to
// alignPanel to decide if overview needs
// updating.
- alignPanel.paintAlignment(false);
+ alignPanel.paintAlignment(false, false);
PaintRefresher.Refresh(alignPanel, viewport.getSequenceSetId());
viewport.sendSelection();
}
public void invertColSel_actionPerformed()
{
viewport.invertColumnSelection();
- alignPanel.paintAlignment(true);
+ alignPanel.paintAlignment(true, false);
PaintRefresher.Refresh(alignPanel, viewport.getSequenceSetId());
viewport.sendSelection();
}
{
viewport.setShowJVSuffix(seqLimits.getState());
alignPanel.fontChanged();
- alignPanel.paintAlignment(true);
+ alignPanel.paintAlignment(true, false);
}
protected void colourTextMenuItem_actionPerformed()
{
viewport.setColourText(colourTextMenuItem.getState());
- alignPanel.paintAlignment(true);
+ alignPanel.paintAlignment(false, false);
}
protected void displayNonconservedMenuItem_actionPerformed()
{
viewport.setShowUnconserved(displayNonconservedMenuItem.getState());
- alignPanel.paintAlignment(true);
+ alignPanel.paintAlignment(false, false);
}
protected void wrapMenuItem_actionPerformed()
scaleAbove.setEnabled(wrapMenuItem.getState());
scaleLeft.setEnabled(wrapMenuItem.getState());
scaleRight.setEnabled(wrapMenuItem.getState());
- alignPanel.paintAlignment(true);
+ alignPanel.paintAlignment(true, false);
}
public void overviewMenuItem_actionPerformed()
{
viewport.setGlobalColourScheme(cs);
- alignPanel.paintAlignment(true);
+ alignPanel.paintAlignment(true, true);
}
protected void modifyPID_actionPerformed()
addHistoryItem(new OrderCommand("Pairwise Sort", oldOrder,
viewport.getAlignment()));
- alignPanel.paintAlignment(true);
+ alignPanel.paintAlignment(true, false);
}
public void sortIDMenuItem_actionPerformed()
AlignmentSorter.sortByID(viewport.getAlignment());
addHistoryItem(
new OrderCommand("ID Sort", oldOrder, viewport.getAlignment()));
- alignPanel.paintAlignment(true);
+ alignPanel.paintAlignment(true, false);
}
public void sortLengthMenuItem_actionPerformed()
AlignmentSorter.sortByLength(viewport.getAlignment());
addHistoryItem(new OrderCommand("Length Sort", oldOrder,
viewport.getAlignment()));
- alignPanel.paintAlignment(true);
+ alignPanel.paintAlignment(true, false);
}
public void sortGroupMenuItem_actionPerformed()
AlignmentSorter.sortByGroup(viewport.getAlignment());
addHistoryItem(new OrderCommand("Group Sort", oldOrder,
viewport.getAlignment()));
- alignPanel.paintAlignment(true);
+ alignPanel.paintAlignment(true, false);
}
current.insertCharAt(Width - 1, viewport.getGapCharacter());
}
}
- alignPanel.paintAlignment(true);
+ alignPanel.paintAlignment(false, false);
}
if ((viewport.getSelectionGroup() != null
current.insertCharAt(Width - 1, viewport.getGapCharacter());
}
}
- alignPanel.paintAlignment(true);
+ alignPanel.paintAlignment(false, false);
}
addHistoryItem(new OrderCommand(MessageManager
.formatMessage("label.order_by_params", new String[]
{ title }), oldOrder, viewport.getAlignment()));
- alignPanel.paintAlignment(true);
+ alignPanel.paintAlignment(true, false);
}
/**
addHistoryItem(new OrderCommand(undoname, oldOrder,
viewport.getAlignment()));
}
- alignPanel.paintAlignment(true);
+ alignPanel.paintAlignment(true, false);
return true;
}
vpRanges.scrollToWrappedVisible(start);
}
- paintAlignment(redrawOverview);
+ paintAlignment(redrawOverview, false);
return true;
}
apvscroll.addNotify();
hscroll.addNotify();
validate();
- paintAlignment(true);
+ paintAlignment(true, false);
}
/**
* Repaint the alignment and annotations, and, optionally, any overview window
*/
@Override
- public void paintAlignment(boolean updateOverview)
+ public void paintAlignment(boolean updateOverview,
+ boolean updateStructures)
{
final AnnotationSorter sorter = new AnnotationSorter(getAlignment(),
av.isShowAutocalculatedAbove());
av.getSortAnnotationsBy());
repaint();
- if (updateOverview)
+ if (updateStructures)
{
- // TODO: determine if this paintAlignment changed structure colours
jalview.structure.StructureSelectionManager
.getStructureSelectionManager(av.applet)
.sequenceColoursChanged(this);
-
+ }
+ if (updateOverview)
+ {
if (overviewPanel != null)
{
overviewPanel.updateOverviewImage();
oldcs = av.getGlobalColourScheme();
if (av.getAlignment().getGroups() != null)
{
- oldgroupColours = new HashMap<SequenceGroup, ColourSchemeI>();
+ oldgroupColours = new HashMap<>();
for (SequenceGroup sg : ap.av.getAlignment().getGroups())
{
oldgroupColours.put(sg, sg.getColourScheme());
// TODO remove duplication with gui.AnnotationRowFilter
// TODO add 'per sequence only' option / parameter
- annotationLabels = new HashMap<AlignmentAnnotation, String>();
- Vector<String> list = new Vector<String>();
+ annotationLabels = new HashMap<>();
+ Vector<String> list = new Vector<>();
AlignmentAnnotation[] anns = av.getAlignment().getAlignmentAnnotation();
if (anns == null)
{
else if (evt.getSource() == cancel)
{
reset();
- ap.paintAlignment(true);
+ ap.paintAlignment(true, true);
frame.setVisible(false);
}
}
currentAnnotation.threshold.value = slider.getValue() / 1000f;
- ap.paintAlignment(false);
+ ap.paintAlignment(false, false);
}
}
// update colours in linked windows
ap.alignmentChanged();
- ap.paintAlignment(true);
+ ap.paintAlignment(true, true);
}
void reset()
sg.setColourScheme(oldgroupColours.get(sg));
}
}
- ap.paintAlignment(true);
+ ap.paintAlignment(true, true);
}
@Override
@Override
public void mouseReleased(MouseEvent evt)
{
- ap.paintAlignment(true);
+ ap.paintAlignment(true, true);
}
@Override
av.getAlignment().setHiddenColumns(oldHidden);
}
av.sendSelection();
- ap.paintAlignment(true);
+ ap.paintAlignment(true, true);
}
}
sliderDragging = false;
valueChanged(true);
}
- ap.paintAlignment(true);
+ ap.paintAlignment(true, true);
}
});
}
if (slider.isEnabled())
{
getCurrentAnnotation().threshold.value = slider.getValue() / 1000f;
- updateView();
- ap.paintAlignment(false);
+ updateView(); // this also calls paintAlignment(true,true)
}
}
filterParams = null;
av.setAnnotationColumnSelectionState(this);
av.sendSelection();
- ap.paintAlignment(true);
+ ap.paintAlignment(true, true);
}
public HiddenColumns getOldHiddenColumns()
ap.annotationPanel.adjustPanelHeight();
setSize(getSize().width, ap.annotationPanel.getSize().height);
ap.validate();
- ap.paintAlignment(true);
+ // TODO: only paint if we needed to
+ ap.paintAlignment(true, true);
}
boolean editLabelDescription(AlignmentAnnotation annotation)
{
ap.av.setIgnoreGapsConsensus(cbmi.getState(), ap);
}
- ap.paintAlignment(true);
+ ap.paintAlignment(true, true);
}
});
popup.add(cbmi);
}
}
}
- ap.paintAlignment(false);
+ ap.paintAlignment(false, false);
PaintRefresher.Refresh(ap, ap.av.getSequenceSetId());
ap.av.sendSelection();
}
sg.addSequence(aa[selectedRow].sequenceRef, false);
}
ap.av.setSelectionGroup(sg);
- ap.paintAlignment(false);
+ ap.paintAlignment(false, false);
PaintRefresher.Refresh(ap, ap.av.getSequenceSetId());
ap.av.sendSelection();
}
graphStretchY = evt.getY();
av.calcPanelHeight();
needValidating = true;
- ap.paintAlignment(true);
+ // TODO: only update overview visible geometry
+ ap.paintAlignment(true, false);
}
else
{
public void cancel_actionPerformed(ActionEvent e)
{
reset();
- ap.paintAlignment(true);
+ ap.paintAlignment(true, true);
frame.setVisible(false);
}
}
// findAllFeatures();
- ap.paintAlignment(true);
+ ap.paintAlignment(true, true);
return true;
}
// Group selection states
void resetTable(boolean groupsChanged)
{
- List<String> displayableTypes = new ArrayList<String>();
- Set<String> foundGroups = new HashSet<String>();
+ List<String> displayableTypes = new ArrayList<>();
+ Set<String> foundGroups = new HashSet<>();
AlignmentI alignment = av.getAlignment();
* and keep track of which groups are visible
*/
Set<String> groups = seq.getFeatures().getFeatureGroups(true);
- Set<String> visibleGroups = new HashSet<String>();
+ Set<String> visibleGroups = new HashSet<>();
for (String group : groups)
{
// if (group == null || fr.checkGroupVisibility(group, true))
fr.setFeaturePriority(data);
- ap.paintAlignment(updateOverview);
+ ap.paintAlignment(updateOverview, updateOverview);
}
MyCheckbox selectedCheck;
{
featurePanel.removeAll();
resetTable(false);
- ap.paintAlignment(true);
+ ap.paintAlignment(true, true);
}
@Override
public void adjustmentValueChanged(AdjustmentEvent evt)
{
fr.setTransparency((100 - transparency.getValue()) / 100f);
- ap.paintAlignment(true);
+ ap.paintAlignment(true, true);
}
class MyCheckbox extends Checkbox
{
ap.av.setCharWidth(oldCharWidth);
}
- ap.paintAlignment(true);
+ ap.paintAlignment(true, false);
}
else if (tp != null)
{
// TODO: add in group link parameter
// make a list of label,url pairs
- HashMap<String, String> urlList = new HashMap<String, String>();
+ HashMap<String, String> urlList = new HashMap<>();
if (viewport.applet != null)
{
for (int i = 1; i < 10; i++)
}
lastid = seq;
- alignPanel.paintAlignment(false);
+ alignPanel.paintAlignment(false, false);
}
@Override
}
else
{
- nlinks = new ArrayList<String>();
+ nlinks = new ArrayList<>();
}
for (SequenceFeature sf : sq.getFeatures().getNonPositionalFeatures())
selectSeq(seq);
}
- alignPanel.paintAlignment(false);
+ alignPanel.paintAlignment(false, false);
}
void selectSeq(int seq)
running = false;
}
- alignPanel.paintAlignment(true);
+ alignPanel.paintAlignment(true, false);
try
{
Thread.sleep(100);
av.getAlignment().getHiddenSequences(),
av.getAlignment().getHiddenColumns());
}
- ap.paintAlignment(false);
+ ap.paintAlignment(false, false);
}
}
float value = slider.getValue();
- List<SequenceI> redundantSequences = new ArrayList<SequenceI>();
+ List<SequenceI> redundantSequences = new ArrayList<>();
for (int i = 0; i < redundancy.length; i++)
{
if (value <= redundancy[i])
ap.av.getAlignment().getSequences());
}
- ap.paintAlignment(true);
+ ap.paintAlignment(true, true);
if (historyList.size() == 0)
{
sg.setStartRes(min);
sg.setEndRes(max);
}
- ap.paintAlignment(false);
+ ap.paintAlignment(false, false);
av.sendSelection();
}
{
av.showColumn(reveal[0]);
reveal = null;
- ap.paintAlignment(true);
+ ap.paintAlignment(true, true);
av.sendSelection();
}
});
{
av.showAllHiddenColumns();
reveal = null;
- ap.paintAlignment(true);
+ ap.paintAlignment(true, true);
av.sendSelection();
}
});
av.setSelectionGroup(null);
}
- ap.paintAlignment(true);
+ ap.paintAlignment(true, true);
av.sendSelection();
}
});
if (!stretchingGroup)
{
- ap.paintAlignment(false);
+ ap.paintAlignment(false, false);
return;
}
}
stretchingGroup = false;
- ap.paintAlignment(false);
+ ap.paintAlignment(false, false);
av.sendSelection();
}
{
stretchingGroup = true;
cs.stretchGroup(res, sg, min, max);
- ap.paintAlignment(false);
+ ap.paintAlignment(false, false);
}
}
sg.addSequence(sequence, false);
av.setSelectionGroup(sg);
}
- ap.paintAlignment(false);
+ ap.paintAlignment(false, false);
av.sendSelection();
}
lastMousePress = evt.getPoint();
- ap.paintAlignment(false);
+ ap.paintAlignment(false, false);
ap.annotationPanel.image = null;
return;
}
{
if (links == null)
{
- links = new Vector<String>();
+ links = new Vector<>();
}
links.addAll(sf.links);
}
}
}
PaintRefresher.Refresh(ap, av.getSequenceSetId());
- ap.paintAlignment(needOverviewUpdate);
+ ap.paintAlignment(needOverviewUpdate, needOverviewUpdate);
needOverviewUpdate = false;
changeEndRes = false;
changeStartRes = false;
@Override
public void mouseReleased(MouseEvent evt)
{
- ap.paintAlignment(true);
+ ap.paintAlignment(true, true);
}
@Override
createSplitFrameWindow(embedded, applet);
validate();
topFrame.alignPanel.adjustAnnotationHeight();
- topFrame.alignPanel.paintAlignment(true);
+ topFrame.alignPanel.paintAlignment(true, true);
bottomFrame.alignPanel.adjustAnnotationHeight();
- bottomFrame.alignPanel.paintAlignment(true);
+ bottomFrame.alignPanel.paintAlignment(true, true);
}
/**
Button selectedButton;
- Vector<Color> oldColours = new Vector<Color>();
+ Vector<Color> oldColours = new Vector<>();
ColourSchemeI oldColourScheme;
ap.av.isIgnoreGapsConsensus());
}
ap.seqPanel.seqCanvas.img = null;
- ap.paintAlignment(true);
+ ap.paintAlignment(true, true);
}
else if (jmol != null)
{
{
ap.av.setGlobalColourScheme(oldColourScheme);
}
- ap.paintAlignment(true);
+ ap.paintAlignment(true, true);
}
frame.setVisible(false);
if (changed)
{
viewport.setColumnSelection(cs);
- alignPanel.paintAlignment(true);
+ alignPanel.paintAlignment(false, false);
int columnCount = invert
? (sqcol.getEndRes() - sqcol.getStartRes() + 1)
- bs.cardinality()
if (!extendCurrent)
{
cs.clear();
- alignPanel.paintAlignment(true);
+ alignPanel.paintAlignment(false, false);
}
}
return false;
AlignmentSorter.sortByFeature(typ, gps, start, stop, al, method);
avcg.addHistoryItem(new OrderCommand(methodText, oldOrder,
viewport.getAlignment()));
- alignPanel.paintAlignment(true);
+ alignPanel.paintAlignment(true, false);
}
{
avcg.getFeatureSettingsUI().discoverAllFeatureData();
}
- alignPanel.paintAlignment(true);
+ alignPanel.paintAlignment(true, true);
}
return featuresFile;
if (changed)
{
viewport.setColumnSelection(cs);
- alignPanel.paintAlignment(true);
+ alignPanel.paintAlignment(false, false);
int columnCount = invert
? (sqcol.getEndRes() - sqcol.getStartRes() + 1)
- bs.cardinality()
if (!extendCurrent)
{
cs.clear();
- alignPanel.paintAlignment(true);
+ alignPanel.paintAlignment(false, false);
}
}
return false;
hideStart = region[0];
hideEnd = region[1];
// edit hidden regions to selection range
- if (hideStart < last)
+
+ // just move on if hideEnd is before last
+ if (hideEnd < last)
{
- if (hideEnd > last)
- {
- hideStart = last;
- }
- else
- {
- continue;
- }
+ continue;
}
-
+ // exit if next region is after end
if (hideStart > end)
{
break;
}
- if (hideEnd > end)
+ // truncate region at start if last falls in region
+ if ((hideStart < last) && (hideEnd >= last))
{
- hideEnd = end;
+ hideStart = last;
}
- if (hideStart > hideEnd)
+ // truncate region at end if end falls in region
+ if (hideEnd > end) // already checked that hideStart<=end
{
- break;
+ hideEnd = end;
}
+
/**
* form operations...
*/
last = hideEnd + 1;
}
// Final match if necessary.
- if (last < end)
+ if (last <= end)
{
addOperation(CigarArray.M, end - last + 1);
}
import java.util.ListIterator;
import java.util.Vector;
-import com.stevesoft.pat.Regex;
-
import fr.orsay.lri.varna.models.rna.RNA;
/**
*/
public class Sequence extends ASequence implements SequenceI
{
- private static final Regex limitrx = new Regex(
- "[/][0-9]{1,}[-][0-9]{1,}$");
-
- private static final Regex endrx = new Regex("[0-9]{1,}$");
-
SequenceI datasetSequence;
String name;
checkValidRange();
}
+ /**
+ * If 'name' ends in /i-j, where i >= j > 0 are integers, extracts i and j as
+ * start and end respectively and removes the suffix from the name
+ */
void parseId()
{
if (name == null)
"POSSIBLE IMPLEMENTATION ERROR: null sequence name passed to constructor.");
name = "";
}
- // Does sequence have the /start-end signature?
- if (limitrx.search(name))
+ int slashPos = name.lastIndexOf('/');
+ if (slashPos > -1 && slashPos < name.length() - 1)
{
- name = limitrx.left();
- endrx.search(limitrx.stringMatched());
- setStart(Integer.parseInt(limitrx.stringMatched().substring(1,
- endrx.matchedFrom() - 1)));
- setEnd(Integer.parseInt(endrx.stringMatched()));
+ String suffix = name.substring(slashPos + 1);
+ String[] range = suffix.split("-");
+ if (range.length == 2)
+ {
+ try
+ {
+ int from = Integer.valueOf(range[0]);
+ int to = Integer.valueOf(range[1]);
+ if (from > 0 && to >= from)
+ {
+ name = name.substring(0, slashPos);
+ setStart(from);
+ setEnd(to);
+ checkValidRange();
+ }
+ } catch (NumberFormatException e)
+ {
+ // leave name unchanged if suffix is invalid
+ }
+ }
}
}
+ /**
+ * Ensures that 'end' is not before the end of the sequence, that is,
+ * (end-start+1) is at least as long as the count of ungapped positions. Note
+ * that end is permitted to be beyond the end of the sequence data.
+ */
void checkValidRange()
{
// Note: JAL-774 :
int endRes = 0;
for (int j = 0; j < sequence.length; j++)
{
- if (!jalview.util.Comparison.isGap(sequence[j]))
+ if (!Comparison.isGap(sequence[j]))
{
endRes++;
}
}
/**
- * DOCUMENT ME!
+ * Sets the sequence name. If the name ends in /start-end, then the start-end
+ * values are parsed out and set, and the suffix is removed from the name.
*
- * @param name
- * DOCUMENT ME!
+ * @param theName
*/
@Override
- public void setName(String name)
+ public void setName(String theName)
{
- this.name = name;
+ this.name = theName;
this.parseId();
}
* and we may have included adjacent or enclosing features;
* remove any that are not enclosing, non-contact features
*/
- if (endPos > this.end || Comparison.isGap(sequence[toColumn - 1]))
+ boolean endColumnIsGapped = toColumn > 0 && toColumn <= sequence.length
+ && Comparison.isGap(sequence[toColumn - 1]);
+ if (endPos > this.end || endColumnIsGapped)
{
ListIterator<SequenceFeature> it = result.listIterator();
while (it.hasNext())
}
/**
- * Converts a query, which may contain one or more gene or transcript
- * identifiers, into a non-redundant list of gene identifiers.
+ * Converts a query, which may contain one or more gene, transcript, or
+ * external (to Ensembl) identifiers, into a non-redundant list of gene
+ * identifiers.
*
* @param accessions
* @return
for (String acc : accessions.split(getAccessionSeparator()))
{
- if (isGeneIdentifier(acc))
- {
- if (!geneIds.contains(acc))
- {
- geneIds.add(acc);
- }
- }
-
/*
- * if given a transcript id, look up its gene parent
+ * First try lookup as an Ensembl (gene or transcript) identifier
*/
- else if (isTranscriptIdentifier(acc))
+ String geneId = new EnsemblLookup(getDomain()).getGeneId(acc);
+ if (geneId != null)
{
- String geneId = new EnsemblLookup(getDomain()).getParent(acc);
- if (geneId != null && !geneIds.contains(geneId))
+ if (!geneIds.contains(geneId))
{
geneIds.add(geneId);
}
}
- else if (isProteinIdentifier(acc))
- {
- String tscriptId = new EnsemblLookup(getDomain()).getParent(acc);
- if (tscriptId != null)
- {
- String geneId = new EnsemblLookup(getDomain())
- .getParent(tscriptId);
-
- if (geneId != null && !geneIds.contains(geneId))
- {
- geneIds.add(geneId);
- }
- }
- // NOTE - acc is lost if it resembles an ENS.+ ID but isn't actually
- // resolving to one... e.g. ENSMICP00000009241
- }
- /*
- * if given a gene or other external name, lookup and fetch
- * the corresponding gene for all model organisms
- */
else
{
+ /*
+ * if given a gene or other external name, lookup and fetch
+ * the corresponding gene for all model organisms
+ */
List<String> ids = new EnsemblSymbol(getDomain(), getDbSource(),
- getDbVersion()).getIds(acc);
- for (String geneId : ids)
+ getDbVersion()).getGeneIds(acc);
+ for (String id : ids)
{
- if (!geneIds.contains(geneId))
+ if (!geneIds.contains(id))
{
- geneIds.add(geneId);
+ geneIds.add(id);
}
}
}
}
/**
- * Attempts to get Ensembl stable identifiers for model organisms for a gene
- * name by calling the xrefs symbol REST service to resolve the gene name.
- *
- * @param query
- * @return
- */
- protected String getGeneIdentifiersForName(String query)
- {
- List<String> ids = new EnsemblSymbol(getDomain(), getDbSource(),
- getDbVersion()).getIds(query);
- if (ids != null)
- {
- for (String id : ids)
- {
- if (isGeneIdentifier(id))
- {
- return id;
- }
- }
- }
- return null;
- }
-
- /**
* Constructs all transcripts for the gene, as identified by "transcript"
* features whose Parent is the requested gene. The coding transcript
* sequences (i.e. with introns omitted) are added to the alignment.
}
@Override
- public boolean isGeneIdentifier(String query)
- {
- return true;
- }
-
- @Override
public String getDbName()
{
return "EnsemblGenomes";
}
+ private String Wrong[];
@Override
public String getTestQuery()
{
import java.net.URL;
import java.util.Arrays;
import java.util.List;
+import java.util.function.Function;
import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser;
import org.json.simple.parser.ParseException;
/**
- * A client for the Ensembl lookup REST endpoint; used to find the Parent gene
- * identifier given a transcript identifier.
+ * A client for the Ensembl lookup REST endpoint
*
* @author gmcarstairs
- *
*/
public class EnsemblLookup extends EnsemblRestClient
{
private static final String PARENT = "Parent";
+ private static final String OBJECT_TYPE_TRANSLATION = "Translation";
+ private static final String OBJECT_TYPE_TRANSCRIPT = "Transcript";
+ private static final String ID = "id";
+ private static final String OBJECT_TYPE_GENE = "Gene";
+ private static final String OBJECT_TYPE = "object_type";
+
/**
* Default constructor (to use rest.ensembl.org)
*/
protected URL getUrl(String identifier)
{
String url = getDomain() + "/lookup/id/" + identifier
- + "?content-type=application/json";
+ + CONTENT_TYPE_JSON;
try
{
return new URL(url);
* @param identifier
* @return
*/
- public String getParent(String identifier)
+ public String getGeneId(String identifier)
{
- return getAttribute(identifier, PARENT);
+ return getResult(identifier, br -> parseGeneId(br));
}
/**
*/
public String getSpecies(String identifier)
{
- return getAttribute(identifier, SPECIES);
+ return getResult(identifier, br -> getAttribute(br, SPECIES));
}
/**
* @param attribute
* @return
*/
- protected String getAttribute(String identifier, String attribute)
+ protected String getResult(String identifier,
+ Function<BufferedReader, String> parser)
{
List<String> ids = Arrays.asList(new String[] { identifier });
{
br = getHttpResponse(url, ids);
}
- return (parseResponse(br, attribute));
+ return br == null ? null : parser.apply(br);
} catch (IOException e)
{
// ignore
}
/**
- * Parses the value of 'attribute' from the JSON response and returns the
- * value, or null if not found
+ * Answers the value of 'attribute' from the JSON response, or null if not
+ * found
*
* @param br
* @param attribute
* @return
- * @throws IOException
*/
- protected String parseResponse(BufferedReader br, String attribute) throws IOException
+ protected String getAttribute(BufferedReader br, String attribute)
+ {
+ String value = null;
+ JSONParser jp = new JSONParser();
+ try
+ {
+ JSONObject val = (JSONObject) jp.parse(br);
+ value = val.get(attribute).toString();
+ } catch (ParseException | NullPointerException | IOException e)
+ {
+ // ignore
+ }
+ return value;
+ }
+
+ /**
+ * Parses the JSON response and returns the gene identifier, or null if not
+ * found. If the returned object_type is Gene, returns the id, if Transcript
+ * returns the Parent. If it is Translation (peptide identifier), then the
+ * Parent is the transcript identifier, so we redo the search with this value.
+ *
+ * @param br
+ * @return
+ */
+ protected String parseGeneId(BufferedReader br)
{
- String parent = null;
+ String geneId = null;
JSONParser jp = new JSONParser();
try
{
JSONObject val = (JSONObject) jp.parse(br);
- parent = val.get(attribute).toString();
- } catch (ParseException | NullPointerException e)
+ String type = val.get(OBJECT_TYPE).toString();
+ if (OBJECT_TYPE_GENE.equalsIgnoreCase(type))
+ {
+ geneId = val.get(ID).toString();
+ }
+ else if (OBJECT_TYPE_TRANSCRIPT.equalsIgnoreCase(type))
+ {
+ geneId = val.get(PARENT).toString();
+ }
+ else if (OBJECT_TYPE_TRANSLATION.equalsIgnoreCase(type))
+ {
+ String transcriptId = val.get(PARENT).toString();
+ try
+ {
+ geneId = getGeneId(transcriptId);
+ } catch (StackOverflowError e)
+ {
+ /*
+ * unlikely data condition error!
+ */
+ System.err
+ .println("** Ensembl lookup "
+ + getUrl(transcriptId).toString()
+ + " looping on Parent!");
+ }
+ }
+ } catch (ParseException | IOException e)
{
// ignore
}
- return parent;
+ return geneId;
}
}
import jalview.datamodel.AlignmentI;
import jalview.datamodel.SequenceFeature;
-import java.util.List;
-
import com.stevesoft.pat.Regex;
/**
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
+import java.net.ProtocolException;
import java.net.URL;
import java.util.HashMap;
import java.util.List;
import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser;
-import com.stevesoft.pat.Regex;
-
/**
* Base class for Ensembl REST service clients
*
private static final int CONNECT_TIMEOUT_MS = 10 * 1000; // 10 seconds
+ private static final int MAX_RETRIES = 3;
+
+ private static final int HTTP_OK = 200;
+
+ private static final int HTTP_OVERLOAD = 429;
+
/*
* update these constants when Jalview has been checked / updated for
* changes to Ensembl REST API (ref JAL-2105)
* @see https://github.com/Ensembl/ensembl-rest/wiki/Change-log
* @see http://rest.ensembl.org/info/rest?content-type=application/json
*/
- private static final String LATEST_ENSEMBLGENOMES_REST_VERSION = "5.0";
+ private static final String LATEST_ENSEMBLGENOMES_REST_VERSION = "6.0";
- private static final String LATEST_ENSEMBL_REST_VERSION = "5.0";
+ private static final String LATEST_ENSEMBL_REST_VERSION = "6.1";
private static final String REST_CHANGE_LOG = "https://github.com/Ensembl/ensembl-rest/wiki/Change-log";
private final static long VERSION_RETEST_INTERVAL = 1000L * 3600; // 1 hr
- private static final Regex PROTEIN_REGEX = new Regex(
- "(ENS)([A-Z]{3}|)P[0-9]{11}$");
-
- private static final Regex TRANSCRIPT_REGEX = new Regex(
- "(ENS)([A-Z]{3}|)T[0-9]{11}$");
-
- private static final Regex GENE_REGEX = new Regex(
- "(ENS)([A-Z]{3}|)G[0-9]{11}$");
+ protected static final String CONTENT_TYPE_JSON = "?content-type=application/json";
static
{
- domainData = new HashMap<String, EnsemblData>();
+ domainData = new HashMap<>();
domainData.put(ENSEMBL_REST,
new EnsemblData(ENSEMBL_REST, LATEST_ENSEMBL_REST_VERSION));
domainData.put(ENSEMBL_GENOMES_REST, new EnsemblData(
setDomain(d);
}
- /**
- * Answers true if the query matches the regular expression pattern for an
- * Ensembl transcript stable identifier
- *
- * @param query
- * @return
- */
- public boolean isTranscriptIdentifier(String query)
- {
- return query == null ? false : TRANSCRIPT_REGEX.search(query);
- }
-
- /**
- * Answers true if the query matches the regular expression pattern for an
- * Ensembl protein stable identifier
- *
- * @param query
- * @return
- */
- public boolean isProteinIdentifier(String query)
- {
- return query == null ? false : PROTEIN_REGEX.search(query);
- }
-
- /**
- * Answers true if the query matches the regular expression pattern for an
- * Ensembl gene stable identifier
- *
- * @param query
- * @return
- */
- public boolean isGeneIdentifier(String query)
- {
- return query == null ? false : GENE_REGEX.search(query);
- }
-
@Override
public boolean queryInProgress()
{
* @see http://rest.ensembl.org/documentation/info/ping
* @return
*/
- private boolean checkEnsembl()
+ boolean checkEnsembl()
{
BufferedReader br = null;
try
{
// note this format works for both ensembl and ensemblgenomes
// info/ping.json works for ensembl only (March 2016)
- URL ping = new URL(
- getDomain() + "/info/ping?content-type=application/json");
+ URL ping = new URL(getDomain() + "/info/ping" + CONTENT_TYPE_JSON);
/*
* expect {"ping":1} if ok
* if ping takes more than 2 seconds to respond, treat as if unavailable
*/
br = getHttpResponse(ping, null, 2 * 1000);
+ if (br == null)
+ {
+ // error reponse status
+ return false;
+ }
JSONParser jp = new JSONParser();
JSONObject val = (JSONObject) jp.parse(br);
String pingString = val.get("ping").toString();
}
/**
- * Writes the HTTP request and gets the response as a reader.
+ * Sends the HTTP request and gets the response as a reader
*
* @param url
* @param ids
protected BufferedReader getHttpResponse(URL url, List<String> ids,
int readTimeout) throws IOException
{
- // long now = System.currentTimeMillis();
+ int retriesLeft = MAX_RETRIES;
+ HttpURLConnection connection = null;
+ int responseCode = 0;
+
+ while (retriesLeft > 0)
+ {
+ connection = tryConnection(url, ids, readTimeout);
+ responseCode = connection.getResponseCode();
+ if (responseCode == HTTP_OVERLOAD) // 429
+ {
+ retriesLeft--;
+ checkRetryAfter(connection);
+ }
+ else
+ {
+ retriesLeft = 0;
+ }
+ }
+ if (responseCode != HTTP_OK) // 200
+ {
+ /*
+ * note: a GET request for an invalid id returns an error code e.g. 415
+ * but POST request returns 200 and an empty Fasta response
+ */
+ System.err.println("Response code " + responseCode + " for " + url);
+ return null;
+ }
+
+ InputStream response = connection.getInputStream();
+
+ // System.out.println(getClass().getName() + " took "
+ // + (System.currentTimeMillis() - now) + "ms to fetch");
+
+ BufferedReader reader = null;
+ reader = new BufferedReader(new InputStreamReader(response, "UTF-8"));
+ return reader;
+ }
+
+ /**
+ * @param url
+ * @param ids
+ * @param readTimeout
+ * @return
+ * @throws IOException
+ * @throws ProtocolException
+ */
+ protected HttpURLConnection tryConnection(URL url, List<String> ids,
+ int readTimeout) throws IOException, ProtocolException
+ {
+ // System.out.println(System.currentTimeMillis() + " " + url);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
/*
{
writePostBody(connection, ids);
}
-
- int responseCode = connection.getResponseCode();
-
- if (responseCode != 200)
- {
- /*
- * note: a GET request for an invalid id returns an error code e.g. 415
- * but POST request returns 200 and an empty Fasta response
- */
- System.err.println("Response code " + responseCode + " for " + url);
- return null;
- }
- // get content
- InputStream response = connection.getInputStream();
-
- // System.out.println(getClass().getName() + " took "
- // + (System.currentTimeMillis() - now) + "ms to fetch");
-
- checkRateLimits(connection);
-
- BufferedReader reader = null;
- reader = new BufferedReader(new InputStreamReader(response, "UTF-8"));
- return reader;
+ return connection;
}
/**
- * Inspect response headers for any sign of server overload and respect any
- * 'retry-after' directive
+ * Inspects response headers for a 'retry-after' directive, and waits for the
+ * directed period (if less than 10 seconds)
*
* @see https://github.com/Ensembl/ensembl-rest/wiki/Rate-Limits
* @param connection
*/
- void checkRateLimits(HttpURLConnection connection)
+ void checkRetryAfter(HttpURLConnection connection)
{
- // number of requests allowed per time interval:
- String limit = connection.getHeaderField("X-RateLimit-Limit");
- // length of quota time interval in seconds:
- // String period = connection.getHeaderField("X-RateLimit-Period");
- // seconds remaining until usage quota is reset:
- String reset = connection.getHeaderField("X-RateLimit-Reset");
- // number of requests remaining from quota for current period:
- String remaining = connection.getHeaderField("X-RateLimit-Remaining");
- // number of seconds to wait before retrying (if remaining == 0)
String retryDelay = connection.getHeaderField("Retry-After");
// to test:
// retryDelay = "5";
- EnsemblData info = domainData.get(getDomain());
if (retryDelay != null)
{
- System.err.println("Ensembl REST service rate limit exceeded, wait "
- + retryDelay + " seconds before retrying");
try
{
- info.retryAfter = System.currentTimeMillis()
- + (1000 * Integer.valueOf(retryDelay));
- } catch (NumberFormatException e)
+ int retrySecs = Integer.valueOf(retryDelay);
+ if (retrySecs > 0 && retrySecs < 10)
+ {
+ System.err
+ .println("Ensembl REST service rate limit exceeded, waiting "
+ + retryDelay + " seconds before retrying");
+ Thread.sleep(1000 * retrySecs);
+ }
+ } catch (NumberFormatException | InterruptedException e)
{
- System.err
- .println("Unexpected value for Retry-After: " + retryDelay);
+ System.err.println("Error handling Retry-After: " + e.getMessage());
}
}
- else
- {
- info.retryAfter = 0;
- // debug:
- // System.out.println(String.format(
- // "%s Ensembl requests remaining of %s (reset in %ss)",
- // remaining, limit, reset));
- }
}
/**
long now = System.currentTimeMillis();
/*
- * check if we are waiting for 'Retry-After' to expire
- */
- if (info.retryAfter > now)
- {
- System.err.println("Still " + (1 + (info.retryAfter - now) / 1000)
- + " secs to wait before retrying Ensembl");
- return false;
- }
- else
- {
- info.retryAfter = 0;
- }
-
- /*
* recheck if Ensembl is up if it was down, or the recheck period has elapsed
*/
boolean retestAvailability = (now
URL url = null;
try
{
- url = new URL(
- getDomain() + "/info/rest?content-type=application/json");
+ url = new URL(getDomain() + "/info/rest" + CONTENT_TYPE_JSON);
BufferedReader br = getHttpResponse(url, null);
+ if (br == null)
+ {
+ return;
+ }
JSONObject val = (JSONObject) jp.parse(br);
String version = val.get("release").toString();
String majorVersion = version.substring(0, version.indexOf("."));
{
JSONParser jp = new JSONParser();
URL url = null;
+ BufferedReader br = null;
+
try
{
- url = new URL(
- getDomain() + "/info/data?content-type=application/json");
- BufferedReader br = getHttpResponse(url, null);
- JSONObject val = (JSONObject) jp.parse(br);
- JSONArray versions = (JSONArray) val.get("releases");
- domainData.get(getDomain()).dataVersion = versions.get(0).toString();
+ url = new URL(getDomain() + "/info/data" + CONTENT_TYPE_JSON);
+ br = getHttpResponse(url, null);
+ if (br != null)
+ {
+ JSONObject val = (JSONObject) jp.parse(br);
+ JSONArray versions = (JSONArray) val.get("releases");
+ domainData.get(getDomain()).dataVersion = versions.get(0)
+ .toString();
+ }
} catch (Throwable t)
{
System.err.println(
"Error checking Ensembl data version: " + t.getMessage());
+ } finally
+ {
+ if (br != null)
+ {
+ try
+ {
+ br.close();
+ } catch (IOException e)
+ {
+ // ignore
+ }
+ }
}
}
*/
public class EnsemblSymbol extends EnsemblXref
{
+ private static final String GENE = "gene";
+ private static final String TYPE = "type";
+ private static final String ID = "id";
+
/**
* Constructor given the target domain to fetch data from
*
while (rvals.hasNext())
{
JSONObject val = (JSONObject) rvals.next();
- String id = val.get("id").toString();
- if (id != null && isGeneIdentifier(id))
+ String id = val.get(ID).toString();
+ String type = val.get(TYPE).toString();
+ if (id != null && GENE.equals(type))
{
result = id;
break;
return result;
}
- protected URL getUrl(String id, Species species)
+ /**
+ * Constructs the URL for the REST symbol endpoint
+ *
+ * @param id
+ * the accession id (Ensembl or external)
+ * @param species
+ * a species name recognisable by Ensembl
+ * @param type
+ * an optional type to filter the response (gene, transcript,
+ * translation)
+ * @return
+ */
+ protected URL getUrl(String id, Species species, String... type)
{
- String url = getDomain() + "/xrefs/symbol/" + species.toString() + "/"
- + id + "?content-type=application/json";
+ StringBuilder sb = new StringBuilder();
+ sb.append(getDomain()).append("/xrefs/symbol/")
+ .append(species.toString()).append("/").append(id)
+ .append(CONTENT_TYPE_JSON);
+ for (String t : type)
+ {
+ sb.append("&object_type=").append(t);
+ }
try
{
+ String url = sb.toString();
return new URL(url);
} catch (MalformedURLException e)
{
* @param identifier
* @return
*/
- public List<String> getIds(String identifier)
+ public List<String> getGeneIds(String identifier)
{
List<String> result = new ArrayList<String>();
List<String> ids = new ArrayList<String>();
{
for (String query : queries)
{
- for (Species taxon : Species.values())
+ for (Species taxon : Species.getModelOrganisms())
{
- if (taxon.isModelOrganism())
+ URL url = getUrl(query, taxon, GENE);
+ if (url != null)
{
- URL url = getUrl(query, taxon);
- if (url != null)
- {
- br = getHttpResponse(url, ids);
- }
- String geneId = parseSymbolResponse(br);
- if (geneId != null)
+ br = getHttpResponse(url, ids);
+ if (br != null)
{
- result.add(geneId);
+ String geneId = parseSymbolResponse(br);
+ System.out.println(url + " returned " + geneId);
+ if (geneId != null && !result.contains(geneId))
+ {
+ result.add(geneId);
+ }
}
}
}
if (url != null)
{
br = getHttpResponse(url, ids);
+ if (br != null)
+ {
+ result = parseResponse(br);
+ }
}
- return (parseResponse(br));
} catch (IOException e)
{
// ignore
while (rvals.hasNext())
{
JSONObject val = (JSONObject) rvals.next();
- String dbName = val.get("dbname").toString();
- if (dbName.equals(GO_GENE_ONTOLOGY))
- {
- continue;
- }
+ String db = val.get("dbname").toString();
String id = val.get("primary_id").toString();
- if (dbName != null && id != null)
+ if (db != null && id != null
+ && !GO_GENE_ONTOLOGY.equals(db))
{
- dbName = DBRefUtils.getCanonicalName(dbName);
- DBRefEntry dbref = new DBRefEntry(dbName, getXRefVersion(), id);
+ db = DBRefUtils.getCanonicalName(db);
+ DBRefEntry dbref = new DBRefEntry(db, getXRefVersion(), id);
result.add(dbref);
}
}
protected URL getUrl(String identifier)
{
String url = getDomain() + "/xrefs/id/" + identifier
- + "?content-type=application/json&all_levels=1";
+ + CONTENT_TYPE_JSON + "&all_levels=1";
try
{
return new URL(url);
*/
package jalview.ext.ensembl;
+import java.util.HashSet;
+import java.util.Set;
+
/**
* Selected species identifiers used by Ensembl
*
chimpanzee(false), cat(false), zebrafish(true), chicken(true),
dmelanogaster(true);
+ static Set<Species> modelOrganisms = new HashSet<>();
+
+ static
+ {
+ for (Species s : values())
+ {
+ if (s.isModelOrganism())
+ {
+ modelOrganisms.add(s);
+ }
+ }
+ }
boolean modelOrganism;
private Species(boolean model)
{
return modelOrganism;
}
+
+ public static Set<Species> getModelOrganisms()
+ {
+ return modelOrganisms;
+ }
}
notifyAtomPicked(((Integer) data[2]).intValue(), (String) data[1],
(String) data[0]);
// also highlight in alignment
+ // deliberate fall through
case HOVER:
notifyAtomHovered(((Integer) data[2]).intValue(), (String) data[1],
(String) data[0]);
for (String chain : modelData.keySet())
{
- chain = chain.trim();
+ chain = " ".equals(chain) ? chain : chain.trim();
List<int[]> rangeList = modelData.get(chain);
{
sb.append(start).append("-").append(end);
}
- if (chain.length() > 0)
- {
- sb.append(".").append(chain);
+
+ sb.append(".");
+ if (!" ".equals(chain)) {
+ sb.append(chain);
}
}
}
private static final String PDB_FTS_CACHE_KEY = "CACHE.PDB_FTS";
- public PDBFTSPanel(SequenceFetcher seqFetcher)
+ public PDBFTSPanel(SequenceFetcher fetcher)
{
super();
pageLimit = PDBFTSRestClient.getInstance().getDefaultResponsePageSize();
- this.seqFetcher = seqFetcher;
- this.progressIndicator = (seqFetcher == null) ? null
- : seqFetcher.getProgressIndicator();
+ this.seqFetcher = fetcher;
+ this.progressIndicator = (fetcher == null) ? null
+ : fetcher.getProgressIndicator();
}
@Override
request.setSearchTerm(searchTerm + ")");
request.setOffSet(offSet);
request.setWantedFields(wantedFields);
- FTSRestClientI pdbRestCleint = PDBFTSRestClient.getInstance();
+ FTSRestClientI pdbRestClient = PDBFTSRestClient.getInstance();
FTSRestResponse resultList;
try
{
- resultList = pdbRestCleint.executeRequest(request);
+ resultList = pdbRestClient.executeRequest(request);
} catch (Exception e)
{
setErrorMessage(e.getMessage());
checkForErrors();
+ setSearchInProgress(false);
return;
}
private static String defaultFTSFrameTitle = MessageManager
.getString("label.uniprot_sequence_fetcher");
- private static Map<String, Integer> tempUserPrefs = new HashMap<String, Integer>();
+ private static Map<String, Integer> tempUserPrefs = new HashMap<>();
private static final String UNIPROT_FTS_CACHE_KEY = "CACHE.UNIPROT_FTS";
- public UniprotFTSPanel(SequenceFetcher seqFetcher)
+ public UniprotFTSPanel(SequenceFetcher fetcher)
{
super();
pageLimit = UniProtFTSRestClient.getInstance()
.getDefaultResponsePageSize();
- this.seqFetcher = seqFetcher;
- this.progressIndicator = (seqFetcher == null) ? null
- : seqFetcher.getProgressIndicator();
+ this.seqFetcher = fetcher;
+ this.progressIndicator = (fetcher == null) ? null
+ : fetcher.getProgressIndicator();
}
@Override
request.setSearchTerm(searchTerm);
request.setOffSet(offSet);
request.setWantedFields(wantedFields);
- FTSRestClientI uniProtRestCleint = UniProtFTSRestClient
+ FTSRestClientI uniProtRestClient = UniProtFTSRestClient
.getInstance();
FTSRestResponse resultList;
try
{
- resultList = uniProtRestCleint.executeRequest(request);
+ resultList = uniProtRestClient.executeRequest(request);
} catch (Exception e)
{
- e.printStackTrace();
setErrorMessage(e.getMessage());
checkForErrors();
+ setSearchInProgress(false);
return;
}
{
disableActionButtons();
StringBuilder selectedIds = new StringBuilder();
- HashSet<String> selectedIdsSet = new HashSet<String>();
+ HashSet<String> selectedIdsSet = new HashSet<>();
int primaryKeyColIndex = 0;
try
{
}
viewport.getAlignment().moveSelectedSequencesByOne(sg,
viewport.getHiddenRepSequences(), up);
- alignPanel.paintAlignment(true);
+ alignPanel.paintAlignment(true, false);
}
synchronized void slideSequences(boolean right, int size)
{
PaintRefresher.Refresh(this, viewport.getSequenceSetId());
alignPanel.updateAnnotation();
- alignPanel.paintAlignment(true);
+ alignPanel.paintAlignment(true, true);
}
}
// JAL-2034 - should delegate to
// alignPanel to decide if overview needs
// updating.
- alignPanel.paintAlignment(false);
+ alignPanel.paintAlignment(false, false);
PaintRefresher.Refresh(alignPanel, viewport.getSequenceSetId());
}
// JAL-2034 - should delegate to
// alignPanel to decide if overview needs
// updating.
- alignPanel.paintAlignment(false);
+ alignPanel.paintAlignment(false, false);
PaintRefresher.Refresh(alignPanel, viewport.getSequenceSetId());
viewport.sendSelection();
}
// alignPanel to decide if overview needs
// updating.
- alignPanel.paintAlignment(true);
+ alignPanel.paintAlignment(true, false);
PaintRefresher.Refresh(alignPanel, viewport.getSequenceSetId());
viewport.sendSelection();
}
public void invertColSel_actionPerformed(ActionEvent e)
{
viewport.invertColumnSelection();
- alignPanel.paintAlignment(true);
+ alignPanel.paintAlignment(true, false);
viewport.sendSelection();
}
alignPanel.getIdPanel().getIdCanvas()
.setPreferredSize(alignPanel.calculateIdWidth());
- alignPanel.paintAlignment(true);
+ alignPanel.paintAlignment(true, false);
}
@Override
public void idRightAlign_actionPerformed(ActionEvent e)
{
viewport.setRightAlignIds(idRightAlign.isSelected());
- alignPanel.paintAlignment(true);
+ alignPanel.paintAlignment(false, false);
}
@Override
public void centreColumnLabels_actionPerformed(ActionEvent e)
{
viewport.setCentreColumnLabels(centreColumnLabelsMenuItem.getState());
- alignPanel.paintAlignment(true);
+ alignPanel.paintAlignment(false, false);
}
/*
protected void colourTextMenuItem_actionPerformed(ActionEvent e)
{
viewport.setColourText(colourTextMenuItem.isSelected());
- alignPanel.paintAlignment(true);
+ alignPanel.paintAlignment(false, false);
}
/**
public void showAllColumns_actionPerformed(ActionEvent e)
{
viewport.showAllHiddenColumns();
- alignPanel.paintAlignment(true);
+ alignPanel.paintAlignment(true, true);
viewport.sendSelection();
}
viewport.expandColSelection(sg, false);
viewport.hideAllSelectedSeqs();
viewport.hideSelectedColumns();
- alignPanel.paintAlignment(true);
+ alignPanel.paintAlignment(true, true);
viewport.sendSelection();
}
{
viewport.showAllHiddenColumns();
viewport.showAllHiddenSeqs();
- alignPanel.paintAlignment(true);
+ alignPanel.paintAlignment(true, true);
viewport.sendSelection();
}
public void hideSelColumns_actionPerformed(ActionEvent e)
{
viewport.hideSelectedColumns();
- alignPanel.paintAlignment(true);
+ alignPanel.paintAlignment(true, true);
viewport.sendSelection();
}
protected void scaleAbove_actionPerformed(ActionEvent e)
{
viewport.setScaleAboveWrapped(scaleAbove.isSelected());
- alignPanel.paintAlignment(true);
+ // TODO: do we actually need to update overview for scale above change ?
+ alignPanel.paintAlignment(true, false);
}
/**
protected void scaleLeft_actionPerformed(ActionEvent e)
{
viewport.setScaleLeftWrapped(scaleLeft.isSelected());
- alignPanel.paintAlignment(true);
+ alignPanel.paintAlignment(true, false);
}
/**
protected void scaleRight_actionPerformed(ActionEvent e)
{
viewport.setScaleRightWrapped(scaleRight.isSelected());
- alignPanel.paintAlignment(true);
+ alignPanel.paintAlignment(true, false);
}
/**
public void viewBoxesMenuItem_actionPerformed(ActionEvent e)
{
viewport.setShowBoxes(viewBoxesMenuItem.isSelected());
- alignPanel.paintAlignment(true);
+ alignPanel.paintAlignment(false, false);
}
/**
public void viewTextMenuItem_actionPerformed(ActionEvent e)
{
viewport.setShowText(viewTextMenuItem.isSelected());
- alignPanel.paintAlignment(true);
+ alignPanel.paintAlignment(false, false);
}
/**
protected void renderGapsMenuItem_actionPerformed(ActionEvent e)
{
viewport.setRenderGaps(renderGapsMenuItem.isSelected());
- alignPanel.paintAlignment(true);
+ alignPanel.paintAlignment(false, false);
}
public FeatureSettings featureSettings;
public void showSeqFeatures_actionPerformed(ActionEvent evt)
{
viewport.setShowSequenceFeatures(showSeqFeatures.isSelected());
- alignPanel.paintAlignment(true);
+ alignPanel.paintAlignment(true, true);
}
/**
viewport.setGlobalColourScheme(cs);
- alignPanel.paintAlignment(true);
+ alignPanel.paintAlignment(true, true);
}
/**
viewport.getAlignment().getSequenceAt(0));
addHistoryItem(new OrderCommand("Pairwise Sort", oldOrder,
viewport.getAlignment()));
- alignPanel.paintAlignment(true);
+ alignPanel.paintAlignment(true, false);
}
/**
AlignmentSorter.sortByID(viewport.getAlignment());
addHistoryItem(
new OrderCommand("ID Sort", oldOrder, viewport.getAlignment()));
- alignPanel.paintAlignment(true);
+ alignPanel.paintAlignment(true, false);
}
/**
AlignmentSorter.sortByLength(viewport.getAlignment());
addHistoryItem(new OrderCommand("Length Sort", oldOrder,
viewport.getAlignment()));
- alignPanel.paintAlignment(true);
+ alignPanel.paintAlignment(true, false);
}
/**
addHistoryItem(new OrderCommand("Group Sort", oldOrder,
viewport.getAlignment()));
- alignPanel.paintAlignment(true);
+ alignPanel.paintAlignment(true, false);
}
/**
addHistoryItem(new OrderCommand(order.getName(), oldOrder,
viewport.getAlignment()));
- alignPanel.paintAlignment(true);
+ alignPanel.paintAlignment(true, false);
}
});
}
viewport.getAlignment());// ,viewport.getSelectionGroup());
addHistoryItem(new OrderCommand("Sort by " + scoreLabel, oldOrder,
viewport.getAlignment()));
- alignPanel.paintAlignment(true);
+ alignPanel.paintAlignment(true, false);
}
});
}
addHistoryItem(new OrderCommand(undoname, oldOrder,
viewport.getAlignment()));
}
- alignPanel.paintAlignment(true);
+ alignPanel.paintAlignment(true, false);
return true;
}
assocfiles++;
}
}
- alignPanel.paintAlignment(true);
+ // TODO: do we need to update overview ? only if features are
+ // shown I guess
+ alignPanel.paintAlignment(true, false);
}
}
}
{
if (parseFeaturesFile(file, sourceType))
{
- alignPanel.paintAlignment(true);
+ alignPanel.paintAlignment(true, true);
}
}
else
alignPanel.adjustAnnotationHeight();
viewport.updateSequenceIdColours();
buildSortByAnnotationScoresMenu();
- alignPanel.paintAlignment(true);
+ alignPanel.paintAlignment(true, true);
}
} catch (Exception ex)
{
protected void showUnconservedMenuItem_actionPerformed(ActionEvent e)
{
viewport.setShowUnconserved(showNonconservedMenuItem.getState());
- alignPanel.paintAlignment(true);
+ alignPanel.paintAlignment(false, false);
}
/*
{
PaintRefresher.Refresh(this, viewport.getSequenceSetId());
alignPanel.updateAnnotation();
- alignPanel.paintAlignment(true);
+ alignPanel.paintAlignment(true, true);
}
}
viewport.getAlignment().setSeqrep(null);
PaintRefresher.Refresh(this, viewport.getSequenceSetId());
alignPanel.updateAnnotation();
- alignPanel.paintAlignment(true);
+ alignPanel.paintAlignment(true, true);
}
}
this.alignPanel.av.setSortAnnotationsBy(getAnnotationSortOrder());
this.alignPanel.av
.setShowAutocalculatedAbove(isShowAutoCalculatedAbove());
- alignPanel.paintAlignment(true);
+ alignPanel.paintAlignment(false, false);
}
/**
private AnnotationLabels alabels;
- // this value is set false when selection area being dragged
- boolean fastPaint = true;
-
private int hextent = 0;
private int vextent = 0;
alignFrame.updateEditMenuBar();
- paintAlignment(true);
+ // no idea if we need to update structure
+ paintAlignment(true, true);
}
scrollNeeded = vpRanges.scrollToWrappedVisible(start);
}
- paintAlignment(redrawOverview);
+ paintAlignment(redrawOverview, false);
return scrollNeeded;
}
}
validateAnnotationDimensions(true);
addNotify();
- paintAlignment(true);
+ // TODO: many places call this method and also paintAlignment with various
+ // different settings. this means multiple redraws are triggered...
+ paintAlignment(true, false);
}
/**
}
else
{
- int widthInRes = (canvasWidth / av.getCharWidth()) - 1;
+ int widthInRes = (canvasWidth / av.getCharWidth());
int heightInSeq = (getSeqPanel().seqCanvas.getHeight()
- / av.getCharHeight()) - 1;
+ / av.getCharHeight());
vpRanges.setViewportWidth(widthInRes);
vpRanges.setViewportHeight(heightInSeq);
}
vpRanges.setViewportStartAndHeight(y, height);
}
- if (!fastPaint)
- {
- repaint();
- }
+ repaint();
}
/**
repaint();
}
- /**
- * Repaint the alignment including the annotations and overview panels (if
- * shown).
+ /* (non-Javadoc)
+ * @see jalview.api.AlignmentViewPanel#paintAlignment(boolean)
*/
@Override
- public void paintAlignment(boolean updateOverview)
+ public void paintAlignment(boolean updateOverview,
+ boolean updateStructures)
{
final AnnotationSorter sorter = new AnnotationSorter(getAlignment(),
av.isShowAutocalculatedAbove());
av.getSortAnnotationsBy());
repaint();
- if (updateOverview)
+ if (updateStructures)
{
- // TODO: determine if this paintAlignment changed structure colours
av.getStructureSelectionManager().sequenceColoursChanged(this);
+ }
+ if (updateOverview)
+ {
if (overviewPanel != null)
{
if (adjustHeight)
{
// sort, repaint, update overview
- paintAlignment(true);
+ paintAlignment(true, false);
}
else
{
private boolean applyToUnselectedSequences;
// currently selected 'annotation type' checkboxes
- private Map<String, String> selectedTypes = new HashMap<String, String>();
+ private Map<String, String> selectedTypes = new HashMap<>();
/**
* Constructor.
// this.ap.alabels.setSize(this.ap.alabels.getSize().width,
// this.ap.annotationPanel.getSize().height);
// this.ap.validate();
- this.ap.paintAlignment(true);
+ this.ap.paintAlignment(true, false);
}
/**
// this.ap.alabels.setSize(this.ap.alabels.getSize().width,
// this.ap.annotationPanel.getSize().height);
// this.ap.validate();
- this.ap.paintAlignment(true);
+ this.ap.paintAlignment(true, false);
}
/**
this.ap.updateAnnotation();
// this.ap.annotationPanel.adjustPanelHeight();
- this.ap.paintAlignment(true);
+ this.ap.paintAlignment(true, false);
}
/**
public static List<String> getAnnotationTypes(AlignmentI alignment,
boolean sequenceSpecificOnly)
{
- List<String> result = new ArrayList<String>();
+ List<String> result = new ArrayList<>();
for (AlignmentAnnotation aa : alignment.getAlignmentAnnotation())
{
if (!sequenceSpecificOnly || aa.sequenceRef != null)
oldcs = av.getGlobalColourScheme();
if (av.getAlignment().getGroups() != null)
{
- oldgroupColours = new Hashtable<SequenceGroup, ColourSchemeI>();
+ oldgroupColours = new Hashtable<>();
for (SequenceGroup sg : ap.av.getAlignment().getGroups())
{
if (sg.getColourScheme() != null)
}
Vector<String> annotItems = getAnnotationItems(
seqAssociated.isSelected());
- annotations = new JComboBox<String>(annotItems);
+ annotations = new JComboBox<>(annotItems);
populateThresholdComboBox(threshold);
getCurrentAnnotation().threshold.value = slider.getValue() / 1000f;
propagateSeqAssociatedThreshold(updateAllAnnotation,
getCurrentAnnotation());
- ap.paintAlignment(false);
+ ap.paintAlignment(false, false);
}
}
colorAlignmentContaining(getCurrentAnnotation(), selectedThresholdItem);
ap.alignmentChanged();
- // ensure all associated views (overviews, structures, etc) are notified of
- // updated colours.
- ap.paintAlignment(true);
}
- protected boolean colorAlignmentContaining(AlignmentAnnotation currentAnn,
+ protected void colorAlignmentContaining(AlignmentAnnotation currentAnn,
int selectedThresholdOption)
{
acg.getInstance(sg, ap.av.getHiddenRepSequences()));
}
}
- return false;
}
}
av.getAlignment().setHiddenColumns(oldHidden);
}
av.sendSelection();
- ap.paintAlignment(true);
+ ap.paintAlignment(true, true);
}
}
updateView();
propagateSeqAssociatedThreshold(updateAllAnnotation,
getCurrentAnnotation());
- ap.paintAlignment(false);
+ ap.paintAlignment(false, false);
}
}
av.getColumnSelection().filterAnnotations(
getCurrentAnnotation().annotations, filterParams);
- if (getActionOption() == ACTION_OPTION_HIDE)
+ boolean hideCols = getActionOption() == ACTION_OPTION_HIDE;
+ if (hideCols)
{
av.hideSelectedColumns();
}
filterParams = null;
av.setAnnotationColumnSelectionState(this);
- ap.paintAlignment(true);
+ // only update overview and structures if columns were hidden
+ ap.paintAlignment(hideCols, hideCols);
}
public HiddenColumns getOldHiddenColumns()
d = ap.annotationSpaceFillerHolder.getPreferredSize();
ap.annotationSpaceFillerHolder
.setPreferredSize(new Dimension(d.width, d.height - dif));
- ap.paintAlignment(true);
+ ap.paintAlignment(true, false);
}
ap.addNotify();
}
}
- ap.paintAlignment(false);
+ ap.paintAlignment(false, false);
PaintRefresher.Refresh(ap, ap.av.getSequenceSetId());
ap.av.sendSelection();
}
sg.addSequence(aa[selectedRow].sequenceRef, false);
}
ap.av.setSelectionGroup(sg);
- ap.paintAlignment(false);
+ ap.paintAlignment(false, false);
PaintRefresher.Refresh(ap, ap.av.getSequenceSetId());
ap.av.sendSelection();
}
}
graphStretchY = evt.getY();
adjustPanelHeight();
- ap.paintAlignment(true);
+ ap.paintAlignment(false, false);
}
else
{
*/
protected boolean sliderDragging = false;
- protected JComboBox<String> threshold = new JComboBox<String>();
+ protected JComboBox<String> threshold = new JComboBox<>();
protected JComboBox<String> annotations;
sliderDragging = false;
valueChanged(true);
}
- ap.paintAlignment(true);
}
});
}
*/
public Vector<String> getAnnotationItems(boolean isSeqAssociated)
{
- annotationLabels = new HashMap<AlignmentAnnotation, String>();
+ annotationLabels = new HashMap<>();
- Vector<String> list = new Vector<String>();
+ Vector<String> list = new Vector<>();
int index = 1;
int[] anmap = new int[av.getAlignment()
.getAlignmentAnnotation().length];
public void cancel_actionPerformed()
{
reset();
- ap.paintAlignment(true);
+ ap.paintAlignment(true, true);
try
{
frame.setClosed(true);
this.currentAnnotation = annotation;
}
+ /**
+ * update associated view model and trigger any necessary repaints.
+ *
+ * @param updateAllAnnotation
+ */
protected abstract void valueChanged(boolean updateAllAnnotation);
protected abstract void updateView();
*/
if (ap != null)
{
- ap.paintAlignment(true);
+ ap.paintAlignment(true, true);
}
}
});
* feature type, and repaints the alignment, and optionally the Overview
* and/or structure viewer if open
*
- * @param updateOverview
+ * @param updateStructsAndOverview
*/
- void changeColour(boolean updateOverview)
+ void changeColour(boolean updateStructsAndOverview)
{
// Check if combobox is still adjusting
if (adjusting)
}
fr.setColour(type, acg);
cs = acg;
- ap.paintAlignment(updateOverview);
+ ap.paintAlignment(updateStructsAndOverview, updateStructsAndOverview);
}
@Override
void reset()
{
fr.setColour(type, oldcs);
- ap.paintAlignment(true);
+ ap.paintAlignment(true, true);
cs = null;
}
/*
* force repaint of any Overview window or structure
*/
- ap.paintAlignment(true);
+ ap.paintAlignment(true, true);
} catch (NumberFormatException ex)
{
}
JPanel choosePanel = new JPanel();
choosePanel.add(new JLabel(
MessageManager.getString("label.select_feature") + ":"));
- final JComboBox<String> overlaps = new JComboBox<String>();
+ final JComboBox<String> overlaps = new JComboBox<>();
List<String> added = new ArrayList<>();
for (SequenceFeature sf : features)
{
featuresAdded();
- alignPanel.paintAlignment(true);
+ alignPanel.paintAlignment(true, true);
return true;
}
}
}
- alignPanel.paintAlignment(true);
+ alignPanel.paintAlignment(true, true);
return true;
}
private static final int MIN_WIDTH = 400;
private static final int MIN_HEIGHT = 400;
+
+ /**
+ * when true, constructor is still executing - so ignore UI events
+ */
+ protected volatile boolean inConstruction = true;
/**
* Constructor
};
});
frame.setLayer(JLayeredPane.PALETTE_LAYER);
+ inConstruction = false;
}
protected void popupSort(final int selectedRow, final String type,
@Override
synchronized public void discoverAllFeatureData()
{
- Set<String> allGroups = new HashSet<String>();
+ Set<String> allGroups = new HashSet<>();
AlignmentI alignment = af.getViewport().getAlignment();
for (int i = 0; i < alignment.getHeight(); i++)
return;
}
resettingTable = true;
- typeWidth = new Hashtable<String, float[]>();
+ typeWidth = new Hashtable<>();
// TODO: change avWidth calculation to 'per-sequence' average and use long
// rather than float
- Set<String> displayableTypes = new HashSet<String>();
- Set<String> foundGroups = new HashSet<String>();
+ Set<String> displayableTypes = new HashSet<>();
+ Set<String> foundGroups = new HashSet<>();
/*
* determine which feature types may be visible depending on
* and keep track of which groups are visible
*/
Set<String> groups = seq.getFeatures().getFeatureGroups(true);
- Set<String> visibleGroups = new HashSet<String>();
+ Set<String> visibleGroups = new HashSet<>();
for (String group : groups)
{
if (group == null || checkGroupState(group))
{
if (fr.setFeaturePriority(data, visibleNew))
{
- af.alignPanel.paintAlignment(true);
+ af.alignPanel.paintAlignment(true, true);
}
}
@Override
public void stateChanged(ChangeEvent evt)
{
- fr.setTransparency((100 - transparency.getValue()) / 100f);
- af.alignPanel.paintAlignment(true);
+ if (!inConstruction)
+ {
+ fr.setTransparency((100 - transparency.getValue()) / 100f);
+ af.alignPanel.paintAlignment(true,true);
+ }
}
});
{
ap.av.antiAlias = smoothFont.isSelected();
ap.getAnnotationPanel().image = null;
- ap.paintAlignment(true);
+ ap.paintAlignment(true, false);
if (ap.av.getCodingComplement() != null && ap.av.isProteinFontAsCdna())
{
((AlignViewport) ap.av
ap.av.setScaleProteinAsCdna(oldProteinScale);
ap.av.setProteinFontAsCdna(oldMirrorFont);
ap.av.antiAlias = oldSmoothFont;
- ap.paintAlignment(true);
+ ap.paintAlignment(true, false);
if (scaleAsCdna.isVisible() && scaleAsCdna.isEnabled())
{
}
lastid = seq;
- alignPanel.paintAlignment(false);
+ alignPanel.paintAlignment(false, false);
}
/**
av.isSelectionGroupChanged(true);
- alignPanel.paintAlignment(false);
+ alignPanel.paintAlignment(false, false);
}
/**
running = false;
}
- alignPanel.paintAlignment(false);
+ alignPanel.paintAlignment(false, false);
try
{
* @param evt
* DOCUMENT ME!
*/
+ @Override
public void mousePressed(MouseEvent evt)
{
oldX = evt.getX();
* @param evt
* DOCUMENT ME!
*/
+ @Override
public void mouseReleased(MouseEvent evt)
{
active = false;
* @param evt
* DOCUMENT ME!
*/
+ @Override
public void mouseEntered(MouseEvent evt)
{
active = true;
* @param evt
* DOCUMENT ME!
*/
+ @Override
public void mouseExited(MouseEvent evt)
{
active = false;
* @param evt
* DOCUMENT ME!
*/
+ @Override
public void mouseDragged(MouseEvent evt)
{
active = true;
{
viewport.setIdWidth(newWidth);
- ap.paintAlignment(true);
+ ap.paintAlignment(true, false);
}
oldX = evt.getX();
* @param evt
* DOCUMENT ME!
*/
+ @Override
public void mouseMoved(MouseEvent evt)
{
}
* @param evt
* DOCUMENT ME!
*/
+ @Override
public void mouseClicked(MouseEvent evt)
{
}
* @param g
* DOCUMENT ME!
*/
+ @Override
public void paintComponent(Graphics g)
{
g.setColor(Color.white);
}
sequence.setName(dialog.getName().replace(' ', '_'));
- ap.paintAlignment(false);
+ ap.paintAlignment(false, false);
}
sequence.setDescription(dialog.getDescription());
AlignmentPanel ap;
- Stack<CommandI> historyList = new Stack<CommandI>();
+ Stack<CommandI> historyList = new Stack<>();
// simpler than synching with alignFrame.
}
float value = slider.getValue();
- List<SequenceI> redundantSequences = new ArrayList<SequenceI>();
+ List<SequenceI> redundantSequences = new ArrayList<>();
for (int i = 0; i < redundancy.length; i++)
{
if (value <= redundancy[i])
af.updateEditMenuBar();
}
- ap.paintAlignment(true);
+ ap.paintAlignment(true, true);
if (historyList.size() == 0)
{
{
av.showColumn(reveal[0]);
reveal = null;
- ap.paintAlignment(true);
+ ap.paintAlignment(true, true);
av.sendSelection();
}
});
{
av.showAllHiddenColumns();
reveal = null;
- ap.paintAlignment(true);
+ ap.paintAlignment(true, true);
av.sendSelection();
}
});
av.setSelectionGroup(null);
}
- ap.paintAlignment(true);
+ ap.paintAlignment(true, true);
av.sendSelection();
}
});
sg.setEndRes(max);
}
av.setSelectionGroup(sg);
- ap.paintAlignment(false);
+ ap.paintAlignment(false, false);
av.sendSelection();
}
}
else
{
- ap.paintAlignment(false);
+ ap.paintAlignment(false, false);
}
return;
}
}
}
stretchingGroup = false;
- ap.paintAlignment(false);
+ ap.paintAlignment(false, false);
av.sendSelection();
}
{
stretchingGroup = true;
cs.stretchGroup(res, sg, min, max);
- ap.paintAlignment(false);
+ ap.paintAlignment(false, false);
}
}
import jalview.datamodel.SequenceI;
import jalview.renderer.ScaleRenderer;
import jalview.renderer.ScaleRenderer.ScaleMark;
+import jalview.util.Comparison;
import jalview.viewmodel.ViewportListenerI;
import jalview.viewmodel.ViewportRanges;
import javax.swing.JComponent;
/**
- * DOCUMENT ME!
+ * The Swing component on which the alignment sequences, and annotations (if
+ * shown), are drawn. This includes scales above, left and right (if shown) in
+ * Wrapped mode, but not the scale above in Unwrapped mode.
*
- * @author $author$
- * @version $Revision$
*/
public class SeqCanvas extends JComponent implements ViewportListenerI
{
- private static String ZEROS = "0000000000";
+ private static final String ZEROS = "0000000000";
final FeatureRenderer fr;
- final SequenceRenderer seqRdr;
-
BufferedImage img;
- Graphics2D gg;
-
AlignViewport av;
- boolean fastPaint = false;
+ int cursorX = 0;
- int labelWidthWest;
+ int cursorY = 0;
- int labelWidthEast;
+ private final SequenceRenderer seqRdr;
- int cursorX = 0;
+ private boolean fastPaint = false;
- int cursorY = 0;
+ private boolean fastpainting = false;
- int charHeight = 0;
+ private AnnotationPanel annotations;
- int charWidth = 0;
+ /*
+ * measurements for drawing a wrapped alignment
+ */
+ private int labelWidthEast; // label right width in pixels if shown
+
+ private int labelWidthWest; // label left width in pixels if shown
- boolean fastpainting = false;
+ private int wrappedSpaceAboveAlignment; // gap between widths
- AnnotationPanel annotations;
+ private int wrappedRepeatHeightPx; // height in pixels of wrapped width
+
+ private int wrappedVisibleWidths; // number of wrapped widths displayed
+
+ private Graphics2D gg;
/**
* Creates a new SeqCanvas object.
*
- * @param av
- * DOCUMENT ME!
+ * @param ap
*/
public SeqCanvas(AlignmentPanel ap)
{
this.av = ap.av;
- updateViewport();
fr = new FeatureRenderer(ap);
seqRdr = new SequenceRenderer(av);
setLayout(new BorderLayout());
return fr;
}
- private void updateViewport()
- {
- charHeight = av.getCharHeight();
- charWidth = av.getCharWidth();
- }
-
/**
- * DOCUMENT ME!
+ * Draws the scale above a region of a wrapped alignment, consisting of a
+ * column number every major interval (10 columns).
*
* @param g
- * DOCUMENT ME!
+ * the graphics context to draw on, positioned at the start (bottom
+ * left) of the line on which to draw any scale marks
* @param startx
- * DOCUMENT ME!
+ * start alignment column (0..)
* @param endx
- * DOCUMENT ME!
+ * end alignment column (0..)
* @param ypos
- * DOCUMENT ME!
+ * y offset to draw at
*/
private void drawNorthScale(Graphics g, int startx, int endx, int ypos)
{
- updateViewport();
- for (ScaleMark mark : new ScaleRenderer().calculateMarks(av, startx,
- endx))
+ int charHeight = av.getCharHeight();
+ int charWidth = av.getCharWidth();
+
+ /*
+ * white fill the scale space (for the fastPaint case)
+ */
+ g.setColor(Color.white);
+ g.fillRect(0, ypos - charHeight - charHeight / 2, getWidth(),
+ charHeight * 3 / 2 + 2);
+ g.setColor(Color.black);
+
+ List<ScaleMark> marks = new ScaleRenderer().calculateMarks(av, startx,
+ endx);
+ for (ScaleMark mark : marks)
{
int mpos = mark.column; // (i - startx - 1)
if (mpos < 0)
{
g.drawString(mstring, mpos * charWidth, ypos - (charHeight / 2));
}
- g.drawLine((mpos * charWidth) + (charWidth / 2),
- (ypos + 2) - (charHeight / 2),
- (mpos * charWidth) + (charWidth / 2), ypos - 2);
+
+ /*
+ * draw a tick mark below the column number, centred on the column;
+ * height of tick mark is 4 pixels less than half a character
+ */
+ int xpos = (mpos * charWidth) + (charWidth / 2);
+ g.drawLine(xpos, (ypos + 2) - (charHeight / 2), xpos, ypos - 2);
}
}
}
/**
- * DOCUMENT ME!
+ * Draw the scale to the left or right of a wrapped alignment
*
* @param g
- * DOCUMENT ME!
+ * graphics context, positioned at the start of the scale to be drawn
* @param startx
- * DOCUMENT ME!
+ * first column of wrapped width (0.. excluding any hidden columns)
* @param endx
- * DOCUMENT ME!
+ * last column of wrapped width (0.. excluding any hidden columns)
* @param ypos
- * DOCUMENT ME!
+ * vertical offset at which to begin the scale
+ * @param left
+ * if true, scale is left of residues, if false, scale is right
*/
- void drawWestScale(Graphics g, int startx, int endx, int ypos)
+ void drawVerticalScale(Graphics g, final int startx, final int endx,
+ final int ypos, final boolean left)
{
- FontMetrics fm = getFontMetrics(av.getFont());
- ypos += charHeight;
+ int charHeight = av.getCharHeight();
+ int charWidth = av.getCharWidth();
- if (av.hasHiddenColumns())
- {
- startx = av.getAlignment().getHiddenColumns()
- .adjustForHiddenColumns(startx);
- endx = av.getAlignment().getHiddenColumns()
- .adjustForHiddenColumns(endx);
- }
+ int yPos = ypos + charHeight;
+ int startX = startx;
+ int endX = endx;
- int maxwidth = av.getAlignment().getWidth();
if (av.hasHiddenColumns())
{
- maxwidth = av.getAlignment().getHiddenColumns()
- .findColumnPosition(maxwidth) - 1;
+ HiddenColumns hiddenColumns = av.getAlignment().getHiddenColumns();
+ startX = hiddenColumns.adjustForHiddenColumns(startx);
+ endX = hiddenColumns.adjustForHiddenColumns(endx);
}
+ FontMetrics fm = getFontMetrics(av.getFont());
- // WEST SCALE
for (int i = 0; i < av.getAlignment().getHeight(); i++)
{
SequenceI seq = av.getAlignment().getSequenceAt(i);
- int index = startx;
- int value = -1;
- while (index < endx)
+ /*
+ * find sequence position of first non-gapped position -
+ * to the right if scale left, to the left if scale right
+ */
+ int index = left ? startX : endX;
+ int value = -1;
+ while (index >= startX && index <= endX)
{
- if (jalview.util.Comparison.isGap(seq.getCharAt(index)))
+ if (!Comparison.isGap(seq.getCharAt(index)))
+ {
+ value = seq.findPosition(index);
+ break;
+ }
+ if (left)
{
index++;
-
- continue;
}
-
- value = av.getAlignment().getSequenceAt(i).findPosition(index);
-
- break;
- }
-
- if (value != -1)
- {
- int x = labelWidthWest - fm.stringWidth(String.valueOf(value))
- - charWidth / 2;
- g.drawString(value + "", x,
- (ypos + (i * charHeight)) - (charHeight / 5));
- }
- }
- }
-
- /**
- * DOCUMENT ME!
- *
- * @param g
- * DOCUMENT ME!
- * @param startx
- * DOCUMENT ME!
- * @param endx
- * DOCUMENT ME!
- * @param ypos
- * DOCUMENT ME!
- */
- void drawEastScale(Graphics g, int startx, int endx, int ypos)
- {
- ypos += charHeight;
-
- if (av.hasHiddenColumns())
- {
- endx = av.getAlignment().getHiddenColumns()
- .adjustForHiddenColumns(endx);
- }
-
- SequenceI seq;
- // EAST SCALE
- for (int i = 0; i < av.getAlignment().getHeight(); i++)
- {
- seq = av.getAlignment().getSequenceAt(i);
- int index = endx;
- int value = -1;
-
- while (index > startx)
- {
- if (jalview.util.Comparison.isGap(seq.getCharAt(index)))
+ else
{
index--;
-
- continue;
}
-
- value = seq.findPosition(index);
-
- break;
}
+ /*
+ * white fill the space for the scale
+ */
+ g.setColor(Color.white);
+ int y = (yPos + (i * charHeight)) - (charHeight / 5);
+ // fillRect origin is top left of rectangle
+ g.fillRect(0, y - charHeight, left ? labelWidthWest : labelWidthEast,
+ charHeight + 1);
+
if (value != -1)
{
- g.drawString(String.valueOf(value), 0,
- (ypos + (i * charHeight)) - (charHeight / 5));
+ /*
+ * draw scale value, right justified within its width less half a
+ * character width padding on the right
+ */
+ int labelSpace = left ? labelWidthWest : labelWidthEast;
+ labelSpace -= charWidth / 2; // leave space to the right
+ String valueAsString = String.valueOf(value);
+ int labelLength = fm.stringWidth(valueAsString);
+ int xOffset = labelSpace - labelLength;
+ g.setColor(Color.black);
+ g.drawString(valueAsString, xOffset, y);
}
}
}
-
/**
- * need to make this thread safe move alignment rendering in response to
- * slider adjustment
+ * Does a fast paint of an alignment in response to a scroll. Most of the
+ * visible region is simply copied and shifted, and then any newly visible
+ * columns or rows are drawn. The scroll may be horizontal or vertical, but
+ * not both at once. Scrolling may be the result of
+ * <ul>
+ * <li>dragging a scroll bar</li>
+ * <li>clicking in the scroll bar</li>
+ * <li>scrolling by trackpad, middle mouse button, or other device</li>
+ * <li>by moving the box in the Overview window</li>
+ * <li>programmatically to make a highlighted position visible</li>
+ * </ul>
*
* @param horizontal
- * shift along
+ * columns to shift right (positive) or left (negative)
* @param vertical
- * shift up or down in repaint
+ * rows to shift down (positive) or up (negative)
*/
public void fastPaint(int horizontal, int vertical)
{
}
fastpainting = true;
fastPaint = true;
- updateViewport();
- ViewportRanges ranges = av.getRanges();
- int startRes = ranges.getStartRes();
- int endRes = ranges.getEndRes();
- int startSeq = ranges.getStartSeq();
- int endSeq = ranges.getEndSeq();
- int transX = 0;
- int transY = 0;
+ try
+ {
+ int charHeight = av.getCharHeight();
+ int charWidth = av.getCharWidth();
+
+ ViewportRanges ranges = av.getRanges();
+ int startRes = ranges.getStartRes();
+ int endRes = ranges.getEndRes();
+ int startSeq = ranges.getStartSeq();
+ int endSeq = ranges.getEndSeq();
+ int transX = 0;
+ int transY = 0;
gg.copyArea(horizontal * charWidth, vertical * charHeight,
img.getWidth(), img.getHeight(), -horizontal * charWidth,
gg.translate(-transX, -transY);
repaint();
- fastpainting = false;
+ } finally
+ {
+ fastpainting = false;
+ }
}
@Override
public void paintComponent(Graphics g)
{
- super.paintComponent(g);
-
- updateViewport();
+ super.paintComponent(g);
+
+ int charHeight = av.getCharHeight();
+ int charWidth = av.getCharWidth();
ViewportRanges ranges = av.getRanges();
g.drawImage(lcimg, 0, 0, this);
}
}
-
+
/**
* Draw an alignment panel for printing
*
{
BufferedImage lcimg = null;
+ int charWidth = av.getCharWidth();
+ int charHeight = av.getCharHeight();
+
int width = getWidth();
int height = getHeight();
*/
public int getWrappedCanvasWidth(int canvasWidth)
{
- FontMetrics fm = getFontMetrics(av.getFont());
+ int charWidth = av.getCharWidth();
- labelWidthEast = 0;
- labelWidthWest = 0;
+ FontMetrics fm = getFontMetrics(av.getFont());
- if (av.getScaleRightWrapped())
+ int labelWidth = 0;
+
+ if (av.getScaleRightWrapped() || av.getScaleLeftWrapped())
{
- labelWidthEast = getLabelWidth(fm);
+ labelWidth = getLabelWidth(fm);
}
- if (av.getScaleLeftWrapped())
- {
- labelWidthWest = labelWidthEast > 0 ? labelWidthEast
- : getLabelWidth(fm);
- }
+ labelWidthEast = av.getScaleRightWrapped() ? labelWidth : 0;
+
+ labelWidthWest = av.getScaleLeftWrapped() ? labelWidth : 0;
return (canvasWidth - labelWidthEast - labelWidthWest) / charWidth;
}
/**
- * Returns a pixel width suitable for showing the largest sequence coordinate
- * (end position) in the alignment. Returns 2 plus the number of decimal
- * digits to be shown (3 for 1-10, 4 for 11-99 etc).
+ * Returns a pixel width sufficient to show the largest sequence coordinate
+ * (end position) in the alignment, calculated as the FontMetrics width of
+ * zeroes "0000000" limited to the number of decimal digits to be shown (3 for
+ * 1-10, 4 for 11-99 etc). One character width is added to this, to allow for
+ * half a character width space on either side.
*
* @param fm
* @return
maxWidth = Math.max(maxWidth, alignment.getSequenceAt(i).getEnd());
}
- int length = 2;
+ int length = 0;
for (int i = maxWidth; i > 0; i /= 10)
{
length++;
}
- return fm.stringWidth(ZEROS.substring(0, length));
+ return fm.stringWidth(ZEROS.substring(0, length)) + av.getCharWidth();
}
/**
- * DOCUMENT ME!
+ * Draws as many widths of a wrapped alignment as can fit in the visible
+ * window
*
* @param g
- * DOCUMENT ME!
* @param canvasWidth
- * DOCUMENT ME!
+ * available width in pixels
* @param canvasHeight
- * DOCUMENT ME!
- * @param startRes
- * DOCUMENT ME!
+ * available height in pixels
+ * @param startColumn
+ * the first column (0...) of the alignment to draw
*/
- private void drawWrappedPanel(Graphics g, int canvasWidth,
- int canvasHeight, int startRes)
+ public void drawWrappedPanel(Graphics g, int canvasWidth,
+ int canvasHeight, final int startColumn)
{
- updateViewport();
- AlignmentI al = av.getAlignment();
+ int wrappedWidthInResidues = calculateWrappedGeometry(canvasWidth,
+ canvasHeight);
- int labelWidth = 0;
- if (av.getScaleRightWrapped() || av.getScaleLeftWrapped())
+ av.setWrappedWidth(wrappedWidthInResidues);
+
+ ViewportRanges ranges = av.getRanges();
+ ranges.setViewportStartAndWidth(startColumn, wrappedWidthInResidues);
+
+ /*
+ * draw one width at a time (including any scales or annotation shown),
+ * until we have run out of either alignment or vertical space available
+ */
+ int ypos = wrappedSpaceAboveAlignment;
+ int maxWidth = ranges.getVisibleAlignmentWidth();
+
+ int start = startColumn;
+ int currentWidth = 0;
+ while ((currentWidth < wrappedVisibleWidths) && (start < maxWidth))
{
- FontMetrics fm = getFontMetrics(av.getFont());
- labelWidth = getLabelWidth(fm);
+ int endColumn = Math
+ .min(maxWidth, start + wrappedWidthInResidues - 1);
+ drawWrappedWidth(g, ypos, start, endColumn, canvasHeight);
+ ypos += wrappedRepeatHeightPx;
+ start += wrappedWidthInResidues;
+ currentWidth++;
}
- labelWidthEast = av.getScaleRightWrapped() ? labelWidth : 0;
- labelWidthWest = av.getScaleLeftWrapped() ? labelWidth : 0;
+ drawWrappedDecorators(g, startColumn);
+ }
- int hgap = charHeight;
- if (av.getScaleAboveWrapped())
+ /**
+ * Calculates and saves values needed when rendering a wrapped alignment.
+ * These depend on many factors, including
+ * <ul>
+ * <li>canvas width and height</li>
+ * <li>number of visible sequences, and height of annotations if shown</li>
+ * <li>font and character width</li>
+ * <li>whether scales are shown left, right or above the alignment</li>
+ * </ul>
+ *
+ * @param canvasWidth
+ * @param canvasHeight
+ * @return the number of residue columns in each width
+ */
+ protected int calculateWrappedGeometry(int canvasWidth, int canvasHeight)
+ {
+ int charHeight = av.getCharHeight();
+
+ /*
+ * vertical space in pixels between wrapped widths of alignment
+ * - one character height, or two if scale above is drawn
+ */
+ wrappedSpaceAboveAlignment = charHeight
+ * (av.getScaleAboveWrapped() ? 2 : 1);
+
+ /*
+ * height in pixels of the wrapped widths
+ */
+ wrappedRepeatHeightPx = wrappedSpaceAboveAlignment;
+ // add sequences
+ wrappedRepeatHeightPx += av.getRanges().getViewportHeight()
+ * charHeight;
+ // add annotations panel height if shown
+ wrappedRepeatHeightPx += getAnnotationHeight();
+
+ /*
+ * number of visible widths (the last one may be part height),
+ * ensuring a part height includes at least one sequence
+ */
+ ViewportRanges ranges = av.getRanges();
+ wrappedVisibleWidths = canvasHeight / wrappedRepeatHeightPx;
+ int remainder = canvasHeight % wrappedRepeatHeightPx;
+ if (remainder >= (wrappedSpaceAboveAlignment + charHeight))
{
- hgap += charHeight;
+ wrappedVisibleWidths++;
}
- int cWidth = (canvasWidth - labelWidthEast - labelWidthWest) / charWidth;
- int cHeight = av.getAlignment().getHeight() * charHeight;
+ /*
+ * compute width in residues; this also sets East and West label widths
+ */
+ int wrappedWidthInResidues = getWrappedCanvasWidth(canvasWidth);
- av.setWrappedWidth(cWidth);
+ /*
+ * limit visibleWidths to not exceed width of alignment
+ */
+ int xMax = ranges.getVisibleAlignmentWidth();
+ int startToEnd = xMax - ranges.getStartRes();
+ int maxWidths = startToEnd / wrappedWidthInResidues;
+ if (startToEnd % wrappedWidthInResidues > 0)
+ {
+ maxWidths++;
+ }
+ wrappedVisibleWidths = Math.min(wrappedVisibleWidths, maxWidths);
- av.getRanges().setViewportStartAndWidth(startRes, cWidth);
+ return wrappedWidthInResidues;
+ }
- int endx;
- int ypos = hgap;
- int maxwidth = av.getAlignment().getWidth();
+ /**
+ * Draws one width of a wrapped alignment, including sequences and
+ * annnotations, if shown, but not scales or hidden column markers
+ *
+ * @param g
+ * @param ypos
+ * @param startColumn
+ * @param endColumn
+ * @param canvasHeight
+ */
+ protected void drawWrappedWidth(Graphics g, int ypos, int startColumn,
+ int endColumn, int canvasHeight)
+ {
+ ViewportRanges ranges = av.getRanges();
+ int viewportWidth = ranges.getViewportWidth();
- if (av.hasHiddenColumns())
+ int endx = Math.min(startColumn + viewportWidth - 1, endColumn);
+
+ /*
+ * move right before drawing by the width of the scale left (if any)
+ * plus column offset from left margin (usually zero, but may be non-zero
+ * when fast painting is drawing just a few columns)
+ */
+ int charWidth = av.getCharWidth();
+ int xOffset = labelWidthWest
+ + ((startColumn - ranges.getStartRes()) % viewportWidth)
+ * charWidth;
+ g.translate(xOffset, 0);
+
+ // When printing we have an extra clipped region,
+ // the Printable page which we need to account for here
+ Shape clip = g.getClip();
+
+ if (clip == null)
{
- maxwidth = av.getAlignment().getHiddenColumns()
- .findColumnPosition(maxwidth);
+ g.setClip(0, 0, viewportWidth * charWidth, canvasHeight);
+ }
+ else
+ {
+ g.setClip(0, (int) clip.getBounds().getY(),
+ viewportWidth * charWidth, (int) clip.getBounds().getHeight());
}
- int annotationHeight = getAnnotationHeight();
+ /*
+ * white fill the region to be drawn (so incremental fast paint doesn't
+ * scribble over an existing image)
+ */
+ gg.setColor(Color.white);
+ gg.fillRect(0, ypos, (endx - startColumn + 1) * charWidth,
+ wrappedRepeatHeightPx);
- while ((ypos <= canvasHeight) && (startRes < maxwidth))
- {
- endx = startRes + cWidth - 1;
+ drawPanel(g, startColumn, endx, 0, av.getAlignment().getHeight() - 1,
+ ypos);
- if (endx > maxwidth)
+ int cHeight = av.getAlignment().getHeight() * av.getCharHeight();
+
+ if (av.isShowAnnotation())
+ {
+ g.translate(0, cHeight + ypos + 3);
+ if (annotations == null)
{
- endx = maxwidth;
+ annotations = new AnnotationPanel(av);
}
- g.setFont(av.getFont());
- g.setColor(Color.black);
+ annotations.renderer.drawComponent(annotations, av, g, -1,
+ startColumn, endx + 1);
+ g.translate(0, -cHeight - ypos - 3);
+ }
+ g.setClip(clip);
+ g.translate(-xOffset, 0);
+ }
+
+ /**
+ * Draws scales left, right and above (if shown), and any hidden column
+ * markers, on all widths of the wrapped alignment
+ *
+ * @param g
+ * @param startColumn
+ */
+ protected void drawWrappedDecorators(Graphics g, final int startColumn)
+ {
+ int charWidth = av.getCharWidth();
+
+ g.setFont(av.getFont());
+ g.setColor(Color.black);
+
+ int ypos = wrappedSpaceAboveAlignment;
+ ViewportRanges ranges = av.getRanges();
+ int viewportWidth = ranges.getViewportWidth();
+ int maxWidth = ranges.getVisibleAlignmentWidth();
+ int widthsDrawn = 0;
+ int startCol = startColumn;
+
+ while (widthsDrawn < wrappedVisibleWidths)
+ {
+ int endColumn = Math.min(maxWidth, startCol + viewportWidth - 1);
if (av.getScaleLeftWrapped())
{
- drawWestScale(g, startRes, endx, ypos);
+ drawVerticalScale(g, startCol, endColumn - 1, ypos, true);
}
if (av.getScaleRightWrapped())
{
- g.translate(canvasWidth - labelWidthEast, 0);
- drawEastScale(g, startRes, endx, ypos);
- g.translate(-(canvasWidth - labelWidthEast), 0);
+ int x = labelWidthWest + viewportWidth * charWidth;
+ g.translate(x, 0);
+ drawVerticalScale(g, startCol, endColumn, ypos, false);
+ g.translate(-x, 0);
}
+ /*
+ * white fill region of scale above and hidden column markers
+ * (to support incremental fast paint of image)
+ */
+ g.translate(labelWidthWest, 0);
+ g.setColor(Color.white);
+ g.fillRect(0, ypos - wrappedSpaceAboveAlignment, viewportWidth
+ * charWidth + labelWidthWest, wrappedSpaceAboveAlignment);
+ g.setColor(Color.black);
+ g.translate(-labelWidthWest, 0);
+
g.translate(labelWidthWest, 0);
if (av.getScaleAboveWrapped())
{
- drawNorthScale(g, startRes, endx, ypos);
+ drawNorthScale(g, startCol, endColumn, ypos);
}
if (av.hasHiddenColumns() && av.getShowHiddenMarkers())
{
- g.setColor(Color.blue);
- int res;
- HiddenColumns hidden = av.getAlignment().getHiddenColumns();
- List<Integer> positions = hidden.findHiddenRegionPositions();
- for (int pos : positions)
- {
- res = pos - startRes;
-
- if (res < 0 || res > endx - startRes)
- {
- continue;
- }
-
- gg.fillPolygon(
- new int[]
- { res * charWidth - charHeight / 4,
- res * charWidth + charHeight / 4, res * charWidth },
- new int[]
- { ypos - (charHeight / 2), ypos - (charHeight / 2),
- ypos - (charHeight / 2) + 8 },
- 3);
-
- }
+ drawHiddenColumnMarkers(g, ypos, startCol, endColumn);
}
- // When printing we have an extra clipped region,
- // the Printable page which we need to account for here
- Shape clip = g.getClip();
+ g.translate(-labelWidthWest, 0);
- if (clip == null)
- {
- g.setClip(0, 0, cWidth * charWidth, canvasHeight);
- }
- else
- {
- g.setClip(0, (int) clip.getBounds().getY(), cWidth * charWidth,
- (int) clip.getBounds().getHeight());
- }
+ ypos += wrappedRepeatHeightPx;
+ startCol += viewportWidth;
+ widthsDrawn++;
+ }
+ }
+
+ /**
+ * Draws markers (triangles) above hidden column positions between startColumn
+ * and endColumn.
+ *
+ * @param g
+ * @param ypos
+ * @param startColumn
+ * @param endColumn
+ */
+ protected void drawHiddenColumnMarkers(Graphics g, int ypos,
+ int startColumn, int endColumn)
+ {
+ int charHeight = av.getCharHeight();
+ int charWidth = av.getCharWidth();
- drawPanel(g, startRes, endx, 0, al.getHeight() - 1, ypos);
+ g.setColor(Color.blue);
+ HiddenColumns hidden = av.getAlignment().getHiddenColumns();
+ List<Integer> positions = hidden.findHiddenRegionPositions();
+ for (int pos : positions)
+ {
+ int res = pos - startColumn;
- if (av.isShowAnnotation())
+ if (res < 0 || res > endColumn - startColumn + 1)
{
- g.translate(0, cHeight + ypos + 3);
- if (annotations == null)
- {
- annotations = new AnnotationPanel(av);
- }
-
- annotations.renderer.drawComponent(annotations, av, g, -1, startRes,
- endx + 1);
- g.translate(0, -cHeight - ypos - 3);
+ continue;
}
- g.setClip(clip);
- g.translate(-labelWidthWest, 0);
-
- ypos += cHeight + annotationHeight + hgap;
- startRes += cWidth;
+ /*
+ * draw a downward-pointing triangle at the hidden columns location
+ * (before the following visible column)
+ */
+ int xMiddle = res * charWidth;
+ int[] xPoints = new int[] { xMiddle - charHeight / 4,
+ xMiddle + charHeight / 4, xMiddle };
+ int yTop = ypos - (charHeight / 2);
+ int[] yPoints = new int[] { yTop, yTop, yTop + 8 };
+ g.fillPolygon(xPoints, yPoints, 3);
}
}
int canvasWidth,
int canvasHeight, int startRes)
{
+ int charHeight = av.getCharHeight();
+ int charWidth = av.getCharWidth();
+
// height gap above each panel
int hgap = charHeight;
if (av.getScaleAboveWrapped())
* marker.
*
* @param g1
- * Graphics object to draw with
+ * the graphics context, positioned at the first residue to be drawn
* @param startRes
- * offset of the first column in the visible region (0..)
+ * offset of the first column to draw (0..)
* @param endRes
- * offset of the last column in the visible region (0..)
+ * offset of the last column to draw (0..)
* @param startSeq
- * offset of the first sequence in the visible region (0..)
+ * offset of the first sequence to draw (0..)
* @param endSeq
- * offset of the last sequence in the visible region (0..)
+ * offset of the last sequence to draw (0..)
* @param yOffset
* vertical offset at which to draw (for wrapped alignments)
*/
public void drawPanel(Graphics g1, final int startRes, final int endRes,
final int startSeq, final int endSeq, final int yOffset)
{
- updateViewport();
+ int charHeight = av.getCharHeight();
+ int charWidth = av.getCharWidth();
+
if (!av.hasHiddenColumns())
{
draw(g1, startRes, endRes, startSeq, endSeq, yOffset);
private void draw(Graphics g, int startRes, int endRes, int startSeq,
int endSeq, int offset)
{
+ int charHeight = av.getCharHeight();
+ int charWidth = av.getCharWidth();
+
g.setFont(av.getFont());
seqRdr.prepare(g, av.isRenderGaps());
private void drawUnwrappedSelection(Graphics2D g, SequenceGroup group,
int startRes, int endRes, int startSeq, int endSeq, int offset)
{
+ int charWidth = av.getCharWidth();
+
if (!av.hasHiddenColumns())
{
drawPartialGroupOutline(g, group, startRes, endRes, startSeq, endSeq,
int startRes, int endRes, int startSeq, int endSeq,
int verticalOffset)
{
+ int charHeight = av.getCharHeight();
+ int charWidth = av.getCharWidth();
+
int visWidth = (endRes - startRes + 1) * charWidth;
int oldY = -1;
return false;
}
boolean wrapped = av.getWrapAlignment();
-
try
{
fastPaint = !noFastPaint;
fastpainting = fastPaint;
- updateViewport();
-
/*
* to avoid redrawing the whole visible region, we instead
* redraw just the minimal regions to remove previous highlights
{
fastPaint = true;
repaint();
+ return;
}
- else if (av.getWrapAlignment())
+
+ int scrollX = 0;
+ if (eventName.equals(ViewportRanges.STARTRES))
{
- if (eventName.equals(ViewportRanges.STARTRES))
+ // Make sure we're not trying to draw a panel
+ // larger than the visible window
+ ViewportRanges vpRanges = av.getRanges();
+ scrollX = (int) evt.getNewValue() - (int) evt.getOldValue();
+ int range = vpRanges.getViewportWidth();
+ if (scrollX > range)
{
- repaint();
+ scrollX = range;
+ }
+ else if (scrollX < -range)
+ {
+ scrollX = -range;
}
}
- else
+
+ // Both scrolling and resizing change viewport ranges: scrolling changes
+ // both start and end points, but resize only changes end values.
+ // Here we only want to fastpaint on a scroll, with resize using a normal
+ // paint, so scroll events are identified as changes to the horizontal or
+ // vertical start value.
+
+ // scroll - startres and endres both change
+ if (eventName.equals(ViewportRanges.STARTRES))
{
- int scrollX = 0;
- if (eventName.equals(ViewportRanges.STARTRES))
+ if (av.getWrapAlignment())
{
- // Make sure we're not trying to draw a panel
- // larger than the visible window
- ViewportRanges vpRanges = av.getRanges();
- scrollX = (int) evt.getNewValue() - (int) evt.getOldValue();
- int range = vpRanges.getEndRes() - vpRanges.getStartRes();
- if (scrollX > range)
- {
- scrollX = range;
- }
- else if (scrollX < -range)
- {
- scrollX = -range;
- }
+ fastPaintWrapped(scrollX);
}
-
- // Both scrolling and resizing change viewport ranges: scrolling changes
- // both start and end points, but resize only changes end values.
- // Here we only want to fastpaint on a scroll, with resize using a normal
- // paint, so scroll events are identified as changes to the horizontal or
- // vertical start value.
- if (eventName.equals(ViewportRanges.STARTRES))
+ else
{
- // scroll - startres and endres both change
fastPaint(scrollX, 0);
}
- else if (eventName.equals(ViewportRanges.STARTSEQ))
+ }
+ else if (eventName.equals(ViewportRanges.STARTSEQ))
+ {
+ // scroll
+ fastPaint(0, (int) evt.getNewValue() - (int) evt.getOldValue());
+ }
+ }
+
+ /**
+ * Does a minimal update of the image for a scroll movement. This method
+ * handles scroll movements of up to one width of the wrapped alignment (one
+ * click in the vertical scrollbar). Larger movements (for example after a
+ * scroll to highlight a mapped position) trigger a full redraw instead.
+ *
+ * @param scrollX
+ * number of positions scrolled (right if positive, left if negative)
+ */
+ protected void fastPaintWrapped(int scrollX)
+ {
+ ViewportRanges ranges = av.getRanges();
+
+ if (Math.abs(scrollX) > ranges.getViewportWidth())
+ {
+ /*
+ * shift of more than one view width is
+ * overcomplicated to handle in this method
+ */
+ fastPaint = false;
+ repaint();
+ return;
+ }
+
+ if (fastpainting || gg == null)
+ {
+ return;
+ }
+
+ fastPaint = true;
+ fastpainting = true;
+
+ try
+ {
+ calculateWrappedGeometry(getWidth(), getHeight());
+
+ /*
+ * relocate the regions of the alignment that are still visible
+ */
+ shiftWrappedAlignment(-scrollX);
+
+ /*
+ * add new columns (sequence, annotation)
+ * - at top left if scrollX < 0
+ * - at right of last two widths if scrollX > 0
+ */
+ if (scrollX < 0)
+ {
+ int startRes = ranges.getStartRes();
+ drawWrappedWidth(gg, wrappedSpaceAboveAlignment, startRes, startRes
+ - scrollX - 1, getHeight());
+ }
+ else
+ {
+ fastPaintWrappedAddRight(scrollX);
+ }
+
+ /*
+ * draw all scales (if shown) and hidden column markers
+ */
+ drawWrappedDecorators(gg, ranges.getStartRes());
+
+ repaint();
+ } finally
+ {
+ fastpainting = false;
+ }
+ }
+
+ /**
+ * Draws the specified number of columns at the 'end' (bottom right) of a
+ * wrapped alignment view, including sequences and annotations if shown, but
+ * not scales. Also draws the same number of columns at the right hand end of
+ * the second last width shown, if the last width is not full height (so
+ * cannot simply be copied from the graphics image).
+ *
+ * @param columns
+ */
+ protected void fastPaintWrappedAddRight(int columns)
+ {
+ if (columns == 0)
+ {
+ return;
+ }
+
+ ViewportRanges ranges = av.getRanges();
+ int viewportWidth = ranges.getViewportWidth();
+ int charWidth = av.getCharWidth();
+
+ /**
+ * draw full height alignment in the second last row, last columns, if the
+ * last row was not full height
+ */
+ int visibleWidths = wrappedVisibleWidths;
+ int canvasHeight = getHeight();
+ boolean lastWidthPartHeight = (wrappedVisibleWidths * wrappedRepeatHeightPx) > canvasHeight;
+
+ if (lastWidthPartHeight)
+ {
+ int widthsAbove = Math.max(0, visibleWidths - 2);
+ int ypos = wrappedRepeatHeightPx * widthsAbove
+ + wrappedSpaceAboveAlignment;
+ int endRes = ranges.getEndRes();
+ endRes += widthsAbove * viewportWidth;
+ int startRes = endRes - columns;
+ int xOffset = ((startRes - ranges.getStartRes()) % viewportWidth)
+ * charWidth;
+
+ /*
+ * white fill first to erase annotations
+ */
+ gg.translate(xOffset, 0);
+ gg.setColor(Color.white);
+ gg.fillRect(labelWidthWest, ypos,
+ (endRes - startRes + 1) * charWidth, wrappedRepeatHeightPx);
+ gg.translate(-xOffset, 0);
+
+ drawWrappedWidth(gg, ypos, startRes, endRes, canvasHeight);
+ }
+
+ /*
+ * draw newly visible columns in last wrapped width (none if we
+ * have reached the end of the alignment)
+ * y-offset for drawing last width is height of widths above,
+ * plus one gap row
+ */
+ int widthsAbove = visibleWidths - 1;
+ int ypos = wrappedRepeatHeightPx * widthsAbove
+ + wrappedSpaceAboveAlignment;
+ int endRes = ranges.getEndRes();
+ endRes += widthsAbove * viewportWidth;
+ int startRes = endRes - columns + 1;
+
+ /*
+ * white fill first to erase annotations
+ */
+ int xOffset = ((startRes - ranges.getStartRes()) % viewportWidth)
+ * charWidth;
+ gg.translate(xOffset, 0);
+ gg.setColor(Color.white);
+ int width = viewportWidth * charWidth - xOffset;
+ gg.fillRect(labelWidthWest, ypos, width, wrappedRepeatHeightPx);
+ gg.translate(-xOffset, 0);
+
+ gg.setFont(av.getFont());
+ gg.setColor(Color.black);
+
+ if (startRes < ranges.getVisibleAlignmentWidth())
+ {
+ drawWrappedWidth(gg, ypos, startRes, endRes, canvasHeight);
+ }
+
+ /*
+ * and finally, white fill any space below the visible alignment
+ */
+ int heightBelow = canvasHeight - visibleWidths * wrappedRepeatHeightPx;
+ if (heightBelow > 0)
+ {
+ gg.setColor(Color.white);
+ gg.fillRect(0, canvasHeight - heightBelow, getWidth(), heightBelow);
+ }
+ }
+
+ /**
+ * Shifts the visible alignment by the specified number of columns - left if
+ * negative, right if positive. Copies and moves sequences and annotations (if
+ * shown). Scales, hidden column markers and any newly visible columns must be
+ * drawn separately.
+ *
+ * @param positions
+ */
+ protected void shiftWrappedAlignment(int positions)
+ {
+ if (positions == 0)
+ {
+ return;
+ }
+ int charWidth = av.getCharWidth();
+
+ int canvasHeight = getHeight();
+ ViewportRanges ranges = av.getRanges();
+ int viewportWidth = ranges.getViewportWidth();
+ int widthToCopy = (ranges.getViewportWidth() - Math.abs(positions))
+ * charWidth;
+ int heightToCopy = wrappedRepeatHeightPx - wrappedSpaceAboveAlignment;
+ int xMax = ranges.getVisibleAlignmentWidth();
+
+ if (positions > 0)
+ {
+ /*
+ * shift right (after scroll left)
+ * for each wrapped width (starting with the last), copy (width-positions)
+ * columns from the left margin to the right margin, and copy positions
+ * columns from the right margin of the row above (if any) to the
+ * left margin of the current row
+ */
+
+ /*
+ * get y-offset of last wrapped width, first row of sequences
+ */
+ int y = canvasHeight / wrappedRepeatHeightPx * wrappedRepeatHeightPx;
+ y += wrappedSpaceAboveAlignment;
+ int copyFromLeftStart = labelWidthWest;
+ int copyFromRightStart = copyFromLeftStart + widthToCopy;
+
+ while (y >= 0)
+ {
+ gg.copyArea(copyFromLeftStart, y, widthToCopy, heightToCopy,
+ positions * charWidth, 0);
+ if (y > 0)
+ {
+ gg.copyArea(copyFromRightStart, y - wrappedRepeatHeightPx,
+ positions * charWidth, heightToCopy, -widthToCopy,
+ wrappedRepeatHeightPx);
+ }
+
+ y -= wrappedRepeatHeightPx;
+ }
+ }
+ else
+ {
+ /*
+ * shift left (after scroll right)
+ * for each wrapped width (starting with the first), copy (width-positions)
+ * columns from the right margin to the left margin, and copy positions
+ * columns from the left margin of the row below (if any) to the
+ * right margin of the current row
+ */
+ int xpos = av.getRanges().getStartRes();
+ int y = wrappedSpaceAboveAlignment;
+ int copyFromRightStart = labelWidthWest - positions * charWidth;
+
+ while (y < canvasHeight)
{
- // scroll
- fastPaint(0, (int) evt.getNewValue() - (int) evt.getOldValue());
+ gg.copyArea(copyFromRightStart, y, widthToCopy, heightToCopy,
+ positions * charWidth, 0);
+ if (y + wrappedRepeatHeightPx < canvasHeight - wrappedRepeatHeightPx
+ && (xpos + viewportWidth <= xMax))
+ {
+ gg.copyArea(labelWidthWest, y + wrappedRepeatHeightPx, -positions
+ * charWidth, heightToCopy, widthToCopy,
+ -wrappedRepeatHeightPx);
+ }
+
+ y += wrappedRepeatHeightPx;
+ xpos += viewportWidth;
}
}
}
+
/**
* Redraws any positions in the search results in the visible region of a
* wrapped alignment. Any highlights are drawn depending on the search results
{
return false;
}
-
+ int charHeight = av.getCharHeight();
+
boolean matchFound = false;
+ calculateWrappedGeometry(getWidth(), getHeight());
int wrappedWidth = av.getWrappedWidth();
- int wrappedHeight = getRepeatHeightWrapped();
+ int wrappedHeight = wrappedRepeatHeightPx;
ViewportRanges ranges = av.getRanges();
int canvasHeight = getHeight();
}
/**
- * Answers the height in pixels of a repeating section of the wrapped
- * alignment, including space above, scale above if shown, sequences, and
- * annotation panel if shown
+ * Answers the width in pixels of the left scale labels (0 if not shown)
*
* @return
*/
- protected int getRepeatHeightWrapped()
+ int getLabelWidthWest()
{
- // gap (and maybe scale) above
- int repeatHeight = charHeight * (av.getScaleAboveWrapped() ? 2 : 1);
-
- // add sequences
- repeatHeight += av.getRanges().getViewportHeight() * charHeight;
-
- // add annotations panel height if shown
- repeatHeight += getAnnotationHeight();
-
- return repeatHeight;
+ return labelWidthWest;
}
}
+ hgap + seqCanvas.getAnnotationHeight();
int y = evt.getY();
- y -= hgap;
- x = Math.max(0, x - seqCanvas.labelWidthWest);
+ y = Math.max(0, y - hgap);
+ x = Math.max(0, x - seqCanvas.getLabelWidthWest());
int cwidth = seqCanvas.getWrappedCanvasWidth(this.getWidth());
if (cwidth < 1)
av.setSelectionGroup(sg);
}
- ap.paintAlignment(false);
+ ap.paintAlignment(false, false);
av.sendSelection();
}
/**
* set when the current UI interaction has resulted in a change that requires
- * overview shading to be recalculated. this could be changed to something
- * more expressive that indicates what actually has changed, so selective
- * redraws can be applied
+ * shading in overviews and structures to be recalculated. this could be
+ * changed to a something more expressive that indicates what actually has
+ * changed, so selective redraws can be applied (ie. only structures, only
+ * overview, etc)
*/
- private boolean needOverviewUpdate = false; // TODO: refactor to avcontroller
+ private boolean updateOverviewAndStructs = false; // TODO: refactor to avcontroller
/**
* set if av.getSelectionGroup() refers to a group that is defined on the
}
if (newWidth > 0)
{
- ap.paintAlignment(false);
+ ap.paintAlignment(false, false);
if (copyChanges)
{
/*
final int res = findColumn(evt);
final int seq = findSeq(evt);
oldSeq = seq;
- needOverviewUpdate = false;
+ updateOverviewAndStructs = false;
startWrapBlock = wrappedBlock;
// always do this - annotation has own state
// but defer colourscheme update until hidden sequences are passed in
boolean vischange = stretchGroup.recalcConservation(true);
- needOverviewUpdate |= vischange && av.isSelectionDefinedGroup()
+ updateOverviewAndStructs |= vischange && av.isSelectionDefinedGroup()
&& afterDrag;
if (stretchGroup.cs != null)
{
}
}
PaintRefresher.Refresh(this, av.getSequenceSetId());
- ap.paintAlignment(needOverviewUpdate);
- needOverviewUpdate = false;
+ // TODO: structure colours only need updating if stretchGroup used to or now
+ // does contain sequences with structure views
+ ap.paintAlignment(updateOverviewAndStructs, updateOverviewAndStructs);
+ updateOverviewAndStructs = false;
changeEndRes = false;
changeStartRes = false;
stretchGroup = null;
if (res > (stretchGroup.getStartRes() - 1))
{
stretchGroup.setEndRes(res);
- needOverviewUpdate |= av.isSelectionDefinedGroup();
+ updateOverviewAndStructs |= av.isSelectionDefinedGroup();
}
}
else if (changeStartRes)
if (res < (stretchGroup.getEndRes() + 1))
{
stretchGroup.setStartRes(res);
- needOverviewUpdate |= av.isSelectionDefinedGroup();
+ updateOverviewAndStructs |= av.isSelectionDefinedGroup();
}
}
if (stretchGroup.getSequences(null).contains(nextSeq))
{
stretchGroup.deleteSequence(seq, false);
- needOverviewUpdate |= av.isSelectionDefinedGroup();
+ updateOverviewAndStructs |= av.isSelectionDefinedGroup();
}
else
{
}
stretchGroup.addSequence(nextSeq, false);
- needOverviewUpdate |= av.isSelectionDefinedGroup();
+ updateOverviewAndStructs |= av.isSelectionDefinedGroup();
}
}
@Override
public void mouseReleased(MouseEvent evt)
{
- ap.paintAlignment(true);
+ ap.paintAlignment(true, true);
}
});
/**
* list of sequenceSet ids associated with the view
*/
- protected List<String> _aps = new ArrayList<String>();
+ protected List<String> _aps = new ArrayList<>();
/**
* list of alignment panels to use for superposition
*/
- protected Vector<AlignmentPanel> _alignwith = new Vector<AlignmentPanel>();
+ protected Vector<AlignmentPanel> _alignwith = new Vector<>();
/**
* list of alignment panels that are used for colouring structures by aligned
* sequences
*/
- protected Vector<AlignmentPanel> _colourwith = new Vector<AlignmentPanel>();
+ protected Vector<AlignmentPanel> _colourwith = new Vector<>();
private String viewId = null;
{
if (_alignwith == null)
{
- _alignwith = new Vector<AlignmentPanel>();
+ _alignwith = new Vector<>();
}
if (_alignwith.size() == 0 && ap != null)
{
if (apanel.getSeqPanel().seqCanvas.fr != null)
{
apanel.getSeqPanel().seqCanvas.fr.featuresAdded();
- apanel.paintAlignment(true);
+ // note - we don't do a refresh for structure here because we do it
+ // explicitly for all panels later on
+ apanel.paintAlignment(true, false);
}
/*
if (_colourwith == null)
{
- _colourwith = new Vector<AlignmentPanel>();
+ _colourwith = new Vector<>();
}
if (_alignwith == null)
{
- _alignwith = new Vector<AlignmentPanel>();
+ _alignwith = new Vector<>();
}
ViewSelectionMenu seqColourBy = new ViewSelectionMenu(
binding.setColourBySequence(seqColour.isSelected());
if (_colourwith == null)
{
- _colourwith = new Vector<AlignmentPanel>();
+ _colourwith = new Vector<>();
}
if (binding.isColourBySequence())
{
*/
protected void saveInitialSettings()
{
- groupColour1 = new HashMap<SequenceGroup, Color>();
- groupColour2 = new HashMap<SequenceGroup, Color>();
- groupThreshold = new HashMap<SequenceGroup, Integer>();
+ groupColour1 = new HashMap<>();
+ groupColour2 = new HashMap<>();
+ groupThreshold = new HashMap<>();
if (sg == null)
{
sg.textColour = col;
}
- ap.paintAlignment(true);
+ ap.paintAlignment(false, false);
}
void colour2Changed(Color col)
sg.textColour2 = col;
}
- ap.paintAlignment(true);
+ ap.paintAlignment(false, false);
}
void thresholdChanged(int value)
sg.thresholdTextColour = value;
}
- ap.paintAlignment(true);
+ ap.paintAlignment(false, false);
}
void setGroupTextColour()
if (treeCanvas.applyToAllViews)
{
- final ArrayList<CommandI> commands = new ArrayList<CommandI>();
+ final ArrayList<CommandI> commands = new ArrayList<>();
for (AlignmentPanel ap : PaintRefresher
.getAssociatedPanels(av.getSequenceSetId()))
{
public CommandI sortAlignmentIn(AlignmentPanel ap)
{
+ // TODO: move to alignment view controller
AlignmentViewport viewport = ap.av;
SequenceI[] oldOrder = viewport.getAlignment().getSequencesArray();
AlignmentSorter.sortByTree(viewport.getAlignment(), tree);
CommandI undo;
undo = new OrderCommand("Tree Sort", oldOrder, viewport.getAlignment());
- ap.paintAlignment(true);
+ ap.paintAlignment(true, false);
return undo;
}
UserDefinedColours()
{
super();
- selectedButtons = new ArrayList<JButton>();
+ selectedButtons = new ArrayList<>();
}
void showFrame()
if (upperCaseButtons == null)
{
- upperCaseButtons = new ArrayList<JButton>();
+ upperCaseButtons = new ArrayList<>();
}
for (int i = 0; i < 20; i++)
if (lowerCaseButtons == null)
{
- lowerCaseButtons = new ArrayList<JButton>();
+ lowerCaseButtons = new ArrayList<>();
}
for (int i = 0; i < 20; i++)
@Override
protected void loadbutton_actionPerformed()
{
- upperCaseButtons = new ArrayList<JButton>();
- lowerCaseButtons = new ArrayList<JButton>();
+ upperCaseButtons = new ArrayList<>();
+ lowerCaseButtons = new ArrayList<>();
JalviewFileChooser chooser = new JalviewFileChooser("jc",
"Jalview User Colours");
protected void cancelButton_actionPerformed()
{
ap.alignFrame.changeColour(oldColourScheme);
- ap.paintAlignment(true);
+ ap.paintAlignment(true, true);
try
{
}
}
}
- ap.paintAlignment(true);
+ ap.paintAlignment(true, false);
}
*/
public class ScaleRenderer
{
+ /**
+ * Represents one major or minor scale mark
+ */
public final class ScaleMark
{
+ /**
+ * true for a major scale mark, false for minor
+ */
public final boolean major;
+ /**
+ * visible column position (0..) e.g. 19
+ */
public final int column;
+ /**
+ * text (if any) to show e.g. "20"
+ */
public final String text;
ScaleMark(boolean isMajor, int col, String txt)
column = col;
text = txt;
}
+
+ /**
+ * String representation for inspection when debugging only
+ */
+ @Override
+ public String toString()
+ {
+ return String.format("%s:%d:%s", major ? "major" : "minor", column,
+ text);
+ }
}
/**
- * calculate positions markers on the alignment ruler
+ * Calculates position markers on the alignment ruler
*
* @param av
* @param startx
- * left-most column in visible view
+ * left-most column in visible view (0..)
* @param endx
- * - right-most column in visible view
- * @return List of ScaleMark holding boolean: true/false for major/minor mark,
- * marker position in alignment column coords, a String to be rendered
- * at the position (or null)
+ * - right-most column in visible view (0..)
+ * @return
*/
public List<ScaleMark> calculateMarks(AlignViewportI av, int startx,
int endx)
scalestartx += 5;
}
List<ScaleMark> marks = new ArrayList<ScaleMark>();
- String string;
- int refN, iadj;
// todo: add a 'reference origin column' to set column number relative to
- for (int i = scalestartx; i < endx; i += 5)
+ for (int i = scalestartx; i <= endx; i += 5)
{
if (((i - refSp) % 10) == 0)
{
+ String text;
if (refSeq == null)
{
- iadj = av.getAlignment().getHiddenColumns()
+ int iadj = av.getAlignment().getHiddenColumns()
.adjustForHiddenColumns(i - 1) + 1;
- string = String.valueOf(iadj);
+ text = String.valueOf(iadj);
}
else
{
- iadj = av.getAlignment().getHiddenColumns()
+ int iadj = av.getAlignment().getHiddenColumns()
.adjustForHiddenColumns(i - 1);
- refN = refSeq.findPosition(iadj);
+ int refN = refSeq.findPosition(iadj);
// TODO show bounds if position is a gap
// - ie L--R -> "1L|2R" for
// marker
if (iadj < refStartI)
{
- string = String.valueOf(iadj - refStartI);
+ text = String.valueOf(iadj - refStartI);
}
else if (iadj > refEndI)
{
- string = "+" + String.valueOf(iadj - refEndI);
+ text = "+" + String.valueOf(iadj - refEndI);
}
else
{
- string = String.valueOf(refN) + refSeq.getCharAt(iadj);
+ text = String.valueOf(refN) + refSeq.getCharAt(iadj);
}
}
- marks.add(new ScaleMark(true, i - startx - 1, string));
+ marks.add(new ScaleMark(true, i - startx - 1, text));
}
else
{
return null;
}
- if (Comparison.isGap(seq.getCharAt(column)))
+ // column is 'base 1' but getCharAt is an array index (ie from 0)
+ if (Comparison.isGap(seq.getCharAt(column - 1)))
{
/*
* returning null allows the colour scheme to provide gap colour
oldcs = av.getGlobalColourScheme();
if (av.getAlignment().getGroups() != null)
{
- oldgroupColours = new Hashtable<SequenceGroup, ColourSchemeI>();
+ oldgroupColours = new Hashtable<>();
for (SequenceGroup sg : ap.getAlignment().getGroups())
{
if (sg.getColourScheme() != null)
this.ap = ap;
adjusting = true;
- Vector<String> list = new Vector<String>();
+ Vector<String> list = new Vector<>();
int index = 1;
AlignmentAnnotation[] anns = av.getAlignment().getAlignmentAnnotation();
if (anns != null)
av.setGlobalColourScheme(rhc);
- ap.paintAlignment(true);
+ ap.paintAlignment(true, true);
}
}
import jalview.datamodel.AlignmentI;
import jalview.datamodel.AlignmentView;
import jalview.datamodel.Annotation;
-import jalview.datamodel.CigarArray;
import jalview.datamodel.ColumnSelection;
import jalview.datamodel.HiddenColumns;
import jalview.datamodel.HiddenSequences;
}
@Override
- public CigarArray getViewAsCigars(boolean selectedRegionOnly)
- {
- return new CigarArray(alignment, alignment.getHiddenColumns(),
- (selectedRegionOnly ? selectionGroup : null));
- }
-
- @Override
public jalview.datamodel.AlignmentView getAlignmentView(
boolean selectedOnly)
{
AnnotationProviderI counter)
{
super(viewport, panel);
- ourAnnots = new ArrayList<AlignmentAnnotation>();
+ ourAnnots = new ArrayList<>();
this.counter = counter;
calcMan.registerWorker(this);
}
if (ap != null)
{
ap.adjustAnnotationHeight();
- ap.paintAlignment(true);
+ // TODO: only need to update colour and geometry if panel height changes
+ // and view is coloured by annotation, and the annotation is actually
+ // changed!
+ ap.paintAlignment(true, true);
}
}
AlignmentViewPanel panel, FeatureSetCounterI counter)
{
super(viewport, panel);
- ourAnnots = new ArrayList<AlignmentAnnotation>();
+ ourAnnots = new ArrayList<>();
this.counter = counter;
calcMan.registerWorker(this);
}
{
ap.adjustAnnotationHeight();
}
- ap.paintAlignment(true);
+ ap.paintAlignment(true, true);
}
}
{
if (ap != null)
{
- ap.paintAlignment(false);
+ ap.paintAlignment(false, false);
}
Thread.sleep(200);
} catch (Exception ex)
if (ap != null)
{
- ap.paintAlignment(true);
+ ap.paintAlignment(true, true);
}
} catch (OutOfMemoryError error)
{
abortAndDestroy();
return;
}
- List<AlignmentAnnotation> ourAnnot = new ArrayList<AlignmentAnnotation>();
+ List<AlignmentAnnotation> ourAnnot = new ArrayList<>();
AlignmentI alignment = alignViewport.getAlignment();
conservation = alignViewport.getAlignmentConservationAnnotation();
quality = alignViewport.getAlignmentQualityAnnot();
}
if (ap != null)
{
- ap.paintAlignment(true);
+ ap.paintAlignment(true, true);
}
}
calcMan.workerComplete(this);
if (ap != null)
{
- ap.paintAlignment(true);
+ ap.paintAlignment(true, true);
}
}
boolean useJDasMultiThread)
{
this.useJDASMultiThread = useJDasMultiThread;
- this.selectedSources = new ArrayList<jalviewSourceI>();
+ this.selectedSources = new ArrayList<>();
// filter both sequences and sources to eliminate duplicates
for (jalviewSourceI src : selectedSources2)
{
FeaturesClientMultipleSources fc = new FeaturesClientMultipleSources();
fc.setConnProps(sourceRegistry.getSessionHandler());
// Now sending requests one at a time to each server
- ArrayList<jalviewSourceI> srcobj = new ArrayList<jalviewSourceI>();
- ArrayList<String> src = new ArrayList<String>();
- List<List<String>> ids = new ArrayList<List<String>>();
- List<List<DBRefEntry>> idobj = new ArrayList<List<DBRefEntry>>();
- List<Map<String, SequenceI>> sqset = new ArrayList<Map<String, SequenceI>>();
+ ArrayList<jalviewSourceI> srcobj = new ArrayList<>();
+ ArrayList<String> src = new ArrayList<>();
+ List<List<String>> ids = new ArrayList<>();
+ List<List<DBRefEntry>> idobj = new ArrayList<>();
+ List<Map<String, SequenceI>> sqset = new ArrayList<>();
for (jalviewSourceI _sr : selectedSources)
{
- Map<String, SequenceI> slist = new HashMap<String, SequenceI>();
- List<DBRefEntry> idob = new ArrayList<DBRefEntry>();
- List<String> qset = new ArrayList<String>();
+ Map<String, SequenceI> slist = new HashMap<>();
+ List<DBRefEntry> idob = new ArrayList<>();
+ List<String> qset = new ArrayList<>();
for (SequenceI seq : sequences)
{
sqset.add(slist);
}
}
- Map<String, Map<List<String>, Exception>> errors = new HashMap<String, Map<List<String>, Exception>>();
- Map<String, Map<List<String>, DasGFFAdapter>> results = new HashMap<String, Map<List<String>, DasGFFAdapter>>();
+ Map<String, Map<List<String>, Exception>> errors = new HashMap<>();
+ Map<String, Map<List<String>, DasGFFAdapter>> results = new HashMap<>();
if (!useJDASMultiThread)
{
Iterator<String> sources = src.iterator();
if (ers == null)
{
results.put(source,
- ers = new HashMap<List<String>, DasGFFAdapter>());
+ ers = new HashMap<>());
}
ers.put(qid, dga);
} catch (Exception ex)
if (ers == null)
{
errors.put(source,
- ers = new HashMap<List<String>, Exception>());
+ ers = new HashMap<>());
}
ers.put(qid, ex);
}
Map<List<String>, DasGFFAdapter> results,
Map<List<String>, Exception> errors)
{
- Set<SequenceI> sequences = new HashSet<SequenceI>();
+ Set<SequenceI> sequences = new HashSet<>();
String source = jvsource.getSourceURL();
// process features
DasGFFAdapter result = (results == null) ? null : results.get(ids);
if (seq == af.getViewport().getAlignment().getSequenceAt(index)
.getDatasetSequence())
{
- af.alignPanel.paintAlignment(true);
+ af.alignPanel.paintAlignment(true, true);
index = end;
break;
}
// TODO: minimal list of DAS queries to make by querying with untyped ID if
// distinct from any typed IDs
- List<DBRefEntry> ids = new ArrayList<DBRefEntry>();
- List<String> qstring = new ArrayList<String>();
+ List<DBRefEntry> ids = new ArrayList<>();
+ List<String> qstring = new ArrayList<>();
boolean dasCoordSysFound = false;
if (uprefs != null)
{
// TODO: turn this into some kind of configuration file that's a bit easier
// to edit
- featureMap = new HashMap<String, Map<String, String[]>>();
+ featureMap = new HashMap<>();
Map<String, String[]> fmap;
featureMap.put(compbio.ws.client.Services.IUPredWS.toString(),
- fmap = new HashMap<String, String[]>());
+ fmap = new HashMap<>());
fmap.put("Glob",
new String[]
{ "Globular Domain", "Predicted globular domain" });
featureMap.put(compbio.ws.client.Services.JronnWS.toString(),
- fmap = new HashMap<String, String[]>());
+ fmap = new HashMap<>());
featureMap.put(compbio.ws.client.Services.DisemblWS.toString(),
- fmap = new HashMap<String, String[]>());
+ fmap = new HashMap<>());
fmap.put("REM465", new String[] { "REM465", "Missing density" });
fmap.put("HOTLOOPS", new String[] { "HOTLOOPS", "Flexible loops" });
fmap.put("COILS", new String[] { "COILS", "Random coil" });
featureMap.put(compbio.ws.client.Services.GlobPlotWS.toString(),
- fmap = new HashMap<String, String[]>());
+ fmap = new HashMap<>());
fmap.put("GlobDoms",
new String[]
{ "Globular Domain", "Predicted globular domain" });
new String[]
{ "Protein Disorder", "Probable unstructured peptide region" });
Map<String, Map<String, Object>> amap;
- annotMap = new HashMap<String, Map<String, Map<String, Object>>>();
+ annotMap = new HashMap<>();
annotMap.put(compbio.ws.client.Services.GlobPlotWS.toString(),
- amap = new HashMap<String, Map<String, Object>>());
+ amap = new HashMap<>());
amap.put("Dydx", new HashMap<String, Object>());
amap.get("Dydx").put(DONTCOMBINE, DONTCOMBINE);
amap.get("Dydx").put(THRESHOLD, new double[] { 1, 0 });
amap.put("RawScore", new HashMap<String, Object>());
amap.get("RawScore").put(INVISIBLE, INVISIBLE);
annotMap.put(compbio.ws.client.Services.DisemblWS.toString(),
- amap = new HashMap<String, Map<String, Object>>());
+ amap = new HashMap<>());
amap.put("COILS", new HashMap<String, Object>());
amap.put("HOTLOOPS", new HashMap<String, Object>());
amap.put("REM465", new HashMap<String, Object>());
amap.get("REM465").put(RANGE, new float[] { 0, 1 });
annotMap.put(compbio.ws.client.Services.IUPredWS.toString(),
- amap = new HashMap<String, Map<String, Object>>());
+ amap = new HashMap<>());
amap.put("Long", new HashMap<String, Object>());
amap.put("Short", new HashMap<String, Object>());
amap.get("Long").put(THRESHOLD, new double[] { 1, 0.5 });
amap.get("Short").put(THRESHOLD, new double[] { 1, 0.5 });
amap.get("Short").put(RANGE, new float[] { 0, 1 });
annotMap.put(compbio.ws.client.Services.JronnWS.toString(),
- amap = new HashMap<String, Map<String, Object>>());
+ amap = new HashMap<>());
amap.put("JRonn", new HashMap<String, Object>());
amap.get("JRonn").put(THRESHOLD, new double[] { 1, 0.5 });
amap.get("JRonn").put(RANGE, new float[] { 0, 1 });
Map<String, Map<String, Object>> annotTypeMap = annotMap
.get(service.serviceType);
boolean dispFeatures = false;
- Map<String, Object> fc = new Hashtable<String, Object>();
- List<AlignmentAnnotation> ourAnnot = new ArrayList<AlignmentAnnotation>();
+ Map<String, Object> fc = new Hashtable<>();
+ List<AlignmentAnnotation> ourAnnot = new ArrayList<>();
/**
* grouping for any annotation rows created
*/
// only do this if the alignFrame is currently showing this view.
af.setShowSeqFeatures(true);
}
- ap.paintAlignment(true);
}
if (ourAnnot.size() > 0)
{
// new alignment annotation rows created.
updateOurAnnots(ourAnnot);
ap.adjustAnnotationHeight();
+ ap.paintAlignment(true, true);
}
}
}
{
guiProgress.setProgressBar("", progressId);
}
- ap.paintAlignment(true);
+ // TODO: may not need to paintAlignment again !
+ ap.paintAlignment(false, false);
}
if (msg.length() > 0)
{
protected boolean checkDone()
{
calcMan.notifyStart(this);
- ap.paintAlignment(false);
+ ap.paintAlignment(false, false);
while (!calcMan.notifyWorking(this))
{
if (calcMan.isWorking(this))
{
if (ap != null)
{
- ap.paintAlignment(false);
+ ap.paintAlignment(false, false);
}
Thread.sleep(200);
--- /dev/null
+/*
+ * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
+ * Copyright (C) $$Year-Rel$$ The Jalview Authors
+ *
+ * This file is part of Jalview.
+ *
+ * Jalview is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, either version 3
+ * of the License, or (at your option) any later version.
+ *
+ * Jalview is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Jalview. If not, see <http://www.gnu.org/licenses/>.
+ * The Jalview Authors are detailed in the 'AUTHORS' file.
+ */
+package jalview.datamodel;
+
+import static org.testng.Assert.assertEquals;
+
+import jalview.gui.JvOptionPane;
+
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+public class CigarArrayTest
+{
+ @BeforeClass(alwaysRun = true)
+ public void setUpJvOptionPane()
+ {
+ JvOptionPane.setInteractiveMode(false);
+ JvOptionPane.setMockResponse(JvOptionPane.CANCEL_OPTION);
+ }
+
+ @Test(groups = "Functional")
+ public void testConstructor()
+ {
+ SequenceI seq1 = new Sequence("sq1",
+ "ASFDDABACBACBACBACBACBACBABCABCBACBABCAB");
+ Sequence seq2 = new Sequence("sq2",
+ "TTTTTTACBCBABCABCABCABCBACBACBABCABCABCBA");
+
+ // construct alignment
+ AlignmentI al = new Alignment(new SequenceI[] { seq1, seq2 });
+
+ // hide columns
+ HiddenColumns hc = new HiddenColumns();
+ hc.hideColumns(3, 6);
+ hc.hideColumns(16, 20);
+
+ // select group
+ SequenceGroup sg1 = new SequenceGroup();
+ sg1.addSequence(seq1, false);
+ sg1.setStartRes(2);
+ sg1.setEndRes(23);
+
+ // Cigar array meanings:
+ // M = match
+ // D = deletion
+ // I = insertion
+ // number preceding M/D/I is the number of residues which
+ // match/are deleted/are inserted
+ // In the CigarArray constructor only matches or deletions are created, as
+ // we are comparing a sequence to its own subsequence (the group) + hidden
+ // columns.
+
+ // no hidden columns case
+ CigarArray cig = new CigarArray(al, null, sg1);
+ String result = cig.getCigarstring();
+ assertEquals(result, "22M");
+
+ cig = new CigarArray(al, hc, sg1);
+ result = cig.getCigarstring();
+ assertEquals(result, "1M4D9M5D3M");
+
+ // group starts at hidden cols
+ sg1.setStartRes(3);
+ cig = new CigarArray(al, hc, sg1);
+ result = cig.getCigarstring();
+ assertEquals(result, "4D9M5D3M");
+
+ // group starts at last but 1 hidden col
+ sg1.setStartRes(5);
+ cig = new CigarArray(al, hc, sg1);
+ result = cig.getCigarstring();
+ assertEquals(result, "2D9M5D3M");
+
+ // group starts at last hidden col
+ sg1.setStartRes(6);
+ cig = new CigarArray(al, hc, sg1);
+ result = cig.getCigarstring();
+ assertEquals(result, "1D9M5D3M");
+
+ // group starts just after hidden region
+ sg1.setStartRes(7);
+ cig = new CigarArray(al, hc, sg1);
+ result = cig.getCigarstring();
+ assertEquals(result, "9M5D3M");
+
+ // group ends just before start of hidden region
+ sg1.setStartRes(5);
+ sg1.setEndRes(15);
+ cig = new CigarArray(al, hc, sg1);
+ result = cig.getCigarstring();
+ assertEquals(result, "2D9M");
+
+ // group ends at start of hidden region
+ sg1.setEndRes(16);
+ cig = new CigarArray(al, hc, sg1);
+ result = cig.getCigarstring();
+ assertEquals(result, "2D9M1D");
+
+ // group ends 1 after start of hidden region
+ sg1.setEndRes(17);
+ cig = new CigarArray(al, hc, sg1);
+ result = cig.getCigarstring();
+ assertEquals(result, "2D9M2D");
+
+ // group ends at end of hidden region
+ sg1.setEndRes(20);
+ cig = new CigarArray(al, hc, sg1);
+ result = cig.getCigarstring();
+ assertEquals(result, "2D9M5D");
+
+ // group ends just after end of hidden region
+ sg1.setEndRes(21);
+ cig = new CigarArray(al, hc, sg1);
+ result = cig.getCigarstring();
+ assertEquals(result, "2D9M5D1M");
+
+ // group ends 2 after end of hidden region
+ sg1.setEndRes(22);
+ cig = new CigarArray(al, hc, sg1);
+ result = cig.getCigarstring();
+ assertEquals(result, "2D9M5D2M");
+ }
+}
assertEquals(new Range(8, 13), sq.findPositions(1, 13)); // the lot
assertEquals(new Range(8, 13), sq.findPositions(1, 99));
}
+
+ @Test(groups = { "Functional" })
+ public void testFindFeatures_largeEndPos()
+ {
+ /*
+ * imitate a PDB sequence where end is larger than end position
+ */
+ SequenceI sq = new Sequence("test", "-ABC--DEF--", 1, 20);
+ sq.createDatasetSequence();
+
+ assertTrue(sq.findFeatures(1, 9).isEmpty());
+ // should be no array bounds exception - JAL-2772
+ assertTrue(sq.findFeatures(1, 15).isEmpty());
+
+ // add feature on BCD
+ SequenceFeature sfBCD = new SequenceFeature("Cath", "desc", 2, 4, 2f,
+ null);
+ sq.addSequenceFeature(sfBCD);
+
+ // no features in columns 1-2 (-A)
+ List<SequenceFeature> found = sq.findFeatures(1, 2);
+ assertTrue(found.isEmpty());
+
+ // columns 1-6 (-ABC--) includes BCD
+ found = sq.findFeatures(1, 6);
+ assertEquals(1, found.size());
+ assertTrue(found.contains(sfBCD));
+
+ // columns 10-11 (--) should find nothing
+ found = sq.findFeatures(10, 11);
+ assertEquals(0, found.size());
+ }
+
+ @Test(groups = { "Functional" })
+ public void testSetName()
+ {
+ SequenceI sq = new Sequence("test", "-ABC---DE-F--");
+ assertEquals("test", sq.getName());
+ assertEquals(1, sq.getStart());
+ assertEquals(6, sq.getEnd());
+
+ sq.setName("testing");
+ assertEquals("testing", sq.getName());
+
+ sq.setName("test/8-10");
+ assertEquals("test", sq.getName());
+ assertEquals(8, sq.getStart());
+ assertEquals(13, sq.getEnd()); // note end is recomputed
+
+ sq.setName("testing/7-99");
+ assertEquals("testing", sq.getName());
+ assertEquals(7, sq.getStart());
+ assertEquals(99, sq.getEnd()); // end may be beyond physical end
+
+ sq.setName("/2-3");
+ assertEquals("", sq.getName());
+ assertEquals(2, sq.getStart());
+ assertEquals(7, sq.getEnd());
+
+ sq.setName("test/"); // invalid
+ assertEquals("test/", sq.getName());
+ assertEquals(2, sq.getStart());
+ assertEquals(7, sq.getEnd());
+
+ sq.setName("test/6-13/7-99");
+ assertEquals("test/6-13", sq.getName());
+ assertEquals(7, sq.getStart());
+ assertEquals(99, sq.getEnd());
+
+ sq.setName("test/0-5"); // 0 is invalid - ignored
+ assertEquals("test/0-5", sq.getName());
+ assertEquals(7, sq.getStart());
+ assertEquals(99, sq.getEnd());
+
+ sq.setName("test/a-5"); // a is invalid - ignored
+ assertEquals("test/a-5", sq.getName());
+ assertEquals(7, sq.getStart());
+ assertEquals(99, sq.getEnd());
+
+ sq.setName("test/6-5"); // start > end is invalid - ignored
+ assertEquals("test/6-5", sq.getName());
+ assertEquals(7, sq.getStart());
+ assertEquals(99, sq.getEnd());
+
+ sq.setName("test/5"); // invalid - ignored
+ assertEquals("test/5", sq.getName());
+ assertEquals(7, sq.getStart());
+ assertEquals(99, sq.getEnd());
+
+ sq.setName("test/-5"); // invalid - ignored
+ assertEquals("test/-5", sq.getName());
+ assertEquals(7, sq.getStart());
+ assertEquals(99, sq.getEnd());
+
+ sq.setName("test/5-"); // invalid - ignored
+ assertEquals("test/5-", sq.getName());
+ assertEquals(7, sq.getStart());
+ assertEquals(99, sq.getEnd());
+
+ sq.setName("test/5-6-7"); // invalid - ignored
+ assertEquals("test/5-6-7", sq.getName());
+ assertEquals(7, sq.getStart());
+ assertEquals(99, sq.getEnd());
+
+ sq.setName(null); // invalid, gets converted to space
+ assertEquals("", sq.getName());
+ assertEquals(7, sq.getStart());
+ assertEquals(99, sq.getEnd());
+ }
+
+ @Test(groups = { "Functional" })
+ public void testCheckValidRange()
+ {
+ Sequence sq = new Sequence("test/7-12", "-ABC---DE-F--");
+ assertEquals(7, sq.getStart());
+ assertEquals(12, sq.getEnd());
+
+ /*
+ * checkValidRange ensures end is at least the last residue position
+ */
+ PA.setValue(sq, "end", 2);
+ sq.checkValidRange();
+ assertEquals(12, sq.getEnd());
+
+ /*
+ * end may be beyond the last residue position
+ */
+ PA.setValue(sq, "end", 22);
+ sq.checkValidRange();
+ assertEquals(22, sq.getEnd());
+ }
}
assertEquals(-1, fc.compare("coding_exon", "feature_variant"));
assertEquals(1f, fc.getTransparency());
}
+
+ @Test(groups = "Network")
+ public void testGetGeneIds()
+ {
+ /*
+ * ENSG00000158828 gene id PINK1 human
+ * ENST00000321556 transcript for the same gene - should not be duplicated
+ * P30419 Uniprot identifier for ENSG00000136448
+ * ENST00000592782 transcript for Uniprot gene - should not be duplicated
+ * BRAF - gene name resolvabe (at time of writing) for 6 model species
+ */
+ String ids = "ENSG00000158828 ENST00000321556 P30419 ENST00000592782 BRAF";
+ EnsemblGene testee = new EnsemblGene();
+ List<String> geneIds = testee.getGeneIds(ids);
+ assertEquals(8, geneIds.size());
+ assertTrue(geneIds.contains("ENSG00000158828"));
+ assertTrue(geneIds.contains("ENSG00000136448"));
+ assertTrue(geneIds.contains("ENSG00000157764")); // BRAF human
+ assertTrue(geneIds.contains("ENSMUSG00000002413")); // mouse
+ assertTrue(geneIds.contains("ENSRNOG00000010957")); // rat
+ assertTrue(geneIds.contains("ENSXETG00000004845")); // xenopus
+ assertTrue(geneIds.contains("ENSDARG00000017661")); // zebrafish
+ assertTrue(geneIds.contains("ENSGALG00000012865")); // chicken
+ }
}
*/
package jalview.ext.ensembl;
+import static org.testng.Assert.assertTrue;
+
import jalview.datamodel.AlignmentI;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.List;
+import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
public class EnsemblRestClientTest
{
+ private EnsemblRestClient sf;
@Test(suiteName = "live")
public void testIsEnsemblAvailable()
{
- EnsemblRestClient sf = new EnsemblRestClient()
+ boolean isAvailable = sf.isEnsemblAvailable();
+ if (isAvailable)
+ {
+ System.out.println("Ensembl is UP!");
+ }
+ else
+ {
+ System.err
+ .println("Ensembl is DOWN or unreachable ******************* BAD!");
+ }
+ }
+
+ @BeforeMethod(alwaysRun = true)
+ protected void setUp()
+ {
+ sf = new EnsemblRestClient()
{
@Override
}
};
- boolean isAvailable = sf.isEnsemblAvailable();
- if (isAvailable)
- {
- System.out.println("Ensembl is UP!");
- }
- else
+ }
+
+ @Test(groups = "Network")
+ public void testCheckEnsembl_overload()
+ {
+ for (int i = 0; i < 20; i++)
{
- System.err
- .println("Ensembl is DOWN or unreachable ******************* BAD!");
+ assertTrue(sf.checkEnsembl(), "Error on " + (i + 1) + "th ping");
}
}
-
}
}
- @Test(groups = "Functional")
- public void testIsTranscriptIdentifier()
- {
- EnsemblSeqProxy testee = new EnsemblGene();
- assertFalse(testee.isTranscriptIdentifier(null));
- assertFalse(testee.isTranscriptIdentifier(""));
- assertFalse(testee.isTranscriptIdentifier("ENSG00000012345"));
- assertTrue(testee.isTranscriptIdentifier("ENST00000012345"));
- assertTrue(testee.isTranscriptIdentifier("ENSMUST00000012345"));
- assertFalse(testee.isTranscriptIdentifier("enst00000012345"));
- assertFalse(testee.isTranscriptIdentifier("ENST000000123456"));
- assertFalse(testee.isTranscriptIdentifier("ENST0000001234"));
- }
-
- @Test(groups = "Functional")
- public void testIsGeneIdentifier()
- {
- EnsemblSeqProxy testee = new EnsemblGene();
- assertFalse(testee.isGeneIdentifier(null));
- assertFalse(testee.isGeneIdentifier(""));
- assertFalse(testee.isGeneIdentifier("ENST00000012345"));
- assertTrue(testee.isGeneIdentifier("ENSG00000012345"));
- assertTrue(testee.isGeneIdentifier("ENSMUSG00000012345"));
- assertFalse(testee.isGeneIdentifier("ensg00000012345"));
- assertFalse(testee.isGeneIdentifier("ENSG000000123456"));
- assertFalse(testee.isGeneIdentifier("ENSG0000001234"));
- }
-
/**
* Test the method that appends a single allele's reverse complement to a
* string buffer
--- /dev/null
+package jalview.ext.ensembl;
+
+import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.assertTrue;
+
+import java.util.Set;
+
+import org.testng.annotations.Test;
+
+public class SpeciesTest
+{
+ @Test
+ public void testGetModelOrganisms()
+ {
+ Set<Species> models = Species.getModelOrganisms();
+ assertTrue(models.contains(Species.human));
+ assertFalse(models.contains(Species.horse));
+ for (Species s : Species.values())
+ {
+ if (s.isModelOrganism())
+ {
+ assertTrue(models.contains(s));
+ }
+ else
+ {
+ assertFalse(models.contains(s));
+ }
+ }
+ }
+}
assertEquals(model.getAtomSpec(), "#0:1-4.B,5-9.C|#1:2-5.A,8.A,5-10.B");
model.addRange(0, 3, 10, "C"); // subsumes 5-9
assertEquals(model.getAtomSpec(), "#0:1-4.B,3-10.C|#1:2-5.A,8.A,5-10.B");
+ model.addRange(5, 25, 35, " "); // empty chain code - e.g. from homology
+ // modelling
+ assertEquals(model.getAtomSpec(),
+ "#0:1-4.B,3-10.C|#1:2-5.A,8.A,5-10.B|#5:25-35.");
+
}
}
package jalview.gui;
import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNotEquals;
import jalview.bin.Cache;
import jalview.bin.Jalview;
.getAlignment().getWidth() - 1 - 21); // 21 is the number of hidden
// columns
}
+
+ /**
+ * Test that update layout reverts to original (unwrapped) values for endRes
+ * and endSeq when switching from wrapped to unwrapped mode (JAL-2739)
+ */
+ @Test(groups = "Functional")
+ public void TestUpdateLayout_endRes()
+ {
+ // get details of original alignment dimensions
+ ViewportRanges ranges = af.getViewport().getRanges();
+ int endres = ranges.getEndRes();
+
+ // wrap
+ af.alignPanel.getAlignViewport().setWrapAlignment(true);
+ af.alignPanel.updateLayout();
+
+ // endRes changes
+ assertNotEquals(ranges.getEndRes(), endres);
+
+ // unwrap
+ af.alignPanel.getAlignViewport().setWrapAlignment(false);
+ af.alignPanel.updateLayout();
+
+ // endRes and endSeq back to original values
+ assertEquals(ranges.getEndRes(), endres);
+
+ }
}
--- /dev/null
+package jalview.gui;
+
+import static org.testng.Assert.assertEquals;
+
+import jalview.datamodel.AlignmentI;
+import jalview.io.DataSourceType;
+import jalview.io.FileLoader;
+
+import java.awt.Font;
+import java.awt.FontMetrics;
+
+import junit.extensions.PA;
+
+import org.testng.annotations.Test;
+
+public class SeqCanvasTest
+{
+ /**
+ * Test the method that computes wrapped width in residues, height of wrapped
+ * widths in pixels, and the number of widths visible
+ */
+ @Test(groups = "Functional")
+ public void testCalculateWrappedGeometry_noAnnotations()
+ {
+ AlignFrame af = new FileLoader().LoadFileWaitTillLoaded(
+ "examples/uniref50.fa", DataSourceType.FILE);
+ AlignViewport av = af.getViewport();
+ AlignmentI al = av.getAlignment();
+ assertEquals(al.getWidth(), 157);
+ assertEquals(al.getHeight(), 15);
+
+ av.setWrapAlignment(true);
+ av.getRanges().setStartEndSeq(0, 14);
+ av.setFont(new Font("SansSerif", Font.PLAIN, 14), true);
+ int charHeight = av.getCharHeight();
+ int charWidth = av.getCharWidth();
+ assertEquals(charHeight, 17);
+ assertEquals(charWidth, 12);
+
+ SeqCanvas testee = af.alignPanel.getSeqPanel().seqCanvas;
+
+ /*
+ * first with scales above, left, right
+ */
+ av.setShowAnnotation(false);
+ av.setScaleAboveWrapped(true);
+ av.setScaleLeftWrapped(true);
+ av.setScaleRightWrapped(true);
+ FontMetrics fm = testee.getFontMetrics(av.getFont());
+ int labelWidth = fm.stringWidth("000") + charWidth;
+ assertEquals(labelWidth, 39); // 3 x 9 + charWidth
+
+ /*
+ * width 400 pixels leaves (400 - 2*labelWidth) for residue columns
+ * take the whole multiple of character widths
+ */
+ int canvasWidth = 400;
+ int canvasHeight = 300;
+ int residueColumns = (canvasWidth - 2 * labelWidth) / charWidth;
+ int wrappedWidth = testee.calculateWrappedGeometry(canvasWidth, canvasHeight);
+ assertEquals(wrappedWidth, residueColumns);
+ assertEquals(PA.getValue(testee, "labelWidthWest"), labelWidth);
+ assertEquals(PA.getValue(testee, "labelWidthEast"), labelWidth);
+ assertEquals(PA.getValue(testee, "wrappedSpaceAboveAlignment"),
+ 2 * charHeight);
+ int repeatingHeight = (int) PA.getValue(testee, "wrappedRepeatHeightPx");
+ assertEquals(repeatingHeight, charHeight * (2 + al.getHeight()));
+ assertEquals(PA.getValue(testee, "wrappedVisibleWidths"), 1);
+
+ /*
+ * repeat height is 17 * (2 + 15) = 289
+ * make canvas height 2 * 289 + 3 * charHeight so just enough to
+ * draw 2 widths and the first sequence of a third
+ */
+ canvasHeight = charHeight * (17 * 2 + 3);
+ testee.calculateWrappedGeometry(canvasWidth, canvasHeight);
+ assertEquals(PA.getValue(testee, "wrappedVisibleWidths"), 3);
+
+ /*
+ * reduce canvas height by 1 pixel - should not be enough height
+ * to draw 3 widths
+ */
+ canvasHeight -= 1;
+ testee.calculateWrappedGeometry(canvasWidth, canvasHeight);
+ assertEquals(PA.getValue(testee, "wrappedVisibleWidths"), 2);
+
+ /*
+ * turn off scale above - can now fit in 2 and a bit widths
+ */
+ av.setScaleAboveWrapped(false);
+ testee.calculateWrappedGeometry(canvasWidth, canvasHeight);
+ assertEquals(PA.getValue(testee, "wrappedVisibleWidths"), 3);
+
+ /*
+ * reduce height to enough for 2 widths and not quite a third
+ * i.e. two repeating heights + spacer + sequence - 1 pixel
+ */
+ canvasHeight = charHeight * (16 * 2 + 2) - 1;
+ testee.calculateWrappedGeometry(canvasWidth, canvasHeight);
+ assertEquals(PA.getValue(testee, "wrappedVisibleWidths"), 2);
+
+ /*
+ * make canvas width enough for scales and 20 residues
+ */
+ canvasWidth = 2 * labelWidth + 20 * charWidth;
+ wrappedWidth = testee.calculateWrappedGeometry(canvasWidth,
+ canvasHeight);
+ assertEquals(wrappedWidth, 20);
+
+ /*
+ * reduce width by 1 pixel - rounds down to 19 residues
+ */
+ canvasWidth -= 1;
+ wrappedWidth = testee.calculateWrappedGeometry(canvasWidth,
+ canvasHeight);
+ assertEquals(wrappedWidth, 19);
+
+ /*
+ * turn off West scale - adds labelWidth (39) to available for residues
+ * which with the 11 remainder makes 50 which is 4 more charWidths rem 2
+ */
+ av.setScaleLeftWrapped(false);
+ wrappedWidth = testee.calculateWrappedGeometry(canvasWidth,
+ canvasHeight);
+ assertEquals(wrappedWidth, 23);
+
+ /*
+ * add 10 pixels to width to fit in another whole residue column
+ */
+ canvasWidth += 9;
+ wrappedWidth = testee.calculateWrappedGeometry(canvasWidth,
+ canvasHeight);
+ assertEquals(wrappedWidth, 23);
+ canvasWidth += 1;
+ wrappedWidth = testee.calculateWrappedGeometry(canvasWidth,
+ canvasHeight);
+ assertEquals(wrappedWidth, 24);
+
+ /*
+ * turn off East scale to gain 39 more pixels (3 columns remainder 3)
+ */
+ av.setScaleRightWrapped(false);
+ wrappedWidth = testee.calculateWrappedGeometry(canvasWidth,
+ canvasHeight);
+ assertEquals(wrappedWidth, 27);
+
+ /*
+ * add 9 pixels to width to gain a residue column
+ */
+ canvasWidth += 8;
+ wrappedWidth = testee.calculateWrappedGeometry(canvasWidth,
+ canvasHeight);
+ assertEquals(wrappedWidth, 27);
+ canvasWidth += 1;
+ wrappedWidth = testee.calculateWrappedGeometry(canvasWidth,
+ canvasHeight);
+ assertEquals(wrappedWidth, 28);
+
+ /*
+ * now West but not East scale - lose 39 pixels or 4 columns
+ */
+ av.setScaleLeftWrapped(true);
+ wrappedWidth = testee.calculateWrappedGeometry(canvasWidth,
+ canvasHeight);
+ assertEquals(wrappedWidth, 24);
+
+ /*
+ * adding 3 pixels to width regains one column
+ */
+ canvasWidth += 2;
+ wrappedWidth = testee.calculateWrappedGeometry(canvasWidth,
+ canvasHeight);
+ assertEquals(wrappedWidth, 24);
+ canvasWidth += 1;
+ wrappedWidth = testee.calculateWrappedGeometry(canvasWidth,
+ canvasHeight);
+ assertEquals(wrappedWidth, 25);
+
+ /*
+ * turn off scales left and right, make width exactly 157 columns
+ */
+ av.setScaleLeftWrapped(false);
+ canvasWidth = al.getWidth() * charWidth;
+ testee.calculateWrappedGeometry(canvasWidth, canvasHeight);
+ assertEquals(PA.getValue(testee, "wrappedVisibleWidths"), 1);
+ }
+
+ /**
+ * Test the method that computes wrapped width in residues, height of wrapped
+ * widths in pixels, and the number of widths visible
+ */
+ @Test(groups = "Functional")
+ public void testCalculateWrappedGeometry_withAnnotations()
+ {
+ AlignFrame af = new FileLoader().LoadFileWaitTillLoaded(
+ "examples/uniref50.fa", DataSourceType.FILE);
+ AlignViewport av = af.getViewport();
+ AlignmentI al = av.getAlignment();
+ assertEquals(al.getWidth(), 157);
+ assertEquals(al.getHeight(), 15);
+
+ av.setWrapAlignment(true);
+ av.getRanges().setStartEndSeq(0, 14);
+ av.setFont(new Font("SansSerif", Font.PLAIN, 14), true);
+ int charHeight = av.getCharHeight();
+ int charWidth = av.getCharWidth();
+ assertEquals(charHeight, 17);
+ assertEquals(charWidth, 12);
+
+ SeqCanvas testee = af.alignPanel.getSeqPanel().seqCanvas;
+
+ /*
+ * first with scales above, left, right
+ */
+ av.setShowAnnotation(true);
+ av.setScaleAboveWrapped(true);
+ av.setScaleLeftWrapped(true);
+ av.setScaleRightWrapped(true);
+ FontMetrics fm = testee.getFontMetrics(av.getFont());
+ int labelWidth = fm.stringWidth("000") + charWidth;
+ assertEquals(labelWidth, 39); // 3 x 9 + charWidth
+ int annotationHeight = testee.getAnnotationHeight();
+
+ /*
+ * width 400 pixels leaves (400 - 2*labelWidth) for residue columns
+ * take the whole multiple of character widths
+ */
+ int canvasWidth = 400;
+ int canvasHeight = 300;
+ int residueColumns = (canvasWidth - 2 * labelWidth) / charWidth;
+ int wrappedWidth = testee.calculateWrappedGeometry(canvasWidth, canvasHeight);
+ assertEquals(wrappedWidth, residueColumns);
+ assertEquals(PA.getValue(testee, "labelWidthWest"), labelWidth);
+ assertEquals(PA.getValue(testee, "labelWidthEast"), labelWidth);
+ assertEquals(PA.getValue(testee, "wrappedSpaceAboveAlignment"),
+ 2 * charHeight);
+ int repeatingHeight = (int) PA.getValue(testee, "wrappedRepeatHeightPx");
+ assertEquals(repeatingHeight, charHeight * (2 + al.getHeight())
+ + annotationHeight);
+ assertEquals(PA.getValue(testee, "wrappedVisibleWidths"), 1);
+
+ /*
+ * repeat height is 17 * (2 + 15) = 289 + annotationHeight = 507
+ * make canvas height 2 * 289 + 3 * charHeight so just enough to
+ * draw 2 widths and the first sequence of a third
+ */
+ canvasHeight = charHeight * (17 * 2 + 3) + 2 * annotationHeight;
+ testee.calculateWrappedGeometry(canvasWidth, canvasHeight);
+ assertEquals(PA.getValue(testee, "wrappedVisibleWidths"), 3);
+
+ /*
+ * reduce canvas height by 1 pixel - should not be enough height
+ * to draw 3 widths
+ */
+ canvasHeight -= 1;
+ testee.calculateWrappedGeometry(canvasWidth, canvasHeight);
+ assertEquals(PA.getValue(testee, "wrappedVisibleWidths"), 2);
+
+ /*
+ * turn off scale above - can now fit in 2 and a bit widths
+ */
+ av.setScaleAboveWrapped(false);
+ testee.calculateWrappedGeometry(canvasWidth, canvasHeight);
+ assertEquals(PA.getValue(testee, "wrappedVisibleWidths"), 3);
+
+ /*
+ * reduce height to enough for 2 widths and not quite a third
+ * i.e. two repeating heights + spacer + sequence - 1 pixel
+ */
+ canvasHeight = charHeight * (16 * 2 + 2) + 2 * annotationHeight - 1;
+ testee.calculateWrappedGeometry(canvasWidth, canvasHeight);
+ assertEquals(PA.getValue(testee, "wrappedVisibleWidths"), 2);
+
+ /*
+ * add 1 pixel to height - should now get 3 widths drawn
+ */
+ canvasHeight += 1;
+ testee.calculateWrappedGeometry(canvasWidth, canvasHeight);
+ assertEquals(PA.getValue(testee, "wrappedVisibleWidths"), 3);
+ }
+}
AlignViewport av = af.getViewport();
/*
- * scale has minor ticks at 5 and 15, major at 10 and 20
+ * scale has minor ticks at 5, 15, 25, major at 10 and 20
* (these are base 1, ScaleMark holds base 0 values)
*/
List<ScaleMark> marks = new ScaleRenderer().calculateMarks(av, 0, 25);
- assertEquals(marks.size(), 4);
+ assertEquals(marks.size(), 5);
assertFalse(marks.get(0).major);
assertEquals(marks.get(0).column, 4);
assertEquals(marks.get(3).column, 19);
assertEquals(marks.get(3).text, "20");
+ assertFalse(marks.get(4).major);
+ assertEquals(marks.get(4).column, 24);
+ assertNull(marks.get(4).text);
+
/*
* now hide columns 9-11 and 18-20 (base 1)
* scale marks are now in the same columns as before, but
av.hideColumns(8, 10);
av.hideColumns(17, 19);
marks = new ScaleRenderer().calculateMarks(av, 0, 25);
- assertEquals(marks.size(), 4);
+ assertEquals(marks.size(), 5);
assertFalse(marks.get(0).major);
assertEquals(marks.get(0).column, 4);
assertNull(marks.get(0).text);
assertTrue(marks.get(3).major);
assertEquals(marks.get(3).column, 19);
assertEquals(marks.get(3).text, "26"); // +6 hidden columns
+ assertFalse(marks.get(4).major);
+ assertEquals(marks.get(4).column, 24);
+ assertNull(marks.get(4).text);
}
}
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.assertNotEquals;
import static org.testng.Assert.assertNull;
import static org.testng.Assert.assertTrue;
}
@Test(groups = "Functional")
+ public void testFindFeatureAtEnd()
+ {
+ /*
+ * terminal residue feature
+ */
+ seq.addSequenceFeature(new SequenceFeature("PDBRESNUM", "pdb res 1",
+ seq.getEnd(), seq.getEnd(), Float.NaN, "1seq.pdb"));
+ fr.setColour("PDBRESNUM", new FeatureColour(Color.red));
+ fr.featuresAdded();
+ av.setShowSequenceFeatures(true);
+
+ /*
+ * final column should have PDBRESNUM feature, the others not
+ */
+ Color c = finder.findFeatureColour(Color.blue, seq,
+ seq.getLength() - 2);
+ assertNotEquals(c, Color.red);
+ c = finder.findFeatureColour(Color.blue, seq, seq.getLength() - 1);
+ assertEquals(c, Color.red);
+ }
+
+ @Test(groups = "Functional")
public void testFindFeatureColour_graduatedFeatureColour()
{
seq.addSequenceFeature(new SequenceFeature("kd", "hydrophobicity", 2,
<!--
Suppress check of externally sourced code
-->
- <suppress checks="[a-zA-Z0-9]*" files="com[\\/]*"/>
- <suppress checks="[a-zA-Z0-9]*" files="ext[\\/]*"/>
- <suppress checks="[a-zA-Z0-9]*" files="org[\\/]*"/>
- <suppress checks="[a-zA-Z0-9]*" files="uk[\\/]*"/>
+ <suppress checks="[a-zA-Z0-9]*" files="[\\/]com[\\/]github*"/>
+ <suppress checks="[a-zA-Z0-9]*" files="[\\/]com[\\/]stevesoft*"/>
+ <suppress checks="[a-zA-Z0-9]*" files="[\\/]ext[\\/]edu*"/>
+ <suppress checks="[a-zA-Z0-9]*" files="[\\/]ext[\\/]vamsas*"/>
+ <suppress checks="[a-zA-Z0-9]*" files="[\\/]org[\\/]jibble*"/>
+ <suppress checks="[a-zA-Z0-9]*" files="[\\/]uk[\\/]ac*"/>
<!--
ImportControl can only handle one top level package
<subpackage name="datamodel">
<disallow pkg="jalview.gui"/>
<allow pkg="fr.orsay.lri.varna"/>
- <subpackage name="xdb">
- <subpackage name="embl">
- <allow pkg="org.exolab.castor"/>
- </subpackage>
+ <subpackage name="xdb.embl">
+ <allow pkg="org.exolab.castor"/>
</subpackage>
</subpackage>
+ <subpackage name="ext">
+ <subpackage name="ensembl">
+ <allow pkg="javax.ws"/>
+ <allow pkg="org.json"/>
+ </subpackage>
+ <subpackage name="htsjdk">
+ <allow pkg="htsjdk"/>
+ </subpackage>
+ <subpackage name="jmol">
+ <allow pkg="MCview"/>
+ <allow pkg="org.jmol"/>
+ </subpackage>
+ <subpackage name="paradise">
+ <allow pkg="org.apache"/>
+ <allow pkg="org.json"/>
+ </subpackage>
+ <subpackage name="rbvi">
+ <allow pkg="ext.edu.ucsf"/>
+ <allow pkg="javax.servlet"/>
+ </subpackage>
+ <subpackage name="so">
+ <allow pkg="org.biojava"/>
+ </subpackage>
+ <subpackage name="varna">
+ <allow pkg="fr.orsay"/>
+ </subpackage>
+ </subpackage>
+
<subpackage name="fts">
<allow pkg="javax.swing"/>
<allow pkg="javax.ws"/>
</subpackage>
<subpackage name="schemes">
- <allow pkg="org.exolab.castor"/>
+ <allow pkg="org.exolab.castor" class="jalview.schemes.ColourSchemeLoader"/>
</subpackage>
<subpackage name="structure">