|
| 1 | +import os |
| 2 | +import xarray as xr |
| 3 | +import numpy as np |
| 4 | +import gempy as gp |
| 5 | +import subsurface |
| 6 | + |
| 7 | + |
| 8 | +def process_file(filename, global_extent, color_generator: gp.data.ColorsGenerator): |
| 9 | + dataset: xr.Dataset = xr.open_dataset(filename) |
| 10 | + file_extent = _calculate_extent(dataset) |
| 11 | + global_extent = _update_global_extent(global_extent, file_extent) |
| 12 | + |
| 13 | + base, ext = os.path.splitext(filename) |
| 14 | + base = os.path.basename(base) |
| 15 | + structural_element = _extract_surface_points_and_orientations(dataset, base, color_generator) |
| 16 | + |
| 17 | + return structural_element, global_extent |
| 18 | + |
| 19 | + |
| 20 | +# Function to calculate the extent (ROI) for a single dataset |
| 21 | +def _calculate_extent(dataset): |
| 22 | + x_coord, y_coord, z_coord = dataset.vertex[:, 0], dataset.vertex[:, 1], dataset.vertex[:, 2] |
| 23 | + return [x_coord.min().values, x_coord.max().values, y_coord.min().values, y_coord.max().values, z_coord.min().values, z_coord.max().values] |
| 24 | + |
| 25 | + |
| 26 | +# Function to extract surface points and orientations from the dataset |
| 27 | + |
| 28 | + |
| 29 | +def _extract_surface_points_and_orientations(dataset, name, color_generator) -> gp.data.StructuralElement: |
| 30 | + name = name.replace("Stonepark_", "") |
| 31 | + |
| 32 | + # Extract surface points and orientations |
| 33 | + unstruct = subsurface.UnstructuredData(dataset) |
| 34 | + ts = subsurface.TriSurf(mesh=unstruct) |
| 35 | + triangulated_mesh = subsurface.visualization.to_pyvista_mesh(ts) |
| 36 | + # print(name) |
| 37 | + # subsurface.visualization.pv_plot([triangulated_mesh]) |
| 38 | + |
| 39 | + # Decimate the mesh and compute normals |
| 40 | + decimated_mesh = triangulated_mesh.decimate_pro(0.95) |
| 41 | + normals = decimated_mesh.compute_normals(point_normals=False, cell_normals=True, consistent_normals=True) |
| 42 | + normals_array = np.array(normals.cell_data["Normals"]) |
| 43 | + |
| 44 | + # Filter points |
| 45 | + vertex_sp = normals.cell_centers().points |
| 46 | + vertex_grads = normals_array |
| 47 | + positive_z = vertex_grads[:, 2] > 0 |
| 48 | + largest_component_z = np.all(vertex_grads[:, 2:3] >= np.abs(vertex_grads[:, :2]), axis=1) |
| 49 | + filter_mask = np.logical_and(positive_z, largest_component_z) |
| 50 | + |
| 51 | + surface_points_xyz = vertex_sp[filter_mask] |
| 52 | + orientations_gxyz = vertex_grads[filter_mask] |
| 53 | + nuggets = np.ones(len(surface_points_xyz)) * 0.000001 |
| 54 | + |
| 55 | + # Create SurfacePointsTable and OrientationsTable |
| 56 | + every = 10 |
| 57 | + surface_points = gp.data.SurfacePointsTable.from_arrays( |
| 58 | + x=surface_points_xyz[::every, 0], |
| 59 | + y=surface_points_xyz[::every, 1], |
| 60 | + z=surface_points_xyz[::every, 2], |
| 61 | + names=name, |
| 62 | + nugget=nuggets[::every] |
| 63 | + ) |
| 64 | + |
| 65 | + every = 10 |
| 66 | + orientations = gp.data.OrientationsTable.from_arrays( |
| 67 | + x=surface_points_xyz[::every, 0], |
| 68 | + y=surface_points_xyz[::every, 1], |
| 69 | + z=surface_points_xyz[::every, 2], |
| 70 | + G_x=orientations_gxyz[::every, 0], |
| 71 | + G_y=orientations_gxyz[::every, 1], |
| 72 | + G_z=orientations_gxyz[::every, 2], |
| 73 | + nugget=4, |
| 74 | + names=name |
| 75 | + ) |
| 76 | + |
| 77 | + structural_element = gp.data.StructuralElement( |
| 78 | + name=name, |
| 79 | + surface_points=surface_points, |
| 80 | + orientations=orientations, |
| 81 | + color=next(color_generator) |
| 82 | + ) |
| 83 | + |
| 84 | + return structural_element |
| 85 | + |
| 86 | + |
| 87 | +# Function to update the global extent based on each file's extent |
| 88 | +def _update_global_extent(global_extent, file_extent): |
| 89 | + if not global_extent: |
| 90 | + return file_extent |
| 91 | + else: |
| 92 | + return [min(global_extent[0], file_extent[0]), max(global_extent[1], file_extent[1]), |
| 93 | + min(global_extent[2], file_extent[2]), max(global_extent[3], file_extent[3]), |
| 94 | + min(global_extent[4], file_extent[4]), max(global_extent[5], file_extent[5])] |
0 commit comments