Merge branch 'develop' into feature/JAL-3390hideUnmappedStructure
[jalview.git] / src / jalview / structure / AtomSpec.java
index 8b8161f..f404d35 100644 (file)
@@ -46,21 +46,17 @@ public class AtomSpec
    * <pre>
    * Chimera format: 
    *    #1.2:12-20.A     model 1, submodel 2, chain A, atoms 12-20
-   * ChimeraX format:
-   *    #1.2/A:12-20
    * </pre>
    * 
    * @param spec
-   * @param chimeraX
    * @return
    * @throw IllegalArgumentException if the spec cannot be parsed, or represents
    *        more than one residue
    * @see https://www.cgl.ucsf.edu/chimera/current/docs/UsersGuide/midas/frameatom_spec.html
-   * @see http://rbvi.ucsf.edu/chimerax/docs/user/commands/atomspec.html
    */
-  public static AtomSpec fromChimeraAtomspec(String spec, boolean chimeraX)
+  public static AtomSpec fromChimeraAtomspec(String spec)
   {
-    int modelSeparatorPos = spec.indexOf(chimeraX ? "/" : ":");
+    int modelSeparatorPos = spec.indexOf(":");
     if (modelSeparatorPos == -1)
     {
       throw new IllegalArgumentException(spec);
@@ -92,9 +88,8 @@ public class AtomSpec
      * ChimeraX: chain:atoms
      */
     String atomsAndChain = spec.substring(modelSeparatorPos + 1);
-    String[] tokens = atomsAndChain.split(chimeraX ? "\\:" : "\\.");
-    String atoms = tokens.length == 1 ? atomsAndChain
-            : (chimeraX ? tokens[1] : tokens[0]);
+    String[] tokens = atomsAndChain.split("\\.");
+    String atoms = tokens.length == 1 ? atomsAndChain : (tokens[0]);
     int resNum = 0;
     try
     {
@@ -105,8 +100,7 @@ public class AtomSpec
       throw new IllegalArgumentException(spec);
     }
 
-    String chainId = tokens.length == 1 ? ""
-            : (chimeraX ? tokens[0] : tokens[1]);
+    String chainId = tokens.length == 1 ? "" : (tokens[1]);
 
     return new AtomSpec(modelId, chainId, resNum, 0);
   }
@@ -179,4 +173,70 @@ public class AtomSpec
     return "pdbFile: " + pdbFile + ", chain: " + chain + ", res: "
             + pdbResNum + ", atom: " + atomIndex;
   }
+
+  /**
+   * Parses a ChimeraX atomspec to construct an AtomSpec model (with
+   * null pdb file name)
+   * 
+   * <pre>
+   * ChimeraX format:
+   *    #1.2/A:12-20     model 1, submodel 2, chain A, atoms 12-20
+   * </pre>
+   * 
+   * @param spec
+   * @return
+   * @throw IllegalArgumentException if the spec cannot be parsed, or represents
+   *        more than one residue
+   * @see http://rbvi.ucsf.edu/chimerax/docs/user/commands/atomspec.html
+   */
+  public static AtomSpec fromChimeraXAtomspec(String spec)
+  {
+    int modelSeparatorPos = spec.indexOf("/");
+    if (modelSeparatorPos == -1)
+    {
+      throw new IllegalArgumentException(spec);
+    }
+
+    int hashPos = spec.indexOf("#");
+    if (hashPos == -1 && modelSeparatorPos != 0)
+    {
+      // # is missing but something precedes : - reject
+      throw new IllegalArgumentException(spec);
+    }
+
+    String modelSubmodel = spec.substring(hashPos + 1, modelSeparatorPos);
+    int modelId = 0;
+    try
+    {
+      int subModelPos = modelSubmodel.indexOf(".");
+      modelId = Integer.valueOf(
+              subModelPos > 0 ? modelSubmodel.substring(0, subModelPos)
+                      : modelSubmodel);
+    } catch (NumberFormatException e)
+    {
+      // ignore, default to model 0
+    }
+
+    /*
+     * now process what follows the model, either
+     * Chimera:  atoms.chain
+     * ChimeraX: chain:atoms
+     */
+    String atomsAndChain = spec.substring(modelSeparatorPos + 1);
+    String[] tokens = atomsAndChain.split("\\:");
+    String atoms = tokens.length == 1 ? atomsAndChain : (tokens[1]);
+    int resNum = 0;
+    try
+    {
+      resNum = Integer.parseInt(atoms);
+    } catch (NumberFormatException e)
+    {
+      // could be a range e.g. #1:4-7.B
+      throw new IllegalArgumentException(spec);
+    }
+
+    String chainId = tokens.length == 1 ? "" : (tokens[0]);
+
+    return new AtomSpec(modelId, chainId, resNum, 0);
+  }
 }