JAL-2110 use shared dataset when copying alignment for split frame
[jalview.git] / src / jalview / analysis / AlignmentUtils.java
index 6a9dc7b..aa7cb18 100644 (file)
@@ -1333,15 +1333,19 @@ public class AlignmentUtils
           Collection<String> types, List<SequenceI> forSequences,
           boolean anyType, boolean doShow)
   {
-    for (AlignmentAnnotation aa : al.getAlignmentAnnotation())
+    AlignmentAnnotation[] anns = al.getAlignmentAnnotation();
+    if (anns != null)
     {
-      if (anyType || types.contains(aa.label))
+      for (AlignmentAnnotation aa : anns)
       {
-        if ((aa.sequenceRef != null)
-                && (forSequences == null || forSequences
-                        .contains(aa.sequenceRef)))
+        if (anyType || types.contains(aa.label))
         {
-          aa.visible = doShow;
+          if ((aa.sequenceRef != null)
+                  && (forSequences == null || forSequences
+                          .contains(aa.sequenceRef)))
+          {
+            aa.visible = doShow;
+          }
         }
       }
     }
@@ -1403,11 +1407,14 @@ public class AlignmentUtils
    *          aligned dna sequences
    * @param dataset
    *          - throws error if not given a dataset
+   * @param products
+   *          (optional) to restrict results to CDS that map to specified
+   *          protein products
    * @return an alignment whose sequences are the cds-only parts of the dna
    *         sequences (or null if no mappings are found)
    */
   public static AlignmentI makeCdsAlignment(SequenceI[] dna,
-          AlignmentI dataset)
+          AlignmentI dataset, AlignmentI products)
   {
     if (dataset.getDataset() != null)
     {
@@ -1416,7 +1423,16 @@ public class AlignmentUtils
     }
     List<SequenceI> cdsSeqs = new ArrayList<SequenceI>();
     List<AlignedCodonFrame> mappings = dataset.getCodonFrames();
-    
+    HashSet<SequenceI> productSeqs = null;
+    if (products != null)
+    {
+      productSeqs = new HashSet<SequenceI>();
+      for (SequenceI seq : products.getSequences())
+      {
+        productSeqs.add(seq.getDatasetSequence() == null ? seq : seq
+                .getDatasetSequence());
+      }
+    }
 
     /*
      * construct CDS sequences from the (cds-to-protein) mappings made earlier;
@@ -1449,9 +1465,20 @@ public class AlignmentUtils
            * the dna mapping's product
            */
           SequenceI cdsSeq = null;
+
           // TODO better mappings collection data model so we can do
-          // a table lookup instead of double loops to find mappings
+          // a direct lookup instead of double loops to find mappings
+
           SequenceI proteinProduct = aMapping.getTo();
+
+          /*
+           * skip if not mapped to one of a specified set of proteins
+           */
+          if (productSeqs != null && !productSeqs.contains(proteinProduct))
+          {
+            continue;
+          }
+
           for (AlignedCodonFrame acf : MappingUtils
                   .findMappingsForSequence(proteinProduct, mappings))
           {
@@ -1540,7 +1567,7 @@ public class AlignmentUtils
 
     AlignmentI cds = new Alignment(cdsSeqs.toArray(new SequenceI[cdsSeqs
             .size()]));
-    cds.setDataset((Alignment) dataset);
+    cds.setDataset(dataset);
 
     return cds;
   }
@@ -2184,32 +2211,15 @@ public class AlignmentUtils
    * 
    * @param seqs
    * @param xrefs
+   * @param dataset
+   *          the alignment dataset shared by the new copy
    * @return
    */
   public static AlignmentI makeCopyAlignment(SequenceI[] seqs,
-          SequenceI[] xrefs)
+          SequenceI[] xrefs, AlignmentI dataset)
   {
     AlignmentI copy = new Alignment(new Alignment(seqs));
-
-    /*
-     * add mappings between sequences to the new alignment
-     */
-    AlignedCodonFrame mappings = new AlignedCodonFrame();
-    copy.addCodonFrame(mappings);
-    for (int i = 0; i < copy.getHeight(); i++)
-    {
-      SequenceI from = seqs[i];
-      SequenceI to = copy.getSequenceAt(i);
-      if (to.getDatasetSequence() != null)
-      {
-        to = to.getDatasetSequence();
-      }
-      int start = from.getStart();
-      int end = from.getEnd();
-      MapList map = new MapList(new int[] { start, end }, new int[] {
-          start, end }, 1, 1);
-      mappings.addMap(to, from, map);
-    }
+    copy.setDataset(dataset);
 
     SequenceIdMatcher matcher = new SequenceIdMatcher(seqs);
     if (xrefs != null)
@@ -2320,13 +2330,13 @@ public class AlignmentUtils
   {
     /*
      * Map will hold, for each aligned column position, a map of
-     * {unalignedSequence, sequenceCharacter} at that position.
+     * {unalignedSequence, characterPerSequence} at that position.
      * TreeMap keeps the entries in ascending column order. 
      */
     Map<Integer, Map<SequenceI, Character>> map = new TreeMap<Integer, Map<SequenceI, Character>>();
 
     /*
-     * r any sequences that have no mapping so can't be realigned
+     * record any sequences that have no mapping so can't be realigned
      */
     unmapped.addAll(unaligned.getSequences());
 
@@ -2375,6 +2385,15 @@ public class AlignmentUtils
       return false;
     }
 
+    /*
+     * invert mapping if it is from unaligned to aligned sequence
+     */
+    if (seqMap.getTo() == fromSeq.getDatasetSequence())
+    {
+      seqMap = new Mapping(seq.getDatasetSequence(), seqMap.getMap()
+              .getInverse());
+    }
+
     char[] fromChars = fromSeq.getSequence();
     int toStart = seq.getStart();
     char[] toChars = seq.getSequence();
@@ -2408,7 +2427,8 @@ public class AlignmentUtils
          * of the next character of the mapped-to sequence; stop when all
          * the characters of the range have been counted
          */
-        while (mappedCharPos <= range[1])
+        while (mappedCharPos <= range[1] && fromCol <= fromChars.length
+                && fromCol >= 0)
         {
           if (!Comparison.isGap(fromChars[fromCol - 1]))
           {