2 * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
3 * Copyright (C) $$Year-Rel$$ The Jalview Authors
5 * This file is part of Jalview.
7 * Jalview is free software: you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation, either version 3
10 * of the License, or (at your option) any later version.
12 * Jalview is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty
14 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15 * PURPOSE. See the GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with Jalview. If not, see <http://www.gnu.org/licenses/>.
19 * The Jalview Authors are detailed in the 'AUTHORS' file.
21 package jalview.structure;
24 * Java bean representing an atom in a PDB (or similar) structure model or
34 private String pdbFile;
38 private int pdbResNum;
40 private int atomIndex;
43 * Parses a Chimera atomspec e.g. #1:12.A to construct an AtomSpec model (with
48 * #1.2:12-20.A model 1, submodel 2, chain A, atoms 12-20
53 * @throw IllegalArgumentException if the spec cannot be parsed, or represents
54 * more than one residue
55 * @see https://www.cgl.ucsf.edu/chimera/current/docs/UsersGuide/midas/frameatom_spec.html
57 public static AtomSpec fromChimeraAtomspec(String spec)
59 int modelSeparatorPos = spec.indexOf(":");
60 if (modelSeparatorPos == -1)
62 throw new IllegalArgumentException(spec);
65 int hashPos = spec.indexOf("#");
66 if (hashPos == -1 && modelSeparatorPos != 0)
68 // # is missing but something precedes : - reject
69 throw new IllegalArgumentException(spec);
72 String modelSubmodel = spec.substring(hashPos + 1, modelSeparatorPos);
76 int subModelPos = modelSubmodel.indexOf(".");
77 modelId = Integer.valueOf(
78 subModelPos > 0 ? modelSubmodel.substring(0, subModelPos)
80 } catch (NumberFormatException e)
82 // ignore, default to model 0
86 * now process what follows the model, either
87 * Chimera: atoms.chain
88 * ChimeraX: chain:atoms
90 String atomsAndChain = spec.substring(modelSeparatorPos + 1);
91 String[] tokens = atomsAndChain.split("\\.");
92 String atoms = tokens.length == 1 ? atomsAndChain : (tokens[0]);
96 resNum = Integer.parseInt(atoms);
97 } catch (NumberFormatException e)
99 // could be a range e.g. #1:4-7.B
100 throw new IllegalArgumentException(spec);
103 String chainId = tokens.length == 1 ? "" : (tokens[1]);
105 return new AtomSpec(modelId, chainId, resNum, 0);
116 public AtomSpec(String pdbFile, String chain, int resNo, int atomNo)
118 this.pdbFile = pdbFile;
120 this.pdbResNum = resNo;
121 this.atomIndex = atomNo;
132 public AtomSpec(int modelId, String chainId, int resNo, int atomNo)
134 this.modelNo = modelId;
135 this.chain = chainId;
136 this.pdbResNum = resNo;
137 this.atomIndex = atomNo;
140 public String getPdbFile()
145 public String getChain()
150 public int getPdbResNum()
155 public int getAtomIndex()
160 public int getModelNumber()
165 public void setPdbFile(String file)
171 public String toString()
173 return "pdbFile: " + pdbFile + ", chain: " + chain + ", res: "
174 + pdbResNum + ", atom: " + atomIndex;
178 * Parses a ChimeraX atomspec to construct an AtomSpec model (with null pdb
183 * #1.2/A:12-20 model 1, submodel 2, chain A, atoms 12-20
188 * @throw IllegalArgumentException if the spec cannot be parsed, or represents
189 * more than one residue
190 * @see http://rbvi.ucsf.edu/chimerax/docs/user/commands/atomspec.html
192 public static AtomSpec fromChimeraXAtomspec(String spec)
194 int modelSeparatorPos = spec.indexOf("/");
195 if (modelSeparatorPos == -1)
197 throw new IllegalArgumentException(spec);
200 int hashPos = spec.indexOf("#");
201 if (hashPos == -1 && modelSeparatorPos != 0)
203 // # is missing but something precedes : - reject
204 throw new IllegalArgumentException(spec);
207 String modelSubmodel = spec.substring(hashPos + 1, modelSeparatorPos);
211 int subModelPos = modelSubmodel.indexOf(".");
212 modelId = Integer.valueOf(
213 subModelPos > 0 ? modelSubmodel.substring(0, subModelPos)
215 } catch (NumberFormatException e)
217 // ignore, default to model 0
221 * now process what follows the model, either
222 * Chimera: atoms.chain
223 * ChimeraX: chain:atoms
225 String atomsAndChain = spec.substring(modelSeparatorPos + 1);
226 String[] tokens = atomsAndChain.split("\\:");
227 String atoms = tokens.length == 1 ? atomsAndChain : (tokens[1]);
231 resNum = Integer.parseInt(atoms);
232 } catch (NumberFormatException e)
234 // could be a range e.g. #1:4-7.B
235 throw new IllegalArgumentException(spec);
238 String chainId = tokens.length == 1 ? "" : (tokens[0]);
240 return new AtomSpec(modelId, chainId, resNum, 0);