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