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 Color gpcol = (cm == null) ? Color.white
154 : cm.getColourForGroup(cm.getGroupsFor(column));
155 // feature still in development - highlight or omit regions hidden in
156 // the alignment - currently marks them as red rows
157 boolean maskHiddenCols = false;
158 // TODO: pass visible column mask to the ContactGeometry object so it maps
159 // only visible contacts to geometry
160 // Bean holding mapping from contact list to pixels
161 final ContactGeometry cgeom = new ContactGeometry(contacts,
164 for (int ht = y2, eht = y2
165 - _aa.graphHeight; ht >= eht; ht -= cgeom.pixels_step)
167 ContactGeometry.contactInterval ci = cgeom.mapFor(y2 - ht,
168 y2 - ht + cgeom.pixels_step);
169 // cstart = (int) Math.floor(((double) y2 - ht) * contacts_per_pixel);
170 // cend = (int) Math.min(contact_height,
171 // Math.ceil(cstart + contacts_per_pixel * pixels_step));
174 boolean rowsel = false, containsHidden = false;
175 if (columnSelection != null)
177 if (_aa.sequenceRef == null)
179 rowsel = columnSelection.intersects(ci.cStart, ci.cEnd);
183 // TODO check we have correctly mapped cstart to local sequence
185 int s = _aa.sequenceRef.findIndex(ci.cStart);
186 int e = _aa.sequenceRef.findIndex(ci.cEnd);
187 if (maskHiddenCols && hasHiddenColumns)
189 // TODO: turn into function and create test !!
190 Iterator<int[]> viscont = hiddenColumns
191 .getVisContigsIterator(s, e, false);
192 containsHidden = !viscont.hasNext();
194 if (s > 0 && s < _aa.sequenceRef.getLength())
196 rowsel = columnSelection.intersects(s, e);
201 // TODO: show selected region
202 if (colsel || rowsel)
205 col = getSelectedColorForRange(min, max, contacts, ci.cStart,
207 if (colsel && rowsel)
209 col = new Color(col.getBlue(), col.getGreen(), col.getRed());
213 col = new Color(col.getBlue(), col.getBlue(), col.getBlue());
218 col = getColorForRange(min, max, contacts, ci.cStart, ci.cEnd);
224 if (gpcol != null && gpcol != Color.white)
226 // todo - could overlay group as a transparent rectangle ?
228 (int) (((float) (col.getRed() + gpcol.getRed())) / 2f),
229 (int) (((float) (col.getGreen() + gpcol.getGreen()))
231 (int) (((float) (col.getBlue() + gpcol.getBlue())) / 2f));
235 if (cgeom.pixels_step > 1)
237 g.fillRect(x * charWidth, ht, charWidth, 1 + cgeom.pixels_step);
241 g.drawLine(x * charWidth, ht, (x + 1) * charWidth, ht);
249 Color shadeFor(float min, float max, float value)
251 return jalview.util.ColorUtils.getGraduatedColour(value, 0,
252 shade.minColor, max, shade.maxColor);
255 public Color getColorForRange(float min, float max, ContactListI cl,
258 ContactRange cr = cl.getRangeFor(i, j);
259 // average for moment - probably more interested in maxIntProj though
260 return shadeFor(min, max, (float) cr.getMean());
263 public Color getSelectedColorForRange(float min, float max,
264 ContactListI cl, int i, int j)
266 ContactRange cr = cl.getRangeFor(i, j);
267 // average for moment - probably more interested in maxIntProj though
268 return jalview.util.ColorUtils.getGraduatedColour((float) cr.getMean(),
269 0, shade.selMinColor, max, shade.selMaxColor);