Search code examples
pythonnumpyscipynormalize

Normalizing A Numpy Arange


I am just beginning to program in python. I would like to normalize a numpy arange for various functions. My code so far is

from numpy import arange
from scipy.integrate import quad
import matplotlib.pyplot as plt

def function_A(x):
    return -(x-1)*(x-5)

def normalize(functionName, numpyRange):
    print "Inside normalize"

    min = numpyRange.min()
    max = numpyRange.max()

    print "functionName: ", functionName
    print "min: ", min
    print "max: ", max
    print "quad(functionName, min, max)[0]: ", quad(functionName, min, max)[0]
    print "functionName(numpyRange): ", functionName(numpyRange) 

    print "RIGHT BEFORE RETURN"

    return functionName(numpyRange) / quad(functionName, min, max)[0]

x = arange(1,5.01,0.01)
plt.plot(x, normalize(function_A, x))
plt.show()

print "This should equal unity: ", quad(normalize(function_A, x), x.min(), x.max(), args=(function_A, x))

The error message when I run my code is:

Traceback (most recent call last):
  File "forStackExchange3.py", line 33, in <module>
    print "This should equal unity: ", quad(normalize(function_A, x), x.min(), x.max(), args=(function_A, x))
  File "/usr/lib/python2.7/dist-packages/scipy/integrate/quadpack.py", line 247, in quad
    retval = _quad(func,a,b,args,full_output,epsabs,epsrel,limit,points)
  File "/usr/lib/python2.7/dist-packages/scipy/integrate/quadpack.py", line 312, in _quad
    return _quadpack._qagse(func,a,b,args,full_output,epsabs,epsrel,limit)
quadpack.error: First argument must be a callable function.

The error message is confusing to me because even though the error occurs on the line

print "This should equal unity: ", quad(normalize(function_A, x), x.min(), x.max(), args=(function_A, x))

I am still able to "enter" my normalize function, as evidenced by my multiple print statements. I have tried experimenting with different ways of writing the line that is giving the error message, but have not had any luck. Any help would be appreciated. Perhaps I need to rewrite my normalize function so that I can correctly use quad? Also, if there is a simpler method for normalizing functions in python for my particular case, please let me know.


Solution

  • The documentation for quad states:

    func : function A Python function or method to integrate.

    However, the first argument you pass is an ndarray, which is not callable. In other words, you are not passing the function you want to integrate, but rather the result of some other such operation.


    That's for what was technically wrong. As to how to fix it, I must say that I'm not sure what you're asking. Given a range y, it's possible to normalize it. The range y might be the result of applying some function to x, but that's besides the point. So you can build a range normalizer, and apply it to the results of functions.

    def function_A(x):
        return -(x-1)*(x-5)
    
    x = arange(1,5.01,0.01)
    
    def normalize(y):
        return y / sum(y)
    
    >> sum(normalize(function_A(x)))
    1.0
    

    You could also build a meta-function, which takes a function and returns a function that normalizes its results:

    def make_normalized(fn):
        return lambda x: fn(x) / sum(fn(x))
    

    So, with that, you could define

    normalized_function_A = make_normalized(function_A)
    

    and just to verify:

    >> sum(normalized_function_A(x))
    1.0