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 interatomic data containers of the relax data store."""
25
26
27 from binascii import hexlify
28 from os import urandom
29 from re import match
30
31
32 from data_store.prototype import Prototype
33 from lib.errors import RelaxFromXMLNotEmptyError, RelaxImplementError
34 from lib.text.table import format_table
35 from lib.xml import fill_object_contents, object_to_xml, xml_to_object
36 import specific_analyses
37
38
40 """Class containing the interatomic data."""
41
42 - def __init__(self, spin_id1=None, spin_id2=None, spin_hash1=None, spin_hash2=None, select=True):
43 """Set up the objects of the interatomic data container.
44
45 @keyword spin_id1: The spin ID string of the first atom.
46 @type spin_id1: str
47 @keyword spin_id2: The spin ID string of the second atom.
48 @type spin_id2: str
49 @keyword spin_hash1: The unique and temporary hash identifying the spin container of the first atom.
50 @type spin_hash1: str
51 @keyword spin_hash2: The unique and temporary hash identifying the spin container of the second atom.
52 @type spin_hash2: str
53 @keyword select: The selection flag.
54 @type select: bool
55 """
56
57
58 self.spin_id1 = spin_id1
59 self.spin_id2 = spin_id2
60 self._spin_hash1 = spin_hash1
61 self._spin_hash2 = spin_hash2
62
63
64 self.dipole_pair = False
65 self.select = select
66
67
68 self._generate_hash()
69
70
72 """The string representation of the object.
73
74 Rather than using the standard Python conventions (either the string representation of the
75 value or the "<...desc...>" notation), a rich-formatted description of the object is given.
76 """
77
78
79 text = "Class containing all the interatomic specific data between spins %s and %s.\n\n" % (self.spin_id1, self.spin_id2)
80
81
82 text = text + "\n"
83 text = text + "Objects:\n"
84 for name in dir(self):
85
86 if name in ['is_empty']:
87 continue
88
89
90 if name not in ['_spin_hash1', '_spin_hash2'] and match("^_", name):
91 continue
92
93
94 text += " %s: %s\n" % (name, repr(getattr(self, name)))
95
96 return text
97
98
100 """Generate a unique hash for the interatomic data container."""
101
102
103 self._hash = hexlify(urandom(20))
104
105
107 """Method for testing if this InteratomContainer object is empty.
108
109 @return: True if this container is empty, False otherwise.
110 @rtype: bool
111 """
112
113
114 for name in dir(self):
115
116 if name in ['dipole_pair', 'spin_id1', 'spin_id2', 'select']:
117 continue
118
119
120 if name in ['is_empty']:
121 continue
122
123
124 if match("^_", name):
125 continue
126
127
128 return False
129
130
131 return True
132
133
134
136 """List type data container for interatomic specific data."""
137
139 """The string representation of the object.
140
141 Rather than using the standard Python conventions (either the string representation of the value or the "<...desc...>" notation), a rich-formatted description of the object is given.
142 """
143
144
145 text = "Interatomic data container list:\n"
146
147
148 table = []
149 for i in range(len(self)):
150 table.append([i, self[i]._hash, self[i].spin_id1, self[i].spin_id2, self[i]._spin_hash1, self[i]._spin_hash2])
151 text += format_table(headings=[["Index", "Hash", "Spin ID 1", "Spin ID 2", "Spin hash 1", "Spin hash 2"]], contents=table)
152
153 return text
154
155
156 - def add_item(self, spin_id1=None, spin_id2=None, spin_hash1=None, spin_hash2=None):
157 """Append an empty container to the list.
158
159 @keyword spin_id1: The spin ID string of the first atom.
160 @type spin_id1: str
161 @keyword spin_id2: The spin ID string of the second atom.
162 @type spin_id2: str
163 @keyword spin_hash1: The unique and temporary hash identifying the spin container of the first atom.
164 @type spin_hash1: str
165 @keyword spin_hash2: The unique and temporary hash identifying the spin container of the second atom.
166 @type spin_hash2: str
167 @return: The new interatomic data container.
168 @rtype: InteratomContainer instance
169 """
170
171
172 cont = InteratomContainer(spin_id1, spin_id2, spin_hash1, spin_hash2)
173 self.append(cont)
174
175
176 return cont
177
178
180 """Method for testing if this InteratomList object is empty.
181
182 @return: True if this list contains no InteratomContainers, False otherwise.
183 @rtype: bool
184 """
185
186
187 if len(self) == 0:
188 return True
189
190
191 return False
192
193
194 - def from_xml(self, interatom_nodes, file_version=None):
195 """Recreate an interatomic list data structure from the XML spin nodes.
196
197 @param interatom_nodes: The spin XML nodes.
198 @type interatom_nodes: xml.dom.minicompat.NodeList instance
199 @keyword file_version: The relax XML version of the XML file.
200 @type file_version: int
201 """
202
203
204 if not self.is_empty():
205 raise RelaxFromXMLNotEmptyError(self.__class__.__name__)
206
207
208 for interatom_node in interatom_nodes:
209
210 spin_id1 = str(interatom_node.getAttribute('spin_id1'))
211 spin_id2 = str(interatom_node.getAttribute('spin_id2'))
212 self.add_item(spin_id1=spin_id1, spin_id2=spin_id2)
213
214
215 xml_to_object(interatom_node, self[-1], file_version=file_version)
216
217
218 - def to_xml(self, doc, element, pipe_type=None):
219 """Create XML elements for each spin.
220
221 @param doc: The XML document object.
222 @type doc: xml.dom.minidom.Document instance
223 @param element: The element to add the spin XML elements to.
224 @type element: XML element object
225 @keyword pipe_type: The type of the pipe being converted to XML.
226 @type pipe_type: str
227 """
228
229
230 api = specific_analyses.api.return_api(analysis_type=pipe_type)
231
232
233 for i in range(len(self)):
234
235 interatom_element = doc.createElement('interatomic')
236 element.appendChild(interatom_element)
237
238
239 interatom_element.setAttribute('desc', 'Interatomic data container')
240 interatom_element.setAttribute('spin_id1', str(self[i].spin_id1))
241 interatom_element.setAttribute('spin_id2', str(self[i].spin_id2))
242
243
244 object_info = []
245 try:
246 for name in api.data_names(error_names=True, sim_names=True):
247
248 if hasattr(api, 'return_data_desc'):
249 desc = api.return_data_desc(name)
250 else:
251 desc = None
252
253
254 object_info.append([name, desc])
255 except RelaxImplementError:
256 pass
257
258
259 blacklist = []
260 for name, desc in object_info:
261
262 blacklist.append(name)
263
264
265 if not hasattr(self[i], name):
266 continue
267
268
269 sub_element = doc.createElement(name)
270 interatom_element.appendChild(sub_element)
271
272
273 if desc:
274 sub_element.setAttribute('desc', desc)
275
276
277 object = getattr(self[i], name)
278
279
280 object_to_xml(doc, sub_element, value=object)
281
282
283 fill_object_contents(doc, interatom_element, object=self[i], blacklist=['spin_id1', 'spin_id2'] + blacklist + list(self[i].__class__.__dict__.keys()))
284