Package Biskit :: Module ProfileMirror
[hide private]
[frames] | no frames]

Source Code for Module Biskit.ProfileMirror

  1  ## 
  2  ## Biskit, a toolkit for the manipulation of macromolecular structures 
  3  ## Copyright (C) 2004-2007 Raik Gruenberg & Johan Leckner 
  4  ## 
  5  ## This program is free software; you can redistribute it and/or 
  6  ## modify it under the terms of the GNU General Public License as 
  7  ## published by the Free Software Foundation; either version 2 of the 
  8  ## License, or any later version. 
  9  ## 
 10  ## This program is distributed in the hope that it will be useful, 
 11  ## but WITHOUT ANY WARRANTY; without even the implied warranty of 
 12  ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 
 13  ## General Public License for more details. 
 14  ## 
 15  ## You find a copy of the GNU General Public License in the file 
 16  ## license.txt along with this program; if not, write to the Free 
 17  ## Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 
 18  ## 
 19  ## last $Author: graik $ 
 20  ## last $Date: 2007/04/23 17:31:31 $ 
 21  ## $Revision: 1.1 $ 
 22  """Work in progress""" 
 23   
 24  import copy 
 25  import numpy as N 
 26   
 27  import Biskit as B 
 28  import Biskit.tools as T 
 29   
 30  from Biskit.ProfileCollection import _ViewSignal, CrossView 
 31   
