/* * 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 . * 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); } }