Read and write ZMAP files#
The venerable ZMAP format looks like this:
! Landmark Zmap grid file name: .DATANSLCU.dat
! Created/converted by Oasis Montaj, Geosoft Inc.
@.DATANSLCU.dat, GRID, 3
20, 1e+30, , 7, 1
208, 435, -630000.0, 672000.0, 2000000.0, 2621000.0
0.0, 0.0, 0.0
@
-16481.9570313 -16283.9033203 -16081.5751953
-15856.7861328 -15583.7167969 -15255.7343750
-14869.3769531 -14426.1513672 -13915.8769531
Files often have a the extension .DAT
. The first two lines shown are comments. The lines between the @
signs give the name of the grid, with some metadata such as null value, precision, and so on.
gio
wraps the zmapio
library. There are several functions:
read_zmap()
: read a ZMAP file.array_to_zmap()
: write a NumPy array as a ZMAP file.dataarray_to_zmap()
: write an XarrayDataArray
as a ZMAP file.xarray.DataArray.gio.to_zmap()
: an Xarray accessor providing another way to save a DataArray as a ZMAP file.
Let’s read some data from a ZMAP file:
!head ../../data/ZMAP/NStopo.dat
! Landmark Zmap grid file name: .\DATA\NStopo.dat
! Created/converted by Oasis Montaj, Geosoft Inc.
@.\DATA\NStopo.dat ,GRID, 4
20, 1.0E+30, , 7, 1
208, 435, -630000.0000, 672000.0000, 2000000.0000, 2621000.0000,
0.0000, 0.0000, 0.0000,
@
-67.2144775 -67.5697021 -67.1472168 -69.0812378
-73.1813660 -74.3084717 -72.7660828 -72.0339966
-70.5137329 -68.5551758 -66.1948547 -62.7756653
import gio
z = gio.read_zmap('../../data/ZMAP/NStopo.dat')
z.plot()
<matplotlib.collections.QuadMesh at 0x7f9df010a160>

Let’s take a look at the xarray
object too:
z
<xarray.DataArray '.\\DATA\\NStopo.dat' (Y: 208, X: 435)> array([[ -50.138916 , -43.8048401, -39.550293 , ..., 702.7687378, 656.3284302, 581.6201782], [ -50.7771301, -43.4010925, -40.3817444, ..., 626.8185425, 587.7715454, 528.4921265], [ -49.3357849, -47.8291626, -43.6928101, ..., 472.8615723, 492.1585693, 453.5387573], ..., [ -67.1472168, -72.3484497, -78.2303467, ..., -2397.1206055, -2378.3427734, -2362.1647949], [ -67.5697021, -72.6132202, -81.2595825, ..., -2409.6945801, -2391.8217773, -2376.5600586], [ -67.2144775, -74.9806519, -82.2666016, ..., -2416.8630371, -2398.3891602, -2387.4147949]]) Coordinates: * X (X) float64 -6.3e+05 -6.27e+05 -6.24e+05 ... 6.69e+05 6.72e+05 * Y (Y) float64 2e+06 2.003e+06 2.006e+06 ... 2.618e+06 2.621e+06 Attributes: fname: ../../data/ZMAP/NStopo.dat null_value: 1e+30 comment: [' Landmark Zmap grid file name: .\\DATA\\NStopo.dat', ' C...
Transform the surface#
The units are feet; let’s transform them to metres and save a new file.
z_m = 0.3048 * z
Use the xarray
accessory#
If your surface is held in an xarray.DataArray
then the accessory is the easiest way to save it in ZMAP format.
To use it, access the to_zmap()
function in the gio
accessory. After importing gio
, the accessory is attached to every instance of a DataArray
.
z_m.gio.to_zmap('NStopo_m.dat')
We can take a peek at this file using IPython to see if it looks legit:
!head ./NStopo_m.dat
!File created by gio.to_zmap xarray accessory
@.\DATA\NStopo.dat, GRID, 6
12, -999.25, , 3, 1
208, 435, -630000.0, 672000.0, 2000000.0, 2621000.0
0.0, 0.0, 0.0
@
-20.487 -20.595 -20.466 -21.056 -22.306 -22.649
-22.179 -21.956 -21.493 -20.896 -20.176 -19.134
-18.187 -17.888 -17.495 -17.983 -17.928 -17.516
-18.176 -21.011 -21.595 -20.317 -19.193 -18.450
Use the function#
If your surface is a NumPy array, then you can use the array_to_zmap()
function.
Note that if you want the ZMAP file to have real-world coordinates, you will need to provide the extent
as a list or tuple of min X, max X, min Y, max Y. For example:
arr = z_m.data
gio.array_to_zmap('NStopo_m.dat', arr, extent=[-630000.0, 672000.0, 2000000.0, 2621000.0])
It should look like the file we got before:
!head ./NStopo_m.dat
!File created by gio.array_to_zmap
@Z, GRID, 6
12, -999.25, , 3, 1
208, 435, -630000.0, 672000.0, 2000000.0, 2621000.0
0.0, 0.0, 0.0
@
-20.487 -20.595 -20.466 -21.056 -22.306 -22.649
-22.179 -21.956 -21.493 -20.896 -20.176 -19.134
-18.187 -17.888 -17.495 -17.983 -17.928 -17.516
-18.176 -21.011 -21.595 -20.317 -19.193 -18.450