00001 """
00002 Parameter class is equivalent to a header file for data
00003 """
00004
00005 __copyright__ = """
00006 Copyright 2008 Sean Ross-Ross
00007 """
00008 __license__ = """
00009 This file is part of SLIMpy .
00010
00011 SLIMpy is free software: you can redistribute it and/or modify
00012 it under the terms of the GNU Lesser General Public License as published by
00013 the Free Software Foundation, either version 3 of the License, or
00014 (at your option) any later version.
00015
00016 SLIMpy is distributed in the hope that it will be useful,
00017 but WITHOUT ANY WARRANTY; without even the implied warranty of
00018 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
00019 GNU Lesser General Public License for more details.
00020
00021 You should have received a copy of the GNU Lesser General Public License
00022 along with SLIMpy . If not, see <http://www.gnu.org/licenses/>.
00023 """
00024
00025 from slimpy_base.Environment.InstanceManager import InstanceManager
00026
00027
00028
00029
00030 class PSpace( object ):
00031 """
00032 parameter is a simple tracking method to pass Metadata without
00033 being bound to each specific datatype
00034 methods are similar to a python dict
00035 """
00036
00037
00038
00039
00040
00041
00042
00043 env = InstanceManager( )
00044
00045
00046
00047 def __init__(self, plugin, *E, **D ):
00048 """
00049 create a space from another space
00050 """
00051
00052 if isinstance(plugin, PSpace):
00053 self._space_dict = dict( plugin.params, *E, **D )
00054 self.plugin = plugin.plugin
00055 else:
00056 self._space_dict = dict( *E, **D )
00057 self.plugin = plugin
00058
00059
00060
00061 def _get_plugin( self ):
00062 'Get the plug-in represented by this space'
00063 return self._plugin
00064
00065 def _set_plugin(self,plugin):
00066 from slimpy_base.Core.Interface.ContainerBase import DataContainer
00067 plugin_type = type(plugin )
00068 assert plugin_type == str or issubclass(plugin, DataContainer)
00069 if isinstance( plugin, str ):
00070 self._plugin = self.env['keystone'].getplugin( plugin )
00071 else:
00072 self._plugin = plugin
00073
00074
00075 plugin = property( _get_plugin ,_set_plugin)
00076
00077
00078
00079
00080 def makeContaner( self, command=None ,tmp=None):
00081 """
00082 makeContaner( self, command=None ,tmp=None) -> Container
00083 Make a new container from the current parameters
00084
00085 """
00086 return self.plugin( parameters=self, command=command, tmp=tmp)
00087
00088
00089 def newParameter( self, *E, **F ):
00090 """
00091 Make a new parameter updated with the new keys, 'keys'
00092 """
00093 SpaceType = type(self)
00094 x = SpaceType( self.plugin, self, *E, **F )
00095 return x
00096
00097
00098 def update(self , *E, **F ):
00099 """
00100 update this PSpace with another same as a python dict
00101 """
00102
00103 for e in E:
00104
00105 if isinstance(e, PSpace):
00106 self._space_dict.update(e.params)
00107 elif e is None:
00108 pass
00109 else:
00110 self._space_dict.update(e)
00111
00112 self._space_dict.update( **F )
00113
00114 return
00115
00116
00117 def __len__(self):
00118 return self.size
00119
00120
00121 def copy( self ):
00122 """
00123 returns a shallow copy of self
00124 """
00125 SpaceType = type(self)
00126 return SpaceType( self.plugin, self._space_dict.copy( ) )
00127
00128
00129
00130 def has_key(self , k ):
00131 ' D.has_key(k) -> True if D has a key k, else False'
00132 return self._space_dict.has_key(k)
00133
00134
00135 def _get_shape( self ):
00136 """
00137 Returns a list of the dimensions of the image of the underlying vector
00138 """
00139 shp = []
00140
00141 N = 1
00142 while self.has_key( "n%s" %N ):
00143 val = self["n%s" %N]
00144 if val < 1:
00145 raise TypeError( "shape parameter does not conform to SLIMpy standard:\n"
00146 "Should be an int greater than 0" )
00147 shp.append( val )
00148 N += 1
00149
00150 if N is 1:
00151 return ( )
00152
00153 i = len( shp ) -1
00154 while i > 0 and shp[i] is 1:
00155 shp.pop( -1 )
00156 i -= 1
00157
00158 return shp
00159
00160
00161
00162 def _set_shape(self, shape ):
00163 """
00164 delete all n* keys and replace them with shape
00165 """
00166 N = 1
00167 nN = "n%s" %N
00168 while self.has_key( nN ):
00169 del self[nN]
00170 N+=1; nN = "n%s" %N
00171
00172
00173 for N,val in enumerate(shape):
00174 nN = "n%s" %(N+1)
00175 self[nN] = val
00176
00177
00178 def get_size(self):
00179
00180 mul = lambda x,y:x*y
00181 prod = lambda shape:reduce( mul, shape, 1 )
00182 shape = self.shape
00183
00184 for i in shape:
00185 if i == UnknownValue:
00186 return None
00187 if not shape:
00188 return 0
00189 else:
00190 return prod(shape)
00191
00192
00193 size = property( get_size )
00194
00195 shape = property( _get_shape, _set_shape )
00196
00197 def _get_ndim(self):
00198 return len(self.shape)
00199
00200 ndim = property( _get_ndim )
00201
00202
00203 def keys(self):
00204 return self._space_dict.keys( )
00205
00206
00207
00208 def pop(self,k,*default):
00209 return self._space_dict.pop( k, *default )
00210
00211 def _get_params(self, keep_unknown=False ):
00212 if keep_unknown:
00213 params = self._space_dict.copy( )
00214 else:
00215 itemset = [ (k,v) for (k,v) in self.iteritems() if v is not UnknownValue ]
00216 params = dict( itemset )
00217
00218 return params
00219
00220 params = property( _get_params )
00221
00222
00223 def iteritems(self):
00224 """
00225 iterates over key value pairs in self
00226 """
00227 return self._space_dict.iteritems()
00228
00229
00230 def _space_helper(self, other ,error=False):
00231 set_self = set( self.keys( ) )
00232 set_other = set( other.keys( ) )
00233
00234 intersect = set_self.intersection( set_other )
00235 diff_self = set_self.difference( set_other )
00236 diff_other = set_other.difference( set_self )
00237
00238 new = {}
00239 for key in intersect:
00240 v1 = self[key];v2 = other[key]
00241 if not self.equal_keys( other, key):
00242 if error:
00243 raise ValueError("item self[%(key)s] != other[%(key)s] ; %(v1)s != %(v2)s")
00244 else:
00245 v1 = UnknownValue
00246 v2 = UnknownValue
00247
00248 if v1 == UnknownValue:
00249 new[key] = v2
00250 else:
00251 new[key] = v1
00252
00253 SpaceType = type(self)
00254 inter_space = SpaceType( self.plugin , new )
00255 dspace_self = SpaceType( self.plugin , [ (key,self[key]) for key in diff_self] )
00256 dspace_other = SpaceType( self.plugin , [ (key,other[key]) for key in diff_other] )
00257
00258 return inter_space, dspace_self, dspace_other
00259
00260
00261 def intersection( self , other ):
00262 """
00263 space.intersection( other ) -> Space
00264
00265 returns a Space object that is the Intersection of self and other
00266 contains the restrictions of each space
00267 the shared restrictions in each must be equal:
00268 i.e. if self contains restriction n1=5 and other -> n1=6
00269 intersection method will raise error.
00270 """
00271 inter_space, dspace_self, dspace_other = self._space_helper( other, True )
00272
00273 inter_space.update( dspace_self, dspace_other )
00274
00275 return inter_space
00276
00277 def _union( self, other ):
00278 """
00279 space.union( other ) -> Space
00280
00281 returns the union of this space with another
00282 """
00283 inter_space, dspace_self, dspace_other = self._space_helper( other, False )
00284
00285 return inter_space
00286
00287
00288 def union(self, other, *others ):
00289 """
00290 space.union( other, *others ) -> Space
00291
00292 returns the union of this space with another
00293 that is only the restrictions that are the same in both spaces
00294
00295 """
00296
00297 next = self._union(other)
00298
00299 for oths in others:
00300 next = next._union( oths )
00301
00302 return next
00303
00304
00305
00306
00307
00308 def __eq__(self,other):
00309
00310 if type(self) != type(other):
00311 return False
00312
00313 test1 = self._space_dict == other._space_dict
00314 test2 = self.plugin == other.plugin
00315
00316 return test1 and test2
00317
00318
00319
00320
00321
00322 def equal_keys(self,other,k , accept_unknown=True):
00323 """
00324 space.equal_keys( space2, key, accept_unknown=True ) -> bool
00325 returns true if key is present and equal in both spaces.
00326 If one value is UnknownValue then will return accept_unknown.
00327 """
00328 if self.has_key(k) and other.has_key(k):
00329 v1 = self[k]; v2 = other[k]
00330 if v1 is UnknownValue or v2 is UnknownValue:
00331 return accept_unknown
00332 else:
00333 return v1==v2
00334 else:
00335 return False
00336
00337 def itervalues(self):
00338 return self._space_dict.itervalues()
00339 def values(self):
00340 return self._space_dict.values()
00341 def iterkeys(self):
00342 return self._space_dict.iterkeys()
00343
00344 def setdefault(self, k ,D=None ):
00345 return self._space_dict.setdefault( k, D=D )
00346
00347 def has_unknown(self):
00348 return len( [ v for v in self.itervalues() if v == UnknownValue ] )
00349
00350
00351 def is_subspace(self,other, accept_unknown=True ):
00352 """
00353 space.is_subspace(other) <--> space in other
00354 returns true if self is a subspace of other.
00355
00356 """
00357 assert isinstance(other, PSpace)
00358
00359 if self.plugin != other.plugin:
00360 return False
00361
00362 key_set = set( self.keys() )
00363 key_set_other = set( other.keys() )
00364
00365
00366 issubset = key_set_other.issubset( key_set )
00367
00368 if not issubset:
00369 return False
00370
00371 for key in key_set_other:
00372 if not self.equal_keys(other, key ,accept_unknown=accept_unknown):
00373 return False
00374
00375 return True
00376
00377
00378 def is_superspace(self,other,accept_unknown=True):
00379 return not self.is_subspace( other, accept_unknown=accept_unknown )
00380
00381
00382
00383 def __contains__(self, k):
00384 """
00385 S.__contains__( k ) <-> k in S
00386 """
00387 if isinstance( k, PSpace ):
00388 return k.is_subspace( self )
00389 elif hasattr(k, 'space') and isinstance( k.space, PSpace ):
00390 return k.space.is_subspace( self )
00391 else:
00392 return self._space_dict.__contains__( k )
00393
00394 def __getitem__(self,item):
00395 return self._space_dict[item]
00396
00397 def __delitem__(self,item):
00398 self._space_dict.__delitem__(item)
00399
00400 def get(self,k,default=None):
00401 return self._space_dict.get(k,default)
00402
00403 def __setitem__(self,item,val):
00404 self._space_dict[item] = val
00405
00406 def __repr__(self):
00407 name = self.__class__.__name__
00408 return "%s( %s, %s )" %( name, repr(self.plugin), repr(self._space_dict) )
00409
00410 def __str__(self):
00411 dtype = self.get( 'data_type', "unknown data type" )
00412 size = self.size
00413 name = self.__class__.__name__
00414 return "<%(name)s %(dtype)s:%(size)s>" %vars()
00415
00416 class umet( type ):
00417 def __str__(self):
00418 return "<Space.UnknownValue>"
00419 def __repr__(self):
00420 return "<Space.UnknownValue>"
00421
00422
00423
00424 class UnknownValue( object ):
00425 __metaclass__ = umet
00426
00427
00428 class voidSpace( PSpace ):
00429
00430 def create( self, out=0 ):
00431 """
00432 @raise TypeError: can not create data from a void space
00433 """
00434 raise TypeError( "can not create data from a void space" )
00435
00436 def testCommand( self, cmd, *args, **kargs ):
00437 """
00438 returns VoidSpace
00439 """
00440 return self