view allpy/markups.py @ 955:841c47a94c9e
blocks3d/wt: add abstract block (rus and eng)
author |
Boris Nagaev <bnagaev@gmail.com> |
date |
Wed, 25 Jan 2012 00:37:52 +0400 |
parents |
7ebba94eece2 |
children |
695cf9ab2293 |
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 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."""
34 """Separator to use when saving/loading markup."""
37 """Quotation sign used on the markup."""
40 """MUST be overloaded when subclassing. io_class in file."""
43 def parse_item(key, value):
44 """Deserialize one item of markup. Overload when subclassing."""
48 def repr_item(key, value):
49 """Serialize one item of markup. Overload when subclassing."""
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)
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):
65 result[key] = cls.parse_item(key, value)
69 """Write markup to semi-serialized record for 'markup' file."""
71 for key in self.sorted_keys():
73 values.append(self.repr_item(key, self[key]))
76 markup = self.separator.join(values)
79 'io_class': self.io_class,
80 'separator': self.separator,
81 'quotes': self.quotes,
84 class IntMarkupMixin(MarkupIOMixin):
85 """Markup that has integer values."""
87 io_class = 'IntMarkup'
90 def parse_item(key, value):
93 class SequenceNumberMarkup(base.SequenceMarkup):
98 for number, monomer in enumerate(self.sequence, 1):
99 monomer.number = number
101 class SequenceIndexMarkup(base.SequenceMarkup):
106 for index, monomer in enumerate(self.sequence):
107 monomer.index = index
109 class AlignmentNumberMarkup(base.AlignmentMarkup):
114 for number, column in enumerate(self.alignment.columns, 1):
115 self[column] = number
117 class AlignmentIndexMarkup(base.AlignmentMarkup):
122 for index, column in enumerate(self.alignment.columns):
125 class SequenceCaseMarkup(base.SequenceMarkup, MarkupIOMixin):
128 io_class = 'SequenceCaseMarkup'
133 for monomer in self.sequence:
134 if monomer.input_code1.isupper():
135 monomer.case = 'upper'
136 elif monomer.input_code1.islower():
137 monomer.case = 'lower'
140 def parse_item(monomer, value):
141 assert monomer.code1 == value.upper()
148 def repr_item(monomer, value):
149 if monomer.case == 'upper':
150 return monomer.code1.upper()
151 if monomer.case == 'lower':
152 return monomer.code1.lower()
153 raise AssertionError("Unknown monomer case")
155 class SequenceQualityMarkup(base.SequenceMarkup, IntMarkupMixin):
158 class SequencePdbResiMarkup(base.SequenceMarkup, IntMarkupMixin):
162 for monomer in self.sequence:
164 monomer.pdb_resi = monomer.pdb_residue.id[1]
168 def add_pdb(self, download_pdb=None, xyz_only=False):
170 if download_pdb is None:
171 download_pdb = structure.cached_download_pdb
173 match = structure.pdb_id_parse(self.sequence.name)
174 code, model , chain = match['code'], match['model'], match['chain']
175 pdb_file = download_pdb(code)
176 pdb_structure = structure.get_structure(pdb_file, self.sequence.name)
177 pdb_chain = pdb_structure[0][chain]
179 self.sequence.pdb_chain = pdb_chain
180 for monomer in self.sequence:
182 pdb_residue = pdb_chain[' ', monomer.pdb_resi, ' ']
183 monomer.ca_xyz = pdb_residue['CA'].get_vector()
185 monomer.pdb_residue = pdb_residue
187 class SequenceSecondaryStructureMarkup(base.SequenceMarkup, MarkupIOMixin):
188 """ Secondary structure markup for sequence.
190 Depends on dsspcmbi program.
191 Sequence should be structure.SequenceMixin, pdb should be loaded.
192 Note that DSSP cannot handle mutiple models!
193 Note that dssp executable name is hardcoded (=dsspcmbi).
197 * B -- Isolated beta-bridge residue
207 io_class = 'SequenceSecondaryStructureMarkup'
210 chain = self.sequence.pdb_chain
211 model = chain.get_parent()
212 pdb_file = NamedTemporaryFile(delete=False)
213 self.sequence.save_pdb(pdb_file)
215 dssp=DSSP(model, pdb_file.name, dssp='dsspcmbi')
216 for monomer in self.sequence:
218 monomer.ss = dssp[(chain.get_id(), monomer.pdb_residue.get_id())][1]
220 monomer.ss = '?' # FIXME
221 os.unlink(pdb_file.name)
223 # This MUST be the last statement in this module.
226 # vim: set ts=4 sts=4 sw=4 et: