Документ взят из кэша поисковой машины. Адрес оригинального документа : http://kodomo.fbb.msu.ru/hg/allpy/file/077e5e18a600/allpy/markups.py
Дата изменения: Unknown
Дата индексирования: Mon Feb 4 05:14:40 2013
Кодировка:
allpy: 077e5e18a600 allpy/markups.py

allpy

view allpy/markups.py @ 852:077e5e18a600

Added allpy.markups.MarkupIOMixin to simplify new saveable markups creation. Switched existing saveable makrups to using it. Tested. (closes #82)
author Daniil Alexeyevsky <dendik@kodomo.fbb.msu.ru>
date Wed, 20 Jul 2011 20:44:59 +0400
parents 137981a4686f
children 9b253b69f8f1
line source
1 import base
3 by_name = {}
4 """A dictionary of default markup name -> markup class."""
6 def update(*args):
7 """Update `by_name` dictionary.
9 If any arguments are given, add them to markups namespace beforehands.
10 """
11 # Add user classes if necessary
12 for markup_class in args:
13 class_name = markup_class.__name__
14 assert class_name not in globals(), "SameNamed markup already exists!"
15 globals()[class_name] = markup_class
16 # Update `by_name` dictonary
17 global by_name
18 by_name = {}
19 for markup_class in globals().values():
20 if hasattr(markup_class, 'name') and hasattr(markup_class, 'kind'):
21 fullname = markup_class.kind, markup_class.name
22 assert fullname not in by_name, "Samenamed markup already exists!"
23 by_name[fullname] = markup_class
25 class MarkupIOMixin(base.Markup):
26 """Standard helper mixin for creating saveable markups."""
28 separator = ','
29 """Separator to use when saving/loading markup."""
31 io_class = None
32 """MUST be overloaded when subclassing. io_class in file."""
34 @staticmethod
35 def parse_item(key, value):
36 """Deserialize one item of markup. Overload when subclassing."""
37 return value
39 @staticmethod
40 def repr_item(key, value):
41 """Serialize one item of markup. Overload when subclassing."""
42 return str(value)
44 @classmethod
45 def from_record(cls, container, record, name=None):
46 """Read markup from semi-parsed record from 'markup' file."""
47 assert record['io_class'] == cls.io_class
48 separator = record.get('separator', cls.separator)
49 values = record['markup'].split(separator)
50 result = container.add_markup(name, markup_class=cls)
51 assert len(values) == len(result.sorted_keys())
52 for key, value in zip(result.sorted_keys(), values):
53 if value:
54 result[key] = cls.parse_item(key, value)
55 return result
57 def to_record(self):
58 """Write markup to semi-serialized record for 'markup' file."""
59 values = []
60 for key in self.sorted_keys():
61 if key in self:
62 values.append(self.repr_item(key, self[key]))
63 else:
64 values.append('')
65 markup = self.separator.join(values)
66 return {
67 'markup': markup,
68 'io_class': self.io_class,
69 'separator': self.separator,
70 }
72 class IntMarkupMixin(MarkupIOMixin):
73 """Markup that has integer values."""
75 io_class = 'IntMarkup'
77 @staticmethod
78 def parse_item(key, value):
79 return int(value)
81 class SequenceNumberMarkup(base.SequenceMarkup):
83 name = 'number'
85 def refresh(self):
86 for number, monomer in enumerate(self.sequence, 1):
87 monomer.number = number
89 class SequenceIndexMarkup(base.SequenceMarkup):
91 name = 'index'
93 def refresh(self):
94 for index, monomer in enumerate(self.sequence):
95 monomer.index = index
97 class AlignmentNumberMarkup(base.AlignmentMarkup):
99 name = 'number'
101 def refresh(self):
102 for number, column in enumerate(self.alignment.columns, 1):
103 self[column] = number
105 class AlignmentIndexMarkup(base.AlignmentMarkup):
107 name = 'index'
109 def refresh(self):
110 for index, column in enumerate(self.alignment.columns):
111 self[column] = index
113 class SequenceCaseMarkup(base.SequenceMarkup, MarkupIOMixin):
115 name = 'case'
116 io_class = 'SequenceCaseMarkup'
118 def refresh(self):
119 for monomer in self.sequence:
120 if monomer.input_code1.isupper():
121 monomer.case = 'upper'
122 elif monomer.input_code1.islower():
123 monomer.case = 'lower'
125 @staticmethod
126 def parse_value(monomer, value):
127 assert mnomer.code1 == value.upper()
128 if value.isupper():
129 return 'upper'
130 if value.islower():
131 return 'lower'
133 @staticmethod
134 def repr_value(monomer, value):
135 if monomer.case == 'upper':
136 return monomer.code1.upper()
137 if monomer.case == 'lower':
138 return monomer.code1.lower()
139 raise AssertionError("Unknown monomer case")
141 class SequencePdbResiMarkup(base.SequenceMarkup, IntMarkupMixin):
142 name = 'pdb_resi'
144 def from_pdb(self):
145 for monomer in self.sequence:
146 try:
147 monomer.pdb_resi = monomer.pdb_residue.id[1]
148 except Exception:
149 pass
151 def add_pdb(self, download_pdb=None, xyz_only=False):
152 import structure
153 if download_pdb is None:
154 download_pdb = structure.cached_download_pdb
156 match = structure.pdb_id_parse(self.sequence.name)
157 code, model , chain = match['code'], match['model'], match['chain']
158 pdb_file = download_pdb(code)
159 pdb_structure = structure.get_structure(pdb_file, self.sequence.name)
160 pdb_chain = pdb_structure[0][chain]
161 if not xyz_only:
162 self.sequence.pdb_chain = pdb_chain
163 for monomer in self.sequence:
164 if monomer in self:
165 pdb_residue = pdb_chain[' ', monomer.pdb_resi, ' ']
166 monomer.ca_xyz = pdb_residue['CA'].get_vector()
167 if not xyz_only:
168 monomer.pdb_residue = pdb_residue
170 # This MUST be the last statement in this module.
171 update()
173 # vim: set ts=4 sts=4 sw=4 et: