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;
54 public Shading(Color no_data, Color hidden, Color maxColor,
55 Color minColor, Color selMinColor, Color selMaxColor)
58 this.no_data = no_data;
60 this.maxColor = maxColor;
61 this.minColor = minColor;
62 this.selMinColor = selMinColor;
63 this.selMaxColor = selMaxColor;
71 * build an EBI-AlphaFold style renderer of PAE matrices
75 public static ContactMapRenderer newPAERenderer()
77 return new ContactMapRenderer()
80 public Shading getShade()
82 return new Shading(Color.pink, Color.red,
84 new Color(246, 252, 243), new Color(0, 60, 26),
85 new Color(26, 0, 60), new Color(243, 246, 252));
92 * @return instance of Shading used to initialise the renderer
94 public abstract Shading getShade();
96 public ContactMapRenderer()
98 this.shade = getShade();
102 public void renderRow(Graphics g, int charWidth, int charHeight,
103 boolean hasHiddenColumns, AlignViewportI viewport,
104 HiddenColumns hiddenColumns, ColumnSelection columnSelection,
105 AlignmentAnnotation _aa, Annotation[] aa_annotations, int sRes,
106 int eRes, float min, float max, int y)
108 if (sRes > aa_annotations.length)
112 eRes = Math.min(eRes, aa_annotations.length);
116 g.setColor(shade.no_data);
118 g.drawLine(x, y2, (eRes - sRes) * charWidth, y2);
121 int aaMax = aa_annotations.length - 1;
122 ContactMatrixI cm = viewport.getContactMatrix(_aa);
123 while (x < eRes - sRes)
126 if (hasHiddenColumns)
128 column = hiddenColumns.visibleToAbsoluteColumn(column);
130 // TODO: highlight columns selected
131 boolean colsel = false;
132 if (columnSelection != null)
134 colsel = columnSelection.contains(column);
142 if (aa_annotations[column] == null)
147 ContactListI contacts = viewport.getContactList(_aa, column);
148 if (contacts == null)
153 // ContactListI from viewport can map column -> group
154 Color gpcol = (cm == null) ? Color.white
155 : contacts.getColourForGroup(); // cm.getColourForGroup(cm.getGroupsFor(column));
157 // feature still in development - highlight or omit regions hidden in
158 // the alignment - currently marks them as red rows
159 boolean maskHiddenCols = false;
160 // TODO: optionally pass visible column mask to the ContactGeometry object
162 // only visible contacts to geometry
163 // Bean holding mapping from contact list to pixels
164 // TODO: allow bracketing/limiting of range on contacts to render (like
165 // visible column mask but more flexible?)
167 // COntactListI provides mapping for column -> cm-groupmapping
168 final ContactGeometry cgeom = new ContactGeometry(contacts,
171 for (int ht = y2, eht = y2
172 - _aa.graphHeight; ht >= eht; ht -= cgeom.pixels_step)
175 ContactGeometry.contactInterval ci = cgeom.mapFor(y2 - ht,
176 y2 - ht + cgeom.pixels_step);
177 // cstart = (int) Math.floor(((double) y2 - ht) * contacts_per_pixel);
178 // cend = (int) Math.min(contact_height,
179 // Math.ceil(cstart + contacts_per_pixel * pixels_step));
182 boolean rowsel = false, containsHidden = false;
183 if (columnSelection != null)
185 rowsel = cgeom.intersects(ci, columnSelection, hiddenColumns,
188 // TODO: show selected region
189 if (colsel || rowsel)
192 col = getSelectedColorForRange(min, max, contacts, ci.cStart,
194 if (colsel && rowsel)
196 col = new Color(col.getBlue(), col.getGreen(), col.getRed());
200 col = new Color(col.getBlue(), col.getBlue(), col.getBlue());
205 col = getColorForRange(min, max, contacts, ci.cStart, ci.cEnd);
211 if (gpcol != null && gpcol != Color.white)
213 // todo - could overlay group as a transparent rectangle ?
215 (int) (((float) (col.getRed() + gpcol.getRed())) / 2f),
216 (int) (((float) (col.getGreen() + gpcol.getGreen()))
218 (int) (((float) (col.getBlue() + gpcol.getBlue())) / 2f));
222 if (cgeom.pixels_step > 1)
224 g.fillRect(x * charWidth, ht, charWidth, 1 + cgeom.pixels_step);
228 g.drawLine(x * charWidth, ht, (x + 1) * charWidth, ht);
236 Color shadeFor(float min, float max, float value)
238 return jalview.util.ColorUtils.getGraduatedColour(value, 0,
239 shade.minColor, max, shade.maxColor);
242 public Color getColorForRange(float min, float max, ContactListI cl,
245 ContactRange cr = cl.getRangeFor(i, j);
246 // average for moment - probably more interested in maxIntProj though
247 return shadeFor(min, max, (float) cr.getMean());
250 public Color getSelectedColorForRange(float min, float max,
251 ContactListI cl, int i, int j)
253 ContactRange cr = cl.getRangeFor(i, j);
254 // average for moment - probably more interested in maxIntProj though
255 return jalview.util.ColorUtils.getGraduatedColour((float) cr.getMean(),
256 0, shade.selMinColor, max, shade.selMaxColor);