view allpy/markups.py @ 822:d87129162eb4
Implemented & tested new markup API. See #95
1) Sequences, Alignment and Blocks now have two new methods:
- add_markup(name, markup_class=optional, **kwargs=optional)
- remove_markup(name)
name refers to the same name as in aln.markups[name] or sequence[i].name
It is now explicitly denied to create markups any other way.
2) Markups now have `remove()` method that means 'release all memory that would
not be released otherwised, if we just remove markup from the dictionary'. For
sequences markups it removes markup attribute from each monomer.
3) Added necessary del sequence_markup[monomer] method.
4) Many base classes have attribute `kind`; for Alignments and Blocks it is
'alignment', for Sequences it is 'sequence' for AlignmentMarkups it is
'alignment_markup' for SequenceMarkups it is 'sequence_markup'. This attribute
is crucial for new alignment construction API.
5) Common stuff for MarkupContainers (Alignments and Sequences) is in
MarkupContainerMixin.
author |
Daniil Alexeyevsky <dendik@kodomo.fbb.msu.ru> |
date |
Fri, 15 Jul 2011 16:43:03 +0400 |
parents |
91e73fb1ac79 |
children |
4f896db3531d |
line source
4 """A dictionary of default markup name -> markup class."""
7 """Update `by_name` dictionary.
9 If any arguments are given, add them to markups namespace beforehands.
11 # Add user classes if necessary
12 for markup_class in args:
13 class_name = markup_class.__name__
14 assert class_name not in globals(), "SameNamed markup already exists!"
15 globals()[class_name] = markup_class
16 # Update `by_name` dictonary
19 for markup_class in globals().values():
20 if hasattr(markup_class, 'name') and hasattr(markup_class, 'kind'):
21 fullname = markup_class.kind, markup_class.name
22 assert fullname not in by_name, "Samenamed markup already exists!"
23 by_name[fullname] = markup_class
25 class IntMarkupMixin(base.Markup):
28 def from_record(cls, container, record, name=None):
29 assert record['io-class'] == 'IntMarkup'
30 result = container.add_markup(name, markup_class=cls)
31 separator = record.get('separator', ',')
32 values = record['markup'].split(separator)
33 assert len(values) == len(result.sorted_keys())
34 for key, value in zip(result.sorted_keys(), values):
36 result[key] = int(value)
44 values = [fmt(self.get(key)) for key in self.sorted_keys()]
45 return {'markup': ','.join(values), 'io-class': 'IntMarkup'}
47 class SequenceNumberMarkup(base.SequenceMarkup):
52 for number, monomer in enumerate(self.sequence, 1):
53 monomer.number = number
55 class SequenceIndexMarkup(base.SequenceMarkup):
60 for index, monomer in enumerate(self.sequence):
63 class AlignmentNumberMarkup(base.AlignmentMarkup):
68 for number, column in enumerate(self.alignment.columns, 1):
71 class AlignmentIndexMarkup(base.AlignmentMarkup):
76 for index, column in enumerate(self.alignment.columns):
79 class SequenceCaseMarkup(base.SequenceMarkup):
84 for monomer in self.sequence:
85 if monomer.input_code1.isupper():
86 monomer.case = 'upper'
87 elif monomer.input_code1.islower():
88 monomer.case = 'lower'
91 def from_record(cls, container, record, name=None):
92 assert record['io-class'] == 'SequenceCaseMarkup'
93 result = container.add_markup(name, markup_class=cls)
94 markup = record['markup']
95 assert markup[0] == markup[-1] == "'"
97 assert len(markup) == len(result.sequence)
98 for monomer, mark in zip(result.sequence, markup):
99 assert monomer.code1 == mark.upper()
101 monomer.case = 'upper'
103 monomer.case = 'lower'
108 for monomer in self.sequence:
109 case = self.get(monomer)
111 markup += monomer.code1.upper()
112 elif case == 'lower':
113 markup += monomer.code1.lower()
114 return {'markup': "'%s'" % markup, 'io-class': 'SequenceCaseMarkup'}
116 class SequencePdbResiMarkup(base.SequenceMarkup, IntMarkupMixin):
120 for monomer in self.sequence:
122 monomer.pdb_resi = monomer.pdb_residue.id[1]
126 def add_pdb(self, download_pdb=None, xyz_only=False):
128 if download_pdb is None:
129 download_pdb = structure.cached_download_pdb
131 match = structure.pdb_id_parse(self.sequence.name)
132 code, model , chain = match['code'], match['model'], match['chain']
133 pdb_file = download_pdb(code)
134 pdb_structure = structure.get_structure(pdb_file, self.sequence.name)
135 pdb_chain = pdb_structure[0][chain]
137 self.sequence.pdb_chain = pdb_chain
138 for monomer in self.sequence:
140 pdb_residue = pdb_chain[' ', monomer.pdb_resi, ' ']
141 monomer.ca_xyz = pdb_residue['CA'].get_vector()
143 monomer.pdb_residue = pdb_residue
145 # This MUST be the last statement in this module.
148 # vim: set ts=4 sts=4 sw=4 et: