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.parsers;
39
40 import ffx.potential.parameters.AngleTorsionType;
41 import ffx.potential.parameters.AngleType;
42 import ffx.potential.parameters.AtomType;
43 import ffx.potential.parameters.BaseType;
44 import ffx.potential.parameters.BioType;
45 import ffx.potential.parameters.BondType;
46 import ffx.potential.parameters.ForceField;
47 import ffx.potential.parameters.ForceField.ForceFieldName;
48 import ffx.potential.parameters.ForceField.ForceFieldType;
49 import ffx.potential.parameters.ImproperTorsionType;
50 import ffx.potential.parameters.MultipoleType;
51 import ffx.potential.parameters.OutOfPlaneBendType;
52 import ffx.potential.parameters.PiOrbitalTorsionType;
53 import ffx.potential.parameters.PolarizeType;
54 import ffx.potential.parameters.RelativeSolvationType;
55 import ffx.potential.parameters.SoluteType;
56 import ffx.potential.parameters.StretchBendType;
57 import ffx.potential.parameters.StretchTorsionType;
58 import ffx.potential.parameters.TorsionTorsionType;
59 import ffx.potential.parameters.TorsionType;
60 import ffx.potential.parameters.UreyBradleyType;
61 import ffx.potential.parameters.VDWPairType;
62 import ffx.potential.parameters.VDWType;
63 import ffx.utilities.Keyword;
64 import org.apache.commons.configuration2.CompositeConfiguration;
65 import org.apache.commons.configuration2.Configuration;
66 import org.apache.commons.configuration2.PropertiesConfiguration;
67 import org.apache.commons.configuration2.builder.FileBasedConfigurationBuilder;
68 import org.apache.commons.configuration2.builder.fluent.Parameters;
69 import org.apache.commons.configuration2.ex.ConfigurationException;
70
71 import java.io.BufferedReader;
72 import java.io.File;
73 import java.io.FileInputStream;
74 import java.io.FileNotFoundException;
75 import java.io.IOException;
76 import java.io.InputStream;
77 import java.io.InputStreamReader;
78 import java.net.URL;
79 import java.util.Iterator;
80 import java.util.logging.Level;
81 import java.util.logging.Logger;
82
83 import static ffx.potential.parameters.AngleType.AngleFunction;
84 import static ffx.potential.parameters.BondType.BondFunction;
85 import static java.lang.String.format;
86
87
88
89
90
91
92
93
94
95
96 public class ForceFieldFilter {
97
98 private static final Logger logger = Logger.getLogger(ForceFieldFilter.class.getName());
99
100
101 private static final ForceFieldName DEFAULT_FORCE_FIELD = ForceFieldName.AMOEBA_BIO_2018;
102
103 private final File forceFieldFile;
104
105 private final CompositeConfiguration properties;
106
107 private final ForceField forceField;
108
109
110
111
112
113
114
115 public ForceFieldFilter(CompositeConfiguration properties) {
116 this.properties = properties;
117 if (properties.containsKey("parameters")) {
118 String fileName = properties.getString("parameters");
119 if (properties.containsKey("propertyFile")) {
120 String propertyName = properties.getString("propertyFile");
121 logger.info(" Property File: " + propertyName);
122 File propertyFile = new File(propertyName);
123 forceFieldFile = parseParameterLocation(fileName, propertyFile);
124 } else {
125 forceFieldFile = parseParameterLocation(fileName, null);
126 }
127 } else {
128 forceFieldFile = null;
129 }
130 forceField = new ForceField(properties);
131 }
132
133
134
135
136
137
138 public static void main(String[] args) {
139 if (args == null || args.length < 1) {
140 System.out.println("Usage: ForceFieldFilter <file.prm>");
141 System.exit(-1);
142 }
143 CompositeConfiguration properties = Keyword.loadProperties(null);
144 properties.setProperty("parameters", args[0]);
145 ForceFieldFilter forceFieldFilter = new ForceFieldFilter(properties);
146 ForceField forceField = forceFieldFilter.parse();
147 if (forceField != null) {
148 forceField.print();
149 }
150 }
151
152
153
154
155
156
157
158
159 private static File parseParameterLocation(String parameterLocation, File keyFile) {
160 File parameterFile = null;
161 if (parameterLocation != null && !parameterLocation.equalsIgnoreCase("NONE")) {
162
163 parameterLocation = parameterLocation.replaceAll("\"", "");
164
165 parameterFile = new File(parameterLocation);
166
167
168 if (!parameterFile.exists() && keyFile != null) {
169 parameterFile = new File(keyFile.getParent() + File.separator + parameterLocation);
170 }
171 }
172 return parameterFile;
173 }
174
175
176
177
178
179
180 public ForceField parse() {
181 try {
182
183 if (forceFieldFile != null) {
184 File fileToOpen = forceFieldFile;
185 if (!fileToOpen.exists()) {
186 fileToOpen = new File(forceFieldFile.getAbsolutePath() + ".prm");
187 if (!fileToOpen.exists()) {
188 logger.log(Level.INFO, " {0} does not exist.", forceFieldFile);
189 return null;
190 }
191 }
192 if (!fileToOpen.canRead()) {
193 logger.log(Level.INFO, " {0} can not be read.", fileToOpen);
194 return null;
195 }
196 parse(new FileInputStream(fileToOpen));
197 } else {
198
199 String defaultFFstring = DEFAULT_FORCE_FIELD.toString().toUpperCase().replaceAll("_", "-");
200 String forceFieldString = properties.getString("forcefield", defaultFFstring);
201 ForceFieldName ff;
202 try {
203 ff = ForceField.ForceFieldName.valueOf(forceFieldString.toUpperCase().replace('-', '_'));
204 } catch (Exception e) {
205 logger.info(format(" The forcefield property %s was not recognized.\n", forceFieldString));
206 ff = DEFAULT_FORCE_FIELD;
207 }
208 URL url = ForceField.getForceFieldURL(ff);
209 if (url != null) {
210 forceField.forceFieldURL = url;
211 try {
212 FileBasedConfigurationBuilder<PropertiesConfiguration> builder = new FileBasedConfigurationBuilder<>(
213 PropertiesConfiguration.class).configure(
214 new Parameters().properties().setURL(url).setThrowExceptionOnMissing(true)
215
216 .setIncludesAllowed(false));
217 PropertiesConfiguration forceFieldConfiguration = builder.getConfiguration();
218 String name = ForceField.toPropertyForm(ff.toString());
219 forceFieldConfiguration.setHeader("Internal force field (" + name + ").");
220 properties.addConfiguration(forceFieldConfiguration);
221 } catch (ConfigurationException e) {
222 logger.warning(e.toString());
223 }
224 }
225 }
226
227
228 if (properties != null) {
229 parse(properties);
230 }
231 } catch (FileNotFoundException e) {
232 String message = "Exception parsing force field.";
233 logger.log(Level.WARNING, message, e);
234 }
235
236 String forceFieldName = forceField.getString("forcefield", "none");
237 if (forceFieldName != null) {
238 forceFieldName = forceFieldName.toUpperCase();
239 if (forceFieldName.contains("AMBER") || forceFieldName.contains("OPLS")
240 || forceFieldName.contains("CHARMM")) {
241 forceField.setBondFunction(BondFunction.HARMONIC);
242 forceField.setAngleFunction(AngleFunction.HARMONIC);
243 }
244 }
245
246 return forceField;
247 }
248
249 private void parse(CompositeConfiguration properties) {
250 try {
251 int numConfigs = properties.getNumberOfConfigurations();
252
253
254
255
256
257 for (int n = numConfigs - 1; n >= 0; n--) {
258 Configuration config = properties.getConfiguration(n);
259 if (config instanceof PropertiesConfiguration propertiesConfiguration) {
260 if (propertiesConfiguration.getHeader() != null) {
261 logger.info(" Parsing: " + propertiesConfiguration.getHeader());
262 }
263 }else{
264 if(logger.isLoggable(Level.FINER)) {
265 logger.finer(" Configuration was not an instance of PropertiesConfiguration.");
266 }
267 }
268
269 Iterator<String> i = config.getKeys();
270 while (i.hasNext()) {
271 String key = i.next();
272
273
274 if (!ForceField.isForceFieldType(key)) {
275 if(logger.isLoggable(Level.FINER)){
276 logger.finer(" Key value (" + key + ") is not a valid force field type.");
277 }
278 continue;
279 }
280
281 String[] list = config.getStringArray(key);
282 for (String s : list) {
283
284 s = key + " " + s;
285
286
287 String input = s.split("#+")[0];
288 String[] tokens = input.trim().split(" +");
289
290
291 ForceFieldType type;
292 try {
293 type = ForceFieldType.valueOf(key.toUpperCase());
294 } catch (Exception e) {
295 break;
296 }
297
298 BaseType baseType = switch (type) {
299 case ATOM -> AtomType.parse(input, tokens);
300 case ANGTORS -> AngleTorsionType.parse(input, tokens);
301 case ANGLE -> AngleType.parse(input, tokens);
302 case ANGLEP -> AngleType.parseInPlane(input, tokens);
303 case BIOTYPE -> BioType.parse(input, tokens);
304 case BOND -> BondType.parse(input, tokens);
305 case CHARGE -> MultipoleType.parseChargeType(input, tokens);
306 case MULTIPOLE -> MultipoleType.parse(input, tokens);
307 case OPBEND -> OutOfPlaneBendType.parse(input, tokens);
308 case STRBND -> StretchBendType.parse(input, tokens);
309 case PITORS -> PiOrbitalTorsionType.parse(input, tokens);
310 case IMPTORS -> ImproperTorsionType.parse(input, tokens);
311 case TORSION -> TorsionType.parse(input, tokens);
312 case IMPROPER -> TorsionType.parseImproper(input, tokens);
313 case STRTORS -> StretchTorsionType.parse(input, tokens);
314 case TORTORS -> TorsionTorsionType.parse(input, tokens);
315 case UREYBRAD -> UreyBradleyType.parse(input, tokens);
316 case VDW -> VDWType.parse(input, tokens);
317 case VDW14 -> VDWType.parseVDW14(input, tokens);
318 case VDWPR, VDWPAIR -> VDWPairType.parse(input, tokens);
319 case POLARIZE -> PolarizeType.parse(input, tokens);
320 case RELATIVESOLV -> RelativeSolvationType.parse(input, tokens);
321 case SOLUTE -> SoluteType.parse(input, tokens);
322 default -> {
323 logger.log(Level.WARNING, "ForceField type recognized, but not stored:{0}", type);
324 yield null;
325 }
326 };
327 if (baseType != null) {
328 forceField.addForceFieldType(baseType);
329 }
330 }
331 }
332 }
333 } catch (Exception e) {
334 String message = "Exception parsing force field.";
335 logger.log(Level.WARNING, message, e);
336 }
337 logger.info("");
338 }
339
340 private void parse(InputStream stream) {
341 try (BufferedReader br = new BufferedReader(new InputStreamReader(stream))) {
342 while (br.ready()) {
343 String input = br.readLine();
344 parse(input, br);
345 }
346 } catch (IOException e) {
347 String message = "Error parsing force field parameters.\n";
348 logger.log(Level.SEVERE, message, e);
349 }
350 }
351
352 private void parse(String input, BufferedReader br) {
353
354
355 String originalInput = input;
356 String[] inputs = input.split("#");
357 if (inputs.length < 1) {
358 return;
359 }
360
361 input = inputs[0].split("#")[0];
362
363 String[] tokens = input.trim().split(" +");
364 if (tokens[0].equalsIgnoreCase("")) {
365 return;
366 }
367
368 try {
369 ForceFieldType type = ForceFieldType.valueOf(tokens[0].toUpperCase());
370 BaseType baseType = switch (type) {
371 case ATOM -> AtomType.parse(input, tokens);
372 case ANGLE -> AngleType.parse(input, tokens);
373 case ANGLEP -> AngleType.parseInPlane(input, tokens);
374 case ANGTORS -> AngleTorsionType.parse(input, tokens);
375 case BIOTYPE -> BioType.parse(input, tokens);
376 case BOND -> BondType.parse(input, tokens);
377 case CHARGE -> MultipoleType.parseChargeType(input, tokens);
378 case MULTIPOLE -> MultipoleType.parse(input, tokens, br);
379 case OPBEND -> OutOfPlaneBendType.parse(input, tokens);
380 case STRBND -> StretchBendType.parse(input, tokens);
381 case PITORS -> PiOrbitalTorsionType.parse(input, tokens);
382 case IMPTORS -> ImproperTorsionType.parse(input, tokens);
383 case STRTORS -> StretchTorsionType.parse(input, tokens);
384 case TORSION -> TorsionType.parse(input, tokens);
385 case IMPROPER -> TorsionType.parseImproper(input, tokens);
386 case TORTORS -> TorsionTorsionType.parse(input, tokens, br);
387 case UREYBRAD -> UreyBradleyType.parse(input, tokens);
388 case VDW -> VDWType.parse(input, tokens);
389 case VDW14 -> VDWType.parseVDW14(input, tokens);
390 case VDWPR, VDWPAIR -> VDWPairType.parse(input, tokens);
391 case POLARIZE -> PolarizeType.parse(input, tokens);
392 case RELATIVESOLV -> RelativeSolvationType.parse(input, tokens);
393 case SOLUTE ->
394
395 SoluteType.parse(originalInput, originalInput.trim().split(" +"));
396 default -> {
397 logger.log(Level.WARNING, "ForceField type recognized, but not stored:{0}", type);
398 yield null;
399 }
400 };
401 if (baseType != null) {
402 forceField.addForceFieldType(baseType);
403 }
404 return;
405 } catch (Exception e) {
406
407
408
409
410 }
411
412
413 try {
414 String key = tokens[0];
415 String value = input.replaceFirst(tokens[0], "").trim();
416 forceField.addProperty(key, value);
417 } catch (Exception e) {
418 logger.info(" Ignored line: " + input);
419 }
420 }
421 }