0

I am noticing some odd behavior when trying to vectorize the following bump function. It should return positive values for any inputs in the open interval (-1,1), and return 0 for inputs elsewhere:

>>import numpy as np

>>def bump(x):
    if np.abs(x)<1:
        return np.exp(-1/(1-x**2))
    else:
        return 0

>>vbump=np.vectorize(bump)

When I then try to evaluate the function vbump on an array which contains only values in (-1,1) it behaves as expected:

>>x=np.linspace(-0.99,0.99,10)
>>vbump(x)

array([  1.50022600e-22,   8.57431637e-02,   2.38427081e-01,
     3.25559999e-01,   3.63401061e-01,   3.63401061e-01,
     3.25559999e-01,   2.38427081e-01,   8.57431637e-02,
     1.50022600e-22])

On the other hand, when I try to evaluate it on an array which contains values outside of (-1,1) I get all zeros, even for the values which should be positive:

>>x2=np.linspace(-1.1,1.1,10)
>>vbump(x2)

array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0])

Why is it behaving like this? I'm fairly new to python and numpy, but from my understanding when I vectorize a function it should allow the function to be threaded over lists element-wise. Why is putting a larger array in affecting the element-wise evaluations elsewhere?

I should add that I have found a solution to the immediate problem of evaluating the bump function over an array, using

>>np.piecewise(x, [x <=-1, x >= 1,(-1<x)&(x<1)], [0,0,lambda t:np.exp(-1/(1-t**2))])

but I'd still like to understand what is going on with my initial approach.

1

1 Answer 1

2

As the documentation for np.vectorize explains:

The data type of the output of vectorized is determined by calling the function with the first element of the input. This can be avoided by specifying the otypes argument.

When the first value is -1.1, the returned value of your function is an integer 0, and so the dtype becomes an integer dtype (the specifics will depend upon your setup; with me it's int32):

>>> vbump(np.array([-0.99]))
array([  1.50022600e-22])
>>> vbump(np.array([-0.99])).dtype
dtype('float64')
>>> vbump(np.array([-1.0]))
array([0])
>>> vbump(np.array([-1.0])).dtype
dtype('int32')

Either change your 0 to 0.0 (so you're always returning a float), or specify otypes:

>>> vbump = np.vectorize(bump, otypes=[float])
>>> vbump(np.linspace(-1.1, 1.1, 10))
array([ 0.        ,  0.02396887,  0.20269374,  0.31495442,  0.36234271,
        0.36234271,  0.31495442,  0.20269374,  0.02396887,  0.        ])
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.