Class |
Line # |
Actions |
|||
---|---|---|---|---|---|
AtomSpec | 30 | 55 | 27 |
1 | /* | |
2 | * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$) | |
3 | * Copyright (C) $$Year-Rel$$ The Jalview Authors | |
4 | * | |
5 | * This file is part of Jalview. | |
6 | * | |
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. | |
11 | * | |
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. | |
16 | * | |
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. | |
20 | */ | |
21 | package jalview.structure; | |
22 | ||
23 | /** | |
24 | * Java bean representing an atom in a PDB (or similar) structure model or | |
25 | * viewer | |
26 | * | |
27 | * @author gmcarstairs | |
28 | * | |
29 | */ | |
30 | public class AtomSpec | |
31 | { | |
32 | int modelNo; | |
33 | ||
34 | private String pdbFile; | |
35 | ||
36 | private String chain; | |
37 | ||
38 | private int pdbResNum; | |
39 | ||
40 | private int atomIndex; | |
41 | ||
42 | /** | |
43 | * Parses a Chimera atomspec e.g. #1:12.A to construct an AtomSpec model (with | |
44 | * null pdb file name) | |
45 | * | |
46 | * <pre> | |
47 | * Chimera format: | |
48 | * #1.2:12-20.A model 1, submodel 2, chain A, atoms 12-20 | |
49 | * </pre> | |
50 | * | |
51 | * @param spec | |
52 | * @return | |
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 | |
56 | */ | |
57 | 0 | public static AtomSpec fromChimeraAtomspec(String spec) |
58 | { | |
59 | 0 | int modelSeparatorPos = spec.indexOf(":"); |
60 | 0 | if (modelSeparatorPos == -1) |
61 | { | |
62 | 0 | throw new IllegalArgumentException(spec); |
63 | } | |
64 | ||
65 | 0 | int hashPos = spec.indexOf("#"); |
66 | 0 | if (hashPos == -1 && modelSeparatorPos != 0) |
67 | { | |
68 | // # is missing but something precedes : - reject | |
69 | 0 | throw new IllegalArgumentException(spec); |
70 | } | |
71 | ||
72 | 0 | String modelSubmodel = spec.substring(hashPos + 1, modelSeparatorPos); |
73 | 0 | int modelId = 0; |
74 | 0 | try |
75 | { | |
76 | 0 | int subModelPos = modelSubmodel.indexOf("."); |
77 | 0 | modelId = Integer.valueOf( |
78 | 0 | subModelPos > 0 ? modelSubmodel.substring(0, subModelPos) |
79 | : modelSubmodel); | |
80 | } catch (NumberFormatException e) | |
81 | { | |
82 | // ignore, default to model 0 | |
83 | } | |
84 | ||
85 | /* | |
86 | * now process what follows the model, either | |
87 | * Chimera: atoms.chain | |
88 | * ChimeraX: chain:atoms | |
89 | */ | |
90 | 0 | String atomsAndChain = spec.substring(modelSeparatorPos + 1); |
91 | 0 | String[] tokens = atomsAndChain.split("\\."); |
92 | 0 | String atoms = tokens.length == 1 ? atomsAndChain : (tokens[0]); |
93 | 0 | int resNum = 0; |
94 | 0 | try |
95 | { | |
96 | 0 | resNum = Integer.parseInt(atoms); |
97 | } catch (NumberFormatException e) | |
98 | { | |
99 | // could be a range e.g. #1:4-7.B | |
100 | 0 | throw new IllegalArgumentException(spec); |
101 | } | |
102 | ||
103 | 0 | String chainId = tokens.length == 1 ? "" : (tokens[1]); |
104 | ||
105 | 0 | return new AtomSpec(modelId, chainId, resNum, 0); |
106 | } | |
107 | ||
108 | /** | |
109 | * Constructor | |
110 | * | |
111 | * @param pdbFile | |
112 | * @param chain | |
113 | * @param resNo | |
114 | * @param atomNo | |
115 | */ | |
116 | 1 | public AtomSpec(String pdbFile, String chain, int resNo, int atomNo) |
117 | { | |
118 | 1 | this.pdbFile = pdbFile; |
119 | 1 | this.chain = chain; |
120 | 1 | this.pdbResNum = resNo; |
121 | 1 | this.atomIndex = atomNo; |
122 | } | |
123 | ||
124 | /** | |
125 | * Constructor | |
126 | * | |
127 | * @param modelId | |
128 | * @param chainId | |
129 | * @param resNo | |
130 | * @param atomNo | |
131 | */ | |
132 | 0 | public AtomSpec(int modelId, String chainId, int resNo, int atomNo) |
133 | { | |
134 | 0 | this.modelNo = modelId; |
135 | 0 | this.chain = chainId; |
136 | 0 | this.pdbResNum = resNo; |
137 | 0 | this.atomIndex = atomNo; |
138 | } | |
139 | ||
140 | 2 | public String getPdbFile() |
141 | { | |
142 | 2 | return pdbFile; |
143 | } | |
144 | ||
145 | 1 | public String getChain() |
146 | { | |
147 | 1 | return chain; |
148 | } | |
149 | ||
150 | 1 | public int getPdbResNum() |
151 | { | |
152 | 1 | return pdbResNum; |
153 | } | |
154 | ||
155 | 0 | public int getAtomIndex() |
156 | { | |
157 | 0 | return atomIndex; |
158 | } | |
159 | ||
160 | 0 | public int getModelNumber() |
161 | { | |
162 | 0 | return modelNo; |
163 | } | |
164 | ||
165 | 0 | public void setPdbFile(String file) |
166 | { | |
167 | 0 | pdbFile = file; |
168 | } | |
169 | ||
170 | 0 | @Override |
171 | public String toString() | |
172 | { | |
173 | 0 | return "pdbFile: " + pdbFile + ", chain: " + chain + ", res: " |
174 | + pdbResNum + ", atom: " + atomIndex; | |
175 | } | |
176 | ||
177 | /** | |
178 | * Parses a ChimeraX atomspec to construct an AtomSpec model (with null pdb | |
179 | * file name) | |
180 | * | |
181 | * <pre> | |
182 | * ChimeraX format: | |
183 | * #1.2/A:12-20 model 1, submodel 2, chain A, atoms 12-20 | |
184 | * </pre> | |
185 | * | |
186 | * @param spec | |
187 | * @return | |
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 | |
191 | */ | |
192 | 0 | public static AtomSpec fromChimeraXAtomspec(String spec) |
193 | { | |
194 | 0 | int modelSeparatorPos = spec.indexOf("/"); |
195 | 0 | if (modelSeparatorPos == -1) |
196 | { | |
197 | 0 | throw new IllegalArgumentException(spec); |
198 | } | |
199 | ||
200 | 0 | int hashPos = spec.indexOf("#"); |
201 | 0 | if (hashPos == -1 && modelSeparatorPos != 0) |
202 | { | |
203 | // # is missing but something precedes : - reject | |
204 | 0 | throw new IllegalArgumentException(spec); |
205 | } | |
206 | ||
207 | 0 | String modelSubmodel = spec.substring(hashPos + 1, modelSeparatorPos); |
208 | 0 | int modelId = 0; |
209 | 0 | try |
210 | { | |
211 | 0 | int subModelPos = modelSubmodel.indexOf("."); |
212 | 0 | modelId = Integer.valueOf( |
213 | 0 | subModelPos > 0 ? modelSubmodel.substring(0, subModelPos) |
214 | : modelSubmodel); | |
215 | } catch (NumberFormatException e) | |
216 | { | |
217 | // ignore, default to model 0 | |
218 | } | |
219 | ||
220 | /* | |
221 | * now process what follows the model, either | |
222 | * Chimera: atoms.chain | |
223 | * ChimeraX: chain:atoms | |
224 | */ | |
225 | 0 | String atomsAndChain = spec.substring(modelSeparatorPos + 1); |
226 | 0 | String[] tokens = atomsAndChain.split("\\:"); |
227 | 0 | String atoms = tokens.length == 1 ? atomsAndChain : (tokens[1]); |
228 | 0 | int resNum = 0; |
229 | 0 | try |
230 | { | |
231 | 0 | resNum = Integer.parseInt(atoms); |
232 | } catch (NumberFormatException e) | |
233 | { | |
234 | // could be a range e.g. #1:4-7.B | |
235 | 0 | throw new IllegalArgumentException(spec); |
236 | } | |
237 | ||
238 | 0 | String chainId = tokens.length == 1 ? "" : (tokens[0]); |
239 | ||
240 | 0 | return new AtomSpec(modelId, chainId, resNum, 0); |
241 | } | |
242 | } |