[Numpy-discussion] Scalar-ndarray arguments passed to not_equal
Friedrich Romstedt
friedrichromstedt at gmail.com
Wed Feb 10 13:57:11 EST 2010
I wonder why there is no response on my e-mail dating back to Feb 4.
Is there nobody interested in it, is somebody working on it, or did it
simply did not come through? I changed the recipient now to
"Discussion of Numerical Python", hth ...
Sorry when there is double posting now, it's not intended if so.
2010/2/4 Friedrich Romstedt <friedrichromstedt at gmail.com>:
> Hi,
>
> I'm just coding a package for uncertain arrays using the accelerated
> numpy functionality intensively. I'm sorry, but I have to give some
> background information first. The package provides a class
> upy.undarray, which holds the nominal value and the uncertainty
> information. It has methods __add__(other), __radd__(other), ...,
> __eq__(other), __ne__(other), which accept both upy.undarrays and all
> other values suitable for coercion, thus also native numpy.ndarrays.
> But because numpy treats in the statement:
>
> result = numpyarray * upyarray
>
> upyarray as a scalar, because it's not an numpy.ndarray, I have to
> overload the numpy arithmetics by own objects by using
> numpy.set_numeric_ops(add = ..., ..., equal = equal, not_equal =
> not_equal). The arguments are defined by the module (it will be
> clearifiied below).
>
> Because numpy.add etc. are ufuncs exhibiting attributes, I wrote a
> class to wrap them:
>
> class ufuncWrap:
> """Wraps numpy ufuncs. Behaves like the original, with the exception
> that __call__() will be overloaded."""
>
> def __init__(self, ufunc, overload):
> """UFUNC is the ufunc to be wrapped. OVERLOAD is the name (string)
> of the undarray method to be used in overloading __call__()."""
>
> self.ufunc = ufunc
> self.overload = overload
>
> def __call__(self, a, b, *args, **kwargs):
> """When B is an undarray, call B.overload(a), else .ufunc(a, b)."""
>
> if isinstance(b, undarray):
> return getattr(b, self.overload)(a)
> else:
> return self.ufunc(a, b, *args, **kwargs)
>
> def __getattr__(self, attr):
> """Return getattr(.ufunc, ATTR)."""
>
> return getattr(self.ufunc, attr)
>
> I only have to wrap binary operators.
>
> Then, e.g.:
>
> class Equal(ufuncWrap):
> def __init__(self):
> ufuncWrap.__init__(self, numpy.equal, '__eq__')
>
> equal = Equal()
>
> This works as expected.
>
> But this approach fails (in first iteration) for a similar class
> NotEqual. I have let the module output the arguments passed to
> ufuncWrap.__call__(), and I found that the statement:
>
> result = (numpyarray != upyarray)
>
> with:
>
> numpyarray = numpy.asarray([1.0])
> upyarray = upy.ndarray([2.0], error = [0.1])
>
> is passed on to NotEqual.__call__() as the arguments:
>
> a = a numpy-array array([1.0])
> b = a numpy-array array(shape = (), dtype = numpy.object), which is a
> scalar array holding the upy.ndarray instance passed to !=.
>
> I can work around the exhbited behaviour by:
>
> class NotEqual(ufuncWrap):
> def __init__(self):
> ufuncWrap.__init__(self, numpy.not_equal, '__ne__')
>
> def __call__(self, a, b, *args, **kwargs):
> # numpy's calling mechanism of not_equal() seems to have a bug,
> # such that b is always a numpy.ndarray. When b should be an undarray,
> # it is a numpy.ndarray(dtype = numpy.object, shape = ()) ...
>
> # Make the call also compatible with future, bug-fixed versions.
> if isinstance(b, numpy.ndarray):
> if b.ndim == 0:
> # Implement some conversion from scalar array to stored object.
> b = b.sum()
>
> return ufuncWrap.__call__(self, a, b, *args, **kwargs)
>
> What is the reason for the behaviour observed?
>
> I'm using numpy 1.4.0 with Python 2.5.
>
> Friedrich
>
More information about the NumPy-Discussion
mailing list