Skip to content

Commit ab9e55d

Browse files
committed
- [WIP] Moving gdal to gempy_plugins
1 parent 2b93431 commit ab9e55d

File tree

4 files changed

+240
-0
lines changed

4 files changed

+240
-0
lines changed

gempy_plugins/gdal_topography/__init__.py

Whitespace-only changes.
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
from gdal_topography.load_dem_gdal import LoadDEMGDAL
2+
3+
4+
def load_from_gdal(self, filepath):
5+
dem = LoadDEMGDAL(filepath, extent=self.extent)
6+
self._x, self._y = None, None
7+
self.set_values(dem.get_values())
Lines changed: 185 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,185 @@
1+
"""
2+
This file is part of gempy.
3+
4+
Created on 16.04.2019
5+
6+
@author: Elisa Heim
7+
"""
8+
9+
import numpy as np
10+
import pandas as pn
11+
import os
12+
13+
from gempy_plugins.optional_dependencies import require_gdal
14+
import matplotlib.pyplot as plt
15+
16+
17+
class LoadDEMGDAL:
18+
"""Class to include height elevation data (e.g. DEMs) with the geological grid
19+
"""
20+
21+
def __init__(self, path_dem, grid=None, extent=None, delete_temp=True):
22+
"""
23+
Args:
24+
path_dem: path where dem is stored. file format: GDAL raster formats
25+
if grid: cropped to geomodel extent
26+
"""
27+
self.gdal = require_gdal()
28+
self.dem = self.gdal.Open(path_dem)
29+
30+
if isinstance(self.dem, type(None)):
31+
raise AttributeError(
32+
'Raster file could not be opened {}. Check if the filepath is correct. If yes,'
33+
'check if your file fits the requirements of GDALs raster file formats.'.format(path_dem))
34+
35+
try:
36+
self.dem_zval = self.dem.ReadAsArray()
37+
except AttributeError:
38+
raise AttributeError('Filepath seems to be wrong.')
39+
40+
self._get_raster_dimensions()
41+
42+
if extent is not None:
43+
self.regular_grid_extent = extent
44+
self.crop2grid()
45+
elif grid is not None:
46+
self.regular_grid_extent = grid.extent
47+
self.crop2grid()
48+
else:
49+
print('pass geo_model to automatically crop the DEM to the grid extent')
50+
print('depending on the size of the raster, this can take a while...')
51+
self.convert2xyz()
52+
53+
if delete_temp is True:
54+
self.dem = None
55+
os.remove('topo.xyz')
56+
if os.path.exists('_cropped_DEM.tif'):
57+
os.remove('_cropped_DEM.tif')
58+
59+
def _get_raster_dimensions(self):
60+
"""calculates DEM extent, resolution, and max. z extent (d_z)"""
61+
ulx, xres, xskew, uly, yskew, yres = self.dem.GetGeoTransform()
62+
z = self.dem_zval
63+
if np.any(np.array([xskew, yskew])) != 0:
64+
print('DEM is not north-oriented.')
65+
lrx = ulx + (self.dem.RasterXSize * xres)
66+
lry = uly + (self.dem.RasterYSize * yres)
67+
self.resolution = np.array([(uly - lry) / (-yres), (lrx - ulx) / xres]).astype(int)
68+
self.extent = np.array([ulx, lrx, lry, uly]).astype(int)
69+
self.d_z = np.array([z.min(), z.max()])
70+
71+
def get_values(self):
72+
return self.values_3D
73+
74+
def info(self):
75+
ulx, xres, xskew, uly, yskew, yres = self.dem.GetGeoTransform()
76+
print('raster extent: {}\n raster resolution: {}\n Pixel X size {}, Pixel Y size {}'.format(
77+
self.extent, self.resolution, xres, yres))
78+
plt.imshow(self.dem_zval, extent=self.extent) # plot raster as image
79+
plt.colorbar()
80+
81+
def crop2grid(self, delete_temp=True):
82+
"""
83+
Crops raster to extent of the geomodel grid.
84+
"""
85+
cornerpoints_geo = self._get_cornerpoints(self.regular_grid_extent)
86+
cornerpoints_dtm = self._get_cornerpoints(self.extent)
87+
88+
# self.check()
89+
90+
if np.any(cornerpoints_geo[:2] - cornerpoints_dtm[:2]) != 0:
91+
path_dest = '_cropped_DEM.tif'
92+
new_bounds = (self.regular_grid_extent[[0, 2, 1, 3]])
93+
self.gdal.Warp(
94+
path_dest,
95+
self.dem,
96+
options=self.gdal.WarpOptions(
97+
options=['outputBounds'], outputBounds=new_bounds
98+
)
99+
)
100+
101+
self.dem = self.gdal.Open(path_dest)
102+
self.dem_zval = self.dem.ReadAsArray()
103+
self._get_raster_dimensions()
104+
105+
print('Cropped raster to geo_model.grid.extent.')
106+
107+
def check(self):
108+
# TODO make this usable
109+
test = np.logical_and.reduce((self.regular_grid_extent[0] <= self.extent[0],
110+
self.regular_grid_extent[1] >= self.extent[1],
111+
self.regular_grid_extent[2] <= self.extent[2],
112+
self.regular_grid_extent[3] >= self.extent[3]))
113+
if test:
114+
cornerpoints_geo = self._get_cornerpoints(self.regular_grid_extent)
115+
cornerpoints_dtm = self._get_cornerpoints(self.extent)
116+
plt.scatter(cornerpoints_geo[:, 0], cornerpoints_geo[:, 1], label='grid extent')
117+
plt.scatter(cornerpoints_dtm[:, 0], cornerpoints_dtm[:, 1], label='raster extent')
118+
plt.legend(frameon=True, loc='upper left')
119+
raise AssertionError('The model extent is too different from the raster extent.')
120+
121+
def convert2xyz(self, del_temp=True):
122+
"""
123+
Translates the gdal raster object to a numpy array of xyz coordinates.
124+
"""
125+
path_dest = 'topo.xyz'
126+
print('storing converted file...')
127+
shape = self.dem_zval.shape
128+
if len(shape) == 3:
129+
shape = shape[1:]
130+
self.gdal.Translate(
131+
path_dest,
132+
self.dem,
133+
options=self.gdal.TranslateOptions(
134+
options=['format'],
135+
format="XYZ"
136+
)
137+
)
138+
139+
xyz = pn.read_csv(path_dest, header=None, sep=' ').values
140+
self.values_3D = xyz.reshape((*shape, 3), order='C')
141+
142+
# This is for 3D going from xyz to ijk
143+
self.values_3D = self.values_3D.swapaxes(0, 1)
144+
self.values_3D = np.flip(self.values_3D, 1)
145+
146+
return self.values_3D
147+
148+
def _resize(self, resx, resy):
149+
raise NotImplementedError
150+
151+
def resample(self, new_xres, new_yres, save_path):
152+
"""
153+
Decrease the pixel size of the raster.
154+
155+
Args:
156+
new_xres (int): desired resolution in x-direction
157+
new_yres (int): desired resolution in y-direction
158+
save_path (str): filepath to where the output file should be stored
159+
160+
Returns: Nothing, it writes a raster file with decreased resolution.
161+
162+
"""
163+
props = self.dem.GetGeoTransform()
164+
print('current pixel xsize:', props[1], 'current pixel ysize:', -props[-1])
165+
options = self.gdal.WarpOptions(options=['tr'], xRes=new_xres, yRes=new_yres)
166+
newfile = self.gdal.Warp(save_path, self.dem, options=options)
167+
newprops = newfile.GetGeoTransform()
168+
print('new pixel xsize:', newprops[1], 'new pixel ysize:', -newprops[-1])
169+
print('file saved in ' + save_path)
170+
171+
@staticmethod
172+
def _get_cornerpoints(extent):
173+
"""Get the coordinates of the bounding box.
174+
175+
Args:
176+
extent: np.array([xmin, xmax, ymin, ymax)]
177+
178+
Returns: np.ndarray with corner coordinates
179+
180+
"""
181+
upleft = ([extent[0], extent[3]])
182+
lowleft = ([extent[0], extent[2]])
183+
upright = ([extent[1], extent[3]])
184+
lowright = ([extent[1], extent[2]])
185+
return np.array([upleft, lowleft, upright, lowright])
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
def require_pandas():
2+
try:
3+
import pandas as pd
4+
except ImportError:
5+
raise ImportError("The pandas library is required to use this function.")
6+
return pd
7+
8+
9+
def require_pooch():
10+
try:
11+
import pooch
12+
except ImportError:
13+
raise ImportError("The pooch library is required to use this function.")
14+
return pooch
15+
16+
17+
def require_gempy_legacy():
18+
try:
19+
import gempy_legacy
20+
except ImportError:
21+
raise ImportError("The gempy_legacy library is required to use this function.")
22+
return gempy_legacy
23+
24+
25+
def require_gempy_viewer():
26+
try:
27+
import gempy_viewer
28+
except ImportError:
29+
raise ImportError("The gempy_viewer package is required to run this function.")
30+
return gempy_viewer
31+
32+
33+
def require_skimage():
34+
try:
35+
import skimage
36+
except ImportError:
37+
raise ImportError("The skimage package is required to run this function.")
38+
return skimage
39+
40+
41+
def require_gdal():
42+
try:
43+
from osgeo import gdal
44+
except ImportError:
45+
raise ImportError("The gdal package is required to run this function.")
46+
return gdal
47+
48+

0 commit comments

Comments
 (0)