1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24 """The objects representing displacement information in the internal structural object."""
25
26
27 from lib.structure.superimpose import kabsch
28 from lib.structure.internal.models import ModelContainer
29 from lib.xml import object_to_xml, xml_to_object
30
31
33 """A special object for representing rotational and translational displacements between models."""
34
36 """Initialise the storage objects."""
37
38
39 self._translation_vector = {}
40 self._translation_distance = {}
41 self._rotation_matrix = {}
42 self._rotation_axis = {}
43 self._rotation_angle = {}
44
45
46 - def _calculate(self, id_from=None, id_to=None, coord_from=None, coord_to=None, centroid=None):
47 """Calculate the rotational and translational displacements using the given coordinate sets.
48
49 This uses the U{Kabsch algorithm<http://en.wikipedia.org/wiki/Kabsch_algorithm>}.
50
51
52 @keyword id_from: The ID string of the starting structure.
53 @type id_from: str
54 @keyword id_to: The ID string of the ending structure.
55 @type id_to: str
56 @keyword coord_from: The list of atomic coordinates for the starting structure.
57 @type coord_from: numpy rank-2, Nx3 array
58 @keyword coord_to: The list of atomic coordinates for the ending structure.
59 @type coord_to: numpy rank-2, Nx3 array
60 @keyword centroid: An alternative position of the centroid, used for studying pivoted systems.
61 @type centroid: list of float or numpy rank-1, 3D array
62 """
63
64
65 if not id_from in self._translation_vector:
66 self._translation_vector[id_from] = {}
67 if not id_from in self._translation_distance:
68 self._translation_distance[id_from] = {}
69 if not id_from in self._rotation_matrix:
70 self._rotation_matrix[id_from] = {}
71 if not id_from in self._rotation_axis:
72 self._rotation_axis[id_from] = {}
73 if not id_from in self._rotation_angle:
74 self._rotation_angle[id_from] = {}
75
76
77 trans_vect, trans_dist, R, axis, angle, pivot = kabsch(name_from="'%s'"%id_from, name_to="'%s'"%id_to, coord_from=coord_from, coord_to=coord_to, centroid=centroid)
78
79
80 self._translation_vector[id_from][id_to] = trans_vect
81 self._translation_distance[id_from][id_to] = trans_dist
82 self._rotation_matrix[id_from][id_to] = R
83 self._rotation_axis[id_from][id_to] = axis
84 self._rotation_angle[id_from][id_to] = angle
85
86
87 - def from_xml(self, str_node, dir=None, file_version=1):
88 """Recreate the structural object from the XML structural object node.
89
90 @param str_node: The structural object XML node.
91 @type str_node: xml.dom.minicompat.Element instance
92 @keyword dir: The name of the directory containing the results file.
93 @type dir: str
94 @keyword file_version: The relax XML version of the XML file.
95 @type file_version: int
96 """
97
98
99 pair_nodes = str_node.getElementsByTagName('pair')
100
101
102 for pair_node in pair_nodes:
103
104 id_from = str(pair_node.getAttribute('id_from'))
105 id_to = str(pair_node.getAttribute('id_to'))
106
107
108 if not id_from in self._translation_vector:
109 self._translation_vector[id_from] = {}
110 if not id_from in self._translation_distance:
111 self._translation_distance[id_from] = {}
112 if not id_from in self._rotation_matrix:
113 self._rotation_matrix[id_from] = {}
114 if not id_from in self._rotation_axis:
115 self._rotation_axis[id_from] = {}
116 if not id_from in self._rotation_angle:
117 self._rotation_angle[id_from] = {}
118
119
120 cont = ModelContainer()
121
122
123 xml_to_object(pair_node, cont, file_version=file_version)
124
125
126 for name in ['translation_vector', 'translation_distance', 'rotation_matrix', 'rotation_axis', 'rotation_angle']:
127
128 obj = getattr(self, '_'+name)
129 obj_temp = getattr(cont, name)
130
131
132 obj[id_from][id_to] = obj_temp
133
134
135 - def to_xml(self, doc, element):
136 """Create XML elements for each model.
137
138 @param doc: The XML document object.
139 @type doc: xml.dom.minidom.Document instance
140 @param element: The element to add the displacement XML elements to.
141 @type element: XML element object
142 """
143
144
145 start_models = sorted(self._translation_vector.keys())
146 for id_from in start_models:
147
148 end_models = sorted(self._translation_vector[id_from].keys())
149 for id_to in end_models:
150
151 pair_element = doc.createElement('pair')
152 element.appendChild(pair_element)
153
154
155 pair_element.setAttribute('desc', 'The displacement from model %s to model %s' % (id_from, id_to))
156 pair_element.setAttribute('id_from', id_from)
157 pair_element.setAttribute('id_to', id_to)
158
159
160 obj_names = [
161 '_translation_vector',
162 '_translation_distance',
163 '_rotation_matrix',
164 '_rotation_axis',
165 '_rotation_angle'
166 ]
167
168
169 for i in range(len(obj_names)):
170
171 sub_elem = doc.createElement(obj_names[i][1:])
172 pair_element.appendChild(sub_elem)
173
174
175 subobj = getattr(self, obj_names[i])[id_from][id_to]
176
177
178 object_to_xml(doc, sub_elem, value=subobj)
179