From 349ef01fe53c28dc78bec2d321f9c833a4b6e023 Mon Sep 17 00:00:00 2001
From: jprocter <Jim Procter>
Date: Sun, 17 Jun 2007 12:59:15 +0000
Subject: [PATCH] AlignedCodonFrame holds mapping information between
 individual cDNA regions on dna and translated peptide
 sequences

---
 src/jalview/datamodel/AlignedCodonFrame.java |  222 ++++++++++++++++++++++++++
 src/jalview/datamodel/Alignment.java         |   81 ++++++++++
 src/jalview/datamodel/AlignmentI.java        |   28 ++++
 3 files changed, 331 insertions(+)
 create mode 100644 src/jalview/datamodel/AlignedCodonFrame.java

diff --git a/src/jalview/datamodel/AlignedCodonFrame.java b/src/jalview/datamodel/AlignedCodonFrame.java
new file mode 100644
index 0000000..c89c170
--- /dev/null
+++ b/src/jalview/datamodel/AlignedCodonFrame.java
@@ -0,0 +1,222 @@
+package jalview.datamodel;
+
+import jalview.util.MapList;
+
+/**
+ * Stores mapping between the columns of a protein alignment and a DNA alignment
+ * and a list of individual codon to amino acid mappings between sequences.
+ */
+
+public class AlignedCodonFrame
+{
+  /**
+   * array of nucleotide positions for aligned codons at column of aligned proteins.
+   */
+  public int[][] codons = null;
+  /**
+   * width of protein sequence alignement
+   * implicit assertion that codons.length >= aaWidth
+   */
+  public int aaWidth=0;
+  /**
+   * initialise codon frame with a nominal alignment width
+   * @param aWidth
+   */
+  public AlignedCodonFrame(int aWidth)
+  {
+    codons = new int[aWidth][];
+    for (int res = 0; res < aWidth; res++)
+      codons[res] = null;
+  }
+
+  /**
+   * ensure that codons array is at least as wide as aslen residues
+   * @param aslen
+   * @return (possibly newly expanded) codon array
+   */
+  public int[][] checkCodonFrameWidth(int aslen)
+  {
+    if (codons.length <= aslen + 1)
+    {
+      // probably never have to do this ?
+      int[][] c = new int[codons.length + 10][];
+      for (int i = 0; i < codons.length; i++)
+      {
+        c[i] = codons[i];
+        codons[i] = null;
+      }
+      codons = c;
+    }
+    return codons;
+  }
+  /**
+   * @return width of aligned translated amino acid residues 
+   */
+  public int getaaWidth()
+  {
+    return aaWidth;
+  }
+  /**
+   * increase aaWidth by one and insert a new aligned codon position space at aspos.
+   * @param aspos
+   */
+  public void insertAAGap(int aspos, char gapCharacter)
+  {            
+    // this aa appears before the aligned codons at aspos - so shift them in each pair of mapped sequences
+    aaWidth++;
+    for (int sq=0;aaSeqs!=null && sq<aaSeqs.length; sq++) {
+      aaSeqs[sq].insertCharAt(aspos, gapCharacter);
+    }
+
+    checkCodonFrameWidth(aspos);
+    if (aspos<aaWidth)
+    {
+      aaWidth++;
+      System.arraycopy(codons, aspos, codons, aspos+1, aaWidth-aspos);
+      codons[aspos]=null; // clear so new codon position can be marked.
+    }
+  }
+
+  public void setAaWidth(int aapos)
+  {
+    aaWidth = aapos;
+  }
+  /**
+   * tied array of na Sequence objects.
+   */
+  SequenceI[] dnaSeqs=null;
+  /**
+   * tied array of protein sequence Objects
+   */
+  SequenceI[] aaSeqs=null;
+  /**
+   * tied array of MapLists where eac maps from the corresponding dnaSeqs element to corresponding aaSeqs element  
+   */
+  MapList[] dnaToProt=null;
+  
+  public void addMap(SequenceI dnaseq, SequenceI aaseq, MapList map)
+  { 
+    int nlen=1;
+    if (dnaSeqs!=null)
+    {
+      nlen = dnaSeqs.length+1;
+    }
+    SequenceI[] ndna = new SequenceI[nlen];
+    SequenceI[] naa = new SequenceI[nlen];
+    MapList[] ndtp = new MapList[nlen];
+    if (dnaSeqs!=null)
+    {
+      System.arraycopy(dnaSeqs,0,ndna, 0, dnaSeqs.length);
+      System.arraycopy(aaSeqs,0,naa, 0, dnaSeqs.length);
+      System.arraycopy(dnaToProt,0,ndtp, 0, dnaSeqs.length);
+    }
+    dnaSeqs = ndna;
+    aaSeqs = naa;
+    dnaToProt = ndtp;
+    nlen--;
+    dnaSeqs[nlen] = (dnaseq.getDatasetSequence()==null) ? dnaseq : dnaseq.getDatasetSequence();
+    aaSeqs[nlen] = (aaseq.getDatasetSequence()==null) ? aaseq : aaseq.getDatasetSequence();
+    dnaToProt[nlen] = map;
+  }
+
+
+  public SequenceI[] getdnaSeqs()
+  {
+    return dnaSeqs;
+  }
+  public SequenceI[] getAaSeqs()
+  {
+    return aaSeqs;
+  }
+  public MapList[] getdnaToProt()
+  {
+    return dnaToProt;
+  }
+  /**
+   * 
+   * @param sequenceRef
+   * @return null or corresponding aaSeq entry for dnaSeq entry
+   */
+  public SequenceI getAaForDnaSeq(SequenceI dnaSeqRef)
+  {
+    if (dnaSeqs==null)
+    {
+      return null;
+    }
+    SequenceI dnads = dnaSeqRef.getDatasetSequence();
+    for (int ds=0;ds<dnaSeqs.length; ds++)
+    {
+      if (dnaSeqs[ds]==dnaSeqRef || dnaSeqs[ds]==dnads)
+        return aaSeqs[ds];
+    }
+    return null;
+  }
+  /**
+   * 
+   * @param sequenceRef
+   * @return null or corresponding aaSeq entry for dnaSeq entry
+   */
+  public SequenceI getDnaForAaSeq(SequenceI aaSeqRef)
+  {
+    if (aaSeqs==null)
+    {
+      return null;
+    }
+    SequenceI aads = aaSeqRef.getDatasetSequence();
+    for (int as=0;as<aaSeqs.length; as++)
+    {
+      if (aaSeqs[as]==aaSeqRef || aaSeqs[as]==aads)
+        return dnaSeqs[as];
+    }
+    return null;
+  }
+  /**
+   * test to see if codon frame involves seq in any way
+   * @param seq a nucleotide or protein sequence
+   * @return true if a mapping exists to or from this sequence to any translated sequence
+   */
+  public boolean involvesSequence(SequenceI seq)
+  {
+    return getAaForDnaSeq(seq)!=null || getDnaForAaSeq(seq)!=null;
+  }
+  /**
+   * Add search results for regions in other sequences that translate or are translated from a particular position in seq 
+   * @param seq
+   * @param index position in seq
+   * @param results where highlighted regions go
+   */
+  public void markMappedRegion(SequenceI seq, int index, SearchResults results)
+  {
+    int[] codon;
+    SequenceI ds = seq.getDatasetSequence();
+    for (int mi = 0; mi<aaSeqs.length; mi++)
+    {
+      if (dnaSeqs[mi]==seq || dnaSeqs[mi]==ds)
+      {
+        // DEBUG System.err.println("dna pos "+index);
+        codon = dnaToProt[mi].locateInTo(index,index);
+        if (codon!=null)
+        {
+          for (int i=0; i<codon.length; i+=2)
+            {
+              results.addResult(aaSeqs[mi], codon[i], codon[i+1]);
+            }
+        }
+      } else
+        if (aaSeqs[mi]==seq || aaSeqs[mi]==ds)
+        {
+          // DEBUG System.err.println("aa pos "+index);
+          {
+            codon = dnaToProt[mi].locateInFrom(index, index);
+            if (codon!=null)
+            {
+            for (int i=0; i<codon.length; i+=2)
+              {
+                results.addResult(dnaSeqs[mi], codon[i], codon[i+1]);
+              }
+          }
+        }
+        }
+    }
+  }
+}
diff --git a/src/jalview/datamodel/Alignment.java b/src/jalview/datamodel/Alignment.java
index 677f436..b3a5266 100755
--- a/src/jalview/datamodel/Alignment.java
+++ b/src/jalview/datamodel/Alignment.java
@@ -725,5 +725,86 @@ public class Alignment
   {
     return alignmentProperties;
   }
+  AlignedCodonFrame[] codonFrameList=null;
+  /* (non-Javadoc)
+   * @see jalview.datamodel.AlignmentI#addCodonFrame(jalview.datamodel.AlignedCodonFrame)
+   */
+  public void addCodonFrame(AlignedCodonFrame codons)
+  {
+    if (codons==null)
+      return;
+    if (codonFrameList==null)
+    {
+      codonFrameList = new AlignedCodonFrame[] { codons };
+      return;
+    }
+    AlignedCodonFrame[] t = new AlignedCodonFrame[codonFrameList.length+1];
+    System.arraycopy(codonFrameList, 0, t, 0, codonFrameList.length);
+    t[codonFrameList.length+1] = codons;
+    codonFrameList = t;
+  }
 
+  /* (non-Javadoc)
+   * @see jalview.datamodel.AlignmentI#getCodonFrame(int)
+   */
+  public AlignedCodonFrame getCodonFrame(int index)
+  {
+    return codonFrameList[index];
+  }
+
+  /* (non-Javadoc)
+   * @see jalview.datamodel.AlignmentI#getCodonFrame(jalview.datamodel.SequenceI)
+   */
+  public AlignedCodonFrame[] getCodonFrame(SequenceI seq)
+  {
+    if (seq==null || codonFrameList==null)
+      return null;
+    Vector cframes=new Vector();
+    for (int f=0;f<codonFrameList.length; f++)
+    {
+      if (codonFrameList[f].involvesSequence(seq))
+        cframes.add(codonFrameList[f]);
+    }
+    if (cframes.size()==0)
+      return null;
+    AlignedCodonFrame[] cfr = new AlignedCodonFrame[cframes.size()];
+    cframes.copyInto(cfr);
+    return cfr;
+  }
+
+  /* (non-Javadoc)
+   * @see jalview.datamodel.AlignmentI#getCodonFrames()
+   */
+  public AlignedCodonFrame[] getCodonFrames()
+  {
+    return codonFrameList;
+  }
+
+  /* (non-Javadoc)
+   * @see jalview.datamodel.AlignmentI#removeCodonFrame(jalview.datamodel.AlignedCodonFrame)
+   */
+  public boolean removeCodonFrame(AlignedCodonFrame codons)
+  {
+    if (codons==null || codonFrameList==null)
+      return false;
+    boolean removed=false;
+    int i=0,iSize=codonFrameList.length;
+    while (i<iSize)
+    {
+      if (codonFrameList[i]==codons)
+      {
+        removed=true;
+        if (i+1<iSize)
+        {
+          System.arraycopy(codonFrameList,i+1,codonFrameList, i, iSize-i-1);
+        }
+        iSize--;
+      }
+      else
+      {
+        i++;
+      }
+    }
+    return removed;
+  }
 }
diff --git a/src/jalview/datamodel/AlignmentI.java b/src/jalview/datamodel/AlignmentI.java
index 34a5ff2..82aff33 100755
--- a/src/jalview/datamodel/AlignmentI.java
+++ b/src/jalview/datamodel/AlignmentI.java
@@ -267,4 +267,32 @@ public interface AlignmentI
    * @return hashtable of alignment properties (or null if none are defined)
    */
   public Hashtable getProperties();
+
+  /**
+   * add a reference to a frame of aligned codons for this alignment
+   * @param codons
+   */
+  public void addCodonFrame(AlignedCodonFrame codons);
+  /**
+   * remove a particular codon frame reference from this alignment
+   * @param codons
+   * @return true if codon frame was removed.
+   */
+  public boolean removeCodonFrame(AlignedCodonFrame codons);
+  /**
+   * get all codon frames associated with this alignment
+   * @return
+   */
+  public AlignedCodonFrame[] getCodonFrames();
+  /**
+   * get a particular codon frame
+   * @param index
+   * @return
+   */
+  public AlignedCodonFrame getCodonFrame(int index);
+  /**
+   * get codon frames involving sequenceI
+   */
+  public AlignedCodonFrame[] getCodonFrame(SequenceI seq);
+  
 }
-- 
1.7.10.2