Package paramz :: Package core :: Module observable_array
[hide private]
[frames] | no frames]

Source Code for Module paramz.core.observable_array

  1  #=============================================================================== 
  2  # Copyright (c) 2015, Max Zwiessele 
  3  # All rights reserved. 
  4  # 
  5  # Redistribution and use in source and binary forms, with or without 
  6  # modification, are permitted provided that the following conditions are met: 
  7  # 
  8  # * Redistributions of source code must retain the above copyright notice, this 
  9  #   list of conditions and the following disclaimer. 
 10  # 
 11  # * Redistributions in binary form must reproduce the above copyright notice, 
 12  #   this list of conditions and the following disclaimer in the documentation 
 13  #   and/or other materials provided with the distribution. 
 14  # 
 15  # * Neither the name of paramax nor the names of its 
 16  #   contributors may be used to endorse or promote products derived from 
 17  #   this software without specific prior written permission. 
 18  # 
 19  # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
 20  # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
 21  # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
 22  # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 
 23  # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
 24  # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 
 25  # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 
 26  # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 
 27  # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
 28  # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
 29  #=============================================================================== 
 30   
 31   
 32  import numpy as np 
 33  from .pickleable import Pickleable 
 34  from .observable import Observable 
35 36 -class ObsAr(np.ndarray, Pickleable, Observable):
37 """ 38 An ndarray which reports changes to its observers. 39 40 .. warning:: 41 42 ObsAr tries to not ever give back an observable array itself. Thus, 43 if you want to preserve an ObsAr you need to work in memory. Let 44 `a` be an ObsAr and you want to add a random number `r` to it. You need to 45 make sure it stays an ObsAr by working in memory (see numpy for details): 46 47 .. code-block:: python 48 49 a[:] += r 50 51 The observers can add themselves with a callable, which 52 will be called every time this array changes. The callable 53 takes exactly one argument, which is this array itself. 54 """ 55 __array_priority__ = -1 # Never give back ObsAr
56 - def __new__(cls, input_array, *a, **kw):
57 # allways make a copy of input paramters, as we need it to be in C order: 58 if not isinstance(input_array, ObsAr): 59 try: 60 # try to cast ints to floats 61 obj = np.atleast_1d(np.require(input_array, dtype=np.float_, requirements=['W', 'C'])).view(cls) 62 except ValueError: 63 # do we have other dtypes in the array? 64 obj = np.atleast_1d(np.require(input_array, requirements=['W', 'C'])).view(cls) 65 else: obj = input_array 66 super(ObsAr, obj).__init__(*a, **kw) 67 return obj
68
69 - def __array_finalize__(self, obj):
70 # see InfoArray.__array_finalize__ for comments 71 if obj is None: return 72 self.observers = getattr(obj, 'observers', None) 73 self._update_on = getattr(obj, '_update_on', None)
74
75 - def __array_wrap__(self, out_arr, context=None):
76 #np.ndarray.__array_wrap__(self, out_arr, context) 77 #return out_arr 78 return out_arr.view(np.ndarray)
79
80 - def _setup_observers(self):
81 # do not setup anything, as observable arrays do not have default observers 82 pass
83 84 @property
85 - def values(self):
86 """ 87 Return the ObsAr underlying array as a standard ndarray. 88 """ 89 return self.view(np.ndarray)
90
91 - def copy(self):
92 """ 93 Make a copy. This means, we delete all observers and return a copy of this 94 array. It will still be an ObsAr! 95 """ 96 from .lists_and_dicts import ObserverList 97 memo = {} 98 memo[id(self)] = self 99 memo[id(self.observers)] = ObserverList() 100 return self.__deepcopy__(memo)
101
102 - def __deepcopy__(self, memo):
103 s = self.__new__(self.__class__, input_array=self.view(np.ndarray).copy()) 104 memo[id(self)] = s 105 import copy 106 Pickleable.__setstate__(s, copy.deepcopy(self.__getstate__(), memo)) 107 return s
108
109 - def __reduce__(self):
110 func, args, state = super(ObsAr, self).__reduce__() 111 return func, args, (state, Pickleable.__getstate__(self))
112
113 - def __setstate__(self, state):
114 np.ndarray.__setstate__(self, state[0]) 115 Pickleable.__setstate__(self, state[1])
116
117 - def __setitem__(self, s, val):
118 super(ObsAr, self).__setitem__(s, val) 119 self.notify_observers()
120
121 - def __getslice__(self, start, stop): #pragma: no cover
122 return self.__getitem__(slice(start, stop))
123
124 - def __setslice__(self, start, stop, val): #pragma: no cover
125 return self.__setitem__(slice(start, stop), val) 126
127 - def __ilshift__(self, *args, **kwargs): #pragma: no cover
128 r = np.ndarray.__ilshift__(self, *args, **kwargs) 129 self.notify_observers() 130 return r 131
132 - def __irshift__(self, *args, **kwargs): #pragma: no cover
133 r = np.ndarray.__irshift__(self, *args, **kwargs) 134 self.notify_observers() 135 return r 136 137
138 - def __ixor__(self, *args, **kwargs): #pragma: no cover
139 r = np.ndarray.__ixor__(self, *args, **kwargs) 140 self.notify_observers() 141 return r 142 143
144 - def __ipow__(self, *args, **kwargs): #pragma: no cover
145 r = np.ndarray.__ipow__(self, *args, **kwargs) 146 self.notify_observers() 147 return r 148 149
150 - def __ifloordiv__(self, *args, **kwargs): #pragma: no cover
151 r = np.ndarray.__ifloordiv__(self, *args, **kwargs) 152 self.notify_observers() 153 return r 154 155
156 - def __isub__(self, *args, **kwargs): #pragma: no cover
157 r = np.ndarray.__isub__(self, *args, **kwargs) 158 self.notify_observers() 159 return r 160 161
162 - def __ior__(self, *args, **kwargs): #pragma: no cover
163 r = np.ndarray.__ior__(self, *args, **kwargs) 164 self.notify_observers() 165 return r 166 167
168 - def __itruediv__(self, *args, **kwargs): #pragma: no cover
169 r = np.ndarray.__itruediv__(self, *args, **kwargs) 170 self.notify_observers() 171 return r 172 173
174 - def __idiv__(self, *args, **kwargs): #pragma: no cover
175 r = np.ndarray.__idiv__(self, *args, **kwargs) 176 self.notify_observers() 177 return r 178 179
180 - def __iand__(self, *args, **kwargs): #pragma: no cover
181 r = np.ndarray.__iand__(self, *args, **kwargs) 182 self.notify_observers() 183 return r 184 185
186 - def __imod__(self, *args, **kwargs): #pragma: no cover
187 r = np.ndarray.__imod__(self, *args, **kwargs) 188 self.notify_observers() 189 return r 190 191
192 - def __iadd__(self, *args, **kwargs): #pragma: no cover
193 r = np.ndarray.__iadd__(self, *args, **kwargs) 194 self.notify_observers() 195 return r 196 197
198 - def __imul__(self, *args, **kwargs): #pragma: no cover
199 r = np.ndarray.__imul__(self, *args, **kwargs) 200 self.notify_observers() 201 return r 202