view allpy/markups.py @ 1078:3f5e9fb2c64f
(closes #153)
author |
Daniil Alexeyevsky <dendik@kodomo.fbb.msu.ru> |
date |
Fri, 25 May 2012 21:12:54 +0400 |
parents |
5b72a644c074 |
children |
41a167bbf150 |
line source
4 """A dictionary of default markup name -> markup class."""
7 """Update `by_name` dictionary.
9 If any arguments are given, add them to markups namespace beforehands.
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
19 for markup_class in globals().values():
20 if not hasattr(markup_class, 'name') or not markup_class.name:
22 if not hasattr(markup_class, 'kind') or not markup_class.kind:
24 fullname = markup_class.kind, markup_class.name
25 assert fullname not in by_name, "Markup %s already exists!" % (fullname,)
26 by_name[fullname] = markup_class
28 class MarkupIOMixin(base.Markup):
29 """Standard helper mixin for creating saveable markups."""
32 """Separator to use when saving/loading markup."""
35 """Quotation sign used on the markup."""
38 """MUST be overloaded when subclassing. io_class in file."""
41 def parse_item(key, value):
42 """Deserialize one item of markup. Overload when subclassing."""
46 def repr_item(key, value):
47 """Serialize one item of markup. Overload when subclassing."""
51 def from_record(cls, container, record, name=None):
52 """Read markup from semi-parsed record from 'markup' file."""
53 assert record['io_class'] == cls.io_class
54 result = container.add_markup(name, markup_class=cls)
55 result.separator = record.get('separator', cls.separator)
56 result.quotes = record.get('quotes', cls.quotes)
57 values = record['markup'].strip(result.quotes)
59 values = values.split(result.separator)
60 assert len(values) == len(result.sorted_keys())
61 for key, value in zip(result.sorted_keys(), values):
63 result[key] = result.parse_item(key, value)
67 """Write markup to semi-serialized record for 'markup' file."""
69 for key in self.sorted_keys():
71 values.append(self.repr_item(key, self[key]))
74 markup = self.separator.join(values)
77 'io_class': self.io_class,
78 'separator': self.separator,
79 'quotes': self.quotes,
82 class IntMarkupMixin(MarkupIOMixin):
83 """Markup that has integer values."""
85 io_class = 'IntMarkup'
88 def parse_item(key, value):
91 class FloatMarkupMixin(MarkupIOMixin):
92 """Markup that has float values."""
94 io_class = 'FloatMarkup'
97 def parse_item(key, value):
100 class BoolMarkupMixin(MarkupIOMixin):
101 """Markup that has boolean values."""
103 io_class = 'BoolMarkup'
106 def parse_item(key, value):
110 def repr_item(key, value):
116 class CharMarkupMixin(MarkupIOMixin):
117 """Markup that has one-letter values."""
119 io_class = 'CharMarkup'
122 def parse_item(key, value):
123 assert len(value) == 1
127 def repr_item(key, value):
128 assert len(str(value)) == 1
131 class StrMarkupMixin(MarkupIOMixin):
132 """Markup that is capable of storing ANY strings."""
134 io_class = 'StrMarkup'
136 def parse_item(self, key, value):
137 return value.replace("%2C", self.separator).replace("%25", "%")
139 def repr_item(self, key, value):
140 return str(value).replace("%", "%25").replace(self.separator, "%2C")
142 class SequenceStrMarkup(base.SequenceMarkup, StrMarkupMixin):
143 """Generic class for string-based markups."""
146 class SequenceCharMarkup(base.SequenceMarkup, CharMarkupMixin):
147 """Generic class for one-letter markups."""
150 class SequenceIntMarkup(base.SequenceMarkup, IntMarkupMixin):
151 """Generic class for integer number markups."""
154 class SequenceFloatMarkup(base.SequenceMarkup, FloatMarkupMixin):
155 """Generic class for floating-point number markups."""
158 class SequenceBoolMarkup(base.SequenceMarkup, BoolMarkupMixin):
159 """Generic class for boolean markups."""
162 class SequenceNumberMarkup(base.SequenceMarkup):
167 for number, monomer in enumerate(self.sequence, 1):
168 monomer.number = number
170 class SequenceIndexMarkup(base.SequenceMarkup):
175 for index, monomer in enumerate(self.sequence):
176 monomer.index = index
178 class AlignmentStrMarkup(base.AlignmentMarkup, StrMarkupMixin):
179 """Generic class for string-based markups."""
182 class AlignmentCharMarkup(base.AlignmentMarkup, CharMarkupMixin):
183 """Generic class for one-letter markups."""
186 class AlignmentIntMarkup(base.AlignmentMarkup, IntMarkupMixin):
187 """Generic class for integer number markups."""
190 class AlignmentFloatMarkup(base.AlignmentMarkup, FloatMarkupMixin):
191 """Generic class for floating-point number markups."""
194 class AlignmentBoolMarkup(base.AlignmentMarkup, BoolMarkupMixin):
195 """Generic class for boolean markups."""
198 class AlignmentNumberMarkup(base.AlignmentMarkup):
203 for number, column in enumerate(self.alignment.columns, 1):
204 self[column] = number
206 class AlignmentIndexMarkup(base.AlignmentMarkup):
211 for index, column in enumerate(self.alignment.columns):
214 class SequenceCaseMarkup(base.SequenceMarkup, MarkupIOMixin):
217 io_class = 'SequenceCaseMarkup'
222 for monomer in self.sequence:
223 if monomer.input_code1.isupper():
224 monomer.case = 'upper'
225 elif monomer.input_code1.islower():
226 monomer.case = 'lower'
229 def parse_item(monomer, value):
230 assert monomer.code1 == value.upper()
237 def repr_item(monomer, value):
238 if monomer.case == 'upper':
239 return monomer.code1.upper()
240 if monomer.case == 'lower':
241 return monomer.code1.lower()
242 raise AssertionError("Unknown monomer case")
244 class SequenceQualityMarkup(base.SequenceMarkup, IntMarkupMixin):
247 class SequencePdbResiMarkup(base.SequenceMarkup, IntMarkupMixin):
251 for monomer in self.sequence:
253 monomer.pdb_resi = monomer.pdb_residue.id[1]
257 def add_pdb(self, download_pdb=None, xyz_only=False):
259 if download_pdb is None:
260 download_pdb = structure.cached_download_pdb
262 match = structure.pdb_id_parse(self.sequence.name)
263 code, model , chain = match['code'], match['model'], match['chain']
264 pdb_file = download_pdb(code)
265 pdb_structure = structure.get_structure(pdb_file, self.sequence.name)
266 pdb_chain = pdb_structure[0][chain]
268 self.sequence.pdb_chain = pdb_chain
269 for monomer in self.sequence:
271 pdb_residue = pdb_chain[' ', monomer.pdb_resi, ' ']
272 monomer.ca_xyz = pdb_residue['CA'].get_vector()
274 monomer.pdb_residue = pdb_residue
276 # This MUST be the last statement in this module.
279 # vim: set ts=4 sts=4 sw=4 et: