JAL-4124 MappableContactMatrix equivalence and hashCode ensuring non-redundant set...
authorJames Procter <j.procter@dundee.ac.uk>
Thu, 31 Aug 2023 15:07:30 +0000 (16:07 +0100)
committerJames Procter <j.procter@dundee.ac.uk>
Thu, 31 Aug 2023 15:07:30 +0000 (16:07 +0100)
src/jalview/datamodel/ContactMapHolder.java
src/jalview/ws/datamodel/alphafold/MappableContactMatrix.java
src/jalview/ws/datamodel/alphafold/PAEContactMatrix.java
test/jalview/project/Jalview2xmlTests.java

index af083dd..3a64917 100644 (file)
@@ -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<ContactMatrixI>(contactmaps.values());
     }
     return Collections.EMPTY_LIST;
   }
index cc96ac4..5f27a2c 100644 (file)
@@ -487,4 +487,25 @@ public abstract class MappableContactMatrix<T extends MappableContactMatrix<T>>
     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);
+
+  }
 }
index 0c1f71a..dcd2022 100644 (file)
@@ -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();
+  }
 }
index c9532cc..38b27b1 100644 (file)
@@ -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);
+    
   }
 
 }