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.algorithms.commands.test;
39
40 import ffx.algorithms.cli.AlgorithmsCommand;
41 import ffx.algorithms.optimize.ConformationScan;
42 import ffx.algorithms.optimize.Minimize;
43 import ffx.algorithms.optimize.TorsionSearch;
44 import ffx.potential.AssemblyState;
45 import ffx.potential.ForceFieldEnergy;
46 import ffx.potential.MolecularAssembly;
47 import ffx.potential.bonded.Atom;
48 import ffx.potential.bonded.Molecule;
49 import ffx.potential.utils.PotentialsUtils;
50 import ffx.utilities.FFXBinding;
51 import org.apache.commons.io.FilenameUtils;
52 import picocli.CommandLine.Command;
53 import picocli.CommandLine.Option;
54 import picocli.CommandLine.Parameters;
55
56 import java.io.BufferedReader;
57 import java.io.BufferedWriter;
58 import java.io.File;
59 import java.io.FileReader;
60 import java.io.FileWriter;
61 import java.io.IOException;
62 import java.util.ArrayList;
63 import java.util.List;
64 import java.util.logging.Logger;
65
66
67
68
69
70
71
72
73
74 @Command(description = " Calculates interaction energies of different molecular orientations and saves low energy orientations.",
75 name = "test.CoformerBindingSearch")
76 public class CoformerBindingSearch extends AlgorithmsCommand {
77
78 private static final Logger logger = Logger.getLogger(CoformerBindingSearch.class.getName());
79
80
81
82
83 @Option(names = {"--eps"}, paramLabel = ".01",
84 description = "Gradient cutoff for minimization.")
85 private double eps = 0.01;
86
87
88
89
90 @Option(names = {"--maxIter"}, paramLabel = "10000",
91 description = "Max iterations for minimization.")
92 private int maxIter = 10000;
93
94
95
96
97 @Option(names = {"--solventDielectric"}, paramLabel = "78.4",
98 description = "Sets the gk solvent dielectric constant.")
99 private double gkSolventDielec = 78.4;
100
101
102
103
104 @Option(names = {"--skipHomodimerNumber"}, paramLabel = "-1",
105 description = "Skip conformation search on input dimer one or two.")
106 private int skipHomodimerNumber = -1;
107
108
109
110
111 @Option(names = {"--torsionScan", "--tscan"}, paramLabel = "false", defaultValue = "false",
112 description = "During sampling, statically scan torsions after direct minimization to find the lowest energy conformation.")
113 private boolean tscan = false;
114
115
116
117
118 @Option(names = {"--noMinimize", "--noMin"}, paramLabel = "false", defaultValue = "false",
119 description = "Don't minimize or torsion scan after conformations are generated. Useful for testing.")
120 private boolean noMinimize = false;
121
122
123
124
125 @Option(names = {"--excludeH", "--eh"}, paramLabel = "false", defaultValue = "false",
126 description = "Only include H bonded to electronegative atoms in conformations.")
127 private boolean excludeH = false;
128
129
130
131
132 @Option(names = {"--coformerOnly"}, paramLabel = "false", defaultValue = "false",
133 description = "Only conformation search the coformer.")
134 private boolean coformerOnly = false;
135
136
137
138
139 @Option(names = {"--gk"}, paramLabel = "false", defaultValue = "false",
140 description = "Use generalized kirkwood solvent.")
141 private boolean gk = false;
142
143
144
145
146 @Parameters(arity = "1..*", paramLabel = "files",
147 description = "XYZ input file.")
148 private List<String> filenames = null;
149
150 private Boolean minimize = null;
151
152
153
154
155
156 public CoformerBindingSearch() {
157 super();
158 }
159
160
161
162
163
164 public CoformerBindingSearch(FFXBinding binding) {
165 super(binding);
166 }
167
168
169
170
171
172 public CoformerBindingSearch(String[] args) {
173 super(args);
174 }
175
176
177
178
179 @Override
180 public CoformerBindingSearch run() {
181 System.setProperty("direct-scf-fallback", "true");
182
183
184 if (!init()) {
185 return this;
186 }
187
188
189
190
191 try {
192 setKeyAndPatchFiles(gk, gkSolventDielec, filenames);
193 } catch (IOException e) {
194 logger.severe("Error creating key/patch files: " + e.getMessage());
195 return this;
196 }
197
198
199 if (!(filenames.size() == 1 || filenames.size() == 2)) {
200 logger.severe("Must provide one or two filenames.");
201 return this;
202 }
203
204 minimize = !noMinimize;
205 boolean skipMoleculeOne = skipHomodimerNumber == 1;
206 boolean skipMoleculeTwo = skipHomodimerNumber == 2;
207
208
209 ConformationScan systemOneScan = null;
210 ConformationScan systemTwoScan = null;
211 if (!coformerOnly) {
212 if (!skipMoleculeOne) {
213 systemOneScan = runScan(filenames.get(0), filenames.get(0));
214 } else {
215 logger.info(" Skipping monomer one scan.");
216 }
217
218 if (!skipMoleculeTwo && filenames.size() == 2) {
219 systemTwoScan = runScan(filenames.get(1), filenames.get(1));
220 } else if (!skipMoleculeTwo && filenames.size() == 1) {
221 logger.info(" Only one file provided, skipping second homodimer scan.");
222 }
223 } else {
224 logger.info(" Skipping monomer one and two scan.");
225 }
226
227 if (filenames.size() == 2) {
228 ConformationScan bothSystems = runScan(filenames.get(0), filenames.get(1));
229 if (systemOneScan != null && systemTwoScan != null) {
230 logger.info("\n System one (" + FilenameUtils.removeExtension(filenames.get(0)) + ") self scan energy information:");
231 systemOneScan.logAllEnergyInformation();
232 logger.info("\n System two (" + FilenameUtils.removeExtension(filenames.get(1)) + ") self scan energy information:");
233 systemTwoScan.logAllEnergyInformation();
234 ConformationScan.logBindingEnergyCalculation(systemOneScan, systemTwoScan, bothSystems);
235 }
236 } else {
237 logger.info(" Only one file provided, skipping coformer scan.");
238 }
239
240 return this;
241 }
242
243 private ConformationScan runScan(String fileOne, String fileTwo) {
244 boolean coformer = !fileOne.equals(fileTwo);
245 PotentialsUtils potentialsUtils = new PotentialsUtils();
246 MolecularAssembly[] molecularAssemblies = potentialsUtils.openAll(new String[]{fileOne, fileTwo});
247 minimizeMolecularAssemblies(molecularAssemblies);
248 int secondSystemStartIndex = molecularAssemblies[0].getMoleculeArray().length;
249 MolecularAssembly combined = combineTwoMolecularAssemblies(molecularAssemblies[0], molecularAssemblies[1]);
250
251 ArrayList<Molecule> setOne = new ArrayList<>();
252 ArrayList<Molecule> setTwo = new ArrayList<>();
253 for (int i = 0; i < combined.getMoleculeArray().length; i++) {
254 if (i < secondSystemStartIndex) {
255 setOne.add(combined.getMoleculeArray()[i]);
256 } else {
257 setTwo.add(combined.getMoleculeArray()[i]);
258 }
259 }
260 Molecule[] systemOne = setOne.toArray(new Molecule[0]);
261 Molecule[] systemTwo = setTwo.toArray(new Molecule[0]);
262 ConformationScan scan = new ConformationScan(
263 combined,
264 systemOne,
265 systemTwo,
266 eps,
267 maxIter,
268 tscan,
269 excludeH,
270 minimize
271 );
272 scan.scan();
273 String fileName = coformer ? "coformerScan.arc" : FilenameUtils.removeExtension(fileOne) + ".arc";
274 File file = new File(fileName);
275 if (!scan.writeStructuresToXYZ(file)) {
276 logger.warning(" No structures saved from scan.");
277 scan = null;
278 } else if (!coformer) {
279 logger.info("\n System (" + FilenameUtils.removeExtension(fileOne) + ") self scan energy information:");
280 scan.logAllEnergyInformation();
281 } else {
282 logger.info("\n System (" + FilenameUtils.removeExtension(fileOne) +
283 ") and system (" + FilenameUtils.removeExtension(fileTwo) + ") scan energy information:");
284 scan.logAllEnergyInformation();
285 }
286 return scan;
287 }
288
289 private static MolecularAssembly combineTwoMolecularAssemblies(MolecularAssembly mola1, MolecularAssembly mola2) {
290 MolecularAssembly mainMonomerAssembly = mola1;
291 MolecularAssembly feederAssembly = mola2;
292 Molecule[] assemblyTwoMolecules = feederAssembly.getMoleculeArray();
293 int molNum = mainMonomerAssembly.getMoleculeArray().length;
294 for (Molecule m : assemblyTwoMolecules) {
295 for (Atom a : m.getAtomList()) {
296 a.setMoleculeNumber(molNum);
297 }
298 m.setName("AddedMol" + molNum);
299 mainMonomerAssembly.addMSNode(m);
300 molNum++;
301 }
302 mainMonomerAssembly.update();
303 mainMonomerAssembly.setPotential(null);
304 ForceFieldEnergy forceFieldEnergy = ForceFieldEnergy.energyFactory(mainMonomerAssembly);
305 return mainMonomerAssembly;
306 }
307
308 private static void setKeyAndPatchFiles(boolean gk, double gkSolventDielec, List<String> filenames) throws IOException {
309 String key = "coformerScan.key";
310 String patch = "coformerScan.patch";
311
312 File keyFile = new File(key);
313 File patchFile = new File(patch);
314 logger.info(" Creating key file: " + key);
315 keyFile.createNewFile();
316
317 try (BufferedWriter bw = new BufferedWriter(new FileWriter(keyFile))) {
318 bw.write("patch " + FilenameUtils.removeExtension(key) + ".patch\n\n");
319 if (gk) {
320 bw.write("gkterm true\n");
321 bw.write("solvent-dielectric " + gkSolventDielec + "\n");
322 bw.write("gk-radius solute\n");
323 bw.write("cavmodel gauss-disp\n");
324 }
325 }
326 logger.info(" Creating patch file: " + patch);
327 patchFile.createNewFile();
328 String patchOne = FilenameUtils.removeExtension(filenames.get(0)) + ".patch";
329 String patchTwo = filenames.size() > 1
330 ? FilenameUtils.removeExtension(filenames.get(1)) + ".patch"
331 : patchOne;
332 String[] files = new String[]{patchOne, patchTwo};
333 try (BufferedWriter bw = new BufferedWriter(new FileWriter(patchFile))) {
334 for (String file : files) {
335 try (BufferedReader br = new BufferedReader(new FileReader(file))) {
336 String line = br.readLine();
337 while (line != null) {
338 bw.write(line + "\n");
339 line = br.readLine();
340 }
341 }
342 }
343 }
344 System.setProperty("key", key);
345 }
346
347 private void minimizeMolecularAssemblies(MolecularAssembly[] molecularAssemblies) {
348 if (!noMinimize) {
349 logger.info(" Minimizing molecular assemblies.");
350 for (MolecularAssembly molecularAssembly : molecularAssemblies) {
351 for (Molecule m : molecularAssembly.getMoleculeArray()) {
352 if (tscan) {
353 TorsionSearch ts = new TorsionSearch(molecularAssembly, m, 32, 1);
354 ts.staticAnalysis(0, 100);
355 if (!ts.getStates().isEmpty()) {
356 AssemblyState minState = ts.getStates().get(0);
357 minState.revertState();
358 }
359 }
360 }
361 Minimize minimizer = new Minimize(molecularAssembly, molecularAssembly.getPotentialEnergy(), algorithmListener);
362 minimizer.minimize(eps, maxIter);
363 }
364 logger.info(" Done minimizing molecular assemblies.");
365 }
366 }
367 }