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 data_store.relax_xml import object_to_xml, xml_to_object
27 from lib.structure.superimpose import kabsch
28 from lib.structure.internal.models import ModelContainer
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