Modeling and plotting neuron responses I want to assign the row of a matrix the return value of a function, but the only way I can figure out how to do this is with a for-loop. I'm assuming this is bad and vectorization would be better.

I'm trying to implement the first principle of the Neural Engineering Framework for a class. The function of the code is to get activation levels of a neuron and put them into an activities matrix.

# I'm going to use a rectified linear neuron model, because it's super easy to implement
def rec_lin_neuron(x_inter, max_fire, gain_sign, x_max=1.0):
    def rec_lin(x):
        return np.minimum(
                np.maximum(
                    np.dot(gain_sign, x) * (max_fire/(x_max-x_inter))
                    - x_inter * (max_fire/(x_max-x_inter)),
                    np.zeros(x.size)
                ),
                max_fire
            )
    return rec_lin

# We're going to make 16 neurons
n_neurons = 16

# These are the neuron attributes that will be created randomly
max_firing_rates = np.random.uniform(100, 200, n_neurons)
x_cepts = np.random.uniform(-0.95, 0.95, n_neurons)
gain_signs = np.random.choice([-1, 1], n_neurons)

# Create the neurons and stick them in a list, because I don't know how else to keep track of them  
neurons = []
for i in range(n_neurons):
    neurons.append(rec_lin_neuron(x_cepts[i], max_firing_rates[i], gain_signs[i]))

# Now let's calculate the response of these neurons to an input and plot it
x_vals = np.arange(-1, 1, 0.05)
A = np.zeros((n_neurons, x_vals.size))

fig = plt.figure()
for i in range(n_neurons):
    A[i,:] = neurons[i](x_vals)
    plt.plot(x_vals, A[i,:])
plt.show()
You could start by adding the necessary imports as well:

import numpy as np
from matplotlib import pyplot as plt


Since you already said how you can improve performance here (it's not
going to be easier to read, at least not to people who don't "live"
matrixes), I'm going to sketch the idea, although at least one step
isn't clear to me as well.  Which is to say, I find the function plus
for-loop way more readable than the following.

Now, instead of computing the response one by one, just vectorise each
step in rec_lin.  With the following rewrite, which is a tiny bit more
structured:

def rec_lin_neuron(x_inter, max_fire, gain_sign, x_max=1.0):
    def rec_lin(x):
        factor = max_fire/(x_max-x_inter)
        fire = np.maximum(np.dot(gain_sign, x) * factor - x_inter * factor,
                          np.zeros(x.size))
        return np.minimum(fire, max_fire)
    return rec_lin


That would be:

diffs = np.subtract(np.repeat(1.0, n_neurons), x_cepts) # aka x_max-x_inter
factors = np.divide(max_firing_rates, diffs) # aka factor


Similarly for the rest of that function, with the exception of np.dot,
where it's not clear to me how you'd run that function element-wise
against the input array, maybe you already know the answer, otherwise
I'll try to update it later.

The maximum and minimum for the matrixes should be np.amax and
np.amin.