# np.dot and other numpy.linalg functions have the nasty habit to
# view cast to generate the output. Since we don't want to pass on
# dependencies to the result of these functions, and we can't use
# the ufunc mechanism to demote the class type to ndarray, we must
# overwrite np.dot and other similar functions.
# BEGINS NUMPY FUNCTIONS OVERRIDE
# ** np.dot
__dp_dot=np.dot
defdep_dot(da,db):
a=depstrip(da)
b=depstrip(db)
return__dp_dot(da,db)
np.dot=dep_dot
# ENDS NUMPY FUNCTIONS OVERRIDE
defdget(obj,member):
"""Takes an object and retrieves one of its attributes.
Note that this is necessary as calling it in the standard way calls the
__get__() function of member.
Args:
obj: A user defined class.
member: A string giving the name of an attribute of obj.
Exceptions:
KeyError: If member is not an attribute of obj.
Returns:
obj.member.
"""
returnobj.__dict__[member]
defdset(obj,member,value,name=None):
"""Takes an object and sets one of its attributes.
Necessary for editing any depend object, and should be used for
initialising them as well, as often initialization occurs more than once,
with the second time effectively being an edit.
Args:
obj: A user defined class.
member: A string giving the name of an attribute of obj.
value: The new value of member.
name: New name of member.
Exceptions:
KeyError: If member is not an attribute of obj.
"""
obj.__dict__[member]=value
ifnotnameisNone:
obj.__dict__[member]._name=name
defdepstrip(da):
"""Removes dependencies from a depend_array.
Takes a depend_array and returns its value as a ndarray, effectively
stripping the dependencies from the ndarray. This speeds up a lot of
calculations involving these arrays. Must only be used if the value of the
array is not going to be changed.
Args:
deparray: A depend_array.
Returns:
A ndarray with the same value as deparray.
"""
ifisinstance(da,depend_array):# only bother to strip dependencies if the array actually IS a depend_array
#if da._tainted[0]:
# print "!!! WARNING depstrip called on tainted array WARNING !!!!!" # I think we can safely assume that when we call depstrip the array has been cleared already but I am not 100% sure so better check - and in case raise the update
returnda.view(np.ndarray)
else:
returnda
defdeppipe(objfrom,memberfrom,objto,memberto):
"""Synchronizes two depend objects.
Takes two depend objects, and makes one of them depend on the other in such
a way that both keep the same value. Used for attributes such as temperature
that are used in many different modules, and so need different depend objects
in each, but which should all have the same value.
Args:
objfrom: An object containing memberfrom.
memberfrom: The base depend object.
objto: An object containing memberto.
memberto: The depend object that should be equal to memberfrom.
"""
dfrom=dget(objfrom,memberfrom)
dto=dget(objto,memberto)
dto._func=lambda:dfrom.get()
dto.add_dependency(dfrom)
defdepcopy(objfrom,memberfrom,objto,memberto):
"""Copies the dependencies of one depend object to another.
Args:
See deppipe.
"""
dfrom=dget(objfrom,memberfrom)
dto=dget(objto,memberto)
dto._dependants=dfrom._dependants
dto._synchro=dfrom._synchro
dto.add_synchro(dfrom._synchro)
dto._tainted=dfrom._tainted
dto._func=dfrom._func
ifhasattr(dfrom,"_bval"):
dto._bval=dfrom._bval
classdobject(object):
"""Class that allows standard notation to be used for depend objects."""
def__getattribute__(self,name):
"""Overwrites standard __getattribute__().
This changes the standard __getattribute__() function of any class that
subclasses dobject such that depend objects are called with their own
__get__() function rather than the standard one.
"""
value=object.__getattribute__(self,name)
ifhasattr(value,'__get__'):
value=value.__get__(self,self.__class__)
returnvalue
def__setattr__(self,name,value):
"""Overwrites standard __setattribute__().
This changes the standard __setattribute__() function of any class that
subclasses dobject such that depend objects are called with their own