X-Git-Url: http://source.jalview.org/gitweb/?a=blobdiff_plain;f=src%2Fjalview%2Frenderer%2FContactMapRenderer.java;h=9f0cc3507590a848c250cea77f9b99419455fb38;hb=4a28fee3e0c129a01268d26e1396b045bd893fb8;hp=7a052da6e6d6e0d07d98de38e15d2905e3280277;hpb=b4940c3adf6345861921c7abdf948e0a0c9beb61;p=jalview.git diff --git a/src/jalview/renderer/ContactMapRenderer.java b/src/jalview/renderer/ContactMapRenderer.java index 7a052da..9f0cc35 100644 --- a/src/jalview/renderer/ContactMapRenderer.java +++ b/src/jalview/renderer/ContactMapRenderer.java @@ -1,33 +1,140 @@ -/** +/* + * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$) + * Copyright (C) $$Year-Rel$$ The Jalview Authors + * + * This file is part of Jalview. * + * Jalview is free software: you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, either version 3 + * of the License, or (at your option) any later version. + * + * Jalview is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Jalview. If not, see . + * The Jalview Authors are detailed in the 'AUTHORS' file. */ 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.ContactMatrixI; import jalview.datamodel.ContactRange; import jalview.datamodel.HiddenColumns; import jalview.renderer.api.AnnotationRowRendererI; -import java.awt.Color; -import java.awt.Graphics; - /** * @author jprocter * */ -public class ContactMapRenderer implements AnnotationRowRendererI +public abstract class ContactMapRenderer implements AnnotationRowRendererI { + /** + * bean holding colours for shading + * + * @author jprocter + * + */ + public class Shading + { + /** + * shown when no data available from map + */ + Color no_data; + + /** + * shown for region not currently visible - should normally not see this + */ + Color hidden; + + /** + * linear shading scheme min/max + */ + Color maxColor, minColor; + + /** + * linear shading scheme min/max for selected region + */ + Color selMinColor, selMaxColor; + + /** + * + * @param no_data + * - colour when no data available + * @param hidden + * - colour if this row is hidden + * @param maxColor + * - colour for maximum value of contact + * @param minColor + * - colour for minimum value of contact + * @param selMinColor + * - min colour if the contact has been selected + * @param selMaxColor + * - max colour if contact is selected + */ + public Shading(Color no_data, Color hidden, Color maxColor, + Color minColor, Color selMinColor, Color selMaxColor) + { + super(); + this.no_data = no_data; + this.hidden = hidden; + this.maxColor = maxColor; + this.minColor = minColor; + this.selMinColor = selMinColor; + this.selMaxColor = selMaxColor; + } + + } + + final Shading shade; + + /** + * build an EBI-AlphaFold style renderer of PAE matrices + * + * @return + */ + public static ContactMapRenderer newPAERenderer() + { + return new ContactMapRenderer() + { + @Override + public Shading getShade() + { + return new Shading(Color.pink, Color.red, + + new Color(247, 252, 245), new Color(0, 68, 28), + new Color(28, 0, 68), new Color(245, 247, 252)); + } + }; + } + + /** + * + * @return instance of Shading used to initialise the renderer + */ + public abstract Shading getShade(); + + public ContactMapRenderer() + { + this.shade = getShade(); + } @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) + 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) { @@ -35,14 +142,21 @@ public class ContactMapRenderer implements AnnotationRowRendererI } eRes = Math.min(eRes, aa_annotations.length); - int x = 0, y2 = y; + int x = 0, topY = y; - g.setColor(Color.pink); - - g.drawLine(x, y2, (eRes - sRes) * charWidth, y2); + // uncomment below to render whole area of matrix as pink + // g.setColor(shade.no_data); + // g.fillRect(x, topY-_aa.height, (eRes - sRes) * charWidth, + // _aa.graphHeight); + boolean showGroups = _aa.isShowGroupsForContactMatrix(); int column; int aaMax = aa_annotations.length - 1; + ContactMatrixI cm = viewport.getContactMatrix(_aa); + if (cm == null) + { + return; + } while (x < eRes - sRes) { column = sRes + x; @@ -50,12 +164,12 @@ public class ContactMapRenderer implements AnnotationRowRendererI { column = hiddenColumns.visibleToAbsoluteColumn(column); } - // // TODO: highlight columns selected - // boolean colsel = false; - // if (columnSelection != null) - // { - // colsel = columnSelection.contains(column); - // } + // TODO: highlight columns selected + boolean colsel = false; + if (columnSelection != null) + { + colsel = columnSelection.contains(column); + } if (column > aaMax) { @@ -67,65 +181,85 @@ public class ContactMapRenderer implements AnnotationRowRendererI x++; continue; } - if (_aa.sequenceRef != null) - { - // get the sequence position for the column - column = _aa.sequenceRef.findPosition(column) - 1; - } ContactListI contacts = viewport.getContactList(_aa, column); if (contacts == null) { - return; - } - int contact_height = contacts.getContactHeight(); - // fractional number of contacts covering each pixel - double contacts_per_pixel = ((double) contact_height) - / ((double) _aa.graphHeight); - - int pixels_step; - - if (contacts_per_pixel >= 1) - { - // many contacts rendered per pixel - pixels_step = 1; - } - else - { - // pixel height for each contact - pixels_step = (int) Math - .ceil(((double) _aa.graphHeight) / (double) contact_height); + x++; + continue; } + // ContactListI from viewport can map column -> group + Color gpcol = (cm == null) ? Color.white + : contacts.getColourForGroup(); // cm.getColourForGroup(cm.getGroupsFor(column)); + // feature still in development - highlight or omit regions hidden in + // the alignment - currently marks them as red rows + boolean maskHiddenCols = false; + // TODO: optionally pass visible column mask to the ContactGeometry object + // so it maps + // only visible contacts to geometry + // Bean holding mapping from contact list to pixels + // TODO: allow bracketing/limiting of range on contacts to render (like + // visible column mask but more flexible?) - int cstart = 0, cend; + // COntactListI provides mapping for column -> cm-groupmapping + final ContactGeometry cgeom = new ContactGeometry(contacts, + _aa.graphHeight); - for (int ht = y2, - eht = y2 - _aa.graphHeight; ht >= eht; ht -= pixels_step) + for (int ht = 0, botY = topY + - _aa.height; ht < _aa.graphHeight; 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 = getColorForRange(min, max, contacts, cstart, cend); + ContactGeometry.contactInterval ci = cgeom.mapFor(ht); + // cstart = (int) Math.floor(((double) y2 - ht) * contacts_per_pixel); + // cend = (int) Math.min(contact_height, + // Math.ceil(cstart + contacts_per_pixel * pixels_step)); + Color col; + boolean rowsel = false; + boolean containsHidden = false; + if (columnSelection != null) + { + rowsel = cgeom.intersects(ci, columnSelection, hiddenColumns, + maskHiddenCols); + } // TODO: show selected region - // if (colsel || columnSelection!=null && - // columnSelection.intersects(cstart,cend)) - // { - // g.setColor(col.brighter()); - // } - // else + 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()); + } + } + else + { + col = getColorForRange(min, max, contacts, ci.cStart, ci.cEnd); + } + if (containsHidden) { - g.setColor(col); + col = shade.hidden; } - if (pixels_step > 1) + if (showGroups && gpcol != null && gpcol != Color.white) { - g.fillRect(x * charWidth, ht, charWidth, 1 + pixels_step); + // todo - could overlay group as a transparent rectangle ? + col = new Color((int) ((col.getRed() + gpcol.getRed()) / 2f), + (int) ((col.getGreen() + gpcol.getGreen()) / 2f), + (int) ((col.getBlue() + gpcol.getBlue()) / 2f)); + } + g.setColor(col); + if (cgeom.pixels_step > 1) + { + g.fillRect(x * charWidth, botY + ht, charWidth, + cgeom.pixels_step); } else { - g.drawLine(x * charWidth, ht, (x + 1) * charWidth, ht); + g.drawLine(x * charWidth, botY + ht, (x + 1) * charWidth, + botY + ht); } } x++; @@ -133,12 +267,10 @@ public class ContactMapRenderer implements AnnotationRowRendererI } - Color minColor = Color.white, maxColor = Color.magenta; - Color shadeFor(float min, float max, float value) { - return jalview.util.ColorUtils.getGraduatedColour(value, 0, minColor, - max, maxColor); + return jalview.util.ColorUtils.getGraduatedColour(value, 0, + shade.minColor, max, shade.maxColor); } public Color getColorForRange(float min, float max, ContactListI cl, @@ -149,4 +281,13 @@ public class ContactMapRenderer implements AnnotationRowRendererI 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.getMin(), + 0, shade.selMinColor, max, shade.selMaxColor); + } + }