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
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 CharMarkupMixin(MarkupIOMixin):
94 """Markup that has one-letter values."""
96 io_class = 'CharMarkup'
99 def parse_item(key, value):
100 assert len(value) == 1
104 def repr_item(key, value):
105 assert len(str(value)) == 1
108 class SequenceCharMarkup(base.SequenceMarkup, CharMarkupMixin):
109 """Generic class for one-letter markups."""
113 class SequenceNumberMarkup(base.SequenceMarkup):
118 for number, monomer in enumerate(self.sequence, 1):
119 monomer.number = number
121 class SequenceIndexMarkup(base.SequenceMarkup):
126 for index, monomer in enumerate(self.sequence):
127 monomer.index = index
129 class AlignmentNumberMarkup(base.AlignmentMarkup):
134 for number, column in enumerate(self.alignment.columns, 1):
135 self[column] = number
137 class AlignmentIndexMarkup(base.AlignmentMarkup):
142 for index, column in enumerate(self.alignment.columns):
145 class SequenceCaseMarkup(base.SequenceMarkup, MarkupIOMixin):
148 io_class = 'SequenceCaseMarkup'
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'
160 def parse_item(monomer, value):
161 assert monomer.code1 == value.upper()
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):
178 class SequencePdbResiMarkup(base.SequenceMarkup, IntMarkupMixin):
182 for monomer in self.sequence:
184 monomer.pdb_resi = monomer.pdb_residue.id[1]
188 def add_pdb(self, download_pdb=None, xyz_only=False):
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]
199 self.sequence.pdb_chain = pdb_chain
200 for monomer in self.sequence:
202 pdb_residue = pdb_chain[' ', monomer.pdb_resi, ' ']
203 monomer.ca_xyz = pdb_residue['CA'].get_vector()
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).
221 * B -- Isolated beta-bridge residue
231 io_class = 'SequenceSecondaryStructureMarkup'
234 chain = self.sequence.pdb_chain
235 model = chain.get_parent()
236 pdb_file = NamedTemporaryFile(delete=False)
237 self.sequence.save_pdb(pdb_file)
239 dssp=DSSP(model, pdb_file.name, dssp='dsspcmbi')
240 for monomer in self.sequence:
242 monomer.ss = dssp[(chain.get_id(), monomer.pdb_residue.get_id())][1]
244 monomer.ss = '?' # FIXME
245 os.unlink(pdb_file.name)
247 # This MUST be the last statement in this module.
250 # vim: set ts=4 sts=4 sw=4 et: