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.numerics.Constraint;
41 import ffx.potential.bonded.Atom.Resolution;
42
43 import java.io.Serial;
44 import java.util.ArrayList;
45 import java.util.Comparator;
46 import java.util.List;
47 import java.util.Objects;
48 import java.util.logging.Logger;
49
50 import org.jogamp.java3d.BranchGroup;
51 import org.jogamp.java3d.Material;
52 import org.jogamp.vecmath.Color3f;
53
54
55
56
57
58
59
60
61 public abstract class BondedTerm extends MSNode implements BondedEnergy, Comparable<BondedTerm> {
62
63 @Serial
64 private static final long serialVersionUID = 1L;
65
66 private static final Logger logger = Logger.getLogger(BondedTerm.class.getName());
67
68
69
70
71
72 private static final StringBuilder idTemp = new StringBuilder();
73
74
75
76 private static final BondedComparator bondedComparator = new BondedComparator();
77
78
79
80 protected String id;
81
82
83
84 protected Atom[] atoms;
85
86
87
88 protected Bond[] bonds;
89
90
91
92 protected double value;
93
94
95
96 protected double energy;
97
98
99
100 private boolean isConstrained = false;
101
102
103
104
105 public BondedTerm() {
106 super("", 1);
107 setAllowsChildren(false);
108 }
109
110
111
112
113
114
115 public BondedTerm(String i) {
116 this();
117 id = i;
118 }
119
120
121
122
123
124
125 public boolean applyLambda() {
126 for (Atom atom : atoms) {
127 if (atom.applyLambda()) {
128 return true;
129 }
130 }
131 return false;
132 }
133
134
135
136
137 @Override
138 public int compareTo(BondedTerm t) {
139 return Objects.compare(this, t, bondedComparator);
140 }
141
142
143
144
145
146
147 public boolean containsHydrogen() {
148 for (Atom atom : atoms) {
149 if (atom.isHydrogen()) {
150 return true;
151 }
152 }
153 return false;
154 }
155
156
157
158
159
160
161 public boolean isNeuralNetwork() {
162 for (Atom atom : atoms) {
163 if (atom.isNeuralNetwork()) {
164 return true;
165 }
166 }
167 return false;
168 }
169
170
171
172
173
174
175
176 public static <T extends BondedTerm> void removeNeuralNetworkTerms(List<T> list) {
177
178 List<T> removeList = new ArrayList<>();
179 for (T term : list) {
180 if (term.isNeuralNetwork()) {
181 removeList.add(term);
182 }
183 }
184 list.removeAll(removeList);
185 }
186
187
188
189
190
191
192
193 public boolean containsResolution(Resolution resolution) {
194 for (Atom atom : atoms) {
195 if (atom.getResolution() == resolution) {
196 return true;
197 }
198 }
199 return false;
200 }
201
202
203
204
205 @Override
206 public boolean destroy() {
207 super.destroy();
208 id = null;
209 value = 0;
210 return true;
211 }
212
213
214
215
216
217
218
219 @Override
220 public final boolean equals(Object object) {
221 if (this == object) {
222 return true;
223 } else if (object == null || getClass() != object.getClass()) {
224 return false;
225 }
226 BondedTerm other = (BondedTerm) object;
227 return getID().equals(other.getID());
228 }
229
230
231
232
233
234
235
236 public Atom getAtom(int index) {
237 if (index >= 0 && index < atoms.length) {
238 return atoms[index];
239 }
240 return null;
241 }
242
243
244
245
246
247
248
249 public Atom[] getAtoms() {
250 return atoms;
251 }
252
253
254
255
256
257
258
259
260 public Atom[] getAtomArray() {
261 return getAtomArray(true);
262 }
263
264
265
266
267
268
269
270
271 public Atom[] getAtomArray(boolean returnCopy) {
272 if (returnCopy) {
273 int nAtoms = atoms.length;
274 Atom[] retAtoms = new Atom[nAtoms];
275 System.arraycopy(atoms, 0, retAtoms, 0, nAtoms);
276 return retAtoms;
277 } else {
278 return atoms;
279 }
280 }
281
282
283
284
285
286
287
288 public Bond getBond(int index) {
289 if (index >= 0 && index < atoms.length) {
290 return bonds[index];
291 }
292 return null;
293 }
294
295
296
297
298
299
300 public String getID() {
301 return id;
302 }
303
304
305
306
307
308
309 public boolean getUse() {
310 for (Atom atom : atoms) {
311 if (atom.getUse()) {
312 return true;
313 }
314 }
315 return false;
316 }
317
318
319
320
321
322
323 public void setID(String i) {
324 id = i;
325 }
326
327
328
329
330
331
332 public double getValue() {
333 return value;
334 }
335
336
337
338
339
340
341 public void setValue(double v) {
342 value = v;
343 }
344
345
346
347
348 @Override
349 public int hashCode() {
350 return Objects.hash(getID());
351 }
352
353
354
355
356
357
358 public boolean isConstrained() {
359 return isConstrained;
360 }
361
362
363
364
365
366
367 public boolean isLambdaScaled() {
368 return false;
369 }
370
371
372
373
374
375
376 @Override
377 public void print() {
378 logger.info(toString());
379 }
380
381
382
383
384
385
386 public void setAtoms(Atom[] a) {
387 atoms = a;
388 }
389
390
391
392
393
394
395 public void setBonds(Bond[] b) {
396 bonds = b;
397 }
398
399
400
401
402 @Override
403 public void setColor(RendererCache.ColorModel newColorModel, Color3f color, Material mat) {
404 if (atoms == null) {
405 return;
406 }
407 for (Atom atom : atoms) {
408 atom.setColor(newColorModel, color, mat);
409 }
410 }
411
412
413
414
415
416
417
418 public void setConstraint(Constraint c) {
419 isConstrained = c != null;
420 }
421
422
423
424
425
426
427 public final void setID_Key(boolean reverse) {
428 if (atoms == null) {
429 return;
430 }
431
432 idTemp.delete(0, idTemp.length());
433 for (int i = 0; i < atoms.length; i++) {
434 Atom a = (reverse) ? atoms[atoms.length - 1 - i] : atoms[i];
435 if (i != 0) {
436 idTemp.append(" ");
437 }
438 idTemp.append(a.describe(Atom.Descriptions.XyzIndex_Name));
439 }
440 id = idTemp.toString().intern();
441 }
442
443
444
445
446 @Override
447 public void setSelected(boolean b) {
448 super.setSelected(b);
449 if (atoms == null) {
450 return;
451 }
452 for (Atom a : atoms) {
453 a.setSelected(b);
454 }
455 if (!(this instanceof Bond)) {
456 if (bonds == null) {
457 return;
458 }
459 for (Bond bond : bonds) {
460 bond.setSelected(b);
461 }
462 }
463 }
464
465
466
467
468 @Override
469 public void setView(RendererCache.ViewModel newViewModel, List<BranchGroup> newShapes) {
470 if (atoms == null) {
471 return;
472 }
473 for (Atom atom : atoms) {
474 atom.setView(newViewModel, newShapes);
475 }
476 if (bonds == null) {
477 return;
478 }
479 for (Bond bond : bonds) {
480 bond.setView(newViewModel, newShapes);
481 }
482 }
483
484
485
486
487
488
489 @Override
490 public String toString() {
491 return String.format("%s (%7.2f,%7.2f)", id, value, energy);
492 }
493
494
495
496
497
498
499 boolean applyAllLambda() {
500 for (Atom atom : atoms) {
501 if (!atom.applyLambda()) {
502 return false;
503 }
504 }
505 return true;
506 }
507
508
509
510
511
512
513
514 boolean containsAtom(Atom atom) {
515 for (Atom a : atoms) {
516 if (a.equals(atom)) {
517 return true;
518 }
519 }
520 return false;
521 }
522
523 public static class BondedComparator implements Comparator<BondedTerm> {
524
525 private static final List<Class<? extends BondedTerm>> naturalOrder =
526 new ArrayList<>() {
527 {
528 add(Bond.class);
529 add(Angle.class);
530 add(StretchBend.class);
531 add(UreyBradley.class);
532 add(OutOfPlaneBend.class);
533 add(Torsion.class);
534 add(ImproperTorsion.class);
535 add(PiOrbitalTorsion.class);
536 add(StretchTorsion.class);
537 add(AngleTorsion.class);
538 add(TorsionTorsion.class);
539 }
540 };
541
542 private BondedComparator() {
543 }
544
545
546
547
548 @Override
549 public int compare(BondedTerm bondedTerm1, BondedTerm bondedTerm2) {
550 final Class<? extends BondedTerm> class1 = bondedTerm2.getClass();
551 final Class<? extends BondedTerm> class2 = bondedTerm1.getClass();
552 int order1 = naturalOrder.indexOf(bondedTerm1.getClass());
553 int order2 = naturalOrder.indexOf(bondedTerm2.getClass());
554 if (order1 >= 0 && order2 >= 0) {
555 return Integer.compare(order1, order2);
556 } else {
557 return String.CASE_INSENSITIVE_ORDER.compare(class2.toString(), class1.toString());
558 }
559 }
560 }
561 }