patch for structures with multiple models, and refactored seq/str binding methods
authorjprocter <Jim Procter>
Fri, 27 Aug 2010 15:43:15 +0000 (15:43 +0000)
committerjprocter <Jim Procter>
Fri, 27 Aug 2010 15:43:15 +0000 (15:43 +0000)
src/jalview/ext/jmol/JalviewJmolBinding.java

index f8fe17b..80cc8af 100644 (file)
@@ -229,6 +229,8 @@ public abstract class JalviewJmolBinding implements StructureListener,
   public void colourByChain()
   {
     colourBySequence = false;
+    // TODO: colour by chain should colour each chain distinctly across all visible models 
+    // TODO: http://issues.jalview.org/browse/JAL-628
     evalStateCommand("select *;color chain");
   }
 
@@ -662,16 +664,23 @@ public abstract class JalviewJmolBinding implements StructureListener,
 
   // ////////////////////////////////
   // /StructureListener
-  public String[] getPdbFile()
+  public synchronized String[] getPdbFile()
   {
     if (modelFileNames == null)
     {
       String mset[] = new String[viewer.getModelCount()];
-      for (int i = 0; i < mset.length; i++)
+      int j=1;
+      mset[0] = viewer.getModelFileName(0);
+      for (int i = 1; i < mset.length; i++)
       {
-        mset[i] = viewer.getModelFileName(i);
+        // skip any additional models in the same file (NMR structures) 
+        if (!(mset[j] = viewer.getModelFileName(i)).equals(mset[j-1]))
+        {
+          j++;
+        }
       }
-      modelFileNames = mset;
+      modelFileNames = new String[j];
+      System.arraycopy(mset, 0, modelFileNames, 0, j);
     }
     return modelFileNames;
   }
@@ -1252,4 +1261,142 @@ public abstract class JalviewJmolBinding implements StructureListener,
             + col.getGreen() + "," + col.getBlue() + "];");
     jmolHistory(true);
   }
+
+  /**
+   * add structures and any known sequence associations
+   * 
+   * @returns the pdb entries added to the current set.
+   */
+  public synchronized PDBEntry[] addSequenceAndChain(PDBEntry[] pdbe, SequenceI[][] seq,
+          String[][] chns)
+  {
+    int pe = -1;
+    Vector v = new Vector();
+    Vector rtn = new Vector();
+    for (int i = 0; i < pdbentry.length; i++)
+    {
+      v.addElement(pdbentry[i]);
+    }
+    for (int i = 0; i < pdbe.length; i++)
+    {
+      int r = v.indexOf(pdbe[i]);
+      if (r == -1 || r >= pdbentry.length)
+      {
+        rtn.addElement(new int[]
+        { v.size(), i });
+        v.addElement(pdbe[i]);
+      }
+      else
+      {
+        // just make sure the sequence/chain entries are all up to date
+        addSequenceAndChain(r, seq[i], chns[i]);
+      }
+    }
+    pdbe = new PDBEntry[v.size()];
+    v.copyInto(pdbe);
+    pdbentry = pdbe;
+    if (rtn.size() > 0)
+    {
+      // expand the tied seuqence[] and string[] arrays
+      SequenceI[][] sqs = new SequenceI[pdbentry.length][];
+      String[][] sch = new String[pdbentry.length][];
+      System.arraycopy(sequence, 0, sqs, 0, sequence.length);
+      System.arraycopy(chains, 0, sch, 0, this.chains.length);
+      sequence = sqs;
+      chains = sch;
+      pdbe = new PDBEntry[rtn.size()];
+      for (int r = 0; r < pdbe.length; r++)
+      {
+        int[] stri = ((int[]) rtn.elementAt(r));
+        // record the pdb file as a new addition
+        pdbe[r] = pdbentry[stri[0]];
+        // and add the new sequence/chain entries
+        addSequenceAndChain(stri[0], seq[stri[1]], chns[stri[1]]);
+      }
+    }
+    else
+    {
+      pdbe = null;
+    }
+    return pdbe;
+  }
+
+  public void addSequence(int pe, SequenceI[] seq)
+  {
+    // add sequences to the pe'th pdbentry's seuqence set.
+    addSequenceAndChain(pe, seq, null);
+  }
+
+  private void addSequenceAndChain(int pe, SequenceI[] seq, String[] tchain)
+  {
+    if (pe < 0 || pe >= pdbentry.length)
+    {
+      throw new Error(
+              "Implementation error - no corresponding pdbentry (for index "
+                      + pe + ") to add sequences mappings to");
+    }
+    final String nullChain = "TheNullChain";
+    Vector s = new Vector();
+    Vector c = new Vector();
+    if (chains == null)
+    {
+      chains = new String[pdbentry.length][];
+    }
+    if (sequence[pe] != null)
+    {
+      for (int i = 0; i < sequence[pe].length; i++)
+      {
+        s.addElement(sequence[pe][i]);
+        if (chains[pe] != null)
+        {
+          if (i < chains[pe].length)
+          {
+            c.addElement(chains[pe][i]);
+          }
+          else
+          {
+            c.addElement(nullChain);
+          }
+        }
+        else
+        {
+          if (tchain != null && tchain.length > 0)
+          {
+            c.addElement(nullChain);
+          }
+        }
+      }
+    }
+    for (int i = 0; i < seq.length; i++)
+    {
+      if (!s.contains(seq[i]))
+      {
+        s.addElement(seq[i]);
+        if (tchain != null && i < tchain.length)
+        {
+          c.addElement(tchain[i] == null ? nullChain : tchain[i]);
+        }
+      }
+    }
+    SequenceI[] tmp = new SequenceI[s.size()];
+    s.copyInto(tmp);
+    sequence[pe] = tmp;
+    if (c.size() > 0)
+    {
+      String[] tch = new String[c.size()];
+      c.copyInto(tch);
+      for (int i = 0; i < tch.length; i++)
+      {
+        if (tch[i] == nullChain)
+        {
+          tch[i] = null;
+        }
+      }
+      chains[pe] = tch;
+    }
+    else
+    {
+      chains[pe] = null;
+    }
+  }
 }