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
34 * shown when no data available from map
38 * shown for region not currently visible - should normally not see this
42 * linear shading scheme min/max
44 Color maxColor, minColor;
47 * linear shading scheme min/max for selected region
49 Color selMinColor, selMaxColor;
51 public Shading(Color no_data, Color hidden, Color maxColor,
52 Color minColor, Color selMinColor, Color selMaxColor)
55 this.no_data = no_data;
57 this.maxColor = maxColor;
58 this.minColor = minColor;
59 this.selMinColor = selMinColor;
60 this.selMaxColor = selMaxColor;
68 * build an EBI-AlphaFold style renderer of PAE matrices
71 public static ContactMapRenderer newPAERenderer()
73 return new ContactMapRenderer()
76 public Shading getShade()
78 return new Shading(Color.pink, Color.red,
80 new Color(246, 252, 243), new Color(0, 60, 26),
81 new Color(26, 0, 60), new Color(243, 246, 252));
88 * @return instance of Shading used to initialise the renderer
90 public abstract Shading getShade();
92 public ContactMapRenderer()
94 this.shade = getShade();
98 public void renderRow(Graphics g, int charWidth, int charHeight,
99 boolean hasHiddenColumns, AlignViewportI viewport,
100 HiddenColumns hiddenColumns, ColumnSelection columnSelection,
101 AlignmentAnnotation _aa, Annotation[] aa_annotations, int sRes,
102 int eRes, float min, float max, int y)
104 if (sRes > aa_annotations.length)
108 eRes = Math.min(eRes, aa_annotations.length);
112 g.setColor(shade.no_data);
114 g.drawLine(x, y2, (eRes - sRes) * charWidth, y2);
117 int aaMax = aa_annotations.length - 1;
118 ContactMatrixI cm = viewport.getContactMatrix(_aa);
119 while (x < eRes - sRes)
122 if (hasHiddenColumns)
124 column = hiddenColumns.visibleToAbsoluteColumn(column);
126 // TODO: highlight columns selected
127 boolean colsel = false;
128 if (columnSelection != null)
130 colsel = columnSelection.contains(column);
138 if (aa_annotations[column] == null)
143 ContactListI contacts = viewport.getContactList(_aa, column);
144 if (contacts == null)
149 Color gpcol = (cm==null) ? Color.white: cm.getColourForGroup(cm.getGroupsFor(column));
150 // feature still in development - highlight or omit regions hidden in
151 // the alignment - currently marks them as red rows
152 boolean maskHiddenCols = false;
153 // TODO: pass visible column mask to the ContactGeometry object so it maps
154 // only visible contacts to geometry
155 // Bean holding mapping from contact list to pixels
156 final ContactGeometry cgeom = new ContactGeometry(contacts,
159 for (int ht = y2, eht = y2
160 - _aa.graphHeight; ht >= eht; ht -= cgeom.pixels_step)
162 ContactGeometry.contactInterval ci = cgeom.mapFor(y2 - ht,
163 y2 - ht + cgeom.pixels_step);
164 // cstart = (int) Math.floor(((double) y2 - ht) * contacts_per_pixel);
165 // cend = (int) Math.min(contact_height,
166 // Math.ceil(cstart + contacts_per_pixel * pixels_step));
169 boolean rowsel = false, containsHidden = false;
170 if (columnSelection != null)
172 if (_aa.sequenceRef == null)
174 rowsel = columnSelection.intersects(ci.cStart, ci.cEnd);
178 // TODO check we have correctly mapped cstart to local sequence
180 int s = _aa.sequenceRef.findIndex(ci.cStart);
181 int e = _aa.sequenceRef.findIndex(ci.cEnd);
182 if (maskHiddenCols && hasHiddenColumns)
184 // TODO: turn into function and create test !!
185 Iterator<int[]> viscont = hiddenColumns
186 .getVisContigsIterator(s, e, false);
187 containsHidden = !viscont.hasNext();
189 if (s > 0 && s < _aa.sequenceRef.getLength())
191 rowsel = columnSelection.intersects(s, e);
196 // TODO: show selected region
197 if (colsel || rowsel)
200 col = getSelectedColorForRange(min, max, contacts, ci.cStart,
202 if (colsel && rowsel)
204 col = new Color(col.getBlue(), col.getGreen(), col.getRed());
208 col = new Color(col.getBlue(), col.getBlue(), col.getBlue());
213 col = getColorForRange(min, max, contacts, ci.cStart, ci.cEnd);
219 if (gpcol!=null && gpcol!=Color.white) {
220 // todo - could overlay group as a transparent rectangle ?
221 col = new Color((int)(((float)(col.getRed()+gpcol.getRed()))/2f),
222 (int)(((float)(col.getGreen()+gpcol.getGreen()))/2f),
223 (int)(((float)(col.getBlue()+gpcol.getBlue()))/2f));
227 if (cgeom.pixels_step > 1)
229 g.fillRect(x * charWidth, ht, charWidth, 1 + cgeom.pixels_step);
233 g.drawLine(x * charWidth, ht, (x + 1) * charWidth, ht);
241 Color shadeFor(float min, float max, float value)
243 return jalview.util.ColorUtils.getGraduatedColour(value, 0, shade.minColor,
244 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.getMean(),
261 0, shade.selMinColor, max, shade.selMaxColor);