JAL-2422 pull-up refactoring of structure commands (continued)
[jalview.git] / src / jalview / ext / rbvi / chimera / ChimeraCommands.java
index b35faa8..9342286 100644 (file)
@@ -31,6 +31,7 @@ import jalview.datamodel.SequenceFeature;
 import jalview.datamodel.SequenceI;
 import jalview.gui.Desktop;
 import jalview.renderer.seqfeatures.FeatureColourFinder;
+import jalview.structure.StructureCommandsBase;
 import jalview.structure.StructureMapping;
 import jalview.structure.StructureMappingcommandSet;
 import jalview.structure.StructureSelectionManager;
@@ -43,6 +44,7 @@ import java.util.HashMap;
 import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.Map.Entry;
 
 /**
  * Routines for generating Chimera commands for Jalview/Chimera binding
@@ -50,39 +52,28 @@ import java.util.Map;
  * @author JimP
  * 
  */
-public class ChimeraCommands
+public class ChimeraCommands extends StructureCommandsBase
 {
-
   public static final String NAMESPACE_PREFIX = "jv_";
 
-  /**
-   * Constructs Chimera commands to colour residues as per the Jalview alignment
-   * 
-   * @param ssm
-   * @param files
-   * @param sequence
-   * @param sr
-   * @param fr
-   * @param viewPanel
-   * @param isChimeraX
-   * @return
-   */
-  public static StructureMappingcommandSet[] getColourBySequenceCommand(
+  protected static final String CMD_SEPARATOR = ";";
+
+  private static final String CMD_COLOUR_BY_CHARGE = "color white;color red ::ASP;color red ::GLU;color blue ::LYS;color blue ::ARG;color yellow ::CYS";
+
+  private static final String CMD_COLOUR_BY_CHAIN = "rainbow chain";
+
+  @Override
+  public String[] colourBySequence(
           StructureSelectionManager ssm, String[] files,
           SequenceI[][] sequence, SequenceRenderer sr,
-          AlignmentViewPanel viewPanel, boolean isChimeraX)
+          AlignmentViewPanel viewPanel)
   {
     Map<Object, AtomSpecModel> colourMap = buildColoursMap(ssm, files,
-            sequence, sr, viewPanel, isChimeraX);
-
-    List<String> colourCommands = buildColourCommands(colourMap,
-            isChimeraX);
+            sequence, sr, viewPanel);
 
-    StructureMappingcommandSet cs = new StructureMappingcommandSet(
-            ChimeraCommands.class, null,
-            colourCommands.toArray(new String[colourCommands.size()]));
+    List<String> colourCommands = buildColourCommands(colourMap);
 
-    return new StructureMappingcommandSet[] { cs };
+    return colourCommands.toArray(new String[colourCommands.size()]);
   }
 
   /**
@@ -98,11 +89,10 @@ public class ChimeraCommands
    * </pre>
    * 
    * @param colourMap
-   * @param isChimeraX
    * @return
    */
