Clover icon

Coverage Report

  1. Project Clover database Tue Mar 10 2026 14:58:44 GMT
  2. Package jalview.ws2.actions.annotation

File AnnotationJob.java

 

Coverage histogram

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

Code metrics

26
58
6
1
168
126
20
0.34
9.67
6
3.33

Classes

Class Line # Actions
AnnotationJob 19 58 20
0.00%
 

Contributing tests

No tests hitting this source file were found.

Source view

1    package jalview.ws2.actions.annotation;
2   
3    import java.util.ArrayList;
4    import java.util.Arrays;
5    import java.util.BitSet;
6    import java.util.HashMap;
7    import java.util.List;
8    import java.util.Map;
9   
10    import jalview.analysis.AlignSeq;
11    import jalview.analysis.SeqsetUtils;
12    import jalview.datamodel.Sequence;
13    import jalview.datamodel.SequenceCollectionI;
14    import jalview.datamodel.SequenceI;
15    import jalview.schemes.ResidueProperties;
16    import jalview.util.Comparison;
17    import jalview.ws2.actions.BaseJob;
18   
 
19    public class AnnotationJob extends BaseJob
20    {
21    final boolean[] gapMap;
22   
23    final Map<String, SequenceI> seqNames;
24   
25    final int regionStart, regionEnd;
26   
27    final int minSize;
28   
 
29  0 toggle public AnnotationJob(List<SequenceI> inputSeqs, boolean[] gapMap,
30    Map<String, SequenceI> seqNames, int start, int end, int minSize)
31    {
32  0 super(inputSeqs);
33  0 this.gapMap = gapMap;
34  0 this.seqNames = seqNames;
35  0 this.regionStart = start;
36  0 this.regionEnd = end;
37  0 this.minSize = minSize;
38    }
39   
 
40  0 toggle @Override
41    public boolean isInputValid()
42    {
43  0 int nvalid = 0;
44  0 for (SequenceI sq : getInputSequences())
45  0 if (sq.getStart() <= sq.getEnd())
46  0 nvalid++;
47  0 return nvalid >= minSize;
48    }
49   
 
50  0 toggle public static AnnotationJob create(SequenceCollectionI inputSeqs,
51    boolean bySequence, boolean submitGaps, boolean requireAligned,
52    boolean filterNonStandardResidues, int minSize)
53    {
54  0 List<SequenceI> sequences = new ArrayList<>();
55  0 int minlen = 10;
56  0 int width = 0;
57  0 Map<String, SequenceI> namesMap = bySequence ? new HashMap<>() : null;
58  0 BitSet residueMap = new BitSet();
59  0 int start = inputSeqs.getStartRes();
60  0 int end = inputSeqs.getEndRes();
61    // TODO: URGENT! unify with JPred / MSA code to handle hidden regions
62    // correctly
63    // TODO: push attributes into WsJob instance (so they can be safely
64    // persisted/restored
65  0 for (SequenceI sq : inputSeqs.getSequences())
66    {
67  0 int sqLen = (bySequence)
68    ? sq.findPosition(end + 1) - sq.findPosition(start + 1)
69    : sq.getEnd() - sq.getStart();
70  0 if (sqLen < minlen)
71  0 continue;
72  0 width = Math.max(width, sq.getLength());
73  0 String newName = SeqsetUtils.unique_name(sequences.size() + 1);
74  0 if (namesMap != null)
75  0 namesMap.put(newName, sq);
76  0 char[] seqChars = sq.getSequence(start, end + 1);
77  0 if (filterNonStandardResidues)
78  0 replaceNonStandardResidues(seqChars, Comparison.GAP_DASH,
79    sq.isProtein());
80  0 Sequence seq;
81  0 if (submitGaps)
82    {
83  0 seq = new Sequence(newName, seqChars);
84  0 updateResidueMap(residueMap, seq);
85    } else
86    {
87    // TODO: add ability to exclude hidden regions
88  0 seq = new Sequence(newName,
89    AlignSeq.extractGaps(Comparison.GapChars, new String(seqChars)));
90    // for annotation need to also record map to sequence start/end
91    // position in range
92    // then transfer back to original sequence on return.
93    }
94  0 sequences.add(seq);
95    }
96  0 boolean[] gapMapArray = null;
97  0 if (submitGaps)
98    {
99  0 adjustColumns(sequences, residueMap, requireAligned);
100  0 gapMapArray = new boolean[width];
101  0 for (int i = 0; i < width; i++)
102  0 gapMapArray[i] = residueMap.get(i);
103    }
104  0 return new AnnotationJob(sequences, gapMapArray, namesMap, start, end,
105    minSize);
106    }
107   
 
108  0 toggle static void replaceNonStandardResidues(char[] seq, char replacement,
109    boolean isProtein)
110    {
111  0 for (int i = 0; i < seq.length; i++)
112    {
113  0 char chr = seq[i];
114  0 if (isProtein ? ResidueProperties.aaIndex[chr] >= 20
115    : ResidueProperties.nucleotideIndex[chr] >= 5)
116    {
117  0 seq[i] = replacement;
118    }
119    }
120    }
121   
122    /**
123    * Add residue positions of the given sequence to the residues map. Perform an
124    * "or" operation between the given residue map and the inverse of the gap map
125    * of the given sequence.
126    *
127    * @param residueMap
128    * mapping to be updated in-place
129    * @param seq
130    * the sequence whose residue positions are added to the map
131    */
 
132  0 toggle static void updateResidueMap(BitSet residueMap, SequenceI seq)
133    {
134  0 var gaps = seq.gapBitset();
135  0 gaps.flip(0, seq.getLength());
136  0 residueMap.or(gaps);
137    }
138   
139    /**
140    * Remove columns not included in the mask from the sequences in-place. If
141    * {@code padToLength} is set, the shorter sequences are padded with gaps at
142    * the end.
143    *
144    * @param sequences
145    * list of sequences to be modified
146    * @param mask
147    * mask of columns that will remain
148    * @param padToLength
149    * if gaps should be added to the end of shorter sequences
150    */
 
151  0 toggle static void adjustColumns(List<SequenceI> sequences, BitSet mask,
152    boolean padToLength)
153    {
154  0 int width = mask.cardinality();
155  0 for (SequenceI seq : sequences)
156    {
157  0 char[] chars = SeqsetUtils.filterSequence(seq.getSequence(), mask);
158  0 if (padToLength && chars.length < width)
159    {
160  0 int limit = chars.length;
161  0 chars = Arrays.copyOf(chars, width);
162  0 Arrays.fill(chars, limit, chars.length, Comparison.GAP_DASH);
163    }
164  0 seq.setEnd(seq.getStart());
165  0 seq.setSequence(chars);
166    }
167    }
168    }