subsurface-terra 2025.1.0rc14__py3-none-any.whl → 2025.1.0rc16__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (81) hide show
  1. subsurface/__init__.py +31 -31
  2. subsurface/_version.py +34 -21
  3. subsurface/api/__init__.py +13 -13
  4. subsurface/api/interfaces/__init__.py +3 -3
  5. subsurface/api/interfaces/stream.py +136 -136
  6. subsurface/api/reader/read_wells.py +78 -78
  7. subsurface/core/geological_formats/boreholes/_combine_trajectories.py +117 -117
  8. subsurface/core/geological_formats/boreholes/_map_attrs_to_survey.py +236 -0
  9. subsurface/core/geological_formats/boreholes/_survey_to_unstruct.py +163 -0
  10. subsurface/core/geological_formats/boreholes/boreholes.py +140 -116
  11. subsurface/core/geological_formats/boreholes/collars.py +26 -26
  12. subsurface/core/geological_formats/boreholes/survey.py +86 -380
  13. subsurface/core/geological_formats/fault.py +47 -47
  14. subsurface/core/reader_helpers/reader_unstruct.py +11 -11
  15. subsurface/core/reader_helpers/readers_data.py +130 -130
  16. subsurface/core/reader_helpers/readers_wells.py +13 -13
  17. subsurface/core/structs/__init__.py +3 -3
  18. subsurface/core/structs/base_structures/__init__.py +2 -2
  19. subsurface/core/structs/base_structures/_liquid_earth_mesh.py +121 -121
  20. subsurface/core/structs/base_structures/_unstructured_data_constructor.py +70 -70
  21. subsurface/core/structs/base_structures/base_structures_enum.py +6 -6
  22. subsurface/core/structs/base_structures/structured_data.py +282 -282
  23. subsurface/core/structs/base_structures/unstructured_data.py +319 -319
  24. subsurface/core/structs/structured_elements/octree_mesh.py +10 -10
  25. subsurface/core/structs/structured_elements/structured_grid.py +59 -59
  26. subsurface/core/structs/structured_elements/structured_mesh.py +9 -9
  27. subsurface/core/structs/unstructured_elements/__init__.py +3 -3
  28. subsurface/core/structs/unstructured_elements/line_set.py +72 -72
  29. subsurface/core/structs/unstructured_elements/point_set.py +43 -43
  30. subsurface/core/structs/unstructured_elements/tetrahedron_mesh.py +35 -35
  31. subsurface/core/structs/unstructured_elements/triangular_surface.py +62 -62
  32. subsurface/core/utils/utils_core.py +38 -38
  33. subsurface/modules/reader/__init__.py +13 -13
  34. subsurface/modules/reader/faults/faults.py +80 -80
  35. subsurface/modules/reader/from_binary.py +46 -46
  36. subsurface/modules/reader/mesh/_GOCAD_mesh.py +82 -82
  37. subsurface/modules/reader/mesh/_trimesh_reader.py +447 -447
  38. subsurface/modules/reader/mesh/csv_mesh_reader.py +53 -53
  39. subsurface/modules/reader/mesh/dxf_reader.py +177 -177
  40. subsurface/modules/reader/mesh/glb_reader.py +30 -30
  41. subsurface/modules/reader/mesh/mx_reader.py +232 -232
  42. subsurface/modules/reader/mesh/obj_reader.py +53 -53
  43. subsurface/modules/reader/mesh/omf_mesh_reader.py +43 -43
  44. subsurface/modules/reader/mesh/surface_reader.py +56 -56
  45. subsurface/modules/reader/mesh/surfaces_api.py +41 -41
  46. subsurface/modules/reader/profiles/__init__.py +3 -3
  47. subsurface/modules/reader/profiles/profiles_core.py +197 -197
  48. subsurface/modules/reader/read_netcdf.py +38 -38
  49. subsurface/modules/reader/topography/__init__.py +7 -7
  50. subsurface/modules/reader/topography/topo_core.py +100 -100
  51. subsurface/modules/reader/volume/read_grav3d.py +478 -428
  52. subsurface/modules/reader/volume/read_volume.py +327 -230
  53. subsurface/modules/reader/volume/segy_reader.py +105 -105
  54. subsurface/modules/reader/volume/seismic.py +173 -173
  55. subsurface/modules/reader/volume/volume_utils.py +43 -43
  56. subsurface/modules/reader/wells/DEP/__init__.py +43 -43
  57. subsurface/modules/reader/wells/DEP/_well_files_reader.py +167 -167
  58. subsurface/modules/reader/wells/DEP/_wells_api.py +61 -61
  59. subsurface/modules/reader/wells/DEP/_welly_reader.py +180 -180
  60. subsurface/modules/reader/wells/DEP/pandas_to_welly.py +212 -212
  61. subsurface/modules/reader/wells/_read_to_df.py +57 -57
  62. subsurface/modules/reader/wells/read_borehole_interface.py +148 -148
  63. subsurface/modules/reader/wells/wells_utils.py +68 -68
  64. subsurface/modules/tools/mocking_aux.py +104 -104
  65. subsurface/modules/visualization/__init__.py +2 -2
  66. subsurface/modules/visualization/to_pyvista.py +320 -320
  67. subsurface/modules/writer/to_binary.py +12 -12
  68. subsurface/modules/writer/to_rex/common.py +78 -78
  69. subsurface/modules/writer/to_rex/data_struct.py +74 -74
  70. subsurface/modules/writer/to_rex/gempy_to_rexfile.py +791 -791
  71. subsurface/modules/writer/to_rex/material_encoder.py +44 -44
  72. subsurface/modules/writer/to_rex/mesh_encoder.py +152 -152
  73. subsurface/modules/writer/to_rex/to_rex.py +115 -115
  74. subsurface/modules/writer/to_rex/utils.py +15 -15
  75. subsurface/optional_requirements.py +116 -116
  76. {subsurface_terra-2025.1.0rc14.dist-info → subsurface_terra-2025.1.0rc16.dist-info}/METADATA +194 -194
  77. subsurface_terra-2025.1.0rc16.dist-info/RECORD +98 -0
  78. {subsurface_terra-2025.1.0rc14.dist-info → subsurface_terra-2025.1.0rc16.dist-info}/WHEEL +1 -1
  79. {subsurface_terra-2025.1.0rc14.dist-info → subsurface_terra-2025.1.0rc16.dist-info}/licenses/LICENSE +203 -203
  80. subsurface_terra-2025.1.0rc14.dist-info/RECORD +0 -96
  81. {subsurface_terra-2025.1.0rc14.dist-info → subsurface_terra-2025.1.0rc16.dist-info}/top_level.txt +0 -0
@@ -1,116 +1,140 @@
1
- import numpy as np
2
- import pandas as pd
3
- from dataclasses import dataclass
4
- from typing import Hashable
5
-
6
- from ._combine_trajectories import create_combined_trajectory, MergeOptions
7
- from .collars import Collars
8
- from .survey import Survey
9
- from ...structs import LineSet
10
-
11
-
12
- @dataclass
13
- class BoreholeSet:
14
- """
15
- This module provides a class, `BoreholeSet`, that represents a collection of boreholes. It contains methods for accessing coordinate data for each lithology in the boreholes.
16
-
17
- Notes:
18
- - Collars is defined as 1 UnstructuredData
19
- - Combined trajectory is defined as 1 UnstructuredData
20
-
21
- Classes:
22
- - `BoreholeSet`: Represents a collection of boreholes.
23
-
24
- Methods:
25
- - `__init__`: Initializes a new `BoreholeSet` object with the specified input parameters.
26
- - `get_top_coords_for_each_lith`: Returns a dictionary of top coordinates for each lithology in the boreholes.
27
- - `get_bottom_coords_for_each_lith`: Returns a dictionary of bottom coordinates for each lithology in the boreholes.
28
-
29
- Attributes:
30
- - `collars`: A `Collars` object representing the collar information for the boreholes.
31
- - `survey`: A `Survey` object representing the survey information for the boreholes.
32
- - `combined_trajectory`: A `LineSet` object representing the combined trajectory of the boreholes.
33
-
34
- Usage:
35
- ```
36
- borehole_set = BoreholeSet(collars, survey, merge_option)
37
- top_coords = borehole_set.get_top_coords_for_each_lith()
38
- bottom_coords = borehole_set.get_bottom_coords_for_each_lith()
39
- ```
40
-
41
- Note: The example usage code provided above is for demonstration purposes only. Please replace `collars`, `survey`, and `merge_option` with the actual input parameters when using the `BoreholeSet` class.
42
-
43
- """
44
- __slots__ = ['collars', 'survey', 'combined_trajectory']
45
- collars: Collars
46
- survey: Survey
47
- combined_trajectory: LineSet
48
-
49
- def __init__(self, collars: Collars, survey: Survey, merge_option: MergeOptions, slice_=slice(None)):
50
-
51
- new_collars = self._remap_collars_with_survey(collars, survey)
52
-
53
- self.collars = new_collars
54
- self.survey = survey
55
- self.combined_trajectory: LineSet = create_combined_trajectory(collars, survey, merge_option, slice_)
56
-
57
- @staticmethod
58
- def _remap_collars_with_survey(collars, survey):
59
- import pandas as pd
60
- # Create a DataFrame from your first list
61
- df1 = pd.DataFrame({'name': collars.ids, 'x': collars.data.vertex[:, 0], 'y': collars.data.vertex[:, 1], 'z': collars.data.vertex[:, 2]})
62
- df1 = df1.set_index('name')
63
- # Reindex to match the second list of names
64
- df_reindexed = df1.reindex(survey.well_id_mapper.keys())
65
- new_collars = Collars.from_df(df_reindexed)
66
- return new_collars
67
-
68
- def to_binary(self, path: str) -> bool:
69
- # I need to implement the survey to and then name the files accordingly
70
- bytearray_le_collars: bytes = self.collars.data.to_binary()
71
- bytearray_le_trajectory: bytes = self.combined_trajectory.data.to_binary()
72
-
73
- new_file = open(f"{path}_collars.le", "wb")
74
- new_file.write(bytearray_le_collars)
75
-
76
- new_file = open(f"{path}_trajectory.le", "wb")
77
- new_file.write(bytearray_le_trajectory)
78
- return True
79
-
80
- def get_top_coords_for_each_lith(self) -> dict[Hashable, np.ndarray]:
81
- merged_df = self._merge_vertex_data_arrays_to_dataframe()
82
- component_lith_arrays = {}
83
- for lith, group in merged_df.groupby('lith_ids'):
84
- lith = int(lith)
85
- first_vertices = group.groupby('well_id').first().reset_index()
86
- array = first_vertices[['X', 'Y', 'Z']].values
87
- component_lith_arrays[lith] = array
88
-
89
- return component_lith_arrays
90
-
91
- def get_bottom_coords_for_each_lith(self) -> dict[Hashable, np.ndarray]:
92
- merged_df = self._merge_vertex_data_arrays_to_dataframe()
93
- component_lith_arrays = {}
94
- groupby = merged_df.groupby('lith_ids')
95
- if groupby.ngroups == 0:
96
- raise ValueError("No components found")
97
- for lith, group in groupby:
98
- lith = int(lith)
99
- first_vertices = group.groupby('well_id').last().reset_index()
100
- array = first_vertices[['X', 'Y', 'Z']].values
101
- component_lith_arrays[lith] = array
102
-
103
- return component_lith_arrays
104
-
105
- def _merge_vertex_data_arrays_to_dataframe(self):
106
- ds = self.combined_trajectory.data.data
107
- # Convert vertex attributes to a DataFrame for easier manipulation
108
- vertex_attrs_df = ds['vertex_attrs'].to_dataframe().reset_index()
109
- vertex_attrs_df = vertex_attrs_df.pivot(index='points', columns='vertex_attr', values='vertex_attrs').reset_index()
110
- # Convert vertex coordinates to a DataFrame
111
- vertex_df = ds['vertex'].to_dataframe().reset_index()
112
- vertex_df = vertex_df.pivot(index='points', columns='XYZ', values='vertex').reset_index()
113
- # Merge the attributes with the vertex coordinates
114
- merged_df = pd.merge(vertex_df, vertex_attrs_df, on='points')
115
- # Create a dictionary to hold the numpy arrays for each component lith
116
- return merged_df
1
+ import numpy as np
2
+ import pandas as pd
3
+ from dataclasses import dataclass
4
+ from typing import Hashable, Literal
5
+
6
+ from ._combine_trajectories import create_combined_trajectory, MergeOptions
7
+ from .collars import Collars
8
+ from .survey import Survey
9
+ from ...structs import LineSet
10
+
11
+
12
+ @dataclass
13
+ class BoreholeSet:
14
+ """
15
+ This module provides a class, `BoreholeSet`, that represents a collection of boreholes. It contains methods for accessing coordinate data for each lithology in the boreholes.
16
+
17
+ Notes:
18
+ - Collars is defined as 1 UnstructuredData
19
+ - Combined trajectory is defined as 1 UnstructuredData
20
+
21
+ Classes:
22
+ - `BoreholeSet`: Represents a collection of boreholes.
23
+
24
+ Methods:
25
+ - `__init__`: Initializes a new `BoreholeSet` object with the specified input parameters.
26
+ - `get_top_coords_for_each_lith`: Returns a dictionary of top coordinates for each lithology in the boreholes.
27
+ - `get_bottom_coords_for_each_lith`: Returns a dictionary of bottom coordinates for each lithology in the boreholes.
28
+
29
+ Attributes:
30
+ - `collars`: A `Collars` object representing the collar information for the boreholes.
31
+ - `survey`: A `Survey` object representing the survey information for the boreholes.
32
+ - `combined_trajectory`: A `LineSet` object representing the combined trajectory of the boreholes.
33
+
34
+ Usage:
35
+ ```
36
+ borehole_set = BoreholeSet(collars, survey, merge_option)
37
+ top_coords = borehole_set.get_top_coords_for_each_lith()
38
+ bottom_coords = borehole_set.get_bottom_coords_for_each_lith()
39
+ ```
40
+
41
+ Note: The example usage code provided above is for demonstration purposes only. Please replace `collars`, `survey`, and `merge_option` with the actual input parameters when using the `BoreholeSet` class.
42
+
43
+ """
44
+ __slots__ = ['collars', 'survey', 'combined_trajectory']
45
+ collars: Collars
46
+ survey: Survey
47
+ combined_trajectory: LineSet
48
+
49
+ def __init__(self, collars: Collars, survey: Survey, merge_option: MergeOptions, slice_=slice(None)):
50
+
51
+ new_collars = self._remap_collars_with_survey(collars, survey)
52
+
53
+ self.collars = new_collars
54
+ self.survey = survey
55
+ self.combined_trajectory: LineSet = create_combined_trajectory(collars, survey, merge_option, slice_)
56
+
57
+ @staticmethod
58
+ def _remap_collars_with_survey(collars, survey):
59
+ import pandas as pd
60
+ # Create a DataFrame from your first list
61
+ df1 = pd.DataFrame({'name': collars.ids, 'x': collars.data.vertex[:, 0], 'y': collars.data.vertex[:, 1], 'z': collars.data.vertex[:, 2]})
62
+ df1 = df1.set_index('name')
63
+ # Reindex to match the second list of names
64
+ df_reindexed = df1.reindex(survey.well_id_mapper.keys())
65
+ new_collars = Collars.from_df(df_reindexed)
66
+ return new_collars
67
+
68
+ def to_binary(self, path: str) -> bool:
69
+ # I need to implement the survey to and then name the files accordingly
70
+ bytearray_le_collars: bytes = self.collars.data.to_binary()
71
+ bytearray_le_trajectory: bytes = self.combined_trajectory.data.to_binary()
72
+
73
+ new_file = open(f"{path}_collars.le", "wb")
74
+ new_file.write(bytearray_le_collars)
75
+
76
+ new_file = open(f"{path}_trajectory.le", "wb")
77
+ new_file.write(bytearray_le_trajectory)
78
+ return True
79
+
80
+ def get_top_coords_for_each_lith(self) -> dict[Hashable, np.ndarray]:
81
+ merged_df = self._merge_vertex_data_arrays_to_dataframe()
82
+ component_lith_arrays = {}
83
+ for lith, group in merged_df.groupby('lith_ids'):
84
+ lith = int(lith)
85
+ first_vertices = group.groupby('well_id').first().reset_index()
86
+ array = first_vertices[['X', 'Y', 'Z']].values
87
+ component_lith_arrays[lith] = array
88
+
89
+ return component_lith_arrays
90
+
91
+ def get_bottom_coords_for_each_lith(self, group_by: Literal['component lith', 'lith_ids'] = 'lith_ids') -> dict[Hashable, np.ndarray]:
92
+ """
93
+ Retrieves the bottom coordinates for each lithological component or lith ID from
94
+ the merged vertex data arrays.
95
+
96
+ This function groups the merged data by either 'component lith' or 'lith_ids',
97
+ then extracts the coordinates of the bottommost vertices for each well. It
98
+ returns a dictionary where keys are either lithological component identifiers
99
+ or lith IDs, and values are arrays of 3D coordinates representing the bottom
100
+ vertices.
101
+
102
+ Args:
103
+ group_by (Literal['component lith', 'lith_ids']): Specifies the grouping
104
+ column to use for lithological components. Acceptable values are either
105
+ 'component lith' or 'lith_ids'. Defaults to 'lith_ids'.
106
+
107
+ Returns:
108
+ dict[Hashable, np.ndarray]: A dictionary mapping the lithological component
109
+ or lith ID to an array of 3D coordinates ([X, Y, Z]) corresponding to the
110
+ bottom vertices for each well.
111
+
112
+ Raises:
113
+ ValueError: If no groups are found from the specified `group_by` column.
114
+ """
115
+ merged_df = self._merge_vertex_data_arrays_to_dataframe()
116
+ component_lith_arrays = {}
117
+ group = merged_df.groupby(group_by)
118
+
119
+ if group.ngroups == 0:
120
+ raise ValueError("No components found")
121
+ for lith, group in group:
122
+ lith = int(lith)
123
+ first_vertices = group.groupby('well_id').last().reset_index()
124
+ array = first_vertices[['X', 'Y', 'Z']].values
125
+ component_lith_arrays[lith] = array
126
+
127
+ return component_lith_arrays
128
+
129
+ def _merge_vertex_data_arrays_to_dataframe(self):
130
+ ds = self.combined_trajectory.data.data
131
+ # Convert vertex attributes to a DataFrame for easier manipulation
132
+ vertex_attrs_df = ds['vertex_attrs'].to_dataframe().reset_index()
133
+ vertex_attrs_df = vertex_attrs_df.pivot(index='points', columns='vertex_attr', values='vertex_attrs').reset_index()
134
+ # Convert vertex coordinates to a DataFrame
135
+ vertex_df = ds['vertex'].to_dataframe().reset_index()
136
+ vertex_df = vertex_df.pivot(index='points', columns='XYZ', values='vertex').reset_index()
137
+ # Merge the attributes with the vertex coordinates
138
+ merged_df = pd.merge(vertex_df, vertex_attrs_df, on='points')
139
+ # Create a dictionary to hold the numpy arrays for each component lith
140
+ return merged_df
@@ -1,27 +1,27 @@
1
- import pandas as pd
2
- from dataclasses import dataclass
3
-
4
- from ...structs.base_structures import UnstructuredData
5
- from ...structs.base_structures.base_structures_enum import SpecialCellCase
6
- from ...structs.unstructured_elements import PointSet
7
-
8
-
9
- @dataclass
10
- class Collars:
11
- ids: list[str]
12
- collar_loc: PointSet
13
-
14
- @classmethod
15
- def from_df(cls, df: pd.DataFrame):
16
- unstruc: UnstructuredData = UnstructuredData.from_array(
17
- vertex=df[["x", "y", "z"]].values,
18
- cells=SpecialCellCase.POINTS
19
- )
20
- return cls(
21
- ids=df.index.to_list(),
22
- collar_loc=PointSet(data=unstruc)
23
- )
24
-
25
- @property
26
- def data(self):
1
+ import pandas as pd
2
+ from dataclasses import dataclass
3
+
4
+ from ...structs.base_structures import UnstructuredData
5
+ from ...structs.base_structures.base_structures_enum import SpecialCellCase
6
+ from ...structs.unstructured_elements import PointSet
7
+
8
+
9
+ @dataclass
10
+ class Collars:
11
+ ids: list[str]
12
+ collar_loc: PointSet
13
+
14
+ @classmethod
15
+ def from_df(cls, df: pd.DataFrame):
16
+ unstruc: UnstructuredData = UnstructuredData.from_array(
17
+ vertex=df[["x", "y", "z"]].values,
18
+ cells=SpecialCellCase.POINTS
19
+ )
20
+ return cls(
21
+ ids=df.index.to_list(),
22
+ collar_loc=PointSet(data=unstruc)
23
+ )
24
+
25
+ @property
26
+ def data(self):
27
27
  return self.collar_loc.data