X-Git-Url: http://source.jalview.org/gitweb/?a=blobdiff_plain;f=src%2Fjalview%2Fws2%2Factions%2Fannotation%2FAnnotationJob.java;h=467dafd774e2f5c119a6a0b204d494611eda1189;hb=a6aaf54e567106178f3f6733b59674f13522b919;hp=23e462b9f890910a61e9c12836ee920ee399ab97;hpb=e45f54d4072df812ae41de43105a302dc106ab43;p=jalview.git diff --git a/src/jalview/ws2/actions/annotation/AnnotationJob.java b/src/jalview/ws2/actions/annotation/AnnotationJob.java index 23e462b..467dafd 100644 --- a/src/jalview/ws2/actions/annotation/AnnotationJob.java +++ b/src/jalview/ws2/actions/annotation/AnnotationJob.java @@ -2,20 +2,15 @@ package jalview.ws2.actions.annotation; import java.util.ArrayList; import java.util.BitSet; -import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import jalview.analysis.AlignSeq; import jalview.analysis.SeqsetUtils; -import jalview.api.FeatureColourI; -import jalview.datamodel.AlignmentAnnotation; -import jalview.datamodel.AlignmentI; -import jalview.datamodel.AnnotatedCollectionI; import jalview.datamodel.Sequence; +import jalview.datamodel.SequenceCollectionI; import jalview.datamodel.SequenceI; -import jalview.datamodel.features.FeatureMatcherSetI; import jalview.schemes.ResidueProperties; import jalview.util.Comparison; import jalview.ws2.actions.BaseJob; @@ -26,25 +21,18 @@ public class AnnotationJob extends BaseJob final Map seqNames; - final int start, end; - - final int minSize; + final int regionStart, regionEnd; - List returnedAnnotations = Collections.emptyList(); - - Map featureColours = Collections.emptyMap(); - - Map featureFilters = Collections.emptyMap(); - + final int minSize; public AnnotationJob(List inputSeqs, boolean[] gapMap, - Map seqNames, int start, int end, int minSize) + Map seqNames, int start, int end, int minSize) { super(inputSeqs); this.gapMap = gapMap; this.seqNames = seqNames; - this.start = start; - this.end = end; + this.regionStart = start; + this.regionEnd = end; this.minSize = minSize; } @@ -58,16 +46,15 @@ public class AnnotationJob extends BaseJob return nvalid >= minSize; } - public static AnnotationJob create(AnnotatedCollectionI inputSeqs, - boolean bySequence, boolean submitGaps, boolean requireAligned, - boolean filterNonStandardResidues, int minSize) + public static AnnotationJob create(SequenceCollectionI inputSeqs, + boolean bySequence, boolean submitGaps, boolean requireAligned, + boolean filterNonStandardResidues, int minSize) { - List seqs = new ArrayList<>(); + List seqences = new ArrayList<>(); int minlen = 10; - int ln = -1; - Map seqNames = bySequence ? new HashMap<>() : null; - BitSet gapMap = new BitSet(); - int gapMapSize = 0; + int width = 0; + Map namesMap = bySequence ? new HashMap<>() : null; + BitSet residueMap = new BitSet(); int start = inputSeqs.getStartRes(); int end = inputSeqs.getEndRes(); // TODO: URGENT! unify with JPred / MSA code to handle hidden regions @@ -76,69 +63,88 @@ public class AnnotationJob extends BaseJob // persisted/restored for (SequenceI sq : inputSeqs.getSequences()) { - int sqlen; - if (bySequence) - sqlen = sq.findPosition(end + 1) - sq.findPosition(start + 1); + int sqLen = (bySequence) + ? sq.findPosition(end + 1) - sq.findPosition(start + 1) + : sq.getEnd() - sq.getStart(); + if (sqLen < minlen) + continue; + String newName = SeqsetUtils.unique_name(seqences.size() + 1); + if (namesMap != null) + namesMap.put(newName, sq); + Sequence seq; + if (submitGaps) + { + seq = new Sequence(newName, sq.getSequenceAsString()); + updateResidueMap(residueMap, seq, filterNonStandardResidues); + } else - sqlen = sq.getEnd() - sq.getStart(); - if (sqlen >= minlen) { - String newName = SeqsetUtils.unique_name(seqs.size() + 1); - if (seqNames != null) - seqNames.put(newName, sq); - Sequence seq; - if (submitGaps) - { - seq = new Sequence(newName, sq.getSequenceAsString()); - gapMapSize = Math.max(gapMapSize, seq.getLength()); - for (int pos : sq.gapMap()) - { - char sqchr = sq.getCharAt(pos); - boolean include = !filterNonStandardResidues; - include |= sq.isProtein() ? ResidueProperties.aaIndex[sqchr] < 20 - : ResidueProperties.nucleotideIndex[sqchr] < 5; - if (include) - gapMap.set(pos); - } - } - else - { - // TODO: add ability to exclude hidden regions - seq = new Sequence(newName, AlignSeq.extractGaps(Comparison.GapChars, - sq.getSequenceAsString(start, end + 1))); - // for annotation need to also record map to sequence start/end - // position in range - // then transfer back to original sequence on return. - } - seqs.add(seq); - ln = Math.max(ln, seq.getLength()); + // TODO: add ability to exclude hidden regions + seq = new Sequence(newName, + AlignSeq.extractGaps(Comparison.GapChars, + sq.getSequenceAsString(start, end + 1))); + // for annotation need to also record map to sequence start/end + // position in range + // then transfer back to original sequence on return. } + seqences.add(seq); + width = Math.max(width, seq.getLength()); } if (requireAligned && submitGaps) { - int realWidth = gapMap.cardinality(); - for (int i = 0; i < seqs.size(); i++) + for (int i = 0; i < seqences.size(); i++) + { + SequenceI sq = seqences.get(i); + char[] padded = fitSequenceToResidueMap(sq.getSequence(), + residueMap); + seqences.set(i, new Sequence(sq.getName(), padded)); + } + } + boolean[] gapMapArray = null; + if (submitGaps) + { + gapMapArray = new boolean[width]; + for (int i = 0; i < width; i++) + gapMapArray[i] = residueMap.get(i); + } + return new AnnotationJob(seqences, gapMapArray, namesMap, start, end, + minSize); + } + + private static void updateResidueMap(BitSet residueMap, SequenceI seq, + boolean filterNonStandardResidues) + { + for (int pos : seq.gapMap()) + { + char sqchr = seq.getCharAt(pos); + boolean include = !filterNonStandardResidues; + include |= seq.isProtein() ? ResidueProperties.aaIndex[sqchr] < 20 + : ResidueProperties.nucleotideIndex[sqchr] < 5; + if (include) + residueMap.set(pos); + } + } + + /** + * Fits the sequence to the residue map removing empty columns where residue + * map is unset and padding the sequence with gaps at the end if needed. + */ + private static char[] fitSequenceToResidueMap(char[] sequence, + BitSet residueMap) + { + int width = residueMap.cardinality(); + char[] padded = new char[width]; + for (int op = 0, pp = 0; pp < width; op++) + { + if (residueMap.get(op)) { - SequenceI sq = seqs.get(i); - char[] padded = new char[realWidth]; - char[] original = sq.getSequence(); - for (int op = 0, pp = 0; pp < realWidth; op++) - { - if (gapMap.get(op)) - { - if (original.length > op) - padded[pp++] = original[op]; - else - padded[pp++] = '-'; - } - } - seqs.set(i, new Sequence(sq.getName(), padded)); + if (sequence.length > op) + padded[pp++] = sequence[op]; + else + padded[pp++] = '-'; } } - boolean[] gapMapArray = new boolean[gapMapSize]; - for (int i = 0; i < gapMapSize; i++) - gapMapArray[i] = gapMap.get(i); - return new AnnotationJob(seqs, gapMapArray, seqNames, start, end, minSize); + return padded; } }