用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') 
+0

完美。转位是我失踪的关键。发布后不久,我想出了如何使用stride_tricks模块来做到这一点,但这是更好的恕我直言。 – tharen

为了完整起见,我将包含这个替代解决方案。与@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'))