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