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.bonded;
39
40 import static ffx.potential.bonded.AminoAcidUtils.AA1toAA3;
41 import static ffx.potential.bonded.NucleicAcidUtils.NA1toNA3;
42 import static java.lang.System.arraycopy;
43
44 import ffx.potential.bonded.AminoAcidUtils.AminoAcid1;
45 import ffx.potential.bonded.AminoAcidUtils.AminoAcid3;
46 import ffx.potential.bonded.NucleicAcidUtils.NucleicAcid1;
47 import ffx.potential.bonded.NucleicAcidUtils.NucleicAcid3;
48 import ffx.potential.parameters.ForceField;
49 import ffx.potential.parameters.TitrationUtils;
50
51 import java.io.Serial;
52 import java.util.ArrayList;
53 import java.util.Comparator;
54 import java.util.HashMap;
55 import java.util.List;
56 import java.util.Objects;
57 import java.util.logging.Level;
58 import java.util.logging.Logger;
59 import org.jogamp.java3d.Canvas3D;
60 import org.jogamp.java3d.J3DGraphics2D;
61 import org.jogamp.java3d.Material;
62 import org.jogamp.java3d.Node;
63 import org.jogamp.vecmath.Color3f;
64 import org.jogamp.vecmath.Point2d;
65 import org.jogamp.vecmath.Point3d;
66
67
68
69
70
71
72
73
74 public class Residue extends MSGroup implements Comparable<Residue> {
75
76 @Serial
77 private static final long serialVersionUID = 1L;
78
79 private static final Logger logger = Logger.getLogger(Residue.class.getName());
80
81 private static final Comparator<Residue> resComparator = Comparator.comparing(Residue::getSegID)
82 .thenComparingInt(Residue::getResidueNumber).thenComparing(Residue::getResidueType)
83 .thenComparing(Residue::getName);
84
85
86 private static final HashMap<NucleicAcid3, Color3f> NA3Color = new HashMap<>();
87
88 private static final HashMap<AminoAcid3, Color3f> AA3Color = new HashMap<>();
89
90 private static final HashMap<SSType, Color3f> SSTypeColor = new HashMap<>();
91
92 public static String[] Ramachandran = new String[17];
93
94 private static final Point3d point3d = new Point3d();
95 private static final Point2d point2d = new Point2d();
96
97 static {
98 NA3Color.put(NucleicAcid3.ADE, RendererCache.RED);
99 NA3Color.put(NucleicAcid3.CYT, RendererCache.MAGENTA);
100 NA3Color.put(NucleicAcid3.GUA, RendererCache.BLUE);
101 NA3Color.put(NucleicAcid3.URI, RendererCache.YELLOW);
102 NA3Color.put(NucleicAcid3.DAD, RendererCache.RED);
103 NA3Color.put(NucleicAcid3.DCY, RendererCache.MAGENTA);
104 NA3Color.put(NucleicAcid3.DGU, RendererCache.BLUE);
105 NA3Color.put(NucleicAcid3.DTY, RendererCache.ORANGE);
106 NA3Color.put(NucleicAcid3.MP1, RendererCache.GREEN);
107 NA3Color.put(NucleicAcid3.DP2, RendererCache.GREEN);
108 NA3Color.put(NucleicAcid3.TP3, RendererCache.GREEN);
109 NA3Color.put(NucleicAcid3.UNK, RendererCache.CYAN);
110
111 AA3Color.put(AminoAcid3.ALA, RendererCache.GRAY);
112 AA3Color.put(AminoAcid3.ARG, RendererCache.BLUE);
113 AA3Color.put(AminoAcid3.ASN, RendererCache.BLUE);
114 AA3Color.put(AminoAcid3.ASP, RendererCache.RED);
115 AA3Color.put(AminoAcid3.CYS, RendererCache.YELLOW);
116 AA3Color.put(AminoAcid3.GLN, RendererCache.BLUE);
117 AA3Color.put(AminoAcid3.GLU, RendererCache.RED);
118 AA3Color.put(AminoAcid3.GLH, RendererCache.RED);
119 AA3Color.put(AminoAcid3.GLD, RendererCache.RED);
120 AA3Color.put(AminoAcid3.GLY, RendererCache.GRAY);
121 AA3Color.put(AminoAcid3.ILE, RendererCache.GRAY);
122 AA3Color.put(AminoAcid3.LEU, RendererCache.GRAY);
123 AA3Color.put(AminoAcid3.LYS, RendererCache.BLUE);
124 AA3Color.put(AminoAcid3.MET, RendererCache.YELLOW);
125 AA3Color.put(AminoAcid3.PHE, RendererCache.GREEN);
126 AA3Color.put(AminoAcid3.PRO, RendererCache.ORANGE);
127 AA3Color.put(AminoAcid3.SER, RendererCache.BLUE);
128 AA3Color.put(AminoAcid3.THR, RendererCache.BLUE);
129 AA3Color.put(AminoAcid3.TRP, RendererCache.GREEN);
130 AA3Color.put(AminoAcid3.TYR, RendererCache.GREEN);
131 AA3Color.put(AminoAcid3.VAL, RendererCache.GRAY);
132 AA3Color.put(AminoAcid3.HIS, RendererCache.BLUE);
133 AA3Color.put(AminoAcid3.HIE, RendererCache.BLUE);
134 AA3Color.put(AminoAcid3.HID, RendererCache.BLUE);
135 AA3Color.put(AminoAcid3.ORN, RendererCache.ORANGE);
136 AA3Color.put(AminoAcid3.AIB, RendererCache.ORANGE);
137 AA3Color.put(AminoAcid3.PCA, RendererCache.ORANGE);
138 AA3Color.put(AminoAcid3.FOR, RendererCache.RED);
139 AA3Color.put(AminoAcid3.ACE, RendererCache.RED);
140 AA3Color.put(AminoAcid3.NH2, RendererCache.BLUE);
141 AA3Color.put(AminoAcid3.NME, RendererCache.BLUE);
142 AA3Color.put(AminoAcid3.UNK, RendererCache.MAGENTA);
143
144 SSTypeColor.put(SSType.NONE, RendererCache.WHITE);
145 SSTypeColor.put(SSType.SHEET, RendererCache.PINK);
146 SSTypeColor.put(SSType.HELIX, RendererCache.BLUE);
147 SSTypeColor.put(SSType.TURN, RendererCache.YELLOW);
148
149 Ramachandran[0] = "Default (Extended) [-135.0 135.0]";
150 Ramachandran[1] = "Alpha Helix (R) [ -57.0 -47.0]";
151 Ramachandran[2] = "Alpha Helix (L) [ 57.0 47.0]";
152 Ramachandran[3] = "3-10 Helix [ -49.0 -26.0]";
153 Ramachandran[4] = "Pi Helix [ -57.0 -70.0]";
154 Ramachandran[5] = "Polyproline II Helix [ -79.0 149.0]";
155 Ramachandran[6] = "Parallel Beta Strand [-119.0 113.0]";
156 Ramachandran[7] = "Antiparallel Beta Strand [-139.0 135.0]";
157 Ramachandran[8] = "Beta-Hairpin 2' (i+1) [ 90.0 -170.0]";
158 Ramachandran[9] = "Beta-Hairpin 2' (i+2) [ -80.0 -10.0]";
159 Ramachandran[10] = "Beta-Hairpin 1' (i+1) [ 57.0 47.0]";
160 Ramachandran[11] = "Beta-Hairpin 1' (i+2) [ 57.0 47.0]";
161 Ramachandran[12] = "Beta-Hairpin 1 (i+1) [ -57.0 -47.0]";
162 Ramachandran[13] = "Beta-Hairpin 1 (i+2) [ -57.0 -47.0]";
163 Ramachandran[14] = "Beta-Hairpin 1 (i+3) [ 90.0 -170.0]";
164 Ramachandran[15] = "Beta-Hairpin 3' (i+1) [ 57.0 47.0]";
165 Ramachandran[16] = "Beta-Hairpin 3' (i+2) [ -80.0 -10.0]";
166 }
167
168
169 ResidueType residueType;
170
171 private int resNumber;
172
173 private Character chainID;
174
175 private String segID;
176
177 private Rotamer[] rotamers = null;
178
179 private Rotamer currentRotamer = null;
180
181 private String shortString = null;
182
183 private AminoAcid3 aa;
184
185 private NucleicAcid3 na;
186
187
188
189 private TitrationUtils titrationUtils = null;
190
191
192
193
194
195
196
197
198
199
200
201
202
203 private double[] O3sNorthCoords, O3sSouthCoords, C1sCoords, O4sCoords, C4sCoords;
204
205
206
207
208
209
210
211 public Residue(int num, ResidueType residueType) {
212 super();
213 resNumber = num;
214 this.residueType = residueType;
215 assignResidueType();
216 }
217
218
219
220
221
222
223
224 public Residue(String name, ResidueType residueType) {
225 super(name);
226 this.residueType = residueType;
227 assignResidueType();
228 }
229
230
231
232
233
234
235
236
237 public Residue(String name, int num, ResidueType residueType) {
238 this(name, residueType);
239 resNumber = num;
240 }
241
242
243
244
245
246
247
248
249
250
251 public Residue(String name, int resNumber, ResidueType residueType, Character chainID,
252 String segID) {
253 this(name, residueType);
254 this.resNumber = resNumber;
255 this.chainID = chainID;
256 this.segID = segID;
257 }
258
259
260
261
262
263
264
265
266
267
268 public Residue(String name, int resNumber, MSNode atoms, ResidueType residueType,
269 ForceField forceField) {
270 super(name, atoms);
271 this.resNumber = resNumber;
272 this.residueType = residueType;
273 assignResidueType();
274 finalize(true, forceField);
275 }
276
277 @Override
278 public void setName(String name) {
279 super.setName(name);
280 if (residueType != null) {
281 assignResidueType();
282 }
283 for (Atom atom : getAtomList()) {
284 atom.setResName(name);
285 }
286 }
287
288
289
290
291
292
293 @Override
294 public MSNode addMSNode(MSNode o) {
295 Atom currentAtom = null;
296 if (o instanceof Atom newAtom) {
297 Character newAlt = newAtom.getAltLoc();
298 MSNode atoms = getAtomNode();
299 currentAtom = (Atom) atoms.contains(newAtom);
300 if (currentAtom == null) {
301 currentAtom = newAtom;
302 currentAtom.setResName(getName());
303 currentAtom.setResidueNumber(resNumber);
304 atoms.add(newAtom);
305 setFinalized(false);
306 } else {
307
308 Character currentAlt = currentAtom.getAltLoc();
309 if (currentAlt.equals(' ') || currentAlt.equals('A')) {
310 if (!newAlt.equals(' ') && !newAlt.equals('A')) {
311 newAtom.setXyzIndex(currentAtom.getXyzIndex());
312 atoms.remove(currentAtom);
313 currentAtom = newAtom;
314
315 currentAtom.setResName(getName());
316 currentAtom.setResidueNumber(resNumber);
317
318 atoms.add(currentAtom);
319 setFinalized(false);
320 }
321 }
322 }
323 } else {
324 logger.warning("Only an Atom can be added to a Residue.");
325 }
326 return currentAtom;
327 }
328
329 @Override
330 public int compareTo(Residue o) {
331 if (this.equals(o)) {
332 return 0;
333 }
334 return resComparator.compare(this, o);
335 }
336
337
338 @Override
339 public void drawLabel(Canvas3D canvas, J3DGraphics2D g2d, Node node) {
340 if (RendererCache.labelResidues) {
341 double[] d = getCenter();
342 point3d.x = d[0];
343 point3d.y = d[1];
344 point3d.z = d[2];
345 RendererCache.getScreenCoordinate(canvas, node, point3d, point2d);
346 g2d.drawString(getName(), (float) point2d.x, (float) point2d.y);
347 }
348 if (RendererCache.labelAtoms) {
349 super.drawLabel(canvas, g2d, node);
350 }
351 }
352
353
354 @Override
355 public boolean equals(Object o) {
356 if (this == o) {
357 return true;
358 }
359 if (o == null || getClass() != o.getClass()) {
360 return false;
361 }
362 Residue residue = (Residue) o;
363 return Objects.equals(segID, residue.segID)
364 && Objects.equals(getResidueNumber(), residue.getResidueNumber())
365 && residueType == residue.residueType && Objects.equals(getName(), residue.getName());
366 }
367
368
369
370
371
372
373
374
375 @Override
376 public void finalize(boolean finalizeGeometry, ForceField forceField) {
377 setFinalized(false);
378 getAtomNode().setName("Atoms (" + getAtomList().size() + ")");
379 if (finalizeGeometry) {
380 assignBondedTerms(forceField);
381 removeLeaves();
382 }
383 setCenter(getMultiScaleCenter(false));
384 setFinalized(true);
385 }
386
387 public void setTitrationUtils(TitrationUtils titrationUtils) {
388 this.titrationUtils = titrationUtils;
389 }
390
391 public TitrationUtils getTitrationUtils() {
392 return titrationUtils;
393 }
394
395
396
397
398
399
400 public AminoAcid3 getAminoAcid3() {
401 if (this.residueType != ResidueType.AA) {
402 throw new IllegalArgumentException(
403 String.format(" This residue is " + "not an amino acid: %s", this));
404 }
405 return aa;
406 }
407
408
409
410
411
412
413
414 public List<Atom> getBackboneAtoms() {
415 List<Atom> atoms = getAtomList();
416 List<Atom> ret;
417 switch (residueType) {
418 case NA -> {
419 ret = new ArrayList<>(atoms);
420 for (Atom atom : atoms) {
421 String name = atom.getName().toUpperCase();
422 if (name.contains("'") || name.equals("P") || name.startsWith("OP") || name.equals("H5T")
423 || name.equals("H3T")) {
424 ret.remove(atom);
425 }
426 }
427 return ret;
428 }
429 case AA -> {
430 ret = new ArrayList<>();
431 tryAddAtom(ret, "N");
432 tryAddAtom(ret, "CA");
433 tryAddAtom(ret, "C");
434 tryAddAtom(ret, "O");
435 tryAddAtom(ret, "OXT");
436 tryAddAtom(ret, "OT2");
437 tryAddAtom(ret, "H1");
438 tryAddAtom(ret, "H2");
439 tryAddAtom(ret, "H3");
440 tryAddAtom(ret, "H");
441 tryAddAtom(ret, "HA");
442 tryAddAtom(ret, "HA2");
443 tryAddAtom(ret, "HA3");
444 return ret;
445 }
446 default -> {
447 return new ArrayList<>(1);
448 }
449 }
450 }
451
452
453
454
455
456
457 public Character getChainID() {
458 return chainID;
459 }
460
461
462
463
464
465
466 public void setChainID(Character c) {
467 chainID = c;
468
469 for (Atom atom : getAtomList()) {
470 atom.setChainID(c);
471 }
472 }
473
474
475
476
477
478
479 public void setSegID(String segID) {
480 this.segID = segID;
481
482 for (Atom atom : getAtomList()) {
483 atom.setSegID(segID);
484 }
485 }
486
487
488
489
490
491
492
493
494
495 public Residue getNextResidue() {
496 switch (residueType) {
497 case AA -> {
498 Atom carbon = (Atom) getAtomNode("C");
499 if (carbon == null) {
500 return null;
501 }
502 List<Bond> bonds = carbon.getBonds();
503 for (Bond b : bonds) {
504 Atom other = b.get1_2(carbon);
505 if (other.getName().equalsIgnoreCase("N")) {
506 return (Residue) other.getParent().getParent();
507 }
508 }
509 }
510 case NA -> {
511 Atom oxygen = (Atom) getAtomNode("O3'");
512 if (oxygen == null) {
513 return null;
514 }
515 List<Bond> bonds = oxygen.getBonds();
516 for (Bond b : bonds) {
517 Atom other = b.get1_2(oxygen);
518 if (other.getName().equalsIgnoreCase("P")) {
519 return (Residue) other.getParent().getParent();
520 }
521 }
522 }
523 default -> {
524 return null;
525 }
526 }
527 return null;
528
529 }
530
531
532
533
534
535
536 public NucleicAcid3 getNucleicAcid3() {
537 if (this.residueType != ResidueType.NA) {
538 throw new IllegalArgumentException(
539 String.format(" This residue is not a nucleic acid: %s", this));
540 }
541 return na;
542 }
543
544
545
546
547
548
549
550
551 public NucleicAcid3 getNucleicAcid3(boolean matchShortName) {
552 NucleicAcid3 na3 = getNucleicAcid3();
553 if (na3 == NucleicAcidUtils.NucleicAcid3.UNK && matchShortName) {
554 switch (getName()) {
555 case "A" -> {
556 return NucleicAcid3.ADE;
557 }
558 case "C" -> {
559 return NucleicAcid3.CYT;
560 }
561 case "G" -> {
562 return NucleicAcid3.GUA;
563 }
564 case "T" -> {
565 return NucleicAcid3.THY;
566 }
567 case "U" -> {
568 return NucleicAcid3.URI;
569 }
570 case "DA" -> {
571 return NucleicAcid3.DAD;
572 }
573 case "DC" -> {
574 return NucleicAcid3.DCY;
575 }
576 case "DG" -> {
577 return NucleicAcid3.DGU;
578 }
579 case "DT" -> {
580 return NucleicAcid3.DTY;
581 }
582 case "DU" -> throw new IllegalArgumentException(
583 " No NucleicAcid3 enum exists for DU (presumed to be deoxy-uracil)!");
584 }
585 }
586 return na3;
587 }
588
589
590
591
592
593
594
595
596
597 public Residue getPreviousResidue() {
598 switch (residueType) {
599 case AA -> {
600 Atom nitrogen = (Atom) getAtomNode("N");
601 if (nitrogen == null) {
602 return null;
603 }
604 List<Bond> bonds = nitrogen.getBonds();
605 for (Bond b : bonds) {
606 Atom other = b.get1_2(nitrogen);
607 if (other.getName().equalsIgnoreCase("C")) {
608 return (Residue) other.getParent().getParent();
609 }
610 }
611 }
612 case NA -> {
613 Atom phosphate = (Atom) getAtomNode("P");
614 if (phosphate == null) {
615 return null;
616 }
617 List<Bond> bonds = phosphate.getBonds();
618 for (Bond b : bonds) {
619 Atom other = b.get1_2(phosphate);
620 if (other.getName().equalsIgnoreCase("O3'")) {
621 return (Residue) other.getParent().getParent();
622 }
623 }
624 }
625 default -> {
626 return null;
627 }
628 }
629 return null;
630
631 }
632
633
634
635
636
637
638
639 public Atom getReferenceAtom() {
640 Atom atom = null;
641 switch (this.getResidueType()) {
642 case AA -> atom = (Atom) this.getAtomNode("CA");
643 case NA -> {
644
645
646 atom = (Atom) this.getAtomNode("N1");
647 if (atom == null) {
648 atom = (Atom) this.getAtomNode("N9");
649 }
650 }
651 default -> {
652 }
653 }
654 if (atom == null) {
655 atom = (Atom) this.getAtomNode(0);
656 }
657 return atom;
658 }
659
660
661
662
663
664
665 public int getResidueNumber() {
666 return resNumber;
667 }
668
669
670
671
672
673
674 public ResidueType getResidueType() {
675 return residueType;
676 }
677
678
679
680
681
682
683 public Rotamer getRotamer() {
684 return currentRotamer;
685 }
686
687
688
689
690
691
692 public void setRotamer(Rotamer rotamer) {
693 this.currentRotamer = rotamer;
694 }
695
696
697
698
699
700
701 public Rotamer[] getRotamers() {
702 return rotamers;
703 }
704
705
706
707
708
709
710
711
712
713
714 public Rotamer[] setRotamers(RotamerLibrary library) {
715
716
717 Rotamer[] libRotamers = library.getRotamers(this, titrationUtils);
718 rotamers = libRotamers;
719
720
721
722 if (library.getUsingOrigCoordsRotamer() && rotamers != null) {
723
724 Rotamer[] originalRotamers = Rotamer.defaultRotamerFactory(this, titrationUtils);
725 int nOrig = originalRotamers.length;
726
727 int libRots = libRotamers.length;
728 rotamers = new Rotamer[libRots + nOrig];
729
730 arraycopy(originalRotamers, 0, rotamers, 0, nOrig);
731
732 arraycopy(libRotamers, 0, rotamers, nOrig, libRots);
733 }
734
735 return rotamers;
736 }
737
738
739
740
741
742
743
744
745
746 public Rotamer[] setRotamers(){
747 Rotamer[] originalRotamers = Rotamer.defaultRotamerFactory(this, titrationUtils);
748 int nOrig = originalRotamers.length;
749 rotamers = new Rotamer[nOrig];
750 arraycopy(originalRotamers, 0, rotamers, 0, nOrig);
751 return rotamers;
752 }
753
754
755
756
757
758
759 public String getSegID() {
760 return segID;
761 }
762
763
764
765
766
767
768
769 public List<Atom> getSideChainAtoms() {
770 List<Atom> atoms = getAtomList();
771 List<Atom> ret;
772 switch (residueType) {
773 case NA -> {
774 ret = new ArrayList<>();
775 for (Atom atom : atoms) {
776 String name = atom.getName().toUpperCase();
777
778
779
780
781
782 if (name.contains("'") || name.equals("P") || name.startsWith("OP")) {
783 ret.add(atom);
784 }
785 }
786 return ret;
787 }
788 case AA -> {
789 ret = new ArrayList<>(atoms);
790 for (Atom atom : atoms) {
791 String name = atom.getName().toUpperCase();
792 if (name.equals("N") || name.equals("H") || name.equals("H1") || name.equals("H2")
793 || name.equals("H3") || name.equals("CA") || name.startsWith("HA") || name.equals("C")
794 || name.equals("O") || name.equals("OXT") || name.equals("OT2")) {
795 ret.remove(atom);
796 }
797 }
798 return ret;
799 }
800 default -> {
801 return null;
802 }
803 }
804 }
805
806
807
808
809
810
811
812
813 public List<Atom> getVariableAtoms() {
814 return getSideChainAtoms();
815 }
816
817
818 @Override
819 public int hashCode() {
820 return Objects.hash(segID, getResidueNumber(), residueType, getName());
821 }
822
823
824
825
826
827
828 public void initializeDefaultAtomicCoordinates() {
829 if (residueType != ResidueType.NA) {
830 return;
831 }
832 boolean isDeoxy;
833 try {
834 isDeoxy = switch (NucleicAcid3.valueOf(this.getName())) {
835 case DAD, DCY, DGU, DTY -> true;
836 default -> false;
837 };
838 C1sCoords = new double[3];
839 ((Atom) getAtomNode("C1'")).getXYZ(C1sCoords);
840 O4sCoords = new double[3];
841 ((Atom) getAtomNode("O4'")).getXYZ(O4sCoords);
842 C4sCoords = new double[3];
843 ((Atom) getAtomNode("C4'")).getXYZ(C4sCoords);
844
845
846
847
848
849
850 O3sNorthCoords = RotamerLibrary.applySugarPucker(this,
851 RotamerLibrary.NucleicSugarPucker.C3_ENDO, isDeoxy, false);
852 O3sSouthCoords = RotamerLibrary.applySugarPucker(this,
853 RotamerLibrary.NucleicSugarPucker.C2_ENDO, isDeoxy, false);
854 } catch (Exception e) {
855 logger.log(Level.WARNING, toString(), e);
856 }
857 }
858
859
860
861
862
863
864 @Override
865 public void print() {
866 logger.info(" " + this);
867 for (Atom a : getAtomNode().getAtomList()) {
868 a.print();
869 }
870 }
871
872
873
874
875
876
877 public void revertState(ResidueState state) {
878 List<Atom> atomList = getAtomList();
879 for (Atom atom : atomList) {
880 atom.moveTo(state.getAtomCoords(atom));
881 }
882 }
883
884
885 @Override
886 public void setColor(RendererCache.ColorModel newColorModel, Color3f color, Material mat) {
887
888 if (newColorModel == RendererCache.ColorModel.RESIDUE) {
889 switch (residueType) {
890 case AA -> color = AA3Color.get(aa);
891 case NA -> color = NA3Color.get(na);
892 default -> color = null;
893 }
894 if (color == null) {
895 return;
896 }
897 mat = RendererCache.materialFactory(color);
898 } else if (newColorModel == RendererCache.ColorModel.STRUCTURE) {
899 color = SSTypeColor.get(SSType.NONE);
900 mat = RendererCache.materialFactory(color);
901 }
902 super.setColor(newColorModel, color, mat);
903 }
904
905
906
907
908
909
910 public void setNumber(int n) {
911 resNumber = n;
912 for (Atom atom : getAtomList()) {
913 atom.setResidueNumber(n);
914 }
915 }
916
917
918
919
920
921
922 public double[][] storeCoordinateArray() {
923 List<Atom> atomList = getAtomList();
924 int nAtoms = atomList.size();
925 double[][] coords = new double[nAtoms][3];
926 int i = 0;
927 for (Atom atom : atomList) {
928 atom.getXYZ(coords[i++]);
929 }
930 return coords;
931 }
932
933
934
935
936
937
938 public ResidueState storeState() {
939 return new ResidueState(this, this);
940 }
941
942
943
944
945
946
947
948
949
950
951 public String toFormattedString(boolean addResType, boolean addChainID) {
952 StringBuilder sb = new StringBuilder();
953 if (addResType) {
954 sb.append(residueType.toString()).append("-");
955 }
956 if (addChainID) {
957 sb.append(chainID);
958 }
959 sb.append(this);
960 return sb.toString();
961 }
962
963
964
965
966
967
968
969
970
971 public String toString(Rotamer rotamer) {
972 return "" + chainID + resNumber + "-" + rotamer.getName();
973 }
974
975
976 @Override
977 public String toString() {
978 if (shortString == null) {
979 shortString = resNumber + "-" + getName();
980 }
981 return shortString;
982 }
983
984
985
986
987
988
989 void addRotamers(Rotamer[] rotamers) {
990 for (Rotamer rotamer : rotamers) {
991 addRotamer(rotamer);
992 }
993 }
994
995
996
997
998
999
1000 void addRotamer(Rotamer rotamer) {
1001 if (rotamers != null) {
1002 Rotamer[] libRotamers = rotamers;
1003 int nRots = libRotamers.length;
1004 rotamers = new Rotamer[nRots + 1];
1005 arraycopy(libRotamers, 0, rotamers, 0, nRots);
1006 rotamers[rotamers.length - 1] = rotamer;
1007 } else {
1008 rotamers = new Rotamer[1];
1009 rotamers[0] = rotamer;
1010 }
1011 }
1012
1013
1014
1015
1016
1017
1018 void deleteAtom(Atom atomToDelete) {
1019 MSNode atoms = getAtomNode();
1020 if (atoms.contains(atomToDelete) != null) {
1021 logger.info(" The following atom is being deleted from the model:\n" + atomToDelete);
1022 atoms.remove(atomToDelete);
1023 }
1024 }
1025
1026
1027
1028
1029
1030
1031
1032 double[] getO3sNorth() {
1033 double[] ret = new double[3];
1034 arraycopy(O3sNorthCoords, 0, ret, 0, ret.length);
1035 return ret;
1036 }
1037
1038
1039
1040
1041
1042
1043
1044 double[] getO3sSouth() {
1045 double[] ret = new double[3];
1046 arraycopy(O3sSouthCoords, 0, ret, 0, ret.length);
1047 return ret;
1048 }
1049
1050
1051
1052
1053
1054
1055 double[] getC1sCoords() {
1056 double[] ret = new double[3];
1057 arraycopy(C1sCoords, 0, ret, 0, ret.length);
1058 return ret;
1059 }
1060
1061
1062
1063
1064
1065
1066 double[] getO4sCoords() {
1067 double[] ret = new double[3];
1068 arraycopy(O4sCoords, 0, ret, 0, ret.length);
1069 return ret;
1070 }
1071
1072
1073
1074
1075
1076
1077 double[] getC4sCoords() {
1078 double[] ret = new double[3];
1079 arraycopy(C4sCoords, 0, ret, 0, ret.length);
1080 return ret;
1081 }
1082
1083
1084
1085
1086
1087
1088
1089
1090 private boolean tryAddAtom(List<Atom> atList, String name) {
1091 try {
1092 Atom at = (Atom) getAtomNode(name);
1093 if (at != null) {
1094 atList.add(at);
1095 return true;
1096 } else {
1097 return false;
1098 }
1099 } catch (Exception ex) {
1100 return false;
1101 }
1102 }
1103
1104 private void assignResidueType() {
1105 String name = getName().toUpperCase();
1106 switch (residueType) {
1107 case AA -> {
1108 aa = null;
1109 try {
1110 if (name.length() >= 2) {
1111 aa = AminoAcid3.valueOf(name);
1112 } else if (name.length() == 1) {
1113 AminoAcid1 aa1 = AminoAcid1.valueOf(name);
1114 aa = AA1toAA3.get(aa1);
1115 }
1116 } catch (Exception e) {
1117 logger.fine(String.format("Exception assigning AA3 for residue: %s", name));
1118 aa = AminoAcid3.UNK;
1119 }
1120 }
1121 case NA -> {
1122 na = null;
1123 try {
1124 if (name.length() >= 2) {
1125 na = NucleicAcid3.parse(name);
1126 } else if (name.length() == 1) {
1127 NucleicAcid1 na1 = NucleicAcid1.valueOf(name);
1128 na = NA1toNA3.get(na1);
1129 }
1130 } catch (Exception e) {
1131 na = NucleicAcid3.UNK;
1132 }
1133 }
1134 }
1135 }
1136
1137 public enum SSType {
1138 NONE, HELIX, SHEET, TURN
1139 }
1140
1141
1142
1143
1144 public enum ResidueType {
1145 NA, AA, UNK
1146 }
1147 }