Search code examples
pythonscipynumerical-integration

scipy.integrate.romberg -- how to pass functions with keyword arguments


Hopefully this is a quick, simple question, but it has got me a bit puzzled...

I have a function that takes two compulsory arguments and several keyword arguments that I want to integrate using scipy.integrate.romberg. I know I can pass extra arguments to scipy.integrate.romberg using the args keyword, where I can specify extra arguments as tuple, but, in the tuple, how wold I specify which function argument is the keyword argument and which are the keyword arguments?

e.g.

import numpy as np
from scipy import integrate

def myfunc(x,y,a=1,b=2):
    if y > 1.0:
         c = (1.0+b)**a
    else:
         c = (1.0+a)**b
    return c*x

y = 2.5
a = 4.0
b = 5.0

integral = integrate.romberg(myfunc,1,10,...?) # What do I specify here so
                                               # that romberg knows that 
                                               # y = 2.5, a = 4.0, b = 5.0?

At first I tried defining the function inside a class, so that all the keyword arguments were set in the __init__, but scipy.integrate.romberg didn't seem to like me passing a function with self as the first argument. (Don't have the error message to hand right now I'm afraid)!

Any ideas?

Thanks!


Solution

  • The comments to the original post suggest passing the keyword arguments as positional arguments. That'll work, but will be cumbersome if there are many keyword arguments and you don't want to pass them all explicitly. A more general (and perhaps more Pythonic) way is to wrap your function using a closure like this:

    def myfunc(x,y,a=1,b=2):
        if y > 1.0:
             c = (1.0+b)**a
        else:
             c = (1.0+a)**b
        return c*x
    
    def mywrapper(*args, **kwargs):
        def func(x):
            return myfunc(x, *args, **kwargs)
        return func
    
    myfunc_with_args = mywrapper(2.5, a=4.0, b=5.0)
    integral = integrate.romberg(myfunc_with_args, 1, 10)