Code Monkey home page Code Monkey logo

zmapio's Introduction

zmapio: reading and writing ZMAP Plus Grid files

CI Status PyPI version

To install:

$ pip install zmapio

Basic usage of zmapio

import matplotlib.pyplot as plt
import numpy as np
from zmapio import ZMAPGrid
%matplotlib inline

Reading a ZMAP file:

z_file = ZMAPGrid('./examples/NSLCU.dat')

Accessing the comments header:

for c in z_file.comments:
    print(c)

Landmark Zmap grid file name: .DATANSLCU.dat Created/converted by Oasis Montaj, Geosoft Inc.

Plotting the grid data:

z_file.plot()

image

Counts for rows and columns:

z_file.no_cols, z_file.no_rows

(435, 208)

Shape for z-values:

z_file.z_values.shape

(208, 435)

Exporting to CSV file:

z_file.to_csv('./output/output.csv')
head ./output/output.csv

-630000.0,2621000.0,-16481.9570313 -630000.0,2618000.0,-16283.9033203 -630000.0,2615000.0,-16081.5751953 -630000.0,2612000.0,-15856.7861328 -630000.0,2609000.0,-15583.7167969 -630000.0,2606000.0,-15255.734375 -630000.0,2603000.0,-14869.3769531 -630000.0,2600000.0,-14426.1513672 -630000.0,2597000.0,-13915.8769531 -630000.0,2594000.0,-13340.4677734

Exporting to WKT file:

z_file.to_wkt('./output/output.wkt', precision=2)

Exporting to GeoJSON file:

z_file.to_geojson('./output/output.json')

Exporting to Pandas Dataframe:

df = z_file.to_dataframe()
df.Z.describe()

count 90480.000000 mean -5244.434235 std 4692.845490 min -16691.371094 25% -10250.590088 50% -4003.433105 75% -1320.896881 max 2084.417969 Name: Z, dtype: float64

Write a new ZMAP file as 3 nodes per line format:

z_file.write('./output/test.zmap', nodes_per_line=3)
head ./output/test.zmap

! 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

Creating a ZMAP object from string:

z_text = """
!
! File created by DMBTools2.GridFileFormats.ZmapPlusFile
!
@GRID FILE, GRID, 4
20, -9999.0000000, , 7, 1
6, 4, 0, 200, 0, 300
0.0, 0.0, 0.0
@
       -9999.0000000       -9999.0000000           3.0000000          32.0000000
          88.0000000          13.0000000
       -9999.0000000          20.0000000           8.0000000          42.0000000
          75.0000000           5.0000000
           5.0000000         100.0000000          35.0000000          50.0000000
          27.0000000           1.0000000
           2.0000000          36.0000000          10.0000000           6.0000000
           9.0000000       -9999.0000000
"""
z_t = ZMAPGrid(z_text)
z_t.plot()

image

Adding colorbar and colormap using matplotlib:

z_obj = ZMAPGrid('./examples/NStopo.dat')
fig=plt.figure(figsize=(12, 6))
z_obj.plot(cmap='jet')
plt.colorbar()

image

Creating a new ZMAP object from 2D-Numpy array with shape (no_cols, no_rows):

z_val = z_obj.z_values
print('Z-values shape: ', z_val.shape)
new_zgrid = ZMAPGrid(z_values=z_val, min_x=-630000.0000, max_x=672000.0000,
                     min_y=2000000.0000,  max_y=2621000.0000)

Z-values shape: (435, 208)

new_zgrid.plot(cmap='gist_earth')

image

Customize writing a ZMAP file:

new_zgrid.comments = ['this is', 'a test']
new_zgrid.nodes_per_line = 4
new_zgrid.field_width = 15
new_zgrid.decimal_places = 3
new_zgrid.name = 'test'
new_zgrid.write('./output/new_z.dat')
head ./output/new_z.dat

!this is !a test @test, GRID, 4 15, 1e+30, , 3, 1 208, 435, -630000.0, 672000.0, 2000000.0, 2621000.0 0.0, 0.0, 0.0 @ -67.214 -67.570 -67.147 -69.081 -73.181 -74.308 -72.766 -72.034 -70.514 -68.555 -66.195 -62.776

References

zmapio's People

Contributors

abduhbm avatar dmbaker avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

zmapio's Issues

xyz points from zmap in wrong position

Thank you for this repo - it is really useful.

I have come across an issue with the creation of the xyz points from the zmap file. When creating the xy arrays the points are incorrectly located. I would expect to see the output points in the cell centers. From inspecting the code I think this occurs when inputting the cell edge min_x, max_x etc. values into np.linspace rather than the cell center min and max values. Hopefully the example below illustrates the point and provides a fix.

Here is an example code that reads a zmap file, creates a dataframe of points using .to_pandas() and creating a shapefile from that to view the point locations

from zmapio import ZMAPGrid
import geopandas as gpd
import numpy as np
from shapely.geometry import Point

z_file = ZMAPGrid(os.path.join(environ['USERPROFILE'],'Desktop','UK_DEM.dat')) # read file

df=z_file.to_pandas() # make dataframe
df.dropna(inplace=True) # drop nulls
df['geometry']=df.apply(lambda x: Point(x['X'],x['Y']),axis=1) # make point geoms
df=gpd.GeoDataFrame(df,crs='epsg:4326') # make geodataframe and export as shapefile
df.to_file(os.path.join(environ['USERPROFILE'],'Desktop','UK_DEM_POINTS.shp')) # export shapefile

