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, id_from=None, id_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 id_from:       The ID string of the starting structure. 
 52          @type id_from:          str 
 53          @keyword id_to:         The ID string of the ending structure. 
 54          @type id_to:            str 
 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 id_from in self._translation_vector: 
 65              self._translation_vector[id_from] = {} 
 66          if not id_from in self._translation_distance: 
 67              self._translation_distance[id_from] = {} 
 68          if not id_from in self._rotation_matrix: 
 69              self._rotation_matrix[id_from] = {} 
 70          if not id_from in self._rotation_axis: 
 71              self._rotation_axis[id_from] = {} 
 72          if not id_from in self._rotation_angle: 
 73              self._rotation_angle[id_from] = {} 
 74   
 75           
 76          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) 
 77   
 78           
 79          self._translation_vector[id_from][id_to] = trans_vect 
 80          self._translation_distance[id_from][id_to] = trans_dist 
 81          self._rotation_matrix[id_from][id_to] = R 
 82          self._rotation_axis[id_from][id_to] = axis 
 83          self._rotation_angle[id_from][id_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              id_from = str(pair_node.getAttribute('id_from')) 
104              id_to = str(pair_node.getAttribute('id_to')) 
105   
106               
107              if not id_from in self._translation_vector: 
108                  self._translation_vector[id_from] = {} 
109              if not id_from in self._translation_distance: 
110                  self._translation_distance[id_from] = {} 
111              if not id_from in self._rotation_matrix: 
112                  self._rotation_matrix[id_from] = {} 
113              if not id_from in self._rotation_axis: 
114                  self._rotation_axis[id_from] = {} 
115              if not id_from in self._rotation_angle: 
116                  self._rotation_angle[id_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[id_from][id_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 id_from in start_models: 
146               
147              end_models = sorted(self._translation_vector[id_from].keys()) 
148              for id_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' % (id_from, id_to)) 
155                  pair_element.setAttribute('id_from', id_from) 
156                  pair_element.setAttribute('id_to', id_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])[id_from][id_to] 
175   
176                       
177                      object_to_xml(doc, sub_elem, value=subobj) 
  178