Clover icon

Coverage Report

  1. Project Clover database Wed Nov 13 2024 16:21:17 GMT
  2. Package jalview.workers

File ColumnCounterSetWorker.java

 

Coverage histogram

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

Code metrics

38
87
6
1
284
182
28
0.32
14.5
6
4.67

Classes

Class Line # Actions
ColumnCounterSetWorker 46 87 28
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 try
74    {
75  0 calcMan.notifyStart(this);
76   
77  0 while (!calcMan.notifyWorking(this))
78    {
79  0 try
80    {
81  0 Thread.sleep(200);
82    } catch (InterruptedException ex)
83    {
84  0 ex.printStackTrace();
85    }
86    }
87  0 if (alignViewport.isClosed())
88    {
89  0 abortAndDestroy();
90  0 return;
91    }
92   
93  0 if (alignViewport.getAlignment() != null)
94    {
95  0 try
96    {
97  0 annotationAdded = computeAnnotations();
98    } catch (IndexOutOfBoundsException x)
99    {
100    // probable race condition. just finish and return without any fuss.
101  0 return;
102    }
103    }
104    } catch (OutOfMemoryError error)
105    {
106  0 ap.raiseOOMWarning("calculating feature counts", error);
107  0 calcMan.disableWorker(this);
108    } finally
109    {
110  0 calcMan.workerComplete(this);
111    }
112   
113  0 if (ap != null)
114    {
115  0 if (annotationAdded)
116    {
117  0 ap.adjustAnnotationHeight();
118    }
119  0 ap.paintAlignment(true, true);
120    }
121   
122    }
123   
124    /**
125    * Scan each column of the alignment to calculate a count by feature type. Set
126    * the count as the value of the alignment annotation for that feature type.
127    *
128    * @return
129    */
 
130  0 toggle boolean computeAnnotations()
131    {
132  0 FeatureRenderer fr = new FeatureRenderer(alignViewport);
133    // TODO use the commented out code once JAL-2075 is fixed
134    // to get adequate performance on genomic length sequence
135  0 AlignmentI alignment = alignViewport.getAlignment();
136    // AlignmentView alignmentView = alignViewport.getAlignmentView(false);
137    // AlignmentI alignment = alignmentView.getVisibleAlignment(' ');
138   
139  0 int rows = counter.getNames().length;
140   
141  0 int width = alignment.getWidth();
142  0 int height = alignment.getHeight();
143  0 int[][] counts = new int[width][rows];
144  0 int max[] = new int[rows];
145  0 for (int crow = 0; crow < rows; crow++)
146    {
147  0 max[crow] = 0;
148    }
149   
150  0 int[] minC = counter.getMinColour();
151  0 int[] maxC = counter.getMaxColour();
152  0 Color minColour = new Color(minC[0], minC[1], minC[2]);
153  0 Color maxColour = new Color(maxC[0], maxC[1], maxC[2]);
154   
155  0 for (int col = 0; col < width; col++)
156    {
157  0 int[] count = counts[col];
158  0 for (int crow = 0; crow < rows; crow++)
159    {
160  0 count[crow] = 0;
161    }
162  0 for (int row = 0; row < height; row++)
163    {
164  0 int[] colcount = countFeaturesAt(alignment, col, row, fr);
165  0 if (colcount != null)
166    {
167  0 for (int crow = 0; crow < rows; crow++)
168    {
169  0 count[crow] += colcount[crow];
170    }
171    }
172    }
173  0 counts[col] = count;
174  0 for (int crow = 0; crow < rows; crow++)
175    {
176  0 max[crow] = Math.max(count[crow], max[crow]);
177    }
178    }
179   
180  0 boolean annotationAdded = false;
181   
182  0 for (int anrow = 0; anrow < rows; anrow++)
183    {
184  0 Annotation[] anns = new Annotation[width];
185  0 long rmax = 0;
186    /*
187    * add counts as annotations. zeros are needed since select-by-annotation ignores empty annotation positions
188    */
189  0 for (int i = 0; i < counts.length; i++)
190    {
191  0 int count = counts[i][anrow];
192   
193  0 Color color = ColorUtils.getGraduatedColour(count, 0, minColour,
194    max[anrow], maxColour);
195  0 String str = String.valueOf(count);
196  0 anns[i] = new Annotation(str, str, '0', count, color);
197  0 rmax = Math.max(count, rmax);
198    }
199   
200    /*
201    * construct or update the annotation
202    */
203  0 String description = counter.getDescriptions()[anrow];
204  0 if (!alignment.findAnnotation(description).iterator().hasNext())
205    {
206  0 annotationAdded = true;
207    }
208  0 AlignmentAnnotation ann = alignment.findOrCreateAnnotation(
209    counter.getNames()[anrow], description, false, null, null);
210  0 ann.description = description;
211  0 ann.showAllColLabels = true;
212  0 ann.scaleColLabel = true;
213  0 ann.graph = AlignmentAnnotation.BAR_GRAPH;
214  0 ann.annotations = anns;
215  0 ann.graphMin = 0f; // minimum always zero count
216  0 ann.graphMax = rmax; // maximum count from loop over feature columns
217  0 ann.validateRangeAndDisplay();
218  0 if (!ourAnnots.contains(ann))
219    {
220  0 ourAnnots.add(ann);
221    }
222    }
223  0 return annotationAdded;
224    }
225   
226    /**
227    * Returns a count of any feature types present at the specified position of
228    * the alignment
229    *
230    * @param alignment
231    * @param col
232    * (0..)
233    * @param row
234    * @param fr
235    */
 
236  0 toggle int[] countFeaturesAt(AlignmentI alignment, int col, int row,
237    FeatureRenderer fr)
238    {
239  0 SequenceI seq = alignment.getSequenceAt(row);
240  0 if (seq == null)
241    {
242  0 return null;
243    }
244  0 if (col >= seq.getLength())
245    {
246  0 return null;// sequence doesn't extend this far
247    }
248  0 char res = seq.getCharAt(col);
249  0 if (Comparison.isGap(res))
250    {
251  0 return null;
252    }
253   
254    /*
255    * compute a count for any displayed features at residue
256    */
257    // see JAL-2075
258  0 List<SequenceFeature> features = fr.findFeaturesAtColumn(seq, col + 1);
259  0 int[] count = this.counter.count(String.valueOf(res), features);
260  0 return count;
261    }
262   
263    /**
264    * Method called when the user changes display options that may affect how the
265    * annotation is rendered, but do not change its values. Currently no such
266    * options affect user-defined annotation, so this method does nothing.
267    */
 
268  0 toggle @Override
269    public void updateAnnotation()
270    {
271    // do nothing
272    }
273   
274    /**
275    * Answers true to indicate that if this worker's annotation is deleted from
276    * the display, the worker should also be removed. This prevents it running
277    * and recreating the annotation when the alignment changes.
278    */
 
279  0 toggle @Override
280    public boolean isDeletable()
281    {
282  0 return true;
283    }
284    }