From d6e6893d922a0fca8fa0c716b714c162ad2b9714 Mon Sep 17 00:00:00 2001 From: James Procter Date: Thu, 31 Aug 2023 16:07:30 +0100 Subject: [PATCH] JAL-4124 MappableContactMatrix equivalence and hashCode ensuring non-redundant set of MappablePAE matrices are held on each dataset sequence --- src/jalview/datamodel/ContactMapHolder.java | 4 +- .../datamodel/alphafold/MappableContactMatrix.java | 21 ++++++++ .../ws/datamodel/alphafold/PAEContactMatrix.java | 10 ++++ test/jalview/project/Jalview2xmlTests.java | 50 ++++++++++++++++++++ 4 files changed, 84 insertions(+), 1 deletion(-) diff --git a/src/jalview/datamodel/ContactMapHolder.java b/src/jalview/datamodel/ContactMapHolder.java index af083dd..3a64917 100644 --- a/src/jalview/datamodel/ContactMapHolder.java +++ b/src/jalview/datamodel/ContactMapHolder.java @@ -3,6 +3,7 @@ package jalview.datamodel; import java.util.Collection; import java.util.Collections; import java.util.HashMap; +import java.util.HashSet; import java.util.Map; import jalview.ws.datamodel.MappableContactMatrixI; @@ -17,7 +18,8 @@ public class ContactMapHolder implements ContactMapHolderI { if (contactmaps != null && contactmaps.size() > 0) { - return contactmaps.values(); + // defensive copy, and return non redundant set of ContactMatrixI instances + return new HashSet(contactmaps.values()); } return Collections.EMPTY_LIST; } diff --git a/src/jalview/ws/datamodel/alphafold/MappableContactMatrix.java b/src/jalview/ws/datamodel/alphafold/MappableContactMatrix.java index cc96ac4..5f27a2c 100644 --- a/src/jalview/ws/datamodel/alphafold/MappableContactMatrix.java +++ b/src/jalview/ws/datamodel/alphafold/MappableContactMatrix.java @@ -487,4 +487,25 @@ public abstract class MappableContactMatrix> return mappedMatrix.getElementAt(_column, i); } + @Override + public int hashCode() + { + return 7 * (refSeq != null ? refSeq.hashCode() : 0) + + 11 * (toSeq != null ? toSeq.hashCode() : 0) + + 13 * (mappedMatrix != null ? mappedMatrix.hashCode() : 0) + + length * 3; + } + + @Override + public boolean equals(Object obj) + { + if (obj == null || !(obj.getClass().equals(getClass()))) + { + return false; + } + T them = (T) obj; + return mappedMatrix == them.mappedMatrix && length == them.length + && refSeq == them.refSeq && toSeq.equals(them.toSeq); + + } } diff --git a/src/jalview/ws/datamodel/alphafold/PAEContactMatrix.java b/src/jalview/ws/datamodel/alphafold/PAEContactMatrix.java index 0c1f71a..dcd2022 100644 --- a/src/jalview/ws/datamodel/alphafold/PAEContactMatrix.java +++ b/src/jalview/ws/datamodel/alphafold/PAEContactMatrix.java @@ -268,4 +268,14 @@ public class PAEContactMatrix extends "No data in PAE matrix read from '" + fileName + "'"); } } + @Override + public boolean equals(Object obj) + { + return super.equals(obj); + } + @Override + public int hashCode() + { + return super.hashCode(); + } } diff --git a/test/jalview/project/Jalview2xmlTests.java b/test/jalview/project/Jalview2xmlTests.java index c9532cc..38b27b1 100644 --- a/test/jalview/project/Jalview2xmlTests.java +++ b/test/jalview/project/Jalview2xmlTests.java @@ -47,6 +47,7 @@ import org.testng.AssertJUnit; import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; +import jalview.analysis.AlignmentUtils; import jalview.analysis.scoremodels.SimilarityParams; import jalview.api.AlignViewportI; import jalview.api.AlignmentViewPanel; @@ -1646,6 +1647,55 @@ public class Jalview2xmlTests extends Jalview2xmlBase Assert.assertEquals(restoredMat.getGroups(), dummyMat.getGroups()); Assert.assertEquals(restoredMat.hasTree(), dummyMat.hasTree()); Assert.assertEquals(restoredMat.getNewick(), dummyMat.getNewick()); + + // verify no duplicate PAE matrix data when new view created and saved + + // add reference annotations to view first, then copy + AlignmentUtils.addReferenceAnnotationTo(newAl, newAl.getSequenceAt(0), newSeq.getAnnotation()[0],null); + + AlignmentViewPanel newview = af.newView("copy of PAE", true); + + // redundant asserts here check all is good with the new view firest... + AlignmentI newviewAl = newview.getAlignment(); + SequenceI newviewSeq = newviewAl.getSequenceAt(0); + // check annotation of the expected type exists + Assert.assertEquals(newviewSeq.getAnnotation().length, 1); + Assert.assertEquals(newviewSeq.getAnnotation()[0].graph, paeCm.graph); + // check we have just one contact matrix mapping + Assert.assertEquals(newviewSeq.getContactMaps().size(), 1); + + // and can be found for the annotation on the sequence + ContactMatrixI newviewMat = newviewSeq + .getContactMatrixFor(newviewSeq.getAnnotation()[0]); + Assert.assertNotNull(newviewMat); + + Assert.assertTrue(newviewMat == restoredMat); + + // save the two views and restore. Now look at visible annotation to check all views have shared refs. + + tfile = File.createTempFile("testStoreAndRecoverPAEmatrixTwoViews", + ".jvp"); + new Jalview2XML(false).saveState(tfile); + Desktop.instance.closeAll_actionPerformed(null); + + af = new FileLoader().LoadFileWaitTillLoaded(tfile.getAbsolutePath(), + DataSourceType.FILE); + newAl = af.getAlignPanels().get(0).getAlignment(); + AlignmentAnnotation view1aa = newAl.getSequenceAt(0).getAnnotation()[0]; + + newviewAl = af.getAlignPanels().get(1).getAlignment(); + AlignmentAnnotation view2aa = newviewAl.getSequenceAt(0).getAnnotation()[0]; + + // annotations are shared across alignment views - so should still have an identical pair of annotations. + Assert.assertTrue(view1aa==view2aa); + // identical annotations means identical contact matrix mappings + Assert.assertEquals(newAl.getDataset().getSequenceAt(0).getContactMaps().size(), 1); + + Assert.assertTrue(view1aa!=view2aa); + restoredMat = newAl.getContactMatrixFor(view1aa); + newviewMat = newviewAl.getContactMatrixFor(view2aa); + Assert.assertTrue(restoredMat!=newviewMat); + } } -- 1.7.10.2