00001 """
00002 Vector Interface.
00003
00004 """
00005
00006 __copyright__ = """
00007 Copyright 2008 Sean Ross-Ross
00008 """
00009 __license__ = """
00010 This file is part of SLIMpy .
00011
00012 SLIMpy is free software: you can redistribute it and/or modify
00013 it under the terms of the GNU Lesser General Public License as published by
00014 the Free Software Foundation, either version 3 of the License, or
00015 (at your option) any later version.
00016
00017 SLIMpy is distributed in the hope that it will be useful,
00018 but WITHOUT ANY WARRANTY; without even the implied warranty of
00019 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
00020 GNU Lesser General Public License for more details.
00021
00022 You should have received a copy of the GNU Lesser General Public License
00023 along with SLIMpy . If not, see <http://www.gnu.org/licenses/>.
00024 """
00025
00026
00027 from slimpy_base.Core.Interface.AbstractDataInterface import ADI
00028 from slimpy_base.Core.Interface.node import Source
00029 from slimpy_base.Core.User.Structures.Scalar import Scalar
00030 from slimpy_base.Environment.InstanceManager import InstanceManager
00031 from slimpy_base.api.functions.vector_product import inner_product, outer_product
00032 from os.path import join
00033 from slimpy_base.api.functions import spboolean
00034 from slimpy_base.Core.User.Structures.VectorType import VectorType
00035 from slimpy_base.Core.User.Structures.VectorType import is_vector
00036 from numpy import ndarray
00037
00038
00039
00040
00041
00042 class Vector( ADI ):
00043 """
00044 When creating a SLIMpy Vector using the command
00045 vector(filename) several variables are initialized.
00046 The only input that the user should need is `file`
00047 corresponding to a file on disk. The other variables are mostly for internal use.
00048 If file is not None, creates a vector instance with a pointer to the file `file`.
00049 If create is given as a list on integers a vector with a temporary
00050 name and the given size will be created.
00051 There are more easy to use functions such as zeros to create a file
00052 """
00053
00054 name = "Vector"
00055
00056
00057 env = InstanceManager()
00058
00059
00060 __metaclass__ = VectorType
00061
00062
00063 def __new__( cls, *args ):
00064 if args and isinstance(args[0], ndarray):
00065 from slimpy_base.User.AumentedMatrix.AugVector import AugVector
00066 avec = AugVector( args[0] ).ravel()
00067 for idx, container in enumerate( avec):
00068 avec[idx] = Vector( container )
00069 return avec
00070 else:
00071 return object.__new__( cls, *args )
00072
00073
00074 def __init__( self, container ):
00075 """
00076 data - must be a data_container.
00077
00078 """
00079 ADI.__init__( self, container )
00080 self.__transpose_flag = False
00081 self.__sorted_vector = None
00082
00083
00084
00085
00086
00087 def _get_transp_flag(self):
00088 return self.__transpose_flag
00089 def _set_transp_flag(self,val):
00090 self.__transpose_flag = bool(val)
00091
00092
00093 is_transp = property( _get_transp_flag, _set_transp_flag )
00094
00095
00096
00097 def __setitem__( self, index, item ):
00098 """
00099 Sets an item in the vector dictionary
00100 """
00101 raise Exception, "not implemented. Ask me to do it later"
00102
00103
00104 def getSpace( self ):
00105 """
00106 returns a Space object that contains all of the information
00107 about this vector
00108 """
00109 from slimpy_base.Core.User.Structures.VectorSpace import VectorSpace
00110
00111 return VectorSpace( self.getParameters( ) )
00112
00113
00114 space = property( getSpace )
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132 def __setslice__( self, i, j, data ):
00133 """
00134 Writes a numarray array from index i to j to the binary
00135 file corresponding to the data_container.
00136 """
00137 raise Exception , "not implemented. Ask me to do it later"
00138
00139
00140
00141
00142
00143
00144
00145 def __add__( self, other ):
00146 """
00147 vec1.__add__(vec2) <==> vec1 + vec2
00148 """
00149 if other is 0:
00150 return self
00151 if other is self:
00152 return self *2
00153 par = other
00154 if isinstance( other, Vector ):
00155 par = Source( other.getContainer() )
00156 return self.generateNew( 'add', vec=par )
00157 else:
00158 par = self.source_or_num( par )
00159 return self.generateNew( 'add', par )
00160
00161
00162 def __radd__( self, other ):
00163 """
00164 vec1.__radd__(vec2) <==> vec2 + vec1
00165 vec2 may be a scalar or a vector
00166 """
00167
00168 return ( self + other )
00169
00170
00171 def __neg__( self ):
00172 """
00173 vec1.__neg__() <==> -vec1
00174 """
00175 return self.generateNew( 'neg' )
00176
00177
00178 def __sub__( self, other ):
00179 """
00180 self..__sub__(other) <==> self - other
00181 vec2 may be a scalar or a vector
00182 """
00183 if other is 0:
00184 return self
00185 if other is self:
00186 return self.space.zeros()
00187 par = other
00188 if isinstance( other, Vector ):
00189 par = Source( other.getContainer() )
00190 return self.generateNew( 'sub', vec=par )
00191 else:
00192 par = self.source_or_num( par )
00193 return self.generateNew( 'sub', par )
00194
00195
00196
00197 def __rsub__( self, other ):
00198 """
00199 vec1.__rsub__(vec2) <==> vec2 - vec1
00200 vec2 may be a scalar or a vector
00201 """
00202
00203 par = other
00204 if isinstance( other, Vector ):
00205 par = Source( other.getContainer() )
00206 return self.generateNew( 'rsub', vec=par )
00207 else:
00208 par = self.source_or_num( par )
00209
00210 return self.generateNew( 'rsub', par )
00211
00212
00213 def __div__( self, other ):
00214 """
00215 vec1.__div__(vec2) <==> vec1 / vec2
00216 vec2 may be a scalar or a vector
00217 """
00218 if other is 1:
00219 return self
00220 if other is self:
00221 return self.space.ones()
00222 par = other
00223 if isinstance( other, Vector ):
00224 par = Source( other.getContainer() )
00225 return self.generateNew( 'div', vec=par )
00226 else:
00227 par = self.source_or_num( par )
00228
00229 return self.generateNew( 'div', par )
00230
00231
00232 def __rdiv__( self, other ):
00233 """
00234 vec1.__rdiv__(vec2) <==> vec2 / vec1
00235 vec2 may be a scalar or a vector
00236 """
00237 par = other
00238 if isinstance( other, Vector ):
00239 par = Source( other.getContainer() )
00240 return self.generateNew( 'rdiv', vec=par )
00241 else:
00242 par = self.source_or_num( par )
00243 return self.generateNew( 'rdiv', par )
00244
00245
00246 def __mul__( self, other ):
00247 """
00248 vec1.__mul__(vec2) <==> vec1 * vec2
00249 vec2 may be a scalar or a vector
00250 """
00251 if other is 0:
00252 return 0
00253 if other is 1:
00254 return self
00255 if other is self:
00256 return self ** 2
00257
00258 par = other
00259 if isinstance( other, Vector ):
00260
00261 if self.is_transp ^ other.is_transp:
00262 if self.is_transp:
00263 return inner_product( self, other )
00264 else:
00265 return outer_product( self, other )
00266
00267 par = Source( other.getContainer() )
00268 return self.generateNew( 'mul', vec=par )
00269 else:
00270 par = self.source_or_num( par )
00271
00272 return self.generateNew( 'mul', par )
00273
00274
00275 def __rmul__( self, other ):
00276 """
00277 vec1.__rmul__(vec2) <==> vec2 * vec
00278 """
00279 return self.__mul__( other )
00280
00281
00282 def __pow__( self, other ):
00283 """
00284 vec1.__pow__(vec2) <==> vec1 ** vec2
00285 vec2 may be a scalar or a vector
00286 """
00287 if other is 1:
00288 return self
00289 par = other
00290 if isinstance( other, Vector ):
00291 par = Source( other.getContainer() )
00292 return self.generateNew( 'pow', vec=par )
00293 else:
00294 par = self.source_or_num( par )
00295
00296 return self.generateNew( 'pow', par )
00297
00298
00299 def __abs__( self ):
00300 """
00301 Vector.__abs__(vec2) <==> abs(vec1)
00302 vec2 may be a scalar or a vector
00303 """
00304 return self.generateNew( 'abs' )
00305
00306
00307
00308
00309
00310
00311 def __or__(self, other):
00312 """
00313 vec1 | vec2 -> vec3
00314 """
00315 return spboolean.or_( self, other )
00316
00317
00318 def __and__(self,other):
00319 "vec1 & vec2 -> vec3"
00320 return spboolean.and_( self, other )
00321
00322
00323 def __lt__(self,other):
00324 """
00325 vec1.__lt__(vec2) <==> vec1 < vec2
00326 """
00327 return spboolean.less_than( self, other )
00328
00329
00330 def __gt__(self,other):
00331 """
00332 vec1.__gt__(vec2) <==> vec1 > vec2
00333 """
00334 return spboolean.greater_than( self, other )
00335
00336
00337 def __le__(self,other):
00338 """
00339 vec1.__le__(vec2) <==> vec1 <= vec2
00340 """
00341 return spboolean.less_than_eq(self, other)
00342
00343
00344 def __ge__(self,other):
00345 """
00346 vec1.__lt__(vec2) <==> vec1 >= vec2
00347 """
00348 return spboolean.greater_than_eq(self, other)
00349
00350
00351 def __eq__(self,other):
00352 """
00353 vec1.__eq__(vec2) <==> vec1 == vec2
00354 """
00355 return spboolean.equal(self, other)
00356
00357
00358 def __ne__(self,other):
00359 """
00360 vec1.__ne__(vec2) <==> vec1 != vec2
00361 """
00362 return spboolean.not_equal( self, other )
00363
00364
00365
00366
00367 def thr( self, obj, mode='soft' ):
00368 """
00369 Returns a thresholded vector.
00370 obj - may be a scalar or a vector.
00371 mode - may be 'soft', 'hard' or 'nng'
00372 """
00373 par = obj
00374 if isinstance( obj, Vector ):
00375 par = Source( obj.getContainer() )
00376 return self.generateNew( 'thr' , mode=mode, fthr=par )
00377 else:
00378 par = self.source_or_num( par )
00379
00380 return self.generateNew( 'thr' , mode=mode, thr=par )
00381
00382
00383 def thrhard( self, obj ):
00384 """
00385 Returns a thresholded vector.
00386 obj - may be a scalar or a vector.
00387 Same as vector.sort(obj,'hard')
00388 """
00389 return self.thr( obj, mode='hard' )
00390
00391 def garrote( self, obj ):
00392 """
00393 Returns a garroted vector.
00394 obj - may be a scalar or a vector.
00395 Same as vector.sort(obj,'nng')
00396 """
00397 return self.thr( obj, mode='nng' )
00398
00399
00400
00401
00402
00403 def sort( self, ascmode=False, memsize=None ):
00404 """
00405 Returns a vector with a sorted data set.
00406 """
00407 if memsize is None:
00408 memsize = self.env['slimvars']['memsize']
00409
00410 return self.generateNew( "sort", memsize=memsize, ascmode=ascmode )
00411
00412
00413 def __real__( self ):
00414 """
00415 Returns a vector containing the real component of a complex vector.
00416 """
00417 if self.space.isComplex():
00418 return self.generateNew( 'real' )
00419 else:
00420 return self
00421
00422
00423 def __imag__( self ):
00424 """
00425 Returns a vector containing the imaginary component of a complex vector.
00426 """
00427 return self.generateNew( 'imag' )
00428
00429
00430
00431
00432 real = __real__
00433 imag = __imag__
00434
00435
00436
00437
00438
00439
00440
00441
00442
00443 def __getitem__( self, index ):
00444 """
00445 If index is a string: Returns an item from one of the dictionaries.
00446 Checks the vector dictionary first.
00447 If index is a number: Returns a number at index from the binary file.
00448 """
00449
00450 if isinstance( index, (int,Scalar) ):
00451 ind = self.source_or_num(index)
00452 return self.scalar_reduction( 'getitem', ind )
00453
00454 elif isinstance( index, str ):
00455 raise Exception, "not implemented. Ask me to do it later"
00456
00457 elif isinstance( index, slice ):
00458
00459 l = len( self.getSpace() )
00460 ind = index.indices( l )
00461 return self.scalar_reduction( 'getslice', ind )
00462 else:
00463 raise TypeError , "expected int or string got %s" % type( index )
00464
00465
00466
00467 def rms( self ):
00468 """ Returns the root mean square"""
00469 return self.scalar_reduction( 'rms' )
00470
00471
00472
00473 def max( self ):
00474 """ Returns the maximum value"""
00475 return self.scalar_reduction( 'max' )
00476
00477
00478
00479 def min( self ):
00480 """ Returns the minimum value"""
00481 return self.scalar_reduction( 'min' )
00482
00483
00484
00485 def mean( self ):
00486 """ Returns the mean value"""
00487 return self.scalar_reduction( 'mean' )
00488
00489
00490
00491 def var( self ):
00492 """ Returns the variance"""
00493 return self.scalar_reduction( 'var' )
00494
00495
00496
00497 def sdt( self ):
00498 """ Returns the standard deviation"""
00499 return self.scalar_reduction( 'std' )
00500
00501
00502
00503
00504 def norm( self, lval=2 ):
00505 """ Returns the lval norm of the vector """
00506 return self.scalar_reduction( 'norm', lval )
00507
00508
00509
00510 def orderstat( self, i ):
00511 """
00512 Returns the ith order statistic of the vector (ith smallest element),
00513 i.e. i=0 is smallest, i=1 second smallest, etc.)
00514 Negative indexing starts with the largest element, i.e. i=-1 is largest,
00515 i=-2 second largest, etc.
00516 """
00517 if not 'sorted' in self.__dict__:
00518 self.sorted = self.sort( ascmode=False )
00519
00520 if i<0:
00521 i = len( self.getSpace() ) + i
00522
00523 return self.sorted[i]
00524
00525
00526
00527
00528
00529
00530
00531
00532
00533
00534
00535
00536
00537
00538 def conj( self ):
00539 """
00540 return vector conjugate of data
00541 """
00542 if self.space.isComplex():
00543 return self.generateNew( 'conj' )
00544 else:
00545 return self
00546
00547
00548 def grad( self ):
00549 """
00550 Returns a vector containing the gradient of the vector.
00551 """
00552
00553 return self.generateNew( 'grad' )
00554
00555
00556 def noise( self, mean=0, seed=None ):
00557 """
00558 Returns vector with added random noise.
00559 mean - noise mean
00560 seed - noise seed
00561 """
00562 param = dict( mean=mean, seed=seed )
00563 if seed is None:
00564 param.pop( 'seed', None )
00565
00566 return self.generateNew( 'noise', **param )
00567
00568
00569
00570
00571 def transp( self, a1=1, a2=2, memsize=100 ):
00572 """
00573 transpose a dataset
00574 """
00575 if a1 == a2:
00576 return self
00577
00578 return self.generateNew( 'transp', plane=( a1, a2 ), memsize=memsize )
00579
00580
00581
00582
00583
00584 def _transpose(self):
00585 vec = Vector( self.container )
00586 vec.is_transp = not vec.is_transp
00587 return vec
00588
00589
00590
00591 T = property( _transpose )
00592
00593 def _conj_transp(self):
00594
00595 vec = Vector(self.container).conj( )
00596 vec.is_transp = not self.is_transp
00597 return vec
00598
00599 H = property( _conj_transp )
00600
00601
00602 def setName( self, name, path=None ):
00603 """
00604 set the name of this vector. Makes it non persistent.
00605 """
00606 if not path is None:
00607 name = join( path, name )
00608
00609 container = self.getContainer()
00610
00611 container.setName( name , path=None )
00612 self.env['graphmgr'].add_target( container )
00613
00614 return self
00615
00616
00617
00618 def plot( self, command=None, plotcmd=None ):
00619 """
00620 calls plot method of this vectors container
00621 """
00622 try:
00623 self.flush()
00624 except:
00625 pass
00626 self.container.plot( command=command, plotcmd=plotcmd )
00627
00628
00629
00630 def reshape(self, *shape):
00631 if len(shape) is 1 and isinstance(shape[0], (list,tuple)):
00632 shape = shape[0]
00633
00634 return self.generateNew( "reshape" , shape=shape )
00635
00636
00637 isvector = lambda obj : isinstance( obj, Vector )