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 // ContactListI from viewport can map column -> group
150 Color gpcol = (cm==null) ? Color.white: contacts.getColourForGroup(); // cm.getColourForGroup(cm.getGroupsFor(column));
152 // feature still in development - highlight or omit regions hidden in
153 // the alignment - currently marks them as red rows
154 boolean maskHiddenCols = false;
155 // TODO: optionally pass visible column mask to the ContactGeometry object so it maps
156 // only visible contacts to geometry
157 // Bean holding mapping from contact list to pixels
158 // TODO: allow bracketing/limiting of range on contacts to render (like visible column mask but more flexible?)
160 // COntactListI provides mapping for column -> cm-groupmapping
161 final ContactGeometry cgeom = new ContactGeometry(contacts,
164 for (int ht = y2, eht = y2
165 - _aa.graphHeight; ht >= eht; ht -= cgeom.pixels_step)
168 ContactGeometry.contactInterval ci = cgeom.mapFor(y2 - ht,
169 y2 - ht + cgeom.pixels_step);
170 // cstart = (int) Math.floor(((double) y2 - ht) * contacts_per_pixel);
171 // cend = (int) Math.min(contact_height,
172 // Math.ceil(cstart + contacts_per_pixel * pixels_step));
175 boolean rowsel = false, containsHidden = false;
176 if (columnSelection != null)
178 rowsel = cgeom.intersects(ci, columnSelection, hiddenColumns, maskHiddenCols);
180 // TODO: show selected region
181 if (colsel || rowsel)
184 col = getSelectedColorForRange(min, max, contacts, ci.cStart,
186 if (colsel && rowsel)
188 col = new Color(col.getBlue(), col.getGreen(), col.getRed());
192 col = new Color(col.getBlue(), col.getBlue(), col.getBlue());
197 col = getColorForRange(min, max, contacts, ci.cStart, ci.cEnd);
203 if (gpcol!=null && gpcol!=Color.white) {
204 // todo - could overlay group as a transparent rectangle ?
205 col = new Color((int)(((float)(col.getRed()+gpcol.getRed()))/2f),
206 (int)(((float)(col.getGreen()+gpcol.getGreen()))/2f),
207 (int)(((float)(col.getBlue()+gpcol.getBlue()))/2f));
211 if (cgeom.pixels_step > 1)
213 g.fillRect(x * charWidth, ht, charWidth, 1 + cgeom.pixels_step);
217 g.drawLine(x * charWidth, ht, (x + 1) * charWidth, ht);
225 Color shadeFor(float min, float max, float value)
227 return jalview.util.ColorUtils.getGraduatedColour(value, 0, shade.minColor,
228 max, shade.maxColor);
231 public Color getColorForRange(float min, float max, ContactListI cl,
234 ContactRange cr = cl.getRangeFor(i, j);
235 // average for moment - probably more interested in maxIntProj though
236 return shadeFor(min, max, (float) cr.getMean());
239 public Color getSelectedColorForRange(float min, float max,
240 ContactListI cl, int i, int j)
242 ContactRange cr = cl.getRangeFor(i, j);
243 // average for moment - probably more interested in maxIntProj though
244 return jalview.util.ColorUtils.getGraduatedColour((float) cr.getMean(),
245 0, shade.selMinColor, max, shade.selMaxColor);