如何将未格式化的 fortran 文件(modflow 输出)转换为 numpy 数组
How to convert a unformatted fortran file(modflow output ) to numpy array
我有一个扩展名为 hds 的 modflow 输出文件。 Google 为 a file 驱动 link。它是一个未格式化的 fortran 文件。我需要将它转换为 numpy 数组,我试过了:
floattype = 'f4'
a = np.fromfile("lake_example.hds", np.dtype([('kstp','i4'),('kper','i4'),('pertim',floattype),('totim',floattype),('text','a16'),('ncol','i4'),('nrow','i4'),('ilay','i4')]))
print a
print a.shape
github link 代码:https://github.com/Kirubaharan/hydrology/blob/master/gw_tut.py
我正在尝试 this link 的教程。因为我在 linux 上,所以我不能使用 flopy 的方法从文件中获取输出数组。所以我尝试使用 np.fromfile,但我在获取输出时遇到问题。
我现在的输出是这样的:
[ (44, 1, 1.401298464324817e-45, 1.0, '\x00\x00\x80? ', 1145128264, 11, 11)
(1, 44, 6.782284567332115e-43, 100.0, '\x00\x00\xc8B\x00\x00\xc8B\x00\x00\xc8B\x00\x00\xc8B', 1120403456, 1120403456, 1120403456)
(1120403456, 1120403456, 100.0, 100.0, '\x0c\xbf\xc7B\x18~\xc7B=@\xc7B\xce\x0e\xc7B', 1120336356, 1120341710, 1120354365)
(1120370200, 1120386828, 100.0, 100.0, '\x18~\xc7B\x0e\xf9\xc6B\xf0s\xc6B\xaa\x00\xc6B', 1120258308, 1120272554, 1120302064)
(1120336142, 1120370200, 100.0, 100.0, '=@\xc7B\xf0s\xc6B\xf8\x94\xc5B\x91\xb3\xc4B', 1120149448, 1120187281, 1120244984)
(1120302064, 1120354365, 100.0, 100.0, '\xce\x0e\xc7B\xaa\x00\xc6B\x91\xb3\xc4B\xac\xff\xc2B', 1119940155, 1120075692, 1120187281)
(1120272554, 1120341710, 100.0, 100.0, '\xe4\xf9\xc6B\x04\xc9\xc5B\xc8\x1f\xc4B;\xee\xc0B', 1119092736, 1119940155, 1120149448)
(1120258308, 1120336356, 100.0, 100.0, '\xce\x0e\xc7B\xaa\x00\xc6B\x91\xb3\xc4B\xac\xff\xc2B', 1119940155, 1120075692, 1120187281)
(1120272554, 1120341710, 100.0, 100.0, '=@\xc7B\xf0s\xc6B\xf8\x94\xc5B\x91\xb3\xc4B', 1120149448, 1120187281, 1120244984)
(1120302064, 1120354365, 100.0, 100.0, '\x18~\xc7B\x0e\xf9\xc6B\xf0s\xc6B\xaa\x00\xc6B', 1120258308, 1120272554, 1120302064)
(1120336142, 1120370200, 100.0, 100.0, '\x0c\xbf\xc7B\x18~\xc7B=@\xc7B\xce\x0e\xc7B', 1120336356, 1120341710, 1120354365)
我只包含了几行输出。
头信息可以参考他们的源码:https://github.com/modflowpy/flopy/blob/master/flopy/utils/binaryfile.py#L30g
您的代码与数据文件的结构不匹配:
00000000 2c 00 00 00 01 00 00 00 01 00 00 00 00 00 80 3f |,..............?|
00000010 00 00 80 3f 20 20 20 20 20 20 20 20 20 20 20 20 |...? |
00000020 48 45 41 44 0b 00 00 00 0b 00 00 00 01 00 00 00 |HEAD............|
00000030 2c 00 00 00 e4 01 00 00 00 00 c8 42 00 00 c8 42 |,..........B...B|
00000040 00 00 c8 42 00 00 c8 42 00 00 c8 42 00 00 c8 42 |...B...B...B...B|
00000050 00 00 c8 42 00 00 c8 42 00 00 c8 42 00 00 c8 42 |...B...B...B...B|
每个数据块都有自己的 56 个字节 header,包括:
3 个整数 (i4)、2 个浮点值 (f4)、16 个字符和 5 个整数 (i4):
44 1 1
1.0 1.0
HEAD
11 11 1 44 484
然后数据块如下(11x11浮点值):
100.0 100.0 100.0 100.0 100.0 100.0 100.0 100.0 100.0 100.0 100.0
100.0 99.87313842773438 99.74627685546875 99.6254653930664 ...
我不确定这是否可以直接导入到 numpy 数组中。
以下示例代码将遍历整个文件并提取每个块的 header 和数据:
#!/usr/bin/python
import struct
import numpy as np
infile = open("lake_example.hds","rb")
blockdata = []
while infile.read(1):
infile.seek(-1,1)
data = infile.read(56)
n = struct.unpack('<3i4', data[0:12])
# print n[0], n[1], n[2]
n = struct.unpack('<2f4', data[12:20])
# print n[0], n[1]
# print data[20:36]
n = struct.unpack('<5i4', data[36:56])
# print n[0], n[1], n[2], n[3], n[4]
ncol = n[0]
nrow = n[1]
a = np.fromfile(infile,dtype='f4',count=ncol*nrow).reshape((ncol,nrow))
blockdata.append(a)
data = infile.read(4)
n = struct.unpack('<i4', data)
# print n[0]
for block in blockdata:
print block
您很可能还需要块 header 中的一些信息(请参阅打印语句)。
另见 'flopy.utils.binaryfile Module':
http://modflowpy.github.io/flopydoc/binaryfile.html
查看 Flopy-3 教程 2(无侧限瞬态流模型),在绘图部分:
发件人:http://modflowpy.github.io/flopydoc/tutorial2.html
首先定义了一个'headobj':
headobj = bf.HeadFile(modelname+'.hds')
头部提取如下:
head = headobj.get_data(totim=time)
在 Debian 上运行
我有一个扩展名为 hds 的 modflow 输出文件。 Google 为 a file 驱动 link。它是一个未格式化的 fortran 文件。我需要将它转换为 numpy 数组,我试过了:
floattype = 'f4'
a = np.fromfile("lake_example.hds", np.dtype([('kstp','i4'),('kper','i4'),('pertim',floattype),('totim',floattype),('text','a16'),('ncol','i4'),('nrow','i4'),('ilay','i4')]))
print a
print a.shape
github link 代码:https://github.com/Kirubaharan/hydrology/blob/master/gw_tut.py
我正在尝试 this link 的教程。因为我在 linux 上,所以我不能使用 flopy 的方法从文件中获取输出数组。所以我尝试使用 np.fromfile,但我在获取输出时遇到问题。
我现在的输出是这样的:
[ (44, 1, 1.401298464324817e-45, 1.0, '\x00\x00\x80? ', 1145128264, 11, 11)
(1, 44, 6.782284567332115e-43, 100.0, '\x00\x00\xc8B\x00\x00\xc8B\x00\x00\xc8B\x00\x00\xc8B', 1120403456, 1120403456, 1120403456)
(1120403456, 1120403456, 100.0, 100.0, '\x0c\xbf\xc7B\x18~\xc7B=@\xc7B\xce\x0e\xc7B', 1120336356, 1120341710, 1120354365)
(1120370200, 1120386828, 100.0, 100.0, '\x18~\xc7B\x0e\xf9\xc6B\xf0s\xc6B\xaa\x00\xc6B', 1120258308, 1120272554, 1120302064)
(1120336142, 1120370200, 100.0, 100.0, '=@\xc7B\xf0s\xc6B\xf8\x94\xc5B\x91\xb3\xc4B', 1120149448, 1120187281, 1120244984)
(1120302064, 1120354365, 100.0, 100.0, '\xce\x0e\xc7B\xaa\x00\xc6B\x91\xb3\xc4B\xac\xff\xc2B', 1119940155, 1120075692, 1120187281)
(1120272554, 1120341710, 100.0, 100.0, '\xe4\xf9\xc6B\x04\xc9\xc5B\xc8\x1f\xc4B;\xee\xc0B', 1119092736, 1119940155, 1120149448)
(1120258308, 1120336356, 100.0, 100.0, '\xce\x0e\xc7B\xaa\x00\xc6B\x91\xb3\xc4B\xac\xff\xc2B', 1119940155, 1120075692, 1120187281)
(1120272554, 1120341710, 100.0, 100.0, '=@\xc7B\xf0s\xc6B\xf8\x94\xc5B\x91\xb3\xc4B', 1120149448, 1120187281, 1120244984)
(1120302064, 1120354365, 100.0, 100.0, '\x18~\xc7B\x0e\xf9\xc6B\xf0s\xc6B\xaa\x00\xc6B', 1120258308, 1120272554, 1120302064)
(1120336142, 1120370200, 100.0, 100.0, '\x0c\xbf\xc7B\x18~\xc7B=@\xc7B\xce\x0e\xc7B', 1120336356, 1120341710, 1120354365)
我只包含了几行输出。
头信息可以参考他们的源码:https://github.com/modflowpy/flopy/blob/master/flopy/utils/binaryfile.py#L30g
您的代码与数据文件的结构不匹配:
00000000 2c 00 00 00 01 00 00 00 01 00 00 00 00 00 80 3f |,..............?|
00000010 00 00 80 3f 20 20 20 20 20 20 20 20 20 20 20 20 |...? |
00000020 48 45 41 44 0b 00 00 00 0b 00 00 00 01 00 00 00 |HEAD............|
00000030 2c 00 00 00 e4 01 00 00 00 00 c8 42 00 00 c8 42 |,..........B...B|
00000040 00 00 c8 42 00 00 c8 42 00 00 c8 42 00 00 c8 42 |...B...B...B...B|
00000050 00 00 c8 42 00 00 c8 42 00 00 c8 42 00 00 c8 42 |...B...B...B...B|
每个数据块都有自己的 56 个字节 header,包括: 3 个整数 (i4)、2 个浮点值 (f4)、16 个字符和 5 个整数 (i4):
44 1 1
1.0 1.0
HEAD
11 11 1 44 484
然后数据块如下(11x11浮点值):
100.0 100.0 100.0 100.0 100.0 100.0 100.0 100.0 100.0 100.0 100.0
100.0 99.87313842773438 99.74627685546875 99.6254653930664 ...
我不确定这是否可以直接导入到 numpy 数组中。
以下示例代码将遍历整个文件并提取每个块的 header 和数据:
#!/usr/bin/python
import struct
import numpy as np
infile = open("lake_example.hds","rb")
blockdata = []
while infile.read(1):
infile.seek(-1,1)
data = infile.read(56)
n = struct.unpack('<3i4', data[0:12])
# print n[0], n[1], n[2]
n = struct.unpack('<2f4', data[12:20])
# print n[0], n[1]
# print data[20:36]
n = struct.unpack('<5i4', data[36:56])
# print n[0], n[1], n[2], n[3], n[4]
ncol = n[0]
nrow = n[1]
a = np.fromfile(infile,dtype='f4',count=ncol*nrow).reshape((ncol,nrow))
blockdata.append(a)
data = infile.read(4)
n = struct.unpack('<i4', data)
# print n[0]
for block in blockdata:
print block
您很可能还需要块 header 中的一些信息(请参阅打印语句)。
另见 'flopy.utils.binaryfile Module': http://modflowpy.github.io/flopydoc/binaryfile.html
查看 Flopy-3 教程 2(无侧限瞬态流模型),在绘图部分:
发件人:http://modflowpy.github.io/flopydoc/tutorial2.html
首先定义了一个'headobj':
headobj = bf.HeadFile(modelname+'.hds')
头部提取如下:
head = headobj.get_data(totim=time)
在 Debian 上运行