I have a function written in Python 2.7 that I call several times in a program. This function is rather slow, and I'd like to rewrite it in NumPy. However, I don't know how to do it.
I basically have a canvas of width * height
pixels, and I'm making something rather complicated inside. I'd like to know how to replace all the parts with:
for i in range(x):
do x[i]
...
by NumPy-style operations.
I know that I can start by making an array of zeros with np.zeros
, but how can I implement the equations / operations in NumPy?
def Circular_cumsum_spot(width,height,centre,radius,spectrum,red_or_violet):
"""makes a "light spot" by cumsums
from the center to the periphery
width, height = size of canvas
x, y = center of the spot
radius = magnitude of the spot in pixels
spectrum = light source
red = to red, violet = to violet
returns a numpy array"""
x,y = centre[0], centre[1]
data = []
X = Y = Z = 0
for i in range(height):
for j in range(width):
distance = radius - np.sqrt((i-x)**2+(j-y)**2)
if distance >= radius:
cumsum = 0
X = Y = Z = 0
else:
cumsum = round((distance/radius) * (len(spectrum)))
if red_or_violet == "red":
for k in range(cumsum):
X += spectrum[k][0]
Y += spectrum[k][1]
Z += spectrum[k][2]
else:
for k in range(cumsum):
l = len(spectrum)-k-1
X += spectrum[l][0]
Y += spectrum[l][1]
Z += spectrum[l][2]
data += [(X,Y,Z)]
X = Y = Z = 0
data = np.array(data)
divisor = np.max(data[:,1])
if divisor == 0:
data = data
else:
data = np.divide(data, divisor)
return data
print "spot created is", red_or_violet
ufunc
numpy calls, you could probably achieve a few multiples faster. However, if you convert this code to Cython, and set types on your variables, you can realistically expect to get it around 150X faster (15000% faster). The loops should all be explicit Cython loops. – cjrh Oct 14 '14 at 5:47