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);
131 while (x < eRes - sRes)
134 if (hasHiddenColumns)
136 column = hiddenColumns.visibleToAbsoluteColumn(column);
138 // TODO: highlight columns selected
139 boolean colsel = false;
140 if (columnSelection != null)
142 colsel = columnSelection.contains(column);
150 if (aa_annotations[column] == null)
155 ContactListI contacts = viewport.getContactList(_aa, column);
156 if (contacts == null)
161 // ContactListI from viewport can map column -> group
162 Color gpcol = (cm == null) ? Color.white
163 : contacts.getColourForGroup(); // cm.getColourForGroup(cm.getGroupsFor(column));
164 // feature still in development - highlight or omit regions hidden in
165 // the alignment - currently marks them as red rows
166 boolean maskHiddenCols = false;
167 // TODO: optionally pass visible column mask to the ContactGeometry object
169 // only visible contacts to geometry
170 // Bean holding mapping from contact list to pixels
171 // TODO: allow bracketing/limiting of range on contacts to render (like
172 // visible column mask but more flexible?)
174 // COntactListI provides mapping for column -> cm-groupmapping
175 final ContactGeometry cgeom = new ContactGeometry(contacts,
178 for (int ht = 0, botY = topY
179 - _aa.height; ht < _aa.graphHeight; ht += cgeom.pixels_step)
181 ContactGeometry.contactInterval ci = cgeom.mapFor(ht);
182 // cstart = (int) Math.floor(((double) y2 - ht) * contacts_per_pixel);
183 // cend = (int) Math.min(contact_height,
184 // Math.ceil(cstart + contacts_per_pixel * pixels_step));
187 boolean rowsel = false;
188 boolean containsHidden = false;
189 if (columnSelection != null)
191 rowsel = cgeom.intersects(ci, columnSelection, hiddenColumns,
194 // TODO: show selected region
195 if (colsel || rowsel)
198 col = getSelectedColorForRange(min, max, contacts, ci.cStart,
200 if (colsel && rowsel)
202 col = new Color(col.getBlue(), col.getGreen(), col.getRed());
206 col = new Color(col.getBlue(), col.getBlue(), col.getBlue());
211 col = getColorForRange(min, max, contacts, ci.cStart, ci.cEnd);
217 if (showGroups && gpcol != null && gpcol != Color.white)
219 // todo - could overlay group as a transparent rectangle ?
221 (int) (((float) (col.getRed() + gpcol.getRed())) / 2f),
222 (int) (((float) (col.getGreen() + gpcol.getGreen()))
224 (int) (((float) (col.getBlue() + gpcol.getBlue())) / 2f));
227 if (cgeom.pixels_step > 1)
229 g.fillRect(x * charWidth, botY+ht, charWidth, cgeom.pixels_step);
233 g.drawLine(x * charWidth, botY+ht, (x + 1) * charWidth, botY+ht);
241 Color shadeFor(float min, float max, float value)
243 return jalview.util.ColorUtils.getGraduatedColour(value, 0,
244 shade.minColor, max, shade.maxColor);
247 public Color getColorForRange(float min, float max, ContactListI cl,
250 ContactRange cr = cl.getRangeFor(i, j);
251 // average for moment - probably more interested in maxIntProj though
252 return shadeFor(min, max, (float) cr.getMean());
255 public Color getSelectedColorForRange(float min, float max,
256 ContactListI cl, int i, int j)
258 ContactRange cr = cl.getRangeFor(i, j);
259 // average for moment - probably more interested in maxIntProj though
260 return jalview.util.ColorUtils.getGraduatedColour((float) cr.getMin(),
261 0, shade.selMinColor, max, shade.selMaxColor);