how to specify a range in numpy.piecewise (2 conditions per range)
Asked Answered
T

2

8

I am trying to construct a piecewise function for some digital signal processing, but I cannot get numpy.piecewise to allow me to specify a range.

Here is what I want to input:

t = np.arange(-10,10,1)
x = lambda x: x**3
fx = np.piecewise(t, [t < -1 and t>-2, t <= 0 and t>-1, t>=0 and t<1,t>1 and t<2], [x(t + 2), x(-t),x(t),-x(2-t)])
plot(t,fx)

However, I get the error: "ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()"

After dissecting the function, it seems the issue is that this function won't allow 2 conditions in one such as: t < -1 and t>-2

But it seems to me that allowing a range to be specified would be essential to many piecewise functions. Is there a way to accomplish this?

Thanks!

Transmute answered 24/9, 2013 at 3:20 Comment(0)
M
4

Another problem, to add to Nicolas's answer, is that each element of funclist must be callable if you want to use piecewise. Your corrected code would look like

t = np.arange(-2,2,.01)
f1 = lambda t: (t+2)**3
f2 = lambda t: (-t)**3
f3 = lambda t: (t)**3
f4 = lambda t: -(2-t)**3
fx = np.piecewise(t, [(t< -1)*(t>=-2), (t <= 0) * (t>=-1), (t>0) * (t<1),(t>=1) * (t<=2)], [f1,f2,f3,f4])
plot(t,fx)

Instead, you could use select

t = np.arange(-2,2,.01)
f = lambda x: x**3
fx = np.select([(t< -1)*(t>=-2), (t <= 0) * (t>=-1), (t>0) * (t<1),(t>=1) * (t<=2)], [f(t+2),f(-t),f(t),-f(2-t)])
plot(t,fx)

Moreover, select allows you to set a default value outside the defined intervals, by passing it into the parameter default. You may need that if you want to stick to a range (-10,10) with your intervals.

Mucous answered 24/9, 2013 at 11:11 Comment(1)
Good point -> select would be my function of preference in this case. I ran the code and it graphed as I was hoping. Thanks!Transmute
M
6

This is because you cannot use and on numpy arrays. You need to replace the and with * and the or with + for numpy boolean arrays. (and do not forget to add parentheses).

Metropolis answered 24/9, 2013 at 9:56 Comment(2)
While the result is the same, it is probably a better practice to use the bitwise operators, & and |.Twilley
yup, that was the issue. Thanks! And I agree with Jamie as well that the bitwise operators are probably best.Transmute
M
4

Another problem, to add to Nicolas's answer, is that each element of funclist must be callable if you want to use piecewise. Your corrected code would look like

t = np.arange(-2,2,.01)
f1 = lambda t: (t+2)**3
f2 = lambda t: (-t)**3
f3 = lambda t: (t)**3
f4 = lambda t: -(2-t)**3
fx = np.piecewise(t, [(t< -1)*(t>=-2), (t <= 0) * (t>=-1), (t>0) * (t<1),(t>=1) * (t<=2)], [f1,f2,f3,f4])
plot(t,fx)

Instead, you could use select

t = np.arange(-2,2,.01)
f = lambda x: x**3
fx = np.select([(t< -1)*(t>=-2), (t <= 0) * (t>=-1), (t>0) * (t<1),(t>=1) * (t<=2)], [f(t+2),f(-t),f(t),-f(2-t)])
plot(t,fx)

Moreover, select allows you to set a default value outside the defined intervals, by passing it into the parameter default. You may need that if you want to stick to a range (-10,10) with your intervals.

Mucous answered 24/9, 2013 at 11:11 Comment(1)
Good point -> select would be my function of preference in this case. I ran the code and it graphed as I was hoping. Thanks!Transmute

© 2022 - 2024 — McMap. All rights reserved.