8
8
import numpy as np
9
9
import pandas as pd
10
10
import pooch
11
+ import pyvista
11
12
12
13
from subsurface .core .geological_formats import Collars , Survey , BoreholeSet
13
14
from subsurface .core .geological_formats .boreholes ._combine_trajectories import MergeOptions
64
65
collar_loc = points
65
66
)
66
67
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 )
69
70
70
71
# %%
71
72
# Your code here:
107
108
108
109
# %%
109
110
110
- s = to_pyvista_line (
111
+ well_mesh = to_pyvista_line (
111
112
line_set = borehole_set .combined_trajectory ,
112
113
active_scalar = "lith_ids" ,
113
114
radius = 40
117
118
import matplotlib .pyplot as plt
118
119
119
120
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 )
121
122
122
123
collar_mesh = to_pyvista_points (collars .collar_loc )
123
124
p .add_mesh (collar_mesh , render_points_as_spheres = True )
143
144
# %% m
144
145
# 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.
145
146
# %%
147
+
148
+ colors_generator = gp .data .ColorsGenerator ()
146
149
elements = gp .structural_elements_from_borehole_set (
147
150
borehole_set = borehole_set ,
148
151
elements_dict = {
149
- "null " : {
152
+ "Basement " : {
150
153
"id" : - 1 ,
151
- "color" : "#983999"
154
+ "color" : next ( colors_generator )
152
155
},
153
156
"etchgoin" : {
154
157
"id" : 1 ,
155
- "color" : "#00923f"
158
+ "color" : next ( colors_generator )
156
159
},
157
160
"macoma" : {
158
161
"id" : 2 ,
159
- "color" : "#da251d"
162
+ "color" : next ( colors_generator )
160
163
},
161
164
"chanac" : {
162
165
"id" : 3 ,
163
- "color" : "#f8c300"
166
+ "color" : next ( colors_generator )
164
167
},
165
168
"mclure" : {
166
169
"id" : 4 ,
167
- "color" : "#bb825b"
170
+ "color" : next ( colors_generator )
168
171
},
169
172
"santa_margarita" : {
170
173
"id" : 5 ,
171
- "color" : "#983999"
174
+ "color" : next ( colors_generator )
172
175
},
173
176
"fruitvale" : {
174
177
"id" : 6 ,
175
- "color" : "#00923f"
178
+ "color" : next ( colors_generator )
176
179
},
177
180
"round_mountain" : {
178
181
"id" : 7 ,
179
- "color" : "#da251d"
182
+ "color" : next ( colors_generator )
180
183
},
181
184
"olcese" : {
182
185
"id" : 8 ,
183
- "color" : "#f8c300"
186
+ "color" : next ( colors_generator )
184
187
},
185
188
"freeman_jewett" : {
186
189
"id" : 9 ,
187
- "color" : "#bb825b"
190
+ "color" : next ( colors_generator )
188
191
},
189
192
"vedder" : {
190
193
"id" : 10 ,
191
- "color" : "#983999"
194
+ "color" : next ( colors_generator )
192
195
},
193
196
"eocene" : {
194
197
"id" : 11 ,
195
- "color" : "#00923f"
198
+ "color" : next ( colors_generator )
196
199
},
197
200
"cretaceous" : {
198
201
"id" : 12 ,
199
- "color" : "#da251d"
202
+ "color" : next ( colors_generator )
200
203
},
201
204
}
202
205
)
223
226
# - **Center grids**: Half sphere grids around a given point at surface. This are specially tuned
224
227
# for geophysical forward computations
225
228
# %%
226
- import gempy as gp
229
+ import gempy_viewer as gpv
227
230
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
+ )
229
240
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 ()
243
307
244
308
245
309
# %% md
@@ -280,23 +344,23 @@ def get_interface_coord_from_surfaces(surface_names: list, verbose=False):
280
344
#
281
345
# This is a list with the formations names for this data set.
282
346
# %%
283
- formations
347
+ elements
284
348
# %% md
285
349
# Lets add the first two (remember we always need a basement defined).
286
350
# %%
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
+
293
359
# %% md
294
360
# And we can set them into the `gempy` model:
295
361
# %%
296
- geo_model .set_surface_points (gempy_surface_points , update_surfaces = False )
297
- geo_model .update_to_interpolator ()
298
362
# %%
299
- g2d = gp .plot_2d (geo_model )
363
+ g2d = gpv .plot_2d (geo_model )
300
364
# %%
301
365
g2d .fig
302
366
# %% md
@@ -308,7 +372,16 @@ def get_interface_coord_from_surfaces(surface_names: list, verbose=False):
308
372
#
309
373
# Lets add an orientation:
310
374
# %%
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
+
312
385
# %% md
313
386
# GemPy depends on multiple data objects to store all the data structures necessary
314
387
# 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):
328
401
# Today we will look into details only some of these classes but what is important
329
402
# to notice is that you can access these objects as follows:
330
403
# %%
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
+
391
406
# %%
392
- geo_model .add_orientations (X = 277278.652995 , Y = 3.929298e+06 , Z = 0 , surface = "etchegoin" , pole_vector = (0 , 0 , 1 ), idx = 2 )
393
407
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 )
400
408
401
- # calculate all fault orientations
402
- new_ori = gp .set_orientation_from_neighbours_all (geo_model , neighbours )
403
- new_ori .df .head ()
404
409
# %%
405
- gp . compute_model (geo_model )
410
+ g3d = gpv . plot_3d (geo_model , show_lith = False , show = False )
406
411
# %%
407
- p3d_4 .plot_orientations ()
408
- p3d_4 .plot_surfaces ()
412
+ g3d .p .add_mesh (well_mesh )
409
413
# %%
410
- p3d_4 .p .add_mesh ( pyvista_mesh )
414
+ g3d .p .show ( )
411
415
412
- # %%
413
- plot_pyvista_to_notebook (p3d_4 .p )
414
416
# %% md
415
417
# -----
416
418
#
0 commit comments