Clover icon

Coverage Report

  1. Project Clover database Thu Dec 4 2025 16:11:35 GMT
  2. Package jalview.workers

File ColumnCounterSetWorker.java

 

Coverage histogram

../../img/srcFileCovDistChart0.png
60% of files have more coverage

Code metrics

36
78
6
1
262
161
25
0.32
13
6
4.17

Classes

Class Line # Actions
ColumnCounterSetWorker 46 78 25
0.00%
 

Contributing tests

No tests hitting this source file were found.

Source view

1    /*
2    * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
3    * Copyright (C) $$Year-Rel$$ The Jalview Authors
4    *
5    * This file is part of Jalview.
6    *
7    * Jalview is free software: you can redistribute it and/or
8    * modify it under the terms of the GNU General Public License
9    * as published by the Free Software Foundation, either version 3
10    * of the License, or (at your option) any later version.
11    *
12    * Jalview is distributed in the hope that it will be useful, but
13    * WITHOUT ANY WARRANTY; without even the implied warranty
14    * of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15    * PURPOSE. See the GNU General Public License for more details.
16    *
17    * You should have received a copy of the GNU General Public License
18    * along with Jalview. If not, see <http://www.gnu.org/licenses/>.
19    * The Jalview Authors are detailed in the 'AUTHORS' file.
20    */
21    package jalview.workers;
22   
23    import jalview.api.AlignViewportI;
24    import jalview.api.AlignmentViewPanel;
25    import jalview.datamodel.AlignmentAnnotation;
26    import jalview.datamodel.AlignmentI;
27    import jalview.datamodel.Annotation;
28    import jalview.datamodel.SequenceFeature;
29    import jalview.datamodel.SequenceI;
30    import jalview.renderer.seqfeatures.FeatureRenderer;
31    import jalview.util.ColorUtils;
32    import jalview.util.Comparison;
33   
34    import java.awt.Color;
35    import java.util.ArrayList;
36    import java.util.List;
37   
38    /**
39    * A class to compute alignment annotations with column counts for a set of
40    * properties of interest on positions in an alignment. <br>
41    * This is designed to be extensible, by supplying to the constructor an object
42    * that computes a vector of counts for each residue position, based on the
43    * residue and and sequence features at that position.
44    *
45    */
 
