From: James Procter Date: Thu, 25 May 2023 15:28:36 +0000 (+0100) Subject: JAL-2381 copy and paste sequence also copies contact matrix annotation X-Git-Tag: Release_2_11_3_0~14^2~3^2^2~13 X-Git-Url: http://source.jalview.org/gitweb/?p=jalview.git;a=commitdiff_plain;h=19c22459dca6c69d6f1fd0eed029c01e21c99854 JAL-2381 copy and paste sequence also copies contact matrix annotation --- diff --git a/src/jalview/datamodel/Sequence.java b/src/jalview/datamodel/Sequence.java index 33c8ac5..32d295a 100755 --- a/src/jalview/datamodel/Sequence.java +++ b/src/jalview/datamodel/Sequence.java @@ -33,6 +33,8 @@ import java.util.Vector; import fr.orsay.lri.varna.models.rna.RNA; import jalview.analysis.AlignSeq; +import jalview.analysis.AlignmentUtils; +import jalview.analysis.SeqsetUtils; import jalview.datamodel.features.SequenceFeatures; import jalview.datamodel.features.SequenceFeaturesI; import jalview.util.Comparison; @@ -350,6 +352,11 @@ public class Sequence extends ASequence implements SequenceI { // only copy the given annotation AlignmentAnnotation newann = new AlignmentAnnotation(sqann[i]); + ContactMatrixI cm = seq.getContactMatrixFor(sqann[i]); + if (cm!=null) + { + addContactListFor(newann, cm); + } addAlignmentAnnotation(newann); } } @@ -1627,14 +1634,19 @@ public class Sequence extends ASequence implements SequenceI // sequence-column mapping datasetSequence.addAlignmentAnnotation(_aa); - // transfer contact matrices - ContactMatrixI cm = getContactMatrixFor(aa); - if (cm != null) - { - datasetSequence.addContactListFor(_aa, cm); + if (_cmholder != null) + { // transfer contact matrices + ContactMatrixI cm = _cmholder.getContactMatrixFor(aa); + if (cm != null) + { + datasetSequence.addContactListFor(_aa, cm); + datasetSequence.addContactListFor(aa, cm); + } } } } + // all matrices should have been transferred. so we clear the local holder + _cmholder=null; } return datasetSequence; } @@ -2119,30 +2131,56 @@ public class Sequence extends ASequence implements SequenceI //// //// Contact Matrix Holder Boilerplate //// - ContactMapHolderI cmholder = new ContactMapHolder(); + ContactMapHolderI _cmholder = null; + private ContactMapHolderI getContactMapHolder() + { + if (datasetSequence!=null) { + return ((Sequence)datasetSequence).getContactMapHolder(); + } + if (_cmholder==null) + { + _cmholder=new ContactMapHolder(); + } + return _cmholder; + } @Override public Collection getContactMaps() { - return cmholder.getContactMaps(); + return getContactMapHolder().getContactMaps(); } @Override public ContactMatrixI getContactMatrixFor(AlignmentAnnotation ann) { - return cmholder.getContactMatrixFor(ann); + return getContactMapHolder().getContactMatrixFor(ann); } @Override public ContactListI getContactListFor(AlignmentAnnotation _aa, int column) { - return cmholder.getContactListFor(_aa, column); + return getContactMapHolder().getContactListFor(_aa, column); } @Override public AlignmentAnnotation addContactList(ContactMatrixI cm) { - AlignmentAnnotation aa = cmholder.addContactList(cm); + AlignmentAnnotation aa; + + if (datasetSequence != null) + { + aa = datasetSequence.addContactList(cm); + // clone the annotation for the local sequence + aa = new AlignmentAnnotation(aa); + aa.restrict(start, end); + aa.adjustForAlignment(); + getContactMapHolder().addContactListFor(aa,cm); + addAlignmentAnnotation(aa); + return aa; + } + + // construct new annotation for matrix on dataset sequence + aa = getContactMapHolder().addContactList(cm); Annotation _aa[] = new Annotation[getLength()]; @@ -2166,6 +2204,6 @@ public class Sequence extends ASequence implements SequenceI public void addContactListFor(AlignmentAnnotation annotation, ContactMatrixI cm) { - cmholder.addContactListFor(annotation, cm); + getContactMapHolder().addContactListFor(annotation, cm); } } diff --git a/src/jalview/datamodel/SequenceGroup.java b/src/jalview/datamodel/SequenceGroup.java index b356894..81f8664 100755 --- a/src/jalview/datamodel/SequenceGroup.java +++ b/src/jalview/datamodel/SequenceGroup.java @@ -311,6 +311,11 @@ public class SequenceGroup implements AnnotatedCollectionI newannot.restrict(startRes, endRes); newannot.setSequenceRef(seqs[ipos]); newannot.adjustForAlignment(); + ContactMatrixI cm = seq.getContactMatrixFor(seq.getAnnotation()[a]); + if (cm!=null) + { + seqs[ipos].addContactListFor(newannot, cm); + } seqipos.addAlignmentAnnotation(newannot); } } diff --git a/src/jalview/datamodel/SequenceI.java b/src/jalview/datamodel/SequenceI.java index c789857..2e1daa3 100755 --- a/src/jalview/datamodel/SequenceI.java +++ b/src/jalview/datamodel/SequenceI.java @@ -415,7 +415,7 @@ public interface SequenceI extends ASequenceI, ContactMapHolderI /** * Derive a sequence (using this one's dataset or as the dataset) * - * @return duplicate sequence with valid dataset sequence + * @return duplicate sequence and any annotation present with valid dataset sequence */ public SequenceI deriveSequence(); diff --git a/src/jalview/gui/AlignFrame.java b/src/jalview/gui/AlignFrame.java index ae945fe..48927bb 100644 --- a/src/jalview/gui/AlignFrame.java +++ b/src/jalview/gui/AlignFrame.java @@ -2304,10 +2304,15 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener, .intValue(); } } - alignment.addAnnotation(sequences[i].getAnnotation()[a]); // annotation - // was - // duplicated - // earlier + // annotation was duplicated earlier + alignment.addAnnotation(sequences[i].getAnnotation()[a]); + // take care of contact matrix too + ContactMatrixI cm=sequences[i].getContactMatrixFor(sequences[i].getAnnotation()[a]); + if (cm!=null) + { + alignment.addContactListFor(sequences[i].getAnnotation()[a], cm); + } + alignment.setAnnotationIndex(sequences[i].getAnnotation()[a], a); } diff --git a/test/jalview/datamodel/SequenceTest.java b/test/jalview/datamodel/SequenceTest.java index 0151a12..344d74d 100644 --- a/test/jalview/datamodel/SequenceTest.java +++ b/test/jalview/datamodel/SequenceTest.java @@ -1052,6 +1052,38 @@ public class SequenceTest assertEquals("ABCDEF", derived.getDatasetSequence().getSequenceAsString()); } + + /** + * test that creating a copy of an existing sequence with dataset sequence and + * associated contact matrix yields annotation associated with the same + * contact matrix in the copy + */ + @Test(groups= {"Functional"}) + public void testCopyPasteStyleDerivesequence_withcontactMatrixAnn() + { + SequenceI seq1=new Sequence("seq1","ACDACDACD"); + seq1.createDatasetSequence(); + ContactMatrixI cm = new SeqDistanceContactMatrix(seq1.getLength()); + // addContactList needs to return annotation addable to the sequence reference it was called from + AlignmentAnnotation aann = seq1.addContactList(cm); + assertTrue(aann.sequenceRef==seq1); + assertEquals(1,seq1.getAnnotation().length); + assertNotNull(seq1.getContactListFor(seq1.getAnnotation()[0], 1)); + + SequenceI seq_derived=seq1.deriveSequence(); + assertEquals(1,seq_derived.getAnnotation().length); + assertTrue(cm==seq_derived.getContactMatrixFor(seq_derived.getAnnotation()[0])); + assertNotNull(seq_derived.getContactListFor(seq_derived.getAnnotation()[0], 1)); + + // copy paste actually uses the copy constructor .. so + + SequenceI seq_copied=new Sequence((Sequence)seq_derived); + assertEquals(1,seq_copied.getAnnotation().length); + assertTrue(cm==seq_copied.getContactMatrixFor(seq_copied.getAnnotation()[0])); + assertNotNull(seq_copied.getContactListFor(seq_copied.getAnnotation()[0], 1)); + + + } @Test(groups = { "Functional" }) public void testCopyConstructor_noDataset() diff --git a/test/jalview/gui/AlignViewportTest.java b/test/jalview/gui/AlignViewportTest.java index b3c6b2a..4537dcc 100644 --- a/test/jalview/gui/AlignViewportTest.java +++ b/test/jalview/gui/AlignViewportTest.java @@ -42,8 +42,10 @@ import jalview.datamodel.Alignment; import jalview.datamodel.AlignmentAnnotation; import jalview.datamodel.AlignmentI; import jalview.datamodel.Annotation; +import jalview.datamodel.ContactMatrixI; import jalview.datamodel.SearchResults; import jalview.datamodel.SearchResultsI; +import jalview.datamodel.SeqDistanceContactMatrix; import jalview.datamodel.Sequence; import jalview.datamodel.SequenceGroup; import jalview.datamodel.SequenceI; @@ -537,4 +539,29 @@ public class AlignViewportTest assertEquals(0, ranges.getStartSeq()); assertEquals(2, ranges.getEndSeq()); } + @Test(groups = {"Functional"}) + public void testGetSelectionAsNewSequences_withContactMatrices() + { + SequenceI seq = new Sequence("seq","ACADA"); + ContactMatrixI cmat = new SeqDistanceContactMatrix(5); + seq.addContactList(cmat); + Alignment al = new Alignment(new SequenceI[] {seq.deriveSequence() }); + al.addAnnotation(al.getSequenceAt(0).getAnnotation()[0]); + AlignFrame af = new AlignFrame(al,500,500); + + SequenceI selseqs[] = af.getViewport().getSelectionAsNewSequence(); + assertNotNull(selseqs[0].getAnnotation()); + assertNotNull(selseqs[0].getAnnotation()[0]); + assertEquals(cmat,selseqs[0].getContactMatrixFor(selseqs[0].getAnnotation()[0])); + + assertNotNull(selseqs[0].getContactListFor(selseqs[0].getAnnotation()[0], 2)); + + // now select everything and test again + af.selectAllSequenceMenuItem_actionPerformed(null); + selseqs = af.getViewport().getSelectionAsNewSequence(); + assertNotNull(selseqs[0].getAnnotation()); + assertNotNull(selseqs[0].getAnnotation()[0]); + assertEquals(cmat,selseqs[0].getContactMatrixFor(selseqs[0].getAnnotation()[0])); + assertNotNull(selseqs[0].getContactListFor(selseqs[0].getAnnotation()[0], 2)); + } }