-  protected static List<String> buildColourCommands(
-          Map<Object, AtomSpecModel> colourMap, boolean isChimeraX)
+  protected List<String> buildColourCommands(
+          Map<Object, AtomSpecModel> colourMap)
   {
     /*
      * This version concatenates all commands into a single String (semi-colon
@@ -120,22 +110,20 @@ public class ChimeraCommands
       {
         sb.append("; ");
       }
-      sb.append("color ");
       firstColour = false;
       final AtomSpecModel colourData = colourMap.get(colour);
-      if (isChimeraX)
-      {
-        sb.append(colourData.getAtomSpecX()).append(" ").append(colourCode);
-      }
-      else
-      {
-        sb.append(colourCode).append(" ").append(colourData.getAtomSpec());
-      }
+      sb.append(getColourCommand(colourData, colourCode));
     }
     commands.add(sb.toString());
     return commands;
   }
 
+  protected String getColourCommand(AtomSpecModel colourData,
+          String colourCode)
+  {
+    return "color " + colourCode + " " + colourData.getAtomSpec();
+  }
+
   /**
    * Traverses a map of { modelNumber, {chain, {list of from-to ranges} } } and
    * builds a Chimera format atom spec
@@ -203,13 +191,12 @@ public class ChimeraCommands
    * @param sequence
    * @param sr
    * @param viewPanel
-   * @param isChimeraX
    * @return
    */
   protected static Map<Object, AtomSpecModel> buildColoursMap(
           StructureSelectionManager ssm, String[] files,
           SequenceI[][] sequence, SequenceRenderer sr,
-          AlignmentViewPanel viewPanel, boolean isChimeraX)
+          AlignmentViewPanel viewPanel)
   {
     FeatureRenderer fr = viewPanel.getFeatureRenderer();
     FeatureColourFinder finder = new FeatureColourFinder(fr);
@@ -221,7 +208,7 @@ public class ChimeraCommands
 
     for (int pdbfnum = 0; pdbfnum < files.length; pdbfnum++)
     {
-      final int modelNumber = pdbfnum + (isChimeraX ? 1 : 0);
+      final int modelNumber = pdbfnum + getModelStartNo();
       StructureMapping[] mapping = ssm.getMapping(files[pdbfnum]);
 
       if (mapping == null || mapping.length < 1)
@@ -301,6 +288,11 @@ public class ChimeraCommands
     return colourMap;
   }
 
+  protected static int getModelStartNo()
+  {
+    return 0;
+  }
+
   /**
    * Helper method to add one contiguous range to the AtomSpec model for the given
    * value (creating the model if necessary). As used by Jalview, {@code value} is
@@ -630,10 +622,10 @@ public class ChimeraCommands
          */
         AtomSpecModel atomSpecModel = values.get(value);
         StringBuilder sb = new StringBuilder(128);
-        sb.append("setattr ");
+        sb.append("setattr");
         if (isChimeraX)
         {
-          sb.append(atomSpecModel.getAtomSpecX());
+          sb.append(" ").append(atomSpecModel.getAtomSpecX());
         }
         String featureValue = value.toString();
         featureValue = featureValue.replaceAll("\\'", "&#39;");
@@ -690,4 +682,82 @@ public class ChimeraCommands
     return attName;
   }
 
+  @Override
+  public String colourByChain()
+  {
+    return CMD_COLOUR_BY_CHAIN;
+  }
+
+  @Override
+  public String colourByCharge()
+  {
+    return CMD_COLOUR_BY_CHARGE;
+  }
+
+  @Override
+  public String colourByResidues(Map<String, Color> colours)
+  {
+    StringBuilder cmd = new StringBuilder(12 * colours.size());
+
+    /*
+     * concatenate commands like
+     * color #4949b6 ::VAL
+     */
+    for (Entry<String, Color> entry : colours.entrySet())
+    {
+      String colorSpec = ColorUtils.toTkCode(entry.getValue());
+      String resCode = entry.getKey();
+      cmd.append("color ").append(colorSpec).append(" ::").append(resCode)
+              .append(CMD_SEPARATOR);
+    }
+    return cmd.toString();
+  }
+
+  @Override
+  public String setBackgroundColour(Color col)
+  {
+    return "set bgColor " + ColorUtils.toTkCode(col);
+  }
+
+  @Override
+  public String focusView()
+  {
+    return "focus";
+  }
+
+  @Override
+  public String showChains(List<String> toShow)
+  {
+    /*
+     * Construct a chimera command like
+     * 
+     * ~display #*;~ribbon #*;ribbon :.A,:.B
+     */
+    StringBuilder cmd = new StringBuilder(64);
+    boolean first = true;
+    for (String chain : toShow)
+    {
+      String[] tokens = chain.split(":");
+      if (tokens.length == 2)
+      {
+        String showChainCmd = tokens[0] + ":." + tokens[1];
+        if (!first)
+        {
+          cmd.append(",");
+        }
+        cmd.append(showChainCmd);
+        first = false;
+      }
+    }
+
+    /*
+     * could append ";focus" to this command to resize the display to fill the
+     * window, but it looks more helpful not to (easier to relate chains to the
+     * whole)
+     */
+    final String command = "~display #*; ~ribbon #*; ribbon :"
+            + cmd.toString();
+    return command;
+  }
+
 }