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
2 from tempfile import NamedTemporaryFile
4 from Bio.PDB import DSSP
9 """A dictionary of default markup name -> markup class."""
12 """Update `by_name` dictionary.
14 If any arguments are given, add them to markups namespace beforehands.
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
24 for markup_class in globals().values():
25 if not hasattr(markup_class, 'name') or not markup_class.name:
27 if not hasattr(markup_class, 'kind') or not markup_class.kind:
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."""
37 """Separator to use when saving/loading markup."""
40 """Quotation sign used on the markup."""
43 """MUST be overloaded when subclassing. io_class in file."""
46 def parse_item(key, value):
47 """Deserialize one item of markup. Overload when subclassing."""
51 def repr_item(key, value):
52 """Serialize one item of markup. Overload when subclassing."""
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)
64 values = values.split(result.separator)
65 assert len(values) == len(result.sorted_keys())
66 for key, value in zip(result.sorted_keys(), values):
68 result[key] = result.parse_item(key, value)
72 """Write markup to semi-serialized record for 'markup' file."""
74 for key in self.sorted_keys():
76 values.append(self.repr_item(key, self[key]))
79 markup = self.separator.join(values)
82 'io_class': self.io_class,
83 'separator': self.separator,
84 'quotes': self.quotes,
87 class IntMarkupMixin(MarkupIOMixin):
88 """Markup that has integer values."""
90 io_class = 'IntMarkup'
93 def parse_item(key, value):
96 class FloatMarkupMixin(MarkupIOMixin):
97 """Markup that has float values."""
99 io_class = 'FloatMarkup'
102 def parse_item(key, value):
105 class BoolMarkupMixin(MarkupIOMixin):
106 """Markup that has boolean values."""
108 io_class = 'BoolMarkup'
111 def parse_item(key, value):
115 def repr_item(key, value):
121 class CharMarkupMixin(MarkupIOMixin):
122 """Markup that has one-letter values."""
124 io_class = 'CharMarkup'
127 def parse_item(key, value):
128 assert len(value) == 1
132 def repr_item(key, value):
133 assert len(str(value)) == 1
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."""
151 class SequenceCharMarkup(base.SequenceMarkup, CharMarkupMixin):
152 """Generic class for one-letter markups."""
155 class SequenceIntMarkup(base.SequenceMarkup, IntMarkupMixin):
156 """Generic class for integer number markups."""
159 class SequenceFloatMarkup(base.SequenceMarkup, FloatMarkupMixin):
160 """Generic class for floating-point number markups."""
163 class SequenceBoolMarkup(base.SequenceMarkup, BoolMarkupMixin):
164 """Generic class for boolean markups."""
167 class SequenceNumberMarkup(base.SequenceMarkup):
172 for number, monomer in enumerate(self.sequence, 1):
173 monomer.number = number
175 class SequenceIndexMarkup(base.SequenceMarkup):
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."""
187 class AlignmentCharMarkup(base.AlignmentMarkup, CharMarkupMixin):
188 """Generic class for one-letter markups."""
191 class AlignmentIntMarkup(base.AlignmentMarkup, IntMarkupMixin):
192 """Generic class for integer number markups."""
195 class AlignmentFloatMarkup(base.AlignmentMarkup, FloatMarkupMixin):
196 """Generic class for floating-point number markups."""
199 class AlignmentBoolMarkup(base.AlignmentMarkup, BoolMarkupMixin):
200 """Generic class for boolean markups."""
203 class AlignmentNumberMarkup(base.AlignmentMarkup):
208 for number, column in enumerate(self.alignment.columns, 1):
209 self[column] = number
211 class AlignmentIndexMarkup(base.AlignmentMarkup):
216 for index, column in enumerate(self.alignment.columns):
219 class SequenceCaseMarkup(base.SequenceMarkup, MarkupIOMixin):
222 io_class = 'SequenceCaseMarkup'
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'
234 def parse_item(monomer, value):
235 assert monomer.code1 == value.upper()
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):
252 class SequencePdbResiMarkup(base.SequenceMarkup, IntMarkupMixin):
256 for monomer in self.sequence:
258 monomer.pdb_resi = monomer.pdb_residue.id[1]
262 def add_pdb(self, download_pdb=None, xyz_only=False):
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]
273 self.sequence.pdb_chain = pdb_chain
274 for monomer in self.sequence:
276 pdb_residue = pdb_chain[' ', monomer.pdb_resi, ' ']
277 monomer.ca_xyz = pdb_residue['CA'].get_vector()
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.
296 * B -- Isolated beta-bridge residue
306 io_class = 'SequenceSecondaryStructureMarkup'
309 chain = self.sequence.pdb_chain
310 model = chain.get_parent()
311 pdb_file = NamedTemporaryFile(delete=False)
312 self.sequence.save_pdb(pdb_file)
314 dssp=DSSP(model, pdb_file.name, dssp='dsspcmbi')
315 for monomer in self.sequence:
317 monomer.ss = dssp[(chain.get_id(), monomer.pdb_residue.get_id())][1]
319 monomer.ss = '?' # FIXME
320 os.unlink(pdb_file.name)
322 # This MUST be the last statement in this module.
325 # vim: set ts=4 sts=4 sw=4 et: