# How can I determine which function is responsible for calling a function listed by %prun?

I'm currently trying to optimize a bit of code using ipython's %prun magic. Here is the output of both %prun and %timeit below:

In [5]: %prun hogopt.findHOGFeatures(lenna) 260114 function calls in 5.614 seconds Ordered by: internal time ncalls tottime percall cumtime percall filename:lineno(function) 1 5.529 5.529 5.613 5.613 hogopt.py:5(findHOGFeatures) 260100 0.066 0.000 0.066 0.000 {math.floor} 2 0.017 0.009 0.017 0.009 {cv2.Sobel} 1 0.001 0.001 5.614 5.614 <string>:1(<module>) 1 0.001 0.001 0.001 0.001 {numpy.core.multiarray.array} 1 0.000 0.000 0.000 0.000 {cv2.cv.GetMat} 1 0.000 0.000 0.001 0.001 ImageClass.py:1977(getNumpyCv2) 1 0.000 0.000 0.000 0.000 {numpy.core.multiarray.zeros} 1 0.000 0.000 0.000 0.000 ImageClass.py:1804(getMatrix) 3 0.000 0.000 0.000 0.000 {method 'transpose' of 'numpy.ndarray' objects} 1 0.000 0.000 0.000 0.000 ImageClass.py:1769(getBitmap) 1 0.000 0.000 0.000 0.000 {method 'disable' of '_lsprof.Profiler' objects} In [6]: %timeit hogopt.findHOGFeatures(lenna) 1 loops, best of 3: 5.25 s per loop

**My question is as follows:**

It appears as though math.floor is responsible for the large majority of the execution time, but I'm wondering who is calling it, since it's never explicitly called in my code. Is there a way to obtain this information?

Below is the full function definition, in case it can provide some insight. Note that this function requires SimpleCV if you actually want to run it:

from itertools import product def findHOGFeatures(img, n_divs=6, n_bins=6): """ **SUMMARY** Get HOG(Histogram of Oriented Gradients) features from the image. **PARAMETERS** * *img* * - SimpleCV image * *n_divs* - the number of divisions(cells). * *n_divs* - the number of orientation bins. **RETURNS** Returns the HOG vector in a numpy array """ # Size of HOG vector n_HOG = n_divs * n_divs * n_bins # Initialize output HOG vector HOG = np.zeros((n_HOG, 1)) # Apply sobel on image to find x and y orientations of the image Icv = img.getNumpyCv2() Ix = cv2.Sobel(Icv, ddepth=cv.CV_32F, dx=1, dy=0, ksize=3) Iy = cv2.Sobel(Icv, ddepth=cv.CV_32F, dx=0, dy=1, ksize=3) Ix = Ix.transpose(1, 0, 2) Iy = Iy.transpose(1, 0, 2) cellx = img.width / n_divs # width of each cell(division) celly = img.height / n_divs # height of each cell(division) img_area = img.height * img.width # Area of image BIN_RANGE = (2 * pi) / n_bins # Range of each bin angles = np.arctan2(Iy, Ix) magnit = ((Ix ** 2) + (Iy ** 2)) ** 0.5 it = product(xrange(n_divs), xrange(n_divs), xrange(cellx), xrange(celly)) for m, n, i, j in it: # grad value grad = magnit[m * cellx + i, n * celly + j][0] # normalized grad value norm_grad = grad / img_area # Orientation Angle angle = angles[m*cellx + i, n*celly+j][0] # (-pi,pi) to (0, 2*pi) if angle < 0: angle += 2 * pi nth_bin = floor(float(angle/BIN_RANGE)) HOG[((m * n_divs + n) * n_bins + int(nth_bin))] += norm_grad return HOG.transpose()

## Answers

Actually, you appear to be calling math.floor:

nth_bin = floor(float(angle/BIN_RANGE))

Anyway, these calls only cost you 0.066 seconds over a total runtime of 5+ seconds. Your time seems to be spent in your loop. Probably because it is being executed 260100 times (as floor is called in your loop, and there are 260100 recorded calls to it).