package jalview.commands;
import static org.testng.AssertJUnit.assertEquals;
-import static org.testng.AssertJUnit.assertNull;
import static org.testng.AssertJUnit.assertSame;
+import static org.testng.AssertJUnit.assertTrue;
import jalview.commands.EditCommand.Action;
import jalview.commands.EditCommand.Edit;
* create sequence features before, after and overlapping
* a cut of columns/residues 4-7
*/
- SequenceI seq0 = seqs[0];
+ SequenceI seq0 = seqs[0]; // abcdefghjk/1-10
seq0.addSequenceFeature(new SequenceFeature("before", "", 1, 3, 0f,
null));
seq0.addSequenceFeature(new SequenceFeature("overlap left", "", 2, 6,
seq0.addSequenceFeature(new SequenceFeature("after", "", 8, 10, 0f,
null));
+ /*
+ * add some contact features
+ */
+ SequenceFeature internalContact = new SequenceFeature("disulphide bond", "", 5,
+ 6, 0f, null);
+ seq0.addSequenceFeature(internalContact); // should get deleted
+ SequenceFeature overlapLeftContact = new SequenceFeature(
+ "disulphide bond", "", 2, 6, 0f, null);
+ seq0.addSequenceFeature(overlapLeftContact); // should get deleted
+ SequenceFeature overlapRightContact = new SequenceFeature(
+ "disulphide bond", "", 5, 8, 0f, null);
+ seq0.addSequenceFeature(overlapRightContact); // should get deleted
+ SequenceFeature spanningContact = new SequenceFeature(
+ "disulphide bond", "", 2, 9, 0f, null);
+ seq0.addSequenceFeature(spanningContact); // should get shortened 3'
+
+ /*
+ * cut columns 3-6 (base 0), residues d-g 4-7
+ */
Edit ec = testee.new Edit(Action.CUT, seqs, 3, 4, al); // cols 3-6 base 0
EditCommand.cut(ec, new AlignmentI[] { al });
List<SequenceFeature> sfs = seq0.getSequenceFeatures();
SequenceFeatures.sortFeatures(sfs, true);
- assertEquals(4, sfs.size()); // feature internal to cut has been deleted
+ assertEquals(5, sfs.size()); // features internal to cut were deleted
SequenceFeature sf = sfs.get(0);
assertEquals("before", sf.getType());
assertEquals(1, sf.getBegin());
assertEquals(3, sf.getEnd());
sf = sfs.get(1);
+ assertEquals("disulphide bond", sf.getType());
+ assertEquals(2, sf.getBegin());
+ assertEquals(5, sf.getEnd()); // truncated by cut
+ sf = sfs.get(2);
assertEquals("overlap left", sf.getType());
assertEquals(2, sf.getBegin());
assertEquals(3, sf.getEnd()); // truncated by cut
- sf = sfs.get(2);
- assertEquals("overlap right", sf.getType());
- assertEquals(4, sf.getBegin()); // shifted left by cut
- assertEquals(5, sf.getEnd()); // truncated by cut
sf = sfs.get(3);
assertEquals("after", sf.getType());
assertEquals(4, sf.getBegin()); // shifted left by cut
assertEquals(6, sf.getEnd()); // shifted left by cut
+ sf = sfs.get(4);
+ assertEquals("overlap right", sf.getType());
+ assertEquals(4, sf.getBegin()); // shifted left by cut
+ assertEquals(4, sf.getEnd()); // truncated by cut
}
/**
{
String desc = String.format("%d-%d", from, to);
SequenceFeature sf = new SequenceFeature("test", desc, from, to,
- 0f,
- null);
+ 0f, null);
sf.setValue("from", Integer.valueOf(from));
sf.setValue("to", Integer.valueOf(to));
seq0.addSequenceFeature(sf);
*/
SequenceI[] sqs = new SequenceI[] { seq0 };
- // goal is to have this passing for all from/to values!!
- // for (int from = 0; from < seq0.getLength(); from++)
- // {
- // for (int to = from; to < seq0.getLength(); to++)
- for (int from = 1; from < 3; from++)
+ for (int from = 0; from < seq0.getLength(); from++)
{
- for (int to = 2; to < 3; to++)
+ for (int to = from; to < seq0.getLength(); to++)
{
testee.appendEdit(Action.CUT, sqs, from, (to - from + 1),
alignment, true);
* number of features within the cut region i.e. by
* func(length of cut)
*/
- String msg = String.format("Cut %d-%d ", from, to);
+ String msg = String.format("Cut %d-%d ", from + 1, to + 1);
if (to - from == 4)
{
- // all columns cut
- assertNull(sfs);
+ // all columns were cut
+ assertTrue(sfs.isEmpty());
}
else
{
/*
* inspect individual features
*/
- if (sfs != null)
+ for (SequenceFeature sf : sfs)
{
- for (SequenceFeature sf : sfs)
- {
- checkFeatureRelocation(sf, from + 1, to + 1);
- }
+ checkFeatureRelocation(sf, from + 1, to + 1, from > 0);
}
+
/*
* undo ready for next cut
*/
testee.undoCommand(new AlignmentI[] { alignment });
- assertEquals(func(5), seq0.getSequenceFeatures().size());
+ sfs = seq0.getSequenceFeatures();
+ assertEquals("After undo of " + msg, func(5), sfs.size());
+ verifyUndo(from, to, sfs);
}
}
}
/**
+ * Check that after Undo, every feature has start/end that match its original
+ * "start" and "end" properties
+ *
+ * @param from
+ * @param to
+ * @param sfs
+ */
+ protected void verifyUndo(int from, int to, List<SequenceFeature> sfs)
+ {
+ for (SequenceFeature sf : sfs)
+ {
+ final int oldFrom = ((Integer) sf.getValue("from")).intValue();
+ final int oldTo = ((Integer) sf.getValue("to")).intValue();
+ String msg = String.format(
+ "Undo cut of [%d-%d], feature at [%d-%d] ", from + 1, to + 1,
+ oldFrom, oldTo);
+ assertEquals(msg + "start", oldFrom, sf.getBegin());
+ assertEquals(msg + "end", oldTo, sf.getEnd());
+ }
+ }
+
+ /**
* Helper method to check a feature has been correctly relocated after a cut
*
* @param sf
* start of cut (first residue cut)
* @param to
* end of cut (last residue cut)
+ * @param newDataset
*/
- private void checkFeatureRelocation(SequenceFeature sf, int from, int to)
+ private void checkFeatureRelocation(SequenceFeature sf, int from, int to,
+ boolean newDataset)
{
// TODO handle the gapped sequence case as well
int cutSize = to - from + 1;
- int oldFrom = ((Integer) sf.getValue("from")).intValue();
- int oldTo = ((Integer) sf.getValue("to")).intValue();
+ final int oldFrom = ((Integer) sf.getValue("from")).intValue();
+ final int oldTo = ((Integer) sf.getValue("to")).intValue();
String msg = String.format(
"Feature %s relocated to %d-%d after cut of %d-%d",
else if (oldFrom > to)
{
// follows cut region - shift by size of cut
- assertEquals("3: " + msg, oldFrom - cutSize, sf.getBegin());
- assertEquals("4: " + msg, oldTo - cutSize, sf.getEnd());
+ assertEquals("3: " + msg, newDataset ? oldFrom - cutSize : oldFrom,
+ sf.getBegin());
+ assertEquals("4: " + msg, newDataset ? oldTo - cutSize : oldTo,
+ sf.getEnd());
}
else if (oldFrom < from && oldTo > to)
{
else if (oldTo > to)
{
// feature overlaps right side of cut region - truncated left
- assertEquals("8: " + msg, from, sf.getBegin());
- assertEquals("9: " + msg, from + oldTo - to - 1, sf.getEnd());
+ assertEquals("8: " + msg, newDataset ? from : to + 1, sf.getBegin());
+ assertEquals("9: " + msg, newDataset ? from + oldTo - to - 1 : oldTo,
+ sf.getEnd());
}
else
{
* Test a cut action's relocation of sequence features
*/
@Test(groups = { "Functional" })
- public void testCut_gappedWithFeatures()
+ public void testCut_withFeatures5prime()
{
+ SequenceI seq0 = new Sequence("seq/8-11", "A-BCC");
+ seq0.createDatasetSequence();
+ assertEquals(8, seq0.getStart());
+ seq0.addSequenceFeature(new SequenceFeature("", "", 10, 11, 0f,
+ null));
+ SequenceI[] seqsArray = new SequenceI[] { seq0 };
+ AlignmentI alignment = new Alignment(seqsArray);
+
/*
- * create sequence features before, after and overlapping
- * a cut of columns/residues 4-7
+ * cut columns of A-B; same dataset sequence is retained, aligned sequence
+ * start becomes 10
*/
- SequenceI seq0 = new Sequence("seq", "A-BCC");
- seq0.addSequenceFeature(new SequenceFeature("", "", 3, 4, 0f,
- null));
- AlignmentI alignment = new Alignment(new SequenceI[] { seq0 });
- // cut columns of A-B
- Edit ec = testee.new Edit(Action.CUT, seqs, 0, 3, alignment); // cols 0-3
- // base 0
+ Edit ec = testee.new Edit(Action.CUT, seqsArray, 0, 3, alignment);
EditCommand.cut(ec, new AlignmentI[] { alignment });
/*
- * feature on CC(3-4) should now be on CC(1-2)
+ * feature on CC(10-11) should still be on CC(10-11)
*/
+ assertSame(seq0, alignment.getSequenceAt(0));
+ assertEquals(10, seq0.getStart());
List<SequenceFeature> sfs = seq0.getSequenceFeatures();
assertEquals(1, sfs.size());
SequenceFeature sf = sfs.get(0);
- assertEquals(1, sf.getBegin());
- assertEquals(2, sf.getEnd());
+ assertEquals(10, sf.getBegin());
+ assertEquals(11, sf.getEnd());
// TODO add further cases including Undo - see JAL-2541
}