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.xray.refine;
39
40 import ffx.potential.MolecularAssembly;
41 import ffx.potential.bonded.Atom;
42 import ffx.potential.bonded.Bond;
43 import ffx.potential.bonded.MSNode;
44 import ffx.potential.bonded.Molecule;
45 import ffx.potential.bonded.Polymer;
46 import ffx.potential.bonded.Residue;
47 import org.apache.commons.configuration2.CompositeConfiguration;
48
49 import java.util.ArrayList;
50 import java.util.IdentityHashMap;
51 import java.util.List;
52 import java.util.Map;
53 import java.util.logging.Level;
54 import java.util.logging.Logger;
55
56 import static ffx.numerics.math.ScalarMath.b2u;
57 import static java.lang.String.format;
58
59
60
61
62
63
64
65 public class RefinementModel {
66
67 private static final Logger logger = Logger.getLogger(RefinementModel.class.getName());
68
69
70
71
72
73 private final MolecularAssembly[] molecularAssemblies;
74
75
76
77
78 private RefinementMode refinementMode;
79
80
81
82
83 private final boolean addAnisou;
84
85
86
87
88
89 private final boolean byResidue;
90
91
92
93
94
95 private final int nResiduePerBFactor;
96
97
98
99
100
101 private final boolean ridingHydrogen;
102
103
104
105
106 private final double bMass;
107
108
109
110
111
112 private final boolean refineMolOcc;
113
114
115
116
117 private final boolean resetHDOccupancy;
118
119
120
121
122 private final double occMass;
123
124
125
126
127
128 private final Atom[] scatteringAtoms;
129
130
131
132
133 private final List<Atom> coordinateAtomList = new ArrayList<>();
134
135
136
137
138 private final Map<Atom, RefinedCoordinates> refinedCoordinates;
139
140
141
142
143 private final List<Atom> bFactorAtomList = new ArrayList<>();
144
145
146
147
148 private final Map<Atom, RefinedBFactor> refinedBFactors;
149
150
151
152
153 private final List<Atom[]> bFactorRestraints = new ArrayList<>();
154
155
156
157
158 private final List<Atom> occupancyAtomList = new ArrayList<>();
159
160
161
162
163 private final Map<Atom, RefinedOccupancy> refinedOccupancies;
164
165
166
167
168 private final List<RefinedParameter> allParametersList;
169
170
171
172
173 private final List<List<Residue>> altResidues;
174
175
176
177
178 private final List<List<Molecule>> altMolecules;
179
180
181
182
183
184
185 public RefinementModel(MolecularAssembly[] molecularAssemblies) {
186 this(RefinementMode.COORDINATES_AND_BFACTORS_AND_OCCUPANCIES, molecularAssemblies);
187 }
188
189
190
191
192
193
194
195 public RefinementModel(RefinementMode refinementMode, MolecularAssembly[] molecularAssemblies) {
196
197 this.refinementMode = refinementMode;
198 this.molecularAssemblies = molecularAssemblies;
199 MolecularAssembly rootAssembly = molecularAssemblies[0];
200
201
202 CompositeConfiguration properties = rootAssembly.getProperties();
203 addAnisou = properties.getBoolean("add-anisou", false);
204 byResidue = properties.getBoolean("residue-bfactor", false);
205 nResiduePerBFactor = properties.getInt("n-residue-bfactor", 1);
206 ridingHydrogen = properties.getBoolean("riding-hydrogen-bfactor", true);
207 bMass = properties.getDouble("bfactor-mass", 5.0);
208 occMass = properties.getDouble("occupancy-mass", 10.0);
209 resetHDOccupancy = properties.getBoolean("reset-hd-occupancy", false);
210
211
212 refineMolOcc = properties.getBoolean("refine-mol-occ", false);
213
214
215 if (addAnisou) {
216 addAnisotropicBFactors();
217 }
218
219
220 if (refinementMode.includesBFactors()) {
221 regularizeActiveAtoms();
222 }
223
224
225 List<Atom> scatteringList = new ArrayList<>();
226 refinedCoordinates = createCoordinateModel(scatteringList);
227 scatteringAtoms = scatteringList.toArray(new Atom[0]);
228
229
230 refinedBFactors = createBFactorModel();
231
232
233 altResidues = new ArrayList<>();
234 altMolecules = new ArrayList<>();
235 refinedOccupancies = createOccupancyModel();
236
237
238 allParametersList = new ArrayList<>();
239 setRefinementMode(refinementMode);
240 }
241
242
243
244
245
246
247
248
249
250
251 public void setRefinementMode(RefinementMode mode) {
252 this.refinementMode = mode;
253 allParametersList.clear();
254
255
256
257
258 if (refinementMode.includesCoordinates()) {
259 for (Atom atom : coordinateAtomList) {
260 allParametersList.add(refinedCoordinates.get(atom));
261 }
262 }
263 if (refinementMode.includesBFactors()) {
264 for (Atom atom : bFactorAtomList) {
265 allParametersList.add(refinedBFactors.get(atom));
266 }
267 collectBFactorRestraints();
268 } else {
269 bFactorRestraints.clear();
270 }
271 if (refinementMode.includesOccupancies()) {
272 for (Atom atom : occupancyAtomList) {
273 allParametersList.add(refinedOccupancies.get(atom));
274 }
275 }
276 setParameterIndices();
277 }
278
279
280
281
282
283
284 public Atom[] getScatteringAtoms() {
285 return scatteringAtoms;
286 }
287
288
289
290
291
292
293 public Atom[] getActiveAtoms() {
294 return coordinateAtomList.toArray(new Atom[0]);
295 }
296
297
298
299
300
301
302 public List<List<Molecule>> getAltMolecules() {
303 return altMolecules;
304 }
305
306
307
308
309
310
311 public List<List<Residue>> getAltResidues() {
312 return altResidues;
313 }
314
315
316
317
318
319
320 public MolecularAssembly[] getMolecularAssemblies() {
321 return molecularAssemblies;
322 }
323
324
325
326
327
328
329 public List<Atom[]> getBFactorRestraints() {
330 return bFactorRestraints;
331 }
332
333
334
335
336
337
338
339
340
341 public void addAssemblyGradient(int assembly, double[] gradient) {
342 MolecularAssembly molecularAssembly = molecularAssemblies[assembly];
343 Atom[] activeAtoms = molecularAssembly.getActiveAtomArray();
344 double[] xyz = new double[3];
345 for (Atom a : activeAtoms) {
346 int index = a.getXrayCoordIndex() * 3;
347 a.getXYZGradient(xyz);
348 gradient[index] += xyz[0];
349 gradient[index + 1] += xyz[1];
350 gradient[index + 2] += xyz[2];
351 }
352 }
353
354
355
356
357
358
359
360
361
362
363 public String toString() {
364 int nAtoms = scatteringAtoms.length;
365 int nActive = coordinateAtomList.size();
366
367 int nUse = 0;
368 for (Atom a : scatteringAtoms) {
369 if (a.getUse()) {
370 nUse++;
371 }
372 }
373 int nXYZ = getNumCoordParameters();
374 int nBFactors = getNumBFactorParameters();
375 int nOccupancies = getNumOccupancyParameters();
376 int n = nXYZ + nBFactors + nOccupancies;
377
378 StringBuilder sb = new StringBuilder("\n Refinement Model\n");
379 sb.append(format(" Number of atoms: %d\n", nAtoms));
380 sb.append(format(" Atoms being used: %d\n", nUse));
381 sb.append(format(" Number of active atoms: %d\n", nActive));
382 sb.append(format(" Number of variables: %d (nXYZ %d, nB %d, nOcc %d)\n",
383 n, nXYZ, nBFactors, nOccupancies));
384
385 return sb.toString();
386 }
387
388
389
390
391
392
393 public RefinementMode getRefinementMode() {
394 return refinementMode;
395 }
396
397
398
399
400
401
402 public List<RefinedParameter> getRefinedParameters() {
403 return allParametersList;
404 }
405
406
407
408
409
410
411
412 public int getNumParameters() {
413 return getNumCoordParameters()
414 + getNumBFactorParameters()
415 + getNumOccupancyParameters();
416 }
417
418
419
420
421
422
423
424 public int getNumCoordParameters() {
425
426 if (refinementMode.includesCoordinates()) {
427 return coordinateAtomList.size() * 3;
428 }
429 return 0;
430 }
431
432
433
434
435
436
437 public int getNumBFactorParameters() {
438 int num = 0;
439 if (refinementMode.includesBFactors()) {
440 for (RefinedBFactor bFactor : refinedBFactors.values()) {
441 num += bFactor.getNumberOfParameters();
442 }
443 }
444 return num;
445 }
446
447
448
449
450
451
452 public int getNumOccupancyParameters() {
453 if (refinementMode.includesOccupancies()) {
454 return occupancyAtomList.size();
455 }
456 return 0;
457 }
458
459
460
461
462
463
464 public int getNumANISOU() {
465 int numANISOU = 0;
466 for (RefinedBFactor bFactor : refinedBFactors.values()) {
467 if (bFactor.isAnisou()) {
468 numANISOU++;
469 }
470 }
471 return numANISOU;
472 }
473
474
475
476
477
478
479
480
481
482 public void getParameters(double[] x) {
483 for (RefinedParameter parameter : allParametersList) {
484 parameter.getParameters(x);
485 }
486 }
487
488
489
490
491
492
493
494
495
496
497 public void setParameters(double[] x) {
498 for (RefinedParameter parameter : allParametersList) {
499 parameter.setParameters(x);
500 }
501 }
502
503
504
505
506
507
508
509
510
511 public void getVelocity(double[] x) {
512 for (RefinedParameter parameter : allParametersList) {
513 parameter.getVelocity(x);
514 }
515 }
516
517
518
519
520
521
522
523
524
525
526 public void setVelocity(double[] x) {
527 for (RefinedParameter parameter : allParametersList) {
528 parameter.setVelocity(x);
529 }
530 }
531
532
533
534
535
536
537
538 public void getAcceleration(double[] x) {
539 for (RefinedParameter parameter : allParametersList) {
540 parameter.getAcceleration(x);
541 }
542 }
543
544
545
546
547
548
549 public void setAcceleration(double[] x) {
550 for (RefinedParameter parameter : allParametersList) {
551 parameter.setAcceleration(x);
552 }
553 }
554
555
556
557
558
559
560
561 public void getPreviousAcceleration(double[] x) {
562 for (RefinedParameter parameter : allParametersList) {
563 parameter.getPreviousAcceleration(x);
564 }
565 }
566
567
568
569
570
571
572 public void setPreviousAcceleration(double[] x) {
573 for (RefinedParameter parameter : allParametersList) {
574 parameter.setPreviousAcceleration(x);
575 }
576 }
577
578
579
580
581
582
583
584 public void getMass(double[] mass) {
585 for (RefinedParameter parameter : allParametersList) {
586 if (parameter instanceof RefinedCoordinates) {
587 parameter.getMass(mass, 5.0);
588 } else if (parameter instanceof RefinedBFactor) {
589 parameter.getMass(mass, bMass);
590 } else if (parameter instanceof RefinedOccupancy) {
591 parameter.getMass(mass, occMass);
592 }
593 }
594 }
595
596
597
598
599
600
601 public void loadOptimizationScaling(double[] optimizationScaling) {
602 for (RefinedParameter parameter : allParametersList) {
603 parameter.setOptimizationScaling(optimizationScaling);
604 }
605 }
606
607
608
609
610 public void zeroGradient() {
611 for (RefinedParameter parameter : allParametersList) {
612 parameter.zeroGradient();
613 }
614 }
615
616
617
618
619
620
621 public void getGradient(double[] gradient) {
622 for (RefinedParameter parameter : allParametersList) {
623 parameter.getGradient(gradient);
624 }
625 }
626
627
628
629
630
631
632
633
634
635
636 private Map<Atom, RefinedCoordinates> createCoordinateModel(List<Atom> scatteringList) {
637 logger.fine("\n Creating Coordinate Refinement Model\n");
638
639 MolecularAssembly rootAssembly = molecularAssemblies[0];
640
641 Map<Atom, RefinedCoordinates> coordinateMap = new IdentityHashMap<>();
642
643
644 Atom[] atomList = rootAssembly.getAtomArray();
645 for (Atom a : atomList) {
646
647 scatteringList.add(a);
648 if (a.isActive()) {
649
650 a.setXrayCoordIndex(coordinateAtomList.size());
651 coordinateAtomList.add(a);
652 coordinateMap.put(a, new RefinedCoordinates(a));
653 logger.fine(" Active: " + a);
654 }
655 }
656
657
658 for (int i = 1; i < molecularAssemblies.length; i++) {
659 MolecularAssembly molecularAssembly = molecularAssemblies[i];
660 atomList = molecularAssembly.getAtomArray();
661 for (Atom a : atomList) {
662 Character altLoc = a.getAltLoc();
663 Atom rootAtom = rootAssembly.findAtom(a, false);
664 Atom deuteriumMatch = rootAssembly.findAtom(a, true);
665 if (rootAtom != null && rootAtom.getAltLoc().equals(altLoc)) {
666
667 if (rootAtom.isActive()) {
668
669 RefinedCoordinates refinedCoordinates = coordinateMap.get(rootAtom);
670 refinedCoordinates.addConstrainedAtom(a);
671 a.setXrayCoordIndex(rootAtom.getXrayCoordIndex());
672 } else {
673
674 a.setActive(false);
675 }
676 } else if (deuteriumMatch != null) {
677
678 scatteringList.add(a);
679 if (deuteriumMatch.isActive()) {
680 RefinedCoordinates refinedCoordinates = coordinateMap.get(deuteriumMatch);
681 refinedCoordinates.addConstrainedAtomThatScatters(a);
682 a.setXrayCoordIndex(deuteriumMatch.getXrayCoordIndex());
683 } else {
684
685 a.setActive(false);
686 }
687 } else {
688
689 scatteringList.add(a);
690 if (a.isActive()) {
691 a.setXrayCoordIndex(coordinateAtomList.size());
692 coordinateAtomList.add(a);
693 coordinateMap.put(a, new RefinedCoordinates(a));
694 }
695 }
696 }
697 }
698
699 return coordinateMap;
700 }
701
702
703
704
705
706
707
708
709
710 private Map<Atom, RefinedBFactor> createBFactorModel() {
711 logger.fine("\n Creating B-Factor Refinement Model\n");
712 MolecularAssembly rootAssembly = molecularAssemblies[0];
713 Map<Atom, RefinedBFactor> bFactorMap = new IdentityHashMap<>();
714
715 if (byResidue) {
716
717 Polymer[] polymers = rootAssembly.getChains();
718 for (Polymer polymer : polymers) {
719 List<Residue> residues = polymer.getResidues();
720 Atom heavyAtom = null;
721 RefinedBFactor currentRefinedBFactor = null;
722 for (int j = 0; j < residues.size(); j++) {
723 Residue residue = residues.get(j);
724 if (j % nResiduePerBFactor == 0 || heavyAtom == null) {
725 heavyAtom = residue.getFirstActiveHeavyAtom();
726 if (heavyAtom == null) {
727
728 continue;
729 }
730 bFactorAtomList.add(heavyAtom);
731 currentRefinedBFactor = new RefinedBFactor(heavyAtom);
732 bFactorMap.put(heavyAtom, currentRefinedBFactor);
733 }
734
735 for (Atom a : residue.getAtomList()) {
736 if (a != heavyAtom) {
737 currentRefinedBFactor.addConstrainedAtomThatScatters(a);
738 }
739 }
740 }
741 }
742 List<MSNode> molecules = rootAssembly.getNodeList(true);
743 for (MSNode m : molecules) {
744 Atom heavyAtom = m.getFirstActiveHeavyAtom();
745 if (heavyAtom == null) {
746
747 continue;
748 }
749 bFactorAtomList.add(heavyAtom);
750 RefinedBFactor currentRefinedBFactor = new RefinedBFactor(heavyAtom);
751 bFactorMap.put(heavyAtom, currentRefinedBFactor);
752
753 for (Atom a : m.getAtomList()) {
754 if (a != heavyAtom) {
755 currentRefinedBFactor.addConstrainedAtomThatScatters(a);
756 }
757 }
758 }
759
760
761 for (int i = 1; i < molecularAssemblies.length; i++) {
762 MolecularAssembly molecularAssembly = molecularAssemblies[i];
763 polymers = molecularAssembly.getChains();
764 for (int j = 0; j < polymers.length; j++) {
765 Polymer polymer = polymers[j];
766 List<Residue> residues = polymer.getResidues();
767 for (int k = 0; k < residues.size(); k++) {
768 Residue residue = residues.get(k);
769 Residue rootResidue = rootAssembly.getResidue(j, k);
770 if (rootResidue == null) {
771 logger.severe(format(" Residue %s not found in the root conformation.", residue));
772 return null;
773 }
774 Atom rootAtom = rootResidue.getFirstActiveHeavyAtom();
775 if (rootAtom == null) {
776
777 continue;
778 }
779 RefinedBFactor refinedBFactor = bFactorMap.get(rootAtom);
780
781 for (Atom a : residue.getAtomList()) {
782 Character altLoc = a.getAltLoc();
783 if (!altLoc.equals(rootAtom.getAltLoc())) {
784 refinedBFactor.addConstrainedAtomThatScatters(a);
785 } else {
786 refinedBFactor.addConstrainedAtom(a);
787 }
788 }
789 }
790 }
791
792 molecules = molecularAssemblies[i].getNodeList(true);
793 for (MSNode m : molecules) {
794 Atom heavyAtom = m.getFirstActiveHeavyAtom();
795 if (heavyAtom == null) {
796
797 continue;
798 }
799 Character altLoc = heavyAtom.getAltLoc();
800 if (!altLoc.equals(' ') && !altLoc.equals('A')) {
801 bFactorAtomList.add(heavyAtom);
802 RefinedBFactor refinedBFactor = new RefinedBFactor(heavyAtom);
803 bFactorMap.put(heavyAtom, refinedBFactor);
804
805 for (Atom a : m.getAtomList()) {
806 if (a != heavyAtom) {
807 refinedBFactor.addConstrainedAtomThatScatters(a);
808 }
809 }
810 }
811 }
812 }
813 } else if (ridingHydrogen) {
814
815
816 for (Atom atom : coordinateAtomList) {
817 if (atom.isHydrogen() && !atom.isDeuterium()) {
818 continue;
819 }
820 bFactorAtomList.add(atom);
821 RefinedBFactor refinedBFactor = new RefinedBFactor(atom);
822 bFactorMap.put(atom, refinedBFactor);
823
824 RefinedCoordinates refinedCoords = refinedCoordinates.get(atom);
825 for (Atom a : refinedCoords.constrainedAtoms) {
826 refinedBFactor.addConstrainedAtom(a);
827 }
828
829 for (Atom a : refinedCoords.constrainedAtomsThatScatter) {
830 refinedBFactor.addConstrainedAtomThatScatters(a);
831 }
832 }
833
834 for (Atom atom : coordinateAtomList) {
835 if (atom.isHydrogen() && !atom.isDeuterium()) {
836 Atom heavy = atom.getBonds().getFirst().get1_2(atom);
837 if (!heavy.isActive()) {
838
839 continue;
840 }
841 if (bFactorMap.containsKey(heavy)) {
842 RefinedBFactor refinedBFactor = bFactorMap.get(heavy);
843 refinedBFactor.addConstrainedAtomThatScatters(atom);
844 continue;
845 }
846 logger.info(" Could not locate a heavy atom B-factor for: " + atom);
847 }
848 }
849 } else {
850
851
852 for (Atom atom : coordinateAtomList) {
853 bFactorAtomList.add(atom);
854 RefinedBFactor refinedBFactor = new RefinedBFactor(atom);
855 bFactorMap.put(atom, refinedBFactor);
856
857 RefinedCoordinates refinedCoords = refinedCoordinates.get(atom);
858 for (Atom a : refinedCoords.constrainedAtoms) {
859 refinedBFactor.addConstrainedAtom(a);
860 }
861
862 for (Atom a : refinedCoords.constrainedAtomsThatScatter) {
863 refinedBFactor.addConstrainedAtomThatScatters(a);
864 }
865 }
866 }
867
868 return bFactorMap;
869 }
870
871
872
873
874 private void collectBFactorRestraints() {
875 bFactorRestraints.clear();
876 MolecularAssembly rootAssembly = molecularAssemblies[0];
877
878 List<Bond> rootBonds = rootAssembly.getBondList();
879 for (Bond bond : rootBonds) {
880 Atom a1 = bond.getAtom(0);
881 Atom a2 = bond.getAtom(1);
882 if (!a1.isActive() && !a2.isActive()) {
883 continue;
884 }
885 bFactorRestraints.add(new Atom[]{a1, a2});
886 }
887
888
889
890 for (int i = 1; i < molecularAssemblies.length; i++) {
891 MolecularAssembly molecularAssembly = molecularAssemblies[i];
892 Character altLoc = molecularAssembly.getAlternateLocation();
893 List<Bond> bonds = molecularAssembly.getBondList();
894 for (Bond bond : bonds) {
895 Atom a1 = bond.getAtom(0);
896 Atom a2 = bond.getAtom(1);
897
898 if (!a1.isActive() && !a2.isActive()) {
899 continue;
900 }
901
902 if (a1.getAltLoc().equals(altLoc) && a2.getAltLoc().equals(altLoc)) {
903 bFactorRestraints.add(new Atom[]{a1, a2});
904 } else if (a1.getAltLoc().equals(altLoc) && !a2.getAltLoc().equals(altLoc)) {
905
906 a2 = rootAssembly.findAtom(a2);
907 if (a2 != null) {
908 bFactorRestraints.add(new Atom[]{a1, a2});
909 }
910 } else if (!a1.getAltLoc().equals(altLoc) && a2.getAltLoc().equals(altLoc)) {
911
912 a1 = rootAssembly.findAtom(a1);
913 if (a1 != null) {
914 bFactorRestraints.add(new Atom[]{a1, a2});
915 }
916 }
917 }
918 }
919 }
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934 private Map<Atom, RefinedOccupancy> createOccupancyModel() {
935 logger.fine("\n Creating Occupancy Refinement Model\n");
936 Map<Atom, RefinedOccupancy> refinedOccupancies = new IdentityHashMap<>();
937
938 boolean refineDeuterium = false;
939 for (MolecularAssembly molecularAssembly : molecularAssemblies) {
940 if (molecularAssembly.hasDeuterium()) {
941 refineDeuterium = true;
942 break;
943 }
944 }
945
946 if (refineDeuterium) {
947
948 MolecularAssembly rootAssembly = molecularAssemblies[0];
949 Polymer[] polymers = rootAssembly.getChains();
950 if (polymers != null) {
951 for (Polymer polymer : polymers) {
952 List<Residue> residues = polymer.getResidues();
953 for (Residue residue : residues) {
954 List<Atom> atoms = residue.getAtomList();
955 for (Atom atom : atoms) {
956 if (atom.isActive() && atom.isHydrogen()) {
957 double occupancy = atom.getOccupancy();
958 if (occupancy < 1.0) {
959 Atom heavy = atom.getBonds().getFirst().get1_2(atom);
960 if (refinedOccupancies.containsKey(heavy)) {
961 RefinedOccupancy refinedOccupancy = refinedOccupancies.get(heavy);
962 refinedOccupancy.addConstrainedAtomThatScatters(atom);
963 } else {
964 RefinedOccupancy refinedOccupancy = new RefinedOccupancy(atom);
965 refinedOccupancies.put(heavy, refinedOccupancy);
966 occupancyAtomList.add(heavy);
967 }
968 }
969 }
970 }
971 }
972 }
973 }
974
975 if (molecularAssemblies.length > 1) {
976 MolecularAssembly molecularAssembly = molecularAssemblies[1];
977 for (Atom heavy : occupancyAtomList) {
978 RefinedOccupancy refinedOccupancy = refinedOccupancies.get(heavy);
979
980 List<Atom> atoms = new ArrayList<>(refinedOccupancy.constrainedAtomsThatScatter);
981 atoms.add(refinedOccupancy.atom);
982 for (Atom atom : atoms) {
983
984 Atom match = molecularAssembly.findAtom(atom, true);
985 if (match != null) {
986 double o1 = atom.getOccupancy();
987 double o2 = match.getOccupancy();
988 if (resetHDOccupancy) {
989 logger.info(" Reset Occupancy for H/D Pair to 0.5/0.5:");
990 atom.setOccupancy(0.5);
991 match.setOccupancy(0.5);
992 logger.info(format(" %s: %6.3f", atom, atom.getOccupancy()));
993 logger.info(format(" %s: %6.3f", match, match.getOccupancy()));
994 } else if (o1 + o2 != 1.0) {
995 logger.info(" Occupancy Sum for H/D Pair is not 1.0:");
996 logger.info(format(" %s: %6.3f", atom, atom.getOccupancy()));
997 logger.info(format(" %s: %6.3f", match, match.getOccupancy()));
998 double delta = (1.0 - o1 - o2) / 2.0;
999 atom.setOccupancy(o1 + delta);
1000 match.setOccupancy(o2 + delta);
1001 logger.info(" Occupancy Sum for H/D Pair adjusted to 1.0:");
1002 logger.info(format(" %s: %6.3f", atom, atom.getOccupancy()));
1003 logger.info(format(" %s: %6.3f", match, match.getOccupancy()));
1004 }
1005 refinedOccupancy.addConstrainedAtomThatScattersComplement(match);
1006 }
1007 }
1008 }
1009 }
1010 } else {
1011
1012 Polymer[] polymers = molecularAssemblies[0].getChains();
1013 if (polymers != null && polymers.length > 0) {
1014 for (int i = 0; i < polymers.length; i++) {
1015 List<Residue> residues = polymers[i].getResidues();
1016 for (int j = 0; j < residues.size(); j++) {
1017 List<Residue> list = getResidueConformers(i, j);
1018 if (list != null && !list.isEmpty()) {
1019 altResidues.add(list);
1020 for (Residue residue : list) {
1021 List<Atom> atomList = residue.getAtomList();
1022 RefinedOccupancy refinedOccupancy = null;
1023 Atom refinedAtom = null;
1024 for (Atom a : atomList) {
1025 Character altLoc = a.getAltLoc();
1026 double occupancy = a.getOccupancy();
1027 if (!altLoc.equals(' ') || occupancy < 1.0) {
1028 occupancyAtomList.add(a);
1029 refinedOccupancy = new RefinedOccupancy(a);
1030 refinedOccupancies.put(a, refinedOccupancy);
1031
1032 refinedAtom = a;
1033 break;
1034 }
1035 }
1036 if (refinedAtom != null) {
1037 for (Atom a : atomList) {
1038 if (a == refinedAtom) {
1039 continue;
1040 }
1041 Character altLoc = a.getAltLoc();
1042 double occupancy = a.getOccupancy();
1043 if (!altLoc.equals(' ') || occupancy < 1.0) {
1044 refinedOccupancy.addConstrainedAtomThatScatters(a);
1045
1046 }
1047 }
1048 }
1049 }
1050 }
1051 }
1052 }
1053 }
1054 }
1055
1056
1057 if (refineMolOcc) {
1058 List<MSNode> molecules = molecularAssemblies[0].getMolecules();
1059 if (molecules != null && !molecules.isEmpty()) {
1060 for (int i = 0; i < molecules.size(); i++) {
1061 List<Molecule> list = getMoleculeConformers(i);
1062 if (list != null && !list.isEmpty()) {
1063 altMolecules.add(list);
1064 for (Molecule molecule : list) {
1065 List<Atom> atomList = molecule.getAtomList();
1066 RefinedOccupancy refinedOccupancy = null;
1067 Atom refinedAtom = null;
1068 for (Atom a : atomList) {
1069 Character altLoc = a.getAltLoc();
1070 double occupancy = a.getOccupancy();
1071 if (!altLoc.equals(' ') || occupancy < 1.0) {
1072 occupancyAtomList.add(a);
1073 refinedOccupancy = new RefinedOccupancy(a);
1074 refinedOccupancies.put(a, refinedOccupancy);
1075 logger.info(" Refined Occupancy: " + a);
1076 refinedAtom = a;
1077 break;
1078 }
1079 }
1080 if (refinedAtom != null) {
1081 for (Atom a : atomList) {
1082 if (a == refinedAtom) {
1083 continue;
1084 }
1085 Character altLoc = a.getAltLoc();
1086 double occupancy = a.getOccupancy();
1087 if (!altLoc.equals(' ') || occupancy < 1.0) {
1088 refinedOccupancy.addConstrainedAtomThatScatters(a);
1089 logger.info(" Constrained Occupancy: " + a);
1090 }
1091 }
1092 }
1093 }
1094 }
1095 }
1096 }
1097 }
1098
1099 return refinedOccupancies;
1100 }
1101
1102
1103
1104
1105
1106
1107
1108
1109 private List<Residue> getResidueConformers(int polymerID, int resID) {
1110 if (molecularAssemblies.length < 2) {
1111 return null;
1112 }
1113
1114 double totalOccupancy = 0.0;
1115 List<Residue> residues = new ArrayList<>();
1116
1117 Residue residue = molecularAssemblies[0].getResidue(polymerID, resID);
1118 for (Atom a : residue.getAtomList()) {
1119 if (!a.getUse()) {
1120 continue;
1121 }
1122 Character altLoc = a.getAltLoc();
1123 double occupancy = a.getOccupancy();
1124 if (!altLoc.equals(' ') || occupancy < 1.0) {
1125
1126 logger.fine(format(" %s %c %5.3f", residue, altLoc, occupancy));
1127 totalOccupancy = occupancy;
1128 residues.add(residue);
1129 break;
1130 }
1131 }
1132
1133 if (residues.isEmpty()) {
1134 return null;
1135 }
1136
1137
1138 int numConformers = molecularAssemblies.length;
1139 for (int i = 1; i < numConformers; i++) {
1140 residue = molecularAssemblies[i].getResidue(polymerID, resID);
1141 for (Atom a : residue.getAtomList()) {
1142 if (!a.getUse()) {
1143 continue;
1144 }
1145 Character altLoc = a.getAltLoc();
1146 if (!altLoc.equals(' ') && !altLoc.equals('A')) {
1147 double occupancy = a.getOccupancy();
1148 totalOccupancy += occupancy;
1149
1150 residues.add(residue);
1151 logger.fine(format(" %s %c %5.3f", residue, altLoc, occupancy));
1152 break;
1153 }
1154 }
1155 }
1156
1157 logger.fine(" Total occupancy: " + totalOccupancy);
1158 return residues;
1159 }
1160
1161
1162
1163
1164
1165
1166
1167 private List<Molecule> getMoleculeConformers(int moleculeID) {
1168 List<Molecule> molecules = new ArrayList<>();
1169 double totalOccupancy = 0.0;
1170
1171 List<MSNode> molList = molecularAssemblies[0].getMolecules();
1172 if (molList != null && !molList.isEmpty()) {
1173 Molecule molecule = (Molecule) molList.get(moleculeID);
1174 for (Atom a : molecule.getAtomList()) {
1175 if (!a.getUse()) {
1176 continue;
1177 }
1178 Character altLoc = a.getAltLoc();
1179 double occupancy = a.getOccupancy();
1180 if (!altLoc.equals(' ') || occupancy < 1.0) {
1181
1182 totalOccupancy = occupancy;
1183 molecules.add(molecule);
1184 logger.fine(format(" %s %c %5.3f", molecule, altLoc, occupancy));
1185 break;
1186 }
1187 }
1188 }
1189
1190
1191 if (molecules.isEmpty()) {
1192 return null;
1193 }
1194
1195
1196 int numConformers = molecularAssemblies.length;
1197 for (int i = 1; i < numConformers; i++) {
1198 molList = molecularAssemblies[i].getMolecules();
1199 Molecule molecule = (Molecule) molList.get(moleculeID);
1200 for (Atom a : molecule.getAtomList()) {
1201 if (!a.getUse()) {
1202 continue;
1203 }
1204 Character altLoc = a.getAltLoc();
1205 if (!altLoc.equals(' ') && !altLoc.equals('A')) {
1206
1207 double occupancy = a.getOccupancy();
1208 totalOccupancy += occupancy;
1209 molecules.add(molecule);
1210 logger.fine(format(" %s %c %5.3f", molecule, altLoc, occupancy));
1211 break;
1212 }
1213 }
1214 }
1215
1216 logger.fine(" Total occupancy: " + totalOccupancy);
1217 return molecules;
1218 }
1219
1220
1221
1222
1223
1224
1225
1226
1227 private void setParameterIndices() {
1228 int index = 0;
1229 for (RefinedParameter parameter : allParametersList) {
1230 parameter.setIndex(index);
1231 index += parameter.getNumberOfParameters();
1232 }
1233 }
1234
1235
1236
1237
1238
1239
1240
1241
1242 private void regularizeActiveAtoms() {
1243 for (MolecularAssembly molecularAssembly : molecularAssemblies) {
1244
1245
1246 if (ridingHydrogen) {
1247 for (Atom atom : molecularAssembly.getAtomList()) {
1248 if (atom.isHydrogen()) {
1249 Atom other = atom.getBonds().getFirst().get1_2(atom);
1250 atom.setActive(other.isActive());
1251 }
1252 }
1253 }
1254
1255
1256 if (byResidue) {
1257 List<MSNode> nodeList = molecularAssembly.getNodeList();
1258 for (MSNode node : nodeList) {
1259 Atom activeAtom = node.getFirstActiveHeavyAtom();
1260 if (activeAtom != null) {
1261 for (Atom atom : node.getAtomList()) {
1262 atom.setActive(true);
1263 }
1264 } else {
1265
1266 for (Atom atom : node.getAtomList()) {
1267 atom.setActive(false);
1268 }
1269 }
1270 }
1271 }
1272 }
1273 }
1274
1275
1276
1277
1278
1279
1280 private void addAnisotropicBFactors() {
1281 if (addAnisou) {
1282 for (MolecularAssembly molecularAssembly : molecularAssemblies) {
1283 int count = 0;
1284 List<Atom> atomList = molecularAssembly.getAtomList();
1285 for (Atom a : atomList) {
1286
1287 if (a.isHeavy() && a.isActive() && a.getAnisou(null) == null) {
1288 double[] anisou = new double[6];
1289 double u = b2u(a.getTempFactor());
1290 anisou[0] = u;
1291 anisou[1] = u;
1292 anisou[2] = u;
1293 anisou[3] = 0.0;
1294 anisou[4] = 0.0;
1295 anisou[5] = 0.0;
1296 a.setAnisou(anisou);
1297 count++;
1298 }
1299 }
1300 if (count > 0) {
1301 Character c = molecularAssembly.getAlternateLocation();
1302 logger.info(format(" %d anisotropic B-factors were added to conformer %c.", count, c));
1303 }
1304 }
1305 }
1306 }
1307
1308 }