JAL-3518 more extraction of ChimeraX commands as overrides
[jalview.git] / src / jalview / ext / rbvi / chimera / JalviewChimeraBinding.java
index 9695eae..be1de5a 100644 (file)
@@ -35,7 +35,6 @@ import jalview.gui.StructureViewer.ViewerType;
 import jalview.httpserver.AbstractRequestHandler;
 import jalview.io.DataSourceType;
 import jalview.structure.AtomSpec;
-import jalview.structure.StructureMappingcommandSet;
 import jalview.structure.StructureSelectionManager;
 import jalview.structures.models.AAStructureBindingModel;
 import jalview.util.MessageManager;
@@ -84,7 +83,7 @@ public abstract class JalviewChimeraBinding extends AAStructureBindingModel
   /*
    * Map of ChimeraModel objects keyed by PDB full local file name
    */
-  private Map<String, List<ChimeraModel>> chimeraMaps = new LinkedHashMap<>();
+  protected Map<String, List<ChimeraModel>> chimeraMaps = new LinkedHashMap<>();
 
   String lastHighlightCommand;
 
@@ -127,34 +126,7 @@ public abstract class JalviewChimeraBinding extends AAStructureBindingModel
       if (!alreadyOpen)
       {
         chimeraManager.openModel(file, pe.getId(), ModelType.PDB_MODEL);
-        if (chimeraManager.isChimeraX())
-        {
-          /*
-           * ChimeraX hack: force chimera model name to pdbId
-           */
-          int modelNumber = chimeraMaps.size() + 1;
-          String command = "setattr #" + modelNumber + " models name "
-                  + pe.getId();
-          executeCommand(command, false);
-          modelsToMap.add(new ChimeraModel(pe.getId(), ModelType.PDB_MODEL,
-                  modelNumber, 0));
-        }
-        else
-        {
-          /*
-           * Chimera: query for actual models and find the one with
-           * matching model name - set in viewer.openModel()
-           */
-          List<ChimeraModel> newList = chimeraManager.getModelList();
-          // JAL-1728 newList.removeAll(oldList) does not work
-          for (ChimeraModel cm : newList)
-          {
-            if (cm.getModelName().equals(pe.getId()))
-            {
-              modelsToMap.add(cm);
-            }
-          }
-        }
+        addChimeraModel(pe, modelsToMap);
       }
 
       chimeraMaps.put(file, modelsToMap);
@@ -174,6 +146,31 @@ public abstract class JalviewChimeraBinding extends AAStructureBindingModel
   }
 
   /**
+   * Adds the ChimeraModel corresponding to the given PDBEntry, based on model
+   * name matching PDB id
+   * 
+   * @param pe
+   * @param modelsToMap
+   */
+  protected void addChimeraModel(PDBEntry pe,
+          List<ChimeraModel> modelsToMap)
+  {
+    /*
+     * Chimera: query for actual models and find the one with
+     * matching model name - already set in viewer.openModel()
+     */
+    List<ChimeraModel> newList = chimeraManager.getModelList();
+    // JAL-1728 newList.removeAll(oldList) does not work
+    for (ChimeraModel cm : newList)
+    {
+      if (cm.getModelName().equals(pe.getId()))
+      {
+        modelsToMap.add(cm);
+      }
+    }
+  }
+
+  /**
    * Constructor
    * 
    * @param ssm
@@ -585,8 +582,7 @@ public abstract class JalviewChimeraBinding extends AAStructureBindingModel
       return true;
     }
 
-    boolean launched = chimeraManager.launchChimera(
-            StructureManager.getChimeraPaths(chimeraManager.isChimeraX()));
+    boolean launched = chimeraManager.launchChimera(getChimeraPaths());
     if (launched)
     {
       startChimeraProcessMonitor();
@@ -599,6 +595,16 @@ public abstract class JalviewChimeraBinding extends AAStructureBindingModel
   }
 
   /**
+   * Returns a list of candidate paths to the Chimera program executable
+   * 
+   * @return
+   */
+  protected List<String> getChimeraPaths()
+  {
+    return StructureManager.getChimeraPaths(false);
+  }
+
+  /**
    * Answers true if the Chimera process is still running, false if ended or not
    * started.
    * 
@@ -856,9 +862,8 @@ public abstract class JalviewChimeraBinding extends AAStructureBindingModel
        * Chimera:  https://www.cgl.ucsf.edu/chimera/current/docs/UsersGuide/midas/save.html
        * ChimeraX: https://www.cgl.ucsf.edu/chimerax/docs/user/commands/save.html
        */
-      String command = isChimeraX() ? "save session " : "save ";
-      List<String> reply = chimeraManager.sendChimeraCommand(command + filepath,
-              true);
+      String command = getSaveSessionCommand(filepath);
+      List<String> reply = chimeraManager.sendChimeraCommand(command, true);
       if (reply.contains("Session written"))
       {
         return true;
@@ -873,6 +878,17 @@ public abstract class JalviewChimeraBinding extends AAStructureBindingModel
   }
 
   /**
+   * Returns the command to save the viewer session to the given file path
+   * 
+   * @param filepath
+   * @return
+   */
+  protected String getSaveSessionCommand(String filepath)
+  {
+    return "save " + filepath;
+  }
+
+  /**
    * Ask Chimera to open a session file. Returns true if successful, else false.
    * The filename must have a .py (Chimera) or .cxs (ChimeraX) extension for
    * this command to work.
@@ -935,10 +951,8 @@ public abstract class JalviewChimeraBinding extends AAStructureBindingModel
       return 0;
     }
 
-    StructureMappingcommandSet commandSet = ChimeraCommands
-            .getSetAttributeCommandsForFeatures(getSsm(), files,
-                    getSequence(), avp, chimeraManager.isChimeraX());
-    String[] commands = commandSet.commands;
+    String[] commands = getCommandGenerator()
+            .setAttributesForFeatures(getSsm(), files, getSequence(), avp);
     if (commands.length > 10)
     {
       sendCommandsByFile(commands);
@@ -962,10 +976,9 @@ public abstract class JalviewChimeraBinding extends AAStructureBindingModel
    */
   protected void sendCommandsByFile(String[] commands)
   {
-    boolean toChimeraX = chimeraManager.isChimeraX();
     try
     {
-      File tmp = File.createTempFile("chim", toChimeraX ? ".cxc" : ".com");
+      File tmp = File.createTempFile("chim", getCommandFileExtension());
       tmp.deleteOnExit();
       PrintWriter out = new PrintWriter(new FileOutputStream(tmp));
       for (String command : commands)
@@ -975,7 +988,7 @@ public abstract class JalviewChimeraBinding extends AAStructureBindingModel
       out.flush();
       out.close();
       String path = tmp.getAbsolutePath();
-      String command = "open " + (toChimeraX ? "" : "cmd:") + path;
+      String command = getOpenCommandFileCommand(path);
       sendAsynchronousCommand(command, null);
     } catch (IOException e)
     {
@@ -985,6 +998,28 @@ public abstract class JalviewChimeraBinding extends AAStructureBindingModel
   }
 
   /**
+   * Returns the command for the structure viewer to open a file of commands at
+   * the given file path
+   * 
+   * @param path
+   * @return
+   */
+  protected String getOpenCommandFileCommand(String path)
+  {
+    return "open cmd:" + path;
+  }
+
+  /**
+   * Returns the file extension required for a file of commands to be read by
+   * the structure viewer
+   * @return
+   */
+  protected String getCommandFileExtension()
+  {
+    return ".com";
+  }
+
+  /**
    * Get Chimera residues which have the named attribute, find the mapped
    * positions in the Jalview sequence(s), and set as sequence features
    * 
@@ -1153,8 +1188,18 @@ public abstract class JalviewChimeraBinding extends AAStructureBindingModel
     return atts;
   }
 
-  public boolean isChimeraX()
+  /**
+   * Returns the file extension to use for a saved viewer session file
+   * 
+   * @return
+   */
+  public String getSessionFileExtension()
+  {
+    return ".py";
+  }
+
+  public String getHelpURL()
   {
-    return chimeraManager.isChimeraX();
+    return "https://www.cgl.ucsf.edu/chimera/docs/UsersGuide";
   }
 }