[SciPy-user] Vectorize wrapped Fortran routine
Pearu Peterson
pearu at scipy.org
Fri Apr 7 13:19:41 EDT 2006
On Fri, 7 Apr 2006, steffen.loeck at gmx.de wrote:
> Hi,
>
> I would like to vectorize a Fortran routine wrapped with f2py using
> scipy.vectorize. With the old scipy this works fine but with the new one i
> get the following error:
>
> TypeError: object is not a callable Python object
>
> Wrapping was done with:
>
> f2py -m hermite -h hermite.pyf hermite.f
> f2py2.3 -c hermite.pyf hermite.f
>
> The routine works without using vectorize but scipy.vectorize(hermite.routine)
> fails.
>
> Is there any way to get this working under new scipy?
vectorize expects a Python function or method as a first argument as this
assumption allows it to determine the number of expected arguments.
As a workaround, you can use
scipy.vectorize(lambda x:hermite.routine(x))
(the number of x-es may vary in your case).
However, the error is misleading. For example, f2py generated fortran
objects and instances of a class with __call__ method are callable
according to callable(<obj>) test but fail in vectorize.
As a possible fix, here is a more general way to determine the number of
arguments of a callable Python object:
# File: test_nargs.py
import re
import types
def get_nargs(obj):
if not callable(obj):
raise TypeError, 'object is not a callable Python object:
'+str(type(obj))
if hasattr(obj,'func_code'):
fcode = obj.func_code
nargs = fcode.co_argcount
if obj.func_defaults is not None:
nargs -= len(obj.func_defaults)
if isinstance(obj, types.MethodType):
nargs -= 1
return nargs
terr = re.compile(r'.*? takes exactly (?P<exargs>\d+) argument(s|)
\((?P<gargs>\d+) given\)')
try:
obj()
return 0
except TypeError, msg:
m = terr.match(str(msg))
if m:
nargs = int(m.group('exargs'))-int(m.group('gargs'))
if isinstance(obj, types.MethodType):
nargs -= 1
return nargs
raise ValueError, 'failed to determine the number of arguments for %s'
% (obj)
# TEST CODE FOLLOWS:
class A:
def foo(self, a1, a2, a3):
pass
def __call__(self, a1, a2):
pass
def car(self, a1, a2=2):
pass
def bar(a1,a2,a3,a4):
pass
def gun(a1,a2,a3=1,a4=2):
pass
from numpy.testing import *
assert_equal(get_nargs(A()),2)
assert_equal(get_nargs(A().foo),3)
assert_equal(get_nargs(A().car),1)
assert_equal(get_nargs(bar),4)
assert_equal(get_nargs(gun),2)
import t
# t is f2py generated module using a command:
# f2py -c foo.f -m t
# where foo.f contains:
"""
subroutine sin(x,r)
double precision x,r
cf2py intent(out) r
r = dsin(x)
end
"""
assert_equal(get_nargs(t.sin),1)
#EOF
More information about the SciPy-User
mailing list