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