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.xray.cli;
39
40 import ffx.potential.MolecularAssembly;
41 import ffx.utilities.FFXProperty;
42 import ffx.xray.solvent.SolventModel;
43 import ffx.xray.DiffractionData;
44 import ffx.xray.RefinementEnergy;
45 import ffx.xray.refine.RefinementMode;
46 import ffx.xray.parsers.DiffractionFile;
47 import org.apache.commons.configuration2.CompositeConfiguration;
48 import org.apache.commons.io.FilenameUtils;
49 import picocli.CommandLine.ArgGroup;
50 import picocli.CommandLine.Option;
51 import picocli.CommandLine.ParseResult;
52
53 import java.util.ArrayList;
54 import java.util.List;
55 import java.util.logging.Logger;
56
57 import static ffx.utilities.PropertyGroup.StructuralRefinement;
58 import static java.lang.Boolean.parseBoolean;
59 import static java.lang.Double.parseDouble;
60 import static java.lang.String.format;
61
62
63
64
65
66
67
68
69 public class XrayOptions extends DataRefinementOptions {
70
71 private static final Logger logger = Logger.getLogger(XrayOptions.class.getName());
72
73
74
75
76 @ArgGroup(heading = "%n X-ray Refinement Options%n", validate = false)
77 private final XrayOptionGroup group = new XrayOptionGroup();
78
79
80
81 @ArgGroup(heading = "%n X-ray Reflection Data Options%n", validate = false)
82 private final XrayReflectionsGroup reflectionGroup = new XrayReflectionsGroup();
83
84
85
86 @ArgGroup(heading = "%n X-ray B-Factor Options%n", validate = false)
87 private final BFactorGroup bfactorGroup = new BFactorGroup();
88
89
90
91 @ArgGroup(heading = "%n X-ray Target Options%n", validate = false)
92 private final ScatteringGroup targetGroup = new ScatteringGroup();
93
94
95
96 @ArgGroup(heading = "%n X-ray Bulk Solvent Options%n", validate = false)
97 private final BulkSolventGroup solventGroup = new BulkSolventGroup();
98
99
100
101 public RefinementMode refinementMode = RefinementMode.COORDINATES;
102
103
104
105 public SolventModel solventModel = SolventModel.POLYNOMIAL;
106
107
108
109
110 public void init() {
111 refinementMode = RefinementMode.parseMode(group.modeString);
112 solventModel = SolventModel.parse(solventGroup.solventString);
113 }
114
115
116
117
118
119
120
121
122 public List<DiffractionFile> processData(List<String> filenames, MolecularAssembly[] systems) {
123 List<DiffractionFile> diffractionfiles = new ArrayList<>();
124
125 logger.info("\n");
126
127 if (filenames.size() > 1) {
128 logger.info(format(" Diffraction file = %s, weight = %3.1f, neutron = %b", filenames.get(1), wA, Boolean.FALSE));
129 DiffractionFile diffractionfile = new DiffractionFile(filenames.get(1), wA, false);
130 diffractionfiles.add(diffractionfile);
131 }
132
133 if (reflectionGroup.data != null) {
134 for (int i = 0; i < reflectionGroup.data.length; i += 3) {
135 boolean neutron = false;
136 double w = wA;
137 if (reflectionGroup.data.length > i + 1) {
138 try {
139 w = parseDouble(reflectionGroup.data[i + 1]);
140 } catch (Exception e) {
141
142 }
143 }
144 if (reflectionGroup.data.length > i + 2) {
145 try {
146 neutron = parseBoolean(reflectionGroup.data[i + 2]);
147 } catch (Exception e) {
148
149 }
150 }
151 logger.info(format(" Diffraction file = %s, weight = %3.1f, neutron = %b", reflectionGroup.data[i], w, neutron));
152 DiffractionFile diffractionfile = new DiffractionFile(reflectionGroup.data[i], w, neutron);
153 diffractionfiles.add(diffractionfile);
154 }
155
156 }
157
158 if (diffractionfiles.isEmpty()) {
159 String filename = systems[0].getFile().getAbsolutePath();
160 filename = FilenameUtils.removeExtension(filename);
161 filename = FilenameUtils.getBaseName(filename);
162
163 logger.info(format(" Diffraction from = %s, weight = %3.1f, neutron = %b", filename, wA, false));
164 DiffractionFile diffractionfile = new DiffractionFile(systems, 1.0, false);
165 diffractionfiles.add(diffractionfile);
166 }
167
168 return diffractionfiles;
169 }
170
171
172
173
174
175
176
177 public void setProperties(ParseResult parseResult, CompositeConfiguration properties) {
178
179 if (!parseResult.hasMatchedOption("wA")) {
180 wA = properties.getDouble("data-weight", wA);
181 }
182 properties.setProperty("data-weight", wA);
183
184
185 if (!parseResult.hasMatchedOption("bSimWeight")) {
186 bfactorGroup.bSimWeight = properties.getDouble("b-sim-weight", bfactorGroup.bSimWeight);
187 }
188 properties.setProperty("b-sim-weight", bfactorGroup.bSimWeight);
189
190
191 if (!parseResult.hasMatchedOption("fSigFCutoff")) {
192 reflectionGroup.fSigFCutoff = properties.getDouble("f-sigf-cutoff", reflectionGroup.fSigFCutoff);
193 }
194 properties.setProperty("f-sigf-cutoff", reflectionGroup.fSigFCutoff);
195
196
197 if (!parseResult.hasMatchedOption("gridSearch")) {
198 solventGroup.gridSearch = properties.getBoolean("solvent-grid-search", solventGroup.gridSearch);
199 }
200 properties.setProperty("solvent-grid-search", solventGroup.gridSearch);
201
202
203 if (!parseResult.hasMatchedOption("nBins")) {
204 reflectionGroup.nBins = properties.getInt("reflection-bins", reflectionGroup.nBins);
205 }
206 properties.setProperty("reflection-bins", reflectionGroup.nBins);
207
208
209 if (!parseResult.hasMatchedOption("sampling")) {
210 targetGroup.sampling = properties.getDouble("sampling", targetGroup.sampling);
211 }
212 properties.setProperty("sampling", targetGroup.sampling);
213
214
215 if (!parseResult.hasMatchedOption("aRadBuffer")) {
216 targetGroup.aRadBuffer = properties.getDouble("scattering-buffer", targetGroup.aRadBuffer);
217 }
218 properties.setProperty("scattering-buffer", targetGroup.aRadBuffer);
219
220
221 if (!parseResult.hasMatchedOption("rFreeFlag")) {
222 reflectionGroup.rFreeFlag = properties.getInt("rfree-flag", reflectionGroup.rFreeFlag);
223 }
224 properties.setProperty("rfree-flag", reflectionGroup.rFreeFlag);
225
226
227 if (!parseResult.hasMatchedOption("noSplineFit")) {
228 targetGroup.noSplineFit = properties.getBoolean("no-spline-fit", targetGroup.noSplineFit);
229 }
230 properties.setProperty("no-spline-fit", targetGroup.noSplineFit);
231
232
233 if (!parseResult.hasMatchedOption("allGaussians")) {
234 targetGroup.useAllGaussians = !properties.getBoolean("use-3g", !targetGroup.useAllGaussians);
235 }
236 properties.setProperty("use-3g", !targetGroup.useAllGaussians);
237
238
239 if (!parseResult.hasMatchedOption("xrayScaleTol")) {
240 targetGroup.xrayScaleTol = properties.getDouble("xray-scale-tol", targetGroup.xrayScaleTol);
241 }
242 properties.setProperty("xray-scale-tol", targetGroup.xrayScaleTol);
243
244
245 if (!parseResult.hasMatchedOption("sigmaATol")) {
246 targetGroup.sigmaATol = properties.getDouble("sigmaa-tol", targetGroup.sigmaATol);
247 }
248 properties.setProperty("sigmaa-tol", targetGroup.sigmaATol);
249
250
251 if (!parseResult.hasMatchedOption("nResidueBFactor")) {
252 bfactorGroup.nResidueBFactor = properties
253 .getInt("n-residue-bfactor", bfactorGroup.nResidueBFactor);
254 }
255 properties.setProperty("n-residue-bfactor", Integer.toString(bfactorGroup.nResidueBFactor));
256 if (bfactorGroup.nResidueBFactor > 0) {
257 properties.setProperty("residue-bfactor", "true");
258 }
259
260
261 if (!parseResult.hasMatchedOption("anisoU")) {
262 bfactorGroup.anisoU = properties.getBoolean("add-anisou", bfactorGroup.anisoU);
263 }
264 properties.setProperty("add-anisou", bfactorGroup.anisoU);
265
266
267 if (!parseResult.hasMatchedOption("refineMolOcc")) {
268 group.refineMolOcc = properties.getBoolean("refine-mol-occ", group.refineMolOcc);
269 }
270 properties.setProperty("refine-mol-occ", group.refineMolOcc);
271 }
272
273
274
275
276
277
278
279
280
281 public DiffractionData getDiffractionData(List<String> filenames, MolecularAssembly[] assemblies,
282 CompositeConfiguration properties) {
283
284 List<DiffractionFile> diffractionFiles = processData(filenames, assemblies);
285 DiffractionData diffractionData = new DiffractionData(assemblies, properties, solventModel,
286 diffractionFiles.toArray(new DiffractionFile[0]));
287 diffractionData.getRefinementModel().setRefinementMode(refinementMode);
288 return diffractionData;
289 }
290
291
292
293
294 private static class XrayOptionGroup {
295
296
297
298
299 @Option(names = {"--rmo", "--refineMolOcc"}, paramLabel = "false", defaultValue = "false",
300 description = "Refine molecular occupancy.")
301 @FFXProperty(name = "refine-mol-occ", propertyGroup = StructuralRefinement, defaultValue = "false",
302 description = "Refine molecular occupancy.")
303 boolean refineMolOcc = false;
304
305
306
307
308
309
310 @Option(names = {"-m", "--mode"}, paramLabel = "coordinates", defaultValue = "coordinates",
311 description = "Refinement mode: coordinates, bfactors and/or occupancies.")
312 String modeString = "coordinates";
313 }
314
315
316
317
318 private static class XrayReflectionsGroup {
319
320
321
322
323 @Option(names = {"--nBins"}, paramLabel = "10", defaultValue = "10",
324 description = "The number of refection bins.")
325 @FFXProperty(name = "reflection-bins", propertyGroup = StructuralRefinement, defaultValue = "10",
326 description = "The number of refection bins.")
327 int nBins = 10;
328
329
330
331
332 @Option(names = {"--FSigFCutoff"}, paramLabel = "-1.0", defaultValue = "-1.0",
333 description = "F / SigF cutoff (-1.0 is no cutoff).")
334 @FFXProperty(name = "f-sigf-cutoff", propertyGroup = StructuralRefinement, defaultValue = "-1.0",
335 description = "F / SigF cutoff (-1.0 is no cutoff)."
336 )
337 double fSigFCutoff = -1.0;
338
339
340
341
342 @Option(names = {"-R", "--rFreeFlag"}, paramLabel = "-1", defaultValue = "-1",
343 description = "R-Free Flag value (-1 attempts to auto-determine from the data).")
344 @FFXProperty(name = "rfree-flag", propertyGroup = StructuralRefinement, defaultValue = "-1",
345 description = "R-Free Flag value (-1 attempts to auto-determine from the data)."
346 )
347 int rFreeFlag = -1;
348
349
350
351
352
353 @Option(names = {"-X", "--data"}, arity = "3",
354 description = "Specify input data filename, its weight (wA) and if its from a neutron experiment (e.g. -X filename 1.0 false).")
355 String[] data = null;
356 }
357
358
359
360
361 private static class BFactorGroup {
362
363
364
365
366 @Option(names = {"-B", "--bSimWeight"}, paramLabel = "1.0", defaultValue = "1.0",
367 description = "B-Factor similarity weight.")
368 @FFXProperty(name = "b-sim-weight", propertyGroup = StructuralRefinement, defaultValue = "1.0", description = """
369 B-factor harmonic restraint weight between bonded atoms.
370 This can be increased for low resolution structures to ~5-10.
371 """)
372 double bSimWeight = 1.0;
373
374
375
376
377 @Option(names = {"--nResidueBFactor"}, paramLabel = "0", defaultValue = "0",
378 description = "Number of residues per B-factor. 0 uses atomic B-factors (default).")
379 @FFXProperty(name = "n-residue-bfactor", propertyGroup = StructuralRefinement, defaultValue = "0",
380 description = "Number of residues per B-factor. 0 uses atomic B-factors (default).")
381 int nResidueBFactor = 0;
382
383
384
385
386 @Option(names = {"-U", "--addAnisoU"}, paramLabel = "false", defaultValue = "false",
387 description = "Add Anisotropic B-Factors to refinement.")
388 @FFXProperty(name = "add-anisou", propertyGroup = StructuralRefinement, defaultValue = "false",
389 description = "Add Anisotropic B-Factors to refinement.")
390 boolean anisoU = false;
391
392 }
393
394
395
396
397 private static class ScatteringGroup {
398
399
400
401
402 @Option(names = {"--aRadBuffer"}, paramLabel = "0.75", defaultValue = "0.75",
403 description = "Scattering is evaluated within the atomic radius plus this buffer (Å).")
404 @FFXProperty(name = "scattering-buffer", propertyGroup = StructuralRefinement, defaultValue = "0.6",
405 description = "Scattering is evaluated within the atomic radius plus this buffer (Å).")
406 double aRadBuffer = 0.75;
407
408
409
410
411 @Option(names = {"-G", "--sampling"}, paramLabel = "0.6", defaultValue = "0.6",
412 description = "The number of grid spaces per Angstrom for the scattering FFT grid.")
413 @FFXProperty(name = "sampling", propertyGroup = StructuralRefinement, defaultValue = "0.6",
414 description = "The number of grid spaces per Angstrom for the scattering FFT grid.")
415 double sampling = 0.6;
416
417
418
419
420 @Option(names = {"--nsf", "--noSplineFit"}, paramLabel = "false", defaultValue = "false",
421 description = "Use a resolution dependent spline scale factor.")
422 @FFXProperty(name = "no-spline-fit", propertyGroup = StructuralRefinement, defaultValue = "false",
423 description = "Do not use a resolution dependent spline scale factor.")
424 boolean noSplineFit = false;
425
426
427
428
429 @Option(names = {"-A", "--allGaussians"}, paramLabel = "false", defaultValue = "false",
430 description = "Use all defined Gaussians for atomic scattering density (the default is to use the top 3).")
431 @FFXProperty(name = "use-3g", propertyGroup = StructuralRefinement, defaultValue = "true",
432 description = "The three Gaussians with the largest amplitudes define the atomic scattering density.")
433 boolean useAllGaussians = false;
434
435
436
437
438 @Option(names = {"--xrayScaleTol"}, paramLabel = "1.0e-4", defaultValue = "1.0e-4",
439 description = "X-ray scale optimization tolerance.")
440 @FFXProperty(name = "xray-scale-tol", propertyGroup = StructuralRefinement, defaultValue = "1.0e-4",
441 description = "X-ray scale optimization tolerance.")
442 double xrayScaleTol = 1.0e-4;
443
444
445
446
447 @Option(names = {"--sigmaATol"}, paramLabel = "0.05", defaultValue = "0.05",
448 description = "Sigma A optimization tolerance.")
449 @FFXProperty(name = "sigmaa-tol", propertyGroup = StructuralRefinement, defaultValue = "0.05",
450 description = "Sigma A optimization tolerance.")
451 double sigmaATol = 0.05;
452 }
453
454
455
456
457 private static class BulkSolventGroup {
458
459
460
461
462 @Option(names = {"-S", "--solventGridSearch"}, paramLabel = "false", defaultValue = "false",
463 description = "Perform a grid search for optimal bulk solvent parameters.")
464 @FFXProperty(name = "solvent-grid-search", propertyGroup = StructuralRefinement, defaultValue = "false",
465 description = "Perform a grid search for optimal bulk solvent parameters.")
466 boolean gridSearch = false;
467
468
469
470
471 @Option(names = {"--sol", "--solvent"}, paramLabel = "POLYNOMIAL", defaultValue = "POLYNOMIAL",
472 description = "Bulk solvent scattering model [Polynomial/Gaussian/Binary/None]")
473 String solventString = "POLYNOMIAL";
474 }
475
476
477
478
479
480
481
482 public RefinementEnergy toXrayEnergy(DiffractionData diffractionData) {
483 diffractionData.scaleBulkFit();
484 diffractionData.printStats();
485 return new RefinementEnergy(diffractionData);
486 }
487 }