When plotting the shapefile over the zmap in ArcGIS/QGIS we can see that the points are located in the cell top left in the top left corner:
image

Near the center in the middle of the zmap:
image

Point in the bottom right of cell toward the bottom right corner of the zmap:
image

To make these consistently cell center when creating the x and y meshgrids the code would need to look something like this:

# get cell size
dx=(max_x-min_x)/no_cols
dy=(max_y-min_y)/no_rows
# make arrays of x and y
x = np.linspace(min_x+(dx/2), max_x-(dx/2), no_cols) # shift min value right by 1/2 cell and max value left by 1/2 cell
y = np.linspace(max_y+(dy/2), min_y-(dy/2), no_rows)
# meshgrid
X,Y=np.meshgrid(x,y)
# export dataframe to view points location compared with zmap
center_points=gpd.GeoDataFrame({'X':X.ravel(),'Y':Y.ravel(),'geometry':map(Point,zip(X.ravel(),Y.ravel()))},crs='epsg:4326')
center_points.to_file(os.path.join(environ['USERPROFILE'],'Desktop','UK_DEM_POINTS_CENTER.shp'))

The resultant shapefile of points plotted over the zmap shows the points now placed in cell center. Again the image below is the top left of the zmap.

image

I hope that is clear. If not let me know.

Many Thanks,

Z values are swapped in written grid

Here's the minimal reproducable example

from zmapio import ZMAPGrid

zmap = ZMAPGrid('D:/tmp/test_pet_sq.txt')

out = ZMAPGrid(z_values = zmap.z_values, 
                min_x = zmap.min_x,
                max_x = zmap.max_x,
                min_y = zmap.min_y,
                max_y = zmap.max_y
                )

out.comments = ['test', 'zmapio']
out.nodes_per_line = 3
out.field_width = 15
out.decimal_places = 4
out.name = 'zmapio_test'

out.write('D:/tmp/test_zmapio_sq.txt')

Files for testing and output generated by this code are attached. As you can see the actual data in an output file differs from an input file.

If I change out generation by the following:

out = ZMAPGrid(z_values = zmap.z_values.swapaxes(0, 1), 

generated file looks correct.

I'm not sure if it's input or output related issue but it doesn't look like a correct behaviour.

test_pet_sq.txt
test_zmapio_sq.txt

zmapio fails to read zmap grid generated by ROXAR RMS

It's a very simple issue, RMS adds the following string

+Grid data starts after this line

after the end of header section (so basically after closing @). Zmapio tries to interpret this line as a z value and fails. You need to skip this line if occurs.

CRS transformation?

Great library for reading and writing zmap files. It would be great to add CRS transformations to this library. To do it correctly, every XY location needs transformation, not just the xMin, xMax, yMin, yMax. I got this far and it works using a GeoDataFrame for the transformation. However, I cannot represent the coordinates in the z_file since it only contains the min/max and coordinates are re-created by x = np.linspace(self.min_x, self.max_x, self.no_cols). The results are a slightly shifted/rotated grid. Perhaps it will work if I replace linespace by a loop of transformed values, but then that would not work when importing into other software.

If I use a CSV where every X,Y,Z is represented the transformation is perfect.

Maybe I'm doing something wrong, suggestions welcome.

The goal is to grid data in lat/long coordinates using griddata() and export to a zMap file in another specified CRS.

def writeZmap(xi, yi, zim, exportCRS):
success = False
try:
z = ma.filled(zim, np.nan)
x, y = np.meshgrid(xi, yi)
dat = np.column_stack([x.flatten(), y.flatten(), z.flatten(),])
df = pd.DataFrame(dat, columns=["X", "Y", "Z"])
gdf = gpd.GeoDataFrame(df, geometry=gpd.points_from_xy(df.X, df.Y, df.Z))
gdf = gdf.set_crs('EPSG:4326') # World Geodetic System
gdf = gdf.to_crs(exportCRS)
x_tx = np.unique(gdf.geometry.x)
y_tx = np.unique(gdf.geometry.y).T
z_tx = df['Z'].values.reshape(z.shape[0], z.shape[1]).swapaxes(0, 1)
z_file = ZMAPGrid(z_values=z_tx, min_x=x_tx.min(), max_x=x_tx.max(),
min_y=y_tx.max(), max_y=y_tx.min())
success = True
print('Zmap file created....')
return success, z_file
except Exception as e:
success = False
print('Error creating Zmap file: ' + str(e))
return success, None

CRS Transformation zMap

Default null_value does not render correctly

Thank you for this library; I'm using it in gio.

The default null value of 1e+30 is passed to a format string like "{0:>{1}.{2}f}".format(1e30, 12, 4) (see line in code) and produces '1000000000000000019884624838656.0000' instead of '1e+30 or possibly '1.0000e+30'.

Could fix by using the str() of the null value for NaNs, and the current format string for 'normal' values. Or you could change the format string to something like "{0:>{1}.{2}e}" (which would use scientific notation for everything, not sure if that's desirable).

I will submit a PR for a fix; you can decide what to do with it!

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.