}
}
+task testTask2(type: Test) {
+ group = "Verification"
+ description = "Tests that need to be isolated from the main test run"
+ useTestNG() {
+ includeGroups name
+ excludeGroups testng_excluded_groups.split(",")
+ preserveOrder true
+ useDefaultListeners=true
+ }
+}
+task testTask3(type: Test) {
+ group = "Verification"
+ description = "Tests that need to be isolated from the main test run"
+ useTestNG() {
+ includeGroups name
+ excludeGroups testng_excluded_groups.split(",")
+ preserveOrder true
+ useDefaultListeners=true
+ }
+}
+
/* insert more testTaskNs here -- change N to next digit or other string */
/*
task testTaskN(type: Test) {
bamboo_channelbase = https://builds.jalview.org/browse
bamboo_planKey =
-bamboo_getdown_channel_suffix = /latest/artifact/shared/getdown-channel
+bamboo_getdown_channel_suffix = /latest/artifact/shared/getdown-build-for-website/default
eclipse_codestyle_file = utils/eclipse/JalviewCodeStyle.xml
eclipse_extra_jdt_prefs_file = utils/eclipse/org.eclipse.jdt.core.jalview.prefs
<p>Jalview allows the columns of an alignment to be coloured using
any numerical annotation rows added to that alignment.</p>
Select "Colour"
- <strong>→</strong> ".. by Annotation" to bring up the
+ <strong>→</strong> "by Annotation..." to bring up the
Colour by Annotation settings window.
<br>
+ <br>You can also apply Colour by annotation for a particular annotation
+ (or per-sequence set) by right-clicking an annotation row's label and selecting "Colour by Annotation..." or "Colour by Annotation (per Sequence)..." from the
+ <strong>Annotation label popup menu</strong>. (<em>Since Jalview 2.11.3</em>)
+ <br>
+ <div align="center">
+ <img src="../features/annotationsubmenucolbyannot.png" width="414" height="266">
+ </div>
+ <p><strong>The Colour by Annotation Settings Window</strong></p>
<br>
<div align="center">
<img src="annotationColourSetting.gif" width="471" height="256">
<br/>
The value can also be specified as a sub-value:
<pre>
- jalview --open examples/uniref50.fa --structure [seqid=FER1+SPIOL,structureviewer=jmol,tempfac=plddt]examples/AlphaFold/AF-P00221-F1-model_v4.pdb
+ jalview --open examples/uniref50.fa --structure [seqid=FER1_SPIOL,structureviewer=jmol,tempfac=plddt]examples/AlphaFold/AF-P00221-F1-model_v4.pdb
</pre>
which is equivalent to
<pre>
- jalview --open examples/uniref50.fa --structure examples/AlphaFold/AF-P00221-F1-model_v4.pdb --tempfac plddt --seqid FER1+SPIOL
+ jalview --open examples/uniref50.fa --structure examples/AlphaFold/AF-P00221-F1-model_v4.pdb --tempfac plddt --seqid FER1_SPIOL
--structureviewer jmol
</pre>
Jalview</strong>
</p>
- <p>Predicted Alignment Error matrices are produced by deep-learning
- based 3D-structure prediction pipelines such as AlphaFold.</p>
+ <p>Predicted Alignment Error (PAE) matrices are produced by
+ deep-learning based 3D-structure prediction pipelines such as
+ AlphaFold. They reflect how reliably two parts of a model have been
+ positioned in space, by giving for each residue the likely error (in
+ Ångstroms) between that residue and every other modelled
+ position the pair of residues' real relative position, if the model
+ and real 3D structure were superimposed at that residue.</p>
+ <p>
+ Jalview visualises PAE matrices as an alignment annotation track,
+ shaded from dark green to white, similar to the encoding used on the
+ EBI-AlphaFold website (see <a
+ href="https://alphafold.ebi.ac.uk/entry/O04090">O04090 3D model</a>
+ at EBI-AlphaFoldDB).
+ </p>
+ <div style="display:flex; flex-wrap:wrap;"align="center" width="100%">
+ <figure><img src="../structures/epas1_annotdetail.png" height="300"/><figcaption>Alignment of EPAS1 homologs from Human, Rat and Cow, with predicted alignment error shown in Jalview</figcaption></figure>
+ <figure><img src="../structures/epas1_pae_ebiaf.png" height="300"/><figcaption>Predicted Alignment Error Matrix<br/>from <a href="https://alphafold.ebi.ac.uk/entry/Q99814">https://alphafold.ebi.ac.uk/entry/Q99814</a></figcaption></figure>
+ </div>
+ <p>
+ <strong>Importing PAE Matrices</strong>
+ </p>
<p>
Jalview retrieves PAE matrices when importing predicted 3D structures
from the EBI-AlphaFold database via <a
href="../features/structurechooser.html">Jalview's structure
- chooser</a> GUI.
+ chooser</a> GUI. If you have produced your own models and accompanying
+ PAE matrices using a pipeline such as ColabFold, then you can load
+ them both together via the
+ <a href="../features/structurechooser.html#loadpdbfile">Load PDB
+ File</a> dropdown menu in the 3D structure chooser, providing it is
+ in a
+ <a href="../io/paematrixformat.html">supported PAE format</a>.
</p>
<p>
- If you have produced your own models using a pipeline such as
- ColabFold, then you can load it via the 'Add PAE matrix file' button
- in the <a href="../features/structurechooser.html#loadpdbfile">Load
- PDB File</a> dropdown menu in the 3D structure chooser, providing it is
- in a <a href="../io/paematrixformat.html">supported PAE format</a>. ,
- or the <a href="../features/clarguments-basic.html">Command Line
- Interface</a>. See <a href="../features/paematrices.html">Working
- with PAE Matrices</a> for information on how they are visualised and
- analysed in Jalview.
+ The <a href="../features/clarguments-basic.html">Command Line
+ Interface</a> also provides a options for importing PAE matrices along
+ side models, enabling the automated production of alignment figures
+ annotated with PAE matrices and PLDDT scores.
</p>
+ <p>
+ <strong>Showing PAE Matrix Annotations </strong>
</p>
<p>
- An additional <em>Predicted Alignment Error</em> file can also be
- provided when importing 3D structure data. Jalview supports import of
- PAE Matrices provided as <a href="../io/paematrixformat.html">AlphaFold
- format JSON files</a> - which are also produced by ColabFold. See <a
- href="paematrices.html">Working with PAE Matrices</a> for details on
- what Jalview allows you to do with associated PAE matrix data.
+ When viewing 3D structures from the EBI-AlphaFold database or local 3D
+ structures with an associated PAE file, the PAE is imported as <i>Reference
+ Annotation</i>, which is not always automatically added to the alignment
+ view.
</p>
+ <p>To show the PAE, right click the sequence and locate the 'Add
+ Reference Annotation' entry in the Sequence ID submenu, or select all
+ sequences and locate the option in the Selection submenu. You can do
+ this in any alignment window (or view) where a sequence with
+ associated PAE data appears.</p>
+ <p></p>
<p>
- <em>The Structure Chooser interface was introduced in Jalview
- 2.9. </em>
+ <em>Support for visualision and analysis of predicted alignment
+ error matrices was added in Jalview 2.11.3. </em>
</p>
</body>
</html>
</p>
<p>The search box is displayed by pressing Control and F or
selecting "Find..." from the "Search" menu.</p>
- <img src="search.png" width="400" height="152">
+ <img src="search.png" height="152">
<p>"Find next" will find the next occurrence of the
query and adjust the alignment window view to show it, and
"Find all" highlights all matches for a query. The
<ul>
<li>The search uses regular expressions. (understands a mixture
of posix and perl style regex - see below for a summary)</li>
- <li>Gaps are ignored when matching the query to the sequences
- in the alignment.</li>
- <li>Hidden columns can optionally be ignored (<em>since Jalview 2.11</em>)</li>
- <li>The search is applied to both sequences and their IDs. It can
- optionally also be applied to the description string (<em>since Jalview
- 2.10</em>), and sequence feature descriptions (<em>since Jalview 2.11.2.5</em>).
- </li>
- <li>If a region is selected, then search will <strong>only</strong>
+ <li>If a region is selected, then search will <strong>only</strong>
be performed on that region.<br />
<em>Tip: to quickly clear the current selection, click the
alignment view you wish to search, then press 'Escape'.</em>
</li>
+ <li>Gaps are ignored when matching the query to the sequences
+ in the alignment.</li>
+ <li>Hidden columns can optionally be ignored (<em>since Jalview 2.11</em>)</li>
+ <li>The search is applied to both sequences and their IDs. <br />
+ Check boxes also enable searching of:
+ <ul>
+ <li><strong>Sequence description</strong> (<em>since Jalview 2.10</em>)
+ </li>
+ <li><strong>Sequence Feature</strong> type and description for currently displayed features (<em>since Jalview
+ 2.11.3.0</em>)
+ </li>
+ </ul>
+ </li>
<li>Tick the "Match Case" box to perform a case
sensitive search.</li>
<li>To access a <a href="#queryhistory">previously used
<strong>Copying highlighted regions to a new alignment</strong>
</p>
<p>
- You can copy the currently highlighted matching regions of sequences to the clipboard with alt-Command-C.
+ Press <strong>Copy</strong> button or type Ctrl (Cmd on OSX) + Shift +
+ C to copy highlighted search results to the clipboard, enabling them
+ to be pasted to a new alignment (via Shift+Ctrl (or Cmd) + V).
</p>
- <p>
+ <p>
<strong>A quick Regular Expression Guide</strong>
</p>
- <!-- JAL-4019 --> Ambiguous Base Colourscheme
- <!-- JAL-4061 --> Find can search sequence features' type and description
- <!-- JAL-4062 --> Hold down Shift + CMD/CTRL C to copy highlighted regions as new sequences
-- <!-- JAL-1556 --> Quickly enable select and/or colour by for displayed annotation row via its popup menu
+- <!-- JAL-1556 --> Quickly enable select and/or colour by for displayed annotation row via annotation panel popup menu
- <!-- JAL-4094 --> Shift+Click+Drag to adjust height of all annotation tracks of same type
- <!-- JAL-4190 --> Pressing escape in tree panel clears any current selection
- <!-- JAL-4165 --> Missing last letter when copying consensus sequence from alignment if first column is hidden
- <!-- JAL-4261 --> Last sequence ID in alignment not shown and annotation labels are misaligned in HTML export
- <!-- JAL-3024 --> Files opened via command line with a relative path are added as relative paths to Recent files list (since 2.0.x)
+- <!-- JAL-4291 --> Test coverage for ID width adjustment disabled pending fix for new annotation label geometry and width calculation
* 3D structure data shown in Jmol can be exported as PNG
* Scale factors and dimensions can be specified, allowing high resolution image exports
-In addition to these new functionality, next generation CLI operations can be applied to a range of files and directories through the use of wild-cards. This allows faster and more efficient processing of large numbers of alignments. It also facilitates modularisation of operations through the use of ['command-line argument files'](../features/clarguments-argfiles.html).
+In addition to these new functionality, next generation CLI operations can be applied to a range of files and directories through the use of wild-cards. This allows faster and more efficient processing of large numbers of alignments. It also facilitates modularisation of operations through the use of ['command-line argument files'](features/clarguments-argfiles.html).
All new CLI parameters are preceded by '--', as opposed to an optional single '-' which was used in Jalview's old CLI. Old style arguments can still be used, so existing scripts will still work as before, but old-style operations cannot be mixed with new operations in the same CLI call. Use of old command line operations will also raise a warning, and we plan to completely remove support in Jalview's next major release (2.12).
AppJmol jmol = (AppJmol) sview;
jmol.makePDBImage(structureImageFile, imageType, renderer,
userBis);
- Console.debug("Finished Rendering image to "
+ Console.info("Exported structure image to "
+ structureImageFile);
// RESTORE SESSION AFTER EXPORT IF NEED BE
@Override
public ContactListI getContactListFor(AlignmentAnnotation _aa, int column)
{
+ if (_aa.annotations==null || column>=_aa.annotations.length || column<0)
+ {
+ return null;
+ }
ContactListI cl = cmholder.getContactListFor(_aa, column);
if (cl == null && _aa.groupRef != null)
{
}
}
}
- if (tot > 0)
+ if (tot > 0 && to_column>from_column)
{
cr.setMean(tot / (1 + to_column - from_column));
}
* @return
*/
boolean contains(SequenceI seq, int start, int end);
+
+ /**
+ *
+ * @param seq
+ * @param from - first position to highlight
+ * @param to - last position to highlight (assumed higher than from)
+ * @return true iff from-to intersects or marks positions either side of start/end
+ */
+ boolean adjacent(SequenceI seq, int from, int to);
}
\ No newline at end of file
{
private int count;
- private List<SearchResultMatchI> matches = new ArrayList<>();
+ private ArrayList<SearchResultMatchI> matches = new ArrayList<>();
/**
* One match consists of a sequence reference, start and end positions.
* Discontiguous ranges in a sequence require two or more Match objects.
*/
- public class Match implements SearchResultMatchI
+ public class Match implements SearchResultMatchI, Comparable<SearchResultMatchI>
{
final SequenceI sequence;
{
return (sequence == seq && start <= from && end >= to);
}
+ @Override
+ public boolean adjacent(SequenceI seq, int from, int to)
+ {
+ return (sequence == seq && ((start <= from && end >= to) || (from<=(end+1) && to >=(end+1)) || (from<=(start-1) && to>=(start-1))));
+ }
+
+ @Override
+ public int compareTo(SearchResultMatchI o)
+ {
+ if (start<o.getStart())
+ {
+ return -1;
+ }
+ if (start > o.getStart())
+ {
+ return +1;
+ }
+ if (end < o.getEnd())
+ {
+ return -1;
+ }
+ if (end > o.getEnd())
+ {
+ return +1;
+ }
+ if (sequence!=o.getSequence())
+ {
+ int hashc =sequence.hashCode(),oseq=o.getSequence().hashCode();
+ return (hashc < oseq) ? -1 : 1;
+ }
+ return 0;
+ }
+
}
@Override
count = beforeCount + 1;
}
}
+
@Override
+ public boolean appendResult(SequenceI sequence, int start, int end)
+ {
+
+ Match m = new Match(sequence, start, end);
+
+ boolean appending=false;
+
+ // we dynamically maintain an interval to add as we test each range in the list
+
+ int cstart=start,cend=end;
+ List<SearchResultMatchI> toRemove=new ArrayList<>();
+ for (SearchResultMatchI thatm:matches)
+ {
+ if (thatm.getSequence()==sequence)
+ {
+ if (thatm.contains(sequence,cstart,cend))
+ {
+ // found a match containing the current range. nothing else to do except report if we operated on the list
+ return appending;
+ }
+ if (thatm.adjacent(sequence, cstart, cend))
+ {
+ // update the match to add with the adjacent start/end
+ start = Math.min(m.start, thatm.getStart());
+ end = Math.max(m.end, thatm.getEnd());
+ // and check if we keep or remove the old one
+ if (thatm.getStart()!=start || thatm.getEnd()!=end)
+ {
+ toRemove.add(thatm);
+ count--;
+ cstart = start;
+ cend = end;
+ appending=true;
+ } else {
+ return false;
+ }
+ }
+ }
+ }
+ matches.removeAll(toRemove);
+ {
+ matches.add(new Match(sequence,cstart,cend));
+ count++;
+ }
+ return appending;
+ }
+ @Override
public boolean involvesSequence(SequenceI sequence)
{
final int start = sequence.getStart();
}
return seqs;
}
+
}
*/
void addResult(SequenceI seq, int[] positions);
+
+ /**
+ * Adds the given start/end region to this search result. If sequence already
+ * has a search result and the range is adjacent to already highlighted
+ * positions, they will be merged
+ *
+ * @param sequence
+ * @param start
+ * @param end
+ * @return true if an existing range was updated with this one
+ */
+ boolean appendResult(SequenceI sequence, int start, int end);
+
/**
* adds all match results in the argument to this set
*
/**
* Calculate the width of the alignment labels based on the displayed names
- * and any bounds on label width set in preferences.
+ * and any bounds on label width set in preferences. Also includes annotations
+ * not actually visible.
+ *
+ * FIXME JAL-244 JAL-4091 - doesn't include sequence associated annotation
+ * label decorators and only called during tests
*
* @param maxwidth
* -1 or maximum width allowed for IdWidth
{
return calculateIdWidth(maxwidth, true, false);
}
-
+ /**
+ * Calculate the width of the alignment labels based on the displayed names
+ * and any bounds on label width set in preferences.
+ *
+ * @param maxwidth
+ * -1 or maximum width allowed for IdWidth
+ * @param includeAnnotations - when true includes width of any additional marks in annotation id panel
+ * @param visibleOnly -
+ * @return Dimension giving the maximum width of the alignment label panel
+ * that should be used.
+ */
public Dimension calculateIdWidth(int maxwidth,
boolean includeAnnotations, boolean visibleOnly)
{
// Also check annotation label widths
if (includeAnnotations && al.getAlignmentAnnotation() != null)
{
- if (Jalview.isHeadlessMode())
- {
- AnnotationLabels aal = getAlabels();
- int stringWidth = aal.drawLabels(null, false, idWidth, false, false,
- fm);
- idWidth = Math.max(idWidth, stringWidth);
- }
- else
- {
- fm = c.getFontMetrics(getAlabels().getFont());
-
- for (i = 0; i < al.getAlignmentAnnotation().length; i++)
- {
- AlignmentAnnotation aa = al.getAlignmentAnnotation()[i];
- if (visibleOnly && !aa.visible)
- {
- continue;
- }
- String label = aa.label;
- int stringWidth = fm.stringWidth(label);
- idWidth = Math.max(idWidth, stringWidth);
- }
- }
+ AnnotationLabels aal = getAlabels();
+ int stringWidth = aal.drawLabels(null, false, idWidth, false, false,
+ fm, !visibleOnly);
+ idWidth = Math.max(idWidth, stringWidth);
}
int w = maxwidth < 0 ? idWidth : Math.min(maxwidth, idWidth);
Graphics idGraphics, Graphics alignmentGraphics)
throws PrinterException
{
- final int idWidth = getVisibleIdWidth(false);
-
+ final int idWidth, idWidthForGui;
+ // otherwise calculate it
+ idWidth = getVisibleIdWidth(false);
+// if (getIdPanel()!=null && getIdPanel().getWidth()>0)
+// {
+// // use the current IdPanel's width, if its set and non-zero
+// idWidthForGui = getIdPanel().getWidth();
+// } else {
+// idWidthForGui=0;
+// }
/*
* Get the horizontal offset to where we draw the sequences.
* This is idWidth if using a single Graphics context, else zero.
}
final int alignmentDrawnHeight = (endSeq - startSeq) * charHeight + 3;
+ alignmentGraphics.setColor(Color.white);
+ alignmentGraphics.fillRect(0, 0, pageWidth, pageHeight+scaleHeight);
+
/*
* draw the Scale at horizontal offset, then reset to top left (0, 0)
*/
IdCanvas idCanvas = getIdPanel().getIdCanvas();
List<SequenceI> selection = av.getSelectionGroup() == null ? null
: av.getSelectionGroup().getSequences(null);
+
idCanvas.drawIds((Graphics2D) idGraphics, av, startSeq, endSeq - 1,
- selection, false);
+ selection, false,idWidth);
idGraphics.setFont(av.getFont());
idGraphics.translate(0, -scaleHeight);
// see if rendering offscreen - check preferences and calc width accordingly
if (!onscreen && Cache.getDefault("FIGURE_AUTOIDWIDTH", false))
{
- return calculateIdWidth(-1).width;
+ return calculateIdWidth(-1,true,true).width;
}
Integer idwidth = onscreen ? null
: Cache.getIntegerProperty("FIGURE_FIXEDIDWIDTH");
Graphics2D g2d = (Graphics2D) g;
Graphics dummy = g2d.create();
int newAnnotationIdWidth = drawLabels(dummy, clip, width, false, forGUI,
- null);
+ null, false);
dummy.dispose();
Dimension d = ap.calculateDefaultAlignmentIdWidth();
int alignmentIdWidth = d.width;
}
else
{
- int newAnnotationIdWidth = drawLabels(g, clip, width, false, forGUI, null);
+ int newAnnotationIdWidth = drawLabels(g, clip, width, false, forGUI, null, false);
width = Math.max(newAnnotationIdWidth, givenWidth);
}
- drawLabels(g, clip, width, true, forGUI, null);
+ drawLabels(g, clip, width, true, forGUI, null, false);
}
/**
* occur, but the widest label width will be returned. If g is null then
* fmetrics must be supplied.
*
- * Returns the width of the annotation labels.
- *
* @param g
* Graphics2D instance (used for rendering and font scaling if no fmetrics supplied)
* @param clip
* @param forGUI - when false, GUI relevant marks like indicators for dragging annotation panel height are not rendered
* @param fmetrics
* FontMetrics if Graphics object g is null
+ * @param includeHidden - when true returned width includes labels in hidden row width calculation
+ * @return the width of the annotation labels.
*/
public int drawLabels(Graphics g0, boolean clip, int width,
- boolean actuallyDraw, boolean forGUI, FontMetrics fmetrics)
+ boolean actuallyDraw, boolean forGUI, FontMetrics fmetrics, boolean includeHidden)
{
if (clip)
{
for (int i = 0; i < aa.length; i++)
{
visible = true;
- if (!aa[i].visible)
+ if (!aa[i].visible && !includeHidden)
{
hasHiddenRows = true;
continue;
olY = y;
// look ahead to next annotation
for (nexAA = i + 1; nexAA < aa.length
- && !aa[nexAA].visible; nexAA++)
+ && (!aa[nexAA].visible && includeHidden); nexAA++)
;
y += aa[i].height;
if (clip)
import jalview.renderer.ContactGeometry;
import jalview.schemes.ResidueProperties;
import jalview.util.Comparison;
+import jalview.util.Format;
import jalview.util.MessageManager;
import jalview.util.Platform;
import jalview.viewmodel.ViewportListenerI;
return false;
}
int yOffset = rowIndex[1];
-
+ AlignmentAnnotation[] allAnnotation = av.getAlignment()
+ .getAlignmentAnnotation();
+ if (allAnnotation==null || rowIndex[0]<0 || rowIndex[0]>=allAnnotation.length)
+ {
+ return false;
+ }
AlignmentAnnotation clicked = av.getAlignment()
.getAlignmentAnnotation()[rowIndex[0]];
if (clicked.graph != AlignmentAnnotation.CONTACT_MAP)
{
ContactGeometry cXcgeom = new ContactGeometry(forCurrentX,
clicked.graphHeight);
- ContactGeometry.contactInterval cXci = cXcgeom.mapFor(yOffset,
- yOffset);
- /**
- * start and end range corresponding to the row range under the mouse at
- * column currentX
- */
- int fr, to;
- fr = Math.min(cXci.cStart, cXci.cEnd);
- to = Math.max(cXci.cStart, cXci.cEnd);
-
- // double click selects the whole group
- if (evt.getClickCount() == 2)
+ ContactGeometry.contactInterval cXci = cXcgeom.mapFor(yOffset);
+ if (cXci != null)
{
- ContactMatrixI matrix = av.getContactMatrix(clicked);
+ /**
+ * start and end range corresponding to the row range under the mouse at
+ * column currentX
+ */
+ int fr, to;
+ fr = Math.min(cXci.cStart, cXci.cEnd);
+ to = Math.max(cXci.cStart, cXci.cEnd);
- if (matrix != null)
+ // double click selects the whole group
+ if (evt.getClickCount() == 2)
{
- // simplest approach is to select all group containing column
- if (matrix.hasGroups())
+ ContactMatrixI matrix = av.getContactMatrix(clicked);
+
+ if (matrix != null)
{
- SequenceI rseq = clicked.sequenceRef;
- BitSet grp = new BitSet();
- grp.or(matrix.getGroupsFor(currentX));
- // TODO: cXci needs to be mapped to real groups
- for (int c = fr; c <= to; c++)
+ // simplest approach is to select all group containing column
+ if (matrix.hasGroups())
{
- BitSet additionalGrp = matrix.getGroupsFor(c);
- grp.or(additionalGrp);
- }
+ SequenceI rseq = clicked.sequenceRef;
+ BitSet grp = new BitSet();
+ grp.or(matrix.getGroupsFor(currentX));
+ // TODO: cXci needs to be mapped to real groups
+ for (int c = fr; c <= to; c++)
+ {
+ BitSet additionalGrp = matrix.getGroupsFor(c);
+ grp.or(additionalGrp);
+ }
- HiddenColumns hc = av.getAlignment().getHiddenColumns();
- ColumnSelection cs = av.getColumnSelection();
-
- for (int p=grp.nextSetBit(0); p >= 0; p = grp
- .nextSetBit(p + 1))
- {
- if (matrix instanceof MappableContactMatrixI)
+ HiddenColumns hc = av.getAlignment().getHiddenColumns();
+ ColumnSelection cs = av.getColumnSelection();
+
+ for (int p = grp.nextSetBit(0); p >= 0; p = grp
+ .nextSetBit(p + 1))
{
- // find the end of this run of set bits
- int nextp = grp.nextClearBit(p)-1;
- int[] pos = ((MappableContactMatrixI)matrix).getMappedPositionsFor(rseq, p,nextp);
- p=nextp;
-
- if (pos!=null)
+ if (matrix instanceof MappableContactMatrixI)
{
- for (int pos_p = pos[0];pos_p<=pos[1];pos_p++)
+ // find the end of this run of set bits
+ int nextp = grp.nextClearBit(p) - 1;
+ int[] pos = ((MappableContactMatrixI) matrix)
+ .getMappedPositionsFor(rseq, p, nextp);
+ p = nextp;
+
+ if (pos != null)
{
- int col = rseq.findIndex(pos_p)-1;
- if (col>=0 && (!av.hasHiddenColumns() || hc.isVisible(col)))
+ for (int pos_p = pos[0]; pos_p <= pos[1]; pos_p++)
{
- cs.addElement(col);
+ int col = rseq.findIndex(pos_p) - 1;
+ if (col >= 0 && (!av.hasHiddenColumns()
+ || hc.isVisible(col)))
+ {
+ cs.addElement(col);
+ }
}
}
}
- } else {
- int offp = (rseq != null)
- ? rseq.findIndex(rseq.getStart() - 1 + p)
- : p;
-
- if (!av.hasHiddenColumns() || hc.isVisible(offp))
+ else
{
- cs.addElement(offp);
+ int offp = (rseq != null)
+ ? rseq.findIndex(rseq.getStart() - 1 + p)
+ : p;
+
+ if (!av.hasHiddenColumns() || hc.isVisible(offp))
+ {
+ cs.addElement(offp);
+ }
}
}
}
- }
- // possible alternative for interactive selection - threshold
- // gives 'ceiling' for forming a cluster
- // when a row+column is selected, farthest common ancestor less
- // than thr is used to compute cluster
+ // possible alternative for interactive selection - threshold
+ // gives 'ceiling' for forming a cluster
+ // when a row+column is selected, farthest common ancestor less
+ // than thr is used to compute cluster
- }
- }
- else
- {
- // select corresponding range in segment under mouse
- {
- int[] rng = forCurrentX.getMappedPositionsFor(fr, to);
- if (rng != null)
- {
- av.getColumnSelection().addRangeOfElements(rng, true);
}
- av.getColumnSelection().addElement(currentX);
}
- // PAE SPECIFIC
- // and also select everything lower than the max range adjacent
- // (kind of works)
- if (evt.isControlDown()
- && PAEContactMatrix.PAEMATRIX.equals(clicked.getCalcId()))
+ else
{
- int c = fr;
- ContactRange cr = forCurrentX.getRangeFor(fr, to);
- double cval;
- // TODO: could use GraphLine instead of arbitrary picking
- // TODO: could report mean/median/variance for partitions
- // (contiguous selected vs unselected regions and inter-contig
- // regions)
- // controls feathering - what other elements in row/column
- // should we select
- double thresh = cr.getMean() + (cr.getMax() - cr.getMean()) * .15;
- while (c >= 0)
+ // select corresponding range in segment under mouse
{
- cval = forCurrentX.getContactAt(c);
- if (// cr.getMin() <= cval &&
- cval <= thresh)
+ int[] rng = forCurrentX.getMappedPositionsFor(fr, to);
+ if (rng != null)
{
- int[] cols = forCurrentX.getMappedPositionsFor(c, c);
- if (cols != null)
- {
- av.getColumnSelection().addRangeOfElements(cols, true);
- }
- else
- {
- break;
- }
+ av.getColumnSelection().addRangeOfElements(rng, true);
}
- c--;
+ av.getColumnSelection().addElement(currentX);
}
- c = to;
- while (c < forCurrentX.getContactHeight())
+ // PAE SPECIFIC
+ // and also select everything lower than the max range adjacent
+ // (kind of works)
+ if (evt.isControlDown()
+ && PAEContactMatrix.PAEMATRIX.equals(clicked.getCalcId()))
{
- cval = forCurrentX.getContactAt(c);
- if (// cr.getMin() <= cval &&
- cval <= thresh)
+ int c = fr;
+ ContactRange cr = forCurrentX.getRangeFor(fr, to);
+ double cval;
+ // TODO: could use GraphLine instead of arbitrary picking
+ // TODO: could report mean/median/variance for partitions
+ // (contiguous selected vs unselected regions and inter-contig
+ // regions)
+ // controls feathering - what other elements in row/column
+ // should we select
+ double thresh = cr.getMean()
+ + (cr.getMax() - cr.getMean()) * .15;
+ while (c >= 0)
{
- int[] cols = forCurrentX.getMappedPositionsFor(c, c);
- if (cols != null)
+ cval = forCurrentX.getContactAt(c);
+ if (// cr.getMin() <= cval &&
+ cval <= thresh)
{
- av.getColumnSelection().addRangeOfElements(cols, true);
+ int[] cols = forCurrentX.getMappedPositionsFor(c, c);
+ if (cols != null)
+ {
+ av.getColumnSelection().addRangeOfElements(cols, true);
+ }
+ else
+ {
+ break;
+ }
}
+ c--;
}
- else
+ c = to;
+ while (c < forCurrentX.getContactHeight())
{
- break;
- }
- c++;
+ cval = forCurrentX.getContactAt(c);
+ if (// cr.getMin() <= cval &&
+ cval <= thresh)
+ {
+ int[] cols = forCurrentX.getMappedPositionsFor(c, c);
+ if (cols != null)
+ {
+ av.getColumnSelection().addRangeOfElements(cols, true);
+ }
+ }
+ else
+ {
+ break;
+ }
+ c++;
+ }
}
+
}
}
}
if (forFromX != null && forToX != null)
{
- ContactGeometry lastXcgeom = new ContactGeometry(forFromX,
- cma.graphHeight);
- ContactGeometry.contactInterval lastXci = lastXcgeom
- .mapFor(rowIndex[1], rowIndex[1] + deltaY);
-
- ContactGeometry cXcgeom = new ContactGeometry(forToX,
+ // FIXME will need two ContactGeometry objects when handling contact matrices with differing numbers of rows at each
+ // column
+ ContactGeometry xcgeom = new ContactGeometry(forFromX,
cma.graphHeight);
- ContactGeometry.contactInterval cXci = cXcgeom.mapFor(rowIndex[1],
- rowIndex[1] + deltaY);
+ ContactGeometry.contactInterval lastXci = xcgeom
+ .mapFor(rowIndex[1]);
+ ContactGeometry.contactInterval cXci = xcgeom.mapFor(rowIndex[1] + deltaY);
// mark rectangular region formed by drag
jalview.bin.Console.trace("Matrix Selection from last(" + fromXc
+ ",[" + lastXci.cStart + "," + lastXci.cEnd + "]) to cur("
+ toXc + ",[" + cXci.cStart + "," + cXci.cEnd + "])");
int fr, to;
- fr = Math.min(lastXci.cStart, lastXci.cEnd);
- to = Math.max(lastXci.cStart, lastXci.cEnd);
+ fr = Math.min(lastXci.cStart, cXci.cStart);
+ to = Math.max(lastXci.cEnd, cXci.cEnd);
int[] mappedPos = forFromX.getMappedPositionsFor(fr, to);
if (mappedPos != null)
{
// }
// else
{
- av.getColumnSelection().addElement(c);
- }
- }
- }
- // and again for most recent corner of drag
- fr = Math.min(cXci.cStart, cXci.cEnd);
- to = Math.max(cXci.cStart, cXci.cEnd);
- mappedPos = forFromX.getMappedPositionsFor(fr, to);
- if (mappedPos != null)
- {
- for (int pair = 0; pair < mappedPos.length; pair += 2)
- {
- jalview.bin.Console.trace("Marking " + fr + " to " + to
- + " mapping to sequence positions " + mappedPos[pair]
- + " to " + mappedPos[pair + 1]);
- for (int c = mappedPos[pair]; c <= mappedPos[pair + 1]; c++)
- {
- // if (cma.sequenceRef != null)
- // {
- // int col =
- // cma.sequenceRef.findIndex(cma.sequenceRef.getStart()+c);
- // av.getColumnSelection().addElement(col);
- // }
- // else
- {
- av.getColumnSelection().addElement(c);
- }
+ av.getColumnSelection().addElement(c-1);
}
}
}
ContactGeometry cgeom = new ContactGeometry(clist, ann.graphHeight);
ContactGeometry.contactInterval ci = cgeom.mapFor(rowAndOffset);
ContactRange cr = clist.getRangeFor(ci.cStart, ci.cEnd);
- tooltip = "Contact from " + clist.getPosition() + ", [" + ci.cStart
- + " - " + ci.cEnd + "]" + "<br/>Mean:" + cr.getMean();
-
+ StringBuilder tooltipb = new StringBuilder();
+ tooltipb.append("Contact from ")
+ .append(clist.getPosition()).append(", [").append(ci.cStart).append(" - ").append(ci.cEnd).append("]").append("<br/>Mean:");
+ Format.appendPercentage(tooltipb, (float)cr.getMean(),2);
+ tooltip = tooltipb.toString();
int col = ann.sequenceRef.findPosition(column);
int[][] highlightPos;
int[] mappedPos = clist.getMappedPositionsFor(ci.cStart, ci.cEnd);
gg.translate(0, transY);
- drawIds(gg, av, ss, es, searchResults,true);
+ drawIds(gg, av, ss, es, searchResults, true, getWidth());
gg.translate(0, -transY);
gg.fillRect(0, 0, getWidth(), imgHeight);
drawIds(gg, av, av.getRanges().getStartSeq(),
- av.getRanges().getEndSeq(), searchResults,true);
+ av.getRanges().getEndSeq(), searchResults,true, getWidth());
gg.dispose();
* @param startSeq
* @param endSeq
* @param selection
+ * @param forGUI when false rendering for print
+ * @param panelWidth width used to calculate righthand margin - usually idCanvas.getWidth()
+ *
*/
void drawIds(Graphics2D g, AlignViewport alignViewport,
- final int startSeq, final int endSeq, List<SequenceI> selection, boolean forGUI)
+ final int startSeq, final int endSeq, List<SequenceI> selection, boolean forGUI, int panelWidth)
{
Font font = alignViewport.getFont();
if (alignViewport.isSeqNameItalics())
}
// Now draw the id strings
- int panelWidth = getWidth();
int xPos = 0;
// Now draw the id strings
if (!manuallyAdjusted())
{
int getAnnotationsIdWidth = labels.drawLabels(g, false, -1, false,forGUI,
- null);
+ null, false);
thisIdWidth = idWidth < 0 ? getAnnotationsIdWidth : idWidth;
if (thisIdWidth > getWidth)
{
*/
public SplashScreen(boolean isTransient)
{
- Desktop.instance.acquireDialogQueue();
this.transientDialog = isTransient;
+ if (this.transientDialog)
+ {
+ Desktop.instance.acquireDialogQueue();
+ }
if (Platform.isJS()) // BH 2019
{
protected boolean refreshText()
{
String newtext = Desktop.instance.getAboutMessage();
- // jalview.bin.Console.errPrintln("Text found: \n"+newtext+"\nEnd of newtext.");
+ // jalview.bin.Console.errPrintln("Text found: \n"+newtext+"\nEnd of
+ // newtext.");
if (oldTextLength != newtext.length())
{
iframe.setVisible(false);
}
closeSplash();
- Desktop.instance.releaseDialogQueue();
}
/**
*/
public void closeSplash()
{
+ if (this.transientDialog)
+ {
+ Desktop.instance.releaseDialogQueue();
+ }
try
{
package jalview.renderer;
+import java.util.Arrays;
import java.util.Iterator;
+import java.util.List;
import jalview.datamodel.ColumnSelection;
import jalview.datamodel.ContactListI;
final ContactListI contacts;
+ /**
+ * how many pixels per contact (1..many)
+ */
final int pixels_step;
+ /**
+ * how many contacts per pixel (many > 0)
+ */
final double contacts_per_pixel;
+ /**
+ * number of contacts being mapped
+ */
final int contact_height;
+ /**
+ * number of pixels to map contact_height to
+ */
final int graphHeight;
+ /**
+ * number of contacts for each pixel_step - to last whole contact
+ */
+ final double contacts_step;
+
+ final int lastStep;
+
+ /**
+ * Bean used to map from a range of contacts to a range of pixels
+ * @param contacts
+ * @param graphHeight Number of pixels to map given range of contacts
+ */
public ContactGeometry(final ContactListI contacts, int graphHeight)
{
this.contacts = contacts;
this.graphHeight = graphHeight;
contact_height = contacts.getContactHeight();
// fractional number of contacts covering each pixel
- contacts_per_pixel = (graphHeight < 1) ? contact_height
+ contacts_per_pixel = (graphHeight <= 1) ? contact_height
: ((double) contact_height) / ((double) graphHeight);
if (contacts_per_pixel >= 1)
pixels_step = (int) Math
.ceil(((double) graphHeight) / (double) contact_height);
}
+ contacts_step = pixels_step*contacts_per_pixel;
+ lastStep = (int) Math.min((double)graphHeight, ((double)graphHeight)/((double)pixels_step));
}
public class contactInterval
public final int pEnd;
+ @Override
+ public boolean equals(Object obj)
+ {
+ if (obj == null || !(obj instanceof contactInterval))
+ {
+ return false;
+ }
+ contactInterval them = (contactInterval) obj;
+ return cStart == them.cStart && cEnd == them.cEnd && pEnd == them.pEnd
+ && pStart == them.pStart;
+ }
+ @Override
+ public String toString()
+ {
+ return "Contacts ["+cStart+","+cEnd+"] : Pixels ["+pStart+","+pEnd+"]";
+ }
}
/**
{
// TODO: turn into function on hiddenColumns and create test !!
Iterator<int[]> viscont = hiddenColumns.getVisContigsIterator(
- mappedRange[p], mappedRange[p + 1], false);
+ -1+mappedRange[p], -1+mappedRange[p + 1], false);
containsHidden = !viscont.hasNext();
if (!containsHidden)
{
}
else
{
- rowsel = columnSelection.intersects(mappedRange[p],
- mappedRange[p + 1]);
+ rowsel = columnSelection.intersects(-1+mappedRange[p],
+ -1+mappedRange[p + 1]);
}
}
return rowsel;
}
/**
+ * Return mapped cell intersecting pStart \
+ *
+ * FIXME: REDUNDANT METHOD - COULD DELETE FIXME: OR RE-IMPLEMENT AS EFFICIENT
+ * RANGE QUERY
*
* @param pStart
+ * [0..)
* @param pEnd
- * @return range for
+ * @return nearest full cell containing pStart - does not set
+ * contactInterval.pEnd or cEnd to equivalent position on pEnd !
*/
public contactInterval mapFor(int pStart, int pEnd)
{
- int cStart = (int) Math.floor(pStart * contacts_per_pixel);
- contactInterval ci = new contactInterval(cStart,
- (int) Math.min(contact_height,
- Math.ceil(
- cStart + (pEnd - pStart) * contacts_per_pixel)),
- pStart, pEnd);
-
- return ci;
+ if (pStart < 0)
+ {
+ pStart = 0;
+ }
+ if (pEnd < pStart)
+ {
+ pEnd = pStart;
+ }
+ if (pEnd >= graphHeight)
+ {
+ pEnd = graphHeight - 1;
+ }
+ if (pStart >= graphHeight)
+ {
+ pStart = graphHeight - pixels_step;
+ }
+ int step = Math.floorDiv(pStart, pixels_step);
+ return findStep(step);
+ }
+
+ /**
+ *
+ * @param step
+ * [0..) n steps covering height and contactHeight
+ * @return contactInterval for step, or null if out of bounds
+ */
+ contactInterval findStep(int step)
+ {
+ if (step < 0 || step > lastStep)
+ {
+ return null;
+ }
+ return new contactInterval((int) Math.floor(contacts_step * step),
+ -1 + (int) Math.min(contact_height,
+ Math.floor(contacts_step * (step + 1))),
+ pixels_step * step,
+ Math.min(graphHeight, (step + 1) * pixels_step) - 1);
}
/**
*/
public contactInterval mapFor(int pCentre)
{
- int pStart = Math.max(pCentre - pixels_step, 0);
- int pEnd = Math.min(pStart + pixels_step, graphHeight);
- int cStart = (int) Math.floor(pStart * contacts_per_pixel);
- contactInterval ci = new contactInterval(cStart,
- (int) Math.min(contact_height,
- Math.ceil(cStart + (pixels_step) * contacts_per_pixel)),
- pStart, pEnd);
-
- return ci;
+ if (pCentre >= graphHeight + pixels_step)
+ {
+ return null;
+ }
+ int step = Math.floorDiv(pCentre, pixels_step);
+ return findStep(step);
+ }
+
+ public List<contactInterval> allSteps()
+ {
+ contactInterval[] array = new contactInterval[lastStep + 1];
+ int csum = 0, psum = 0;
+ for (int i = 0; i <= lastStep; i++)
+ {
+ array[i] = findStep(i);
+ csum += 1 + array[i].cEnd - array[i].cStart;
+ psum += 1 + array[i].pEnd - array[i].pStart;
+ }
+ if (csum != contact_height || psum != graphHeight)
+ {
+ System.err.println("csum = " + csum + " not " + contact_height + "\n"
+ + "psum = " + psum + " not " + graphHeight);
+ return null;
+ }
+ return Arrays.asList(array);
}
public Iterator<contactInterval> iterateOverContactIntervals(
*/
Color selMinColor, selMaxColor;
+ /**
+ *
+ * @param no_data - colour when no data available
+ * @param hidden - colour if this row is hidden
+ * @param maxColor - colour for maximum value of contact
+ * @param minColor - colour for minimum value of contact
+ * @param selMinColor - min colour if the contact has been selected
+ * @param selMaxColor - max colour if contact is selected
+ */
public Shading(Color no_data, Color hidden, Color maxColor,
Color minColor, Color selMinColor, Color selMaxColor)
{
{
return new Shading(Color.pink, Color.red,
- new Color(246, 252, 243), new Color(0, 60, 26),
- new Color(26, 0, 60), new Color(243, 246, 252));
+ new Color(247, 252, 245), new Color(0, 68, 28),
+ new Color(28, 0, 68), new Color(245,247,252));
}
};
}
for (int ht = 0, botY = topY
- _aa.height; ht < _aa.graphHeight; ht += cgeom.pixels_step)
{
- ContactGeometry.contactInterval ci = cgeom.mapFor(ht,
- ht + cgeom.pixels_step);
+ ContactGeometry.contactInterval ci = cgeom.mapFor(ht);
// cstart = (int) Math.floor(((double) y2 - ht) * contacts_per_pixel);
// cend = (int) Math.min(contact_height,
// Math.ceil(cstart + contacts_per_pixel * pixels_step));
Color col;
- boolean rowsel = false, containsHidden = false;
+ boolean rowsel = false;
+ boolean containsHidden = false;
if (columnSelection != null)
{
rowsel = cgeom.intersects(ci, columnSelection, hiddenColumns,
g.setColor(col);
if (cgeom.pixels_step > 1)
{
- g.fillRect(x * charWidth, botY+ht, charWidth, 1 + cgeom.pixels_step);
+ g.fillRect(x * charWidth, botY+ht, charWidth, cgeom.pixels_step);
}
else
{
{
ContactRange cr = cl.getRangeFor(i, j);
// average for moment - probably more interested in maxIntProj though
- return jalview.util.ColorUtils.getGraduatedColour((float) cr.getMean(),
+ return jalview.util.ColorUtils.getGraduatedColour((float) cr.getMin(),
0, shade.selMinColor, max, shade.selMaxColor);
}
int indexpos = sm.getSeqPos(atom.getPdbResNum());
if (lastipos != indexpos || lastseq != sm.sequence)
{
- results.addResult(sm.sequence, indexpos, indexpos);
+ results.appendResult(sm.sequence, indexpos, indexpos);
lastipos = indexpos;
lastseq = sm.sequence;
// construct highlighted sequence list
}
/**
- * Bespoke method to format percentage float value to the specified number of
+ * Bespoke method to format a percentage (or any other) float value to the specified number of
* decimal places. Avoids use of general-purpose format parsers as a
* processing hotspot.
*
}
*/
- @Test(groups = "Functional", dataProvider = "cmdLines")
+ @Test(groups = {"Functional","testTask3"}, dataProvider = "cmdLines")
public void commandsOpenTest(String cmdLine, boolean cmdArgs,
int numFrames, String[] sequences)
{
@Test(
groups =
- { "Functional", "testTask1" },
+ { "Functional", "testTask3" },
dataProvider = "structureImageOutputFiles")
public void structureImageOutputTest(String cmdLine, String[] filenames)
throws IOException
Cache.loadProperties("test/jalview/bin/hidpiTestProps.jvprops");
Jalview.main(
new String[]
- { "-nosplash", "-nonews", "-noquestionnaire",
- "-nowebservicediscovery" });
+ { "--nosplash", "--nonews", "--noquestionnaire",
+ "--nowebservicediscovery" });
af = new FileLoader().LoadFileWaitTillLoaded("examples/uniref50.fa",
DataSourceType.FILE);
AlignmentI alForSeq = new Alignment(new SequenceI[] { alseq });
newaa = AlignmentUtils.addReferenceAnnotationTo(alForSeq, alseq, newaa,
null);
- ContactListI alcl = alForSeq.getContactListFor(newaa, 1);
+ // check for null on out of bounds
+ ContactListI alcl = alForSeq.getContactListFor(newaa, newaa.annotations.length);
+ assertNull(alcl,"Should've gotten null!");
+ // now check for mapping
+ alcl = alForSeq.getContactListFor(newaa, 1);
assertNotNull(alcl);
mappedCl = alcl.getMappedPositionsFor(0, 4);
assertNotNull(mappedCl);
assertFalse(m.contains(null, 3, 3));
}
+ @Test(groups = { "Functional" })
+ public void testMatchAdjacent()
+ {
+ SequenceI seq1 = new Sequence("", "abcdefghijklm");
+ SequenceI seq2 = new Sequence("", "abcdefghijklm");
+ SearchResultMatchI m = new SearchResults().new Match(seq1, 2, 5);
+
+ assertTrue(m.adjacent(seq1, 2, 5));
+ assertTrue(m.adjacent(seq1, 3, 5));
+ assertTrue(m.adjacent(seq1, 2, 4));
+ assertTrue(m.adjacent(seq1, 3, 3));
+
+ assertTrue(m.adjacent(seq1, 2, 6));
+ assertTrue(m.adjacent(seq1, 1, 5));
+ assertTrue(m.adjacent(seq1, 1, 8));
+ assertFalse(m.adjacent(seq1, 0, 0));
+ assertFalse(m.adjacent(seq1, 7, 8));
+ assertTrue(m.adjacent(seq1, 6, 8));
+ assertTrue(m.adjacent(seq1, 5, 8));
+ assertTrue(m.adjacent(seq1, 0, 1));
+
+
+ assertFalse(m.adjacent(seq2, 3, 3));
+ assertFalse(m.adjacent(null, 3, 3));
+ }
+
/**
* test markColumns for creating column selections
*/
}
/**
+ * Test to verify appending creates a minimal set of results
+ */
+ @Test(groups = { "Functional" })
+ public void testAppendResult()
+ {
+ SequenceI seq1 = new Sequence("", "abcdefghijklm"),seq2=new Sequence("","defdefdefdef");
+ SearchResultsI sr = new SearchResults();
+ sr.appendResult(seq1, 3, 5);
+ assertEquals(1, sr.getCount());
+ sr.appendResult(seq1, 3, 6);
+ assertEquals(1, sr.getCount());
+ sr.appendResult(seq1, 8, 8);
+ assertEquals(2, sr.getCount());
+ sr.appendResult(seq1, 7, 7);
+ assertEquals(1, sr.getCount());
+ sr.appendResult(seq2, 7, 7);
+ assertEquals(2, sr.getCount());
+ sr.appendResult(seq2, 2, 7);
+ assertTrue(sr.appendResult(seq2, 7, 49));
+ assertTrue(sr.appendResult(seq2, 0, 30));
+ assertEquals(2, sr.getCount());
+ int c=0;
+ for (SearchResultMatchI sre: sr.getResults())
+ {
+ c++;
+ }
+ assertEquals(c,2);
+
+ }
+ /**
* Test for method that checks if search results matches a sequence region
*/
@Test(groups = { "Functional" })
{
Jalview.main(
new String[]
- { "-noquestionnaire", "-nonews", "-props",
+ { "--noquestionnaire", "--nonews", "--props",
"test/jalview/ext/rbvi/chimera/testProps.jvprops" });
}
{
Jalview.main(
new String[]
- { "-noquestionnaire", "-nonews", "-props",
+ { "--noquestionnaire", "--nonews", "--props",
"test/jalview/ext/rbvi/chimera/testProps.jvprops" });
Cache.setProperty(Preferences.STRUCTURE_DISPLAY,
ViewerType.CHIMERA.name());
* use read-only test properties file
*/
Cache.loadProperties("test/jalview/io/testProps.jvprops");
- Jalview.main(new String[] { "-nonews" });
+ Jalview.main(new String[] { "--nonews" });
}
@AfterMethod(alwaysRun = true)
{
Jalview.main(
new String[]
- { "-nonews", "-props", "test/jalview/testProps.jvprops" });
+ { "--nonews", "--props", "test/jalview/testProps.jvprops" });
/*
* remove any sequence mappings left lying around by other tests
import static org.testng.Assert.assertNotEquals;
import static org.testng.Assert.assertNotNull;
+import java.awt.Container;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.FontMetrics;
{
Jalview.main(
new String[]
- { "-nonews", "-props", "test/jalview/testProps.jvprops" });
+ { "--nonews", "--props", "test/jalview/testProps.jvprops" });
Cache.applicationProperties.setProperty("SHOW_IDENTITY",
Boolean.TRUE.toString());
/**
* Test the variant of calculateIdWidth that computes the longest of any
* sequence name or annotation label width
+ * FIXME: JAL-4291: test needs updating for JAL-244 and JAL-4091
*/
- @Test(groups = "Functional")
+ @Test(groups = "Functional",enabled=false)
public void testCalculateIdWidth_withMaxWidth()
{
AlignViewportI av = af.alignPanel.getAlignViewport();
av.setShowAnnotation(false);
av.setIdWidth(18);
+ FontMetrics fmfor = new Container()
+ .getFontMetrics(new Font(af.viewport.font.getName(),
+ Font.ITALIC, af.viewport.font.getSize()));
+
/*
* note 4 pixels 'padding' are added to the longest seq name/annotation label
*/
Dimension d = af.alignPanel.calculateIdWidth(2000);
+ // Assumption ID_WIDTH_PADDING == 4
+ int expwidth = 3 + fmfor.stringWidth("Conservation");
+
assertEquals(d.width, 166); // 4 + pixel width of "Q93Z60_ARATH/1-118"
assertEquals(d.height, 12); // fixed value (not used?)
- assertEquals(av.getIdWidth(), 18); // not changed by this method
+ assertEquals(av.getIdWidth(), expwidth); // not changed by this method
/*
* make the longest sequence name longer
*/
AlignmentAnnotation aa = av.getAlignment().getAlignmentAnnotation()[0];
aa.label = "THIS IS A VERY LONG LABEL INDEED";
- FontMetrics fmfor = af.alignPanel
- .getFontMetrics(af.alignPanel.getAlabels().getFont());
- // Assumption ID_WIDTH_PADDING == 4
- int expwidth = 4 + fmfor.stringWidth(aa.label);
d = af.alignPanel.calculateIdWidth(2000);
+ // Assumption ID_WIDTH_PADDING == 3
+ expwidth = 3 + fmfor.stringWidth(aa.label);
+
assertEquals(d.width, expwidth); // 228 == ID_WIDTH_PADDING + pixel width of
// "THIS IS A VERY LONG LABEL INDEED"
assertEquals(d.height, 12);
* use read-only test properties file
*/
Cache.loadProperties("test/jalview/io/testProps.jvprops");
- Jalview.main(new String[] { "-nonews" });
+ Jalview.main(new String[] { "--nonews" });
}
@AfterMethod(alwaysRun = true)
* use read-only test properties file
*/
Cache.loadProperties("test/jalview/io/testProps.jvprops");
- Jalview.main(new String[] { "-nonews" });
+ Jalview.main(new String[] { "--nonews" });
}
@AfterMethod(alwaysRun = true)
{
Jalview.main(
new String[]
- { "-nonews", "-props", "test/jalview/testProps.jvprops" });
+ { "--nonews", "--props", "test/jalview/testProps.jvprops" });
String True = Boolean.TRUE.toString();
Cache.applicationProperties.setProperty("SHOW_ANNOTATIONS", True);
Cache.applicationProperties.setProperty("SHOW_QUALITY", True);
Jalview.main(
new String[]
- { "-nowebservicediscovery", "-nosplash", "-nonews" });
+ { "--nowebservicediscovery", "--nosplash", "--nonews" });
}
@AfterClass(alwaysRun = true)
* use read-only test properties file
*/
Cache.loadProperties("test/jalview/io/testProps.jvprops");
- Jalview.main(new String[] { "-nonews" });
+ Jalview.main(new String[] { "--nonews" });
}
}
* use read-only test properties file
*/
Cache.loadProperties("test/jalview/io/testProps.jvprops");
- Jalview.main(new String[] { "-nonews" });
+ Jalview.main(new String[] { "--nonews" });
}
/**
{
Jalview.main(
new String[]
- { "-nonews", "-props", "test/jalview/testProps.jvprops" });
+ { "--nonews", "--props", "test/jalview/testProps.jvprops" });
}
@BeforeMethod(alwaysRun = true)
{
jalview.bin.Jalview
.main(new String[]
- { "-props", "test/jalview/io/testProps.jvprops" });
+ { "--props", "test/jalview/io/testProps.jvprops" });
}
/**
{
jalview.bin.Jalview
.main(new String[]
- { "-props", "test/jalview/io/testProps.jvprops" });
+ { "--props", "test/jalview/io/testProps.jvprops" });
}
/**
appCache = AppCache.getInstance();
}
- @Test(groups = { "Functional" })
+ @Test(groups = { "Functional", "testTask2" })
public void getUserInputTest()
{
String userInput = cacheBox.getUserInput();
--- /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.renderer;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.assertNotEquals;
+import static org.testng.Assert.assertNotNull;
+import static org.testng.Assert.assertTrue;
+
+import org.testng.annotations.Test;
+
+import jalview.datamodel.AlignmentAnnotation;
+import jalview.datamodel.ColumnSelection;
+import jalview.datamodel.ContactListI;
+import jalview.datamodel.ContactRange;
+import jalview.datamodel.Mapping;
+import jalview.datamodel.SeqDistanceContactMatrix;
+import jalview.datamodel.Sequence;
+import jalview.datamodel.SequenceI;
+import jalview.util.MapList;
+import jalview.util.StringUtils;
+import jalview.ws.datamodel.MappableContactMatrixI;
+
+public class ContactGeometryTest
+{
+ @Test(groups="Functional")
+ public void testCoverageofRange()
+ {
+ // a really dumb test to make sure we really cover the requested pixel and
+ // contactList range for any dimension of each
+ for (int range = 12; range < 2000; range += 35)
+ {
+ StringBuilder sb = new StringBuilder();
+ while (sb.length() < range)
+ {
+ sb.append("c");
+ }
+ SequenceI sq = new Sequence("a", sb.toString());
+ MappableContactMatrixI cm = new SeqDistanceContactMatrix(range);
+ AlignmentAnnotation cm_aan = sq.addContactList(cm);
+ ContactListI cl = sq.getContactListFor(cm_aan, 10);
+ assertNotNull(cl);
+ for (int ht = range / 2; ht < range * 3; ht++)
+ {
+ ContactGeometry clgeom = new ContactGeometry(cl, ht);
+ assertNotNull(clgeom.allSteps());
+ }
+ }
+ }
+ @Test(groups = "Functional")
+ public void testContactGeometry()
+ {
+ SequenceI sq = new Sequence("a", "SSSQ");
+ MappableContactMatrixI cm = new SeqDistanceContactMatrix(4);
+ AlignmentAnnotation cm_aan = sq.addContactList(cm);
+ checkConsistencyFor(sq,cm_aan);
+ // Also check all is good when there's a sequence mapping involved
+ MappableContactMatrixI newcm=cm.liftOver(sq,
+ new Mapping(sq, new MapList(new int[]
+ { 1, 4 }, new int[] { 1, 4 }, 1, 1)));
+ AlignmentAnnotation mapped_cm = sq.addContactList(newcm);
+ checkConsistencyFor(sq,mapped_cm);
+ }
+ // Do some asserts for a sequence and a contact matrix
+ private void checkConsistencyFor(SequenceI sq, AlignmentAnnotation cm_aan)
+ {
+ int col=1;
+ ContactListI cl = sq.getContactListFor(cm_aan, col);
+ assertNotNull(cl);
+ assertEquals(cl.getContactHeight(),4);
+
+ // Map contacts 0 to 3 to a tiny range and check
+ ContactGeometry testee = new ContactGeometry(cl,2);
+ assertEquals(testee.contacts_per_pixel,2d);
+ ContactGeometry.contactInterval lastInterval = testee.mapFor(1);
+ assertEquals(lastInterval.cStart,2);
+ assertEquals(lastInterval.cEnd,3);
+ assertEquals(lastInterval.pStart,1);
+ assertEquals(lastInterval.pEnd,1);
+ ContactGeometry.contactInterval another = testee.mapFor(1,2);
+ assertEquals(lastInterval,another);
+ // Also check for a big pixel range
+ testee = new ContactGeometry(cl, 395);
+ lastInterval = testee.mapFor(390, 395); // 395 is one over limit.
+ assertNotNull(lastInterval);
+ assertEquals(lastInterval.cEnd,3);
+ assertEquals(lastInterval.pEnd,394);
+ // Map contacts 0 to 3 to Pixels 0-9, 10-19, 20-29, 30-39
+ testee = new ContactGeometry(cl, 40);
+
+ // verify mapping from pixel to contacts
+
+ // renderer thinks base 0 for pixel coordinates
+ // contact coordinates are base 1
+ for (int p = 0; p < 40; p++)
+ {
+ int expectC=(p / 10);
+ int expectP=(expectC)*10;
+ ContactGeometry.contactInterval ci_at = testee.mapFor(p),
+ ci_from = testee.mapFor(p, p);
+ assertNotNull(ci_at);
+ // mapFor and map should locate the same pixel window
+ assertEquals(ci_at.cStart, expectC,"Different cStart at position "+p);
+ assertEquals(ci_at.cEnd, expectC,"Different cEnd at position "+p);
+ assertEquals(ci_at.pStart,expectP, "Different pStart at position "+p);
+ assertEquals(ci_at.pEnd,expectP+9, "Different pEnd at position "+p);
+
+ assertEquals(ci_from,ci_at, "Different contactIntervals at position "+p);
+ // also test getRangeFor
+ ContactRange cr = cl.getRangeFor(ci_at.cStart, ci_at.cEnd);
+ assertEquals(cr.getFrom_column(),cr.getTo_column());
+ assertEquals((double) cr.getMean(),(double)Math.abs(col-cr.getFrom_column()), "Didn't resolve expected value at position "+p);
+ }
+
+ ContactGeometry.contactInterval ci_at0 = testee.mapFor(0);
+ ContactGeometry.contactInterval ci_at9 = testee.mapFor(9);
+ assertNotNull(ci_at9);
+
+ assertEquals(ci_at0,ci_at9);
+
+ // Adjacent cell
+ ContactGeometry.contactInterval ci_at10 = testee.mapFor(10);
+ assertNotNull(ci_at10);
+ ContactGeometry.contactInterval ci_at11 = testee.mapFor(11);
+ assertNotNull(ci_at11);
+
+ assertEquals(ci_at11,ci_at10,"Off-by-one in ContactGeometry mapping.");
+
+ assertNotEquals(ci_at0,ci_at10,"Expected adjacent cells to be not equal.");
+
+ // verify adjacent window is mapped
+ assertEquals(ci_at11.cStart,ci_at9.cStart+1);
+
+ assertEquals(ci_at9.cEnd+1,ci_at11.cStart);
+ assertEquals(ci_at9.cEnd+1,ci_at11.cEnd);
+
+ // verify interval/intersection
+ // column selection is base 0
+ ColumnSelection cs = new ColumnSelection();
+ cs.addElement(2);
+
+ boolean mask = false;
+ do
+ {
+ assertFalse(testee.intersects(ci_at0, cs, null, mask));
+ assertFalse(testee.intersects(ci_at11, cs, null, mask));
+ assertTrue(testee.intersects(testee.mapFor(21), cs, null, mask));
+ assertFalse(testee.intersects(testee.mapFor(31), cs, null, mask));
+ cs.addElement(3);
+ assertTrue(testee.intersects(testee.mapFor(31), cs, null, mask));
+ cs.removeElement(2);
+ assertFalse(testee.intersects(testee.mapFor(21), cs, null, mask));
+ mask = !mask;
+ } while (!mask);
+
+ }
+}
{
Jalview.main(
new String[]
- { "-nonews", "-props", "test/jalview/testProps.jvprops" });
+ { "--nonews", "--props", "test/jalview/testProps.jvprops" });
// codons for MCWHSE
String cdsSeq = ">cds\nATGtgtTGGcacTCAgaa";
* use read-only test properties file
*/
Cache.loadProperties("test/jalview/io/testProps.jvprops");
- Jalview.main(new String[] { "-nonews" });
+ Jalview.main(new String[] { "--nonews" });
}
@AfterClass(alwaysRun = true)