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 data_store.relax_xml import fill_object_contents, object_to_xml, xml_to_object
31 import pipe_control
32 from lib.errors import RelaxError, RelaxFromXMLNotEmptyError, RelaxImplementError
33 import specific_analyses
34
35
36
37
38
40 """Class containing all the spin system specific data."""
41
42 - def __init__(self, spin_name=None, spin_num=None, select=True):
43 """Set up the default objects of the spin system data container."""
44
45
46 self.name = spin_name
47 self.num = spin_num
48 self.select = select
49
50
51 self._mol_name = None
52 self._mol_index = None
53 self._res_name = None
54 self._res_num = None
55 self._res_index = None
56 self._spin_index = None
57 self._spin_ids = []
58
59
61 """The string representation of the object.
62
63 Rather than using the standard Python conventions (either the string representation of the
64 value or the "<...desc...>" notation), a rich-formatted description of the object is given.
65 """
66
67
68 text = "Class containing all the spin system specific data.\n\n"
69
70
71 text = text + "\n"
72 text = text + "Objects:\n"
73 for name in dir(self):
74
75 if name == 'is_empty':
76 continue
77
78
79 if match("^_", name):
80 continue
81
82
83 text = text + " " + name + ": " + repr(getattr(self, name)) + "\n"
84
85 return text
86
87
89 """Method for converting old spin data structures to the new ones.
90
91 @keyword file_version: The relax XML version of the XML file.
92 @type file_version: int
93 """
94
95
96 if hasattr(self, 'equation') and self.equation in ['mf_orig', 'mf_ext', 'mf_ext2']:
97 self._back_compat_hook_mf_data()
98
99
100 self._back_compat_hook_ri_data()
101
102
104 """Converting the old model-free parameter vector to the new one."""
105
106
107 if not hasattr(self, 'params'):
108 return
109
110
111 for i in range(len(self.params)):
112 self.params[i] = self.params[i].lower()
113
114
116 """Converting the old spin relaxation data structures to the new ones."""
117
118
119 if not (hasattr(self, 'frq_labels') and hasattr(self, 'noe_r1_table') and hasattr(self, 'remap_table')):
120 return
121
122
123 self.ri_data = {}
124 self.ri_data_err = {}
125 sims = False
126 if hasattr(self, 'relax_sim_data'):
127 sims = True
128 self.ri_data_sim = {}
129
130
131 for i in range(self.num_ri):
132
133 ri_id = "%s_%s" % (self.ri_labels[i], self.frq_labels[self.remap_table[i]])
134
135
136 self.ri_data[ri_id] = self.relax_data[i]
137 self.ri_data_err[ri_id] = self.relax_error[i]
138
139
140 if sims:
141 self.ri_data_sim[ri_id] = []
142 for j in range(cdp.sim_number):
143 self.ri_data_sim[ri_id].append(self.relax_sim_data[j][i])
144
145
146 del self.frq
147 del self.frq_labels
148 del self.noe_r1_table
149 del self.num_frq
150 del self.num_ri
151 del self.ri_labels
152 del self.remap_table
153 del self.relax_data
154 del self.relax_error
155 if sims:
156 del self.relax_sim_data
157
158
160 """Method for testing if this SpinContainer object is empty.
161
162 @return: True if this container is empty and the spin number and name have not been set,
163 False otherwise.
164 @rtype: bool
165 """
166
167
168 if self.num != None or self.name != None:
169 return False
170
171
172 for name in dir(self):
173
174 if name == 'num' or name == 'name' or name == 'select':
175 continue
176
177
178 if name == 'is_empty':
179 continue
180
181
182 if match("^_", name):
183 continue
184
185
186 return False
187
188
189 return True
190
191
193 """List type data container for spin system specific data."""
194
196 """Set up the first spin system data container."""
197
198
199 self.append(SpinContainer())
200
201
203 """The string representation of the object.
204
205 Rather than using the standard Python conventions (either the string representation of the
206 value or the "<...desc...>" notation), a rich-formatted description of the object is given.
207 """
208
209
210 text = "Spin systems.\n\n"
211
212
213 text = text + "%-8s%-8s%-8s%-10s" % ("Index", "Number", "Name", "Selected") + "\n"
214 for i in range(len(self)):
215 text = text + "%-8i%-8s%-8s%-10s" % (i, repr(self[i].num), self[i].name, self[i].select) + "\n"
216 text = text + "\nThese can be accessed by typing 'D.mol[i].res[j].spin[k]', where D is the relax data storage object.\n"
217
218 return text
219
220
221 - def add_item(self, spin_name=None, spin_num=None, select=True):
222 """Appending an empty container to the list.
223
224 @keyword spin_name: The name of the new spin.
225 @type spin_name: str or None
226 @keyword spin_num: The number of the new spin.
227 @type spin_num: str or None
228 @keyword select: The selection flag.
229 @type select: bool
230 @return: The new container.
231 @rtype: SpinContainer instance
232 """
233
234
235 if self.is_empty():
236 self[0].num = spin_num
237 self[0].name = spin_name
238 self[0].select = select
239
240
241 return self[0]
242
243
244 else:
245
246 for i in range(len(self)):
247
248 if spin_num != None and spin_name != None:
249 if self[i].num == spin_num and self[i].name == spin_name:
250 raise RelaxError("The spin with name '%s' and number '%s' already exists." % (spin_name, spin_num))
251
252
253 if spin_num == None and self[i].name == spin_name:
254 raise RelaxError("The unnumbered spin name '%s' already exists." % spin_name)
255
256
257 self.append(SpinContainer(spin_name, spin_num, select))
258
259
260 return self[-1]
261
262
264 """Method for testing if this SpinList object is empty.
265
266 @return: True if this list only has one SpinContainer and the spin number and name have
267 not been set, False otherwise.
268 @rtype: bool
269 """
270
271
272 if len(self) == 1 and self[0].is_empty():
273 return True
274
275
276 return False
277
278
279 - def from_xml(self, spin_nodes, file_version=None):
280 """Recreate a spin list data structure from the XML spin nodes.
281
282 @param spin_nodes: The spin XML nodes.
283 @type spin_nodes: xml.dom.minicompat.NodeList instance
284 @keyword file_version: The relax XML version of the XML file.
285 @type file_version: int
286 """
287
288
289 if not self.is_empty():
290 raise RelaxFromXMLNotEmptyError(self.__class__.__name__)
291
292
293 for spin_node in spin_nodes:
294
295 name = str(spin_node.getAttribute('name'))
296 if name == 'None':
297 name = None
298 num = eval(spin_node.getAttribute('num'))
299 self.add_item(spin_name=name, spin_num=num)
300
301
302 xml_to_object(spin_node, self[-1], file_version=file_version)
303
304
305 self[-1]._back_compat_hook(file_version)
306
307
308 - def to_xml(self, doc, element):
309 """Create XML elements for each spin.
310
311 @param doc: The XML document object.
312 @type doc: xml.dom.minidom.Document instance
313 @param element: The element to add the spin XML elements to.
314 @type element: XML element object
315 """
316
317
318 data_names = specific_analyses.setup.get_specific_fn('data_names', pipe_control.pipes.get_type(), raise_error=False)
319 return_data_desc = specific_analyses.setup.get_specific_fn('return_data_desc', pipe_control.pipes.get_type(), raise_error=False)
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 data_names(error_names=True, sim_names=True):
336
337 if return_data_desc:
338 desc = 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):
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 """
576
577
578 for i in range(len(self)):
579
580 res_element = doc.createElement('res')
581 element.appendChild(res_element)
582
583
584 res_element.setAttribute('desc', 'Residue container')
585 res_element.setAttribute('name', str(self[i].name))
586 res_element.setAttribute('num', str(self[i].num))
587
588
589 fill_object_contents(doc, res_element, object=self[i], blacklist=['name', 'num', 'spin'] + list(self[i].__class__.__dict__.keys()))
590
591
592 self[i].spin.to_xml(doc, res_element)
593
594
595
596
597
598
600 """Class containing all the molecule specific data."""
601
602 - def __init__(self, mol_name=None, mol_type=None):
603 """Set up the default objects of the molecule data container."""
604
605
606 self.name = mol_name
607
608
609 self.type = mol_type
610
611
612 self._mol_index = None
613
614
615 self.res = ResidueList()
616
617
619 """The string representation of the object.
620
621 Rather than using the standard Python conventions (either the string representation of the
622 value or the "<...desc...>" notation), a rich-formatted description of the object is given.
623 """
624
625
626 text = "Class containing all the molecule specific data.\n"
627
628
629 text = text + "\n"
630 text = text + "Objects:\n"
631 for name in dir(self):
632
633 if name == 'res':
634 text = text + " res: The list of the residues of the molecule\n"
635 continue
636
637
638 if name == 'is_empty':
639 continue
640
641
642 if match("^_", name):
643 continue
644
645
646 text = text + " " + name + ": " + repr(getattr(self, name)) + "\n"
647
648 return text
649
650
652 """Method for testing if this MoleculeContainer object is empty.
653
654 @return: True if this container is empty and the molecule name has not been set, False
655 otherwise.
656 @rtype: bool
657 """
658
659
660 if self.name != None:
661 return False
662
663
664 for name in dir(self):
665
666 if name in ['name', 'res', 'type']:
667 continue
668
669
670 if name == 'is_empty':
671 continue
672
673
674 if match("^_", name):
675 continue
676
677
678 return False
679
680
681 if not self.res.is_empty():
682 return False
683
684
685 return True
686
687
689 """List type data container for the molecule specific data."""
690
692 """Set up the first molecule data container."""
693
694
695 self.append(MoleculeContainer())
696
697
698 self._spin_id_lookup = {}
699
700
702 """The string representation of the object.
703
704 Rather than using the standard Python conventions (either the string representation of the
705 value or the "<...desc...>" notation), a rich-formatted description of the object is given.
706 """
707
708 text = "Molecules.\n\n"
709 text = text + "%-8s%-8s" % ("Index", "Name") + "\n"
710 for i in range(len(self)):
711 text = text + "%-8i%-8s" % (i, self[i].name) + "\n"
712 text = text + "\nThese can be accessed by typing 'D.mol[i]', where D is the relax data storage object.\n"
713 return text
714
715
716 - def add_item(self, mol_name=None, mol_type=None):
717 """Append an empty MoleculeContainer to the MoleculeList."""
718
719
720 if self.is_empty():
721 self[0].name = mol_name
722 self[0].type = mol_type
723
724
725 else:
726
727 for i in range(len(self)):
728 if self[i].name == mol_name:
729 raise RelaxError("The molecule '%s' already exists in the sequence." % mol_name)
730
731
732 self.append(MoleculeContainer(mol_name, mol_type))
733
734
736 """Method for testing if this MoleculeList object is empty.
737
738 @return: True if this list only has one MoleculeContainer and the molecule name has not
739 been set, False otherwise.
740 @rtype: bool
741 """
742
743
744 if len(self) == 1 and self[0].is_empty():
745 return True
746
747
748 return False
749
750
751 - def from_xml(self, mol_nodes, file_version=None):
752 """Recreate a molecule list data structure from the XML molecule nodes.
753
754 @param mol_nodes: The molecule XML nodes.
755 @type mol_nodes: xml.dom.minicompat.NodeList instance
756 @keyword file_version: The relax XML version of the XML file.
757 @type file_version: int
758 """
759
760
761 if not self.is_empty():
762 raise RelaxFromXMLNotEmptyError(self.__class__.__name__)
763
764
765 for mol_node in mol_nodes:
766
767 name = str(mol_node.getAttribute('name'))
768 if name == 'None':
769 name = None
770 type = str(mol_node.getAttribute('type'))
771 if type == 'None':
772 type = None
773 self.add_item(mol_name=name, mol_type=type)
774
775
776 res_nodes = mol_node.getElementsByTagName('res')
777
778
779 self[-1].res.from_xml(res_nodes, file_version=file_version)
780
781
782 - def to_xml(self, doc, element):
783 """Create XML elements for each molecule.
784
785 @param doc: The XML document object.
786 @type doc: xml.dom.minidom.Document instance
787 @param element: The element to add the molecule XML elements to.
788 @type element: XML element object
789 """
790
791
792 for i in range(len(self)):
793
794 mol_element = doc.createElement('mol')
795 element.appendChild(mol_element)
796
797
798 mol_element.setAttribute('desc', 'Molecule container')
799 mol_element.setAttribute('name', str(self[i].name))
800 mol_element.setAttribute('type', str(self[i].type))
801
802
803 fill_object_contents(doc, mol_element, object=self[i], blacklist=['name', 'res', 'type'] + list(self[i].__class__.__dict__.keys()))
804
805
806 self[i].res.to_xml(doc, mol_element)
807