allpy
diff allpy/base.py @ 724:fd531580b9af
Merge between Burkov and others.
author | Boris Burkov <BurkovBA@gmail.com> |
---|---|
date | Fri, 08 Jul 2011 16:20:20 +0400 |
parents | b71f9c1d1509 83a40cd34923 |
children | 0a7917b4ca71 |
line diff
1.1 --- a/allpy/base.py Fri Jul 08 16:06:59 2011 +0400 1.2 +++ b/allpy/base.py Fri Jul 08 16:20:20 2011 +0400 1.3 @@ -221,17 +221,13 @@ 1.4 If sequences in file have gaps (detected as characters belonging to 1.5 `gaps` set), treat them accordingly. 1.6 """ 1.7 - sequences = [] 1.8 - io = fileio.File(file, format) 1.9 - for name, description, body in io.read_strings(): 1.10 - self.append_row_from_string(body, name, description, file.name, gaps) 1.11 + fileio.File(file, format, gaps=gaps).read_alignment(self) 1.12 return self 1.13 1.14 def to_file(self, file, format='fasta', gap='-'): 1.15 """Write alignment in FASTA file as sequences with gaps.""" 1.16 - strings = [(s, s.sequence.name, s.sequence.description) 1.17 - for s in self.rows_as_strings()] 1.18 - fileio.File(file, format).write_strings(strings) 1.19 + fileio.File(file, format, gaps=gap).write_alignment(self) 1.20 + return self 1.21 1.22 # Data access methods for alignment 1.23 # ================================= 1.24 @@ -510,11 +506,27 @@ 1.25 return block 1.26 1.27 class Markup(object): 1.28 + """Base class for sequence and alignment markups. 1.29 + 1.30 + We shall call either sequence or alignment a container. And we shall call 1.31 + either monomers or columns elements respectively. 1.32 + 1.33 + Markup behaves like a dictionary of [element] -> value. 1.34 + 1.35 + Every container has a dictionary of [name] -> markup. It is Markup's 1.36 + responsibility to add itself to this dictionary and to avoid collisions 1.37 + while doing it. 1.38 + """ 1.39 1.40 name = None 1.41 """Name of markup elements""" 1.42 1.43 def _register(self, container, name): 1.44 + """Register self within container. 1.45 + 1.46 + Assure the name is not taken before. If name is not given, look in the 1.47 + class. Make sure we have some name at all. 1.48 + """ 1.49 if name: 1.50 self.name = name 1.51 assert self.name is not None 1.52 @@ -522,37 +534,94 @@ 1.53 container.markups[self.name] = self 1.54 1.55 def refresh(self): 1.56 + """Recalculate markup values (if they are generated automatically).""" 1.57 pass 1.58 1.59 + @classmethod 1.60 + def from_record(cls, container, record, name=None): 1.61 + """Restore markup from `record`. (Used for loading from file). 1.62 + 1.63 + `record` is a dict of all metadata and data related to one markup. All 1.64 + keys and values in `record` are strings, markup must parse them itself. 1.65 + 1.66 + Markup values should be stored in `record['markup']`, which is a list 1.67 + of items separated with either `record['separator']` or a comma. 1.68 + """ 1.69 + return cls(container, name) 1.70 + 1.71 + def to_record(self): 1.72 + """Save markup to `record`, for saving to file. 1.73 + 1.74 + For description of `record` see docstring for `from_record` method. 1.75 + """ 1.76 + return {} 1.77 + 1.78 + def sorted_keys(self): 1.79 + """Return list of elements in the container in proper order.""" 1.80 + raise NotImplementedError() 1.81 + 1.82 + def sorted_values(self): 1.83 + """Return list of markup values in container.""" 1.84 + raise NotImplementedError() 1.85 + 1.86 class SequenceMarkup(Markup): 1.87 + """Markup for sequence. 1.88 + 1.89 + Behaves like a dictionary of [monomer] -> value. Value may be anything 1.90 + or something specific, depending on subclass. 1.91 + 1.92 + Actual values are stored in monomers themselves as attributes. 1.93 + """ 1.94 1.95 def __init__(self, sequence, name=None): 1.96 self.sequence = sequence 1.97 self._register(sequence, name) 1.98 self.refresh() 1.99 1.100 - def as_list(self): 1.101 - for monomer in self.sequence: 1.102 - yield self[monomer] 1.103 + def sorted_keys(self): 1.104 + """Return list of monomers.""" 1.105 + return self.sequence 1.106 + 1.107 + def sorted_values(self): 1.108 + """Return list of markup values, if every monomer is marked up.""" 1.109 + return (self[monomer] for monomer in self.sequence) 1.110 + 1.111 + def get(self, key, value=None): 1.112 + """Part of Mapping collection interface.""" 1.113 + if key not in self: 1.114 + return value 1.115 + return self[key] 1.116 1.117 def __contains__(self, monomer): 1.118 - return monomer in self.sequence 1.119 + """Part of Mapping collection interface.""" 1.120 + return hasattr(monomer, self.name) 1.121 1.122 def __getitem__(self, monomer): 1.123 + """Part of Mapping collection interface.""" 1.124 return getattr(monomer, self.name) 1.125 1.126 def __setitem__(self, monomer, value): 1.127 + """Part of Mapping collection interface.""" 1.128 return setattr(monomer, self.name, value) 1.129 1.130 class AlignmentMarkup(dict, Markup): 1.131 + """Markupf for alignment. 1.132 + 1.133 + Is a dictionary of [column] -> value. Value may be anything or something 1.134 + specific, depending on subclass. 1.135 + """ 1.136 1.137 def __init__(self, alignment, name=None): 1.138 self.alignment = alignment 1.139 self._register(alignment, name) 1.140 self.refresh() 1.141 1.142 - def as_list(self): 1.143 - for column in self.alignment.columns: 1.144 - yield self[column] 1.145 + def sorted_keys(self): 1.146 + """Return a list of columns.""" 1.147 + return self.alignment.columns 1.148 + 1.149 + def sorted_values(self): 1.150 + """Return a list of makrup values, if every column is marked up.""" 1.151 + return (self[column] for column in self.alignment.columns) 1.152 1.153 # vim: set ts=4 sts=4 sw=4 et: