JAL-1432 updated copyright notices
[jalview.git] / src / jalview / analysis / Dna.java
index f0041f6..e74d4b5 100644 (file)
@@ -1,6 +1,6 @@
 /*
- * Jalview - A Sequence Alignment Editor and Viewer (Version 2.8)
- * Copyright (C) 2012 J Procter, AM Waterhouse, LM Lui, J Engelhardt, G Barton, M Clamp, S Searle
+ * Jalview - A Sequence Alignment Editor and Viewer (Version 2.8.0b1)
+ * Copyright (C) 2014 The Jalview Authors
  * 
  * This file is part of Jalview.
  * 
@@ -14,6 +14,7 @@
  * PURPOSE.  See the GNU General Public License for more details.
  * 
  * You should have received a copy of the GNU General Public License along with Jalview.  If not, see <http://www.gnu.org/licenses/>.
+ * The Jalview Authors are detailed in the 'AUTHORS' file.
  */
 package jalview.analysis;
 
@@ -125,17 +126,20 @@ public class Dna
     {
       SequenceI newseq = translateCodingRegion(selection[s], seqstring[s],
               viscontigs, codons, gapCharacter,
-              (product != null) ? product[s] : null); // possibly anonymous
+              (product != null) ? product[s] : null, false); // possibly anonymous
       // product
       if (newseq != null)
       {
         pepseqs.addElement(newseq);
         SequenceI ds = newseq;
-        while (ds.getDatasetSequence() != null)
+        if (dataset != null)
         {
-          ds = ds.getDatasetSequence();
+          while (ds.getDatasetSequence() != null)
+          {
+            ds = ds.getDatasetSequence();
+          }
+          dataset.addSequence(ds);
         }
-        dataset.addSequence(ds);
       }
     }
     if (codons.aaWidth == 0)
@@ -417,13 +421,36 @@ public class Dna
    * @param codons
    *          Definition of global ORF alignment reference frame
    * @param gapCharacter
-   * @param newSeq
    * @return sequence ready to be added to alignment.
+   * @deprecated Use {@link #translateCodingRegion(SequenceI,String,int[],AlignedCodonFrame,char,DBRefEntry,boolean)} instead
    */
   public static SequenceI translateCodingRegion(SequenceI selection,
           String seqstring, int[] viscontigs, AlignedCodonFrame codons,
           char gapCharacter, DBRefEntry product)
   {
+    return translateCodingRegion(selection, seqstring, viscontigs, codons,
+            gapCharacter, product, false);
+  }
+
+  /**
+   * Translate a na sequence
+   * 
+   * @param selection
+   *          sequence displayed under viscontigs visible columns
+   * @param seqstring
+   *          ORF read in some global alignment reference frame
+   * @param viscontigs
+   *          mapping from global reference frame to visible seqstring ORF read
+   * @param codons
+   *          Definition of global ORF alignment reference frame
+   * @param gapCharacter
+   * @param starForStop when true stop codons will translate as '*', otherwise as 'X'  
+   * @return sequence ready to be added to alignment.
+   */
+  public static SequenceI translateCodingRegion(SequenceI selection,
+          String seqstring, int[] viscontigs, AlignedCodonFrame codons,
+          char gapCharacter, DBRefEntry product, final boolean starForStop)
+  {
     java.util.List skip = new ArrayList();
     int skipint[] = null;
     ShiftList vismapping = new ShiftList(); // map from viscontigs to seqstring
@@ -480,23 +507,75 @@ public class Dna
             // edit scontigs
             skipint[0] = vismapping.shift(skipint[0]);
             skipint[1] = vismapping.shift(skipint[1]);
-            for (vc = 0; vc < scontigs.length; vc += 2)
+            for (vc = 0; vc < scontigs.length; )
             {
               if (scontigs[vc + 1] < skipint[0])
               {
+                // before skipint starts
+                vc += 2;
                 continue;
               }
+              if (scontigs[vc]>skipint[1])
+              {
+                // finished editing so
+                break;
+              }
+              // Edit the contig list to include the skipped region which did not translate
+              int[] t;
+              // from : s1 e1 s2 e2 s3 e3
+              // to s:  s1 e1 s2 k0 k1 e2 s3 e3
+              // list increases by one unless one boundary (s2==k0 or e2==k1) matches, and decreases by one if skipint intersects whole visible contig 
               if (scontigs[vc] <= skipint[0])
               {
                 if (skipint[0] == scontigs[vc])
                 {
-
+                  // skipint at start of contig
+                  // shift the start of this contig
+                  if (scontigs[vc + 1] > skipint[1])
+                  {
+                    scontigs[vc] = skipint[1];
+                    vc+=2;
+                  }
+                  else
+                  {
+                    if (scontigs[vc+1]==skipint[1])
+                    {
+                      // remove the contig
+                      t = new int[scontigs.length - 2];
+                      if (vc > 0)
+                      {
+                        System.arraycopy(scontigs, 0, t, 0, vc - 1);
+                      }
+                      if (vc + 2 < t.length)
+                      {
+                        System.arraycopy(scontigs, vc + 2, t, vc, t.length
+                              - vc + 2);
+                      }
+                      scontigs=t;
+                    } else {
+                      // truncate contig to before the skipint region
+                      scontigs[vc+1] = skipint[0]-1;
+                      vc+=2;
+                    }
+                  }
                 }
                 else
                 {
-                  int[] t = new int[scontigs.length + 2];
-                  System.arraycopy(scontigs, 0, t, 0, vc - 1);
-                  // scontigs[vc]; //
+                  // scontig starts before start of skipint
+                  if (scontigs[vc+1]<skipint[1]) {
+                    // skipint truncates end of scontig
+                    scontigs[vc+1] = skipint[0]-1; 
+                    vc+=2;
+                  } else {
+                    // divide region to new contigs
+                    t = new int[scontigs.length + 2];
+                    System.arraycopy(scontigs, 0, t, 0, vc +1);
+                    t[vc+1] = skipint[0];
+                    t[vc+2] = skipint[1];
+                    System.arraycopy(scontigs, vc + 1, t, vc+3, scontigs.length-(vc+1));
+                    scontigs=t;
+                    vc+=4;
+                  }
                 }
               }
             }
@@ -505,7 +584,7 @@ public class Dna
           }
           if (aa.equals("STOP"))
           {
-            aa = "X";
+            aa = starForStop ? "*" : "X";
           }
           resSize++;
         }
@@ -562,8 +641,11 @@ public class Dna
               protein.toString());
       if (rf != 0)
       {
-        jalview.bin.Cache.log
-                .debug("trimming contigs for incomplete terminal codon.");
+        if (jalview.bin.Cache.log!=null) {
+          jalview.bin.Cache.log.debug("trimming contigs for incomplete terminal codon.");
+        } else {
+          System.err.println("trimming contigs for incomplete terminal codon.");
+        }
         // map and trim contigs to ORF region
         vc = scontigs.length - 1;
         lastnpos = vismapping.shift(lastnpos); // place npos in context of
@@ -676,7 +758,7 @@ public class Dna
   private static void transferCodedFeatures(SequenceI dna, SequenceI pep,
           MapList map, Hashtable featureTypes, Hashtable featureGroups)
   {
-    SequenceFeature[] sf = dna.getDatasetSequence().getSequenceFeatures();
+    SequenceFeature[] sf = (dna.getDatasetSequence()!=null ? dna.getDatasetSequence() : dna).getSequenceFeatures();
     Boolean fgstate;
     jalview.datamodel.DBRefEntry[] dnarefs = jalview.util.DBRefUtils
             .selectRefs(dna.getDBRef(),