import java.util.List;
/**
- * A class to compute an alignment annotation with column counts of any
- * properties of interest of positions in an alignment. <br>
+ * A class to compute alignment annotations with column counts for a set of
+ * properties of interest on positions in an alignment. <br>
* This is designed to be extensible, by supplying to the constructor an object
- * that computes a count for each residue position, based on the residue value
- * and any sequence features at that position.
+ * that computes a vector of counts for each residue position, based on the
+ * residue and and sequence features at that position.
*
*/
-class ColumnCounterWorker extends AlignCalcWorker
+class ColumnCounterSetWorker extends AlignCalcWorker
{
- FeatureCounterI counter;
+ FeatureSetCounterI counter;
/**
* Constructor registers the annotation for the given alignment frame
* @param af
* @param counter
*/
- public ColumnCounterWorker(AlignViewportI viewport,
- AlignmentViewPanel panel, FeatureCounterI counter)
+ public ColumnCounterSetWorker(AlignViewportI viewport,
+ AlignmentViewPanel panel, FeatureSetCounterI counter)
{
super(viewport, panel);
ourAnnots = new ArrayList<AlignmentAnnotation>();
@Override
public void run()
{
+ boolean annotationAdded = false;
try
{
calcMan.notifyStart(this);
{
try
{
- computeAnnotations();
+ annotationAdded = computeAnnotations();
} catch (IndexOutOfBoundsException x)
{
// probable race condition. just finish and return without any fuss.
if (ap != null)
{
- ap.adjustAnnotationHeight();
+ if (annotationAdded)
+ {
+ ap.adjustAnnotationHeight();
+ }
ap.paintAlignment(true);
}
/**
* Scan each column of the alignment to calculate a count by feature type. Set
* the count as the value of the alignment annotation for that feature type.
+ *
+ * @return
*/
- void computeAnnotations()
+ boolean computeAnnotations()
{
FeatureRenderer fr = new FeatureRenderer(alignViewport);
// TODO use the commented out code once JAL-2075 is fixed
// AlignmentView alignmentView = alignViewport.getAlignmentView(false);
// AlignmentI alignment = alignmentView.getVisibleAlignment(' ');
- // int width = alignmentView.getWidth();
+ int rows = counter.getNames().length;
+
int width = alignment.getWidth();
int height = alignment.getHeight();
- int[] counts = new int[width];
- int max = 0;
+ int[][] counts = new int[width][rows];
+ int max[] = new int[rows];
+ for (int crow = 0; crow < rows; crow++)
+ {
+ max[crow] = 0;
+ }
+
+ int[] minC = counter.getMinColour();
+ int[] maxC = counter.getMaxColour();
+ Color minColour = new Color(minC[0], minC[1], minC[2]);
+ Color maxColour = new Color(maxC[0], maxC[1], maxC[2]);
for (int col = 0; col < width; col++)
{
- int count = 0;
+ int[] count = counts[col];
+ for (int crow = 0; crow < rows; crow++)
+ {
+ count[crow] = 0;
+ }
for (int row = 0; row < height; row++)
{
- count += countFeaturesAt(alignment, col, row, fr);
+ int[] colcount = countFeaturesAt(alignment, col, row, fr);
+ if (colcount != null)
+ {
+ for (int crow = 0; crow < rows; crow++)
+ {
+ count[crow] += colcount[crow];
+ }
+ }
}
counts[col] = count;
- max = Math.max(count, max);
+ for (int crow = 0; crow < rows; crow++)
+ {
+ max[crow] = Math.max(count[crow], max[crow]);
+ }
}
- Annotation[] anns = new Annotation[width];
- /*
- * add non-zero counts as annotations
- */
- for (int i = 0; i < counts.length; i++)
+ boolean annotationAdded = false;
+
+ for (int anrow = 0; anrow < rows; anrow++)
{
- int count = counts[i];
- if (count > 0)
+ Annotation[] anns = new Annotation[width];
+ long rmax = 0;
+ /*
+ * add counts as annotations. zeros are needed since select-by-annotation ignores empty annotation positions
+ */
+ for (int i = 0; i < counts.length; i++)
{
- Color color = ColorUtils.getGraduatedColour(count, 0, Color.cyan,
- max, Color.blue);
+ int count = counts[i][anrow];
+
+ Color color = ColorUtils.getGraduatedColour(count, 0, minColour,
+ max[anrow], maxColour);
String str = String.valueOf(count);
anns[i] = new Annotation(str, str, '0', count, color);
+ rmax = Math.max(count, rmax);
}
- }
- /*
- * construct or update the annotation
- */
- AlignmentAnnotation ann = alignViewport.getAlignment()
- .findOrCreateAnnotation(counter.getName(),
- counter.getDescription(), false, null, null);
- ann.description = counter.getDescription();
- ann.showAllColLabels = true;
- ann.scaleColLabel = true;
- ann.graph = AlignmentAnnotation.BAR_GRAPH;
- ann.annotations = anns;
- setGraphMinMax(ann, anns);
- ann.validateRangeAndDisplay();
- if (!ourAnnots.contains(ann))
- {
- ourAnnots.add(ann);
+ /*
+ * construct or update the annotation
+ */
+ String description = counter.getDescriptions()[anrow];
+ if (!alignment.findAnnotation(description).iterator().hasNext())
+ {
+ annotationAdded = true;
+ }
+ AlignmentAnnotation ann = alignment.findOrCreateAnnotation(
+ counter.getNames()[anrow], description, false, null, null);
+ ann.description = description;
+ ann.showAllColLabels = true;
+ ann.scaleColLabel = true;
+ ann.graph = AlignmentAnnotation.BAR_GRAPH;
+ ann.annotations = anns;
+ ann.graphMin = 0f; // minimum always zero count
+ ann.graphMax = rmax; // maximum count from loop over feature columns
+ ann.validateRangeAndDisplay();
+ if (!ourAnnots.contains(ann))
+ {
+ ourAnnots.add(ann);
+ }
}
+ return annotationAdded;
}
/**
*
* @param alignment
* @param col
+ * (0..)
* @param row
* @param fr
*/
- int countFeaturesAt(AlignmentI alignment, int col, int row,
+ int[] countFeaturesAt(AlignmentI alignment, int col, int row,
FeatureRenderer fr)
{
SequenceI seq = alignment.getSequenceAt(row);
if (seq == null)
{
- return 0;
+ return null;
}
if (col >= seq.getLength())
{
- return 0;// sequence doesn't extend this far
+ return null;// sequence doesn't extend this far
}
char res = seq.getCharAt(col);
if (Comparison.isGap(res))
{
- return 0;
+ return null;
}
- int pos = seq.findPosition(col);
/*
* compute a count for any displayed features at residue
*/
- // NB have to adjust pos if using AlignmentView.getVisibleAlignment
// see JAL-2075
- List<SequenceFeature> features = fr.findFeaturesAtRes(seq, pos);
- int count = this.counter.count(String.valueOf(res), features);
+ List<SequenceFeature> features = fr.findFeaturesAtColumn(seq, col + 1);
+ int[] count = this.counter.count(String.valueOf(res), features);
return count;
}