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