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

allpy

view allpy/markups.py @ 984:a1be82967e81

allpy/structure: add ``parts'' argument to blocks3d() You can provide pre-calculated pair core parts in this argument.
author Boris Nagaev <bnagaev@gmail.com>
date Wed, 29 Feb 2012 15:13:12 +0400
parents 695cf9ab2293
children 4349a1f31dd2
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 hasattr(markup_class, 'name') and hasattr(markup_class, 'kind'):
26 fullname = markup_class.kind, markup_class.name
27 assert fullname not in by_name, "Samenamed markup already exists!"
28 by_name[fullname] = markup_class
30 class MarkupIOMixin(base.Markup):
31 """Standard helper mixin for creating saveable markups."""
33 separator = ','
34 """Separator to use when saving/loading markup."""
36 quotes = ''
37 """Quotation sign used on the markup."""
39 io_class = None
40 """MUST be overloaded when subclassing. io_class in file."""
42 @staticmethod
43 def parse_item(key, value):
44 """Deserialize one item of markup. Overload when subclassing."""
45 return value
47 @staticmethod
48 def repr_item(key, value):
49 """Serialize one item of markup. Overload when subclassing."""
50 return str(value)
52 @classmethod
53 def from_record(cls, container, record, name=None):
54 """Read markup from semi-parsed record from 'markup' file."""
55 assert record['io_class'] == cls.io_class
56 separator = record.get('separator', cls.separator)
57 quotes = record.get('quotes', cls.quotes)
58 values = record['markup'].strip(quotes)
59 if separator:
60 values = values.split(separator)
61 result = container.add_markup(name, markup_class=cls)
62 assert len(values) == len(result.sorted_keys())
63 for key, value in zip(result.sorted_keys(), values):
64 if value:
65 result[key] = cls.parse_item(key, value)
66 return result
68 def to_record(self):
69 """Write markup to semi-serialized record for 'markup' file."""
70 values = []
71 for key in self.sorted_keys():
72 if key in self:
73 values.append(self.repr_item(key, self[key]))
74 else:
75 values.append('')
76 markup = self.separator.join(values)
77 return {
78 'markup': markup,
79 'io_class': self.io_class,
80 'separator': self.separator,
81 'quotes': self.quotes,
82 }
84 class IntMarkupMixin(MarkupIOMixin):
85 """Markup that has integer values."""
87 io_class = 'IntMarkup'
89 @staticmethod
90 def parse_item(key, value):
91 return int(value)
93 class CharMarkupMixin(MarkupIOMixin):
94 """Markup that has one-letter values."""
96 io_class = 'CharMarkup'
98 @staticmethod
99 def parse_item(key, value):
100 assert len(value) == 1
101 return value
103 @staticmethod
104 def repr_item(key, value):
105 assert len(str(value)) == 1
106 return str(value)
108 class SequenceCharMarkup(base.SequenceMarkup, CharMarkupMixin):
109 """Generic class for one-letter markups."""
111 name = 'char'
113 class SequenceNumberMarkup(base.SequenceMarkup):
115 name = 'number'
117 def refresh(self):
118 for number, monomer in enumerate(self.sequence, 1):
119 monomer.number = number
121 class SequenceIndexMarkup(base.SequenceMarkup):
123 name = 'index'
125 def refresh(self):
126 for index, monomer in enumerate(self.sequence):
127 monomer.index = index
129 class AlignmentNumberMarkup(base.AlignmentMarkup):
131 name = 'number'
133 def refresh(self):
134 for number, column in enumerate(self.alignment.columns, 1):
135 self[column] = number
137 class AlignmentIndexMarkup(base.AlignmentMarkup):
139 name = 'index'
141 def refresh(self):
142 for index, column in enumerate(self.alignment.columns):
143 self[column] = index
145 class SequenceCaseMarkup(base.SequenceMarkup, MarkupIOMixin):
147 name = 'case'
148 io_class = 'SequenceCaseMarkup'
149 separator = ''
150 quotes = "'"
152 def refresh(self):
153 for monomer in self.sequence:
154 if monomer.input_code1.isupper():
155 monomer.case = 'upper'
156 elif monomer.input_code1.islower():
157 monomer.case = 'lower'
159 @staticmethod
160 def parse_item(monomer, value):
161 assert monomer.code1 == value.upper()
162 if value.isupper():
163 return 'upper'
164 if value.islower():
165 return 'lower'
167 @staticmethod
168 def repr_item(monomer, value):
169 if monomer.case == 'upper':
170 return monomer.code1.upper()
171 if monomer.case == 'lower':
172 return monomer.code1.lower()
173 raise AssertionError("Unknown monomer case")
175 class SequenceQualityMarkup(base.SequenceMarkup, IntMarkupMixin):
176 name = 'quality'
178 class SequencePdbResiMarkup(base.SequenceMarkup, IntMarkupMixin):
179 name = 'pdb_resi'
181 def from_pdb(self):
182 for monomer in self.sequence:
183 try:
184 monomer.pdb_resi = monomer.pdb_residue.id[1]
185 except Exception:
186 pass
188 def add_pdb(self, download_pdb=None, xyz_only=False):
189 import structure
190 if download_pdb is None:
191 download_pdb = structure.cached_download_pdb
193 match = structure.pdb_id_parse(self.sequence.name)
194 code, model , chain = match['code'], match['model'], match['chain']
195 pdb_file = download_pdb(code)
196 pdb_structure = structure.get_structure(pdb_file, self.sequence.name)
197 pdb_chain = pdb_structure[0][chain]
198 if not xyz_only:
199 self.sequence.pdb_chain = pdb_chain
200 for monomer in self.sequence:
201 if monomer in self:
202 pdb_residue = pdb_chain[' ', monomer.pdb_resi, ' ']
203 monomer.ca_xyz = pdb_residue['CA'].get_vector()
204 if not xyz_only:
205 monomer.pdb_residue = pdb_residue
207 class SequenceSecondaryStructureMarkup(base.SequenceMarkup, MarkupIOMixin):
208 """ WARNING! WARNING! WARNING!
209 This class will soon be eliminated and replaced with totally incompatible one.
210 Only use on your own risk!
212 Secondary structure markup for sequence.
214 Depends on dsspcmbi program.
215 Sequence should be structure.SequenceMixin, pdb should be loaded.
216 Note that DSSP cannot handle mutiple models!
217 Note that dssp executable name is hardcoded (=dsspcmbi).
219 Notation:
220 * H -- alpha-helix
221 * B -- Isolated beta-bridge residue
222 * E -- Strand
223 * G -- 3-10 helix
224 * I -- pi-helix
225 * T -- Turn
226 * S -- Bend
227 * - -- Other
228 """
230 name = 'ss'
231 io_class = 'SequenceSecondaryStructureMarkup'
233 def refresh(self):
234 chain = self.sequence.pdb_chain
235 model = chain.get_parent()
236 pdb_file = NamedTemporaryFile(delete=False)
237 self.sequence.save_pdb(pdb_file)
238 pdb_file.close()
239 dssp=DSSP(model, pdb_file.name, dssp='dsspcmbi')
240 for monomer in self.sequence:
241 try:
242 monomer.ss = dssp[(chain.get_id(), monomer.pdb_residue.get_id())][1]
243 except:
244 monomer.ss = '?' # FIXME
245 os.unlink(pdb_file.name)
247 # This MUST be the last statement in this module.
248 update()
250 # vim: set ts=4 sts=4 sw=4 et: