revised sequence/structure binding so one structure associated with x-seuqenceI's...
[jalview.git] / src / jalview / ext / jmol / JalviewJmolBinding.java
index c2eceed..8831bd6 100644 (file)
@@ -77,7 +77,10 @@ public abstract class JalviewJmolBinding implements StructureListener,
 
   public Vector chainNames;
 
-  String[] chains;
+  /**
+   * array of target chains for seuqences - tied to pdbentry and sequence[]
+   */
+  protected String[][] chains;
 
   boolean colourBySequence = true;
 
@@ -113,20 +116,26 @@ public abstract class JalviewJmolBinding implements StructureListener,
 
   StringBuffer resetLastRes = new StringBuffer();
 
-  public SequenceI[] sequence;
+  /**
+   * sequences mapped to each pdbentry
+   */
+  public SequenceI[][] sequence;
 
   StructureSelectionManager ssm;
 
   public JmolViewer viewer;
 
-  public JalviewJmolBinding(PDBEntry[] pdbentry, SequenceI[] seq,
-          String[] chains, String protocol)
+  public JalviewJmolBinding(PDBEntry[] pdbentry, SequenceI[][] sequenceIs,
+          String[][] chains, String protocol)
   {
-    this.sequence = seq;
+    this.sequence = sequenceIs;
     this.chains = chains;
     this.pdbentry = pdbentry;
     this.protocol = protocol;
-
+    if (chains == null)
+    {
+      this.chains = new String[pdbentry.length][];
+    }
     /*
      * viewer = JmolViewer.allocateViewer(renderPanel, new SmarterJmolAdapter(),
      * "jalviewJmol", ap.av.applet .getDocumentBase(),
@@ -156,7 +165,7 @@ public abstract class JalviewJmolBinding implements StructureListener,
     {
       return ("Jalview Jmol Window");
     }
-    StringBuffer title = new StringBuffer(sequence[0].getName() + ":"
+    StringBuffer title = new StringBuffer(sequence[0][0].getName() + ":"
             + pdbentry[0].getId());
 
     if (pdbentry[0].getProperty() != null)
@@ -236,12 +245,55 @@ public abstract class JalviewJmolBinding implements StructureListener,
    */
   public void superposeStructures(AlignmentI alignment)
   {
-    String[] files = getPdbFile();
+    superposeStructures(alignment, -1, null);
+  }
 
-    StringBuffer command = new StringBuffer();
+  /**
+   * superpose the structures associated with sequences in the alignment
+   * according to their corresponding positions. ded)
+   * 
+   * @param refStructure
+   *          - select which pdb file to use as reference (default is -1 - the
+   *          first structure in the alignment)
+   */
+  public void superposeStructures(AlignmentI alignment, int refStructure)
+  {
+    superposeStructures(alignment, refStructure, null);
+  }
+
+  /**
+   * superpose the structures associated with sequences in the alignment
+   * according to their corresponding positions. ded)
+   * @param refStructure
+   *          - select which pdb file to use as reference (default is -1 - the
+   *          first structure in the alignment)
+   * @param hiddenCols TODO
+   */
+  public void superposeStructures(AlignmentI alignment, int refStructure, ColumnSelection hiddenCols)
+  {
+    String[] files = getPdbFile();
+    if (refStructure>=files.length)
+    {
+      System.err.println("Invalid reference structure value "+refStructure);
+      refStructure= -1;
+    }
+    if (refStructure<-1)
+    {
+      refStructure=-1;
+    }
+    StringBuffer command = new StringBuffer(), selectioncom = new StringBuffer();
+    
     boolean matched[] = new boolean[alignment.getWidth()];
-    String commonpositions[][] = new String[files.length][alignment
-            .getWidth()];
+    for (int m = 0; m < matched.length; m++)
+    {
+      
+      matched[m] = (hiddenCols!=null) ? hiddenCols.isVisible(m) : true;
+    }
+    
+    int commonrpositions[][] = new int[files.length][alignment.getWidth()];
+    String isel[] = new String[files.length];
+    // reference structure - all others are superposed in it
+    String[] targetC = new String[files.length];
     for (int pdbfnum = 0; pdbfnum < files.length; pdbfnum++)
     {
       StructureMapping[] mapping = ssm.getMapping(files[pdbfnum]);
@@ -250,60 +302,156 @@ public abstract class JalviewJmolBinding implements StructureListener,
         continue;
 
       int lastPos = -1;
-      for (int s = 0; s < sequence.length; s++)
+      for (int s = 0; s < sequence[pdbfnum].length; s++)
       {
         for (int sp, m = 0; m < mapping.length; m++)
         {
-          if (mapping[m].getSequence() == sequence[s]
-                  && (sp = alignment.findIndex(sequence[s])) > -1)
+          if (mapping[m].getSequence() == sequence[pdbfnum][s]
+                  && (sp = alignment.findIndex(sequence[pdbfnum][s])) > -1)
           {
+            if (refStructure == -1)
+            {
+              refStructure = pdbfnum;
+            }
             SequenceI asp = alignment.getSequenceAt(sp);
-            for (int r = 0; r < asp.getLength(); r++)
+            for (int r = 0; r < matched.length; r++)
             {
-              // no mapping to gaps in sequence
+              if (!matched[r])
+              {
+                continue;
+              }
+              matched[r] = false; // assume this is not a good site
+              if (r >= asp.getLength())
+              {
+                continue;
+              }
+
               if (jalview.util.Comparison.isGap(asp.getCharAt(r)))
               {
-                matched[r] = false; // exclude from common set
+                // no mapping to gaps in sequence
                 continue;
               }
-              int pos = mapping[m].getPDBResNum(asp.findPosition(r));
+              int t = asp.findPosition(r); // sequence position
+              int apos = mapping[m].getAtomNum(t);
+              int pos = mapping[m].getPDBResNum(t);
 
               if (pos < 1 || pos == lastPos)
+              {
+                // can't align unmapped sequence
                 continue;
-
+              }
+              matched[r] = true; // this is a good ite
               lastPos = pos;
-
-              commonpositions[m][r] = (mapping[m].getChain() != " " ? ":"
-                      + mapping[m].getChain() : "")
-                      + "/" + (pdbfnum + 1) + ".1";
+              // just record this residue position
+              commonrpositions[pdbfnum][r] = pos;
+            }
+            // create model selection suffix
+            isel[pdbfnum] = "/" + (pdbfnum + 1) + ".1";
+            if (mapping[m].getChain() == null
+                    || mapping[m].getChain().trim().length() == 0)
+            {
+              targetC[pdbfnum] = "";
+            }
+            else
+            {
+              targetC[pdbfnum] = ":" + mapping[m].getChain();
             }
+            // move on to next pdb file
+            s = sequence[pdbfnum].length;
             break;
           }
         }
       }
     }
-    command.append("select ");
-    // form the matched pair selection strings
-    String sep = "";
-    for (int r = 0; r < matched.length; r++)
+    StringBuffer selcom[] = new StringBuffer[files.length];
+    // generate select statements to select regions to superimpose structures
     {
-      if (matched[r])
+      for (int pdbfnum = 0; pdbfnum < files.length; pdbfnum++)
       {
-        command.append(sep);
-        command.append("(");
-        for (int s = 0; s < commonpositions.length; s++)
+        String chainCd = targetC[pdbfnum];
+        int lpos = -1;
+        boolean run = false;
+        StringBuffer molsel = (selcom[pdbfnum] = new StringBuffer());
+        molsel.append("{");
+        for (int r = 0; r < matched.length; r++)
         {
-          if (s > 0)
+          if (matched[r])
           {
-            command.append(" | ");
+
+            if (lpos != commonrpositions[pdbfnum][r] - 1)
+            {
+              // discontinuity
+              if (lpos != -1)
+              {
+                molsel.append(lpos);
+                molsel.append(chainCd);
+                // molsel.append("} {");
+                molsel.append("|");
+              }
+            }
+            else
+            {
+              // continuous run - and lpos >-1
+              if (!run)
+              {
+                // at the beginning, so add dash
+                molsel.append(lpos);
+                molsel.append("-");
+              }
+              run = true;
+            }
+            lpos = commonrpositions[pdbfnum][r];
+            // molsel.append(lpos);
           }
-          command.append(commonpositions[s][r]);
         }
-        command.append(")");
-        sep = " | ";
+        // add final selection phrase
+        if (lpos != -1)
+        {
+          molsel.append(lpos);
+          molsel.append(chainCd);
+          molsel.append("}");
+        }
+        selectioncom.append("((");
+        selectioncom.append(molsel.subSequence(1, molsel.length()-1));
+        selectioncom.append(" )& ");
+        selectioncom.append(pdbfnum+1);
+        selectioncom.append(".1)");
+        if (pdbfnum<files.length-1)
+        {
+          selectioncom.append("|");
+        }
+      }
+    }
+
+    for (int pdbfnum = 0; pdbfnum < files.length; pdbfnum++)
+    {
+      if (pdbfnum == refStructure)
+      {
+        continue;
       }
+      command.append("compare ");
+      command.append("{");
+      command.append(1 + pdbfnum);
+      command.append(".1} {");
+      command.append(1 + refStructure);
+      command.append(".1} SUBSET {*.CA | *.P} ATOMS ");
+
+      // form the matched pair strings
+      String sep = "";
+      for (int s = 0; s < 2; s++)
+      {
+        command.append(selcom[(s == 0 ? pdbfnum : refStructure)]);
+      }
+      command.append(" ROTATE TRANSLATE;\n");
     }
+    System.out.println("Select regions:\n" + selectioncom.toString());
+    evalStateCommand("select *; cartoons off; backbone; select ("+selectioncom.toString()+"); cartoons; ");
+    // selcom.append("; ribbons; ");
+    System.out.println("Superimpose command(s):\n" + command.toString());
+
     evalStateCommand(command.toString());
+    
+    // evalStateCommand("select *; backbone; select "+selcom.toString()+"; cartoons; center "+selcom.toString());
   }
 
   public void evalStateCommand(String command)
@@ -349,12 +497,12 @@ public abstract class JalviewJmolBinding implements StructureListener,
         continue;
 
       int lastPos = -1;
-      for (int s = 0; s < sequence.length; s++)
+      for (int s = 0; s < sequence[pdbfnum].length; s++)
       {
         for (int sp, m = 0; m < mapping.length; m++)
         {
-          if (mapping[m].getSequence() == sequence[s]
-                  && (sp = alignment.findIndex(sequence[s])) > -1)
+          if (mapping[m].getSequence() == sequence[pdbfnum][s]
+                  && (sp = alignment.findIndex(sequence[pdbfnum][s])) > -1)
           {
             SequenceI asp = alignment.getSequenceAt(sp);
             for (int r = 0; r < asp.getLength(); r++)
@@ -371,10 +519,10 @@ public abstract class JalviewJmolBinding implements StructureListener,
 
               lastPos = pos;
 
-              Color col = sr.getResidueBoxColour(sequence[s], r);
+              Color col = sr.getResidueBoxColour(sequence[pdbfnum][s], r);
 
               if (showFeatures)
-                col = fr.findFeatureColour(col, sequence[s], r);
+                col = fr.findFeatureColour(col, sequence[pdbfnum][s], r);
               String newSelcom = (mapping[m].getChain() != " " ? ":"
                       + mapping[m].getChain() : "")
                       + "/"
@@ -896,7 +1044,7 @@ public abstract class JalviewJmolBinding implements StructureListener,
               if (loadedInline)
               {
                 // TODO: replace with getData ?
-                pdb = ssm.setMapping(sequence, chains,
+                pdb = ssm.setMapping(sequence[pe], chains[pe],
                         pdbentry[pe].getFile(), AppletFormatAdapter.PASTE);
                 pdbentry[pe].setFile("INLINE" + pdb.id);
               }
@@ -921,7 +1069,7 @@ public abstract class JalviewJmolBinding implements StructureListener,
                 {
                 }
                 ;
-                pdb = ssm.setMapping(sequence, chains,
+                pdb = ssm.setMapping(sequence[pe], chains[pe],
                         pdbentry[pe].getFile(), protocol);
 
               }
@@ -1066,21 +1214,23 @@ public abstract class JalviewJmolBinding implements StructureListener,
    */
   public abstract void refreshGUI();
 
-
   /**
    * @param renderPanel
-   * @param jmolfileio - when true will initialise jmol's file IO system (should be false in applet context)
+   * @param jmolfileio
+   *          - when true will initialise jmol's file IO system (should be false
+   *          in applet context)
    * @param htmlName
    * @param documentBase
    * @param codeBase
    * @param commandOptions
    */
-  public void allocateViewer(Component renderPanel, boolean jmolfileio, String htmlName,
-          URL documentBase, URL codeBase, String commandOptions)
+  public void allocateViewer(Component renderPanel, boolean jmolfileio,
+          String htmlName, URL documentBase, URL codeBase,
+          String commandOptions)
   {
     viewer = JmolViewer.allocateViewer(renderPanel,
-            (jmolfileio ? new SmarterJmolAdapter() : null),
-            htmlName + ((Object) this).toString(), documentBase, codeBase,
+            (jmolfileio ? new SmarterJmolAdapter() : null), htmlName
+                    + ((Object) this).toString(), documentBase, codeBase,
             commandOptions, this);
   }