Merge branch 'bug/JAL-3806_mappingCoversSequence_for2112' into develop bug/JAL-3806_without_shared_DS_for_2_11_2
authorJim Procter <j.procter@dundee.ac.uk>
Fri, 4 Feb 2022 14:34:20 +0000 (14:34 +0000)
committerJim Procter <j.procter@dundee.ac.uk>
Fri, 4 Feb 2022 14:34:20 +0000 (14:34 +0000)
Combines patches for JAL-3806 prior to redaction of shared CDS dataset sequences with patches for JAL-3673
 Conflicts:
src/jalview/datamodel/AlignedCodonFrame.java
src/jalview/util/MappingUtils.java
test/jalview/util/MappingUtilsTest.java

1  2 
src/jalview/datamodel/AlignedCodonFrame.java
src/jalview/util/MappingUtils.java
test/jalview/util/MappingUtilsTest.java

@@@ -160,7 -210,7 +210,7 @@@ public class AlignedCodonFram
      /**
       * Adds any regions mapped to or from position {@code pos} in sequence
       * {@code seq} to the given search results
--     * 
++     * Note: recommend first using the .covers(,true,true) to ensure mapping covers both sequences
       * @param seq
       * @param pos
       * @param sr
    public void markMappedRegion(SequenceI seq, int index,
            SearchResultsI results)
    {
 -    int[] codon;
      SequenceI ds = seq.getDatasetSequence();
 -    for (SequenceToSequenceMapping ssm : mappings)
 +    if (ds == null)
      {
 -      if (ssm.covers(seq,true,true))
 -      {
 -      if ((ssm.fromSeq == seq || ssm.fromSeq == ds))
 -      {
 -        codon = ssm.mapping.map.locateInTo(index, index);
 -        if (codon != null)
 -        {
 -          for (int i = 0; i < codon.length; i += 2)
 -          {
 -            results.addResult(ssm.mapping.to, codon[i], codon[i + 1]);
 -          }
 -        }
 -      }
 -      else if ((ssm.mapping.to == seq || ssm.mapping.to == ds))
 -      {
 -        {
 -          codon = ssm.mapping.map.locateInFrom(index, index);
 -          if (codon != null)
 -          {
 -            for (int i = 0; i < codon.length; i += 2)
 -            {
 -              results.addResult(ssm.fromSeq, codon[i], codon[i + 1]);
 -            }
 -          }
 -        }
 -      }}
 +      ds = seq;
      }
 -  }
 -
 -  /**
 -   * Returns the DNA codon positions (base 1) for the given position (base 1) in
 -   * a mapped protein sequence, or null if no mapping is found.
 -   * 
 -   * Intended for use in aligning cDNA to match aligned protein. Only the first
 -   * mapping found is returned, so not suitable for use if multiple protein
 -   * sequences are mapped to the same cDNA (but aligning cDNA as protein is
 -   * ill-defined for this case anyway).
 -   * 
 -   * @param seq
 -   *          the DNA dataset sequence
 -   * @param aaPos
 -   *          residue position (base 1) in a protein sequence
 -   * @return
 -   */
 -  public int[] getDnaPosition(SequenceI seq, int aaPos)
 -  {
 -    /*
 -     * Adapted from markMappedRegion().
 -     */
 -    MapList ml = null;
 -    int i = 0;
      for (SequenceToSequenceMapping ssm : mappings)
      {
-       ssm.markMappedRegion(ds, index, results);
 -      if (ssm.fromSeq == seq)
 -      {
 -        ml = getdnaToProt()[i];
 -        break;
++      if (ssm.covers(seq,true,true)) {
++        ssm.markMappedRegion(ds, index, results);
+       }
 -      i++;
      }
 -    return ml == null ? null : ml.locateInFrom(aaPos, aaPos);
    }
  
    /**
@@@ -363,49 -364,53 +364,55 @@@ public final class MappingUtil
         */
        int startResiduePos = selected.findPosition(firstUngappedPos);
        int endResiduePos = selected.findPosition(lastUngappedPos);
-       for (AlignedCodonFrame acf : codonFrames)
+       for (SequenceI seq : mapTo.getAlignment().getSequences())
        {
-         for (SequenceI seq : mapTo.getAlignment().getSequences())
+         int mappedStartResidue = 0;
+         int mappedEndResidue = 0;
+         for (AlignedCodonFrame acf : codonFrames)
          {
-           SequenceI peptide = targetIsNucleotide ? selected : seq;
-           SequenceI cds = targetIsNucleotide ? seq : selected;
-           SequenceToSequenceMapping s2s = acf.getCoveringMapping(cds,
-                   peptide);
-           if (s2s == null)
-           {
-             continue;
-           }
-           int mappedStartResidue = 0;
-           int mappedEndResidue = 0;
-           List<AlignedCodonFrame> mapping = Arrays.asList(acf);
-           SearchResultsI sr = buildSearchResults(selected, startResiduePos,
-                   mapping);
-           for (SearchResultMatchI m : sr.getResults())
++          // rather than use acf.getCoveringMapping() we iterate through all
++          // mappings to make sure all CDS are selected for a protein
+           for (SequenceToSequenceMapping map: acf.getMappings())
            {
-             mappedStartResidue = m.getStart();
-             mappedEndResidue = m.getEnd();
-           }
-           sr = buildSearchResults(selected, endResiduePos, mapping);
-           for (SearchResultMatchI m : sr.getResults())
+           if (map.covers(selected) && map.covers(seq))
            {
-             mappedStartResidue = Math.min(mappedStartResidue, m.getStart());
-             mappedEndResidue = Math.max(mappedEndResidue, m.getEnd());
-           }
+             /*
+              * Found a sequence mapping. Locate the start/end mapped residues.
+              */
+             List<AlignedCodonFrame> mapping = Arrays
+                     .asList(new AlignedCodonFrame[]
+                     { acf });
+             // locate start 
+             SearchResultsI sr = buildSearchResults(selected,
+                     startResiduePos, mapping);
+             for (SearchResultMatchI m : sr.getResults())
+             {
+               mappedStartResidue = m.getStart();
+               mappedEndResidue = m.getEnd();
+             }
+             // locate end - allowing for adjustment of start range
+             sr = buildSearchResults(selected, endResiduePos, mapping);
+             for (SearchResultMatchI 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;
-         }
+             /*
+              * 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;
+           }
+         }}
        }
      }
      mappedGroup.setStartRes(minStartCol < 0 ? 0 : minStartCol);