Source code for NEDAS.models.nextsim.v1.bin_io
import numpy as np
import struct
from NEDAS.utils.conversion import type_convert, type_dic, type_size
[docs]
def get_info(filename):
"""basic read/write of data from nextsim bin/dat file"""
info = {}
with open(filename.replace('.bin','.dat'), 'r') as f:
lines = f.readlines()
pos = 4
for recno, lin in enumerate(lines):
ss = lin.split()
if len(ss) < 2:
continue
# #get info about the variable record
v_name = ss[0]
v_type = ss[1]
v_len = int(ss[2])
typeconv = type_convert[v_type]
v_min_val = typeconv(ss[3])
v_max_val = typeconv(ss[4])
v_rec = {}
v_rec.update({'type':v_type})
v_rec.update({'len':v_len})
v_rec.update({'min_val':v_min_val})
v_rec.update({'max_val':v_max_val})
v_rec.update({'recno':recno})
v_rec.update({'pos':pos})
# add variable record to the info dict
info.update({v_name: v_rec})
# position of starting point for f.seek
pos += (4 + v_len *type_size[v_type])
return info
[docs]
def read_data(filename, v_name):
"""Read data frim a binary file"""
info = get_info(filename)
if v_name not in info:
raise ValueError('variable %s not found in %s' %(v_name, filename))
with open(filename, 'rb') as f:
f.seek(info[v_name]['pos'])
v_len = info[v_name]['len']
v_type = info[v_name]['type']
v_data = np.array(struct.unpack((v_len*type_dic[v_type]),
f.read(v_len*type_size[v_type])))
return v_data
[docs]
def write_data(filename, v_name, v_data):
"""
write some var to existing nextsim restart file
only for outputing analysis after DA
to generate new file, see nextsim model documentation
"""
info = get_info(filename)
if v_name not in info:
raise ValueError('variable %s not in %s' %(v_name, filename))
# update info with new v_data
assert v_data.dtype == type_convert[info[v_name]['type']], "input data type mismatch with datfile record"
assert v_data.size == info[v_name]['len'], f"input data size {v_data.size} mismatch with datfile record {info[v_name]['len']}"
info[v_name]['min_val'] = np.nanmin(v_data)
info[v_name]['max_val'] = np.nanmax(v_data)
# write the dat file with updated info
with open(filename.replace('.bin','.dat'), 'wt') as f:
for v in info:
ss = '%s %s %i' %(v, info[v]['type'], info[v]['len'])
if info[v]['type'] == 'int':
ss += ' %i %i' %(info[v]['min_val'], info[v]['max_val'])
else:
ss += ' %g %g' %(info[v]['min_val'], info[v]['max_val'])
f.write(ss+'\n')
# write v_data to the bin file
with open(filename, 'r+b') as f:
if len(v_data) != info[v_name]['len']:
raise ValueError('v_data length does not match length on record')
f.seek(info[v_name]['pos'])
f.write(v_data.tobytes())