4 package jalview.renderer;
7 import java.awt.Graphics;
8 import java.util.Iterator;
10 import jalview.api.AlignViewportI;
11 import jalview.datamodel.AlignmentAnnotation;
12 import jalview.datamodel.Annotation;
13 import jalview.datamodel.ColumnSelection;
14 import jalview.datamodel.ContactListI;
15 import jalview.datamodel.ContactMatrixI;
16 import jalview.datamodel.ContactRange;
17 import jalview.datamodel.HiddenColumns;
18 import jalview.renderer.api.AnnotationRowRendererI;
24 public abstract class ContactMapRenderer implements AnnotationRowRendererI
27 * bean holding colours for shading
35 * shown when no data available from map
39 * shown for region not currently visible - should normally not see this
43 * linear shading scheme min/max
45 Color maxColor, minColor;
48 * linear shading scheme min/max for selected region
50 Color selMinColor, selMaxColor;
52 public Shading(Color no_data, Color hidden, Color maxColor,
53 Color minColor, Color selMinColor, Color selMaxColor)
56 this.no_data = no_data;
58 this.maxColor = maxColor;
59 this.minColor = minColor;
60 this.selMinColor = selMinColor;
61 this.selMaxColor = selMaxColor;
69 * build an EBI-AlphaFold style renderer of PAE matrices
73 public static ContactMapRenderer newPAERenderer()
75 return new ContactMapRenderer()
78 public Shading getShade()
80 return new Shading(Color.pink, Color.red,
82 new Color(246, 252, 243), new Color(0, 60, 26),
83 new Color(26, 0, 60), new Color(243, 246, 252));
90 * @return instance of Shading used to initialise the renderer
92 public abstract Shading getShade();
94 public ContactMapRenderer()
96 this.shade = getShade();
100 public void renderRow(Graphics g, int charWidth, int charHeight,
101 boolean hasHiddenColumns, AlignViewportI viewport,
102 HiddenColumns hiddenColumns, ColumnSelection columnSelection,
103 AlignmentAnnotation _aa, Annotation[] aa_annotations, int sRes,
104 int eRes, float min, float max, int y)
106 if (sRes > aa_annotations.length)
110 eRes = Math.min(eRes, aa_annotations.length);
114 g.setColor(shade.no_data);
116 g.drawLine(x, y2, (eRes - sRes) * charWidth, y2);
117 boolean showGroups = _aa.isShowGroupsForContactMatrix();
119 int aaMax = aa_annotations.length - 1;
120 ContactMatrixI cm = viewport.getContactMatrix(_aa);
121 while (x < eRes - sRes)
124 if (hasHiddenColumns)
126 column = hiddenColumns.visibleToAbsoluteColumn(column);
128 // TODO: highlight columns selected
129 boolean colsel = false;
130 if (columnSelection != null)
132 colsel = columnSelection.contains(column);
140 if (aa_annotations[column] == null)
145 ContactListI contacts = viewport.getContactList(_aa, column);
146 if (contacts == null)
151 // ContactListI from viewport can map column -> group
152 Color gpcol = (cm == null) ? Color.white
153 : contacts.getColourForGroup(); // cm.getColourForGroup(cm.getGroupsFor(column));
154 // feature still in development - highlight or omit regions hidden in
155 // the alignment - currently marks them as red rows
156 boolean maskHiddenCols = false;
157 // TODO: optionally pass visible column mask to the ContactGeometry object
159 // only visible contacts to geometry
160 // Bean holding mapping from contact list to pixels
161 // TODO: allow bracketing/limiting of range on contacts to render (like
162 // visible column mask but more flexible?)
164 // COntactListI provides mapping for column -> cm-groupmapping
165 final ContactGeometry cgeom = new ContactGeometry(contacts,
168 for (int ht = y2, eht = y2
169 - _aa.graphHeight; ht >= eht; ht -= cgeom.pixels_step)
171 ContactGeometry.contactInterval ci = cgeom.mapFor(y2 - ht,
172 y2 - ht + cgeom.pixels_step);
173 // cstart = (int) Math.floor(((double) y2 - ht) * contacts_per_pixel);
174 // cend = (int) Math.min(contact_height,
175 // Math.ceil(cstart + contacts_per_pixel * pixels_step));
178 boolean rowsel = false, containsHidden = false;
179 if (columnSelection != null)
181 rowsel = cgeom.intersects(ci, columnSelection, hiddenColumns,
184 // TODO: show selected region
185 if (colsel || rowsel)
188 col = getSelectedColorForRange(min, max, contacts, ci.cStart,
190 if (colsel && rowsel)
192 col = new Color(col.getBlue(), col.getGreen(), col.getRed());
196 col = new Color(col.getBlue(), col.getBlue(), col.getBlue());
201 col = getColorForRange(min, max, contacts, ci.cStart, ci.cEnd);
207 if (showGroups && gpcol != null && gpcol != Color.white)
209 // todo - could overlay group as a transparent rectangle ?
211 (int) (((float) (col.getRed() + gpcol.getRed())) / 2f),
212 (int) (((float) (col.getGreen() + gpcol.getGreen()))
214 (int) (((float) (col.getBlue() + gpcol.getBlue())) / 2f));
217 if (cgeom.pixels_step > 1)
219 g.fillRect(x * charWidth, ht, charWidth, 1 + cgeom.pixels_step);
223 g.drawLine(x * charWidth, ht, (x + 1) * charWidth, ht);
231 Color shadeFor(float min, float max, float value)
233 return jalview.util.ColorUtils.getGraduatedColour(value, 0,
234 shade.minColor, max, shade.maxColor);
237 public Color getColorForRange(float min, float max, ContactListI cl,
240 ContactRange cr = cl.getRangeFor(i, j);
241 // average for moment - probably more interested in maxIntProj though
242 return shadeFor(min, max, (float) cr.getMean());
245 public Color getSelectedColorForRange(float min, float max,
246 ContactListI cl, int i, int j)
248 ContactRange cr = cl.getRangeFor(i, j);
249 // average for moment - probably more interested in maxIntProj though
250 return jalview.util.ColorUtils.getGraduatedColour((float) cr.getMean(),
251 0, shade.selMinColor, max, shade.selMaxColor);