I have used f2py extensively in my work (modeling, and ensemble Kalman filtering for atmospheric models). You do not have to interface python to all the fortran routines, just the 1 or 2 that have to interact with input. The rest can be added to the compile as “*.o" files. So for input parameters from python (suppose you want to be able to use command line input using one of the Parser modules in Python), you would pass parameters from python through to the fortran. So your fortran “main” program becomes a fortran subroutine that Python calls. If that “main” routine also writes out the txt file, you can pass an array or whatever back through on exit from the fortran to python automatically and then do more stuff in python (plotting, writing netCDF, etc) with the data passed back.
The easiest way to interface automatically is to write the subroutine that interaces with python using INTENT arguments…. Here is an example of a 2D analysis in fortran from scattered data. The cressman routine does the analysis and returns a 2D array. Below the code is my line to compile this code, and then the line that calls it within a python rouytine. The fortran is in F90, but one can use F77…...
subroutine cressman(x, y, ob, xg, yg, method, min_count, min_weight, min_range, roi, missing_value, anal, nobs, nx, ny)
implicit none
real(8), intent(in), dimension(nobs) :: x
real(8), intent(in), dimension(nobs) :: y
real(4), intent(in), dimension(nobs) :: ob
real(8), intent(in), dimension(nx) :: xg
real(8), intent(in), dimension(ny) :: yg
real(4), intent(out), dimension(nx,ny) :: anal
real, intent(in) :: roi, missing_value, min_weight, min_range
integer, intent(in) :: nobs, nx, ny, min_count, method
integer n, i, j, count
real(kind=8) dis, R2, w_sum, sum, wk, rk2
real, parameter :: hsp0 = 1.33
logical, parameter :: debug = .true.
IF ( method .eq. 1 ) THEN
R2 = roi**2.0
ELSE
R2 = (hsp0*roi/1000.)**2 ! Pauley and Wu (1990)
ENDIF
IF( debug ) THEN
print *, 'Method: ', method
print *, 'Min gates for analysis: ', min_count
print *, 'Min weight for analysis:', min_weight
print *, 'Min range for analysis: ', min_range
print *, 'Nobs: ', nobs
print *, 'Nx/Ny: ', nx, ny
print *, 'Maxval of anal before: ', maxval(anal)
print *, 'Minval of anal before: ', minval(anal)
print *, ''
print *, 'Maxval of observations: ', maxval(ob)
print *, 'Minval of observations: ', minval(ob)
print *, 'Min/Max xob: ', minval(x), maxval(x)
print *, 'Min/Max yob: ', minval(y), maxval(y)
print *, 'Min/Max xgrid: ', minval(xg), maxval(xg)
print *, 'Min/Max ygrid: ', minval(yg), maxval(yg)
print *, 'Radius of influence: ', roi
print *, ''
ENDIF
DO j = 1,ny
DO i = 1,nx
IF( method .eq. 1 ) THEN ! Cressman
count = 0
w_sum = 0.0
sum = 0.0
anal(i,j) = missing_value
DO n = 1,nobs
dis = sqrt( (xg(i) - x(n))**2 + (yg(j)-y(n))**2 )
IF ((dis .le. roi) .and. (dis .ge. min_range)) THEN
rk2 = dis**2.0
wk = (R2-rk2) / (R2+rk2)
sum = sum + wk*ob(n)
w_sum = w_sum + wk
count = count + 1
ENDIF
ENDDO
ELSE ! Barnes 1-pass
count = 0
w_sum = 0.0
sum = 0.0
anal(i,j) = missing_value
DO n = 1,nobs
dis = sqrt( (xg(i) - x(n))**2 + (yg(j)-y(n))**2 )
IF ((dis .le. 6.0*roi) .and. (dis .ge. min_range)) THEN
rk2 = dis**2.0
wk = exp( -rk2 / R2 )
sum = sum + wk*ob(n)
w_sum = w_sum + wk
count = count + 1
ENDIF
ENDDO
ENDIF
IF ((w_sum .ge. min_weight) .and. (count .ge. min_count)) THEN
anal(i,j) = anal(i,j) + sum/w_sum
ENDIF
ENDDO
ENDDO
IF( debug ) THEN
print *, 'Maxval of anal after: ', maxval(anal)
print *, 'Minval of anal after: ', minval(anal)
ENDIF
end subroutine cressman
---------------COMPILE--------
#!/usr/bin/env python
import os
# remove all module files in directory - this can trip you up bad!
print "\n=====================================================\n"
print(" ---> Compiling...")
print "\n=====================================================\n"
cmd = "f2py --fcompiler='gnu95' --f90flags='-O3' -c -m cressman cressman.f90"
os.system(cmd)
------------PYTHON
.
.
.
anal2d = cressman.obs_2_grid2d(obs, xob, yob, xg, yg, ix, iy, anal_method, min_count, min_weight, min_range, \
2.0*grid_spacing_xy, _missing)
—> notice that anal array is NOT in the python call to the subroutine. The INTENT(OUT) in the fortran declarations
makes the array a returned pointer to the 2D numpy array within python, so you omit it from the call list from python, even though its in the fortran subroutine call.
HTH,
Lou Wicker