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 from re import match
27
28
29 from data_store.prototype import Prototype
30 from lib.errors import RelaxError, RelaxFromXMLNotEmptyError, RelaxImplementError
31 from lib.xml import fill_object_contents, object_to_xml, xml_to_object
32 import specific_analyses
33
34
35
36
37
39 """Class containing all the spin system specific data."""
40
41 - def __init__(self, spin_name=None, spin_num=None, select=True):
42 """Set up the default objects of the spin system data container."""
43
44
45 self.name = spin_name
46 self.num = spin_num
47 self.select = select
48
49
50 self._mol_name = None
51 self._mol_index = None
52 self._res_name = None
53 self._res_num = None
54 self._res_index = None
55 self._spin_index = None
56 self._spin_ids = []
57
58
60 """The string representation of the object.
61
62 Rather than using the standard Python conventions (either the string representation of the
63 value or the "<...desc...>" notation), a rich-formatted description of the object is given.
64 """
65
66
67 text = "Class containing all the spin system specific data.\n\n"
68
69
70 text = text + "\n"
71 text = text + "Objects:\n"
72 for name in dir(self):
73
74 if name == 'is_empty':
75 continue
76
77
78 if match("^_", name):
79 continue
80
81
82 text = text + " " + name + ": " + repr(getattr(self, name)) + "\n"
83
84 return text
85
86
88 """Method for converting old spin data structures to the new ones.
89
90 @keyword file_version: The relax XML version of the XML file.
91 @type file_version: int
92 """
93
94
95 if hasattr(self, 'equation') and self.equation in ['mf_orig', 'mf_ext', 'mf_ext2']:
96 self._back_compat_hook_mf_data()
97
98
99 self._back_compat_hook_ri_data()
100
101
103 """Converting the old model-free parameter vector to the new one."""
104
105
106 if not hasattr(self, 'params'):
107 return
108
109
110 for i in range(len(self.params)):
111 self.params[i] = self.params[i].lower()
112
113
115 """Converting the old spin relaxation data structures to the new ones."""
116
117
118 if not (hasattr(self, 'frq_labels') and hasattr(self, 'noe_r1_table') and hasattr(self, 'remap_table')):
119 return
120
121
122 self.ri_data = {}
123 self.ri_data_err = {}
124 sims = False
125 if hasattr(self, 'relax_sim_data'):
126 sims = True
127 self.ri_data_sim = {}
128
129
130 for i in range(self.num_ri):
131
132 ri_id = "%s_%s" % (self.ri_labels[i], self.frq_labels[self.remap_table[i]])
133
134
135 self.ri_data[ri_id] = self.relax_data[i]
136 self.ri_data_err[ri_id] = self.relax_error[i]
137
138
139 if sims:
140 self.ri_data_sim[ri_id] = []
141 for j in range(cdp.sim_number):
142 self.ri_data_sim[ri_id].append(self.relax_sim_data[j][i])
143
144
145 del self.frq
146 del self.frq_labels
147 del self.noe_r1_table
148 del self.num_frq
149 del self.num_ri
150 del self.ri_labels
151 del self.remap_table
152 del self.relax_data
153 del self.relax_error
154 if sims:
155 del self.relax_sim_data
156
157
159 """Method for testing if this SpinContainer object is empty.
160
161 @return: True if this container is empty and the spin number and name have not been set,
162 False otherwise.
163 @rtype: bool
164 """
165
166
167 if self.num != None or self.name != None:
168 return False
169
170
171 for name in dir(self):
172
173 if name == 'num' or name == 'name' or name == 'select':
174 continue
175
176
177 if name == 'is_empty':
178 continue
179
180
181 if match("^_", name):
182 continue
183
184
185 return False
186
187
188 return True
189
190
192 """List type data container for spin system specific data."""
193
195 """Set up the first spin system data container."""
196
197
198 self.append(SpinContainer())
199
200
202 """The string representation of the object.
203
204 Rather than using the standard Python conventions (either the string representation of the
205 value or the "<...desc...>" notation), a rich-formatted description of the object is given.
206 """
207
208
209 text = "Spin systems.\n\n"
210
211
212 text = text + "%-8s%-8s%-8s%-10s" % ("Index", "Number", "Name", "Selected") + "\n"
213 for i in range(len(self)):
214 text = text + "%-8i%-8s%-8s%-10s" % (i, repr(self[i].num), self[i].name, self[i].select) + "\n"
215 text = text + "\nThese can be accessed by typing 'D.mol[i].res[j].spin[k]', where D is the relax data storage object.\n"
216
217 return text
218
219
220 - def add_item(self, spin_name=None, spin_num=None, select=True):
221 """Appending an empty container to the list.
222
223 @keyword spin_name: The name of the new spin.
224 @type spin_name: str or None
225 @keyword spin_num: The number of the new spin.
226 @type spin_num: str or None
227 @keyword select: The selection flag.
228 @type select: bool
229 @return: The new container.
230 @rtype: SpinContainer instance
231 """
232
233
234 if self.is_empty():
235 self[0].num = spin_num
236 self[0].name = spin_name
237 self[0].select = select
238
239
240 return self[0]
241
242
243 else:
244
245 for i in range(len(self)):
246
247 if spin_num != None and spin_name != None:
248 if self[i].num == spin_num and self[i].name == spin_name:
249 raise RelaxError("The spin with name '%s' and number '%s' already exists." % (spin_name, spin_num))
250
251
252 if spin_num == None and self[i].name == spin_name:
253 raise RelaxError("The unnumbered spin name '%s' already exists." % spin_name)
254
255
256 self.append(SpinContainer(spin_name, spin_num, select))
257
258
259 return self[-1]
260
261
263 """Method for testing if this SpinList object is empty.
264
265 @return: True if this list only has one SpinContainer and the spin number and name have
266 not been set, False otherwise.
267 @rtype: bool
268 """
269
270
271 if len(self) == 1 and self[0].is_empty():
272 return True
273
274
275 return False
276
277
278 - def from_xml(self, spin_nodes, file_version=None):
279 """Recreate a spin list data structure from the XML spin nodes.
280
281 @param spin_nodes: The spin XML nodes.
282 @type spin_nodes: xml.dom.minicompat.NodeList instance
283 @keyword file_version: The relax XML version of the XML file.
284 @type file_version: int
285 """
286
287
288 if not self.is_empty():
289 raise RelaxFromXMLNotEmptyError(self.__class__.__name__)
290
291
292 for spin_node in spin_nodes:
293
294 name = str(spin_node.getAttribute('name'))
295 if name == 'None':
296 name = None
297 num = eval(spin_node.getAttribute('num'))
298 self.add_item(spin_name=name, spin_num=num)
299
300
301 xml_to_object(spin_node, self[-1], file_version=file_version)
302
303
304 self[-1]._back_compat_hook(file_version)
305
306
307 - def to_xml(self, doc, element, pipe_type=None):
308 """Create XML elements for each spin.
309
310 @param doc: The XML document object.
311 @type doc: xml.dom.minidom.Document instance
312 @param element: The element to add the spin XML elements to.
313 @type element: XML element object
314 @keyword pipe_type: The type of the pipe being converted to XML.
315 @type pipe_type: str
316 """
317
318
319 api = specific_analyses.api.return_api(analysis_type=pipe_type)
320
321
322 for i in range(len(self)):
323
324 spin_element = doc.createElement('spin')
325 element.appendChild(spin_element)
326
327
328 spin_element.setAttribute('desc', 'Spin container')
329 spin_element.setAttribute('name', str(self[i].name))
330 spin_element.setAttribute('num', str(self[i].num))
331
332
333 object_info = []
334 try:
335 for name in api.data_names(error_names=True, sim_names=True):
336
337 if hasattr(api, 'return_data_desc'):
338 desc = api.return_data_desc(name)
339 else:
340 desc = None
341
342
343 object_info.append([name, desc])
344 except RelaxImplementError:
345 pass
346
347
348 blacklist = []
349 for name, desc in object_info:
350
351 blacklist.append(name)
352
353
354 if not hasattr(self[i], name):
355 continue
356
357
358 sub_element = doc.createElement(name)
359 spin_element.appendChild(sub_element)
360
361
362 if desc:
363 sub_element.setAttribute('desc', desc)
364
365
366 object = getattr(self[i], name)
367
368
369 object_to_xml(doc, sub_element, value=object)
370
371
372 fill_object_contents(doc, spin_element, object=self[i], blacklist=['name', 'num', 'spin'] + blacklist + list(self[i].__class__.__dict__.keys()))
373
374
375
376
377
378
380 """Class containing all the residue specific data."""
381
382 - def __init__(self, res_name=None, res_num=None):
383 """Set up the default objects of the residue data container."""
384
385
386 self.name = res_name
387 self.num = res_num
388
389
390 self._mol_name = None
391 self._mol_index = None
392 self._res_index = None
393
394
395 self.spin = SpinList()
396
397
399 """The string representation of the object.
400
401 Rather than using the standard Python conventions (either the string representation of the
402 value or the "<...desc...>" notation), a rich-formatted description of the object is given.
403 """
404
405
406 text = "Class containing all the residue specific data.\n"
407
408
409 text = text + "\n"
410 text = text + "Objects:\n"
411 for name in dir(self):
412
413 if name == 'spin':
414 text = text + " spin: The list of spin systems of the residues\n"
415 continue
416
417
418 if name == 'is_empty':
419 continue
420
421
422 if match("^_", name):
423 continue
424
425
426 text = text + " " + name + ": " + repr(getattr(self, name)) + "\n"
427
428 return text
429
430
432 """Method for testing if this ResidueContainer object is empty.
433
434 @return: True if this container is empty and the residue number and name have not been
435 set, False otherwise.
436 @rtype: bool
437 """
438
439
440 if self.num != None or self.name != None:
441 return False
442
443
444 for name in dir(self):
445
446 if name == 'num' or name == 'name' or name == 'spin':
447 continue
448
449
450 if name == 'is_empty':
451 continue
452
453
454 if match("^_", name):
455 continue
456
457
458 return False
459
460
461 if not self.spin.is_empty():
462 return False
463
464
465 return True
466
467
469 """List type data container for residue specific data."""
470
476
477
479 """The string representation of the object.
480
481 Rather than using the standard Python conventions (either the string representation of the
482 value or the "<...desc...>" notation), a rich-formatted description of the object is given.
483 """
484
485
486 text = "Residues.\n\n"
487
488
489 text = text + "%-8s%-8s%-8s" % ("Index", "Number", "Name") + "\n"
490 for i in range(len(self)):
491 text = text + "%-8i%-8s%-8s" % (i, repr(self[i].num), self[i].name) + "\n"
492 text = text + "\nThese can be accessed by typing 'D.mol[i].res[j]', where D is the relax data storage object.\n"
493
494 return text
495
496
497 - def add_item(self, res_name=None, res_num=None):
498 """Append an empty ResidueContainer to the ResidueList."""
499
500
501 if self.is_empty():
502 self[0].num = res_num
503 self[0].name = res_name
504
505
506 else:
507
508 for i in range(len(self)):
509
510 if res_num != None:
511 if self[i].num == res_num:
512 raise RelaxError("The residue number '" + repr(res_num) + "' already exists in the sequence.")
513
514
515 else:
516 if self[i].name == res_name:
517 raise RelaxError("The unnumbered residue name '" + repr(res_name) + "' already exists.")
518
519
520 self.append(ResidueContainer(res_name, res_num))
521
522
524 """Method for testing if this ResidueList object is empty.
525
526 @return: True if this list only has one ResidueContainer and the residue number and name
527 have not been set, False otherwise.
528 @rtype: bool
529 """
530
531
532 if len(self) == 1 and self[0].is_empty():
533 return True
534
535
536 return False
537
538
539 - def from_xml(self, res_nodes, file_version=None):
540 """Recreate a residue list data structure from the XML residue nodes.
541
542 @param res_nodes: The residue XML nodes.
543 @type res_nodes: xml.dom.minicompat.NodeList instance
544 @keyword file_version: The relax XML version of the XML file.
545 @type file_version: int
546 """
547
548
549 if not self.is_empty():
550 raise RelaxFromXMLNotEmptyError(self.__class__.__name__)
551
552
553 for res_node in res_nodes:
554
555 name = str(res_node.getAttribute('name'))
556 if name == 'None':
557 name = None
558 num = eval(res_node.getAttribute('num'))
559 self.add_item(res_name=name, res_num=num)
560
561
562 spin_nodes = res_node.getElementsByTagName('spin')
563
564
565 self[-1].spin.from_xml(spin_nodes, file_version=file_version)
566
567
568 - def to_xml(self, doc, element, pipe_type=None):
569 """Create XML elements for each residue.
570
571 @param doc: The XML document object.
572 @type doc: xml.dom.minidom.Document instance
573 @param element: The element to add the residue XML elements to.
574 @type element: XML element object
575 @keyword pipe_type: The type of the pipe being converted to XML.
576 @type pipe_type: str
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, pipe_type=pipe_type)
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, pipe_type=None):
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 @keyword pipe_type: The type of the pipe being converted to XML.
792 @type pipe_type: str
793 """
794
795
796 for i in range(len(self)):
797
798 mol_element = doc.createElement('mol')
799 element.appendChild(mol_element)
800
801
802 mol_element.setAttribute('desc', 'Molecule container')
803 mol_element.setAttribute('name', str(self[i].name))
804 mol_element.setAttribute('type', str(self[i].type))
805
806
807 fill_object_contents(doc, mol_element, object=self[i], blacklist=['name', 'res', 'type'] + list(self[i].__class__.__dict__.keys()))
808
809
810 self[i].res.to_xml(doc, mol_element, pipe_type=pipe_type)
811