Skip to content

Commit 570c54f

Browse files
committed
[DOC] Mik decent
1 parent c1783c0 commit 570c54f

File tree

2 files changed

+125
-121
lines changed

2 files changed

+125
-121
lines changed

examples/examples/real/mik.py

Lines changed: 122 additions & 120 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
import numpy as np
99
import pandas as pd
1010
import pooch
11+
import pyvista
1112

1213
from subsurface.core.geological_formats import Collars, Survey, BoreholeSet
1314
from subsurface.core.geological_formats.boreholes._combine_trajectories import MergeOptions
@@ -64,8 +65,8 @@
6465
collar_loc=points
6566
)
6667

67-
s = to_pyvista_points(collars.collar_loc)
68-
pv_plot([s], image_2d=True)
68+
well_mesh = to_pyvista_points(collars.collar_loc)
69+
pv_plot([well_mesh], image_2d=True)
6970

7071
# %%
7172
# Your code here:
@@ -107,7 +108,7 @@
107108

108109
# %%
109110

110-
s = to_pyvista_line(
111+
well_mesh = to_pyvista_line(
111112
line_set=borehole_set.combined_trajectory,
112113
active_scalar="lith_ids",
113114
radius=40
@@ -117,7 +118,7 @@
117118
import matplotlib.pyplot as plt
118119

119120
boring_cmap = plt.get_cmap(name="viridis", lut=14)
120-
p.add_mesh(s, cmap=boring_cmap)
121+
p.add_mesh(well_mesh, cmap=boring_cmap)
121122

122123
collar_mesh = to_pyvista_points(collars.collar_loc)
123124
p.add_mesh(collar_mesh, render_points_as_spheres=True)
@@ -143,60 +144,62 @@
143144
# %% m
144145
# Welly is a very powerful tool to inspect well data but it was not design for 3D. However they have a method to export XYZ coordinates of each of the well that we can take advanatage of to create a `subsurface.UnstructuredData` object. This object is one of the core data class of `subsurface` and we will use it from now on to keep working in 3D.
145146
# %%
147+
148+
colors_generator = gp.data.ColorsGenerator()
146149
elements = gp.structural_elements_from_borehole_set(
147150
borehole_set=borehole_set,
148151
elements_dict={
149-
"null": {
152+
"Basement": {
150153
"id": -1,
151-
"color": "#983999"
154+
"color": next(colors_generator)
152155
},
153156
"etchgoin": {
154157
"id": 1,
155-
"color": "#00923f"
158+
"color": next(colors_generator)
156159
},
157160
"macoma": {
158161
"id": 2,
159-
"color": "#da251d"
162+
"color": next(colors_generator)
160163
},
161164
"chanac": {
162165
"id": 3,
163-
"color": "#f8c300"
166+
"color": next(colors_generator)
164167
},
165168
"mclure": {
166169
"id": 4,
167-
"color": "#bb825b"
170+
"color": next(colors_generator)
168171
},
169172
"santa_margarita": {
170173
"id": 5,
171-
"color": "#983999"
174+
"color": next(colors_generator)
172175
},
173176
"fruitvale": {
174177
"id": 6,
175-
"color": "#00923f"
178+
"color": next(colors_generator)
176179
},
177180
"round_mountain": {
178181
"id": 7,
179-
"color": "#da251d"
182+
"color": next(colors_generator)
180183
},
181184
"olcese": {
182185
"id": 8,
183-
"color": "#f8c300"
186+
"color": next(colors_generator)
184187
},
185188
"freeman_jewett": {
186189
"id": 9,
187-
"color": "#bb825b"
190+
"color": next(colors_generator)
188191
},
189192
"vedder": {
190193
"id": 10,
191-
"color": "#983999"
194+
"color": next(colors_generator)
192195
},
193196
"eocene": {
194197
"id": 11,
195-
"color": "#00923f"
198+
"color": next(colors_generator)
196199
},
197200
"cretaceous": {
198201
"id": 12,
199-
"color": "#da251d"
202+
"color": next(colors_generator)
200203
},
201204
}
202205
)
@@ -223,23 +226,84 @@
223226
# - **Center grids**: Half sphere grids around a given point at surface. This are specially tuned
224227
# for geophysical forward computations
225228
# %%
226-
import gempy as gp
229+
import gempy_viewer as gpv
227230

228-
extent = [275619, 323824, 3914125, 3961793, -3972.6, 313.922]
231+
group = gp.data.StructuralGroup(
232+
name="Stratigraphic Pile",
233+
elements=elements,
234+
structural_relation=gp.data.StackRelationType.ERODE
235+
)
236+
structural_frame = gp.data.StructuralFrame(
237+
structural_groups=[group],
238+
color_gen=colors_generator
239+
)
229240

230-
# Your code here:
231-
geo_model = gp.create_model("getting started")
232-
geo_model.set_regular_grid(extent=extent, resolution=[50, 50, 50])
233-
# %% md
234-
# GemPy core code is written in Python. However for efficiency and gradient based
235-
# machine learning most of heavy computations happen in optimize compile code,
236-
# either C or CUDA for GPU.
237-
#
238-
# To do so, GemPy rely on the library `Theano`. To guarantee maximum optimization
239-
# `Theano` requires to compile the code for every Python kernel. The compilation is
240-
# done by calling the following line at any point (before computing the model):
241-
# %%
242-
gp.set_interpolator(geo_model, theano_optimizer='fast_compile', verbose=[])
241+
242+
# %% [markdown]
243+
# Determine the extent of the geological model from the surface points coordinates.
244+
all_surface_points_coords: gp.data.SurfacePointsTable = structural_frame.surface_points_copy
245+
extent_from_data = all_surface_points_coords.xyz.min(axis=0), all_surface_points_coords.xyz.max(axis=0)
246+
247+
# %% [markdown]
248+
# Create a GeoModel with the specified extent, grid resolution, and interpolation options.
249+
geo_model = gp.data.GeoModel(
250+
name="Stratigraphic Pile",
251+
structural_frame=structural_frame,
252+
grid=gp.data.Grid(
253+
extent=[extent_from_data[0][0], extent_from_data[1][0], extent_from_data[0][1], extent_from_data[1][1], extent_from_data[0][2], extent_from_data[1][2]],
254+
resolution=(50, 50, 50)
255+
),
256+
interpolation_options=gp.data.InterpolationOptions(
257+
range=5,
258+
c_o=10,
259+
mesh_extraction=True,
260+
number_octree_levels=3,
261+
),
262+
)
263+
264+
# %% [markdown]
265+
# Visualize the 3D geological model using GemPy's plot_3d function.
266+
gempy_plot = gpv.plot_3d(
267+
model=geo_model,
268+
kwargs_pyvista_bounds={
269+
'show_xlabels': False,
270+
'show_ylabels': False,
271+
},
272+
show=True,
273+
image=False
274+
)
275+
276+
# %% [markdown]
277+
# Combine all visual elements and display them together.
278+
sp_mesh: pyvista.PolyData = gempy_plot.surface_points_mesh
279+
280+
pyvista_plotter = init_plotter()
281+
pyvista_plotter.show_bounds(all_edges=True)
282+
283+
units_limit = [0, 13]
284+
pyvista_plotter.add_mesh(
285+
well_mesh.threshold(units_limit),
286+
cmap="tab20c",
287+
clim=units_limit
288+
)
289+
290+
pyvista_plotter.add_mesh(
291+
collar_mesh,
292+
point_size=10,
293+
render_points_as_spheres=True
294+
)
295+
296+
pyvista_plotter.add_point_labels(
297+
points=collars.collar_loc.points,
298+
labels=collars.ids,
299+
point_size=10,
300+
shape_opacity=0.5,
301+
font_size=12,
302+
bold=True
303+
)
304+
pyvista_plotter.add_actor(gempy_plot.surface_points_actor)
305+
306+
pyvista_plotter.show()
243307

244308

245309
# %% md
@@ -280,23 +344,23 @@ def get_interface_coord_from_surfaces(surface_names: list, verbose=False):
280344
#
281345
# This is a list with the formations names for this data set.
282346
# %%
283-
formations
347+
elements
284348
# %% md
285349
# Lets add the first two (remember we always need a basement defined).
286350
# %%
287-
geo_model.add_surfaces(formations[:2])
288-
# %% md
289-
# Using the function defined above we just extract the surface points for **topo**:
290-
# %%
291-
gempy_surface_points = get_interface_coord_from_surfaces(["topo"])
292-
gempy_surface_points
351+
group = gp.data.StructuralGroup(
352+
name="Stratigraphic Pile Top",
353+
elements=elements[:3],
354+
structural_relation=gp.data.StackRelationType.ERODE
355+
)
356+
geo_model.structural_frame.structural_groups[0] = group
357+
358+
293359
# %% md
294360
# And we can set them into the `gempy` model:
295361
# %%
296-
geo_model.set_surface_points(gempy_surface_points, update_surfaces=False)
297-
geo_model.update_to_interpolator()
298362
# %%
299-
g2d = gp.plot_2d(geo_model)
363+
g2d = gpv.plot_2d(geo_model)
300364
# %%
301365
g2d.fig
302366
# %% md
@@ -308,7 +372,16 @@ def get_interface_coord_from_surfaces(surface_names: list, verbose=False):
308372
#
309373
# Lets add an orientation:
310374
# %%
311-
geo_model.add_orientations(X=300000, Y=3930000, Z=0, surface="topo", pole_vector=(0, 0, 1))
375+
# geo_model.add_orientations(X=300000, Y=3930000, Z=0, surface="topo", pole_vector=(0, 0, 1))
376+
gp.add_orientations(
377+
x=[300000],
378+
y=[3930000],
379+
z=[0],
380+
elements_names=elements[0].name,
381+
pole_vector=np.array([0, 0, 1]),
382+
geo_model=geo_model
383+
)
384+
312385
# %% md
313386
# GemPy depends on multiple data objects to store all the data structures necessary
314387
# to construct an structural model. To keep all the necessary objects in sync the
@@ -328,89 +401,18 @@ def get_interface_coord_from_surfaces(surface_names: list, verbose=False):
328401
# Today we will look into details only some of these classes but what is important
329402
# to notice is that you can access these objects as follows:
330403
# %%
331-
geo_model.additional_data
332-
# %%
333-
gp.compute_model(geo_model)
334-
# %%
335-
g3d = gp.plot_3d(geo_model, plotter_type="background")
336-
# %%
337-
g3d.p.add_mesh(pyvista_mesh)
338-
# %%
339-
plot_pyvista_to_notebook(g3d.p)
340-
# %% md
341-
# ## Second layer
342-
# %%
343-
geo_model.add_surfaces(formations[2])
344-
# %%
345-
gempy_surface_points = get_interface_coord_from_surfaces(formations[:2])
346-
geo_model.set_surface_points(gempy_surface_points, update_surfaces=False)
347-
geo_model.update_to_interpolator()
348-
# %%
349-
gp.compute_model(geo_model)
350-
# %%
351-
live_plot = gp.plot_3d(geo_model, plotter_type="background", show_results=True)
352-
# %%
353-
plot_pyvista_to_notebook(live_plot.p)
354-
# %%
355-
live_plot.toggle_live_updating()
356-
# %% md
357-
# ### Trying to fix the model: Multiple Geo. Features/Series
358-
# %%
359-
geo_model.add_features("Formations")
360-
# %%
361-
geo_model.map_stack_to_surfaces({"Form1": ["etchegoin", "macoma"]}, set_series=False)
362-
# %%
363-
geo_model.add_orientations(X=300000, Y=3930000, Z=0, surface="etchegoin", pole_vector=(0, 0, 1), idx=1)
364-
# %%
365-
gp.compute_model(geo_model)
366-
# %%
367-
h3d = gp.plot_3d(geo_model, plotter_type="background", show_lith=False, ve=5)
368-
# %%
369-
plot_pyvista_to_notebook(h3d.p)
370-
# %% md
371-
# ## Last layers for today
372-
# %%
373-
geo_model.add_surfaces(formations[3:5])
374-
# %%
375-
f_last = formations[:4]
376-
f_last
377-
# %%
378-
gempy_surface_points = get_interface_coord_from_surfaces(f_last)
379-
geo_model.set_surface_points(gempy_surface_points, update_surfaces=False)
380-
geo_model.update_to_interpolator()
381-
# %%
382-
gp.compute_model(geo_model)
383-
# %%
384-
p3d_4 = gp.plot_3d(geo_model, plotter_type="background", show_lith=False, ve=5)
385-
# %%
386-
plot_pyvista_to_notebook(p3d_4.p)
387-
# %%
388-
geo_model.add_orientations(X=321687.059770, Y=3.945955e+06, Z=0, surface="etchegoin", pole_vector=(0, 0, 1), idx=1)
389-
gp.compute_model(geo_model)
390-
p3d_4.plot_surfaces()
404+
geo_model.interpolation_options
405+
391406
# %%
392-
geo_model.add_orientations(X=277278.652995, Y=3.929298e+06, Z=0, surface="etchegoin", pole_vector=(0, 0, 1), idx=2)
393407
gp.compute_model(geo_model)
394-
p3d_4.plot_surfaces()
395-
# %% md
396-
# ## Adding many more orientations
397-
# %%
398-
# find neighbours
399-
neighbours = gp.select_nearest_surfaces_points(geo_model, geo_model._surface_points.df, 2)
400408

401-
# calculate all fault orientations
402-
new_ori = gp.set_orientation_from_neighbours_all(geo_model, neighbours)
403-
new_ori.df.head()
404409
# %%
405-
gp.compute_model(geo_model)
410+
g3d = gpv.plot_3d(geo_model,show_lith=False, show=False)
406411
# %%
407-
p3d_4.plot_orientations()
408-
p3d_4.plot_surfaces()
412+
g3d.p.add_mesh(well_mesh)
409413
# %%
410-
p3d_4.p.add_mesh(pyvista_mesh)
414+
g3d.p.show()
411415

412-
# %%
413-
plot_pyvista_to_notebook(p3d_4.p)
414416
# %% md
415417
# -----
416418
#

gempy/modules/data_manipulation/manipulate_points.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -126,12 +126,14 @@ def add_orientations(geo_model: GeoModel,
126126
raise ValueError("Either pole_vector or orientation must be provided.")
127127

128128
if orientation is not None:
129-
orientation = np.array(orientation)
129+
orientation = np.array(orientation, ndmin=2)
130130
pole_vector = convert_orientation_to_pole_vector(
131131
azimuth=orientation[:, 0],
132132
dip=orientation[:, 1],
133133
polarity=orientation[:, 2]
134134
)
135+
else:
136+
pole_vector = np.array(pole_vector, ndmin=2)
135137

136138
elements_names = _validate_args(elements_names, x, y, z, pole_vector)
137139

0 commit comments

Comments
 (0)