- contactInterval.cStart/cEnd and pStart/pEnd are now base-0 inclusive ranges, always less than contactHeight and graphHeight
- change in mapFor behaviour so cStart/cEnd and pStart/pEnd are always just one mapped range, not as many as requested to cover mapFor(pFrom,pTo)
{
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);
}
}
}
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(
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
{
--- /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);
+
+ }
+}