JAL-4124 decouple mappable contact matrix mapping logic from underlying contact matri...
authorJames Procter <j.procter@dundee.ac.uk>
Tue, 29 Aug 2023 17:23:57 +0000 (18:23 +0100)
committerJames Procter <j.procter@dundee.ac.uk>
Tue, 29 Aug 2023 17:23:57 +0000 (18:23 +0100)
src/jalview/datamodel/ContactMatrix.java
src/jalview/datamodel/ContactMatrixI.java
src/jalview/datamodel/FloatContactMatrix.java [new file with mode: 0644]
src/jalview/datamodel/GroupSetHolder.java [new file with mode: 0644]
src/jalview/datamodel/SeqDistanceContactMatrix.java
src/jalview/ws/datamodel/MappableContactMatrixI.java
src/jalview/ws/datamodel/alphafold/MappableContactMatrix.java
src/jalview/ws/datamodel/alphafold/PAEContactMatrix.java

index 48b6e6b..32fa5b1 100644 (file)
@@ -1,17 +1,12 @@
 package jalview.datamodel;
 
-import java.awt.Color;
-import java.math.BigInteger;
 import java.util.ArrayList;
-import java.util.BitSet;
-import java.util.HashMap;
 import java.util.List;
-import java.util.Spliterator;
 import java.util.StringTokenizer;
 
 import jalview.bin.Console;
 
-public abstract class ContactMatrix implements ContactMatrixI
+public abstract class ContactMatrix extends GroupSetHolder implements ContactMatrixI
 {
   /**
    * are contacts reflexive ?
@@ -107,26 +102,7 @@ public abstract class ContactMatrix implements ContactMatrixI
       @Override
       public double getContactAt(int column)
       {
-        List<Float> clist;
-        Float cl = null;
-        if (symmetric)
-        {
-          if (p < column)
-          {
-            clist = contacts.get(p);
-            cl = clist.get(column);
-          }
-          else
-          {
-            clist = contacts.get(column);
-            cl = clist.get(p);
-          }
-        }
-        else
-        {
-          clist = contacts.get(p);
-          cl = clist.get(column);
-        }
+        Float cl = getFloatElementAt(column, p);
         if (cl == null)
         {
           // return 0 not NaN ?
@@ -136,7 +112,41 @@ public abstract class ContactMatrix implements ContactMatrixI
       }
     });
   }
-
+  private Float getFloatElementAt(int column, int p)
+  {
+    
+    List<Float> clist;
+    Float cl = null;
+    if (symmetric)
+    {
+      if (p < column)
+      {
+        clist = contacts.get(p);
+        cl = clist.get(column);
+      }
+      else
+      {
+        clist = contacts.get(column);
+        cl = clist.get(p);
+      }
+    }
+    else
+    {
+      clist = contacts.get(p);
+      cl = clist.get(column);
+    }
+    return cl;
+  }
+  @Override
+  public double getElementAt(int column, int row)
+  {
+    Float cl = getFloatElementAt(column, row);
+    if (cl!=null)
+    {
+      return cl;
+    }
+    throw(new RuntimeException("Out of Bounds "+column+","+row));
+  }
   @Override
   public float getMin()
   {
@@ -160,17 +170,6 @@ public abstract class ContactMatrix implements ContactMatrixI
   {
     return "Contact Matrix";
   }
-  GroupSet grps = new GroupSet();
-  @Override
-  public GroupSetI getGroupSet()
-  {
-    return grps;
-  }
-  @Override
-  public void setGroupSet(GroupSet makeGroups)
-  {
-    grps = makeGroups;
-  }
   public static String contactToFloatString(ContactMatrixI cm)
   {
     StringBuilder sb = new StringBuilder();
index 925025f..4261519 100644 (file)
@@ -199,5 +199,17 @@ public interface ContactMatrixI
     }
     return Color.white;
   }
+
+  /**
+   * direct access to column and row position of matrix
+   
+   * Implementations are allowed to throw
+   * RunTimeExceptions if _column/i are out of bounds
+   * 
+   * @param column
+   * @param row
+   * @return
+   */
+  double getElementAt(int column, int row);
   
 }
