From 4be2c7d1bcf79664267750cb1187079305794363 Mon Sep 17 00:00:00 2001 From: gmungoc Date: Thu, 1 Dec 2016 14:52:15 +0000 Subject: [PATCH] JAL-2346 restore choice of annotation for colouring faithfully --- src/jalview/appletgui/AnnotationColourChooser.java | 115 +++++++++------- src/jalview/gui/AnnotationColourChooser.java | 25 ++-- src/jalview/gui/AnnotationRowFilter.java | 69 +++++++--- src/jalview/schemes/AnnotationColourGradient.java | 140 +++++++++++--------- 4 files changed, 211 insertions(+), 138 deletions(-) diff --git a/src/jalview/appletgui/AnnotationColourChooser.java b/src/jalview/appletgui/AnnotationColourChooser.java index 79d2f1f..d4a21b2 100644 --- a/src/jalview/appletgui/AnnotationColourChooser.java +++ b/src/jalview/appletgui/AnnotationColourChooser.java @@ -20,12 +20,6 @@ */ package jalview.appletgui; -import jalview.datamodel.AlignmentAnnotation; -import jalview.datamodel.SequenceGroup; -import jalview.schemes.AnnotationColourGradient; -import jalview.schemes.ColourSchemeI; -import jalview.util.MessageManager; - import java.awt.BorderLayout; import java.awt.Button; import java.awt.Checkbox; @@ -46,9 +40,16 @@ import java.awt.event.ItemEvent; import java.awt.event.ItemListener; import java.awt.event.MouseEvent; import java.awt.event.MouseListener; -import java.util.Hashtable; +import java.util.HashMap; +import java.util.Map; import java.util.Vector; +import jalview.datamodel.AlignmentAnnotation; +import jalview.datamodel.SequenceGroup; +import jalview.schemes.AnnotationColourGradient; +import jalview.schemes.ColourSchemeI; +import jalview.util.MessageManager; + public class AnnotationColourChooser extends Panel implements ActionListener, AdjustmentListener, ItemListener, MouseListener { @@ -60,9 +61,15 @@ public class AnnotationColourChooser extends Panel implements ColourSchemeI oldcs; - Hashtable oldgroupColours; + Map oldgroupColours; + + /* + * map from annotation to its menu item display label + * - so we know which item to pre-select on restore + */ + private Map annotationLabels; - jalview.datamodel.AlignmentAnnotation currentAnnotation; + AlignmentAnnotation currentAnnotation; boolean adjusting = false; @@ -78,17 +85,13 @@ public class AnnotationColourChooser extends Panel implements oldcs = av.getGlobalColourScheme(); if (av.getAlignment().getGroups() != null) { - oldgroupColours = new Hashtable(); + oldgroupColours = new HashMap(); for (SequenceGroup sg : ap.av.getAlignment().getGroups()) { if (sg.cs != null) { oldgroupColours.put(sg, sg.cs); } - else - { - oldgroupColours.put(sg, "null"); - } } } this.av = av; @@ -119,24 +122,7 @@ public class AnnotationColourChooser extends Panel implements // seqAssociated.setState(acg.isSeqAssociated()); } - Vector list = new Vector(); - int index = 1; - for (int i = 0; i < anns.length; i++) - { - String label = anns[i].label; - if (anns[i].sequenceRef != null) - { - label = label + "_" + anns[i].sequenceRef.getName(); - } - if (!list.contains(label)) - { - list.addElement(label); - } - else - { - list.addElement(label + "_" + (index++)); - } - } + Vector list = getAnnotationItems(); for (int i = 0; i < list.size(); i++) { @@ -153,7 +139,8 @@ public class AnnotationColourChooser extends Panel implements if (oldcs instanceof AnnotationColourGradient) { AnnotationColourGradient acg = (AnnotationColourGradient) oldcs; - annotations.select(acg.getAnnotation()); + String label = annotationLabels.get(acg.getAnnotation()); + annotations.select(label); switch (acg.getAboveThreshold()) { case AnnotationColourGradient.NO_THRESHOLD: @@ -170,7 +157,7 @@ public class AnnotationColourChooser extends Panel implements MessageManager .getString("error.implementation_error_dont_know_threshold_annotationcolourgradient")); } - thresholdIsMin.setState(acg.thresholdIsMinMax); + thresholdIsMin.setState(acg.isThresholdIsMinMax()); thresholdValue.setText("" + acg.getAnnotationThreshold()); } @@ -186,6 +173,51 @@ public class AnnotationColourChooser extends Panel implements validate(); } + /** + * Builds and returns a list of menu items (display text) for choice of + * annotation. Also builds a map between annotations and their display labels. + * + * @return + */ + protected Vector getAnnotationItems() + { + // TODO remove duplication with gui.AnnotationRowFilter + // TODO add 'per sequence only' option / parameter + + annotationLabels = new HashMap(); + Vector list = new Vector(); + AlignmentAnnotation[] anns = av.getAlignment().getAlignmentAnnotation(); + if (anns == null) + { + return list; + } + int index = 1; + for (int i = 0; i < anns.length; i++) + { + String label = anns[i].label; + if (anns[i].sequenceRef != null) + { + /* + * be helpful and include sequence id in label for + * sequence-associated annotation (JAL-2236) + */ + label = label + "_" + anns[i].sequenceRef.getName(); + } + if (!list.contains(label)) + { + list.addElement(label); + annotationLabels.put(anns[i], label); + } + else + { + label = label + "_" + (index++); + list.addElement(label); + annotationLabels.put(anns[i], label); + } + } + return list; + } + private void setDefaultMinMax() { minColour.setBackground(av.applet.getDefaultColourParameter( @@ -503,7 +535,7 @@ public class AnnotationColourChooser extends Panel implements acg.setPredefinedColours(true); } - acg.thresholdIsMinMax = thresholdIsMin.getState(); + acg.setThresholdIsMinMax(thresholdIsMin.getState()); av.setGlobalColourScheme(acg); @@ -512,7 +544,6 @@ public class AnnotationColourChooser extends Panel implements { for (SequenceGroup sg : ap.av.getAlignment().getGroups()) { - if (sg.cs == null) { continue; @@ -529,7 +560,6 @@ public class AnnotationColourChooser extends Panel implements minColour.getBackground(), maxColour.getBackground(), aboveThreshold); } - } } @@ -545,16 +575,7 @@ public class AnnotationColourChooser extends Panel implements { for (SequenceGroup sg : ap.av.getAlignment().getGroups()) { - Object cs = oldgroupColours.get(sg); - if (cs instanceof ColourSchemeI) - { - sg.cs = (ColourSchemeI) cs; - } - else - { - // probably the "null" string we set it to if it was null originally. - sg.cs = null; - } + sg.cs = oldgroupColours.get(sg); } } ap.paintAlignment(true); diff --git a/src/jalview/gui/AnnotationColourChooser.java b/src/jalview/gui/AnnotationColourChooser.java index 39cde03..4daf6b2 100644 --- a/src/jalview/gui/AnnotationColourChooser.java +++ b/src/jalview/gui/AnnotationColourChooser.java @@ -20,12 +20,6 @@ */ package jalview.gui; -import jalview.bin.Cache; -import jalview.datamodel.SequenceGroup; -import jalview.schemes.AnnotationColourGradient; -import jalview.schemes.ColourSchemeI; -import jalview.util.MessageManager; - import java.awt.BorderLayout; import java.awt.Color; import java.awt.Dimension; @@ -35,6 +29,13 @@ import java.awt.event.ActionListener; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.util.Hashtable; +import java.util.Vector; + +import jalview.bin.Cache; +import jalview.datamodel.SequenceGroup; +import jalview.schemes.AnnotationColourGradient; +import jalview.schemes.ColourSchemeI; +import jalview.util.MessageManager; import javax.swing.BorderFactory; import javax.swing.JButton; @@ -118,15 +119,17 @@ public class AnnotationColourChooser extends AnnotationRowFilter seqAssociated.setSelected(acg.isSeqAssociated()); } - annotations = new JComboBox( - getAnnotationItems(seqAssociated.isSelected())); + Vector annotItems = getAnnotationItems(seqAssociated + .isSelected()); + annotations = new JComboBox(annotItems); populateThresholdComboBox(threshold); if (oldcs instanceof AnnotationColourGradient) { AnnotationColourGradient acg = (AnnotationColourGradient) oldcs; - annotations.setSelectedItem(acg.getAnnotation()); + String label = getAnnotationMenuLabel(acg.getAnnotation()); + annotations.setSelectedItem(label); switch (acg.getAboveThreshold()) { case AnnotationColourGradient.NO_THRESHOLD: @@ -143,7 +146,7 @@ public class AnnotationColourChooser extends AnnotationRowFilter MessageManager .getString("error.implementation_error_dont_know_about_threshold_setting")); } - thresholdIsMin.setSelected(acg.thresholdIsMinMax); + thresholdIsMin.setSelected(acg.isThresholdIsMinMax()); thresholdValue.setText("" + acg.getAnnotationThreshold()); } @@ -475,7 +478,7 @@ public class AnnotationColourChooser extends AnnotationRowFilter thresholdValue.setEnabled(true); adjusting = false; } - colorAlignmContaining(getCurrentAnnotation(), selectedThresholdItem); + colorAlignmentContaining(getCurrentAnnotation(), selectedThresholdItem); ap.alignmentChanged(); // ensure all associated views (overviews, structures, etc) are notified of diff --git a/src/jalview/gui/AnnotationRowFilter.java b/src/jalview/gui/AnnotationRowFilter.java index c8bd69c..ea531f2 100644 --- a/src/jalview/gui/AnnotationRowFilter.java +++ b/src/jalview/gui/AnnotationRowFilter.java @@ -20,16 +20,18 @@ */ package jalview.gui; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.util.HashMap; +import java.util.Map; +import java.util.Vector; + import jalview.datamodel.AlignmentAnnotation; import jalview.datamodel.GraphLine; import jalview.datamodel.SequenceGroup; import jalview.schemes.AnnotationColourGradient; import jalview.util.MessageManager; -import java.awt.event.MouseAdapter; -import java.awt.event.MouseEvent; -import java.util.Vector; - import javax.swing.JButton; import javax.swing.JCheckBox; import javax.swing.JComboBox; @@ -49,6 +51,12 @@ public abstract class AnnotationRowFilter extends JPanel protected int[] annmap; + /* + * map from annotation to its menu item display label + * - so we know which item to pre-select on restore + */ + private Map annotationLabels; + protected boolean enableSeqAss = false; private AlignmentAnnotation currentAnnotation; @@ -141,14 +149,26 @@ public abstract class AnnotationRowFilter extends JPanel } + /** + * Builds and returns a list of menu items (display text) for choice of + * annotation. Also builds maps between annotations, their positions in the + * list, and their display labels in the list. + * + * @param isSeqAssociated + * @return + */ public Vector getAnnotationItems(boolean isSeqAssociated) { + annotationLabels = new HashMap(); + Vector list = new Vector(); int index = 1; int[] anmap = new int[av.getAlignment().getAlignmentAnnotation().length]; for (int i = 0; i < av.getAlignment().getAlignmentAnnotation().length; i++) { - if (av.getAlignment().getAlignmentAnnotation()[i].sequenceRef == null) + AlignmentAnnotation annotation = av.getAlignment() + .getAlignmentAnnotation()[i]; + if (annotation.sequenceRef == null) { if (isSeqAssociated) { @@ -159,28 +179,27 @@ public abstract class AnnotationRowFilter extends JPanel { enableSeqAss = true; } - String label = av.getAlignment().getAlignmentAnnotation()[i].label; + String label = annotation.label; // add associated sequence ID if available - if (!isSeqAssociated - && av.getAlignment().getAlignmentAnnotation()[i].sequenceRef != null) + if (!isSeqAssociated && annotation.sequenceRef != null) { - label = label - + "_" - + av.getAlignment().getAlignmentAnnotation()[i].sequenceRef - .getName(); + label = label + "_" + annotation.sequenceRef.getName(); } // make label unique if (!list.contains(label)) { anmap[list.size()] = i; list.add(label); + annotationLabels.put(annotation, label); } else { if (!isSeqAssociated) { anmap[list.size()] = i; - list.add(label + "_" + (index++)); + label = label + "_" + (index++); + list.add(label); + annotationLabels.put(annotation, label); } } } @@ -272,6 +291,12 @@ public abstract class AnnotationRowFilter extends JPanel .getString("label.threshold_feature_below_threshold")); } + /** + * Rebuilds the drop-down list of annotations to choose from when the 'per + * sequence only' checkbox is checked or unchecked. + * + * @param annotations + */ protected void seqAssociated_actionPerformed(JComboBox annotations) { adjusting = true; @@ -329,8 +354,8 @@ public abstract class AnnotationRowFilter extends JPanel } } - protected boolean colorAlignmContaining(AlignmentAnnotation currentAnn, - int selectedThresholdOption) + protected boolean colorAlignmentContaining( + AlignmentAnnotation currentAnn, int selectedThresholdOption) { AnnotationColourGradient acg = null; @@ -352,7 +377,7 @@ public abstract class AnnotationRowFilter extends JPanel acg.setPredefinedColours(true); } - acg.thresholdIsMinMax = thresholdIsMin.isSelected(); + acg.setThresholdIsMinMax(thresholdIsMin.isSelected()); av.setGlobalColourScheme(acg); @@ -372,7 +397,6 @@ public abstract class AnnotationRowFilter extends JPanel selectedThresholdOption); ((AnnotationColourGradient) sg.cs).setSeqAssociated(seqAssociated .isSelected()); - } else { @@ -382,19 +406,17 @@ public abstract class AnnotationRowFilter extends JPanel ((AnnotationColourGradient) sg.cs).setSeqAssociated(seqAssociated .isSelected()); } - } } return false; } - public jalview.datamodel.AlignmentAnnotation getCurrentAnnotation() + public AlignmentAnnotation getCurrentAnnotation() { return currentAnnotation; } - public void setCurrentAnnotation( - jalview.datamodel.AlignmentAnnotation currentAnnotation) + public void setCurrentAnnotation(AlignmentAnnotation currentAnnotation) { this.currentAnnotation = currentAnnotation; } @@ -404,4 +426,9 @@ public abstract class AnnotationRowFilter extends JPanel public abstract void updateView(); public abstract void reset(); + + protected String getAnnotationMenuLabel(AlignmentAnnotation ann) + { + return annotationLabels.get(ann); + } } diff --git a/src/jalview/schemes/AnnotationColourGradient.java b/src/jalview/schemes/AnnotationColourGradient.java index 89b8f07..2c8d5dd 100755 --- a/src/jalview/schemes/AnnotationColourGradient.java +++ b/src/jalview/schemes/AnnotationColourGradient.java @@ -20,6 +20,10 @@ */ package jalview.schemes; +import java.awt.Color; +import java.util.IdentityHashMap; +import java.util.Map; + import jalview.datamodel.AlignmentAnnotation; import jalview.datamodel.AlignmentI; import jalview.datamodel.AnnotatedCollectionI; @@ -28,10 +32,6 @@ import jalview.datamodel.GraphLine; import jalview.datamodel.SequenceCollectionI; import jalview.datamodel.SequenceI; -import java.awt.Color; -import java.util.IdentityHashMap; -import java.util.Map; - public class AnnotationColourGradient extends FollowerColourScheme { public static final int NO_THRESHOLD = -1; @@ -40,15 +40,25 @@ public class AnnotationColourGradient extends FollowerColourScheme public static final int ABOVE_THRESHOLD = 1; - public AlignmentAnnotation annotation; + private final AlignmentAnnotation annotation; + + private final int aboveAnnotationThreshold; + + private boolean thresholdIsMinMax = false; - int aboveAnnotationThreshold = -1; + private GraphLine annotationThreshold; - public boolean thresholdIsMinMax = false; + private int redMin; - GraphLine annotationThreshold; + private int greenMin; - float r1, g1, b1, rr, gg, bb; + private int blueMin; + + private int redRange; + + private int greenRange; + + private int blueRange; private boolean predefinedColours = false; @@ -61,7 +71,7 @@ public class AnnotationColourGradient extends FollowerColourScheme */ private boolean noGradient = false; - IdentityHashMap seqannot = null; + private IdentityHashMap seqannot = null; @Override public ColourSchemeI applyTo(AnnotatedCollectionI sg, @@ -72,12 +82,12 @@ public class AnnotationColourGradient extends FollowerColourScheme acg.thresholdIsMinMax = thresholdIsMinMax; acg.annotationThreshold = (annotationThreshold == null) ? null : new GraphLine(annotationThreshold); - acg.r1 = r1; - acg.g1 = g1; - acg.b1 = b1; - acg.rr = rr; - acg.gg = gg; - acg.bb = bb; + acg.redMin = redMin; + acg.greenMin = greenMin; + acg.blueMin = blueMin; + acg.redRange = redRange; + acg.greenRange = greenRange; + acg.blueRange = blueRange; acg.predefinedColours = predefinedColours; acg.seqAssociated = seqAssociated; acg.noGradient = noGradient; @@ -108,12 +118,12 @@ public class AnnotationColourGradient extends FollowerColourScheme annotationThreshold = annotation.threshold; } // clear values so we don't get weird black bands... - r1 = 254; - g1 = 254; - b1 = 254; - rr = 0; - gg = 0; - bb = 0; + redMin = 254; + greenMin = 254; + blueMin = 254; + redRange = 0; + greenRange = 0; + blueRange = 0; noGradient = true; checkLimits(); @@ -134,13 +144,13 @@ public class AnnotationColourGradient extends FollowerColourScheme annotationThreshold = annotation.threshold; } - r1 = minColour.getRed(); - g1 = minColour.getGreen(); - b1 = minColour.getBlue(); + redMin = minColour.getRed(); + greenMin = minColour.getGreen(); + blueMin = minColour.getBlue(); - rr = maxColour.getRed() - r1; - gg = maxColour.getGreen() - g1; - bb = maxColour.getBlue() - b1; + redRange = maxColour.getRed() - redMin; + greenRange = maxColour.getGreen() - greenMin; + blueRange = maxColour.getBlue() - blueMin; noGradient = false; checkLimits(); @@ -210,9 +220,9 @@ public class AnnotationColourGradient extends FollowerColourScheme float aamin = 0f, aamax = 0f; - public String getAnnotation() + public AlignmentAnnotation getAnnotation() { - return annotation.label; + return annotation; } public int getAboveThreshold() @@ -234,12 +244,13 @@ public class AnnotationColourGradient extends FollowerColourScheme public Color getMinColour() { - return new Color((int) r1, (int) g1, (int) b1); + return new Color(redMin, greenMin, blueMin); } public Color getMaxColour() { - return new Color((int) (r1 + rr), (int) (g1 + gg), (int) (b1 + bb)); + return new Color(redMin + redRange, greenMin + greenRange, blueMin + + blueRange); } /** @@ -250,6 +261,7 @@ public class AnnotationColourGradient extends FollowerColourScheme * * @return DOCUMENT ME! */ + @Override public Color findColour(char c) { return Color.red; @@ -269,20 +281,20 @@ public class AnnotationColourGradient extends FollowerColourScheme public Color findColour(char c, int j, SequenceI seq) { Color currentColour = Color.white; - AlignmentAnnotation annotation = (seqAssociated && seqannot != null ? seqannot + AlignmentAnnotation ann = (seqAssociated && seqannot != null ? seqannot .get(seq) : this.annotation); - if (annotation == null) + if (ann == null) { return currentColour; } if ((threshold == 0) || aboveThreshold(c, j)) { - if (annotation.annotations != null - && j < annotation.annotations.length - && annotation.annotations[j] != null + if (ann.annotations != null + && j < ann.annotations.length + && ann.annotations[j] != null && !jalview.util.Comparison.isGap(c)) { - Annotation aj = annotation.annotations[j]; + Annotation aj = ann.annotations[j]; // 'use original colours' => colourScheme != null // -> look up colour to be used // predefined colours => preconfigured shading @@ -302,8 +314,8 @@ public class AnnotationColourGradient extends FollowerColourScheme { currentColour = aj.colour; } - else if (annotation.hasIcons - && annotation.graph == AlignmentAnnotation.NO_GRAPH) + else if (ann.hasIcons + && ann.graph == AlignmentAnnotation.NO_GRAPH) { if (aj.secondaryStructure > ' ' && aj.secondaryStructure != '.' && aj.secondaryStructure != '-') @@ -314,14 +326,14 @@ public class AnnotationColourGradient extends FollowerColourScheme } else { - if (annotation.isRNA()) + if (ann.isRNA()) { currentColour = ColourSchemeProperty.rnaHelices[(int) aj.value]; } else { - currentColour = annotation.annotations[j].secondaryStructure == 'H' ? jalview.renderer.AnnotationRenderer.HELIX_COLOUR - : annotation.annotations[j].secondaryStructure == 'E' ? jalview.renderer.AnnotationRenderer.SHEET_COLOUR + currentColour = ann.annotations[j].secondaryStructure == 'H' ? jalview.renderer.AnnotationRenderer.HELIX_COLOUR + : ann.annotations[j].secondaryStructure == 'E' ? jalview.renderer.AnnotationRenderer.SHEET_COLOUR : jalview.renderer.AnnotationRenderer.STEM_COLOUR; } } @@ -348,7 +360,7 @@ public class AnnotationColourGradient extends FollowerColourScheme } else { - currentColour = shadeCalculation(annotation, j); + currentColour = shadeCalculation(ann, j); } } if (conservationColouring) @@ -360,32 +372,31 @@ public class AnnotationColourGradient extends FollowerColourScheme return currentColour; } - private Color shadeCalculation(AlignmentAnnotation annotation, int j) + private Color shadeCalculation(AlignmentAnnotation ann, int j) { // calculate a shade float range = 1f; - if (thresholdIsMinMax - && annotation.threshold != null + if (thresholdIsMinMax && ann.threshold != null && aboveAnnotationThreshold == ABOVE_THRESHOLD - && annotation.annotations[j].value >= annotation.threshold.value) + && ann.annotations[j].value >= ann.threshold.value) { - range = (annotation.annotations[j].value - annotation.threshold.value) - / (annotation.graphMax - annotation.threshold.value); + range = (ann.annotations[j].value - ann.threshold.value) + / (ann.graphMax - ann.threshold.value); } - else if (thresholdIsMinMax && annotation.threshold != null + else if (thresholdIsMinMax && ann.threshold != null && aboveAnnotationThreshold == BELOW_THRESHOLD - && annotation.annotations[j].value >= annotation.graphMin) + && ann.annotations[j].value >= ann.graphMin) { - range = (annotation.annotations[j].value - annotation.graphMin) - / (annotation.threshold.value - annotation.graphMin); + range = (ann.annotations[j].value - ann.graphMin) + / (ann.threshold.value - ann.graphMin); } else { - if (annotation.graphMax != annotation.graphMin) + if (ann.graphMax != ann.graphMin) { - range = (annotation.annotations[j].value - annotation.graphMin) - / (annotation.graphMax - annotation.graphMin); + range = (ann.annotations[j].value - ann.graphMin) + / (ann.graphMax - ann.graphMin); } else { @@ -393,8 +404,9 @@ public class AnnotationColourGradient extends FollowerColourScheme } } - int dr = (int) (rr * range + r1), dg = (int) (gg * range + g1), db = (int) (bb - * range + b1); + int dr = (int) (redRange * range + redMin); + int dg = (int) (greenRange * range + greenMin); + int db = (int) (blueRange * range + blueMin); return new Color(dr, dg, db); @@ -419,4 +431,14 @@ public class AnnotationColourGradient extends FollowerColourScheme { seqAssociated = sassoc; } + + public boolean isThresholdIsMinMax() + { + return thresholdIsMinMax; + } + + public void setThresholdIsMinMax(boolean thresholdIsMinMax) + { + this.thresholdIsMinMax = thresholdIsMinMax; + } } -- 1.7.10.2