X-Git-Url: http://source.jalview.org/gitweb/?a=blobdiff_plain;f=src%2Fjalview%2Fdatamodel%2FAlignedCodonFrame.java;h=ec11fc13b73dfb193fedb4cddee7821fd88731be;hb=403014222ea05e99c1bddeb6aaf3a85078f99756;hp=3fc8c287ff472e17e4dcd258dfbd1474b3076592;hpb=a4ace9297e743fb504dffd43ebb11074db263e10;p=jalview.git diff --git a/src/jalview/datamodel/AlignedCodonFrame.java b/src/jalview/datamodel/AlignedCodonFrame.java index 3fc8c28..ec11fc1 100644 --- a/src/jalview/datamodel/AlignedCodonFrame.java +++ b/src/jalview/datamodel/AlignedCodonFrame.java @@ -23,6 +23,7 @@ package jalview.datamodel; import jalview.util.MapList; import jalview.util.MappingUtils; +import java.util.AbstractList; import java.util.ArrayList; import java.util.List; @@ -36,7 +37,7 @@ public class AlignedCodonFrame /* * Data bean to hold mappings from one sequence to another */ - private class SequenceToSequenceMapping + public class SequenceToSequenceMapping { private SequenceI fromSeq; @@ -57,6 +58,55 @@ public class AlignedCodonFrame return String.format("From %s %s", fromSeq.getName(), mapping.toString()); } + + /** + * Returns a hashCode derived from the hashcodes of the mappings and fromSeq + * + * @see SequenceToSequenceMapping#hashCode() + */ + @Override + public int hashCode() + { + return (fromSeq == null ? 0 : fromSeq.hashCode() * 31) + + mapping.hashCode(); + } + + /** + * Answers true if the objects hold the same mapping between the same two + * sequences + * + * @see Mapping#equals + */ + @Override + public boolean equals(Object obj) + { + if (!(obj instanceof SequenceToSequenceMapping)) + { + return false; + } + SequenceToSequenceMapping that = (SequenceToSequenceMapping) obj; + if (this.mapping == null) + { + return that.mapping == null; + } + // TODO: can simplify by asserting fromSeq is a dataset sequence + return (this.fromSeq == that.fromSeq + || (this.fromSeq != null && that.fromSeq != null + && this.fromSeq.getDatasetSequence() != null + && this.fromSeq.getDatasetSequence() == that.fromSeq + .getDatasetSequence())) + && this.mapping.equals(that.mapping); + } + + public SequenceI getFromSeq() + { + return fromSeq; + } + + public Mapping getMapping() + { + return mapping; + } } private List mappings; @@ -79,17 +129,34 @@ public class AlignedCodonFrame */ public void addMap(SequenceI dnaseq, SequenceI aaseq, MapList map) { + addMap(dnaseq, aaseq, map, null); + } + + /** + * Adds a mapping between the dataset sequences for the associated dna and + * protein sequence objects + * + * @param dnaseq + * @param aaseq + * @param map + * @param mapFromId + */ + public void addMap(SequenceI dnaseq, SequenceI aaseq, MapList map, + String mapFromId) + { // JBPNote DEBUG! THIS ! // dnaseq.transferAnnotation(aaseq, mp); // aaseq.transferAnnotation(dnaseq, new Mapping(map.getInverse())); SequenceI fromSeq = (dnaseq.getDatasetSequence() == null) ? dnaseq : dnaseq.getDatasetSequence(); - SequenceI toSeq = (aaseq.getDatasetSequence() == null) ? aaseq : aaseq - .getDatasetSequence(); + SequenceI toSeq = (aaseq.getDatasetSequence() == null) ? aaseq + : aaseq.getDatasetSequence(); /* * if we already hold a mapping between these sequences, just add to it + * note that 'adding' a duplicate map does nothing; this protects against + * creating duplicate mappings in AlignedCodonFrame */ for (SequenceToSequenceMapping ssm : mappings) { @@ -104,6 +171,7 @@ public class AlignedCodonFrame * otherwise, add a new sequence mapping */ Mapping mp = new Mapping(toSeq, map); + mp.setMappedFromId(mapFromId); mappings.add(new SequenceToSequenceMapping(fromSeq, mp)); } @@ -234,7 +302,7 @@ public class AlignedCodonFrame * where highlighted regions go */ public void markMappedRegion(SequenceI seq, int index, - SearchResults results) + SearchResultsI results) { int[] codon; SequenceI ds = seq.getDatasetSequence(); @@ -303,7 +371,8 @@ public class AlignedCodonFrame /** * Convenience method to return the first aligned sequence in the given - * alignment whose dataset has a mapping with the given dataset sequence. + * alignment whose dataset has a mapping with the given (aligned or dataset) + * sequence. * * @param seq * @@ -317,7 +386,7 @@ public class AlignedCodonFrame */ for (SequenceToSequenceMapping ssm : mappings) { - if (ssm.fromSeq == seq) + if (ssm.fromSeq == seq || ssm.fromSeq == seq.getDatasetSequence()) { for (SequenceI sourceAligned : al.getSequences()) { @@ -335,7 +404,8 @@ public class AlignedCodonFrame */ for (SequenceToSequenceMapping ssm : mappings) { - if (ssm.mapping.to == seq) + if (ssm.mapping.to == seq + || ssm.mapping.to == seq.getDatasetSequence()) { for (SequenceI sourceAligned : al.getSequences()) { @@ -365,8 +435,8 @@ public class AlignedCodonFrame { SequenceI targetDs = target.getDatasetSequence() == null ? target : target.getDatasetSequence(); - SequenceI queryDs = query.getDatasetSequence() == null ? query : query - .getDatasetSequence(); + SequenceI queryDs = query.getDatasetSequence() == null ? query + : query.getDatasetSequence(); if (targetDs == null || queryDs == null /*|| dnaToProt == null*/) { return null; @@ -419,7 +489,8 @@ public class AlignedCodonFrame for (SequenceToSequenceMapping ssm : mappings) { - if (ssm.mapping.to == protein) + if (ssm.mapping.to == protein + && ssm.mapping.getMap().getFromRatio() == 3) { ml = ssm.mapping.map; dnaSeq = ssm.fromSeq; @@ -434,23 +505,24 @@ public class AlignedCodonFrame * Read off the mapped nucleotides (converting to position base 0) */ codonPos = MappingUtils.flattenRanges(codonPos); - char[] dna = dnaSeq.getSequence(); int start = dnaSeq.getStart(); - result.add(new char[] { dna[codonPos[0] - start], - dna[codonPos[1] - start], dna[codonPos[2] - start] }); + char c1 = dnaSeq.getCharAt(codonPos[0] - start); + char c2 = dnaSeq.getCharAt(codonPos[1] - start); + char c3 = dnaSeq.getCharAt(codonPos[2] - start); + result.add(new char[] { c1, c2, c3 }); } } return result.isEmpty() ? null : result; } /** - * Returns any mappings found which are to (or from) the given sequence, and - * to distinct sequences. + * Returns any mappings found which are from the given sequence, and to + * distinct sequences. * * @param seq * @return */ - public List getMappingsForSequence(SequenceI seq) + public List getMappingsFromSequence(SequenceI seq) { List result = new ArrayList(); List related = new ArrayList(); @@ -460,7 +532,7 @@ public class AlignedCodonFrame for (SequenceToSequenceMapping ssm : mappings) { final Mapping mapping = ssm.mapping; - if (ssm.fromSeq == seqDs || mapping.to == seqDs) + if (ssm.fromSeq == seqDs) { if (!related.contains(mapping.to)) { @@ -509,8 +581,9 @@ public class AlignedCodonFrame */ protected int realiseWith(SequenceI seq, boolean doUpdate) { - SequenceI ds = seq.getDatasetSequence() != null ? seq - .getDatasetSequence() : seq; + SequenceI ds = seq.getDatasetSequence() != null + ? seq.getDatasetSequence() + : seq; int count = 0; /* @@ -584,8 +657,8 @@ public class AlignedCodonFrame { int start = replacement.getStart(); int end = replacement.getEnd(); - boolean mappingOverlapsSequence = (mapStart >= start && mapStart <= end) - || (mapEnd >= start && mapEnd <= end); + boolean mappingOverlapsSequence = (mapStart >= start + && mapStart <= end) || (mapEnd >= start && mapEnd <= end); if (mappingOverlapsSequence) { return true; @@ -638,4 +711,76 @@ public class AlignedCodonFrame { return mappings.isEmpty(); } + + /** + * Method for debug / inspection purposes only, may change in future + */ + @Override + public String toString() + { + return mappings == null ? "null" : mappings.toString(); + } + + /** + * Returns the first mapping found that is between 'fromSeq' and 'toSeq', or + * null if none found + * + * @param fromSeq + * aligned or dataset sequence + * @param toSeq + * aligned or dataset sequence + * @return + */ + public Mapping getMappingBetween(SequenceI fromSeq, SequenceI toSeq) + { + SequenceI dssFrom = fromSeq.getDatasetSequence() == null ? fromSeq + : fromSeq.getDatasetSequence(); + SequenceI dssTo = toSeq.getDatasetSequence() == null ? toSeq + : toSeq.getDatasetSequence(); + + for (SequenceToSequenceMapping mapping : mappings) + { + SequenceI from = mapping.fromSeq; + SequenceI to = mapping.mapping.to; + if ((from == dssFrom && to == dssTo) + || (from == dssTo && to == dssFrom)) + { + return mapping.mapping; + } + } + return null; + } + + /** + * Returns a hashcode derived from the list of sequence mappings + * + * @see SequenceToSequenceMapping#hashCode() + * @see AbstractList#hashCode() + */ + @Override + public int hashCode() + { + return this.mappings.hashCode(); + } + + /** + * Two AlignedCodonFrame objects are equal if they hold the same ordered list + * of mappings + * + * @see SequenceToSequenceMapping# + */ + @Override + public boolean equals(Object obj) + { + if (!(obj instanceof AlignedCodonFrame)) + { + return false; + } + return this.mappings.equals(((AlignedCodonFrame) obj).mappings); + } + + public List getMappings() + { + return mappings; + } }