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
40 * shown for region not currently visible - should normally not see this
45 * linear shading scheme min/max
47 Color maxColor, minColor;
50 * linear shading scheme min/max for selected region
52 Color selMinColor, selMaxColor;
57 * - colour when no data available
59 * - colour if this row is hidden
61 * - colour for maximum value of contact
63 * - colour for minimum value of contact
65 * - min colour if the contact has been selected
67 * - max colour if contact is selected
69 public Shading(Color no_data, Color hidden, Color maxColor,
70 Color minColor, Color selMinColor, Color selMaxColor)
73 this.no_data = no_data;
75 this.maxColor = maxColor;
76 this.minColor = minColor;
77 this.selMinColor = selMinColor;
78 this.selMaxColor = selMaxColor;
86 * build an EBI-AlphaFold style renderer of PAE matrices
90 public static ContactMapRenderer newPAERenderer()
92 return new ContactMapRenderer()
95 public Shading getShade()
97 return new Shading(Color.pink, Color.red,
99 new Color(247, 252, 245), new Color(0, 68, 28),
100 new Color(28, 0, 68), new Color(245, 247, 252));
107 * @return instance of Shading used to initialise the renderer
109 public abstract Shading getShade();
111 public ContactMapRenderer()
113 this.shade = getShade();
117 public void renderRow(Graphics g, int charWidth, int charHeight,
118 boolean hasHiddenColumns, AlignViewportI viewport,
119 HiddenColumns hiddenColumns, ColumnSelection columnSelection,
120 AlignmentAnnotation _aa, Annotation[] aa_annotations, int sRes,
121 int eRes, float min, float max, int y)
123 if (sRes > aa_annotations.length)
127 eRes = Math.min(eRes, aa_annotations.length);
131 // uncomment below to render whole area of matrix as pink
132 // g.setColor(shade.no_data);
133 // g.fillRect(x, topY-_aa.height, (eRes - sRes) * charWidth,
136 boolean showGroups = _aa.isShowGroupsForContactMatrix();
138 int aaMax = aa_annotations.length - 1;
139 ContactMatrixI cm = viewport.getContactMatrix(_aa);
144 while (x < eRes - sRes)
147 if (hasHiddenColumns)
149 column = hiddenColumns.visibleToAbsoluteColumn(column);
151 // TODO: highlight columns selected
152 boolean colsel = false;
153 if (columnSelection != null)
155 colsel = columnSelection.contains(column);
163 if (aa_annotations[column] == null)
168 ContactListI contacts = viewport.getContactList(_aa, column);
169 if (contacts == null)
174 // ContactListI from viewport can map column -> group
175 Color gpcol = (cm == null) ? Color.white
176 : contacts.getColourForGroup(); // cm.getColourForGroup(cm.getGroupsFor(column));
177 // feature still in development - highlight or omit regions hidden in
178 // the alignment - currently marks them as red rows
179 boolean maskHiddenCols = false;
180 // TODO: optionally pass visible column mask to the ContactGeometry object
182 // only visible contacts to geometry
183 // Bean holding mapping from contact list to pixels
184 // TODO: allow bracketing/limiting of range on contacts to render (like
185 // visible column mask but more flexible?)
187 // COntactListI provides mapping for column -> cm-groupmapping
188 final ContactGeometry cgeom = new ContactGeometry(contacts,
191 for (int ht = 0, botY = topY
192 - _aa.height; ht < _aa.graphHeight; ht += cgeom.pixels_step)
194 ContactGeometry.contactInterval ci = cgeom.mapFor(ht);
195 // cstart = (int) Math.floor(((double) y2 - ht) * contacts_per_pixel);
196 // cend = (int) Math.min(contact_height,
197 // Math.ceil(cstart + contacts_per_pixel * pixels_step));
200 boolean rowsel = false;
201 boolean containsHidden = false;
202 if (columnSelection != null)
204 rowsel = cgeom.intersects(ci, columnSelection, hiddenColumns,
207 // TODO: show selected region
208 if (colsel || rowsel)
211 col = getSelectedColorForRange(min, max, contacts, ci.cStart,
213 if (colsel && rowsel)
215 col = new Color(col.getBlue(), col.getGreen(), col.getRed());
219 col = new Color(col.getBlue(), col.getBlue(), col.getBlue());
224 col = getColorForRange(min, max, contacts, ci.cStart, ci.cEnd);
230 if (showGroups && gpcol != null && gpcol != Color.white)
232 // todo - could overlay group as a transparent rectangle ?
234 (int) (((float) (col.getRed() + gpcol.getRed())) / 2f),
235 (int) (((float) (col.getGreen() + gpcol.getGreen()))
237 (int) (((float) (col.getBlue() + gpcol.getBlue())) / 2f));
240 if (cgeom.pixels_step > 1)
242 g.fillRect(x * charWidth, botY + ht, charWidth,
247 g.drawLine(x * charWidth, botY + ht, (x + 1) * charWidth,
256 Color shadeFor(float min, float max, float value)
258 return jalview.util.ColorUtils.getGraduatedColour(value, 0,
259 shade.minColor, max, shade.maxColor);
262 public Color getColorForRange(float min, float max, ContactListI cl,
265 ContactRange cr = cl.getRangeFor(i, j);
266 // average for moment - probably more interested in maxIntProj though
267 return shadeFor(min, max, (float) cr.getMean());
270 public Color getSelectedColorForRange(float min, float max,
271 ContactListI cl, int i, int j)
273 ContactRange cr = cl.getRangeFor(i, j);
274 // average for moment - probably more interested in maxIntProj though
275 return jalview.util.ColorUtils.getGraduatedColour((float) cr.getMin(),
276 0, shade.selMinColor, max, shade.selMaxColor);