用F2PY处理来自Python的Fortran字符阵列
问题描述:
我用F2PY包装了传统的Fortran库。然而,我不知道如何从Python中正确读取声明为模块数据的字符数组。数据数据通过,但阵列转置的方式是不可分辨的。我如何才能让Numpy正确处理我的数组?如果他们是在一个可理解的顺序,我会满意一个二维数组的字符。用F2PY处理来自Python的Fortran字符阵列
字符数组的声明和使用Fortran填充像这样:
module plot_mod
implicit none
CHARACTER*4, JSP(39)
...
JSP = (/ &
'SF ', 'WF ', 'GF ', 'AF ', 'RF ', 'SS ', 'NF ', &
'YC ', 'IC ', 'ES ', 'LP ', 'JP ', 'SP ', 'WP ', &
'PP ', 'DF ', 'RW ', 'RC ', 'WH ', 'MH ', 'BM ', &
'RA ', 'WA ', 'PB ', 'GC ', 'AS ', 'CW ', 'WO ', &
'WJ ', 'LL ', 'WB ', 'KP ', 'PY ', 'DG ', 'HT ', &
'CH ', 'WI ', ' ', 'OT '/)
end module plot_mod
在Python 2.7(以前版本numpy的的),我可以这样做:
x = numpy.frombuffer(fvslib.plot_mod.jsp.data, numpy.dtype('a4'))
但现在的Python(3.4。 4)和Numpy(1.10.4)产生了一个错误BufferError: memoryview: underlying buffer is not C-contiguous
。
我知道我应该可以让Numpy通过重塑或使用步幅技巧来处理这个问题,但我似乎无法弄清楚。该阵列被报告为F连续的,所以至少看起来是正确的。
如果我只是打印阵列它看起来像这样:
array([[b'S', b' ', b' ', b'L'],
[b'F', b'L', b' ', b' '],
[b' ', b'P', b'B', b' '],
[b' ', b' ', b'M', b'W'],
[b'W', b' ', b' ', b'B'],
[b'F', b'J', b' ', b' '],
[b' ', b'P', b'R', b' '],
[b' ', b' ', b'A', b'K'],
[b'G', b' ', b' ', b'P'],
[b'F', b'S', b' ', b' '],
[b' ', b'P', b'W', b' '],
[b' ', b' ', b'A', b'P'],
[b'A', b' ', b' ', b'Y'],
[b'F', b'W', b' ', b' '],
[b' ', b'P', b'P', b' '],
[b' ', b' ', b'B', b'D'],
[b'R', b' ', b' ', b'G'],
[b'F', b'P', b' ', b' '],
[b' ', b'P', b'G', b' '],
[b' ', b' ', b'C', b'H'],
[b'S', b' ', b' ', b'T'],
[b'S', b'D', b' ', b' '],
[b' ', b'F', b'A', b' '],
[b' ', b' ', b'S', b'C'],
[b'N', b' ', b' ', b'H'],
[b'F', b'R', b' ', b' '],
[b' ', b'W', b'C', b' '],
[b' ', b' ', b'W', b'W'],
[b'Y', b' ', b' ', b'I'],
[b'C', b'R', b' ', b' '],
[b' ', b'C', b'W', b' '],
[b' ', b' ', b'O', b' '],
[b'I', b' ', b' ', b' '],
[b'C', b'W', b' ', b' '],
[b' ', b'H', b'W', b' '],
[b' ', b' ', b'J', b'O'],
[b'E', b' ', b' ', b'T'],
[b'S', b'M', b' ', b' '],
[b' ', b'H', b'L', b' ']],
dtype='|S1')
我想什么像这样的数组:
[['SF ']
, ['WF ']
, ['GF ']
, ['AF ']
, ['RF ']
, ['SS ']
, ['NF ']
, ['YC ']
, ['IC ']
, ['ES ']
, ['LP ']
, ['JP ']
, ['SP ']
, ['WP ']
, ['PP ']
, ['DF ']
, ['RW ']
, ['RC ']
, ['WH ']
, ['MH ']
, ['BM ']
, ['RA ']
, ['WA ']
, ['PB ']
, ['GC ']
, ['AS ']
, ['CW ']
, ['WO ']
, ['WJ ']
, ['LL ']
, ['WB ']
, ['KP ']
, ['PY ']
, ['DG ']
, ['HT ']
, ['CH ']
, ['WI ']
, [' ']
, ['OT ']]
答
我没有尝试过的模块上运行f2py,但如果我定义数组你显示为:
In [11]: s = array([[b'S', b' ', b' ', b'L'],
...: [b'F', b'L', b' ', b' '],
...: [b' ', b'P', b'B', b' '],
...: [b' ', b' ', b'M', b'W'],
...: [b'W', b' ', b' ', b'B'],
...: [b'F', b'J', b' ', b' '],
...: [b' ', b'P', b'R', b' '],
...: [b' ', b' ', b'A', b'K'],
...: [b'G', b' ', b' ', b'P'],
...: [b'F', b'S', b' ', b' '],
...: [b' ', b'P', b'W', b' '],
...: [b' ', b' ', b'A', b'P'],
...: [b'A', b' ', b' ', b'Y'],
...: [b'F', b'W', b' ', b' '],
...: [b' ', b'P', b'P', b' '],
...: [b' ', b' ', b'B', b'D'],
...: [b'R', b' ', b' ', b'G'],
...: [b'F', b'P', b' ', b' '],
...: [b' ', b'P', b'G', b' '],
...: [b' ', b' ', b'C', b'H'],
...: [b'S', b' ', b' ', b'T'],
...: [b'S', b'D', b' ', b' '],
...: [b' ', b'F', b'A', b' '],
...: [b' ', b' ', b'S', b'C'],
...: [b'N', b' ', b' ', b'H'],
...: [b'F', b'R', b' ', b' '],
...: [b' ', b'W', b'C', b' '],
...: [b' ', b' ', b'W', b'W'],
...: [b'Y', b' ', b' ', b'I'],
...: [b'C', b'R', b' ', b' '],
...: [b' ', b'C', b'W', b' '],
...: [b' ', b' ', b'O', b' '],
...: [b'I', b' ', b' ', b' '],
...: [b'C', b'W', b' ', b' '],
...: [b' ', b'H', b'W', b' '],
...: [b' ', b' ', b'J', b'O'],
...: [b'E', b' ', b' ', b'T'],
...: [b'S', b'M', b' ', b' '],
...: [b' ', b'H', b'L', b' ']],
...: dtype='|S1')
我可以得到一个数组,看起来像你想要什么:
In [12]: s.T.reshape(-1, 4).view('S4')
Out[12]:
array([[b'SF '],
[b'WF '],
[b'GF '],
[b'AF '],
[b'RF '],
[b'SS '],
[b'NF '],
[b'YC '],
[b'IC '],
[b'ES '],
[b'LP '],
[b'JP '],
[b'SP '],
[b'WP '],
[b'PP '],
[b'DF '],
[b'RW '],
[b'RC '],
[b'WH '],
[b'MH '],
[b'BM '],
[b'RA '],
[b'WA '],
[b'PB '],
[b'GC '],
[b'AS '],
[b'CW '],
[b'WO '],
[b'WJ '],
[b'LL '],
[b'WB '],
[b'KP '],
[b'PY '],
[b'DG '],
[b'HT '],
[b'CH '],
[b'WI '],
[b' '],
[b'OT ']],
dtype='|S4')
请注意,数据类型为'S4'
,以匹配Fortran阵列的声明大小。
该结果留下了一个平凡的第二维,因此您可能希望将其转换为一维数组,例如,
In [22]: s.T.reshape(-1, 4).view('S4')[:,0]
Out[22]:
array([b'SF ', b'WF ', b'GF ', b'AF ', b'RF ', b'SS ', b'NF ',
b'YC ', b'IC ', b'ES ', b'LP ', b'JP ', b'SP ', b'WP ',
b'PP ', b'DF ', b'RW ', b'RC ', b'WH ', b'MH ', b'BM ',
b'RA ', b'WA ', b'PB ', b'GC ', b'AS ', b'CW ', b'WO ',
b'WJ ', b'LL ', b'WB ', b'KP ', b'PY ', b'DG ', b'HT ',
b'CH ', b'WI ', b' ', b'OT '],
dtype='|S4')
答
为了完整起见,我将包含这个替代解决方案。与@Warren Weckesser相同的结果,但需要额外的导入。
from numpy.lib import stride_tricks
spp = stride_tricks.as_strided(jsp, strides=(jsp.shape[1],1))
# View as S4 and strip whitespace
spp = np.char.strip(spp.view('S4'))
完美。转位是我失踪的关键。发布后不久,我想出了如何使用stride_tricks模块来做到这一点,但这是更好的恕我直言。 – tharen