使用F2PY从Python处理Fortran字符数组
我有一个用F2PY包装的传统Fortran库。但是,我不知道如何正确地从Python中读取声明为模块数据的字符数组。数据通过,但数组的转置方式使其无法识别。如何让Numpy正确处理阵列?如果二维字符数组的顺序可以理解,我会很满意 字符数组在Fortran中声明和填充,如下所示:使用F2PY从Python处理Fortran字符数组,python,numpy,fortran,Python,Numpy,Fortran,我有一个用F2PY包装的传统Fortran库。但是,我不知道如何正确地从Python中读取声明为模块数据的字符数组。数据通过,但数组的转置方式使其无法识别。如何让Numpy正确处理阵列?如果二维字符数组的顺序可以理解,我会很满意 字符数组在Fortran中声明和填充,如下所示: module plot_mod implicit none CHARACTER*4, JSP(39) ... JSP = (/ & 'SF ', 'WF ',
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:底层缓冲区不是C连续的
我知道我应该能够让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 ']]
我想要一个这样的数组:
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模块,但这比IMHO好得多。