diff --git a/src/jalview/datamodel/FloatContactMatrix.java b/src/jalview/datamodel/FloatContactMatrix.java
new file mode 100644 (file)
index 0000000..5fb156f
--- /dev/null
@@ -0,0 +1,133 @@
+package jalview.datamodel;
+
+public class FloatContactMatrix extends GroupSetHolder implements ContactMatrixI
+{
+
+  int maxrow = 0, maxcol = 0;
+
+
+  float[][] elements;
+
+  float maxscore;
+
+
+  public FloatContactMatrix(float[][] matrix)
+  {
+    maxcol = 0;
+    for (float[] row : matrix)
+    {
+      if (row.length > maxcol)
+      {
+        maxcol = row.length;
+      }
+      maxscore = row[0];
+      for (float f : row)
+      {
+        if (maxscore < f)
+        {
+          maxscore = f;
+        }
+      }
+    }
+    maxrow = matrix.length;
+    elements = matrix;
+  }
+
+  public FloatContactMatrix(float[][] elements2, GroupSet grps2)
+  {
+    this(elements2);
+    setGroupSet(grps2);
+  }
+
+  /**
+   * getContactList(column) @returns the vector of predicted alignment errors
+   * for reference position given by column
+   */
+  @Override
+  public ContactListI getContactList(final int column)
+  {
+    if (column < 0 || column >= elements.length)
+    {
+      return null;
+    }
+
+    return new ContactListImpl(new ContactListProviderI()
+    {
+      @Override
+      public int getPosition()
+      {
+        return column;
+      }
+
+      @Override
+      public int getContactHeight()
+      {
+        return maxcol - 1;
+      }
+
+      @Override
+      public double getContactAt(int mcolumn)
+      {
+        if (mcolumn < 0 || mcolumn >= elements[column].length)
+        {
+          return -1;
+        }
+        return elements[column][mcolumn];
+      }
+    });
+  }
+
+  /**
+   * getElementAt(column, i) @returns the predicted superposition error for the
+   * ith position when column is used as reference
+   */
+  @Override
+  public double getElementAt(int _column, int i)
+  {
+    return elements[_column][i];
+  }
+
+  @Override
+  public float getMin()
+  {
+    return 0;
+  }
+
+  @Override
+  public float getMax()
+  {
+    return maxscore;
+  }
+
+  @Override
+  public String getAnnotDescr()
+  {
+    // TODO Auto-generated method stub
+    return null;
+  }
+
+  @Override
+  public String getAnnotLabel()
+  {
+    // TODO Auto-generated method stub
+    return null;
+  }
+
+  @Override
+  public String getType()
+  {
+    return null;
+  }
+
+  @Override
+  public int getWidth()
+  {
+    return maxcol;
+  }
+
+  @Override
+  public int getHeight()
+  {
+    return maxrow;
+  }
+}
diff --git a/src/jalview/datamodel/GroupSetHolder.java b/src/jalview/datamodel/GroupSetHolder.java
new file mode 100644 (file)
index 0000000..faeb7c0
--- /dev/null
@@ -0,0 +1,24 @@
+package jalview.datamodel;
+
+/**
+ * holds a group set and provides getters and setters for ContactMatrixI
+ * implementations
+ * 
+ * @author jprocter
+ */
+public class GroupSetHolder
+{
+
+  GroupSet grps = new GroupSet();
+
+  public GroupSetI getGroupSet()
+  {
+    return grps;
+  }
+
+  public void setGroupSet(GroupSet makeGroups)
+  {
+    grps = makeGroups;
+  }
+
+}
index f8fd750..b04ac13 100644 (file)
@@ -114,7 +114,7 @@ public class SeqDistanceContactMatrix
     return width;
   }
   @Override
-  protected double getElementAt(int _column, int i)
+  public double getElementAt(int _column, int i)
   {
     return Math.abs(_column - i);
   }
index 9762428..3f294d0 100644 (file)
@@ -73,4 +73,6 @@ public interface MappableContactMatrixI extends ContactMatrixI
    * @return sequence position(s) corresponding to column in contact matrix
    */
   int[] getMappedPositionsFor(SequenceI localFrame, int from, int to);
+
+  ContactMatrixI getMappedMatrix();
 }
index d545741..cc96ac4 100644 (file)
@@ -7,6 +7,7 @@ import java.util.BitSet;
 import jalview.datamodel.ContactListI;
 import jalview.datamodel.ContactListImpl;
 import jalview.datamodel.ContactListProviderI;
+import jalview.datamodel.ContactMatrixI;
 import jalview.datamodel.GroupSet;
 import jalview.datamodel.GroupSetI;
 import jalview.datamodel.Mapping;
