1 package jalview.ws2.actions.annotation;
3 import java.util.ArrayList;
4 import java.util.BitSet;
5 import java.util.Collections;
6 import java.util.HashMap;
10 import jalview.analysis.AlignSeq;
11 import jalview.analysis.SeqsetUtils;
12 import jalview.api.FeatureColourI;
13 import jalview.datamodel.AlignmentAnnotation;
14 import jalview.datamodel.AlignmentI;
15 import jalview.datamodel.AnnotatedCollectionI;
16 import jalview.datamodel.Sequence;
17 import jalview.datamodel.SequenceI;
18 import jalview.datamodel.features.FeatureMatcherSetI;
19 import jalview.schemes.ResidueProperties;
20 import jalview.util.Comparison;
21 import jalview.ws2.actions.BaseJob;
23 public class AnnotationJob extends BaseJob
25 final boolean[] gapMap;
27 final Map<String, SequenceI> seqNames;
33 List<AlignmentAnnotation> returnedAnnotations = Collections.emptyList();
35 Map<String, FeatureColourI> featureColours = Collections.emptyMap();
37 Map<String, FeatureMatcherSetI> featureFilters = Collections.emptyMap();
40 public AnnotationJob(List<SequenceI> inputSeqs, boolean[] gapMap,
41 Map<String, SequenceI> seqNames, int start, int end, int minSize)
45 this.seqNames = seqNames;
48 this.minSize = minSize;
52 public boolean isInputValid()
55 for (SequenceI sq : getInputSequences())
56 if (sq.getStart() <= sq.getEnd())
58 return nvalid >= minSize;
61 public static AnnotationJob create(AnnotatedCollectionI inputSeqs,
62 boolean bySequence, boolean submitGaps, boolean requireAligned,
63 boolean filterNonStandardResidues, int minSize)
65 List<SequenceI> seqs = new ArrayList<>();
68 Map<String, SequenceI> seqNames = bySequence ? new HashMap<>() : null;
69 BitSet gapMap = new BitSet();
71 int start = inputSeqs.getStartRes();
72 int end = inputSeqs.getEndRes();
73 // TODO: URGENT! unify with JPred / MSA code to handle hidden regions
75 // TODO: push attributes into WsJob instance (so they can be safely
77 for (SequenceI sq : inputSeqs.getSequences())
81 sqlen = sq.findPosition(end + 1) - sq.findPosition(start + 1);
83 sqlen = sq.getEnd() - sq.getStart();
86 String newName = SeqsetUtils.unique_name(seqs.size() + 1);
88 seqNames.put(newName, sq);
92 seq = new Sequence(newName, sq.getSequenceAsString());
93 gapMapSize = Math.max(gapMapSize, seq.getLength());
94 for (int pos : sq.gapMap())
96 char sqchr = sq.getCharAt(pos);
97 boolean include = !filterNonStandardResidues;
98 include |= sq.isProtein() ? ResidueProperties.aaIndex[sqchr] < 20
99 : ResidueProperties.nucleotideIndex[sqchr] < 5;
106 // TODO: add ability to exclude hidden regions
107 seq = new Sequence(newName, AlignSeq.extractGaps(Comparison.GapChars,
108 sq.getSequenceAsString(start, end + 1)));
109 // for annotation need to also record map to sequence start/end
111 // then transfer back to original sequence on return.
114 ln = Math.max(ln, seq.getLength());
118 if (requireAligned && submitGaps)
120 int realWidth = gapMap.cardinality();
121 for (int i = 0; i < seqs.size(); i++)
123 SequenceI sq = seqs.get(i);
124 char[] padded = new char[realWidth];
125 char[] original = sq.getSequence();
126 for (int op = 0, pp = 0; pp < realWidth; op++)
130 if (original.length > op)
131 padded[pp++] = original[op];
136 seqs.set(i, new Sequence(sq.getName(), padded));
139 boolean[] gapMapArray = new boolean[gapMapSize];
140 for (int i = 0; i < gapMapSize; i++)
141 gapMapArray[i] = gapMap.get(i);
142 return new AnnotationJob(seqs, gapMapArray, seqNames, start, end, minSize);