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;
54 * @param no_data - colour when no data available
55 * @param hidden - colour if this row is hidden
56 * @param maxColor - colour for maximum value of contact
57 * @param minColor - colour for minimum value of contact
58 * @param selMinColor - min colour if the contact has been selected
59 * @param selMaxColor - max colour if contact is selected
61 public Shading(Color no_data, Color hidden, Color maxColor,
62 Color minColor, Color selMinColor, Color selMaxColor)
65 this.no_data = no_data;
67 this.maxColor = maxColor;
68 this.minColor = minColor;
69 this.selMinColor = selMinColor;
70 this.selMaxColor = selMaxColor;
78 * build an EBI-AlphaFold style renderer of PAE matrices
82 public static ContactMapRenderer newPAERenderer()
84 return new ContactMapRenderer()
87 public Shading getShade()
89 return new Shading(Color.pink, Color.red,
91 new Color(247, 252, 245), new Color(0, 68, 28),
92 new Color(28, 0, 68), new Color(245,247,252));
99 * @return instance of Shading used to initialise the renderer
101 public abstract Shading getShade();
103 public ContactMapRenderer()
105 this.shade = getShade();
109 public void renderRow(Graphics g, int charWidth, int charHeight,
110 boolean hasHiddenColumns, AlignViewportI viewport,
111 HiddenColumns hiddenColumns, ColumnSelection columnSelection,
112 AlignmentAnnotation _aa, Annotation[] aa_annotations, int sRes,
113 int eRes, float min, float max, int y)
115 if (sRes > aa_annotations.length)
119 eRes = Math.min(eRes, aa_annotations.length);
123 // uncomment below to render whole area of matrix as pink
124 // g.setColor(shade.no_data);
125 // g.fillRect(x, topY-_aa.height, (eRes - sRes) * charWidth, _aa.graphHeight);
127 boolean showGroups = _aa.isShowGroupsForContactMatrix();
129 int aaMax = aa_annotations.length - 1;
130 ContactMatrixI cm = viewport.getContactMatrix(_aa);
135 while (x < eRes - sRes)
138 if (hasHiddenColumns)
140 column = hiddenColumns.visibleToAbsoluteColumn(column);
142 // TODO: highlight columns selected
143 boolean colsel = false;
144 if (columnSelection != null)
146 colsel = columnSelection.contains(column);
154 if (aa_annotations[column] == null)
159 ContactListI contacts = viewport.getContactList(_aa, column);
160 if (contacts == null)
165 // ContactListI from viewport can map column -> group
166 Color gpcol = (cm == null) ? Color.white
167 : contacts.getColourForGroup(); // cm.getColourForGroup(cm.getGroupsFor(column));
168 // feature still in development - highlight or omit regions hidden in
169 // the alignment - currently marks them as red rows
170 boolean maskHiddenCols = false;
171 // TODO: optionally pass visible column mask to the ContactGeometry object
173 // only visible contacts to geometry
174 // Bean holding mapping from contact list to pixels
175 // TODO: allow bracketing/limiting of range on contacts to render (like
176 // visible column mask but more flexible?)
178 // COntactListI provides mapping for column -> cm-groupmapping
179 final ContactGeometry cgeom = new ContactGeometry(contacts,
182 for (int ht = 0, botY = topY
183 - _aa.height; ht < _aa.graphHeight; ht += cgeom.pixels_step)
185 ContactGeometry.contactInterval ci = cgeom.mapFor(ht);
186 // cstart = (int) Math.floor(((double) y2 - ht) * contacts_per_pixel);
187 // cend = (int) Math.min(contact_height,
188 // Math.ceil(cstart + contacts_per_pixel * pixels_step));
191 boolean rowsel = false;
192 boolean containsHidden = false;
193 if (columnSelection != null)
195 rowsel = cgeom.intersects(ci, columnSelection, hiddenColumns,
198 // TODO: show selected region
199 if (colsel || rowsel)
202 col = getSelectedColorForRange(min, max, contacts, ci.cStart,
204 if (colsel && rowsel)
206 col = new Color(col.getBlue(), col.getGreen(), col.getRed());
210 col = new Color(col.getBlue(), col.getBlue(), col.getBlue());
215 col = getColorForRange(min, max, contacts, ci.cStart, ci.cEnd);
221 if (showGroups && gpcol != null && gpcol != Color.white)
223 // todo - could overlay group as a transparent rectangle ?
225 (int) (((float) (col.getRed() + gpcol.getRed())) / 2f),
226 (int) (((float) (col.getGreen() + gpcol.getGreen()))
228 (int) (((float) (col.getBlue() + gpcol.getBlue())) / 2f));
231 if (cgeom.pixels_step > 1)
233 g.fillRect(x * charWidth, botY+ht, charWidth, cgeom.pixels_step);
237 g.drawLine(x * charWidth, botY+ht, (x + 1) * charWidth, botY+ht);
245 Color shadeFor(float min, float max, float value)
247 return jalview.util.ColorUtils.getGraduatedColour(value, 0,
248 shade.minColor, max, shade.maxColor);
251 public Color getColorForRange(float min, float max, ContactListI cl,
254 ContactRange cr = cl.getRangeFor(i, j);
255 // average for moment - probably more interested in maxIntProj though
256 return shadeFor(min, max, (float) cr.getMean());
259 public Color getSelectedColorForRange(float min, float max,
260 ContactListI cl, int i, int j)
262 ContactRange cr = cl.getRangeFor(i, j);
263 // average for moment - probably more interested in maxIntProj though
264 return jalview.util.ColorUtils.getGraduatedColour((float) cr.getMin(),
265 0, shade.selMinColor, max, shade.selMaxColor);