我想编写一个Python包,其中包含Brian Ripley维护的R的KernSmooth包的基本功能。 R的KernSmooth的大多数代码都是用Fortran77语法编写的。因此,基本上是模仿Brian Ripley在R中所做的事情,我的计划是将Fortran subroutines导入Python并编写相应的用户界面。首先,我想将Fortran77子例程 rlbin.f (下面的代码)放入Python函数中。
c Part of R package KernSmooth
c Copyright (C) 1995 M. P. Wand
c
c Unlimited use and distribution (see LICENCE).
cccccccccc FORTRAN subroutine rlbin.f cccccccccc
c Obtains bin counts for univariate regression data
c via the linear binning strategy. If "trun=0" then
c weight from end observations is given to corresponding
c end grid points. If "trun=1" then end observations
c are truncated.
c Last changed: 26 MAR 2009
subroutine rlbin(X,Y,n,a,b,M,trun,xcnts,ycnts)
double precision X(*),Y(*),a,b,xcnts(*),ycnts(*),lxi,delta,rem
integer n,M,i,li,trun
c Initialize grid counts to zero
do 10 i=1,M
xcnts(i) = dble(0)
ycnts(i) = dble(0)
10 continue
delta = (b-a)/(M-1)
do 20 i=1,n
lxi = ((X(i)-a)/delta) + 1
c Find integer part of "lxi"
li = int(lxi)
rem = lxi - li
if (li.ge.1.and.li.lt.M) then
xcnts(li) = xcnts(li) + (1-rem)
xcnts(li+1) = xcnts(li+1) + rem
ycnts(li) = ycnts(li) + (1-rem)*y(i)
ycnts(li+1) = ycnts(li+1) + rem*y(i)
endif
if (li.lt.1.and.trun.eq.0) then
xcnts(1) = xcnts(1) + 1
ycnts(1) = ycnts(1) + y(i)
endif
if (li.ge.M.and.trun.eq.0) then
xcnts(M) = xcnts(M) + 1
ycnts(M) = ycnts(M) + y(i)
endif
20 continue
return
end
cccccccccc End of rlbin.f cccccccccc
我已经成功编译了Fortran代码并将其导入Python。
在Unix shell中,我键入
f2py -c -m rlbin rlbin.f
创建一个共享库 rlbin.so ,我将其导入Python:
import rlbin
print(rlbin.__doc__)
输出:
This module 'rlbin' is auto-generated with f2py (version:2).
Functions:
rlbin(x,y,n,a,b,m,trun,xcnts,ycnts)
.
print(rlbin.rlbin.__doc__)
输出:
rlbin(x,y,n,a,b,m,trun,xcnts,ycnts)
Wrapper for ``rlbin``.
Parameters
----------
x : input rank-1 array('d') with bounds (*)
y : input rank-1 array('d') with bounds (*)
n : input int
a : input float
b : input float
m : input int
trun : input int
xcnts : input rank-1 array('d') with bounds (*)
ycnts : input rank-1 array('d') with bounds (*)
我指定了以下输入参数:
import numpy as np
# create random x and y arrays
x = np.ndarray(shape=(2000,), dtype=float, order='F')
y = np.ndarray(shape=(2000,), dtype=float, order='F')
n = len(x)
a = 0.05
b = 0.995
M = 500
trun = 1
xcents = np.zeros(M)
ycnts = np.zeros(M)
我检查了数据类型: a 和 b 确实是浮点型; n , M 和 trun 是整数; x , y , xcnst 和 ycnts 是numpy数组。
并称为Fortran子例程
out = rlbin.rlbin(x, y, n, a, b, M, trun, xcnts, ycnts)
它执行没有错误。同样,调用 out 不会引发错误,但也不返回任何内容。
type(out)
无论如何都会返回NoneType
和
print(out)
返回None
。
我在R中尝试了相同的过程(编译,导入,调用),但没有任何问题。
对于感兴趣的人,相应的R调用将是(摘自all.R脚本,第713-724行):
out <- .Fortran("rlbin", as.double(x), as.double(y), as.integer(n),
as.double(a), as.double(b), as.integer(M), as.integer(trun), double(M), double(M))
我已经按照一些教程来检查我的f2py环境是否设置正确,是的,我在用Python调用其他Fortran子例程时没有问题:
https://notmatthancock.github.io/2017/02/10/calling-fortran-from-python.html
https://notmatthancock.github.io/2017/03/07/multiple-modules-with-f2py.html
https://www-uxsup.csx.cam.ac.uk/courses/moved.PythonFortran/f2py.pdf(教程) https://git.physics.byu.edu/dfvankom/python-learning/tree/master/python-fortran(数据)
所以让我感到恼火的是,使用完全相同的输入参数在R中调用完全相同的Fortran子例程可以完美地工作。也许Python处理输入参数的方式与R处理方式不同,但是我目前还不了解。
感谢您的帮助!