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, pipe_type=None):
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 @keyword pipe_type: The type of the pipe being converted to XML.
316 @type pipe_type: str
317 """
318
319
320 data_names = specific_analyses.setup.get_specific_fn('data_names', pipe_type, raise_error=False)
321 return_data_desc = specific_analyses.setup.get_specific_fn('return_data_desc', pipe_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, pipe_type=None):
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 @keyword pipe_type: The type of the pipe being converted to XML.
578 @type pipe_type: str
579 """
580
581
582 for i in range(len(self)):
583
584 res_element = doc.createElement('res')
585 element.appendChild(res_element)
586
587
588 res_element.setAttribute('desc', 'Residue container')
589 res_element.setAttribute('name', str(self[i].name))
590 res_element.setAttribute('num', str(self[i].num))
591
592
593 fill_object_contents(doc, res_element, object=self[i], blacklist=['name', 'num', 'spin'] + list(self[i].__class__.__dict__.keys()))
594
595
596 self[i].spin.to_xml(doc, res_element, pipe_type=pipe_type)
597
598
599
600
601
602
604 """Class containing all the molecule specific data."""
605
606 - def __init__(self, mol_name=None, mol_type=None):
607 """Set up the default objects of the molecule data container."""
608
609
610 self.name = mol_name
611
612
613 self.type = mol_type
614
615
616 self._mol_index = None
617
618
619 self.res = ResidueList()
620
621
623 """The string representation of the object.
624
625 Rather than using the standard Python conventions (either the string representation of the
626 value or the "<...desc...>" notation), a rich-formatted description of the object is given.
627 """
628
629
630 text = "Class containing all the molecule specific data.\n"
631
632
633 text = text + "\n"
634 text = text + "Objects:\n"
635 for name in dir(self):
636
637 if name == 'res':
638 text = text + " res: The list of the residues of the molecule\n"
639 continue
640
641
642 if name == 'is_empty':
643 continue
644
645
646 if match("^_", name):
647 continue
648
649
650 text = text + " " + name + ": " + repr(getattr(self, name)) + "\n"
651
652 return text
653
654
656 """Method for testing if this MoleculeContainer object is empty.
657
658 @return: True if this container is empty and the molecule name has not been set, False
659 otherwise.
660 @rtype: bool
661 """
662
663
664 if self.name != None:
665 return False
666
667
668 for name in dir(self):
669
670 if name in ['name', 'res', 'type']:
671 continue
672
673
674 if name == 'is_empty':
675 continue
676
677
678 if match("^_", name):
679 continue
680
681
682 return False
683
684
685 if not self.res.is_empty():
686 return False
687
688
689 return True
690
691
693 """List type data container for the molecule specific data."""
694
696 """Set up the first molecule data container."""
697
698
699 self.append(MoleculeContainer())
700
701
702 self._spin_id_lookup = {}
703
704
706 """The string representation of the object.
707
708 Rather than using the standard Python conventions (either the string representation of the
709 value or the "<...desc...>" notation), a rich-formatted description of the object is given.
710 """
711
712 text = "Molecules.\n\n"
713 text = text + "%-8s%-8s" % ("Index", "Name") + "\n"
714 for i in range(len(self)):
715 text = text + "%-8i%-8s" % (i, self[i].name) + "\n"
716 text = text + "\nThese can be accessed by typing 'D.mol[i]', where D is the relax data storage object.\n"
717 return text
718
719
720 - def add_item(self, mol_name=None, mol_type=None):
721 """Append an empty MoleculeContainer to the MoleculeList."""
722
723
724 if self.is_empty():
725 self[0].name = mol_name
726 self[0].type = mol_type
727
728
729 else:
730
731 for i in range(len(self)):
732 if self[i].name == mol_name:
733 raise RelaxError("The molecule '%s' already exists in the sequence." % mol_name)
734
735
736 self.append(MoleculeContainer(mol_name, mol_type))
737
738
740 """Method for testing if this MoleculeList object is empty.
741
742 @return: True if this list only has one MoleculeContainer and the molecule name has not
743 been set, False otherwise.
744 @rtype: bool
745 """
746
747
748 if len(self) == 1 and self[0].is_empty():
749 return True
750
751
752 return False
753
754
755 - def from_xml(self, mol_nodes, file_version=None):
756 """Recreate a molecule list data structure from the XML molecule nodes.
757
758 @param mol_nodes: The molecule XML nodes.
759 @type mol_nodes: xml.dom.minicompat.NodeList instance
760 @keyword file_version: The relax XML version of the XML file.
761 @type file_version: int
762 """
763
764
765 if not self.is_empty():
766 raise RelaxFromXMLNotEmptyError(self.__class__.__name__)
767
768
769 for mol_node in mol_nodes:
770
771 name = str(mol_node.getAttribute('name'))
772 if name == 'None':
773 name = None
774 type = str(mol_node.getAttribute('type'))
775 if type == 'None':
776 type = None
777 self.add_item(mol_name=name, mol_type=type)
778
779
780 res_nodes = mol_node.getElementsByTagName('res')
781
782
783 self[-1].res.from_xml(res_nodes, file_version=file_version)
784
785
786 - def to_xml(self, doc, element, pipe_type=None):
787 """Create XML elements for each molecule.
788
789 @param doc: The XML document object.
790 @type doc: Xml.dom.minidom.Document instance
791 @param element: The element to add the molecule XML elements to.
792 @type element: XML element object
793 @keyword pipe_type: The type of the pipe being converted to XML.
794 @type pipe_type: str
795 """
796
797
798 for i in range(len(self)):
799
800 mol_element = doc.createElement('mol')
801 element.appendChild(mol_element)
802
803
804 mol_element.setAttribute('desc', 'Molecule container')
805 mol_element.setAttribute('name', str(self[i].name))
806 mol_element.setAttribute('type', str(self[i].type))
807
808
809 fill_object_contents(doc, mol_element, object=self[i], blacklist=['name', 'res', 'type'] + list(self[i].__class__.__dict__.keys()))
810
811
812 self[i].res.to_xml(doc, mol_element, pipe_type=pipe_type)
813