allpy
diff allpy/_monomer.py @ 251:9369dbad919d
Incompatible changes to Monomer interfaces.
This branch does not work!
- (!!) only changed allpy._monomer, not uses
- (!!) removed (temporarily) classes for specific monomer types (DNAMonomer, etc)
- refurbished allpy.data.AAcodes to allpy.data.codes with much cleaner
interface
- refurbished allpy._monomer for simplicity and more friendly interface
Now it will (someday) be possible to say:
a = Monomer.from_name("alanine")
b = protein.Monomer.from_code1("a")
c = protein.MonomerType.from_code3("ala")
d = dna.Monomer.from_code3("DA")
but impossible to say:
d = protein.Monomer.from_code3("DA")
author | Daniil Alexeyevsky <me.dendik@gmail.com> |
---|---|
date | Mon, 13 Dec 2010 20:12:11 +0300 |
parents | fc6418e32e3c |
children | 4033c9b05888 |
line diff
1.1 --- a/allpy/_monomer.py Tue Dec 07 20:22:19 2010 +0300 1.2 +++ b/allpy/_monomer.py Mon Dec 13 20:12:11 2010 +0300 1.3 @@ -1,99 +1,116 @@ 1.4 #!/usr/bin/python 1.5 1.6 -from data.AAdict import AAdict 1.7 - 1.8 -index_code3 = {} 1.9 -index_code1 = {} 1.10 -index_name = {} 1.11 +import data.codes as table 1.12 1.13 class MonomerType(object): 1.14 - """ Monomer type 1.15 - 1.16 - name -- string like "Valine" 1.17 - code1 -- one-letter code (in upper case) 1.18 - code3 -- three-letter code (in upper case) 1.19 - is_modified -- True of False 1.20 + """Class of monomer types. 1.21 + 1.22 + Each MonomerType object represents a known monomer type, e.g. Valine, 1.23 + and is referenced to by each instance of monomer in a given sequence. 1.24 + 1.25 + - `name`: full name of monomer type 1.26 + - `code1`: one-letter code 1.27 + - `code3`: three-letter code 1.28 + - `is_modified`: either of True or False 1.29 + 1.30 + class atributes: 1.31 + - `by_code1`: a mapping from one-letter code to MonomerType object 1.32 + - `by_code3`: a mapping from three-letter code to MonomerType object 1.33 + - `by_name`: a mapping from monomer name to MonomerType object 1.34 + - `instance_type`: class of Monomer objects to use when creating new 1.35 + objects; this must be redefined in descendent classes 1.36 + 1.37 + All of the class attributes MUST be redefined when subclassing. 1.38 """ 1.39 1.40 - instance_type = None # Must be redefined when subclassing 1.41 - 1.42 - def __init__(self, name, code1, code3, is_modified=False): 1.43 + by_code1 = {} 1.44 + by_code3 = {} 1.45 + by_name = {} 1.46 + instance_type = None 1.47 + 1.48 + def __init__(self, name="", code1="", code3="", is_modified=False): 1.49 self.name = name.capitalize() 1.50 self.code1 = code1.upper() 1.51 self.code3 = code3.upper() 1.52 - self.is_modified = bool(is_modified) # ugly 1.53 + self.is_modified = bool(is_modified) 1.54 + if not is_modified: 1.55 + self.by_code1[self.code1] = self 1.56 + self.by_code3[code3] = self 1.57 + self.by_name[name] = self 1.58 + # We duplicate distinguished long names into MonomerType itself, 1.59 + # so that we can use MonomerType.from_code3 to create the relevant 1.60 + # type of monomer. 1.61 + MonomerType.by_code3[code3] = self 1.62 + MonomerType.by_name[name] = self 1.63 1.64 @classmethod 1.65 - def create(cls, name, code1, code3, is_modified=False): 1.66 - self = cls(name, code1, code3, is_modified) 1.67 - index_name[self.name] = self 1.68 - index_code3[self.code3] = self 1.69 - if not is_modified: 1.70 - if cls not in index_code1: 1.71 - index_code1[cls] = {} 1.72 - index_code1[cls][code1] = self 1.73 - 1.74 + def _initialize(cls, type_letter, codes=table.codes): 1.75 + """Create all relevant instances of MonomerType. 1.76 + 1.77 + `type_letter` is either of: 1.78 + - 'p' for protein 1.79 + - 'd' for DNA 1.80 + - 'r' for RNA 1.81 + 1.82 + `codes` is a table of monomer codes 1.83 + """ 1.84 + for type, code1, is_modified, code3, name in codes: 1.85 + if type == type_letter: 1.86 + cls(name, code1, code3, is_modified) 1.87 + 1.88 @classmethod 1.89 def from_code1(cls, code1): 1.90 - return index_code1[cls][code1.upper()] 1.91 + """Return monomer type by one-letter code.""" 1.92 + return cls.by_code1[code1.upper()] 1.93 1.94 - @staticmethod 1.95 - def from_name(name): 1.96 - return index_name[name.capitalize()] 1.97 - 1.98 - @staticmethod 1.99 - def from_pdb_residue(pdb_residue): 1.100 - """ pdb_residue type is Bio.PDB.Residue """ 1.101 - return MonomerType.from_code3(pdb_residue.get_resname()) 1.102 - 1.103 - # TO DISCUSS 1.104 - def __eq__(self, other): 1.105 - return self.code1 == other.code1 1.106 + @clasmethod 1.107 + def from_code3(cls, code3): 1.108 + """Return monomer type by three-letter code.""" 1.109 + return cls.by_code3[code3.upper()] 1.110 1.111 - def __ne__(self, other): 1.112 - return not (self == other) 1.113 - 1.114 + @classmethod 1.115 + def from_name(cls, name): 1.116 + """Return monomer type by name.""" 1.117 + return cls.by_name[name.capitalize()] 1.118 + 1.119 def instance(self): 1.120 + """Create a new monomer of given type.""" 1.121 return self.instance_type(self) 1.122 1.123 + def __eq__(self, other): 1.124 + if hasattr(other, "type"): 1.125 + return self is other.type 1.126 + return self is other 1.127 + 1.128 class Monomer(object): 1.129 - """ Monomer 1.130 - 1.131 - type -- link to MonomerType object 1.132 + """Monomer object. 1.133 + 1.134 + attributes: 1.135 + - `type`: type of monomer (a MonomerType object) 1.136 + 1.137 + class attribute `monomer_type` is MonomerType or either of it's subclasses, 1.138 + it is used when creating new monomers. It MUST be redefined when subclassing Monomer. 1.139 """ 1.140 - def __init__(self, monomer_type): 1.141 - self.type = monomer_type 1.142 - 1.143 + monomer_type = MonomerType 1.144 + 1.145 + def __init__(self, type): 1.146 + self.type = type 1.147 + 1.148 + @classmethod 1.149 + def from_code1(cls, code1): 1.150 + return cls(cls.monomer_type.by_code1[code1.upper()]) 1.151 + 1.152 + @classmethod 1.153 + def from_code3(cls, code3): 1.154 + return cls(cls.monomer_type.by_code3[code3.upper()]) 1.155 + 1.156 + @classmethod 1.157 + def from_name(cls, name): 1.158 + return cls(cls.monomer_type.by_name[name.capitalize()]) 1.159 + 1.160 def __eq__(self, other): 1.161 - return self.type == other.type 1.162 - 1.163 - def __ne__(self, other): 1.164 - return not (self == other) 1.165 - 1.166 - 1.167 -class AminoAcidType(MonomerType): 1.168 - instance_type = AminoAcid 1.169 -class DNAType(MonomerType): 1.170 - instance_type = DNA 1.171 -class RNAType(MonomerType): 1.172 - instance_type = RNA 1.173 - 1.174 -class AminoAcid(Monomer): 1.175 - pass 1.176 -class DNA(Monomer): 1.177 - pass 1.178 -class RNA(Monomer): 1.179 - pass 1.180 - 1.181 -types = {'p': AminoAcidType, 'd': DNAType, 'r': RNAType} 1.182 - 1.183 -# prepare all aminoacids 1.184 - 1.185 -for code3, data in AAdict.items(): 1.186 - code1, m_type, is_modified, none, name = data 1.187 - monomer_type = types[m_type] 1.188 - monomer_type.create(name, code1, code3, is_modified) 1.189 -del code3, data, code1, m_type, is_modified, none, name 1.190 - 1.191 + if hasattr(other, "type"): 1.192 + return self.type is other.type 1.193 + return self.type is other 1.194 1.195 # vim: set ts=4 sts=4 sw=4 et: