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.commands;
39
40 import ffx.algorithms.cli.AlgorithmsCommand;
41 import ffx.algorithms.cli.MinimizeOptions;
42 import ffx.numerics.Potential;
43 import ffx.potential.MolecularAssembly;
44 import ffx.potential.cli.AtomSelectionOptions;
45 import ffx.potential.cli.PotentialCommand;
46 import ffx.utilities.FFXBinding;
47 import ffx.xray.DiffractionData;
48 import ffx.xray.RefinementMinimize;
49 import ffx.xray.cli.XrayOptions;
50 import ffx.xray.refine.RefinementMode;
51 import ffx.xray.refine.RefinementModel;
52 import org.apache.commons.configuration2.CompositeConfiguration;
53 import picocli.CommandLine.Command;
54 import picocli.CommandLine.Mixin;
55 import picocli.CommandLine.Option;
56 import picocli.CommandLine.Parameters;
57
58 import java.util.ArrayList;
59 import java.util.Arrays;
60 import java.util.List;
61 import java.util.stream.Collectors;
62
63 import static java.lang.String.format;
64 import static org.apache.commons.io.FilenameUtils.removeExtension;
65
66
67
68
69
70
71
72
73 @Command(description = " Refine an X-ray/Neutron target.", name = "xray.Minimize")
74 public class Minimize extends AlgorithmsCommand {
75
76 @Mixin
77 private XrayOptions xrayOptions;
78
79 @Mixin
80 AtomSelectionOptions atomSelectionOptions;
81
82 @Mixin
83 private MinimizeOptions minimizeOptions;
84
85
86
87
88 @Option(names = {"-t", "--threeStage"}, paramLabel = "false",
89 description = "Perform refinement in 3 stages: coordinates, b-factors, and then occupancies (overrides mode setting if true)")
90 private boolean threeStage = false;
91
92
93
94
95 @Option(names = {"-E", "--eps3"}, paramLabel = "-1.0", arity = "3",
96 description = "RMS gradient convergence criteria for three stage refinement (default of -1.0 automatically determines eps for each stage).")
97 private double[] eps3 = {-1.0, -1.0, -1.0};
98
99
100
101
102 @Option(names = {"-c", "--cycles"}, paramLabel = "1", defaultValue = "1",
103 description = "Number of refinement cycles.")
104 private int ncycles = 1;
105
106
107
108
109 @Option(names = {"--mtz"}, paramLabel = "false",
110 description = "Write out an MTZ containing structure factor coefficients.")
111 private boolean mtz = false;
112
113
114
115
116 @Parameters(arity = "1..*", paramLabel = "files", description = "PDB and Diffraction input files.")
117 private List<String> filenames;
118
119 private MolecularAssembly[] molecularAssemblies;
120 private DiffractionData diffractionData;
121
122
123
124
125 public Minimize() {
126 super();
127 }
128
129
130
131
132
133
134 public Minimize(String[] args) {
135 super(args);
136 }
137
138
139
140
141
142
143 public Minimize(FFXBinding binding) {
144 super(binding);
145 }
146
147 @Override
148 public Minimize run() {
149
150 if (!init()) {
151 return this;
152 }
153
154 xrayOptions.init();
155
156 String filename;
157 if (filenames != null && !filenames.isEmpty()) {
158
159 molecularAssemblies = algorithmFunctions.openAll(filenames.getFirst());
160 activeAssembly = molecularAssemblies[0];
161 } else if (activeAssembly == null) {
162 logger.info(helpString());
163 return this;
164 } else {
165 molecularAssemblies = new MolecularAssembly[]{activeAssembly};
166 }
167
168
169 filename = activeAssembly.getFile().getAbsolutePath();
170
171
172 for (MolecularAssembly molecularAssembly : molecularAssemblies) {
173 atomSelectionOptions.setActiveAtoms(molecularAssembly);
174 }
175
176 logger.info("\n Running xray.Minimize on " + filename);
177
178
179 CompositeConfiguration properties = activeAssembly.getProperties();
180 xrayOptions.setProperties(parseResult, properties);
181
182
183 diffractionData = xrayOptions.getDiffractionData(filenames, molecularAssemblies, properties);
184
185
186 algorithmFunctions.energy(molecularAssemblies);
187
188
189 double coordinateEPS = eps3[0];
190 double bfactorEPS = eps3[1];
191 double occupancyEPS = eps3[2];
192
193
194 int nBFGS = minimizeOptions.getNBFGS();
195
196
197 int maxIterations = minimizeOptions.getIterations();
198
199 for (int cycle = 0; cycle < ncycles; cycle++) {
200 if (ncycles > 1) {
201 logger.info(format("\n Refinement Cycle: %d\n", cycle + 1));
202 }
203 diffractionData.scaleBulkFit();
204 diffractionData.printStats();
205
206 if (threeStage) {
207
208 RefinementModel refinementModel = diffractionData.getRefinementModel();
209 RefinementMode refinementMode = RefinementMode.COORDINATES;
210 refinementModel.setRefinementMode(refinementMode);
211 if (refinementModel.getNumCoordParameters() > 0) {
212 RefinementMinimize refinementMinimize = new RefinementMinimize(diffractionData);
213 if (coordinateEPS < 0.0) {
214 coordinateEPS = refinementMode.getDefaultEps();
215 }
216 if (maxIterations < Integer.MAX_VALUE) {
217 logger.info(format("\n RMS gradient convergence criteria: %8.5f, Maximum iterations %d",
218 coordinateEPS, maxIterations));
219 } else {
220 logger.info(format("\n RMS gradient convergence criteria: %8.5f", coordinateEPS));
221 }
222 refinementMinimize.minimize(nBFGS, coordinateEPS, maxIterations);
223 algorithmFunctions.energy(molecularAssemblies);
224 }
225
226
227 refinementMode = RefinementMode.BFACTORS;
228 refinementModel.setRefinementMode(refinementMode);
229 if (refinementModel.getNumBFactorParameters() > 0) {
230 RefinementMinimize refinementMinimize = new RefinementMinimize(diffractionData);
231 if (bfactorEPS < 0.0) {
232 boolean hasAnisous = refinementModel.getNumANISOU() > 0;
233 bfactorEPS = refinementMode.getDefaultEps(hasAnisous);
234 }
235 if (maxIterations < Integer.MAX_VALUE) {
236 logger.info(format("\n RMS gradient convergence criteria: %8.5f, Maximum iterations %d",
237 bfactorEPS, maxIterations));
238 } else {
239 logger.info(format("\n RMS gradient convergence criteria: %8.5f", bfactorEPS));
240 }
241 refinementMinimize.minimize(nBFGS, bfactorEPS, maxIterations);
242 }
243
244
245 refinementMode = RefinementMode.OCCUPANCIES;
246 refinementModel.setRefinementMode(refinementMode);
247 if (refinementModel.getNumOccupancyParameters() > 0) {
248 RefinementMinimize refinementMinimize = new RefinementMinimize(diffractionData);
249 if (occupancyEPS < 0.0) {
250 occupancyEPS = refinementMode.getDefaultEps();
251 }
252 if (maxIterations < Integer.MAX_VALUE) {
253 logger.info(format("\n RMS gradient convergence criteria: %8.5f, Maximum iterations %d",
254 occupancyEPS, maxIterations));
255 } else {
256 logger.info(format("\n RMS gradient convergence criteria: %8.5f", occupancyEPS));
257 }
258 refinementMinimize.minimize(occupancyEPS, maxIterations);
259 } else {
260 logger.info("Occupancy refinement not necessary, skipping");
261 }
262 } else {
263 RefinementMinimize refinementMinimize = new RefinementMinimize(diffractionData);
264 RefinementModel refinementModel = diffractionData.getRefinementModel();
265 RefinementMode refinementMode = refinementModel.getRefinementMode();
266 double eps = minimizeOptions.getEps();
267 if (eps < 0.0) {
268 boolean hasAnisous = refinementModel.getNumANISOU() > 0;
269 eps = refinementMode.getDefaultEps(hasAnisous);
270 }
271 if (maxIterations < Integer.MAX_VALUE) {
272 logger.info(format("\n RMS gradient convergence criteria: %8.5f, Maximum iterations %d", eps,
273 maxIterations));
274 } else {
275 logger.info(format("\n RMS gradient convergence criteria: %8.5f", eps));
276 }
277 refinementMinimize.minimize(eps, maxIterations);
278 }
279 }
280
281 diffractionData.scaleBulkFit();
282 diffractionData.printStats();
283
284
285 algorithmFunctions.energy(molecularAssemblies);
286
287 logger.info(" ");
288 diffractionData.writeModel(removeExtension(filename) + ".pdb");
289 if (mtz) {
290 diffractionData.writeData(removeExtension(filename) + ".mtz");
291 }
292
293 return this;
294 }
295
296 @Override
297 public List<Potential> getPotentials() {
298 return getPotentialsFromAssemblies(molecularAssemblies);
299 }
300
301 @Override
302 public boolean destroyPotentials() {
303 return diffractionData == null ? true : diffractionData.destroy();
304 }
305 }