1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38 package ffx.potential.cli;
39
40 import ffx.potential.MolecularAssembly;
41 import ffx.potential.bonded.Atom;
42 import ffx.potential.bonded.Residue;
43 import picocli.CommandLine.ArgGroup;
44 import picocli.CommandLine.Option;
45
46 import javax.annotation.Nonnull;
47 import javax.annotation.Nullable;
48 import java.util.ArrayList;
49 import java.util.List;
50 import java.util.function.BiConsumer;
51 import java.util.logging.Logger;
52
53 import static ffx.utilities.StringUtils.parseAtomRanges;
54 import static ffx.utilities.StringUtils.parseResidueString;
55
56
57
58
59
60
61
62 public class AtomSelectionOptions {
63
64 private static final Logger logger = Logger.getLogger(AtomSelectionOptions.class.getName());
65
66
67
68
69 @ArgGroup(heading = "%n Atom Selection Options%n", validate = false)
70 private final AtomSelectionOptionGroup group = new AtomSelectionOptionGroup();
71
72 public static void actOnAtoms(@Nonnull MolecularAssembly assembly, @Nullable String selection,
73 @Nonnull BiConsumer<Atom, Boolean> action, @Nonnull String description) {
74 if (selection == null || selection.equalsIgnoreCase("")) {
75
76 return;
77 }
78
79 Atom[] atoms = assembly.getAtomArray();
80
81
82 if (selection.equalsIgnoreCase("NONE")) {
83 for (Atom atom : atoms) {
84 action.accept(atom, false);
85 }
86 logger.info(" No atoms are " + description + ".\n");
87 return;
88 }
89
90
91 if (selection.equalsIgnoreCase("ALL")) {
92 for (Atom atom : atoms) {
93 action.accept(atom, true);
94 }
95 logger.info(" All atoms are " + description + ".\n");
96 return;
97 }
98
99
100 int nAtoms = atoms.length;
101 for (Atom atom : atoms) {
102 action.accept(atom, false);
103 }
104
105 List<Integer> atomRanges = parseAtomRanges(description, selection, nAtoms);
106 for (int i : atomRanges) {
107 action.accept(atoms[i], true);
108 }
109 logger.info("\n " + description + " atoms set to: " + selection);
110
111 }
112
113 public static void actOnResidueAtoms(@Nonnull MolecularAssembly assembly, @Nullable String selection,
114 @Nonnull BiConsumer<Atom, Boolean> action, String description) {
115 if (selection == null || selection.equalsIgnoreCase("")) {
116
117 return;
118 }
119
120 Atom[] atoms = assembly.getAtomArray();
121
122
123 if (selection.equalsIgnoreCase("NONE")) {
124 for (Atom atom : atoms) {
125 action.accept(atom, false);
126 }
127 logger.info(" No residues are " + description + ".\n");
128 return;
129 }
130
131
132 if (selection.equalsIgnoreCase("ALL")) {
133 for (Atom atom : atoms) {
134 action.accept(atom, true);
135 }
136 logger.info(" All residues (and atoms) are " + description + ".\n");
137 return;
138 }
139
140
141 for (Atom atom : atoms) {
142 action.accept(atom, false);
143 }
144
145
146 StringBuilder seleRes = new StringBuilder();
147 StringBuilder seleAtoms = new StringBuilder();
148
149 int nResidues = assembly.getResidueList().size();
150 List<String> resList = parseResidueString(description, selection, nResidues);
151 assert resList.size() % 2 == 0;
152
153 for (int i=0; i < resList.size(); i=i+2) {
154 String chain = resList.get(i);
155 int resid = Integer.parseInt(resList.get(i+1));
156
157 List<Atom> atomList = new ArrayList<>();
158
159 Residue res = assembly.getChain(chain).getResidue(resid);
160 seleRes.append(res.toFormattedString(true, true)).append(",");
161 if (res.getResidueType() == Residue.ResidueType.AA) {
162 atomList = res.getSideChainAtoms();
163 } else if (res.getResidueType() == Residue.ResidueType.NA) {
164 atomList = res.getBackboneAtoms();
165 }
166
167
168 for (Atom atom : atomList) {
169 seleAtoms.append(atom.getIndex()).append(",");
170 action.accept(atom, true);
171 }
172 }
173
174 logger.info("\n " + description + " residues are: " + seleRes.substring(0, seleRes.length()-1));
175 logger.info(" " + description + " atoms set to: " + seleAtoms.substring(0, seleAtoms.length()-1));
176 }
177
178
179
180
181
182
183 public String getActiveAtoms() {
184 return group.activeAtoms;
185 }
186
187
188
189
190
191
192 public void setActiveAtoms(MolecularAssembly molecularAssembly) {
193
194 setInactive(molecularAssembly);
195
196
197 setActive(molecularAssembly);
198 }
199
200
201
202
203
204
205 public String getInactiveAtoms() {
206 return group.inactiveAtoms;
207 }
208
209
210
211
212
213
214 public boolean isAtomSelectionSet() {
215 if (group.activeAtoms != null && !group.activeAtoms.isEmpty()) {
216 return true;
217 }
218 return group.inactiveAtoms != null && !group.inactiveAtoms.isEmpty();
219 }
220
221 private void setInactive(MolecularAssembly assembly) {
222 actOnAtoms(assembly, getInactiveAtoms(), (Atom a, Boolean b) -> a.setActive(!b), "Inactive");
223 }
224
225 private void setActive(MolecularAssembly assembly) {
226 actOnAtoms(assembly, getActiveAtoms(), Atom::setActive, "Active");
227 }
228
229
230
231
232 private static class AtomSelectionOptionGroup {
233
234
235
236
237 @Option(names = {"--aa",
238 "--active"}, paramLabel = "<selection>", defaultValue = "",
239 description = "Ranges of active atoms [NONE, ALL, Range(s): 1-3,6-N].")
240 public String activeAtoms = "";
241
242
243
244
245 @Option(names = {"--ia",
246 "--inactive"}, paramLabel = "<selection>", defaultValue = "",
247 description = "Ranges of inactive atoms [NONE, ALL, Range(s): 1-3,6-N].")
248 public String inactiveAtoms = "";
249 }
250 }