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 molecule-residue-spin containers."""
25
26
27 import numpy
28 from re import match
29 from string import lower
30
31
32 from float import floatAsByteArray
33 import generic_fns
34 from prototype import Prototype
35 from relax_errors import RelaxError, RelaxFromXMLNotEmptyError, RelaxImplementError
36 from relax_xml import fill_object_contents, xml_to_object
37 import specific_fns
38
39
40
41
42
44 """Class containing all the spin system specific data."""
45
46 - def __init__(self, spin_name=None, spin_num=None, select=True):
47 """Set up the default objects of the spin system data container."""
48
49
50 self.name = spin_name
51 self.num = spin_num
52 self.select = select
53
54
56 """The string representation of the object.
57
58 Rather than using the standard Python conventions (either the string representation of the
59 value or the "<...desc...>" notation), a rich-formatted description of the object is given.
60 """
61
62
63 text = "Class containing all the spin system specific data.\n\n"
64
65
66 text = text + "\n"
67 text = text + "Objects:\n"
68 for name in dir(self):
69
70 if name == 'is_empty':
71 continue
72
73
74 if match("^_", name):
75 continue
76
77
78 text = text + " " + name + ": " + repr(getattr(self, name)) + "\n"
79
80 return text
81
82
84 """Method for converting old spin data structures to the new ones.
85
86 @keyword file_version: The relax version used to create the XML file.
87 @type file_version: str
88 """
89
90
91 self._back_compat_hook_mf_data()
92
93
94 self._back_compat_hook_ri_data()
95
96
98 """Converting the old model-free parameter vector to the new one."""
99
100
101 if not hasattr(self, 'params'):
102 return
103
104
105 for i in range(len(self.params)):
106 self.params[i] = lower(self.params[i])
107
108
110 """Converting the old spin relaxation data structures to the new ones."""
111
112
113 if not (hasattr(self, 'frq_labels') and hasattr(self, 'noe_r1_table') and hasattr(self, 'remap_table')):
114 return
115
116
117 self.ri_data = {}
118 self.ri_data_err = {}
119 sims = False
120 if hasattr(self, 'relax_sim_data'):
121 sims = True
122 self.ri_data_sim = {}
123
124
125 for i in range(self.num_ri):
126
127 ri_id = "%s_%s" % (self.ri_labels[i], self.frq_labels[self.remap_table[i]])
128
129
130 self.ri_data[ri_id] = self.relax_data[i]
131 self.ri_data_err[ri_id] = self.relax_error[i]
132
133
134 if sims:
135 self.ri_data_sim[ri_id] = []
136 for j in range(cdp.sim_number):
137 self.ri_data_sim[ri_id].append(self.relax_sim_data[j][i])
138
139
140
141 del self.frq
142 del self.frq_labels
143 del self.noe_r1_table
144 del self.num_frq
145 del self.num_ri
146 del self.ri_labels
147 del self.remap_table
148 del self.relax_data
149 del self.relax_error
150 if sims:
151 del self.relax_sim_data
152
153
155 """Method for testing if this SpinContainer object is empty.
156
157 @return: True if this container is empty and the spin number and name have not been set,
158 False otherwise.
159 @rtype: bool
160 """
161
162
163 if self.num != None or self.name != None:
164 return False
165
166
167 for name in dir(self):
168
169 if name == 'num' or name == 'name' or name == 'select':
170 continue
171
172
173 if name == 'is_empty':
174 continue
175
176
177 if match("^_", name):
178 continue
179
180
181 return False
182
183
184 return True
185
186
188 """List type data container for spin system specific data."""
189
191 """Set up the first spin system data container."""
192
193
194 self.append(SpinContainer())
195
196
198 """The string representation of the object.
199
200 Rather than using the standard Python conventions (either the string representation of the
201 value or the "<...desc...>" notation), a rich-formatted description of the object is given.
202 """
203
204
205 text = "Spin systems.\n\n"
206
207
208 text = text + "%-8s%-8s%-8s%-10s" % ("Index", "Number", "Name", "Selected") + "\n"
209 for i in xrange(len(self)):
210 text = text + "%-8i%-8s%-8s%-10s" % (i, repr(self[i].num), self[i].name, self[i].select) + "\n"
211 text = text + "\nThese can be accessed by typing 'D.mol[i].res[j].spin[k]', where D is the relax data storage object.\n"
212
213 return text
214
215
216 - def add_item(self, spin_name=None, spin_num=None, select=True):
217 """Function for appending an empty container to the list."""
218
219
220 if self.is_empty():
221 self[0].num = spin_num
222 self[0].name = spin_name
223 self[0].select = select
224
225
226 else:
227
228 for i in xrange(len(self)):
229
230 if spin_num != None:
231 if self[i].num == spin_num:
232 raise RelaxError("The spin number '" + repr(spin_num) + "' already exists.")
233
234
235 else:
236 if self[i].name == spin_name:
237 raise RelaxError("The unnumbered spin name '" + repr(spin_name) + "' already exists.")
238
239
240 self.append(SpinContainer(spin_name, spin_num, select))
241
242
244 """Method for testing if this SpinList object is empty.
245
246 @return: True if this list only has one SpinContainer and the spin number and name have
247 not been set, False otherwise.
248 @rtype: bool
249 """
250
251
252 if len(self) == 1 and self[0].is_empty():
253 return True
254
255
256 return False
257
258
259 - def from_xml(self, spin_nodes, file_version=None):
260 """Recreate a spin list data structure from the XML spin nodes.
261
262 @param spin_nodes: The spin XML nodes.
263 @type spin_nodes: xml.dom.minicompat.NodeList instance
264 @keyword file_version: The relax version used to create the XML file.
265 @type file_version: str
266 """
267
268
269 if not self.is_empty():
270 raise RelaxFromXMLNotEmptyError(self.__class__.__name__)
271
272
273 for spin_node in spin_nodes:
274
275 name = str(spin_node.getAttribute('name'))
276 if name == 'None':
277 name = None
278 num = eval(spin_node.getAttribute('num'))
279 self.add_item(spin_name=name, spin_num=num)
280
281
282 xml_to_object(spin_node, self[-1])
283
284
285 self[-1]._back_compat_hook(file_version)
286
287
288 - def to_xml(self, doc, element):
289 """Create XML elements for each spin.
290
291 @param doc: The XML document object.
292 @type doc: xml.dom.minidom.Document instance
293 @param element: The element to add the spin XML elements to.
294 @type element: XML element object
295 """
296
297
298 data_names = specific_fns.setup.get_specific_fn('data_names', generic_fns.pipes.get_type(), raise_error=False)
299 return_data_desc = specific_fns.setup.get_specific_fn('return_data_desc', generic_fns.pipes.get_type(), raise_error=False)
300
301
302 for i in xrange(len(self)):
303
304 spin_element = doc.createElement('spin')
305 element.appendChild(spin_element)
306
307
308 spin_element.setAttribute('desc', 'Spin container')
309 spin_element.setAttribute('name', str(self[i].name))
310 spin_element.setAttribute('num', str(self[i].num))
311
312
313 object_info = []
314 try:
315 for name in data_names(error_names=True, sim_names=True):
316
317 if return_data_desc:
318 desc = return_data_desc(name)
319 else:
320 desc = None
321
322
323 object_info.append([name, desc])
324 except RelaxImplementError:
325 pass
326
327
328 blacklist = []
329 for name, desc in object_info:
330
331 blacklist.append(name)
332
333
334 if not hasattr(self[i], name):
335 continue
336
337
338 sub_element = doc.createElement(name)
339 spin_element.appendChild(sub_element)
340
341
342 if desc:
343 sub_element.setAttribute('desc', desc)
344
345
346 object = getattr(self[i], name)
347
348
349 if isinstance(object, float) or isinstance(object, numpy.float64):
350 sub_element.setAttribute('ieee_754_byte_array', repr(floatAsByteArray(object)))
351
352
353 text_val = doc.createTextNode(repr(object))
354 sub_element.appendChild(text_val)
355
356
357 fill_object_contents(doc, spin_element, object=self[i], blacklist=['name', 'num', 'spin'] + blacklist + list(self[i].__class__.__dict__.keys()))
358
359
360
361
362
363
365 """Class containing all the residue specific data."""
366
367 - def __init__(self, res_name=None, res_num=None):
368 """Set up the default objects of the residue data container."""
369
370
371 self.name = res_name
372 self.num = res_num
373
374
375 self.spin = SpinList()
376
377
379 """The string representation of the object.
380
381 Rather than using the standard Python conventions (either the string representation of the
382 value or the "<...desc...>" notation), a rich-formatted description of the object is given.
383 """
384
385
386 text = "Class containing all the residue specific data.\n"
387
388
389 text = text + "\n"
390 text = text + "Objects:\n"
391 for name in dir(self):
392
393 if name == 'spin':
394 text = text + " spin: The list of spin systems of the residues\n"
395 continue
396
397
398 if name == 'is_empty':
399 continue
400
401
402 if match("^_", name):
403 continue
404
405
406 text = text + " " + name + ": " + repr(getattr(self, name)) + "\n"
407
408 return text
409
410
412 """Method for testing if this ResidueContainer object is empty.
413
414 @return: True if this container is empty and the residue number and name have not been
415 set, False otherwise.
416 @rtype: bool
417 """
418
419
420 if self.num != None or self.name != None:
421 return False
422
423
424 for name in dir(self):
425
426 if name == 'num' or name == 'name' or name == 'spin':
427 continue
428
429
430 if name == 'is_empty':
431 continue
432
433
434 if match("^_", name):
435 continue
436
437
438 return False
439
440
441 if not self.spin.is_empty():
442 return False
443
444
445 return True
446
447
449 """List type data container for residue specific data."""
450
456
457
459 """The string representation of the object.
460
461 Rather than using the standard Python conventions (either the string representation of the
462 value or the "<...desc...>" notation), a rich-formatted description of the object is given.
463 """
464
465
466 text = "Residues.\n\n"
467
468
469 text = text + "%-8s%-8s%-8s" % ("Index", "Number", "Name") + "\n"
470 for i in xrange(len(self)):
471 text = text + "%-8i%-8s%-8s" % (i, repr(self[i].num), self[i].name) + "\n"
472 text = text + "\nThese can be accessed by typing 'D.mol[i].res[j]', where D is the relax data storage object.\n"
473
474 return text
475
476
477 - def add_item(self, res_name=None, res_num=None):
478 """Append an empty ResidueContainer to the ResidueList."""
479
480
481 if self.is_empty():
482 self[0].num = res_num
483 self[0].name = res_name
484
485
486 else:
487
488 for i in xrange(len(self)):
489
490 if res_num != None:
491 if self[i].num == res_num:
492 raise RelaxError("The residue number '" + repr(res_num) + "' already exists in the sequence.")
493
494
495 else:
496 if self[i].name == res_name:
497 raise RelaxError("The unnumbered residue name '" + repr(res_name) + "' already exists.")
498
499
500 self.append(ResidueContainer(res_name, res_num))
501
502
504 """Method for testing if this ResidueList object is empty.
505
506 @return: True if this list only has one ResidueContainer and the residue number and name
507 have not been set, False otherwise.
508 @rtype: bool
509 """
510
511
512 if len(self) == 1 and self[0].is_empty():
513 return True
514
515
516 return False
517
518
519 - def from_xml(self, res_nodes, file_version=None):
520 """Recreate a residue list data structure from the XML residue nodes.
521
522 @param res_nodes: The residue XML nodes.
523 @type res_nodes: xml.dom.minicompat.NodeList instance
524 @keyword file_version: The relax version used to create the XML file.
525 @type file_version: str
526 """
527
528
529 if not self.is_empty():
530 raise RelaxFromXMLNotEmptyError(self.__class__.__name__)
531
532
533 for res_node in res_nodes:
534
535 name = str(res_node.getAttribute('name'))
536 if name == 'None':
537 name = None
538 num = eval(res_node.getAttribute('num'))
539 self.add_item(res_name=name, res_num=num)
540
541
542 spin_nodes = res_node.getElementsByTagName('spin')
543
544
545 self[-1].spin.from_xml(spin_nodes, file_version=file_version)
546
547
548 - def to_xml(self, doc, element):
549 """Create XML elements for each residue.
550
551 @param doc: The XML document object.
552 @type doc: xml.dom.minidom.Document instance
553 @param element: The element to add the residue XML elements to.
554 @type element: XML element object
555 """
556
557
558 for i in xrange(len(self)):
559
560 res_element = doc.createElement('res')
561 element.appendChild(res_element)
562
563
564 res_element.setAttribute('desc', 'Residue container')
565 res_element.setAttribute('name', str(self[i].name))
566 res_element.setAttribute('num', str(self[i].num))
567
568
569 fill_object_contents(doc, res_element, object=self[i], blacklist=['name', 'num', 'spin'] + list(self[i].__class__.__dict__.keys()))
570
571
572 self[i].spin.to_xml(doc, res_element)
573
574
575
576
577
578
580 """Class containing all the molecule specific data."""
581
582 - def __init__(self, mol_name=None, mol_type=None):
583 """Set up the default objects of the molecule data container."""
584
585
586 self.name = mol_name
587
588
589 self.type = mol_type
590
591
592 self.res = ResidueList()
593
594
596 """The string representation of the object.
597
598 Rather than using the standard Python conventions (either the string representation of the
599 value or the "<...desc...>" notation), a rich-formatted description of the object is given.
600 """
601
602
603 text = "Class containing all the molecule specific data.\n"
604
605
606 text = text + "\n"
607 text = text + "Objects:\n"
608 for name in dir(self):
609
610 if name == 'res':
611 text = text + " res: The list of the residues of the molecule\n"
612 continue
613
614
615 if name == 'is_empty':
616 continue
617
618
619 if match("^_", name):
620 continue
621
622
623 text = text + " " + name + ": " + repr(getattr(self, name)) + "\n"
624
625 return text
626
627
629 """Method for testing if this MoleculeContainer object is empty.
630
631 @return: True if this container is empty and the molecule name has not been set, False
632 otherwise.
633 @rtype: bool
634 """
635
636
637 if self.name != None:
638 return False
639
640
641 for name in dir(self):
642
643 if name in ['name', 'res', 'type']:
644 continue
645
646
647 if name == 'is_empty':
648 continue
649
650
651 if match("^_", name):
652 continue
653
654
655 return False
656
657
658 if not self.res.is_empty():
659 return False
660
661
662 return True
663
664
666 """List type data container for the molecule specific data."""
667
673
674
676 """The string representation of the object.
677
678 Rather than using the standard Python conventions (either the string representation of the
679 value or the "<...desc...>" notation), a rich-formatted description of the object is given.
680 """
681
682 text = "Molecules.\n\n"
683 text = text + "%-8s%-8s" % ("Index", "Name") + "\n"
684 for i in xrange(len(self)):
685 text = text + "%-8i%-8s" % (i, self[i].name) + "\n"
686 text = text + "\nThese can be accessed by typing 'D.mol[i]', where D is the relax data storage object.\n"
687 return text
688
689
690 - def add_item(self, mol_name=None, mol_type=None):
691 """Append an empty MoleculeContainer to the MoleculeList."""
692
693
694 if self.is_empty():
695 self[0].name = mol_name
696 self[0].type = mol_type
697
698
699 else:
700
701 for i in xrange(len(self)):
702 if self[i].name == mol_name:
703 raise RelaxError("The molecule '%s' already exists in the sequence." % mol_name)
704
705
706 self.append(MoleculeContainer(mol_name, mol_type))
707
708
710 """Method for testing if this MoleculeList object is empty.
711
712 @return: True if this list only has one MoleculeContainer and the molecule name has not
713 been set, False otherwise.
714 @rtype: bool
715 """
716
717
718 if len(self) == 1 and self[0].is_empty():
719 return True
720
721
722 return False
723
724
725 - def from_xml(self, mol_nodes, file_version=None):
726 """Recreate a molecule list data structure from the XML molecule nodes.
727
728 @param mol_nodes: The molecule XML nodes.
729 @type mol_nodes: xml.dom.minicompat.NodeList instance
730 @keyword file_version: The relax version used to create the XML file.
731 @type file_version: str
732 """
733
734
735 if not self.is_empty():
736 raise RelaxFromXMLNotEmptyError(self.__class__.__name__)
737
738
739 for mol_node in mol_nodes:
740
741 name = mol_node.getAttribute('name')
742 if name == 'None':
743 name = None
744 type = mol_node.getAttribute('type')
745 if type == 'None':
746 type = None
747 self.add_item(mol_name=name, mol_type=type)
748
749
750 res_nodes = mol_node.getElementsByTagName('res')
751
752
753 self[-1].res.from_xml(res_nodes, file_version=file_version)
754
755
756 - def to_xml(self, doc, element):
757 """Create XML elements for each molecule.
758
759 @param doc: The XML document object.
760 @type doc: xml.dom.minidom.Document instance
761 @param element: The element to add the molecule XML elements to.
762 @type element: XML element object
763 """
764
765
766 for i in xrange(len(self)):
767
768 mol_element = doc.createElement('mol')
769 element.appendChild(mol_element)
770
771
772 mol_element.setAttribute('desc', 'Molecule container')
773 mol_element.setAttribute('name', str(self[i].name))
774 mol_element.setAttribute('type', str(self[i].type))
775
776
777 fill_object_contents(doc, mol_element, object=self[i], blacklist=['name', 'res', 'type'] + list(self[i].__class__.__dict__.keys()))
778
779
780 self[i].res.to_xml(doc, mol_element)
781