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 edu.rit.pj.ParallelTeam;
41 import ffx.algorithms.cli.AlgorithmsCommand;
42 import ffx.potential.MolecularAssembly;
43 import ffx.potential.cli.TopologyOptions;
44 import ffx.potential.extended.ExtendedSystem;
45 import ffx.potential.parsers.XPHFilter;
46 import ffx.utilities.FFXBinding;
47 import org.apache.commons.configuration2.CompositeConfiguration;
48 import org.apache.commons.io.FilenameUtils;
49 import picocli.CommandLine.Command;
50 import picocli.CommandLine.Mixin;
51 import picocli.CommandLine.Option;
52 import picocli.CommandLine.Parameters;
53
54 import java.io.File;
55 import java.util.ArrayList;
56 import java.util.List;
57
58
59
60
61
62
63
64
65 @Command(description = " The SortXPH command unwinds .ARC files from CpHMD runs.", name = "test.SortXPH")
66 public class SortXPH extends AlgorithmsCommand {
67
68 @Mixin
69 private TopologyOptions topology;
70
71 @Option(names = {"--nw", "--nWindows"}, paramLabel = "-1", defaultValue = "-1",
72 description = "If set, auto-determine lambda values and subdirectories (overrides other flags).")
73 private int nWindows;
74
75 @Option(names = {"--bT", "--sortByTemp"}, paramLabel = "false", defaultValue = "false",
76 description = "If set, sort archive files by temperature values")
77 private boolean sortTemp;
78
79 @Option(names = {"--sT", "--startTemp"}, paramLabel = "298.15", defaultValue = "298.15",
80 description = "Sets the starting temperature for the exponential temperature ladder if sorting by temperature.")
81 private double lowTemperature;
82
83 @Option(names = {"--pH"}, paramLabel = "7.4", defaultValue = "7.4",
84 description = "Sets the middle of the pH ladder")
85 private double pH;
86
87 @Option(names = {"--pHGaps"}, paramLabel = "1", defaultValue = "1",
88 description = "Sets the size of the gaps in the pH ladder")
89 private double pHGap;
90
91 @Option(names = {"--ex", "--exponent"}, paramLabel = "0.5", defaultValue = "0.5",
92 description = "Sets the exponent for the exponential temperature ladder if sorting by temperature.")
93 private double exponent;
94
95
96
97
98 @Parameters(arity = "1", paramLabel = "file",
99 description = "Trajectory files for the first end of the window, followed by trajectories for the other end")
100 private String filename = null;
101
102 private double[] lambdaValues;
103 private double[] temperatureValues;
104 private double[] pHValues;
105 private XPHFilter opener;
106 private XPHFilter[] writers;
107 private CompositeConfiguration additionalProperties;
108 private List<String> windowFiles = new ArrayList<>();
109 private MolecularAssembly molecularAssembly;
110 private int threadsAvail = ParallelTeam.getDefaultThreadCount();
111 private int threadsPer = threadsAvail;
112 private ExtendedSystem extendedSystem;
113
114
115
116
117
118
119 public void setProperties(CompositeConfiguration additionalProps) {
120 this.additionalProperties = additionalProps;
121 }
122
123
124
125
126 public SortXPH() {
127 super();
128 }
129
130
131
132
133
134
135 public SortXPH(FFXBinding binding) {
136 super(binding);
137 }
138
139
140
141
142
143
144 public SortXPH(String[] args) {
145 super(args);
146 }
147
148
149
150
151 @Override
152 public SortXPH run() {
153 logger.info(" Running");
154
155 if (!init()) {
156 return this;
157 }
158
159 if (nWindows != -1) {
160 for (int i = 0; i < nWindows; i++) {
161 String fullPathToFile = FilenameUtils.getFullPath(filename);
162 String directoryFullPath = fullPathToFile.replace(filename, "") + i;
163 windowFiles.add(directoryFullPath + File.separator + i);
164 }
165
166 lambdaValues = new double[nWindows];
167 temperatureValues = new double[nWindows];
168 pHValues = new double[nWindows];
169 for (int i = 0; i < nWindows; i++) {
170 if (sortTemp) {
171 temperatureValues[i] = lowTemperature * Math.exp(exponent * i);
172 } else {
173 double range = nWindows * pHGap;
174 double pHMin = pH - range / 2;
175 if (nWindows % 2 != 0) {
176 pHMin += pHGap / 2;
177 }
178 pHValues[i] = pHMin + i * pHGap;
179 }
180 }
181 }
182
183 String[] archiveFullPaths = new String[nWindows];
184 File file = new File(filename);
185 String directoryPath = file.getAbsoluteFile().getParent() + File.separator;
186 String[] archiveNewPath = new String[nWindows];
187 File[] saveFile = new File[nWindows];
188 File[] arcFiles = new File[nWindows];
189 String archiveName = FilenameUtils.getBaseName(filename) + ".arc";
190
191 writers = new XPHFilter[nWindows];
192 for (int i = 0; i < nWindows; i++) {
193 archiveFullPaths[i] = directoryPath + i + File.separator + archiveName;
194 File arcFile = new File(archiveFullPaths[i]);
195 arcFiles[i] = arcFile;
196 archiveNewPath[i] = directoryPath + i + File.separator + FilenameUtils.getBaseName(filename) + "_E" + i + ".arc";
197 saveFile[i] = new File(archiveNewPath[i]);
198 }
199
200 molecularAssembly = getActiveAssembly(filename);
201 extendedSystem = new ExtendedSystem(molecularAssembly, pH, null);
202 molecularAssembly.getPotentialEnergy().attachExtendedSystem(extendedSystem);
203
204 int numParallel = topology.getTopologiesInParallel(1);
205 threadsPer = threadsAvail / numParallel;
206
207 for (int i = 0; i < nWindows; i++) {
208 File arc = saveFile[i];
209 writers[i] = new XPHFilter(arc, molecularAssembly, molecularAssembly.getForceField(),
210 additionalProperties, extendedSystem);
211 }
212 opener = new XPHFilter(algorithmFunctions.getFilter(), extendedSystem);
213
214 double tolerance;
215 if (sortTemp) {
216 tolerance = 1.0e-2;
217 } else {
218 tolerance = 1.0e-1;
219 }
220
221 for (int i = 0; i < nWindows; i++) {
222
223 opener.setFile(arcFiles[i]);
224 molecularAssembly.setFile(arcFiles[i]);
225 logger.info("Set file to:" + arcFiles[i].toString());
226
227 int snapshots = opener.countNumModels();
228 logger.info(String.valueOf(snapshots));
229
230 for (int n = 0; n < snapshots; n++) {
231 boolean resetPosition = n == 0;
232
233
234 opener.readNext(resetPosition, false);
235
236 String remarkLine = opener.getRemarkLines()[0];
237
238 double snapshotLambda = 0;
239 double snapshotTemp = 0;
240 double snapshotPH = 0;
241 if (remarkLine.contains(" Lambda: ")) {
242 String[] tokens = remarkLine.split(" +");
243 for (int p = 0; p < tokens.length; p++) {
244 if (tokens[p].startsWith("Lambda")) {
245 snapshotLambda = Double.parseDouble(tokens[p + 1]);
246 }
247 if (tokens[p].startsWith("Temp")) {
248 snapshotTemp = Double.parseDouble(tokens[p + 1]);
249 }
250 if (tokens[p].startsWith("pH")) {
251 snapshotPH = Double.parseDouble(tokens[p + 1]);
252 }
253 }
254 }
255
256 double diff;
257 for (int k = 0; k < nWindows; k++) {
258 if (sortTemp) {
259 diff = Math.abs(temperatureValues[k] - snapshotTemp);
260 } else {
261 diff = Math.abs(pHValues[k] - snapshotPH);
262 }
263
264
265
266
267
268
269
270
271
272
273
274
275
276 }
277 }
278 }
279 return this;
280 }
281 }