@@ -17,42 +18,77 @@ import jalview.ws.datamodel.MappableContactMatrixI;
 public abstract class MappableContactMatrix<T extends MappableContactMatrix<T>>
         implements MappableContactMatrixI
 {
-  SequenceI refSeq = null;
-
-  MapList toSeq = null;
-
   /**
-   * the length that refSeq is expected to be (excluding gaps, of course)
+   * the matrix that is being mapped to
    */
-  int length;
+  protected ContactMatrixI mappedMatrix=null;
+  
+  public ContactListI getContactList(int column)
+  {
+    return mappedMatrix.getContactList(column);
+  }
+
+  public float getMin()
+  {
+    return mappedMatrix.getMin();
+  }
+
+  public float getMax()
+  {
+    return mappedMatrix.getMax();
+  }
+
+  public int getWidth()
+  {
+    return mappedMatrix.getWidth();
+  }
+
+  public int getHeight()
+  {
+    return mappedMatrix.getHeight();
+  }
 
   @Override
-  public boolean hasReferenceSeq()
+  public ContactMatrixI getMappedMatrix()
   {
-    return (refSeq != null);
+    return mappedMatrix;
   }
+  
+  @Override
+  public GroupSetI getGroupSet()
+  {
+    return mappedMatrix.getGroupSet();
+  };
 
   @Override
-  public SequenceI getReferenceSeq()
+  public void setGroupSet(GroupSet makeGroups)
   {
-    return refSeq;
+    mappedMatrix.setGroupSet(makeGroups);
   }
+  
+  /**
+   * the sequence and how it is mapped to the matrix
+   */
+
+  SequenceI refSeq = null;
+
+  MapList toSeq = null;
 
   /**
-   * container for groups - defined on matrix columns
+   * the length that refSeq is expected to be (excluding gaps, of course)
    */
-  GroupSet grps = new GroupSet();
+  int length;
 
   @Override
-  public GroupSetI getGroupSet()
+  public boolean hasReferenceSeq()
   {
-    return grps;
-  };
+    return (refSeq != null);
+  }
 
   @Override
-  public void setGroupSet(GroupSet makeGroups)
+  public SequenceI getReferenceSeq()
   {
-    grps = makeGroups;
+    return refSeq;
   }
 
   @Override
@@ -439,7 +475,7 @@ public abstract class MappableContactMatrix<T extends MappableContactMatrix<T>>
   }
 
   /**
-   * get a specific element of the contact matrix in its data-local coordinates
+   * get a specific element of the underlying contact matrix in its data-local coordinates
    * rather than the mapped frame. Implementations are allowed to throw
    * RunTimeExceptions if _column/i are out of bounds
    * 
@@ -447,6 +483,8 @@ public abstract class MappableContactMatrix<T extends MappableContactMatrix<T>>
    * @param i
    * @return
    */
-  protected abstract double getElementAt(int _column, int i);
+  public double getElementAt(int _column, int i) {
+    return mappedMatrix.getElementAt(_column, i);
+  }
 
 }
index 22884f1..0c1f71a 100644 (file)
@@ -13,6 +13,7 @@ import jalview.datamodel.ContactListI;
 import jalview.datamodel.ContactListImpl;
 import jalview.datamodel.ContactListProviderI;
 import jalview.datamodel.ContactMatrixI;
+import jalview.datamodel.FloatContactMatrix;
 import jalview.datamodel.GroupSet;
 import jalview.datamodel.SequenceDummy;
 import jalview.datamodel.SequenceI;
@@ -41,14 +42,6 @@ public class PAEContactMatrix extends
 {
 
 
-  int maxrow = 0, maxcol = 0;
-
-
-  float[][] elements;
-
-  float maxscore;
-
-
   @SuppressWarnings("unchecked")
   public PAEContactMatrix(SequenceI _refSeq, Map<String, Object> pae_obj)
           throws FileFormatException
@@ -75,26 +68,8 @@ public class PAEContactMatrix extends
    */
   public PAEContactMatrix(SequenceI _refSeq, float[][] matrix)
   {
+    mappedMatrix=new FloatContactMatrix(matrix);
     setRefSeq(_refSeq);
-    maxcol = 0;
-    for (float[] row : matrix)
-    {
-      if (row.length > maxcol)
-      {
-        maxcol = row.length;
-      }
-      maxscore = row[0];
-      for (float f : row)
-      {
-        if (maxscore < f)
-        {
-          maxscore = f;
-        }
-      }
-    }
-    maxrow = matrix.length;
-    elements = matrix;
-
   }
 
   /**
@@ -108,20 +83,40 @@ public class PAEContactMatrix extends
   public PAEContactMatrix(SequenceI newRefSeq, MapList newFromMapList,
           float[][] elements2, GroupSet grps2)
   {
-    this(newRefSeq, elements2);
+    this(newRefSeq, new FloatContactMatrix(elements2,grps2));
+    toSeq = newFromMapList;
+  }
+
+  public PAEContactMatrix(SequenceI _refSeq,
+          ContactMatrixI floatContactMatrix)
+  {
+    mappedMatrix = floatContactMatrix;
+    setRefSeq(_refSeq);
+  }
+  public PAEContactMatrix(SequenceI _refSeq, MapList newFromMapList,
+          ContactMatrixI floatContactMatrix)
+  {
+    mappedMatrix = floatContactMatrix;
+    setRefSeq(_refSeq);
     toSeq = newFromMapList;
-    grps = grps2;
+  }
+  
+  @Override
+  protected PAEContactMatrix newMappableContactMatrix(SequenceI newRefSeq,
+          MapList newFromMapList)
+  {
+    return new PAEContactMatrix(newRefSeq, newFromMapList, mappedMatrix);
   }
 
   /**
-   * parse a sane JSON representation of the pAE
+   * parse a sane JSON representation of the pAE and update the mappedMatrix
    * 
    * @param pae_obj
    */
   @SuppressWarnings("unchecked")
   private void parse_version_2_pAE(Map<String, Object> pae_obj)
   {
-    maxscore = -1;
+    float maxscore = -1;
     // look for a maxscore element - if there is one...
     try
     {
@@ -134,7 +129,7 @@ public class PAEContactMatrix extends
     }
     List<List<Long>> scoreRows = ((List<List<Long>>) MapUtils
             .getFirst(pae_obj, "predicted_aligned_error", "pae"));
-    elements = new float[scoreRows.size()][scoreRows.size()];
+    float[][] elements = new float[scoreRows.size()][scoreRows.size()];
     int row = 0, col = 0;
     for (List<Long> scoreRow : scoreRows)
     {
@@ -160,8 +155,7 @@ public class PAEContactMatrix extends
       row++;
       col = 0;
     }
-    maxcol = length;
-    maxrow = length;
+    mappedMatrix=new FloatContactMatrix(elements);
   }
 
   /**
@@ -178,6 +172,8 @@ public class PAEContactMatrix extends
     Iterator<Long> rows = ((List<Long>) pae_obj.get("residue1")).iterator();
     Iterator<Long> cols = ((List<Long>) pae_obj.get("residue2")).iterator();
     // two pass - to allocate the elements array
+    
+    int maxrow=-1,maxcol=-1;
     while (rows.hasNext())
     {
       int row = rows.next().intValue();
@@ -196,7 +192,7 @@ public class PAEContactMatrix extends
     cols = ((List<Long>) pae_obj.get("residue2")).iterator();
     Iterator<Double> scores = ((List<Double>) pae_obj.get("distance"))
             .iterator();
-    elements = new float[maxcol][maxrow];
+    float[][] elements = new float[maxcol][maxrow];
     while (scores.hasNext())
     {
       float escore = scores.next().floatValue();
@@ -213,68 +209,7 @@ public class PAEContactMatrix extends
       elements[col - 1][row-1] = escore;
     }
 
-    maxscore = ((Double) MapUtils.getFirst(pae_obj,
-            "max_predicted_aligned_error", "max_pae")).floatValue();
-  }
-
-  /**
-   * getContactList(column) @returns the vector of predicted alignment errors
-   * for reference position given by column
-   */
-  @Override
-  public ContactListI getContactList(final int column)
-  {
-    if (column < 0 || column >= elements.length)
-    {
-      return null;
-    }
-
-    return new ContactListImpl(new ContactListProviderI()
-    {
-      @Override
-      public int getPosition()
-      {
-        return column;
-      }
-
-      @Override
-      public int getContactHeight()
-      {
-        return maxcol - 1;
-      }
-
-      @Override
-      public double getContactAt(int mcolumn)
-      {
-        if (mcolumn < 0 || mcolumn >= elements[column].length)
-        {
-          return -1;
-        }
-        return elements[column][mcolumn];
-      }
-    });
-  }
-
-  /**
-   * getElementAt(column, i) @returns the predicted superposition error for the
-   * ith position when column is used as reference
-   */
-  @Override
-  protected double getElementAt(int _column, int i)
-  {
-    return elements[_column][i];
-  }
-
-  @Override
-  public float getMin()
-  {
-    return 0;
-  }
-
-  @Override
-  public float getMax()
-  {
-    return maxscore;
+    mappedMatrix=new FloatContactMatrix(elements);
   }
 
   @Override
@@ -303,17 +238,7 @@ public class PAEContactMatrix extends
     return PAEMATRIX;
   }
 
-  @Override
-  public int getWidth()
-  {
-    return maxcol;
-  }
 
-  @Override
-  public int getHeight()
-  {
-    return maxrow;
-  }
   public static void validateContactMatrixFile(String fileName)
           throws FileFormatException, IOException
   {
@@ -343,12 +268,4 @@ public class PAEContactMatrix extends
               "No data in PAE matrix read from '" + fileName + "'");
     }
   }
-  @Override
-  protected PAEContactMatrix newMappableContactMatrix(SequenceI newRefSeq,
-          MapList newFromMapList)
-  {
-    PAEContactMatrix pae = new PAEContactMatrix(newRefSeq, newFromMapList,
-            elements, new GroupSet(grps));
-    return pae;
-  }
 }