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.crystal.Crystal;
41 import ffx.crystal.SymOp;
42 import ffx.potential.MolecularAssembly;
43 import ffx.potential.Utilities.FileType;
44 import ffx.potential.bonded.Atom;
45 import ffx.potential.bonded.Bond;
46 import ffx.potential.bonded.Residue;
47 import ffx.potential.extended.ExtendedSystem;
48 import ffx.potential.parameters.AtomType;
49 import ffx.potential.parameters.BondType;
50 import ffx.potential.parameters.ForceField;
51 import org.apache.commons.configuration2.CompositeConfiguration;
52 import org.jogamp.vecmath.Vector3d;
53
54 import java.io.BufferedReader;
55 import java.io.BufferedWriter;
56 import java.io.File;
57 import java.io.FileNotFoundException;
58 import java.io.FileReader;
59 import java.io.FileWriter;
60 import java.io.IOException;
61 import java.util.ArrayList;
62 import java.util.HashMap;
63 import java.util.List;
64 import java.util.OptionalDouble;
65 import java.util.logging.Level;
66 import java.util.logging.Logger;
67 import java.util.regex.Matcher;
68 import java.util.regex.Pattern;
69
70 import static ffx.potential.bonded.Bond.logNoBondType;
71 import static java.lang.Double.parseDouble;
72 import static java.lang.Integer.parseInt;
73 import static java.lang.String.format;
74
75
76
77
78
79
80
81 public class XPHFilter extends SystemFilter {
82
83 private static final Logger logger = Logger.getLogger(XPHFilter.class.getName());
84 private BufferedReader bufferedReader = null;
85 private int snapShot;
86 private String remarkLine;
87 private ExtendedSystem extendedSystem;
88 private MolecularAssembly system = null;
89
90
91
92
93
94
95
96
97
98 public XPHFilter(File file, MolecularAssembly system, ForceField forceField,
99 CompositeConfiguration properties, ExtendedSystem esvSystem) {
100 super(file, system, forceField, properties);
101 this.fileType = FileType.XPH;
102 extendedSystem = esvSystem;
103 this.system = system;
104 }
105
106 public XPHFilter(SystemFilter systemFilter, ExtendedSystem esvSystem) {
107 super(systemFilter.getFile(), systemFilter.getActiveMolecularSystem(),
108 systemFilter.getActiveMolecularSystem().getForceField(),
109 systemFilter.getActiveMolecularSystem().getProperties());
110
111 extendedSystem = esvSystem;
112 }
113
114
115
116
117
118
119
120
121 public static boolean readOnto(File newFile, MolecularAssembly oldSystem) {
122 if (newFile == null || !newFile.exists() || oldSystem == null) {
123 return false;
124 }
125 try (BufferedReader br = new BufferedReader(new FileReader(newFile))) {
126 String data = br.readLine();
127 if (data == null) {
128 return false;
129 }
130 String[] tokens = data.trim().split(" +");
131 int num_atoms = parseInt(tokens[0]);
132 if (num_atoms != oldSystem.getAtomList().size()) {
133 return false;
134 }
135
136 br.mark(10000);
137 data = br.readLine();
138 if (!readPBC(data, oldSystem)) {
139 br.reset();
140 }
141
142 double[][] d = new double[num_atoms][3];
143 for (int i = 0; i < num_atoms; i++) {
144 if (!br.ready()) {
145 return false;
146 }
147 data = br.readLine();
148 if (data == null) {
149 logger.warning(format(" Check atom %d.", (i + 1)));
150 return false;
151 }
152 tokens = data.trim().split(" +");
153 if (tokens.length < 6) {
154 logger.warning(format(" Check atom %d.", (i + 1)));
155 return false;
156 }
157 d[i][0] = parseDouble(tokens[2]);
158 d[i][1] = parseDouble(tokens[3]);
159 d[i][2] = parseDouble(tokens[4]);
160 }
161 List<Atom> atoms = oldSystem.getAtomList();
162 for (Atom a : atoms) {
163 int index = a.getIndex() - 1;
164 a.setXYZ(d[index]);
165 }
166 oldSystem.center();
167 oldSystem.setFile(newFile);
168 return true;
169 } catch (Exception e) {
170 return false;
171 }
172 }
173
174 private static boolean firstTokenIsInteger(String data) {
175 if (data == null) {
176 return false;
177 }
178
179
180 data = data.trim();
181 if (data.equals("")) {
182 return false;
183 }
184
185
186 try {
187 String[] tokens = data.split(" +");
188 parseInt(tokens[0]);
189 return true;
190 } catch (NumberFormatException e) {
191 return false;
192 }
193 }
194
195
196
197
198
199
200
201 private static boolean readPBC(String data, MolecularAssembly activeMolecularAssembly) {
202 if (firstTokenIsInteger(data)) {
203 return false;
204 }
205
206 String[] tokens = data.trim().split(" +");
207 if (tokens.length == 6) {
208 CompositeConfiguration config = activeMolecularAssembly.getProperties();
209 double a = parseDouble(tokens[0]);
210 double b = parseDouble(tokens[1]);
211 double c = parseDouble(tokens[2]);
212 double alpha = parseDouble(tokens[3]);
213 double beta = parseDouble(tokens[4]);
214 double gamma = parseDouble(tokens[5]);
215 config.setProperty("a-axis", a);
216 config.setProperty("b-axis", b);
217 config.setProperty("c-axis", c);
218 config.setProperty("alpha", alpha);
219 config.setProperty("beta", beta);
220 config.setProperty("gamma", gamma);
221
222 Crystal crystal = activeMolecularAssembly.getCrystal();
223 if (crystal != null) {
224 crystal.changeUnitCellParameters(a, b, c, alpha, beta, gamma);
225 }
226 }
227 return true;
228 }
229
230
231 @Override
232 public void closeReader() {
233 if (bufferedReader != null) {
234 try {
235 bufferedReader.close();
236 } catch (IOException ex) {
237 logger.warning(format(" Exception in closing XYZ filter: %s", ex));
238 }
239 }
240 }
241
242 @Override
243 public int countNumModels(){
244 File xphFile = currentFile;
245 int nAtoms = activeMolecularAssembly.getAtomArray().length;
246 Pattern crystInfoPattern = Pattern.compile(
247 "^ *(?:[0-9]+\\.[0-9]+ +){3}(?:-?[0-9]+\\.[0-9]+ +){2}(?:-?[0-9]+\\.[0-9]+) *$");
248
249 try (BufferedReader br = new BufferedReader(new FileReader(xphFile))) {
250 String line = br.readLine();
251 int nSnaps = 0;
252
253 while (line != null) {
254 assert parseInt(line.trim().split("\\s+")[0]) == nAtoms;
255
256 line = br.readLine();
257 Matcher m = crystInfoPattern.matcher(line);
258 if (m.matches()) {
259
260 br.readLine();
261 }
262
263 for (int i = 1; i < nAtoms; i++) {
264 br.readLine();
265 }
266
267 String data = br.readLine();
268
269
270 while (data != null && data.trim().equals("")) {
271 data = br.readLine();
272 }
273
274
275
276 assert data != null;
277 if(data.contains("ESV")) {
278
279 while (data != null && !data.trim().equals("")) {
280 data = br.readLine();
281 }
282 }
283
284 ++nSnaps;
285 line = br.readLine();
286 }
287 return nSnaps;
288 } catch (Exception ex) {
289 logger.log(Level.WARNING,
290 String.format(" Exception reading trajectory file %s: %s", xphFile, ex));
291 return -1;
292 }
293 }
294
295
296 @Override
297 public OptionalDouble getLastReadLambda() {
298 String[] toks = remarkLine.split("\\s+");
299 int nToks = toks.length;
300 for (int i = 0; i < (nToks - 1); i++) {
301 if (toks[i].equals("Lambda:")) {
302 return OptionalDouble.of(Double.parseDouble(toks[i + 1]));
303 }
304 }
305 return OptionalDouble.empty();
306 }
307
308 @Override
309 public String[] getRemarkLines() {
310 return new String[] {remarkLine};
311 }
312
313 @Override
314 public int getSnapshot() {
315 return snapShot;
316 }
317
318
319
320
321
322
323 @Override
324 public boolean readFile() {
325 File xphFile = activeMolecularAssembly.getFile();
326
327 if (forceField == null) {
328 logger.warning(format(" No force field is associated with %s.", xphFile.toString()));
329 return false;
330 }
331 try (BufferedReader br = new BufferedReader(new FileReader(xphFile))) {
332 String data = br.readLine();
333
334 while (data != null && data.trim().equals("")) {
335 data = br.readLine();
336 }
337 if (data == null) {
338 return false;
339 }
340 String[] tokens = data.trim().split(" +", 2);
341 int numberOfAtoms = parseInt(tokens[0]);
342 if (numberOfAtoms < 1) {
343 return false;
344 }
345 if (tokens.length == 2) {
346 getActiveMolecularSystem().setName(tokens[1]);
347 }
348 logger.info(format(" Opening %s with %d atoms\n", xphFile.getName(), numberOfAtoms));
349 remarkLine = data.trim();
350
351
352 br.mark(10000);
353 data = br.readLine();
354 if (!readPBC(data, activeMolecularAssembly)) {
355 br.reset();
356 }
357
358
359 HashMap<Integer, Integer> labelHash = new HashMap<>();
360 int[] label = new int[numberOfAtoms];
361 int[][] bonds = new int[numberOfAtoms][8];
362 double[][] d = new double[numberOfAtoms][3];
363 boolean renumber = false;
364 atomList = new ArrayList<>();
365
366 for (int i = 0; i < numberOfAtoms; i++) {
367 if (!br.ready()) {
368 return false;
369 }
370 data = br.readLine();
371 if (data == null) {
372 logger.warning(
373 format(" Check atom %d in %s.", (i + 1), activeMolecularAssembly.getFile().getName()));
374 return false;
375 }
376 tokens = data.trim().split(" +");
377 if (tokens.length < 6) {
378 logger.warning(
379 format(" Check atom %d in %s.", (i + 1), activeMolecularAssembly.getFile().getName()));
380 return false;
381 }
382
383 label[i] = parseInt(tokens[0]);
384
385 if (label[i] != i + 1) {
386 renumber = true;
387 }
388 String atomName = tokens[1];
389 d[i][0] = parseDouble(tokens[2]);
390 d[i][1] = parseDouble(tokens[3]);
391 d[i][2] = parseDouble(tokens[4]);
392 int type = parseInt(tokens[5]);
393 AtomType atomType = forceField.getAtomType(Integer.toString(type));
394 if (atomType == null) {
395 StringBuilder message = new StringBuilder("Check atom type ");
396 message.append(type).append(" for Atom ").append(i + 1);
397 message.append(" in ").append(activeMolecularAssembly.getFile().getName());
398 logger.warning(message.toString());
399 return false;
400 }
401 Atom a = new Atom(i + 1, atomName, atomType, d[i]);
402 atomList.add(a);
403
404 int numberOfBonds = tokens.length - 6;
405 for (int b = 0; b < 8; b++) {
406 if (b < numberOfBonds) {
407 int bond = parseInt(tokens[6 + b]);
408 bonds[i][b] = bond;
409 } else {
410 bonds[i][b] = 0;
411 }
412 }
413 }
414
415
416 if (br.ready()) {
417
418 data = br.readLine().trim();
419 while (data.equals("") && br.ready()) {
420 data = br.readLine().trim();
421 }
422 tokens = data.split(" +", 2);
423 if (tokens.length > 0) {
424 try {
425 int archiveNumberOfAtoms = parseInt(tokens[0]);
426 if (archiveNumberOfAtoms == numberOfAtoms) {
427 setType(FileType.ARC);
428 }
429 } catch (NumberFormatException e) {
430
431 }
432 }
433 }
434
435 if (renumber) {
436 for (int i = 0; i < numberOfAtoms; i++) {
437 if (labelHash.containsKey(label[i])) {
438 logger.warning(format(" Two atoms have the same index: %d.", label[i]));
439 return false;
440 }
441 labelHash.put(label[i], i + 1);
442 }
443 for (int i = 0; i < numberOfAtoms; i++) {
444 int j = -1;
445 while (j < 3 && bonds[i][++j] > 0) {
446 bonds[i][j] = labelHash.get(bonds[i][j]);
447 }
448 }
449 }
450 bondList = new ArrayList<>();
451 int[] c = new int[2];
452 for (int a1 = 1; a1 <= numberOfAtoms; a1++) {
453 int j = -1;
454 while (j < 7 && bonds[a1 - 1][++j] > 0) {
455 int a2 = bonds[a1 - 1][j];
456 if (a1 < a2) {
457 if (a2 > numberOfAtoms) {
458 logger.warning(format(" Check the bond between %d and %d in %s.", a1, a2,
459 activeMolecularAssembly.getFile().getName()));
460 return false;
461 }
462
463 boolean bidirectional = false;
464 int k = -1;
465 while (k < 7 && bonds[a2 - 1][++k] > 0) {
466 int a3 = bonds[a2 - 1][k];
467 if (a3 == a1) {
468 bidirectional = true;
469 break;
470 }
471 }
472 if (!bidirectional) {
473 logger.warning(format(" Check the bond between %d and %d in %s.", a1, a2,
474 activeMolecularAssembly.getFile().getName()));
475 return false;
476 }
477 Atom atom1 = atomList.get(a1 - 1);
478 Atom atom2 = atomList.get(a2 - 1);
479 if (atom1 == null || atom2 == null) {
480 logger.warning(format(" Check the bond between %d and %d in %s.", a1, a2,
481 activeMolecularAssembly.getFile().getName()));
482 return false;
483 }
484 Bond bond = new Bond(atom1, atom2);
485 BondType bondType = forceField.getBondType(atom1.getAtomType(), atom2.getAtomType());
486 if (bondType == null) {
487 logNoBondType(atom1, atom2, forceField);
488 } else {
489 bond.setBondType(bondType);
490 }
491 bondList.add(bond);
492 }
493 }
494 }
495
496 while (data != null && data.equals("") && br.ready()) {
497 data = br.readLine().trim();
498 }
499
500 if (data != null) {
501 tokens = data.split(" +", 2);
502
503 if (tokens[0].equalsIgnoreCase("ESV")) {
504 int numOfESVs = parseInt(tokens[1]);
505 data = br.readLine().trim();
506
507 List<Residue> residueList = extendedSystem.getExtendedResidueList();
508
509 if (numOfESVs == residueList.size()) {
510 int switchIndex = extendedSystem.getTitratingResidueList().size();
511 for (int i = 0; i < residueList.size(); i++) {
512 tokens = data.split(" +");
513
514 if (i < switchIndex) {
515 extendedSystem.setTitrationLambda(residueList.get(i), parseDouble(tokens[2]));
516 } else {
517 extendedSystem.setTautomerLambda(residueList.get(i), parseDouble(tokens[2]));
518 }
519
520 data = br.readLine().trim();
521 }
522
523 for (Atom atom : system.getAtomList()) {
524 int atomIndex = atom.getIndex() - 1;
525 atom.setOccupancy(extendedSystem.getTitrationLambda(atomIndex));
526 atom.setTempFactor(extendedSystem.getTautomerLambda(atomIndex));
527 }
528
529 } else {
530 logger.severe(
531 " Number of ESVs in archive doesn't match extended system residue list size.");
532 return false;
533 }
534 }
535 }
536 return true;
537 } catch (IOException e) {
538 logger.severe(e.toString());
539 }
540 return false;
541 }
542
543
544 @Override
545 public boolean readNext() {
546 return readNext(false);
547 }
548
549
550
551
552
553
554
555 @Override
556 public boolean readNext(boolean resetPosition) {
557 return readNext(resetPosition, true);
558 }
559
560
561
562
563
564
565
566 @Override
567 public boolean readNext(boolean resetPosition, boolean print) {
568 return readNext(resetPosition, print, true);
569 }
570
571
572
573
574
575 public boolean readNext(boolean resetPosition, boolean print, boolean parse) {
576 try {
577 String data;
578 Atom[] atoms = activeMolecularAssembly.getAtomArray();
579 int nSystem = atoms.length;
580
581 if (bufferedReader == null && !resetPosition) {
582 bufferedReader = new BufferedReader(new FileReader(currentFile));
583
584 for (int i = 0; i < nSystem + 1; i++) {
585 data = bufferedReader.readLine();
586 while (!firstTokenIsInteger(data)) {
587 data = bufferedReader.readLine();
588 }
589 }
590 snapShot = 1;
591 } else if (resetPosition) {
592
593 bufferedReader = new BufferedReader(new FileReader(currentFile));
594 snapShot = 0;
595 }
596
597 snapShot++;
598
599 data = bufferedReader.readLine();
600
601
602 while (data != null && data.trim().equals("")) {
603 data = bufferedReader.readLine();
604 }
605 if (data == null) {
606 return false;
607 }
608
609
610 if (data.contains("ESV")) {
611 while (data != null && !data.trim().equals("")) {
612 data = bufferedReader.readLine();
613 }
614
615 data = bufferedReader.readLine();
616
617 if (data == null) {
618 return false;
619 }
620 }
621
622 if (print) {
623 logger.info(format("\n Attempting to read snapshot %d.", snapShot));
624 }
625 try {
626 int nArchive = parseInt(data.trim().split(" +")[0]);
627 if (nArchive != nSystem) {
628 String message = format("Number of atoms mismatch (Archive: %d, System: %d).", nArchive,
629 nSystem);
630 if (dieOnMissingAtom) {
631 logger.severe(message);
632 }
633 logger.warning(message);
634 return false;
635 }
636 } catch (NumberFormatException e) {
637 logger.warning(e.toString());
638 return false;
639 }
640
641 remarkLine = data;
642
643
644 bufferedReader.mark(10000);
645 data = bufferedReader.readLine();
646 if (!readPBC(data, activeMolecularAssembly)) {
647 bufferedReader.reset();
648 }
649
650 String[] tokens;
651 for (int i = 0; i < nSystem; i++) {
652 data = bufferedReader.readLine();
653
654 while (data != null && data.trim().equals("")) {
655 data = bufferedReader.readLine();
656 }
657 tokens = data.trim().split(" +");
658 if (tokens.length < 6) {
659 String message = format("Check atom %d in %s.", (i + 1), currentFile.getName());
660 logger.warning(message);
661 return false;
662 }
663 double x = parseDouble(tokens[2]);
664 double y = parseDouble(tokens[3]);
665 double z = parseDouble(tokens[4]);
666 int xyzIndex = atoms[i].getIndex();
667 if (xyzIndex != i + 1) {
668 String message = format("Archive atom index %d being read onto system atom index %d.",
669 i + 1, xyzIndex);
670 logger.warning(message);
671 }
672 atoms[i].moveTo(x, y, z);
673 }
674
675
676 int counter = 0;
677 while (data != null && !data.contains("ESV") && bufferedReader.ready()) {
678 data = bufferedReader.readLine().trim();
679 counter++;
680 if (counter > 5) {
681 logger.severe(" Read through too many lines");
682 }
683 }
684
685 if (data != null) {
686 tokens = data.split(" +", 2);
687 if (tokens[0].equalsIgnoreCase("ESV")) {
688 int numOfESVs = parseInt(tokens[1]);
689 data = bufferedReader.readLine().trim();
690
691 List<Residue> residueList = extendedSystem.getExtendedResidueList();
692
693 if (numOfESVs == residueList.size()) {
694 int switchIndex = extendedSystem.getTitratingResidueList().size();
695 for (int i = 0; i < residueList.size(); i++) {
696 tokens = data.split(" +");
697
698 if (i < switchIndex) {
699 extendedSystem.setTitrationLambda(residueList.get(i), parseDouble(tokens[2]));
700 } else {
701 extendedSystem.setTautomerLambda(residueList.get(i), parseDouble(tokens[2]));
702 }
703
704 data = bufferedReader.readLine().trim();
705 }
706 } else {
707 logger.severe(
708 " Number of ESVs in archive doesn't match extended system residue list size.");
709 return false;
710 }
711 }
712 }
713 return true;
714
715 } catch (FileNotFoundException e) {
716 String message = format("Exception opening file %s.", currentFile);
717 logger.log(Level.WARNING, message, e);
718 } catch (IOException e) {
719 String message = format("Exception reading from file %s.", currentFile);
720 logger.log(Level.WARNING, message, e);
721 }
722 return false;
723 }
724
725 public ExtendedSystem getExtendedSystem() {
726 return extendedSystem;
727 }
728
729 public void setExtendedSystem(ExtendedSystem esvSystem) {
730 this.extendedSystem = esvSystem;
731 }
732
733
734 @Override
735 public boolean writeFile(File saveFile, boolean append, String[] extraLines) {
736 if (saveFile == null) {
737 return false;
738 }
739
740 File newFile = saveFile;
741 if (!append) {
742 newFile = version(saveFile);
743 }
744 activeMolecularAssembly.setFile(newFile);
745 if (activeMolecularAssembly.getName() == null) {
746 activeMolecularAssembly.setName(newFile.getName());
747 }
748
749 try (FileWriter fw = new FileWriter(newFile,
750 append && newFile.exists()); BufferedWriter bw = new BufferedWriter(fw)) {
751
752 int numberOfAtoms = activeMolecularAssembly.getAtomList().size();
753 StringBuilder sb = new StringBuilder(
754 format("%7d %s", numberOfAtoms, activeMolecularAssembly.getName()));
755 if (extraLines != null) {
756 for (String line : extraLines) {
757 line = line.replaceAll("\n", " ");
758 sb.append(" ").append(line);
759 }
760 }
761 String output = sb.append("\n").toString();
762 bw.write(output);
763
764 Crystal crystal = activeMolecularAssembly.getCrystal();
765 if (crystal != null && !crystal.aperiodic()) {
766 Crystal uc = crystal.getUnitCell();
767 String params = format("%14.8f%14.8f%14.8f%14.8f%14.8f%14.8f\n", uc.a, uc.b, uc.c, uc.alpha,
768 uc.beta, uc.gamma);
769 bw.write(params);
770 }
771
772 Atom a2;
773 StringBuilder line;
774 StringBuilder[] lines = new StringBuilder[numberOfAtoms];
775
776 List<Atom> atoms = activeMolecularAssembly.getAtomList();
777 Vector3d offset = activeMolecularAssembly.getOffset();
778 for (Atom a : atoms) {
779 if (vdwH) {
780 line = new StringBuilder(
781 format("%7d %3s%14.8f%14.8f%14.8f%6d", a.getIndex(), a.getAtomType().name,
782 a.getRedX() - offset.x, a.getRedY() - offset.y, a.getRedZ() - offset.z,
783 a.getType()));
784 } else {
785 line = new StringBuilder(
786 format("%7d %3s%14.8f%14.8f%14.8f%6d", a.getIndex(), a.getAtomType().name,
787 a.getX() - offset.x, a.getY() - offset.y, a.getZ() - offset.z, a.getType()));
788 }
789 for (Bond b : a.getBonds()) {
790 a2 = b.get1_2(a);
791 line.append(format("%8d", a2.getIndex()));
792 }
793 lines[a.getIndex() - 1] = line.append("\n");
794 }
795
796 StringBuilder[] esvLines = null;
797 if (extendedSystem != null) {
798 List<Residue> residueList = extendedSystem.getTitratingResidueList();
799 esvLines = new StringBuilder[extendedSystem.getExtendedResidueList().size()];
800 double ESV;
801
802 List<Atom> residueAtoms;
803 int CAIndex = -1;
804
805
806 for (int i = 0; i < residueList.size(); i++) {
807 ESV = extendedSystem.getTitrationLambda(residueList.get(i));
808
809 residueAtoms = residueList.get(i).getAtomList(true);
810 for (Atom atom : residueAtoms) {
811 if (atom.getAtomType().name.equalsIgnoreCase("CA")) {
812 CAIndex = atom.getIndex();
813 }
814 }
815
816 line = new StringBuilder(
817 format("%7d%7d%14.8f%7s\n", i, CAIndex, ESV, residueList.get(i).getAminoAcid3()));
818
819 esvLines[i] = line;
820
821 CAIndex = -1;
822 }
823
824 int offsetIndex = residueList.size();
825 residueList = extendedSystem.getTautomerizingResidueList();
826
827 for (int i = 0; i < residueList.size(); i++) {
828 ESV = extendedSystem.getTautomerLambda(residueList.get(i));
829
830 residueAtoms = residueList.get(i).getAtomList(true);
831 for (Atom atom : residueAtoms) {
832 if (atom.getAtomType().name.equalsIgnoreCase("CA")) {
833 CAIndex = atom.getIndex();
834 }
835 }
836
837 line = new StringBuilder(format("%7d%7d%14.8f%7s\n", offsetIndex + i, CAIndex, ESV,
838 residueList.get(i).getAminoAcid3()));
839
840 esvLines[offsetIndex + i] = line;
841
842 CAIndex = -1;
843 }
844
845 }
846 try {
847 for (int i = 0; i < numberOfAtoms; i++) {
848 bw.write(lines[i].toString());
849 }
850
851 if (esvLines != null) {
852 String esvHead = format("\n%7s%7d\n", "ESV", esvLines.length);
853 bw.write(esvHead);
854
855 for (int i = 0; i < esvLines.length; i++) {
856 bw.write(esvLines[i].toString());
857 }
858 bw.write("\n");
859 }
860 } catch (IOException e) {
861 String message = format(" There was an unexpected error writing to %s.",
862 getActiveMolecularSystem().toString());
863 logger.log(Level.WARNING, message, e);
864 return false;
865 }
866 } catch (IOException e) {
867 String message = format(" There was an unexpected error writing to %s.",
868 getActiveMolecularSystem().toString());
869 logger.log(Level.WARNING, message, e);
870 return false;
871 }
872 return true;
873 }
874
875
876
877
878
879
880
881
882
883 public boolean writeFileAsP1(File saveFile, boolean append, Crystal crystal) {
884 return writeFileAsP1(saveFile, append, crystal, null);
885 }
886
887
888
889
890
891
892
893
894
895
896 public boolean writeFileAsP1(File saveFile, boolean append, Crystal crystal, String[] extraLines) {
897 if (saveFile == null) {
898 return false;
899 }
900
901 File newFile = saveFile;
902 if (!append) {
903 newFile = version(saveFile);
904 }
905 activeMolecularAssembly.setFile(newFile);
906 activeMolecularAssembly.setName(newFile.getName());
907
908 try (FileWriter fw = new FileWriter(newFile,
909 append && newFile.exists()); BufferedWriter bw = new BufferedWriter(fw)) {
910 int nSymm = crystal.spaceGroup.symOps.size();
911
912 int numberOfAtoms = activeMolecularAssembly.getAtomList().size() * nSymm;
913 StringBuilder sb = new StringBuilder(
914 format("%7d %s", numberOfAtoms, activeMolecularAssembly.toString()));
915 if (extraLines != null) {
916 for (String line : extraLines) {
917 line = line.replaceAll("\n", " ");
918 sb.append(" ").append(line);
919 }
920 }
921 String output = sb.append("\n").toString();
922 bw.write(output);
923
924 if (!crystal.aperiodic()) {
925 Crystal uc = crystal.getUnitCell();
926 String params = format("%14.8f%14.8f%14.8f%14.8f%14.8f%14.8f\n", uc.a, uc.b, uc.c, uc.alpha,
927 uc.beta, uc.gamma);
928 bw.write(params);
929 }
930
931 Atom a2;
932 StringBuilder line;
933 StringBuilder[] lines = new StringBuilder[numberOfAtoms];
934
935 Atom[] atoms = activeMolecularAssembly.getAtomArray();
936 double[] xyz = new double[3];
937 for (int iSym = 0; iSym < nSymm; iSym++) {
938 SymOp symOp = crystal.spaceGroup.getSymOp(iSym);
939 int indexOffset = iSym * atoms.length;
940 for (Atom a : atoms) {
941 int index = a.getIndex() + indexOffset;
942 String id = a.getAtomType().name;
943 if (vdwH) {
944 a.getRedXYZ(xyz);
945 } else {
946 xyz[0] = a.getX();
947 xyz[1] = a.getY();
948 xyz[2] = a.getZ();
949 }
950 crystal.applySymOp(xyz, xyz, symOp);
951 int type = a.getType();
952 line = new StringBuilder(
953 format("%7d %3s%14.8f%14.8f%14.8f%6d", index, id, xyz[0], xyz[1], xyz[2], type));
954 for (Bond b : a.getBonds()) {
955 a2 = b.get1_2(a);
956 line.append(format("%8d", a2.getIndex() + indexOffset));
957 }
958 lines[index - 1] = line.append("\n");
959 }
960 }
961 try {
962 for (int i = 0; i < numberOfAtoms; i++) {
963 bw.write(lines[i].toString());
964 }
965 } catch (IOException e) {
966 String message = format(" There was an unexpected error writing to %s.",
967 getActiveMolecularSystem().toString());
968 logger.log(Level.WARNING, message, e);
969 return false;
970 }
971 } catch (IOException e) {
972 String message = format(" There was an unexpected error writing to %s.",
973 getActiveMolecularSystem().toString());
974 logger.log(Level.WARNING, message, e);
975 return false;
976 }
977 return true;
978 }
979 }