label.run_groovy = Run Groovy console script
label.run_groovy_tip = Run the script in the Groovy console over this alignment
label.couldnt_run_groovy_script = Failed to run Groovy script
-label.uniprot_sequence_fetcher = UniProt Sequence Fetcher
\ No newline at end of file
+label.uniprot_sequence_fetcher = UniProt Sequence Fetcher
+label.colour_alternately = Alternately
+label.colour_alternately_tip = Colour features in two alternating colours
public static int transferFeatures(SequenceI fromSeq, SequenceI toSeq,
MapList mapping, String select, String... omitting)
{
+ Map<String, Integer> featureCounts = new HashMap<String, Integer>();
+
SequenceI copyTo = toSeq;
while (copyTo.getDatasetSequence() != null)
{
copy.setBegin(Math.min(mappedTo[0], mappedTo[1]));
copy.setEnd(Math.max(mappedTo[0], mappedTo[1]));
copyTo.addSequenceFeature(copy);
+ int featureNumber = featureCounts.containsKey(type) ? featureCounts
+ .get(type) : -1;
+ featureNumber++;
+ featureCounts.put(type, featureNumber);
+ copy.setFeatureNumber(featureNumber);
count++;
}
}
*/
void setVisible(String featureType);
+ /**
+ * Answers true if the feature has 'featureNumber' properties set
+ *
+ * @param featureType
+ * @return
+ */
+ boolean isOrdinal(String featureType);
+
}
// private key for Phase designed not to conflict with real GFF data
private static final String PHASE = "!Phase";
+ // private key for feature number designed not to conflict with real GFF data
+ private static final String NUMBER = "!Num";
+
/*
* ATTRIBUTES is reserved for the GFF 'column 9' data, formatted as
* name1=value1;name2=value2,value3;...etc
}
/**
+ * Set the ordinal number of this feature on the sequence
+ *
+ * @param num
+ */
+ public void setFeatureNumber(int num)
+ {
+ setValue(NUMBER, String.valueOf(num));
+ }
+
+ /**
+ * Returns the feature number if set, else 0. Intended for use as the ordinal
+ * position of the feature on the sequence for features of the same type.
+ *
+ * @return
+ */
+ public int getFeatureNumber()
+ {
+ try
+ {
+ return Integer.parseInt((String) getValue(NUMBER));
+ } catch (Exception e)
+ {
+ // property absent or not numeric
+ return 0;
+ }
+ }
+
+ /**
* Readable representation, for debug only, not guaranteed not to change
* between versions
*/
String type = null;
+ JPanel minColour = new JPanel();
+
+ JPanel maxColour = new JPanel();
+
+ JComboBox threshold = new JComboBox();
+
+ JSlider slider = new JSlider();
+
+ JTextField thresholdValue = new JTextField(20);
+
+ // TODO implement GUI for tolower flag
+ // JCheckBox toLower = new JCheckBox();
+
+ JCheckBox thresholdIsMin = new JCheckBox();
+
+ JCheckBox colourAlternately = new JCheckBox();
+
+ JCheckBox colourByLabel = new JCheckBox();
+
+ private GraphLine threshline;
+
+ private Color oldmaxColour;
+
+ private Color oldminColour;
+
public FeatureColourChooser(FeatureRenderer frender, String type)
{
this(frender, false, type);
}
});
- float mm[] = ((float[][]) fr.getMinMax().get(type))[0];
+ float mm[] = fr.getMinMax().get(type)[0];
min = mm[0];
max = mm[1];
// update the gui from threshold state
thresholdIsMin.setSelected(!cs.isAutoScale());
colourByLabel.setSelected(cs.isColourByLabel());
+ colourAlternately.setSelected(cs.isColourAlternately());
if (cs.getThreshType() != AnnotationColourGradient.NO_THRESHOLD)
{
// initialise threshold slider and selector
}
});
maxColour.setBorder(new LineBorder(Color.black));
+ JLabel minText = new JLabel();
minText.setText(MessageManager.getString("label.min"));
minText.setFont(JvSwingUtils.getLabelFont());
+ JLabel maxText = new JLabel();
maxText.setText(MessageManager.getString("label.max"));
maxText.setFont(JvSwingUtils.getLabelFont());
- this.setLayout(borderLayout1);
- jPanel2.setLayout(flowLayout1);
+ this.setLayout(new BorderLayout());
+ JPanel jPanel1 = new JPanel();
+ JPanel jPanel2 = new JPanel();
+ jPanel2.setLayout(new FlowLayout());
jPanel1.setBackground(Color.white);
jPanel2.setBackground(Color.white);
threshold.addActionListener(new ActionListener()
.getString("label.threshold_feature_above_thereshold")); // index 1
threshold.addItem(MessageManager
.getString("label.threshold_feature_below_thereshold")); // index 2
- jPanel3.setLayout(flowLayout2);
+ JPanel jPanel3 = new JPanel();
+ jPanel3.setLayout(new FlowLayout());
thresholdValue.addActionListener(new ActionListener()
{
@Override
thresholdIsMin_actionPerformed(actionEvent);
}
});
+ colourAlternately.setBackground(Color.white);
+ colourAlternately.setText(MessageManager
+ .getString("label.colour_alternately"));
+ colourAlternately.setToolTipText(MessageManager
+ .getString("label.colour_alternately_tip"));
+ colourAlternately.addActionListener(new ActionListener()
+ {
+ @Override
+ public void actionPerformed(ActionEvent actionEvent)
+ {
+ colourAlternately_actionPerformed(actionEvent);
+ }
+ });
colourByLabel.setBackground(Color.white);
colourByLabel
.setText(MessageManager.getString("label.colour_by_label"));
colourByLabel_actionPerformed(actionEvent);
}
});
+
+ JPanel colourPanel = new JPanel();
colourPanel.setBackground(Color.white);
jPanel1.add(ok);
jPanel1.add(cancel);
- jPanel2.add(colourByLabel, java.awt.BorderLayout.WEST);
+ jPanel2.add(colourAlternately, java.awt.BorderLayout.WEST);
+ jPanel2.add(colourByLabel, java.awt.BorderLayout.CENTER);
jPanel2.add(colourPanel, java.awt.BorderLayout.EAST);
colourPanel.add(minText);
colourPanel.add(minColour);
this.add(jPanel2, java.awt.BorderLayout.NORTH);
}
- JLabel minText = new JLabel();
-
- JLabel maxText = new JLabel();
-
- JPanel minColour = new JPanel();
-
- JPanel maxColour = new JPanel();
-
- JPanel colourPanel = new JPanel();
-
- JPanel jPanel1 = new JPanel();
-
- JPanel jPanel2 = new JPanel();
-
- BorderLayout borderLayout1 = new BorderLayout();
-
- JComboBox threshold = new JComboBox();
-
- FlowLayout flowLayout1 = new FlowLayout();
-
- JPanel jPanel3 = new JPanel();
-
- FlowLayout flowLayout2 = new FlowLayout();
-
- JSlider slider = new JSlider();
-
- JTextField thresholdValue = new JTextField(20);
-
- // TODO implement GUI for tolower flag
- // JCheckBox toLower = new JCheckBox();
-
- JCheckBox thresholdIsMin = new JCheckBox();
-
- JCheckBox colourByLabel = new JCheckBox();
-
- private GraphLine threshline;
-
- private Color oldmaxColour;
-
- private Color oldminColour;
+ protected void colourAlternately_actionPerformed(ActionEvent actionEvent)
+ {
+ changeColour();
+ }
public void minColour_actionPerformed()
{
acg.setAutoScaled(true);
}
acg.setColourByLabel(colourByLabel.isSelected());
+ acg.setColourAlternately(colourAlternately.isSelected());
+ colourByLabel.setEnabled(!colourAlternately.isSelected());
+ colourAlternately.setEnabled(!colourByLabel.isSelected());
+ if (!fr.isOrdinal(type))
+ {
+ // don't allow colour alternately if no feature numbering on features
+ colourAlternately.setEnabled(false);
+ }
if (acg.isColourByLabel())
{
maxColour.setEnabled(false);
tx += "Label";
comp.setIcon(null);
}
+ // else if (gcol.isColourAlternately())
+ // {
+ // tt = "Coloured alternately " + tt;
+ // if (thr)
+ // {
+ // tx += " ";
+ // }
+ // tx += "Alternately";
+ // comp.setIcon(null);
+ // }
else
{
Color newColor = gcol.getMaxColor();
comp.setBackground(newColor);
- // System.err.println("Width is " + w / 2);
Icon ficon = new FeatureIcon(gcol, comp.getBackground(), w, h, thr);
comp.setIcon(ficon);
- // tt+="RGB value: Max (" + newColor.getRed() + ", "
- // + newColor.getGreen() + ", " + newColor.getBlue()
- // + ")\nMin (" + minCol.getRed() + ", " + minCol.getGreen()
- // + ", " + minCol.getBlue() + ")");
}
comp.setHorizontalAlignment(SwingConstants.CENTER);
comp.setText(tx);
width = w;
height = h;
midspace = mspace;
- if (midspace)
+ if (midspace || gcol.isColourAlternately())
{
s1 = width / 3;
e1 = s1 * 2;
g.drawString(MessageManager.getString("label.label"), 0, 0);
}
+ else if (gcol.isColourAlternately())
+ {
+ Color minCol = gcol.getMinColor();
+ g.setColor(minCol);
+ g.fillRect(0, 0, s1, height);
+ g.setColor(gcol.getMaxColor());
+ g.fillRect(s1, 0, e1 - s1, height);
+ g.setColor(minCol);
+ g.fillRect(e1, 0, width - e1, height);
+ }
else
{
Color minCol = gcol.getMinColor();
g.fillRect(s1, 0, e1 - s1, height);
}
g.setColor(gcol.getMaxColor());
- g.fillRect(0, e1, width - e1, height);
+ g.fillRect(e1, 0, width - e1, height);
+ // this is wrong but works - why??
+ // g.fillRect(0, e1, width - e1, height);
}
}
}
*/
public class GraduatedColor
{
+ private static final Color[] colours = new Color[] { Color.blue,
+ Color.red };
+
+ private static int colourModulus = 0;
+
int thresholdState = AnnotationColourGradient.NO_THRESHOLD; // or
// ABOVE_THRESHOLD
// or
thrsh = oldcs.thrsh;
autoScale = oldcs.autoScale;
colourByLabel = oldcs.colourByLabel;
+ colourAlternately = oldcs.colourAlternately;
}
/**
private boolean colourByLabel = false;
+ private boolean colourAlternately = false;
+
/**
*
* @return true if colourByLabel style is set
}
return ucs.createColourFromName(feature.getDescription());
}
+ if (colourAlternately)
+ {
+ int minOrMax = feature.getFeatureNumber() % 2;
+ return minOrMax == 0 ? new Color(lr, lg, lb) : new Color(lr + dr, lg
+ + dg, lb + db);
+ }
if (range == 0.0)
{
return getMaxColor();
tolow = false;
}
}
+
+ public boolean isColourAlternately()
+ {
+ return colourAlternately;
+ }
+
+ public void setColourAlternately(boolean colourAlternately)
+ {
+ this.colourAlternately = colourAlternately;
+ }
}
*/
private Map<String, float[][]> minmax = new Hashtable<String, float[][]>();
+ /*
+ * List of feature types where getFeatureNumber() > 0 is found
+ * - a heuristic for 'features have an explicit ordering'
+ */
+ private List<String> ordinalFeatures = new ArrayList<String>();
+
@Override
public AlignViewportI getViewport()
{
* Searches alignment for all features and updates colours
*
* @param newMadeVisible
- * if true newly added feature types will be rendered immediatly
+ * if true newly added feature types will be rendered immediately
* TODO: check to see if this method should actually be proxied so
* repaint events can be propagated by the renderer code
*/
}
findingFeatures = true;
+ ordinalFeatures.clear();
if (av.getFeaturesDisplayed() == null)
{
av.setFeaturesDisplayed(new FeaturesDisplayed());
}
FeaturesDisplayedI featuresDisplayed = av.getFeaturesDisplayed();
- ArrayList<String> allfeatures = new ArrayList<String>();
- ArrayList<String> oldfeatures = new ArrayList<String>();
+ List<String> allfeatures = new ArrayList<String>();
+ List<String> oldfeatures = new ArrayList<String>();
if (renderOrder != null)
{
for (int i = 0; i < renderOrder.length; i++)
minmax = new Hashtable<String, float[][]>();
}
AlignmentI alignment = av.getAlignment();
- for (int i = 0; i < alignment.getHeight(); i++)
+ for (SequenceI asq : alignment.getSequences())
{
- SequenceI asq = alignment.getSequenceAt(i);
SequenceFeature[] features = asq.getSequenceFeatures();
if (features == null)
continue;
}
- int index = 0;
- while (index < features.length)
+ for (SequenceFeature feature : features)
{
- if (!featuresDisplayed.isRegistered(features[index].getType()))
+ String type = feature.getType();
+ if (!featuresDisplayed.isRegistered(type))
{
- String fgrp = features[index].getFeatureGroup();
+ String fgrp = feature.getFeatureGroup();
if (fgrp != null)
{
Boolean groupDisplayed = featureGroups.get(fgrp);
}
if (!groupDisplayed.booleanValue())
{
- index++;
continue;
}
}
- if (!(features[index].begin == 0 && features[index].end == 0))
+ if (!(feature.begin == 0 && feature.end == 0))
{
// If beginning and end are 0, the feature is for the whole sequence
// and we don't want to render the feature in the normal way
if (newMadeVisible
- && !oldfeatures.contains(features[index].getType()))
+ && !oldfeatures.contains(type))
{
// this is a new feature type on the alignment. Mark it for
// display.
- featuresDisplayed.setVisible(features[index].getType());
- setOrder(features[index].getType(), 0);
+ featuresDisplayed.setVisible(type);
+ setOrder(type, 0);
}
}
}
- if (!allfeatures.contains(features[index].getType()))
+ if (!allfeatures.contains(type))
{
- allfeatures.add(features[index].getType());
+ allfeatures.add(type);
}
- if (!Float.isNaN(features[index].score))
+ float score = feature.score;
+ if (!Float.isNaN(score))
{
- int nonpos = features[index].getBegin() >= 1 ? 0 : 1;
- float[][] mm = minmax.get(features[index].getType());
+ int nonpos = feature.getBegin() >= 1 ? 0 : 1;
+ float[][] mm = minmax.get(type);
if (mm == null)
{
mm = new float[][] { null, null };
- minmax.put(features[index].getType(), mm);
+ minmax.put(type, mm);
}
if (mm[nonpos] == null)
{
- mm[nonpos] = new float[] { features[index].score,
- features[index].score };
+ mm[nonpos] = new float[] { score, score };
}
else
{
- if (mm[nonpos][0] > features[index].score)
- {
- mm[nonpos][0] = features[index].score;
- }
- if (mm[nonpos][1] < features[index].score)
- {
- mm[nonpos][1] = features[index].score;
- }
+ mm[nonpos][0] = Math.min(mm[nonpos][0], score);
+ mm[nonpos][1] = Math.max(mm[nonpos][1], score);
+ }
+ }
+
+ /*
+ * add to 'ordinal feature types' if it has featureNumber > 0
+ */
+ if (!ordinalFeatures.contains(type))
+ {
+ if (feature.getFeatureNumber() > 0)
+ {
+ ordinalFeatures.add(type);
}
}
- index++;
}
}
updateRenderOrder(allfeatures);
List<String> allfeatures = new ArrayList<String>(allFeatures);
String[] oldRender = renderOrder;
renderOrder = new String[allfeatures.size()];
- Object mmrange, fc = null;
+ float[][] mmrange;
+ Object fc;
boolean initOrders = (featureOrder == null);
int opos = 0;
if (oldRender != null && oldRender.length > 0)
}
if (allfeatures.contains(oldRender[j]))
{
- renderOrder[opos++] = oldRender[j]; // existing features always
- // appear below new features
+ renderOrder[opos++] = oldRender[j];
+ // existing features always appear below new features
allfeatures.remove(oldRender[j]);
if (minmax != null)
{
&& ((GraduatedColor) fc).isAutoScale())
{
((GraduatedColor) fc).updateBounds(
- ((float[][]) mmrange)[0][0],
- ((float[][]) mmrange)[0][1]);
+ mmrange[0][0],
+ mmrange[0][1]);
}
}
}
if (fc != null && fc instanceof GraduatedColor
&& ((GraduatedColor) fc).isAutoScale())
{
- ((GraduatedColor) fc).updateBounds(((float[][]) mmrange)[0][0],
- ((float[][]) mmrange)[0][1]);
+ ((GraduatedColor) fc).updateBounds(mmrange[0][0],
+ mmrange[0][1]);
}
}
}
return _gps;
}
+ @Override
+ public boolean isOrdinal(String featureType)
+ {
+ return ordinalFeatures.contains(featureType);
+ }
}