I've been playing with Scipy's inline tool (via weave) for fun, but I'm running into some trouble. My C is rusty and I have a feeling that I'm missing something simple.
The function below is designed to take a 3D float32 numpy array. I'm using a massive set of gridded atmospheric data, but this should work with any 3D array. This then takes the grid and gets the arithmetic mean across axis i, for each point j,k (i.e. if i is the time axis, j and k are lat/lon, then I'm averaging across time for each grid point).
I hope that my code is doing this and avoiding numpy NaNs (I believe that isnan() works in inline C/C++...?). But, whether it does this or not, I'm having trouble getting the code to compile without errors such as:
tools.py: In function ‘PyObject* compiled_func(PyObject*, PyObject*)’:
tools.py:93:45: error: invalid types ‘float[int]’ for array subscript
tools.py:95:51: error: invalid types ‘float[int]’ for array subscript
tools.py: In function ‘PyObject* compiled_func(PyObject*, PyObject*)’:
tools.py:93:45: error: invalid types ‘float[int]’ for array subscript
tools.py:95:51: error: invalid types ‘float[int]’ for array subscript
I think I'm declaring and initializing properly, so perhaps something isn't being passed to weave in the way I think it is? I would love it if someone could help me out with this. Here is the function:
from scipy.weave import inline
def foo(x):
xi = np.shape(x)[0]
xj = np.shape(x)[1]
xk = np.shape(x)[2]
code = """
#line 87 "tools.py"
int n;
float out[xj][xk];
for (int k = 0; k < xk; k++) {
for (int j = 0; j < xj; j++) {
n = 0;
for (int i = 0; i < xi; i++) {
if (!isnan(x[i][j][k])) {
n += 1;
out[j][k] += x[i][j][k];
}
}
out[j][k] = out[j][k]/n;
}
}
return_val = out;
开发者_StackOverflow社区 """
awesomeness = inline(code, ['x', 'xi', 'xj', 'xk'], compiler = 'gcc')
return(awesomeness)
you can create the out array in python first, and pass it to C++. In C++ you can get the shape of x by Nx[0], Nx[1], Nx[2]. And you can use macros defined for array to access it's elements. For example: X3(k,j,i) is the same as x[k,j,i] in python, and OUT2(j,i) is the same as out[j,i] in python. You can view the automatic created C++ code to know what variables and macros you can use for the arrays. To get the folder of C++ code:
from scipy import weave
print weave.catalog.default_dir()
My compiler doesn't support isnan(), so I use tmp==tmp to check it.
# -*- coding: utf-8 -*-
import scipy.weave as weave
import numpy as np
def foo(x):
out = np.zeros(x.shape[1:])
code = """
int i,j,k,n;
for(i=0;i<Nx[2];i++)
{
for(j=0;j<Nx[1];j++)
{
n = 0;
for(k=0;k<Nx[0];k++)
{
double tmp = X3(k,j,i);
if(tmp == tmp) // if isnan() is not available
{
OUT2(j,i) += tmp;
n++;
}
}
OUT2(j,i) /= n;
}
}
"""
weave.inline(code, ["x","out"], headers=["<math.h>"], compiler="gcc")
return out
np.random.seed(0)
x = np.random.rand(3,4,5)
x[0,0,0] = np.nan
mx = np.ma.array(x, mask=np.isnan(x))
avg1 = foo(x)
avg2 = np.ma.average(mx, axis=0)
print np.all(avg1 == avg2)
You can also use blitz converter to access array in C++. For the detail, try google: weave.converters.blitz
C doesn't support dynamic array sizing like out[xj][xk]. you either have to hardcode the sizes or use malloc or something supported by Weave to dynamically allocate the data.
精彩评论