X-Git-Url: http://source.jalview.org/gitweb/?a=blobdiff_plain;ds=sidebyside;f=src%2Fjalview%2Futil%2FMappingUtils.java;h=f2213adcdcffa65363e887cf4b6cad441f17a4ec;hb=b6d073bedc4b28e1a0e5a3a899cfb0e32349087e;hp=4cfb49ea09f72eecf4e59e9c87eec6d9953b4ab1;hpb=be32c14cd8e48fe0a207cd7030cb9cd46f894678;p=jalview.git diff --git a/src/jalview/util/MappingUtils.java b/src/jalview/util/MappingUtils.java index 4cfb49e..f2213ad 100644 --- a/src/jalview/util/MappingUtils.java +++ b/src/jalview/util/MappingUtils.java @@ -1,5 +1,13 @@ package jalview.util; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Set; + import jalview.analysis.AlignmentSorter; import jalview.api.AlignViewportI; import jalview.commands.CommandI; @@ -17,13 +25,6 @@ import jalview.datamodel.Sequence; import jalview.datamodel.SequenceGroup; import jalview.datamodel.SequenceI; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Set; - /** * Helper methods for manipulations involving sequence mappings. * @@ -249,8 +250,23 @@ public final class MappingUtils public static SearchResults buildSearchResults(SequenceI seq, int index, Set seqmappings) { - SearchResults results; - results = new SearchResults(); + SearchResults results = new SearchResults(); + addSearchResults(results, seq, index, seqmappings); + return results; + } + + /** + * Adds entries to a SearchResults object describing the mapped region + * corresponding to the specified sequence position. + * + * @param results + * @param seq + * @param index + * @param seqmappings + */ + public static void addSearchResults(SearchResults results, SequenceI seq, + int index, Set seqmappings) + { if (index >= seq.getStart() && index <= seq.getEnd()) { for (AlignedCodonFrame acf : seqmappings) @@ -258,7 +274,6 @@ public final class MappingUtils acf.markMappedRegion(seq, index, results); } } - return results; } /** @@ -270,8 +285,8 @@ public final class MappingUtils * @param mapTo * @return */ - public static SequenceGroup mapSequenceGroup(SequenceGroup sg, - AlignViewportI mapFrom, AlignViewportI mapTo) + public static SequenceGroup mapSequenceGroup(final SequenceGroup sg, + final AlignViewportI mapFrom, final AlignViewportI mapTo) { /* * Note the SequenceGroup holds aligned sequences, the mappings hold dataset @@ -281,18 +296,50 @@ public final class MappingUtils AlignViewportI protein = targetIsNucleotide ? mapFrom : mapTo; Set codonFrames = protein.getAlignment() .getCodonFrames(); - /* - * Copy group name, name colours, but not sequences or sequence colour - * scheme + * Copy group name, colours etc, but not sequences or sequence colour scheme */ SequenceGroup mappedGroup = new SequenceGroup(sg); mappedGroup.cs = mapTo.getGlobalColourScheme(); mappedGroup.clear(); - // TODO set width of mapped group + int minStartCol = -1; + int maxEndCol = -1; + final int selectionStartRes = sg.getStartRes(); + final int selectionEndRes = sg.getEndRes(); for (SequenceI selected : sg.getSequences()) { + /* + * Find the widest range of non-gapped positions in the selection range + */ + int firstUngappedPos = selectionStartRes; + while (firstUngappedPos <= selectionEndRes + && Comparison.isGap(selected.getCharAt(firstUngappedPos))) + { + firstUngappedPos++; + } + + /* + * If this sequence is only gaps in the selected range, skip it + */ + if (firstUngappedPos > selectionEndRes) + { + continue; + } + + int lastUngappedPos = selectionEndRes; + while (lastUngappedPos >= selectionStartRes + && Comparison.isGap(selected.getCharAt(lastUngappedPos))) + { + lastUngappedPos--; + } + + /* + * Find the selected start/end residue positions in sequence + */ + int startResiduePos = selected.findPosition(firstUngappedPos); + int endResiduePos = selected.findPosition(lastUngappedPos); + for (AlignedCodonFrame acf : codonFrames) { SequenceI mappedSequence = targetIsNucleotide ? acf @@ -301,8 +348,39 @@ public final class MappingUtils { for (SequenceI seq : mapTo.getAlignment().getSequences()) { + int mappedStartResidue = 0; + int mappedEndResidue = 0; if (seq.getDatasetSequence() == mappedSequence) { + /* + * Found a sequence mapping. Locate the start/end mapped residues. + */ + SearchResults sr = buildSearchResults(selected, + startResiduePos, Collections.singleton(acf)); + for (Match m : sr.getResults()) + { + mappedStartResidue = m.getStart(); + mappedEndResidue = m.getEnd(); + } + sr = buildSearchResults(selected, endResiduePos, + Collections.singleton(acf)); + for (Match m : sr.getResults()) + { + mappedStartResidue = Math.min(mappedStartResidue, + m.getStart()); + mappedEndResidue = Math.max(mappedEndResidue, m.getEnd()); + } + + /* + * Find the mapped aligned columns, save the range. Note findIndex + * returns a base 1 position, SequenceGroup uses base 0 + */ + int mappedStartCol = seq.findIndex(mappedStartResidue) - 1; + minStartCol = minStartCol == -1 ? mappedStartCol : Math.min( + minStartCol, mappedStartCol); + int mappedEndCol = seq.findIndex(mappedEndResidue) - 1; + maxEndCol = maxEndCol == -1 ? mappedEndCol : Math.max( + maxEndCol, mappedEndCol); mappedGroup.addSequence(seq, false); break; } @@ -310,6 +388,8 @@ public final class MappingUtils } } } + mappedGroup.setStartRes(minStartCol < 0 ? 0 : minStartCol); + mappedGroup.setEndRes(maxEndCol < 0 ? 0 : maxEndCol); return mappedGroup; } @@ -333,18 +413,18 @@ public final class MappingUtils SequenceI[] sortOrder = command.getSequenceOrder(undo); List mappedOrder = new ArrayList(); int j = 0; + + /* + * Assumption: we are only interested in a cDNA/protein mapping; refactor in + * future if we want to support sorting (c)dna as (c)dna or protein as + * protein + */ + boolean mappingToNucleotide = mapTo.isNucleotide(); for (SequenceI seq : sortOrder) { for (AlignedCodonFrame acf : mappings) { - /* - * Try protein-to-Dna, failing that try dna-to-protein - */ - SequenceI mappedSeq = acf.getDnaForAaSeq(seq); - if (mappedSeq == null) - { - mappedSeq = acf.getAaForDnaSeq(seq); - } + SequenceI mappedSeq = mappingToNucleotide ? acf.getDnaForAaSeq(seq) : acf.getAaForDnaSeq(seq); if (mappedSeq != null) { for (SequenceI seq2 : mapTo.getSequences()) @@ -414,6 +494,12 @@ public final class MappingUtils Set codonFrames = protein.getAlignment() .getCodonFrames(); ColumnSelection mappedColumns = new ColumnSelection(); + + if (colsel == null) + { + return mappedColumns; + } + char fromGapChar = mapFrom.getAlignment().getGapCharacter(); // FIXME allow for hidden columns @@ -542,4 +628,28 @@ public final class MappingUtils } return result; } + + /** + * Returns a list of any mappings that are from or to the given (aligned or + * dataset) sequence. + * + * @param sequence + * @param mappings + * @return + */ + public static List findMappingsForSequence( + SequenceI sequence, Set mappings) + { + List result = new ArrayList(); + if (sequence == null || mappings == null) + { + return result; + } + for (AlignedCodonFrame mapping : mappings) { + if (mapping.involvesSequence(sequence)) { + result.add(mapping); + } + } + return result; + } }