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.MolecularAssembly;
41 import ffx.potential.Utilities.FileType;
42 import ffx.potential.bonded.Atom;
43 import ffx.potential.bonded.Bond;
44 import ffx.potential.nonbonded.RestrainPosition;
45 import ffx.potential.parameters.ForceField;
46 import org.apache.commons.configuration2.CompositeConfiguration;
47
48 import java.io.File;
49 import java.util.ArrayList;
50 import java.util.HashSet;
51 import java.util.List;
52 import java.util.OptionalDouble;
53 import java.util.Set;
54 import java.util.Vector;
55 import java.util.logging.Level;
56 import java.util.logging.Logger;
57 import java.util.regex.Pattern;
58
59 import static ffx.utilities.StringUtils.parseAtomRange;
60 import static java.lang.String.format;
61
62
63
64
65
66
67
68 public abstract class SystemFilter {
69
70 protected static final Pattern lambdaPattern = Pattern.compile("Lambda: +([01]\\.\\d+)");
71 private static final Logger logger = Logger.getLogger(SystemFilter.class.getName());
72 private static Versioning vers = Versioning.TINKER;
73 private static int absoluteCounter = 0;
74
75
76
77 protected final boolean dieOnMissingAtom;
78
79
80
81 protected final boolean standardizeAtomNames;
82
83
84
85
86 protected final boolean vdwH;
87
88
89
90 protected List<Atom> atomList = null;
91
92
93
94 protected List<Bond> bondList = null;
95
96
97
98
99 protected List<MolecularAssembly> systems = new Vector<>();
100
101
102
103 protected List<File> files;
104
105
106
107 protected FileType fileType = FileType.UNK;
108
109
110
111 protected CompositeConfiguration properties;
112
113
114
115 protected ForceField forceField;
116
117
118
119 protected boolean fileRead = false;
120
121
122
123
124 MolecularAssembly activeMolecularAssembly;
125
126
127
128 File currentFile = null;
129
130
131
132
133
134
135
136 private SystemFilter(ForceField forceField, CompositeConfiguration properties) {
137 this.forceField = forceField;
138 this.properties = properties;
139 if (properties != null) {
140 vdwH = properties.getBoolean("vdwHydrogens", false);
141 dieOnMissingAtom = properties.getBoolean("trajectory-dieOnMissing", false);
142 standardizeAtomNames = properties.getBoolean("standardizeAtomNames", true);
143 } else {
144 vdwH = false;
145 dieOnMissingAtom = false;
146 standardizeAtomNames = true;
147 }
148 }
149
150
151
152
153
154
155
156
157
158
159 public SystemFilter(List<File> files, MolecularAssembly molecularAssembly, ForceField forceField,
160 CompositeConfiguration properties) {
161 this(forceField, properties);
162 this.files = files;
163 if (files != null) {
164 this.currentFile = files.get(0);
165 }
166 this.activeMolecularAssembly = molecularAssembly;
167 }
168
169
170
171
172
173
174
175
176
177
178 public SystemFilter(File file, MolecularAssembly molecularAssembly, ForceField forceField,
179 CompositeConfiguration properties) {
180 this(forceField, properties);
181 files = new ArrayList<>();
182 if (file != null) {
183 files.add(file);
184 }
185 this.currentFile = file;
186 this.activeMolecularAssembly = molecularAssembly;
187 }
188
189
190
191
192
193
194
195
196
197
198 public SystemFilter(File file, List<MolecularAssembly> molecularAssemblies, ForceField forceField,
199 CompositeConfiguration properties) {
200 this(forceField, properties);
201 files = new ArrayList<>();
202 if (file != null) {
203 files.add(file);
204 }
205 this.currentFile = file;
206 this.systems = new ArrayList<>(molecularAssemblies);
207 this.activeMolecularAssembly = systems.get(0);
208 }
209
210
211
212
213
214
215
216 public static File previousVersion(File file) {
217 if (file == null) {
218 return null;
219 }
220 String fileName = file.getAbsolutePath();
221 int dot = file.getAbsolutePath().lastIndexOf(".");
222 int under = file.getAbsolutePath().lastIndexOf("_");
223 File newFile = file;
224 if (under > dot) {
225 String name = fileName.substring(0, under);
226 newFile = new File(name);
227 }
228 File baseFile = newFile;
229 File previousFile = null;
230 int i = 1;
231 while (newFile.exists()) {
232 i = i + 1;
233 previousFile = newFile;
234 newFile = baseFile;
235 int thousand = i / 1000;
236 int hundred = (i - 1000 * thousand) / 100;
237 int tens = (i - 1000 * thousand - 100 * hundred) / 10;
238 int ones = i - 1000 * thousand - 100 * hundred - 10 * tens;
239 StringBuilder newFileString = new StringBuilder(baseFile.getAbsolutePath());
240 if (thousand != 0) {
241 newFileString.append('_').append(thousand).append(hundred).append(tens).append(ones);
242 } else if (hundred != 0) {
243 newFileString.append('_').append(hundred).append(tens).append(ones);
244 } else if (tens != 0) {
245 newFileString.append('_').append(tens).append(ones);
246 } else {
247 newFileString.append('_').append(ones);
248 }
249 newFile = new File(newFileString.toString());
250 }
251 return previousFile;
252 }
253
254
255
256
257
258
259 public static void setVersioning(Versioning vers) {
260 SystemFilter.vers = vers;
261 }
262
263
264
265
266
267
268
269 public static File version(File file) {
270 if (vers == Versioning.TINKER) {
271 return versionTinker(file);
272 } else {
273 if (vers == Versioning.PREFIX_ABSOLUTE || vers == Versioning.POSTFIX_ABSOLUTE) {
274 return versionAbsolute(file, (vers == Versioning.PREFIX_ABSOLUTE));
275 } else {
276 return version(file, (vers == Versioning.PREFIX));
277 }
278 }
279 }
280
281 private static File version(File file, boolean prefix) {
282 if (file == null || !(file.exists())) {
283 return file;
284 }
285 String fn = file.getAbsolutePath();
286 int dot = fn.lastIndexOf(".");
287 int under = fn.lastIndexOf("_");
288 if (dot < 0) {
289 fn += ".unk";
290 dot = fn.lastIndexOf(".");
291 }
292 if (under < 0) {
293 under = dot;
294 }
295 String name = (prefix) ? fn.substring(0, under) : fn.substring(0, dot);
296 String extension = (prefix) ? fn.substring(dot + 1) : fn.substring(dot + 1, under);
297 int number = 0;
298 String newFn = (prefix) ? format("%s_%d.%s", name, number, extension)
299 : format("%s.%s_%d", name, extension, number);
300 if (prefix && under < dot) {
301 try {
302 number = Integer.parseInt(fn.substring(under + 1, dot));
303 } catch (NumberFormatException ex) {
304
305 name = fn.substring(0, dot);
306 number++;
307 newFn = format("%s_%d.%s", name, number, extension);
308 }
309 } else if (!prefix && under > dot) {
310 try {
311 number = Integer.parseInt(fn.substring(under + 1));
312 number++;
313 } catch (NumberFormatException ex) {
314
315 }
316 }
317 File newFile = new File(newFn);
318 while (newFile.exists()) {
319 ++number;
320 newFn = (prefix) ? format("%s_%d.%s", name, number, extension)
321 : format("%s.%s_%d", name, extension, number);
322 newFile = new File(newFn);
323 }
324 return newFile;
325 }
326
327 private static synchronized File versionAbsolute(File file, boolean prefix) {
328 if (file == null || !(file.exists())) {
329 return file;
330 }
331 String fn = file.getAbsolutePath();
332 int dot = fn.lastIndexOf(".");
333 int under = fn.lastIndexOf("_");
334 if (dot < 0) {
335 fn += ".unk";
336 dot = fn.lastIndexOf(".");
337 }
338 if (under < 0) {
339 under = dot;
340 }
341 String name = (prefix) ? fn.substring(0, under) : fn.substring(0, dot);
342 String extension = (prefix) ? fn.substring(dot + 1) : fn.substring(dot + 1, under);
343 String newFn = (prefix) ? format("%s_%d.%s", name, absoluteCounter, extension)
344 : format("%s.%s_%d", name, extension, absoluteCounter);
345 File newFile = new File(newFn);
346 while (newFile.exists()) {
347 absoluteCounter++;
348 newFn = (prefix) ? format("%s_%d.%s", name, absoluteCounter, extension)
349 : format("%s.%s_%d", name, extension, absoluteCounter);
350 newFile = new File(newFn);
351 }
352 return newFile;
353 }
354
355
356
357
358
359
360
361 private static File versionTinker(File file) {
362 if (file == null) {
363 return null;
364 }
365 if (!file.exists()) {
366 return file;
367 }
368 String fileName = file.getAbsolutePath();
369 int dot = file.getAbsolutePath().lastIndexOf(".");
370 int under = file.getAbsolutePath().lastIndexOf("_");
371 File newFile = file;
372 if (under > dot) {
373 String name = fileName.substring(0, under);
374 newFile = new File(name);
375 }
376 File oldFile = newFile;
377 int i = 1;
378 while (newFile.exists()) {
379 i = i + 1;
380 String newFileString = format("%s_%d", oldFile.getAbsolutePath(), i);
381 newFile = new File(newFileString);
382 }
383 return newFile;
384 }
385
386
387
388
389
390
391
392
393 public static Set<Atom> atomListToSet(List<Integer> atomList, Atom[] atoms) {
394 Set<Atom> atomSet = new HashSet<>();
395 for (int i = 0; i < atomList.size(); i++) {
396 atomSet.add(atoms[atomList.get(i)]);
397 }
398 return atomSet;
399 }
400
401
402
403
404
405
406
407 public void applyAtomProperties() {
408
409
410
411
412
413 Atom[] atomArray = activeMolecularAssembly.getAtomArray();
414 int nAtoms = atomArray.length;
415 String[] nouseKeys = properties.getStringArray("nouse");
416 for (String nouseKey : nouseKeys) {
417 String[] toks = nouseKey.split("\\s+");
418 for (String tok : toks) {
419 try {
420 List<Integer> nouseRange = parseAtomRange("nouse", tok, nAtoms);
421 for (int j : nouseRange) {
422 atomArray[j].setUse(false);
423 }
424 } catch (IllegalArgumentException ex) {
425 boolean atomFound = false;
426 for (Atom atom : atomArray) {
427 if (atom.getName().equalsIgnoreCase(tok)) {
428 atomFound = true;
429 atom.setUse(false);
430 }
431 }
432 if (atomFound) {
433 logger.info(format(" Setting atoms with name %s to not be used", tok));
434 } else {
435 logger.log(Level.INFO, ex.getLocalizedMessage());
436 }
437 }
438 }
439 }
440
441 if (properties.containsKey("active")) {
442 for (Atom atom : atomArray) {
443 atom.setActive(false);
444 }
445 String[] activeKeys = properties.getStringArray("active");
446 for (String inactiveKey : activeKeys) {
447 try {
448 List<Integer> inactiveRange = parseAtomRange("inactive", inactiveKey, nAtoms);
449 for (int i : inactiveRange) {
450 atomArray[i].setActive(false);
451 }
452 } catch (IllegalArgumentException ex) {
453 logger.log(Level.INFO, ex.getLocalizedMessage());
454 }
455 }
456 } else if (properties.containsKey("inactive")) {
457 for (Atom atom : atomArray) {
458 atom.setActive(true);
459 }
460 String[] inactiveKeys = properties.getStringArray("inactive");
461 for (String inactiveKey : inactiveKeys) {
462 try {
463 List<Integer> inactiveRange = parseAtomRange("inactive", inactiveKey, nAtoms);
464 for (int i : inactiveRange) {
465 atomArray[i].setActive(false);
466 }
467 } catch (IllegalArgumentException ex) {
468 logger.log(Level.INFO, ex.getLocalizedMessage());
469 }
470 }
471 }
472
473 String[] noElStrings = properties.getStringArray("noElectro");
474 for (String noE : noElStrings) {
475 String[] toks = noE.split("\\s+");
476 for (String tok : toks) {
477 try {
478 List<Integer> noERange = parseAtomRange("noElectro", tok, nAtoms);
479 for (int i : noERange) {
480 atomArray[i].setElectrostatics(false);
481 }
482 } catch (IllegalArgumentException ex) {
483 boolean atomFound = false;
484 for (Atom atom : atomArray) {
485 if (atom.getName().equalsIgnoreCase(tok)) {
486 atomFound = true;
487 atom.setElectrostatics(false);
488 }
489 }
490 if (atomFound) {
491 logger.info(format(" Disabled electrostatics for atoms with name %s", tok));
492 } else {
493 logger.log(Level.INFO, format(" No electrostatics input %s could not be parsed as a numerical "
494 + "range or atom type present in assembly", tok));
495 }
496 }
497 }
498 }
499 }
500
501
502
503
504
505 public abstract void closeReader();
506
507 public int countNumModels() {
508 return -1;
509 }
510
511
512
513
514
515
516 public boolean fileRead() {
517 return fileRead;
518 }
519
520
521
522
523
524
525 public MolecularAssembly getActiveMolecularSystem() {
526 return activeMolecularAssembly;
527 }
528
529
530
531
532
533
534 public List<Atom> getAtomList() {
535 return atomList;
536 }
537
538
539
540
541
542
543 public File getFile() {
544 return currentFile;
545 }
546
547
548
549
550
551
552 public void setFile(File file) {
553 this.currentFile = file;
554 files = new ArrayList<>();
555 if (file != null) {
556 files.add(file);
557 }
558 }
559
560
561
562
563
564
565 public List<File> getFiles() {
566 return files;
567 }
568
569
570
571
572
573
574 public void setFiles(List<File> files) {
575 this.files = files;
576 if (files != null && !files.isEmpty()) {
577 this.currentFile = files.get(0);
578 } else {
579 this.currentFile = null;
580 }
581 }
582
583
584
585
586
587
588 public OptionalDouble getLastReadLambda() {
589 return OptionalDouble.empty();
590 }
591
592
593
594
595
596
597 public MolecularAssembly[] getMolecularAssemblyArray() {
598 if (!systems.isEmpty()) {
599 return systems.toArray(new MolecularAssembly[0]);
600 } else {
601 return new MolecularAssembly[]{activeMolecularAssembly};
602 }
603 }
604
605
606
607
608
609
610 public String[] getRemarkLines() {
611 return new String[0];
612 }
613
614
615
616
617
618
619 public int getSnapshot() {
620 return -1;
621 }
622
623
624
625
626
627
628 public FileType getType() {
629 return fileType;
630 }
631
632
633
634
635
636
637 public void setType(FileType fileType) {
638 this.fileType = fileType;
639 }
640
641
642
643
644
645
646 public abstract boolean readFile();
647
648
649
650
651
652
653 public abstract boolean readNext();
654
655
656
657
658
659
660
661 public abstract boolean readNext(boolean resetPosition);
662
663
664
665
666
667
668
669
670 public abstract boolean readNext(boolean resetPosition, boolean print);
671
672
673
674
675
676
677
678
679
680 public abstract boolean readNext(boolean resetPosition, boolean print, boolean parse);
681
682
683
684
685
686
687 public void setForceField(ForceField forceField) {
688 this.forceField = forceField;
689 }
690
691
692
693
694
695
696
697 public void setProperties(CompositeConfiguration properties) {
698 this.properties = properties;
699 }
700
701
702
703
704
705
706
707
708
709
710
711
712 public boolean writeFile(File saveFile, boolean append) {
713 return writeFile(saveFile, append, null);
714 }
715
716
717
718
719
720
721
722
723
724
725
726
727
728 public abstract boolean writeFile(File saveFile, boolean append, String[] extraLines);
729
730
731
732
733
734
735 protected void setFileRead(boolean fileRead) {
736 this.fileRead = fileRead;
737 }
738
739
740
741
742
743
744 void setMolecularSystem(MolecularAssembly molecularAssembly) {
745 activeMolecularAssembly = molecularAssembly;
746 }
747
748 public enum Versioning {
749 TINKER, PREFIX, POSTFIX, PREFIX_ABSOLUTE, POSTFIX_ABSOLUTE, NONE
750 }
751 }