/** * */ package jalview.renderer; import java.awt.Color; import java.awt.Graphics; import jalview.api.AlignViewportI; import jalview.datamodel.AlignmentAnnotation; import jalview.datamodel.Annotation; import jalview.datamodel.ColumnSelection; import jalview.datamodel.ContactListI; import jalview.datamodel.ContactRange; import jalview.datamodel.HiddenColumns; import jalview.renderer.api.AnnotationRowRendererI; /** * @author jprocter * */ public class ContactMapRenderer implements AnnotationRowRendererI { @Override public void renderRow(Graphics g, int charWidth, int charHeight, boolean hasHiddenColumns, AlignViewportI viewport, HiddenColumns hiddenColumns, ColumnSelection columnSelection, AlignmentAnnotation _aa, Annotation[] aa_annotations, int sRes, int eRes, float min, float max, int y) { if (sRes > aa_annotations.length) { return; } eRes = Math.min(eRes, aa_annotations.length); int x = 0, y2 = y; g.setColor(Color.pink); g.drawLine(x, y2, (eRes - sRes) * charWidth, y2); int column; int aaMax = aa_annotations.length - 1; while (x < eRes - sRes) { column = sRes + x; if (hasHiddenColumns) { column = hiddenColumns.visibleToAbsoluteColumn(column); } // TODO: highlight columns selected boolean colsel = false; if (columnSelection != null) { colsel = columnSelection.contains(column); } if (column > aaMax) { break; } if (aa_annotations[column] == null) { x++; continue; } ContactListI contacts = viewport.getContactList(_aa, column); if (contacts == null) { x++; continue; } // Bean holding mapping from contact list to pixels final ContactGeometry cgeom = new ContactGeometry(contacts, _aa.graphHeight); for (int ht = y2, eht = y2 - _aa.graphHeight; ht >= eht; ht -= cgeom.pixels_step) { ContactGeometry.contactInterval ci = cgeom.mapFor(y2 - ht, y2 - ht + cgeom.pixels_step); // cstart = (int) Math.floor(((double) y2 - ht) * contacts_per_pixel); // cend = (int) Math.min(contact_height, // Math.ceil(cstart + contacts_per_pixel * pixels_step)); // TODO show maximum colour for range - sort of done // also need a 'getMaxPosForRange(start,end)' to accurately render Color col; boolean rowsel = false; if (columnSelection != null) { if (_aa.sequenceRef == null) { rowsel = columnSelection.intersects(ci.cStart, ci.cEnd); } else { // TODO check we have correctly mapped cstart to local sequence // numbering int s = _aa.sequenceRef.findIndex(ci.cStart); int e = _aa.sequenceRef.findIndex(ci.cEnd); if (s > 0 && s < _aa.sequenceRef.getLength()) { rowsel = columnSelection.intersects(s, e); } } } // TODO: show selected region if (colsel || rowsel) { col = getSelectedColorForRange(min, max, contacts, ci.cStart, ci.cEnd); if (colsel && rowsel) { col = new Color(col.getBlue(), col.getGreen(), col.getRed()); } else { col = new Color(col.getBlue(), col.getBlue(), col.getBlue()); } g.setColor(col); } else { col = getColorForRange(min, max, contacts, ci.cStart, ci.cEnd); g.setColor(col); } if (cgeom.pixels_step > 1) { g.fillRect(x * charWidth, ht, charWidth, 1 + cgeom.pixels_step); } else { g.drawLine(x * charWidth, ht, (x + 1) * charWidth, ht); } } x++; } } // Shading parameters // currently hardwired for alphafold Color maxColor = new Color(246, 252, 243), minColor = new Color(0, 60, 26), selMinColor = new Color(26, 0, 60), selMaxColor = new Color(243, 246, 252); Color shadeFor(float min, float max, float value) { return jalview.util.ColorUtils.getGraduatedColour(value, 0, minColor, max, maxColor); } public Color getColorForRange(float min, float max, ContactListI cl, int i, int j) { ContactRange cr = cl.getRangeFor(i, j); // average for moment - probably more interested in maxIntProj though return shadeFor(min, max, (float) cr.getMean()); } public Color getSelectedColorForRange(float min, float max, ContactListI cl, int i, int j) { ContactRange cr = cl.getRangeFor(i, j); // average for moment - probably more interested in maxIntProj though return jalview.util.ColorUtils.getGraduatedColour((float) cr.getMean(), 0, selMinColor, max, selMaxColor); } }