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