46    class ColumnCounterSetWorker extends AlignCalcWorker
47    {
48    FeatureSetCounterI counter;
49   
50    /**
51    * Constructor registers the annotation for the given alignment frame
52    *
53    * @param af
54    * @param counter
55    */
 
56  0 toggle public ColumnCounterSetWorker(AlignViewportI viewport,
57    AlignmentViewPanel panel, FeatureSetCounterI counter)
58    {
59  0 super(viewport, panel);
60  0 ourAnnots = new ArrayList<>();
61  0 this.counter = counter;
62  0 calcMan.registerWorker(this);
63    }
64   
65    /**
66    * method called under control of AlignCalcManager to recompute the annotation
67    * when the alignment changes
68    */
 
69  0 toggle @Override
70    public void run()
71    {
72  0 boolean annotationAdded = false;
73  0 if (alignViewport.isClosed())
74    {
75  0 abortAndDestroy();
76  0 return;
77    }
78   
79  0 if (alignViewport.getAlignment() != null)
80    {
81  0 try
82    {
83  0 annotationAdded = computeAnnotations();
84    } catch (IndexOutOfBoundsException x)
85    {
86    // probable race condition. just finish and return without any fuss.
87  0 return;
88    }
89    }
90   
91  0 if (ap != null)
92    {
93  0 if (annotationAdded)
94    {
95  0 ap.adjustAnnotationHeight();
96    }
97  0 ap.paintAlignment(true, true);
98    }
99   
100    }
101   
102    /**
103    * Scan each column of the alignment to calculate a count by feature type. Set
104    * the count as the value of the alignment annotation for that feature type.
105    *
106    * @return
107    */
 
108  0 toggle boolean computeAnnotations()
109    {
110  0 FeatureRenderer fr = new FeatureRenderer(alignViewport);
111    // TODO use the commented out code once JAL-2075 is fixed
112    // to get adequate performance on genomic length sequence
113  0 AlignmentI alignment = alignViewport.getAlignment();
114    // AlignmentView alignmentView = alignViewport.getAlignmentView(false);
115    // AlignmentI alignment = alignmentView.getVisibleAlignment(' ');
116   
117  0 int rows = counter.getNames().length;
118   
119  0 int width = alignment.getWidth();
120  0 int height = alignment.getHeight();
121  0 int[][] counts = new int[width][rows];
122  0 int max[] = new int[rows];
123  0 for (int crow = 0; crow < rows; crow++)
124    {
125  0 max[crow] = 0;
126    }
127   
128  0 int[] minC = counter.getMinColour();
129  0 int[] maxC = counter.getMaxColour();
130  0 Color minColour = new Color(minC[0], minC[1], minC[2]);
131  0 Color maxColour = new Color(maxC[0], maxC[1], maxC[2]);
132   
133  0 for (int col = 0; col < width; col++)
134    {
135  0 int[] count = counts[col];
136  0 for (int crow = 0; crow < rows; crow++)
137    {
138  0 count[crow] = 0;
139    }
140  0 for (int row = 0; row < height; row++)
141    {
142  0 int[] colcount = countFeaturesAt(alignment, col, row, fr);
143  0 if (colcount != null)
144    {
145  0 for (int crow = 0; crow < rows; crow++)
146    {
147  0 count[crow] += colcount[crow];
148    }
149    }
150    }
151  0 counts[col] = count;
152  0 for (int crow = 0; crow < rows; crow++)
153    {
154  0 max[crow] = Math.max(count[crow], max[crow]);
155    }
156    }
157   
158  0 boolean annotationAdded = false;
159   
160  0 for (int anrow = 0; anrow < rows; anrow++)
161    {
162  0 Annotation[] anns = new Annotation[width];
163  0 long rmax = 0;
164    /*
165    * add counts as annotations. zeros are needed since select-by-annotation ignores empty annotation positions
166    */
167  0 for (int i = 0; i < counts.length; i++)
168    {
169  0 int count = counts[i][anrow];
170   
171  0 Color color = ColorUtils.getGraduatedColour(count, 0, minColour,
172    max[anrow], maxColour);
173  0 String str = String.valueOf(count);
174  0 anns[i] = new Annotation(str, str, '0', count, color);
175  0 rmax = Math.max(count, rmax);
176    }
177   
178    /*
179    * construct or update the annotation
180    */
181  0 String description = counter.getDescriptions()[anrow];
182  0 if (!alignment.findAnnotation(description).iterator().hasNext())
183    {
184  0 annotationAdded = true;
185    }
186  0 AlignmentAnnotation ann = alignment.findOrCreateAnnotation(
187    counter.getNames()[anrow], description, false, null, null);
188  0 ann.description = description;
189  0 ann.showAllColLabels = true;
190  0 ann.scaleColLabel = true;
191  0 ann.graph = AlignmentAnnotation.BAR_GRAPH;
192  0 ann.annotations = anns;
193  0 ann.graphMin = 0f; // minimum always zero count
194  0 ann.graphMax = rmax; // maximum count from loop over feature columns
195  0 ann.validateRangeAndDisplay();
196  0 if (!ourAnnots.contains(ann))
197    {
198  0 ourAnnots.add(ann);
199    }
200    }
201  0 return annotationAdded;
202    }
203   
204    /**
205    * Returns a count of any feature types present at the specified position of
206    * the alignment
207    *
208    * @param alignment
209    * @param col
210    * (0..)
211    * @param row
212    * @param fr
213    */
 
214  0 toggle int[] countFeaturesAt(AlignmentI alignment, int col, int row,
215    FeatureRenderer fr)
216    {
217  0 SequenceI seq = alignment.getSequenceAt(row);
218  0 if (seq == null)
219    {
220  0 return null;
221    }
222  0 if (col >= seq.getLength())
223    {
224  0 return null;// sequence doesn't extend this far
225    }
226  0 char res = seq.getCharAt(col);
227  0 if (Comparison.isGap(res))
228    {
229  0 return null;
230    }
231   
232    /*
233    * compute a count for any displayed features at residue
234    */
235    // see JAL-2075
236  0 List<SequenceFeature> features = fr.findFeaturesAtColumn(seq, col + 1);
237  0 int[] count = this.counter.count(String.valueOf(res), features);
238  0 return count;
239    }
240   
241    /**
242    * Method called when the user changes display options that may affect how the
243    * annotation is rendered, but do not change its values. Currently no such
244    * options affect user-defined annotation, so this method does nothing.
245    */
 
246  0 toggle @Override
247    public void updateAnnotation()
248    {
249    // do nothing
250    }
251   
252    /**
253    * Answers true to indicate that if this worker's annotation is deleted from
254    * the display, the worker should also be removed. This prevents it running
255    * and recreating the annotation when the alignment changes.
256    */
 
257  0 toggle @Override
258    public boolean isDeletable()
259    {
260  0 return true;
261    }
262    }