allpy
diff allpy/base.py @ 328:e3bcb9f8d7b0
Got rid of all MonomerType classes
author | Daniil Alexeyevsky <me.dendik@gmail.com> |
---|---|
date | Fri, 17 Dec 2010 16:28:58 +0300 |
parents | 6fdc4406e2fd |
children | 9bf144c25dbd |
line diff
1.1 --- a/allpy/base.py Fri Dec 17 00:58:54 2010 +0300 1.2 +++ b/allpy/base.py Fri Dec 17 16:28:58 2010 +0300 1.3 @@ -7,140 +7,71 @@ 1.4 default_gaps = set((".", "-", "~")) 1.5 """Set of characters to recoginze as gaps when parsing alignment.""" 1.6 1.7 -class MonomerType(object): 1.8 - """Class of monomer types. 1.9 +class Monomer(object): 1.10 + """Monomer object.""" 1.11 1.12 - Each MonomerType object represents a known monomer type, e.g. Valine, 1.13 - and is referenced to by each instance of monomer in a given sequence. 1.14 - 1.15 - - `name`: full name of monomer type 1.16 - - `code1`: one-letter code 1.17 - - `code3`: three-letter code 1.18 - - `is_modified`: either of True or False 1.19 - 1.20 - class atributes: 1.21 - 1.22 - - `by_code1`: a mapping from one-letter code to MonomerType object 1.23 - - `by_code3`: a mapping from three-letter code to MonomerType object 1.24 - - `by_name`: a mapping from monomer name to MonomerType object 1.25 - - `instance_type`: class of Monomer objects to use when creating new 1.26 - objects; this must be redefined in descendent classes 1.27 - 1.28 - All of the class attributes MUST be redefined when subclassing. 1.29 - """ 1.30 + type = None 1.31 + """Either of 'dna', 'rna', 'protein'.""" 1.32 1.33 by_code1 = {} 1.34 + """A mapping from 1-letter code to Monomer subclass.""" 1.35 + 1.36 by_code3 = {} 1.37 + """A mapping from 3-letter code to Monomer subclass.""" 1.38 + 1.39 by_name = {} 1.40 - instance_type = None 1.41 - 1.42 - def __init__(self, name="", code1="", code3="", is_modified=False): 1.43 - super(MonomerType, self).__init__() 1.44 - self.name = name.capitalize() 1.45 - self.code1 = code1.upper() 1.46 - self.code3 = code3.upper() 1.47 - self.is_modified = bool(is_modified) 1.48 - if not is_modified: 1.49 - self.by_code1[self.code1] = self 1.50 - self.by_code3[code3] = self 1.51 - self.by_name[name] = self 1.52 - # We duplicate distinguished long names into MonomerType itself, 1.53 - # so that we can use MonomerType.from_code3 to create the relevant 1.54 - # type of monomer. 1.55 - MonomerType.by_code3[code3] = self 1.56 - MonomerType.by_name[name] = self 1.57 + """A mapping from full monomer name to Monomer subclass.""" 1.58 1.59 @classmethod 1.60 - def _initialize(cls, type_letter, codes=data.codes.codes): 1.61 - """Create all relevant instances of MonomerType. 1.62 + def _subclass(cls, name='', code1='', code3='', is_modified=False): 1.63 + """Create new subclass of Monomer for given monomer type.""" 1.64 + class TheMonomer(cls): 1.65 + pass 1.66 + name = name.strip().capitalize() 1.67 + code1 = code1.upper() 1.68 + code3 = code3.upper() 1.69 + TheMonomer.__name__ = "Monomer" 1.70 + TheMonomer.name = name 1.71 + TheMonomer.code1 = code1 1.72 + TheMonomer.code3 = code3 1.73 + TheMonomer.is_modified = is_modified 1.74 + if not is_modified: 1.75 + cls.by_code1[code1] = TheMonomer 1.76 + cls.by_code3[code3] = TheMonomer 1.77 + cls.by_name[name] = TheMonomer 1.78 + # We duplicate distinguished long names into Monomer itself, so that we 1.79 + # can use Monomer.from_code3 to create the relevant type of monomer. 1.80 + Monomer.by_code3[code3] = TheMonomer 1.81 + Monomer.by_name[name] = TheMonomer 1.82 1.83 - `type_letter` is either of: 1.84 - 1.85 - - 'p' for protein 1.86 - - 'd' for DNA 1.87 - - 'r' for RNA 1.88 - 1.89 - `codes` is a table of monomer codes 1.90 - """ 1.91 + @classmethod 1.92 + def _initialize(cls, codes=data.codes.codes): 1.93 + """Create all relevant subclasses of Monomer.""" 1.94 + # NB. The table uses letters d, r, p for types, 1.95 + # while we use full words; hence, we compare by first letter 1.96 for type, code1, is_modified, code3, name in codes: 1.97 - if type == type_letter: 1.98 - cls(name, code1, code3, is_modified) 1.99 + if type[0] == cls.type[0]: 1.100 + cls._subclass(name, code1, code3, is_modified) 1.101 1.102 @classmethod 1.103 def from_code1(cls, code1): 1.104 - """Return monomer type by one-letter code.""" 1.105 - return cls.by_code1[code1.upper()] 1.106 + """Create new monomer from 1-letter code.""" 1.107 + return cls.by_code1[code1.upper()]() 1.108 1.109 @classmethod 1.110 def from_code3(cls, code3): 1.111 - """Return monomer type by three-letter code.""" 1.112 - return cls.by_code3[code3.upper()] 1.113 + """Create new monomer from 3-letter code.""" 1.114 + return cls.by_code3[code3.upper()]() 1.115 1.116 @classmethod 1.117 def from_name(cls, name): 1.118 - """Return monomer type by name.""" 1.119 - return cls.by_name[name.capitalize()] 1.120 - 1.121 - def instance(self): 1.122 - """Create a new monomer of given type.""" 1.123 - return self.instance_type(self) 1.124 + """Create new monomer from full name.""" 1.125 + return cls.by_name[name.strip().capitalize()]() 1.126 1.127 def __eq__(self, other): 1.128 - if hasattr(other, "type"): 1.129 - return self is other.type 1.130 - return self is other 1.131 - 1.132 -class Monomer(object): 1.133 - """Monomer object. 1.134 - 1.135 - attributes: 1.136 - 1.137 - - `type`: type of monomer (a MonomerType object) 1.138 - 1.139 - class attributes: 1.140 - 1.141 - - `monomer_type`: either MonomerType or one of it's subclasses, it is used 1.142 - when creating new monomers. It SHOULD be redefined when subclassing 1.143 - Monomer. 1.144 - """ 1.145 - monomer_type = MonomerType 1.146 - 1.147 - def __init__(self, type): 1.148 - super(Monomer, self).__init__() 1.149 - self.type = type 1.150 - 1.151 - @classmethod 1.152 - def from_code1(cls, code1): 1.153 - return cls(cls.monomer_type.by_code1[code1.upper()]) 1.154 - 1.155 - @classmethod 1.156 - def from_code3(cls, code3): 1.157 - return cls(cls.monomer_type.by_code3[code3.upper()]) 1.158 - 1.159 - @classmethod 1.160 - def from_name(cls, name): 1.161 - return cls(cls.monomer_type.by_name[name.capitalize()]) 1.162 - 1.163 - @property 1.164 - def code1(self): 1.165 - return self.type.code1 1.166 - 1.167 - @property 1.168 - def code3(self): 1.169 - return self.type.code3 1.170 - 1.171 - @property 1.172 - def name(self): 1.173 - return self.type.name 1.174 - 1.175 - @property 1.176 - def is_modified(self): 1.177 - return self.type.is_modified 1.178 - 1.179 - def __eq__(self, other): 1.180 - if hasattr(other, "type"): 1.181 - return self.type is other.type 1.182 - return self.type is other 1.183 + """Monomers within same monomer type are compared by code1.""" 1.184 + assert self.type == other.type 1.185 + return self.code1 == other.code1 1.186 1.187 class Sequence(list): 1.188 """Sequence of Monomers.