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.potential.commands;
39
40 import ffx.crystal.SymOp;
41 import ffx.potential.MolecularAssembly;
42 import ffx.potential.bonded.Atom;
43 import ffx.potential.cli.PotentialCommand;
44 import ffx.potential.cli.SaveOptions;
45 import ffx.potential.parameters.ForceField;
46 import ffx.potential.parsers.SystemFilter;
47 import ffx.potential.parsers.XYZFilter;
48 import ffx.utilities.FFXBinding;
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
56 import static ffx.crystal.SymOp.applyCartesianSymOp;
57 import static org.apache.commons.io.FilenameUtils.concat;
58 import static org.apache.commons.io.FilenameUtils.getName;
59 import static org.apache.commons.io.FilenameUtils.removeExtension;
60
61
62
63
64
65
66
67 @Command(name = "SaveAsXYZ", description = " Save the system as an XYZ file.")
68 public class SaveAsXYZ extends PotentialCommand {
69
70 @Mixin
71 private SaveOptions saveOptions = new SaveOptions();
72
73
74 @Option(names = {"-p", "--pos-offset"}, paramLabel = "0",
75 description = "Positive offset of atom types in the new file")
76 private int posOffset = 0;
77
78
79 @Option(names = {"-n", "--neg-offset"}, paramLabel = "0",
80 description = "Negative offset of atom types in the new file.")
81 private int negOffset = 0;
82
83
84 @Option(names = {"-r", "--random"}, paramLabel = "X",
85 description = "Apply a random Cartesian SymOp with translation range -X .. X.")
86 private double scalar = -1.0;
87
88
89 @Option(names = {"--fs", "--firstSnapshot"}, paramLabel = "-1", defaultValue = "-1",
90 description = "First snapshot to write out (indexed from 0).")
91 private int firstSnapshot = -1;
92
93
94 @Option(names = {"--ls", "--lastSnapshot"}, paramLabel = "-1", defaultValue = "-1",
95 description = "Last snapshot to write out (indexed from 0).")
96 private int lastSnapshot = -1;
97
98
99 @Option(names = {"--si", "--snapshotIncrement"}, paramLabel = "1", defaultValue = "1",
100 description = "Increment between written snapshots.")
101 private int snapshotIncrement = 1;
102
103
104 @Option(names = {"--wd", "--writeToDirectories"}, paramLabel = "false", defaultValue = "false",
105 description = "Write snapshots to numbered subdirectories.")
106 private boolean writeToDirectories = false;
107
108
109 @Option(names = {"--alt", "--alternateLocation"}, paramLabel = "A", defaultValue = "A",
110 description = "Choose an alternate location for the PDB file (not supported for PDBs with multiple models.")
111 private Character alternateLocation = 'A';
112
113
114 @Parameters(arity = "1", paramLabel = "file",
115 description = "The atomic coordinate file PDB format.")
116 private String filename = null;
117
118 public SaveAsXYZ() { super(); }
119 public SaveAsXYZ(FFXBinding binding) { super(binding); }
120 public SaveAsXYZ(String[] args) { super(args); }
121
122 @Override
123 public SaveAsXYZ run() {
124 if (!init()) {
125 return this;
126 }
127
128
129 MolecularAssembly[] molecularAssemblies = getActiveAssemblies(filename);
130 if (molecularAssemblies == null) {
131 logger.info(helpString());
132 return this;
133 }
134
135 if (molecularAssemblies.length > 1) {
136 Character currentAltLoc = activeAssembly.getAlternateLocation();
137 logger.info("\n Current alternate location: " + currentAltLoc);
138 if (!currentAltLoc.equals(alternateLocation)) {
139 for (MolecularAssembly molecularAssembly : molecularAssemblies) {
140 Character altLoc = molecularAssembly.getAlternateLocation();
141 if (altLoc.equals(alternateLocation)) {
142 activeAssembly = molecularAssembly;
143 logger.info(" Switching to alternate location: " + altLoc);
144 break;
145 }
146 }
147 }
148 }
149
150
151 filename = activeAssembly.getFile().getAbsolutePath();
152
153 SystemFilter openFilter = potentialFunctions.getFilter();
154 int numModels = openFilter.countNumModels();
155
156 int offset = 0;
157 if (posOffset > 0) {
158 offset = posOffset;
159 }
160 if (negOffset > 0) {
161 offset = -negOffset;
162 }
163
164 if (offset != 0) {
165 logger.info("\n Offset atom types by " + offset);
166 ForceField forceField = activeAssembly.getForceField();
167 forceField.renumberForceField(0, offset, 0);
168 }
169
170 if (scalar > 0.0) {
171 SymOp symOp = SymOp.randomSymOpFactory(scalar);
172 logger.info(String.format("\n Applying random Cartesian SymOp\n: %s", symOp));
173 Atom[] atoms = activeAssembly.getAtomArray();
174 double[] xyz = new double[3];
175 for (Atom atom : atoms) {
176 atom.getXYZ(xyz);
177 applyCartesianSymOp(xyz, xyz, symOp);
178 atom.setXYZ(xyz);
179 }
180 }
181
182 String dirString = getBaseDirString(filename);
183 String name = getName(filename);
184
185
186 if (firstSnapshot >= 0) {
187 XYZFilter snapshotFilter = new XYZFilter(new File(dirString + name),
188 activeAssembly, activeAssembly.getForceField(), activeAssembly.getProperties());
189 openFilter.readNext(true);
190 int counter = 0;
191 int snapshotCounter = 0;
192 logger.info(" Writing snapshots from " + firstSnapshot + " to " + lastSnapshot + " with increment " + snapshotIncrement);
193 boolean reset = true;
194
195 while (openFilter.readNext(reset)) {
196
197 reset = false;
198 int counterOffset = counter - firstSnapshot;
199 if (counter >= firstSnapshot && (lastSnapshot < 0 || counter <= lastSnapshot) && counterOffset % snapshotIncrement == 0) {
200 File snapshotFile;
201 if (writeToDirectories) {
202 String subdirectory = concat(dirString, Integer.toString(snapshotCounter));
203 new File(subdirectory).mkdirs();
204 snapshotFile = new File(concat(subdirectory, name));
205 } else {
206 snapshotFile = new File(concat(dirString, removeExtension(name) + "." + counter + ".xyz"));
207 }
208
209 potentialFunctions.versionFile(snapshotFile);
210 saveOptions.preSaveOperations(activeAssembly);
211 logger.info("\n Writing out XYZ for " + snapshotFile);
212 snapshotFilter.writeFile(snapshotFile, true);
213 snapshotCounter++;
214 }
215 counter++;
216 }
217 return this;
218 }
219
220 logger.info("\n Writing out XYZ for " + filename);
221
222 if (numModels <= 1) {
223
224 name = removeExtension(name) + ".xyz";
225 File saveFile = new File(dirString + name);
226 saveOptions.preSaveOperations(activeAssembly);
227 potentialFunctions.save(activeAssembly, saveFile);
228 } else {
229
230 name = removeExtension(name) + ".arc";
231 File saveFile = new File(dirString + name);
232 saveFile = potentialFunctions.versionFile(saveFile);
233 saveOptions.preSaveOperations(activeAssembly);
234 potentialFunctions.save(activeAssembly, saveFile);
235
236 XYZFilter saveFilter = (XYZFilter) potentialFunctions.getFilter();
237 while (openFilter.readNext(false)) {
238 saveOptions.preSaveOperations(activeAssembly);
239 saveFilter.writeFile(saveFile, true);
240 }
241 }
242
243 return this;
244 }
245 }