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