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

allpy

view allpy/markups.py @ 1062:5f8b5a13adfa

pair-cores/web: add field "Execution log" Execution log is printed on main application page
author Boris Nagaev <bnagaev@gmail.com>
date Wed, 16 May 2012 23:21:30 +0400
parents 4349a1f31dd2
children 83167a09a19d 3c32489fcb3b
line source
1 import os
2 from tempfile import NamedTemporaryFile
4 from Bio.PDB import DSSP
6 import base
8 by_name = {}
9 """A dictionary of default markup name -> markup class."""
11 def update(*args):
12 """Update `by_name` dictionary.
14 If any arguments are given, add them to markups namespace beforehands.
15 """
16 # Add user classes if necessary
17 for markup_class in args:
18 class_name = markup_class.__name__
19 assert class_name not in globals(), "SameNamed markup already exists!"
20 globals()[class_name] = markup_class
21 # Update `by_name` dictonary
22 global by_name
23 by_name = {}
24 for markup_class in globals().values():
25 if not hasattr(markup_class, 'name') or not markup_class.name:
26 continue
27 if not hasattr(markup_class, 'kind') or not markup_class.kind:
28 continue
29 fullname = markup_class.kind, markup_class.name
30 assert fullname not in by_name, "Markup %s already exists!" % (fullname,)
31 by_name[fullname] = markup_class
33 class MarkupIOMixin(base.Markup):
34 """Standard helper mixin for creating saveable markups."""
36 separator = ','
37 """Separator to use when saving/loading markup."""
39 quotes = ''
40 """Quotation sign used on the markup."""
42 io_class = None
43 """MUST be overloaded when subclassing. io_class in file."""
45 @staticmethod
46 def parse_item(key, value):
47 """Deserialize one item of markup. Overload when subclassing."""
48 return value
50 @staticmethod
51 def repr_item(key, value):
52 """Serialize one item of markup. Overload when subclassing."""
53 return str(value)
55 @classmethod
56 def from_record(cls, container, record, name=None):
57 """Read markup from semi-parsed record from 'markup' file."""
58 assert record['io_class'] == cls.io_class
59 result = container.add_markup(name, markup_class=cls)
60 result.separator = record.get('separator', cls.separator)
61 result.quotes = record.get('quotes', cls.quotes)
62 values = record['markup'].strip(result.quotes)
63 if result.separator:
64 values = values.split(result.separator)
65 assert len(values) == len(result.sorted_keys())
66 for key, value in zip(result.sorted_keys(), values):
67 if value:
68 result[key] = result.parse_item(key, value)
69 return result
71 def to_record(self):
72 """Write markup to semi-serialized record for 'markup' file."""
73 values = []
74 for key in self.sorted_keys():
75 if key in self:
76 values.append(self.repr_item(key, self[key]))
77 else:
78 values.append('')
79 markup = self.separator.join(values)
80 return {
81 'markup': markup,
82 'io_class': self.io_class,
83 'separator': self.separator,
84 'quotes': self.quotes,
85 }
87 class IntMarkupMixin(MarkupIOMixin):
88 """Markup that has integer values."""
90 io_class = 'IntMarkup'
92 @staticmethod
93 def parse_item(key, value):
94 return int(value)
96 class FloatMarkupMixin(MarkupIOMixin):
97 """Markup that has float values."""
99 io_class = 'FloatMarkup'
101 @staticmethod
102 def parse_item(key, value):
103 return float(value)
105 class BoolMarkupMixin(MarkupIOMixin):
106 """Markup that has boolean values."""
108 io_class = 'BoolMarkup'
110 @staticmethod
111 def parse_item(key, value):
112 return value == '+'
114 @staticmethod
115 def repr_item(key, value):
116 if value:
117 return '+'
118 else:
119 return '-'
121 class CharMarkupMixin(MarkupIOMixin):
122 """Markup that has one-letter values."""
124 io_class = 'CharMarkup'
126 @staticmethod
127 def parse_item(key, value):
128 assert len(value) == 1
129 return value
131 @staticmethod
132 def repr_item(key, value):
133 assert len(str(value)) == 1
134 return str(value)
136 class StrMarkupMixin(MarkupIOMixin):
137 """Markup that is capable of storing ANY strings."""
139 io_class = 'StrMarkup'
141 def parse_item(self, key, value):
142 return value.replace("%2C", self.separator).replace("%25", "%")
144 def repr_item(self, key, value):
145 return str(value).replace("%", "%25").replace(self.separator, "%2C")
147 class SequenceStrMarkup(base.SequenceMarkup, StrMarkupMixin):
148 """Generic class for string-based markups."""
149 pass
151 class SequenceCharMarkup(base.SequenceMarkup, CharMarkupMixin):
152 """Generic class for one-letter markups."""
153 pass
155 class SequenceIntMarkup(base.SequenceMarkup, IntMarkupMixin):
156 """Generic class for integer number markups."""
157 pass
159 class SequenceFloatMarkup(base.SequenceMarkup, FloatMarkupMixin):
160 """Generic class for floating-point number markups."""
161 pass
163 class SequenceBoolMarkup(base.SequenceMarkup, BoolMarkupMixin):
164 """Generic class for boolean markups."""
165 pass
167 class SequenceNumberMarkup(base.SequenceMarkup):
169 name = 'number'
171 def refresh(self):
172 for number, monomer in enumerate(self.sequence, 1):
173 monomer.number = number
175 class SequenceIndexMarkup(base.SequenceMarkup):
177 name = 'index'
179 def refresh(self):
180 for index, monomer in enumerate(self.sequence):
181 monomer.index = index
183 class AlignmentStrMarkup(base.AlignmentMarkup, StrMarkupMixin):
184 """Generic class for string-based markups."""
185 pass
187 class AlignmentCharMarkup(base.AlignmentMarkup, CharMarkupMixin):
188 """Generic class for one-letter markups."""
189 pass
191 class AlignmentIntMarkup(base.AlignmentMarkup, IntMarkupMixin):
192 """Generic class for integer number markups."""
193 pass
195 class AlignmentFloatMarkup(base.AlignmentMarkup, FloatMarkupMixin):
196 """Generic class for floating-point number markups."""
197 pass
199 class AlignmentBoolMarkup(base.AlignmentMarkup, BoolMarkupMixin):
200 """Generic class for boolean markups."""
201 pass
203 class AlignmentNumberMarkup(base.AlignmentMarkup):
205 name = 'number'
207 def refresh(self):
208 for number, column in enumerate(self.alignment.columns, 1):
209 self[column] = number
211 class AlignmentIndexMarkup(base.AlignmentMarkup):
213 name = 'index'
215 def refresh(self):
216 for index, column in enumerate(self.alignment.columns):
217 self[column] = index
219 class SequenceCaseMarkup(base.SequenceMarkup, MarkupIOMixin):
221 name = 'case'
222 io_class = 'SequenceCaseMarkup'
223 separator = ''
224 quotes = "'"
226 def refresh(self):
227 for monomer in self.sequence:
228 if monomer.input_code1.isupper():
229 monomer.case = 'upper'
230 elif monomer.input_code1.islower():
231 monomer.case = 'lower'
233 @staticmethod
234 def parse_item(monomer, value):
235 assert monomer.code1 == value.upper()
236 if value.isupper():
237 return 'upper'
238 if value.islower():
239 return 'lower'
241 @staticmethod
242 def repr_item(monomer, value):
243 if monomer.case == 'upper':
244 return monomer.code1.upper()
245 if monomer.case == 'lower':
246 return monomer.code1.lower()
247 raise AssertionError("Unknown monomer case")
249 class SequenceQualityMarkup(base.SequenceMarkup, IntMarkupMixin):
250 name = 'quality'
252 class SequencePdbResiMarkup(base.SequenceMarkup, IntMarkupMixin):
253 name = 'pdb_resi'
255 def from_pdb(self):
256 for monomer in self.sequence:
257 try:
258 monomer.pdb_resi = monomer.pdb_residue.id[1]
259 except Exception:
260 pass
262 def add_pdb(self, download_pdb=None, xyz_only=False):
263 import structure
264 if download_pdb is None:
265 download_pdb = structure.cached_download_pdb
267 match = structure.pdb_id_parse(self.sequence.name)
268 code, model , chain = match['code'], match['model'], match['chain']
269 pdb_file = download_pdb(code)
270 pdb_structure = structure.get_structure(pdb_file, self.sequence.name)
271 pdb_chain = pdb_structure[0][chain]
272 if not xyz_only:
273 self.sequence.pdb_chain = pdb_chain
274 for monomer in self.sequence:
275 if monomer in self:
276 pdb_residue = pdb_chain[' ', monomer.pdb_resi, ' ']
277 monomer.ca_xyz = pdb_residue['CA'].get_vector()
278 if not xyz_only:
279 monomer.pdb_residue = pdb_residue
281 class SequenceSecondaryStructureMarkup(base.SequenceMarkup, MarkupIOMixin):
282 """ WARNING! WARNING! WARNING!
283 This class will soon be eliminated and replaced with totally incompatible one.
284 Only use on your own risk!
286 Secondary structure markup for sequence.
288 Depends on dsspcmbi program.
289 Sequence should be structure.SequenceMixin, pdb should be loaded.
290 Note that DSSP cannot handle mutiple models!
291 Note that dssp executable name is hardcoded (=dsspcmbi).
292 Note that new version of dssp can not be used, so use DSSPold.
294 Notation:
295 * H -- alpha-helix
296 * B -- Isolated beta-bridge residue
297 * E -- Strand
298 * G -- 3-10 helix
299 * I -- pi-helix
300 * T -- Turn
301 * S -- Bend
302 * - -- Other
303 """
305 name = 'ss'
306 io_class = 'SequenceSecondaryStructureMarkup'
308 def refresh(self):
309 chain = self.sequence.pdb_chain
310 model = chain.get_parent()
311 pdb_file = NamedTemporaryFile(delete=False)
312 self.sequence.save_pdb(pdb_file)
313 pdb_file.close()
314 dssp=DSSP(model, pdb_file.name, dssp='dsspcmbi')
315 for monomer in self.sequence:
316 try:
317 monomer.ss = dssp[(chain.get_id(), monomer.pdb_residue.get_id())][1]
318 except:
319 monomer.ss = '?' # FIXME
320 os.unlink(pdb_file.name)
322 # This MUST be the last statement in this module.
323 update()
325 # vim: set ts=4 sts=4 sw=4 et: