From e122bcdde6d11fd3711eda525924d0d737a4f62a Mon Sep 17 00:00:00 2001 From: James Procter Date: Fri, 24 Mar 2023 07:02:13 +0000 Subject: [PATCH] JAL-4158 first attempt at stashing colours for contact matrix groups and allowing them to be overlayed on the contact matrix visual. NEEDS TESTS! --- src/jalview/datamodel/ContactMatrix.java | 51 +++++++++++++++++++- src/jalview/datamodel/ContactMatrixI.java | 7 +++ .../datamodel/SeqDistanceContactMatrix.java | 41 ++++++++++++++++ src/jalview/gui/TreeCanvas.java | 49 ++++++++++++++++++- src/jalview/io/PContactPredictionFile.java | 1 + src/jalview/renderer/ContactMapRenderer.java | 10 ++++ .../ws/datamodel/alphafold/PAEContactMatrix.java | 30 +++++++++++- 7 files changed, 186 insertions(+), 3 deletions(-) diff --git a/src/jalview/datamodel/ContactMatrix.java b/src/jalview/datamodel/ContactMatrix.java index f2e207c..1b1889e 100644 --- a/src/jalview/datamodel/ContactMatrix.java +++ b/src/jalview/datamodel/ContactMatrix.java @@ -1,7 +1,10 @@ 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; @@ -171,7 +174,53 @@ public abstract class ContactMatrix implements ContactMatrixI { return "Contact Matrix"; } - + List groups=null; + @Override + public void updateGroups(List colGroups) + { + groups = colGroups; + colorMap=new HashMap<>(); + } + @Override + public boolean hasGroups() + { + return groups!=null && groups.size()>0; + } + @Override + public List getGroups() + { + return groups; + } + @Override + public BitSet getGroupsFor(int column) + { + for (BitSet gp:groups) { + if (gp.get(column)) + { + return gp; + } + } + return ContactMatrixI.super.getGroupsFor(column); + } + HashMap colorMap = new HashMap<>(); + @Override + public Color getColourForGroup(BitSet bs) + { + if (bs==null) { + return Color.white; + } + Color groupCol=colorMap.get(bs); + if (groupCol==null) + { + return Color.white; + } + return groupCol; + } + @Override + public void setColorForGroup(BitSet bs,Color color) + { + colorMap.put(bs,color); + } public static String contactToFloatString(ContactMatrixI cm) { StringBuilder sb = new StringBuilder(); diff --git a/src/jalview/datamodel/ContactMatrixI.java b/src/jalview/datamodel/ContactMatrixI.java index 9eabb10..1c169ef 100644 --- a/src/jalview/datamodel/ContactMatrixI.java +++ b/src/jalview/datamodel/ContactMatrixI.java @@ -1,5 +1,6 @@ package jalview.datamodel; +import java.awt.Color; import java.util.Arrays; import java.util.BitSet; import java.util.List; @@ -66,4 +67,10 @@ public interface ContactMatrixI default double getCutHeight() { return 0; } + + void updateGroups(List colGroups); + + void setColorForGroup(BitSet bs, Color color); + + default Color getColourForGroup(BitSet bs) { return Color.white;}; } diff --git a/src/jalview/datamodel/SeqDistanceContactMatrix.java b/src/jalview/datamodel/SeqDistanceContactMatrix.java index 731948b..c3f3670 100644 --- a/src/jalview/datamodel/SeqDistanceContactMatrix.java +++ b/src/jalview/datamodel/SeqDistanceContactMatrix.java @@ -1,5 +1,10 @@ package jalview.datamodel; +import java.awt.Color; +import java.util.BitSet; +import java.util.HashMap; +import java.util.List; + /** * Dummy contact matrix based on sequence distance * @@ -118,4 +123,40 @@ public class SeqDistanceContactMatrix implements ContactMatrixI { return width; } + private List groups=null; + @Override + public void updateGroups(List colGroups) + { + groups = colGroups; + } + @Override + public boolean hasGroups() + { + return groups!=null; + } + @Override + public List getGroups() + { + return groups; + } + + HashMap colorMap = new HashMap<>(); + @Override + public Color getColourForGroup(BitSet bs) + { + if (bs==null) { + return Color.white; + } + Color groupCol=colorMap.get(bs); + if (groupCol==null) + { + return Color.white; + } + return groupCol; + } + @Override + public void setColorForGroup(BitSet bs,Color color) + { + colorMap.put(bs,color); + } } diff --git a/src/jalview/gui/TreeCanvas.java b/src/jalview/gui/TreeCanvas.java index 7af8940..29826f0 100755 --- a/src/jalview/gui/TreeCanvas.java +++ b/src/jalview/gui/TreeCanvas.java @@ -36,7 +36,9 @@ import java.awt.print.PageFormat; import java.awt.print.Printable; import java.awt.print.PrinterException; import java.awt.print.PrinterJob; +import java.util.ArrayList; import java.util.BitSet; +import java.util.HashMap; import java.util.Hashtable; import java.util.List; import java.util.Map; @@ -51,8 +53,10 @@ import javax.swing.ToolTipManager; import jalview.analysis.Conservation; import jalview.analysis.TreeModel; import jalview.api.AlignViewportI; +import jalview.datamodel.AlignmentAnnotation; import jalview.datamodel.BinaryNode; import jalview.datamodel.ColumnSelection; +import jalview.datamodel.ContactMatrixI; import jalview.datamodel.HiddenColumns; import jalview.datamodel.Sequence; import jalview.datamodel.SequenceGroup; @@ -993,6 +997,8 @@ public class TreeCanvas extends JPanel implements MouseListener, Runnable, void colourGroups(List groups) { AlignmentPanel[] aps = getAssociatedPanels(); + List colGroups = new ArrayList<>(); + Map colors=new HashMap(); for (int i = 0; i < groups.size(); i++) { Color col = new Color((int) (Math.random() * 255), @@ -1003,7 +1009,25 @@ public class TreeCanvas extends JPanel implements MouseListener, Runnable, if (!tp.isColumnWise()) { createSeqGroupFor(aps, l, col); } else { - markColumnsFor(aps,l,col); + BitSet gp=createColumnGroupFor(l,col); + + colGroups.add(gp); + colors.put(gp, col); + } + } + if (tp.isColumnWise()) + { + AlignmentAnnotation aa = tp.getAssocAnnotation(); + if (aa!=null) { + ContactMatrixI cm = av.getContactMatrix(aa); + if (cm!=null) + { + cm.updateGroups(colGroups); + for (BitSet gp:colors.keySet()) + { + cm.setColorForGroup(gp, colors.get(gp)); + } + } } } @@ -1056,6 +1080,29 @@ public class TreeCanvas extends JPanel implements MouseListener, Runnable, } return false; } + + private BitSet createColumnGroupFor(Vector l, + Color col) + { + BitSet gp=new BitSet(); + for (BinaryNode bn:l) + { + int colm=-1; + if (bn.element()!=null && bn.element()instanceof Integer) + { colm = (Integer)bn.element(); + } else { + // parse out from nodename + try { + colm = Integer.parseInt(bn.getName().substring(bn.getName().indexOf("c")+1)); + } catch (Exception e) + { + continue; + } + } + gp.set(colm); + } + return gp; + } private void markColumnsFor(AlignmentPanel[] aps, Vector l, Color col) diff --git a/src/jalview/io/PContactPredictionFile.java b/src/jalview/io/PContactPredictionFile.java index e1ef021..3df9804 100644 --- a/src/jalview/io/PContactPredictionFile.java +++ b/src/jalview/io/PContactPredictionFile.java @@ -25,6 +25,7 @@ import jalview.datamodel.SequenceI; import java.io.IOException; import java.util.ArrayList; +import java.util.BitSet; import java.util.HashMap; import java.util.List; import java.util.Map; diff --git a/src/jalview/renderer/ContactMapRenderer.java b/src/jalview/renderer/ContactMapRenderer.java index 0a2278b..e54f471 100644 --- a/src/jalview/renderer/ContactMapRenderer.java +++ b/src/jalview/renderer/ContactMapRenderer.java @@ -12,6 +12,7 @@ import jalview.datamodel.AlignmentAnnotation; import jalview.datamodel.Annotation; import jalview.datamodel.ColumnSelection; import jalview.datamodel.ContactListI; +import jalview.datamodel.ContactMatrixI; import jalview.datamodel.ContactRange; import jalview.datamodel.HiddenColumns; import jalview.renderer.api.AnnotationRowRendererI; @@ -114,6 +115,7 @@ public abstract class ContactMapRenderer implements AnnotationRowRendererI int column; int aaMax = aa_annotations.length - 1; + ContactMatrixI cm = viewport.getContactMatrix(_aa); while (x < eRes - sRes) { column = sRes + x; @@ -144,6 +146,7 @@ public abstract class ContactMapRenderer implements AnnotationRowRendererI x++; continue; } + Color gpcol = (cm==null) ? Color.white: cm.getColourForGroup(cm.getGroupsFor(column)); // feature still in development - highlight or omit regions hidden in // the alignment - currently marks them as red rows boolean maskHiddenCols = false; @@ -213,7 +216,14 @@ public abstract class ContactMapRenderer implements AnnotationRowRendererI { col = shade.hidden; } + if (gpcol!=null && gpcol!=Color.white) { + // todo - could overlay group as a transparent rectangle ? + col = new Color((int)(((float)(col.getRed()+gpcol.getRed()))/2f), + (int)(((float)(col.getGreen()+gpcol.getGreen()))/2f), + (int)(((float)(col.getBlue()+gpcol.getBlue()))/2f)); + } g.setColor(col); + if (cgeom.pixels_step > 1) { g.fillRect(x * charWidth, ht, charWidth, 1 + cgeom.pixels_step); diff --git a/src/jalview/ws/datamodel/alphafold/PAEContactMatrix.java b/src/jalview/ws/datamodel/alphafold/PAEContactMatrix.java index 5fe27cc..41e677a 100644 --- a/src/jalview/ws/datamodel/alphafold/PAEContactMatrix.java +++ b/src/jalview/ws/datamodel/alphafold/PAEContactMatrix.java @@ -1,7 +1,9 @@ package jalview.ws.datamodel.alphafold; +import java.awt.Color; import java.util.ArrayList; import java.util.BitSet; +import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; @@ -309,7 +311,14 @@ public class PAEContactMatrix implements ContactMatrixI groups.add(gpset); } } - + @Override + public void updateGroups(List colGroups) + { + if (colGroups!=null) + { + groups=colGroups; + } + } @Override public BitSet getGroupsFor(int column) { @@ -322,6 +331,25 @@ public class PAEContactMatrix implements ContactMatrixI return ContactMatrixI.super.getGroupsFor(column); } + HashMap colorMap = new HashMap<>(); + @Override + public Color getColourForGroup(BitSet bs) + { + if (bs==null) { + return Color.white; + } + Color groupCol=colorMap.get(bs); + if (groupCol==null) + { + return Color.white; + } + return groupCol; + } + @Override + public void setColorForGroup(BitSet bs,Color color) + { + colorMap.put(bs,color); + } public void restoreGroups(List newgroups, String treeMethod, String tree, double thresh2) { -- 1.7.10.2