32 -class ProfileMirror( B.ProfileCollection ):
33 """ 34 Access only part of an underlying ProfileCollection from a MultiModel. 35 """ 36
37 - def __init__( self, parentProfiles, map2model ):
38 """ 39 @param parentProfiles: profiles of the MultiModel 40 @type parentProfiles: ProfileCollection 41 @param map: map positions in this ProfileCollection to positions in the 42 parent profile 43 @type map: N.array of int 44 """ 45 #: feature -> model map from parent feature 46 self.map = map2model 47 48 #: a ProfileCollection of the MultiModel that is parent of the Feature 49 assert isinstance( parentProfiles, B.ProfileCollection ) 50 self.pc = parentProfiles 51 52 #: default value to use if profile is removed / changed by set() 53 self.default = None 54 55 #: support CrossView de-activation 56 self._viewSignal = _ViewSignal() 57 58 self.initVersion = self.version()
59
60 - def version( self ):
61 """Class version. 62 @return: class version number 63 @rtype: str 64 """ 65 return 'ProfileMirror $Revision: 1.1 $ on '\ 66 + B.ProfileCollection.version(self)
67 68
69 - def __len__( self ):
70 """ 71 @return: number of profiles in the collection 72 @rtype: int 73 """ 74 return len( self.pc )
75
76 - def keys( self ):
77 return self.pc.keys()
78
79 - def has_key( self, k ):
80 return self.pc.has_key(k)
81
82 - def __iter__(self):
83 """ 84 Iterate over profile keys:: 85 for k in self <==> for k in p.keys() 86 87 @return: list of items 88 @rtype: list 89 """ 90 return iter(self.pc)
91 92
93 - def getInfo( self, name ):
94 """ 95 Use:: 96 getInfo( name ) -> dict with meta infos about profile:: 97 98 Guaranteed infos: 'version'->str, 'comment'->str, 'changed'->1|0 99 100 @param name: profile name 101 @type name: str 102 103 @return: dict with infos about profile 104 @rtype: dict 105 @raise ProfileError: if no profile is found with |name| 106 """ 107 return self.pc.getInfo( name )
108 109
110 - def get( self, name, default=None ):
111 112 r = self.pc.get( name, default=None ) 113 114 if r is None: 115 r = default 116 117 if self.pc[ name, 'isarray']: 118 return N.take( r, self.map ) 119 120 return [ r[i] for i in self.map ]
121 122
123 - def setInfo( self, name, **args ):
124 """ 125 Add/Override infos about a given profile:: 126 e.g. setInfo('relASA', comment='new', params={'bin':'whatif'}) 127 128 @raise ProfileError: if no profile is found with |name| 129 """ 130 self.pc.setInfo( name, **args )
131 132
133 - def set( self, name, prof, mask=None, default=None, asarray=1, 134 comment=None, **moreInfo ):
135 """ 136 Add/override a profile. The two info records 'version', 'changed' and 137 'isarray' are always modified but can be overridden by key=value pairs 138 to this function. If the profile does not yet exist in the parent 139 ProfileCollection, a new profile is created for the whole MultiModel 140 and the values not covered by this ProfileMirror are set to <default>. 141 142 @param name: profile name (i.e. key) 143 @type name: str 144 @param prof: list of values OR None 145 @type prof: [any] OR None 146 @param mask: list 1 x N_items of 0|1, if there are less values than 147 items, provide mask with 0 for missing values, 148 N.sum(mask)==N_items 149 @type mask: [int] 150 @param default: value for items masked and for new parent profile 151 (default: None for lists, 0 for arrays] 152 @type default: any 153 @param asarray: store as list (0), as array (2) or store numbers as 154 array but everything else as list (1) (default: 1) 155 @type asarray: 0|1|2 156 @param comment: goes into info[name]['comment'] 157 @type comment: str 158 @param moreInfo: additional key-value pairs for info[name] 159 @type moreInfo: key=value 160 161 @raise ProfileError: if length of prof != length of other profiles 162 @raise ProfileError: if mask is given but N.sum(mask) != len(prof) 163 """ 164 165 ## consistency check 166 if mask and N.sum(mask) != len(prof): 167 raise ProfileError( 168 "Mask doesn't match profile ( N.sum(mask)!=len(prof) ). " + 169 "%i != %i" % (N.sum(mask), len( prof ) ) ) 170 171 r = self.pc.get( name, default=0 ) 172 173 ## take array status from existing profile 174 if not r is 0: 175 if self.pc.get( (name, 'isarray') ): 176 asarray = 2 177 else: 178 asarray = 0 179 180 prof = self.array_or_list( prof, asarray ) 181 182 ## use default == 0 for arrays 183 if not default and isinstance( prof, N.ndarray ): 184 default = 0 185 186 self.default = default 187 188 ## expand profile to have a value also for masked positions 189 prof = self.expand( prof, mask, default ) 190 191 l = len( self.map ) 192 if l and len( prof ) != l: 193 raise ProfileError( "Profile %s has wrong length." % name ) 194 195 196 ## create a new profile 197 if r is 0: 198 r = [ default ] * self.pc.profLength() 199 if isinstance( prof, N.ndarray ): 200 r = N.array( r ) 201 202 if isinstance( r, N.ndarray ): 203 N.put( r, self.map, prof ) 204 else: 205 r = N.array( r, 'O' ) 206 N.put( r, self.map, prof ) 207 r = r.tolist() 208 209 self.pc.set( name, r, asarray=asarray, comment=comment, **moreInfo )
210 211
212 - def take( self,indices, *initArgs, **initKw ):
213 """ 214 Take from profiles using provided indices:: 215 take( indices ) -> FeatureProfiles mapping to subset of parent 216 217 @param indices: list of indices into this profile (not the MultiModel) 218 @type indices: [int] 219 220 @return: new instance that maps to a new subset of positions 221 @rtype: ProfileMirror 222 """ 223 rmap = N.take( self.map, indices ) 224 return self.__class__( rmap, self.pc )
225
226 - def concat( self, *profiles ):
227 """ 228 Concatenate this with the given ProfileMirror(s).:: 229 p0.concat( p1 [, p2, ..]) -> single ProfileMirror with the 230 same number of profiles as p0 but with the length of p0+p1+p2.. 231 232 Note: it's not yet clear what meaning this will have for ProfileMirrors 233 234 @param profiles: profile(s) to concatenate 235 @type profiles: ProfileCollection(s) 236 237 @return: concatenated profile(s) 238 @rtype: ProfileCollection / subclass 239 """ 240 if len( profiles ) == 0: 241 return self 242 243 next = profiles[0] 244 245 assert isinstance( next, self.__class__ ), \ 246 'can only concat with other ProfileMirrors' 247 248 rmap = N.concatenate( (self.map, next.map ) ) 249 250 r = self.__class__( rmap, self.pc ) 251 252 return r.concat( *profiles[1:] )
253 254
255 - def remove( self, *key ):
256 """ 257 Profiles can only be removed by the parent ProfileCollection 258 @raises ProfileError: always 259 """ 260 raise B.ProfileError, 'Cannot remove profile %r from a ProfileMirror'\ 261 % key
262
263 - def clone( self ):
264 """ 265 Clone profile mirror:: 266 clone() -> ProfileMirror (or sub-class) 267 268 @return: profile mirror 269 @rtype: ProfileCollection 270 """ 271 return self.__class__( copy.copy( self.map ), self.pc )
272
273 - def clear( self ):
274 """ 275 Profiles can only be cleared by the parent ProfileCollection 276 """ 277 raise B.ProfileError, 'Cannot remove profile %r from a ProfileMirror'\ 278 % key
279
280 - def profLength( self ):
281 """ 282 Length of profile:: 283 profLength() -> int; length of first non-None profile or 0 284 285 @return: length of first non-None profile or 0 286 @rtype: int 287 """ 288 return len( self.map )
289 290 291 292 if __name__ == '__main__': 293 294 import string 295 296 p = B.ProfileCollection() 297 p['name'] = string.letters 298 p['id'] = range( len(string.letters) ) 299 300 ## mirror looks at every second position 301 mirror = ProfileMirror( p, range(0, len(string.letters), 2 ) ) 302 303 assert mirror['name'] == list( string.letters[::2] ) 304 assert N.all( mirror['id'] == range( 0, p.profLength(), 2 ) ) 305 306 ## create a new profile 307 mirror['m_id'] = range( mirror.profLength() ) 308 assert N.all( p['m_id'][::2] == mirror['m_id'] ) 309 310 mirror['name'][2] = '#' ## does not have any effect 311 mirror['name'] = ['#'] * mirror.profLength() 312 assert p['name'][::2] == ['#'] * mirror.profLength() 313 assert p['name'][1::2]== list( string.letters[1::2] ) 314