Source code for resqpy.olio.zmap_reader
"""Functions for reading zmap and roxar format files."""
# RMS and ROXAR are registered trademarks of Roxar Software Solutions AS, an Emerson company
import logging
log = logging.getLogger(__name__)
import numpy as np
[docs]def read_zmap_header(inputfile):
"""Reads header lines from a zmap format file.
returns:
header_lines_count, no_rows, no_cols, minx, maxx, miny, maxy, null_value
"""
# read header, read until second '@', record header lines and content
with open(inputfile, 'r') as infile:
comments = []
head = []
a = 0 # count '@'s
headers = 0 # count header+comment lines
while a < 2:
line = infile.readline()
headers += 1
if line[:1] == '@':
a += 1
if line[:1] == '!':
comments.append(line.strip())
elif a == 1 or (line[:1] == '@'):
row = line.strip().strip('@').split(',')
head.append(row)
else:
log.error("Header section does not seem to be defined by 2 @s")
return None, None, None
line = infile.readline()
if line[0] == '+':
headers = headers + 1 # add extra line for the + symbol..
# for c in comments:
# log.debug(c)
# ok now process the header
# nodes_per_line = int(head[0][2])
# field_w = head[1][0]
null_value = head[1][1].strip()
null_value2 = head[1][2].strip()
# dec_places = head[1][3]
# strt_c = head[1][4]
no_rows = int(head[2][0])
no_cols = int(head[2][1])
minx = np.float64(head[2][2])
maxx = np.float64(head[2][3])
miny = np.float64(head[2][4])
maxy = np.float64(head[2][5])
# decide on the null value
if not null_value:
null_value = null_value2
# log.debug("Read {} header lines, we have {} rows, {} cols, and data from {} to {} and {} to {}".format(
# headers, no_rows, no_cols, minx, maxx, miny, maxy))
return headers, no_rows, no_cols, minx, maxx, miny, maxy, null_value
# note: the RMS text format was previously known as the Roxar format
[docs]def read_roxar_header(inputfile):
"""Reads header lines from a roxar format file.
returns:
header_lines_count, no_rows, no_cols, minx, maxx, miny, maxy, null_value
"""
with open(inputfile, 'r') as fp:
words = fp.readline().split()
assert words[0] == '-996', 'RMS text format indicator -996 not found'
no_rows = int(words[1])
# dx = float(words[2])
# dy = float(words[3])
words = fp.readline().split()
minx = float(words[0])
maxx = float(words[1])
miny = float(words[2])
maxy = float(words[3])
words = fp.readline().split()
no_cols = int(words[0])
headers = 4
null_value = '9999900.0000'
return headers, no_rows, no_cols, minx, maxx, miny, maxy, null_value
[docs]def read_mesh(inputfile, dtype = np.float64, format = None):
"""Reads a mesh (lattice) from a zmap or roxar format file.
returns:
x, y, f: each a numpy float array of shape (no_rows, no_cols)
"""
if format == 'zmap':
headers, no_rows, no_cols, minx, maxx, miny, maxy, null_value = read_zmap_header(inputfile)
elif format in ['rms', 'roxar']:
headers, no_rows, no_cols, minx, maxx, miny, maxy, null_value = read_roxar_header(inputfile)
else:
raise ValueError('format not recognised for read_mesh: ' + str(format))
# load the values in, converting null value to NaN's
infile = open(inputfile, 'r')
indata = infile.readlines()
infile.close()
c = 0
f = np.zeros(no_cols * no_rows, dtype = dtype)
n = 0
for line in indata:
c += 1
if c <= headers:
continue
else:
for x in line.split():
if (x == null_value) or (dtype(x) == dtype(null_value)):
f[n] = np.nan
else:
f[n] = dtype(x)
n += 1
# if (n % 10000 == 0) and (n > 10000):
# log.debug("Read node {} of {}".format(n, no_cols * no_rows))
# log.debug("Read {} nodes".format(len(f)))
if format == 'zmap':
# reshape it, and swap axis. Beacuse columns major order from fortran.
f = f.reshape((no_cols, no_rows)).swapaxes(0, 1)
else: # format in ['rms', 'roxar']
f = f.reshape((no_rows, no_cols))
# now generate x and y coords
x = np.linspace(minx, maxx, no_cols) # get x axis coords
if format == 'zmap':
y = np.linspace(maxy, miny, no_rows)
else: # format in ['rms', 'roxar']
y = np.linspace(miny, maxy, no_rows)
x, y = np.meshgrid(x, y) # get x and y of every node
assert x.shape == y.shape == f.shape
return x, y, f
[docs]def read_zmapplusgrid(inputfile, dtype = np.float64):
"""Read zmapplus grid (surface mesh); returns triple (x, y, z) 2D arrays."""
return read_mesh(inputfile, dtype = dtype, format = 'zmap')
[docs]def read_roxar_mesh(inputfile, dtype = np.float64):
"""Read RMS text format surface mesh; returns triple (x, y, z) 2D arrays.
note:
the RMS text format was previously known as the Roxar format
"""
return read_mesh(inputfile, dtype = dtype, format = 'rms')
[docs]def read_rms_text_mesh(inputfile, dtype = np.float64):
"""Read RMS text format surface mesh; returns triple (x, y, z) 2D arrays.
note:
the RMS text format was previously known as the Roxar format
"""
return read_roxar_mesh(inputfile, dtype = dtype)