Plot a piecewise-defined function I would like to plot the following function:

$$
\begin{align}
\Lambda(\delta\tau) &amp;\equiv\ \chi(\delta\tau, 0)
= \frac{1}{T_i} \int_0^{T_i} a(t_0+t')a(t_0+t'+\delta\tau) dt' \\
&amp;= \begin{cases}
   1 - \frac{\left|\delta\tau\right|}{\tau_c}, &amp;\left|\delta\tau\right| \le \tau_c(1+\frac{\tau_c}{T_i}) \\
   -\frac{\tau_c}{T_i}, &amp;\left|\delta\tau\right| \gt \tau_c(1+\frac{\tau_c}{T_i}) \\
   \end{cases}
\end{align}
$$
which represents a simple triangular shape. 
There is a conditional statement. My implementation uses a for loop as follows:

def waf_delay(delay_increment):
    for d in delay_increment:
        if np.abs(d) &lt;= delay_chip*(1+delay_chip/integration_time):
            yield 1 - np.abs(d)/delay_chip
        else:
            yield -delay_chip/integration_time;

integration_time = 1e-3 # seconds
delay_chip =  1/1.023e6 # seconds

x=np.arange(-5.0, 5.0, 0.1) 
y=list(waf_delay(x))
plt.plot(x, y)
plt.show()


Is there a more correct way to transform an array based on a condition rather than just looping through it? Instead of having something like this:


def f(x_array):
    for x in x_array:
        if np.abs(x) &lt;= 3:
            yield 1 - x/3
        else:
            yield 0

x=np.arange(-5.0, 5.0, 0.1) 
y=list(f(x))
plt.plot(x, y)
plt.show()



I would like to write something like this:


def f(x):
        if np.abs(x) &lt;= 3:
            yield 1 - x/3
        else:
            yield 0


x=np.arange(-5.0, 5.0, 0.1) 
plt.plot(x, f(x))
plt.show()



that could take an array.
There are two ways to solve this problem. The first one is numpy.where, which can take two arrays and it will choose from one wherever a condition is true and from the other wherever it is false. This only works if your piecewise function has only two possible states (as is the case here):

def waf_delay(delays):
    return np.where(np.abs(delays) &lt;= delay_chip*(1+delay_chip/integration_time),
                    1 - np.abs(delays)/delay_chip,
                    -delay_chip/integration_time)


Another more general possibility is to use numpy.piecewise, but that is probably overkill here:

def f1(x):
    return 1 - np.abs(x)/delay_chip

def f2(x):
    return -delay_chip/integration_time

cut_off = delay_chip*(1+delay_chip/integration_time)
y = np.piecewise(x, [np.abs(x) &lt;= cut_off, np.abs(x) &gt; cut_off], [f1, f2])


Note that in both cases no for d in delays is needed, because all functions used are vecotorized (the basic arithmetic operations for numpy arrays are and so is numpy.abs).