Skip to content

Horizon grids and map files

Ophiolite reads three more horizon grid formats and three map-layer formats. A grid becomes the same horizon grid as an ESRI ASCII grid (see Well tops, trajectories and horizon grids); a map layer becomes Map features: shapes with their attribute table, kept as stored. Nothing is reprojected, resampled or swapped, and what a file does not say stays Not stated until you say it.

KindFilesWhat is asked
Horizon grid (ZMAP+).zmap (@ header, fixed-width values column by column)whether the corner values are cell centres or cell edges
Horizon grid (CPS-3).cps3 (FSASCI … FSXINC header)the corner question, and whether each column starts at the north end or the south end
Horizon grid (IRAP ASCII).irap (classic four-line header)nothing more: the header states origin, step and count
Map features (Shapefile)the .shp with its .shx, .dbf and, when present, .prj, .cpg or .cst; loose or in a .zipthe coordinate system when there is no .prj; the text encoding when nothing states it
Map features (GeoPackage).gpkg, GeoPackage 1.2 or laterwhich layer, when the file holds more than one
Map features (GeoJSON).geojson, .jsonthe coordinate system when the file states none

Every grid also asks what any grid asks: coordinate system, map unit, what the values are, their unit, the positive direction and the vertical datum. Each limit is listed on File kinds.

  1. Open Connect → Add files and drop the files, the folder or the .zip. A Shapefile’s files are recognised as one file with its companions: the report lists the .shp as the file and the others as files that came with it.
  2. The read report asks what the files leave open, each answer preselected Not stated. For a ZMAP+ grid the question “The corner values in the file are” has a hint under it, marked “Hint, not stated by the file”, with the arithmetic it comes from; it is never chosen for you.
  3. A GeoPackage with several layers is asked “Layer in fields.gpkg” once it has been read: on its row of the report, choose the layer by its title and press Add this file. Two GeoPackages in one drop are each asked their own layer. The files are not chosen again.
  4. The added map layer opens in Map features: a plan view with its axes named as the file states them (“Easting →, northing ↑ · north at the top, east to the right” only when the file or you state easting-northing or longitude-latitude; otherwise “first coordinate →, second coordinate ↑”), the attribute table, and the selected feature drawn heavier. Click a shape or a row, or use the arrow keys. Download original file saves the .shp, .gpkg or .geojson exactly as uploaded; Files that came with it saves each companion.

A layer’s title is shown where you choose and read it; its table name inside the file appears only under Technical details, as does anything a reader said about a file it refused.

Name the folders that hold your files. Here maps holds a Shapefile’s files and a ZMAP+ grid, and packages holds a GeoPackage with two layers.

maps, packages = 'maps', 'packages'

declare answers, by kind, the questions a kind asks before it is read. The Shapefile states its coordinate system in its .prj; naming the same one agrees with it. The grid’s corner values are cell centres:

report = client.upload(maps, attribution='NLOG.NL, nlog.nl', rights_confirmed=True,
declare={'esri-shapefile/1': {'crs': 'EPSG:23031'}, 'zmap-plus-grid/1': {'corners': 'centres'}})
for item in report.items:
print(item['path'], item['role'], item['state'])

A map layer reads as a FeatureSet: its features in file order, each with its geometry and properties, and the fields with their kinds. to_frame() gives one row per feature (pandas):

shp = next(i for i in report.items if i['role'] == 'primary' and i['path'].endswith('.shp'))
fields = client.read_data(shp['asset_id'], shp['revision'])
print(fields, fields.context['encoding'])
frame = fields.to_frame()
print(frame[['FIELD_CODE', 'CHRONOSTRA']].to_string(index=False))

A grid reads as the same GridSurface as an ESRI ASCII grid; missing cells are NaN:

item = next(i for i in report.items if i['path'].endswith('.zmap'))
grid = client.read_data(item['asset_id'], item['revision'])
values = grid.to_numpy()
missing = int((values != values).sum())
print(values.shape, missing, 'missing cells')

A GeoPackage’s layer is asked once the file has been read. Upload without it to see the choices (table name: title), then upload again with the layer, keyed by the file’s name so that each file of a folder gets its own:

waiting = client.upload(packages, attribution='NLOG.NL, nlog.nl', rights_confirmed=True, declare={'ogc-geopackage/1': {'crs': 'unknown'}})
asked = next(i for i in waiting.items if i['state'] == 'needs-decision')
choices = next(a for a in asked['asks'] if a['key'] == 'layer')['choices']
print(asked['path'], choices)
added = client.upload(packages, attribution='NLOG.NL, nlog.nl', rights_confirmed=True,
declare={'ogc-geopackage/1': {'crs': 'unknown'}, 'two.gpkg': {'ogc-geopackage/1': {'layer': 't_two'}}})
layer = client.read_data(added.items[0]['asset_id'], added.items[0]['revision'])
print(layer.context['layer_title'], sorted(f['properties']['FIELD_CODE'] for f in layer.features))

The second upload continues the first: the file waits for its answer and is read again with it.

Nothing is repaired. A refused file’s row says which kind it could not be read as (“This file could not be read as Map features (Shapefile): it does not have the structure that kind of file needs. Nothing was repaired.”), and Technical details say what is wrong, for example “This shapefile has no .dbf table, which every shapefile has; add it and upload again.” Refused are, among others: a Shapefile without its .dbf, a .shp and .dbf that disagree on the number of records, a grid whose header and values disagree, a rotated IRAP grid, multipatch shapes, a GeoPackage before 1.2, and a GeoJSON property that holds numbers in one feature and text in another.

Shapes are drawn and read as stored; there is no coordinate transformation and no binary IRAP. The CPS-3 and IRAP files in the conformance suite are synthetic: no rights-cleared file from those producers was available, so they prove that the reader and your answers agree, not what a given application writes.