1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24 from numpy import float64, zeros
25 from warnings import warn
26
27
28 from generic_fns.mol_res_spin import return_molecule, return_residue, return_spin
29 from physical_constants import return_atomic_mass
30 from relax_errors import RelaxError, RelaxNoPdbError
31 from relax_warnings import RelaxWarning
32
33
34
36 """Calculate and return the centre of mass of the structure.
37
38 @keyword atom_id: The molecule, residue, and atom identifier string. Only atoms matching this selection will be used.
39 @type atom_id: str or None
40 @keyword model: Only use a specific model.
41 @type model: int or None
42 @keyword return_mass: A flag which if False will cause only the centre of mass to be returned, but if True will cause the centre of mass and the mass itself to be returned as a tuple.
43 @type return_mass: bool
44 @return: The centre of mass vector, and additionally the mass.
45 @rtype: list of 3 floats (or tuple of a list of 3 floats and one float)
46 """
47
48
49 if not hasattr(cdp, 'structure'):
50 raise RelaxNoPdbError
51
52
53 print("Calculating the centre of mass.")
54
55
56 R = zeros(3, float64)
57
58
59 M = 0.0
60
61
62 for mol_name, res_num, res_name, atom_num, atom_name, element, pos in cdp.structure.atom_loop(atom_id=atom_id, model_num=model, mol_name_flag=True, res_num_flag=True, res_name_flag=True, atom_num_flag=True, atom_name_flag=True, element_flag=True, pos_flag=True):
63
64 id = ''
65
66
67 if mol_name == None:
68 mol_cont = cdp.mol[0]
69 else:
70 id = id + '#' + mol_name
71 mol_cont = return_molecule(id)
72
73
74 if res_name == None and res_num == None:
75 res_cont = mol_cont.res[0]
76 else:
77 id = id + ':' + repr(res_num)
78 res_cont = return_residue(id)
79
80
81 if atom_name == None and atom_num == None:
82 spin_cont = res_cont.spin[0]
83 else:
84 id = id + '@' + repr(atom_num)
85 spin_cont = return_spin(id)
86
87
88 if spin_cont and not spin_cont.select:
89 continue
90
91
92 if element == None:
93 warn(RelaxWarning("Skipping the atom '%s' as the element type cannot be determined." % id))
94 continue
95
96
97 try:
98 mass = return_atomic_mass(element)
99 except RelaxError:
100 warn(RelaxWarning("Skipping the atom '%s' as the element '%s' is unknown." % (id, element)))
101
102
103 M = M + mass
104
105
106 R = R + mass * pos
107
108
109 R = R / M
110
111
112 print((" Total mass: M = " + repr(M)))
113 print((" Centre of mass: R = " + repr(R)))
114
115
116 if return_mass:
117 return R, M
118 else:
119 return R
120