subsurface-terra 2025.1.0rc15__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.
- subsurface/__init__.py +31 -31
- subsurface/_version.py +34 -21
- subsurface/api/__init__.py +13 -13
- subsurface/api/interfaces/__init__.py +3 -3
- subsurface/api/interfaces/stream.py +136 -136
- subsurface/api/reader/read_wells.py +78 -78
- subsurface/core/geological_formats/boreholes/_combine_trajectories.py +117 -117
- subsurface/core/geological_formats/boreholes/_map_attrs_to_survey.py +236 -234
- subsurface/core/geological_formats/boreholes/_survey_to_unstruct.py +163 -163
- subsurface/core/geological_formats/boreholes/boreholes.py +140 -140
- subsurface/core/geological_formats/boreholes/collars.py +26 -26
- subsurface/core/geological_formats/boreholes/survey.py +86 -86
- subsurface/core/geological_formats/fault.py +47 -47
- subsurface/core/reader_helpers/reader_unstruct.py +11 -11
- subsurface/core/reader_helpers/readers_data.py +130 -130
- subsurface/core/reader_helpers/readers_wells.py +13 -13
- subsurface/core/structs/__init__.py +3 -3
- subsurface/core/structs/base_structures/__init__.py +2 -2
- subsurface/core/structs/base_structures/_liquid_earth_mesh.py +121 -121
- subsurface/core/structs/base_structures/_unstructured_data_constructor.py +70 -70
- subsurface/core/structs/base_structures/base_structures_enum.py +6 -6
- subsurface/core/structs/base_structures/structured_data.py +282 -282
- subsurface/core/structs/base_structures/unstructured_data.py +319 -319
- subsurface/core/structs/structured_elements/octree_mesh.py +10 -10
- subsurface/core/structs/structured_elements/structured_grid.py +59 -59
- subsurface/core/structs/structured_elements/structured_mesh.py +9 -9
- subsurface/core/structs/unstructured_elements/__init__.py +3 -3
- subsurface/core/structs/unstructured_elements/line_set.py +72 -72
- subsurface/core/structs/unstructured_elements/point_set.py +43 -43
- subsurface/core/structs/unstructured_elements/tetrahedron_mesh.py +35 -35
- subsurface/core/structs/unstructured_elements/triangular_surface.py +62 -62
- subsurface/core/utils/utils_core.py +38 -38
- subsurface/modules/reader/__init__.py +13 -13
- subsurface/modules/reader/faults/faults.py +80 -80
- subsurface/modules/reader/from_binary.py +46 -46
- subsurface/modules/reader/mesh/_GOCAD_mesh.py +82 -82
- subsurface/modules/reader/mesh/_trimesh_reader.py +447 -447
- subsurface/modules/reader/mesh/csv_mesh_reader.py +53 -53
- subsurface/modules/reader/mesh/dxf_reader.py +177 -177
- subsurface/modules/reader/mesh/glb_reader.py +30 -30
- subsurface/modules/reader/mesh/mx_reader.py +232 -232
- subsurface/modules/reader/mesh/obj_reader.py +53 -53
- subsurface/modules/reader/mesh/omf_mesh_reader.py +43 -43
- subsurface/modules/reader/mesh/surface_reader.py +56 -56
- subsurface/modules/reader/mesh/surfaces_api.py +41 -41
- subsurface/modules/reader/profiles/__init__.py +3 -3
- subsurface/modules/reader/profiles/profiles_core.py +197 -197
- subsurface/modules/reader/read_netcdf.py +38 -38
- subsurface/modules/reader/topography/__init__.py +7 -7
- subsurface/modules/reader/topography/topo_core.py +100 -100
- subsurface/modules/reader/volume/read_grav3d.py +478 -428
- subsurface/modules/reader/volume/read_volume.py +327 -230
- subsurface/modules/reader/volume/segy_reader.py +105 -105
- subsurface/modules/reader/volume/seismic.py +173 -173
- subsurface/modules/reader/volume/volume_utils.py +43 -43
- subsurface/modules/reader/wells/DEP/__init__.py +43 -43
- subsurface/modules/reader/wells/DEP/_well_files_reader.py +167 -167
- subsurface/modules/reader/wells/DEP/_wells_api.py +61 -61
- subsurface/modules/reader/wells/DEP/_welly_reader.py +180 -180
- subsurface/modules/reader/wells/DEP/pandas_to_welly.py +212 -212
- subsurface/modules/reader/wells/_read_to_df.py +57 -57
- subsurface/modules/reader/wells/read_borehole_interface.py +148 -148
- subsurface/modules/reader/wells/wells_utils.py +68 -68
- subsurface/modules/tools/mocking_aux.py +104 -104
- subsurface/modules/visualization/__init__.py +2 -2
- subsurface/modules/visualization/to_pyvista.py +320 -320
- subsurface/modules/writer/to_binary.py +12 -12
- subsurface/modules/writer/to_rex/common.py +78 -78
- subsurface/modules/writer/to_rex/data_struct.py +74 -74
- subsurface/modules/writer/to_rex/gempy_to_rexfile.py +791 -791
- subsurface/modules/writer/to_rex/material_encoder.py +44 -44
- subsurface/modules/writer/to_rex/mesh_encoder.py +152 -152
- subsurface/modules/writer/to_rex/to_rex.py +115 -115
- subsurface/modules/writer/to_rex/utils.py +15 -15
- subsurface/optional_requirements.py +116 -116
- {subsurface_terra-2025.1.0rc15.dist-info → subsurface_terra-2025.1.0rc16.dist-info}/METADATA +194 -194
- subsurface_terra-2025.1.0rc16.dist-info/RECORD +98 -0
- {subsurface_terra-2025.1.0rc15.dist-info → subsurface_terra-2025.1.0rc16.dist-info}/WHEEL +1 -1
- {subsurface_terra-2025.1.0rc15.dist-info → subsurface_terra-2025.1.0rc16.dist-info}/licenses/LICENSE +203 -203
- subsurface_terra-2025.1.0rc15.dist-info/RECORD +0 -98
- {subsurface_terra-2025.1.0rc15.dist-info → subsurface_terra-2025.1.0rc16.dist-info}/top_level.txt +0 -0
|
@@ -1,59 +1,59 @@
|
|
|
1
|
-
import numpy as np
|
|
2
|
-
from ..base_structures import StructuredData
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
class StructuredGrid:
|
|
6
|
-
# TODO check structured_data has three coordinates
|
|
7
|
-
"""Container for curvilinear mesh grids.
|
|
8
|
-
|
|
9
|
-
This is analogous to PyVista's StructuredGrid class or discretize's
|
|
10
|
-
CurviMesh class.
|
|
11
|
-
|
|
12
|
-
"""
|
|
13
|
-
|
|
14
|
-
def __init__(self, structured_data: StructuredData):
|
|
15
|
-
self.ds = structured_data
|
|
16
|
-
|
|
17
|
-
@property
|
|
18
|
-
def cartesian_dimensions(self):
|
|
19
|
-
return len(self.cartesian_coords_names)
|
|
20
|
-
|
|
21
|
-
@property
|
|
22
|
-
def cartesian_coords_names(self):
|
|
23
|
-
coord_names = np.array(['X', 'Y', 'Z', 'x', 'y', 'z'])
|
|
24
|
-
return coord_names[np.isin(coord_names, self.ds.data.dims)]
|
|
25
|
-
|
|
26
|
-
@property
|
|
27
|
-
def coord(self):
|
|
28
|
-
return self.ds.data.coords
|
|
29
|
-
|
|
30
|
-
@property
|
|
31
|
-
def meshgrid_3d(self):
|
|
32
|
-
cart_coord = [self.coord[i] for i in self.cartesian_coords_names]
|
|
33
|
-
grid_3d = np.meshgrid(*cart_coord, indexing='ij')
|
|
34
|
-
return grid_3d
|
|
35
|
-
|
|
36
|
-
@property
|
|
37
|
-
def active_attributes(self) -> np.ndarray:
|
|
38
|
-
return self.ds.data[self.ds.active_data_array_name].values
|
|
39
|
-
|
|
40
|
-
def meshgrid_2d(self, attribute_name_coord_name: str = None) -> list:
|
|
41
|
-
"""
|
|
42
|
-
|
|
43
|
-
Args:
|
|
44
|
-
attribute_name_coord_name(str): Name of the xarray.Dataset coord that
|
|
45
|
-
will be used for the z direction. This must be 2d
|
|
46
|
-
|
|
47
|
-
Returns:
|
|
48
|
-
|
|
49
|
-
"""
|
|
50
|
-
grid_2d_: tuple = np.meshgrid(self.coord['x'], self.coord['y'])
|
|
51
|
-
grid_2d = list(grid_2d_)
|
|
52
|
-
if attribute_name_coord_name is not None:
|
|
53
|
-
z_coord = self.ds.data[attribute_name_coord_name].values.T
|
|
54
|
-
if z_coord.ndim != 2:
|
|
55
|
-
raise AttributeError('The attribute must be a 2D array')
|
|
56
|
-
|
|
57
|
-
grid_2d.append(z_coord)
|
|
58
|
-
|
|
59
|
-
return grid_2d
|
|
1
|
+
import numpy as np
|
|
2
|
+
from ..base_structures import StructuredData
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class StructuredGrid:
|
|
6
|
+
# TODO check structured_data has three coordinates
|
|
7
|
+
"""Container for curvilinear mesh grids.
|
|
8
|
+
|
|
9
|
+
This is analogous to PyVista's StructuredGrid class or discretize's
|
|
10
|
+
CurviMesh class.
|
|
11
|
+
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
def __init__(self, structured_data: StructuredData):
|
|
15
|
+
self.ds = structured_data
|
|
16
|
+
|
|
17
|
+
@property
|
|
18
|
+
def cartesian_dimensions(self):
|
|
19
|
+
return len(self.cartesian_coords_names)
|
|
20
|
+
|
|
21
|
+
@property
|
|
22
|
+
def cartesian_coords_names(self):
|
|
23
|
+
coord_names = np.array(['X', 'Y', 'Z', 'x', 'y', 'z'])
|
|
24
|
+
return coord_names[np.isin(coord_names, self.ds.data.dims)]
|
|
25
|
+
|
|
26
|
+
@property
|
|
27
|
+
def coord(self):
|
|
28
|
+
return self.ds.data.coords
|
|
29
|
+
|
|
30
|
+
@property
|
|
31
|
+
def meshgrid_3d(self):
|
|
32
|
+
cart_coord = [self.coord[i] for i in self.cartesian_coords_names]
|
|
33
|
+
grid_3d = np.meshgrid(*cart_coord, indexing='ij')
|
|
34
|
+
return grid_3d
|
|
35
|
+
|
|
36
|
+
@property
|
|
37
|
+
def active_attributes(self) -> np.ndarray:
|
|
38
|
+
return self.ds.data[self.ds.active_data_array_name].values
|
|
39
|
+
|
|
40
|
+
def meshgrid_2d(self, attribute_name_coord_name: str = None) -> list:
|
|
41
|
+
"""
|
|
42
|
+
|
|
43
|
+
Args:
|
|
44
|
+
attribute_name_coord_name(str): Name of the xarray.Dataset coord that
|
|
45
|
+
will be used for the z direction. This must be 2d
|
|
46
|
+
|
|
47
|
+
Returns:
|
|
48
|
+
|
|
49
|
+
"""
|
|
50
|
+
grid_2d_: tuple = np.meshgrid(self.coord['x'], self.coord['y'])
|
|
51
|
+
grid_2d = list(grid_2d_)
|
|
52
|
+
if attribute_name_coord_name is not None:
|
|
53
|
+
z_coord = self.ds.data[attribute_name_coord_name].values.T
|
|
54
|
+
if z_coord.ndim != 2:
|
|
55
|
+
raise AttributeError('The attribute must be a 2D array')
|
|
56
|
+
|
|
57
|
+
grid_2d.append(z_coord)
|
|
58
|
+
|
|
59
|
+
return grid_2d
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
from subsurface import StructuredData
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
class StructuredSurface:
|
|
5
|
-
def __init__(self, structured_data: StructuredData):
|
|
6
|
-
# TODO check structured_data has two coordinates
|
|
7
|
-
self.ds = structured_data
|
|
8
|
-
|
|
9
|
-
# Add pyvista methods of gridded data
|
|
1
|
+
from subsurface import StructuredData
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class StructuredSurface:
|
|
5
|
+
def __init__(self, structured_data: StructuredData):
|
|
6
|
+
# TODO check structured_data has two coordinates
|
|
7
|
+
self.ds = structured_data
|
|
8
|
+
|
|
9
|
+
# Add pyvista methods of gridded data
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
from .triangular_surface import TriSurf
|
|
2
|
-
from .line_set import LineSet
|
|
3
|
-
from .point_set import PointSet
|
|
1
|
+
from .triangular_surface import TriSurf
|
|
2
|
+
from .line_set import LineSet
|
|
3
|
+
from .point_set import PointSet
|
|
4
4
|
from .tetrahedron_mesh import TetraMesh
|
|
@@ -1,72 +1,72 @@
|
|
|
1
|
-
import numpy as np
|
|
2
|
-
import pandas as pd
|
|
3
|
-
|
|
4
|
-
from ..base_structures import UnstructuredData
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
class LineSet:
|
|
8
|
-
"""PointSet with line cells.
|
|
9
|
-
|
|
10
|
-
This dataset defines cell connectivity between points to create
|
|
11
|
-
line segments.
|
|
12
|
-
|
|
13
|
-
Args:
|
|
14
|
-
data (UnstructuredData): Base object for unstructured data.
|
|
15
|
-
|
|
16
|
-
data.cells represent the indices of the end points for each
|
|
17
|
-
line segment in the mesh. Each column corresponds to a line
|
|
18
|
-
segment. If not specified, the vertices are connected in order,
|
|
19
|
-
equivalent to ``segments=[[0, 1], [1, 2], [2, 3], ...]``
|
|
20
|
-
|
|
21
|
-
radius (float): Thickness of the line set
|
|
22
|
-
"""
|
|
23
|
-
|
|
24
|
-
def __init__(self, data: UnstructuredData, radius: float = 1):
|
|
25
|
-
|
|
26
|
-
self.data: UnstructuredData = data
|
|
27
|
-
self.radius = radius
|
|
28
|
-
|
|
29
|
-
if data.cells is None or data.cells.shape[1] < 2:
|
|
30
|
-
self.generate_default_cells()
|
|
31
|
-
|
|
32
|
-
elif data.cells.shape[1] != 2:
|
|
33
|
-
raise AttributeError('data.cells must be of the format'
|
|
34
|
-
'NDArray[(Any, 2), IntX]')
|
|
35
|
-
|
|
36
|
-
# TODO: these must all be integer dtypes!
|
|
37
|
-
|
|
38
|
-
def get_first_index_per_well(self, attr_hole_id: str):
|
|
39
|
-
""" Method to get the first index of each well in the LineSet
|
|
40
|
-
|
|
41
|
-
Returns:
|
|
42
|
-
np.ndarray[(Any,), IntX]
|
|
43
|
-
|
|
44
|
-
"""
|
|
45
|
-
import xarray as xr
|
|
46
|
-
dataset: xr.Dataset = self.data.data
|
|
47
|
-
dataframe: pd.DataFrame = self.data.attributes
|
|
48
|
-
array = dataframe[attr_hole_id].values
|
|
49
|
-
|
|
50
|
-
first_index = np.where(array[:-1] != array[1:])[0]
|
|
51
|
-
return first_index
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
def generate_default_cells(self):
|
|
55
|
-
""" Method to generate cells based on the order of the vertex. This
|
|
56
|
-
only works if the LineSet only represents one single line
|
|
57
|
-
|
|
58
|
-
Returns:
|
|
59
|
-
np.ndarray[(Any, 2), IntX]
|
|
60
|
-
|
|
61
|
-
"""
|
|
62
|
-
a = np.arange(0, self.data.n_points - 1, dtype=np.int_)
|
|
63
|
-
b = np.arange(1, self.data.n_points, dtype=np.int_)
|
|
64
|
-
return np.vstack([a, b]).T
|
|
65
|
-
|
|
66
|
-
@property
|
|
67
|
-
def segments(self):
|
|
68
|
-
return self.data.cells
|
|
69
|
-
|
|
70
|
-
@property
|
|
71
|
-
def n_segments(self):
|
|
72
|
-
return self.segments.shape[0]
|
|
1
|
+
import numpy as np
|
|
2
|
+
import pandas as pd
|
|
3
|
+
|
|
4
|
+
from ..base_structures import UnstructuredData
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class LineSet:
|
|
8
|
+
"""PointSet with line cells.
|
|
9
|
+
|
|
10
|
+
This dataset defines cell connectivity between points to create
|
|
11
|
+
line segments.
|
|
12
|
+
|
|
13
|
+
Args:
|
|
14
|
+
data (UnstructuredData): Base object for unstructured data.
|
|
15
|
+
|
|
16
|
+
data.cells represent the indices of the end points for each
|
|
17
|
+
line segment in the mesh. Each column corresponds to a line
|
|
18
|
+
segment. If not specified, the vertices are connected in order,
|
|
19
|
+
equivalent to ``segments=[[0, 1], [1, 2], [2, 3], ...]``
|
|
20
|
+
|
|
21
|
+
radius (float): Thickness of the line set
|
|
22
|
+
"""
|
|
23
|
+
|
|
24
|
+
def __init__(self, data: UnstructuredData, radius: float = 1):
|
|
25
|
+
|
|
26
|
+
self.data: UnstructuredData = data
|
|
27
|
+
self.radius = radius
|
|
28
|
+
|
|
29
|
+
if data.cells is None or data.cells.shape[1] < 2:
|
|
30
|
+
self.generate_default_cells()
|
|
31
|
+
|
|
32
|
+
elif data.cells.shape[1] != 2:
|
|
33
|
+
raise AttributeError('data.cells must be of the format'
|
|
34
|
+
'NDArray[(Any, 2), IntX]')
|
|
35
|
+
|
|
36
|
+
# TODO: these must all be integer dtypes!
|
|
37
|
+
|
|
38
|
+
def get_first_index_per_well(self, attr_hole_id: str):
|
|
39
|
+
""" Method to get the first index of each well in the LineSet
|
|
40
|
+
|
|
41
|
+
Returns:
|
|
42
|
+
np.ndarray[(Any,), IntX]
|
|
43
|
+
|
|
44
|
+
"""
|
|
45
|
+
import xarray as xr
|
|
46
|
+
dataset: xr.Dataset = self.data.data
|
|
47
|
+
dataframe: pd.DataFrame = self.data.attributes
|
|
48
|
+
array = dataframe[attr_hole_id].values
|
|
49
|
+
|
|
50
|
+
first_index = np.where(array[:-1] != array[1:])[0]
|
|
51
|
+
return first_index
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
def generate_default_cells(self):
|
|
55
|
+
""" Method to generate cells based on the order of the vertex. This
|
|
56
|
+
only works if the LineSet only represents one single line
|
|
57
|
+
|
|
58
|
+
Returns:
|
|
59
|
+
np.ndarray[(Any, 2), IntX]
|
|
60
|
+
|
|
61
|
+
"""
|
|
62
|
+
a = np.arange(0, self.data.n_points - 1, dtype=np.int_)
|
|
63
|
+
b = np.arange(1, self.data.n_points, dtype=np.int_)
|
|
64
|
+
return np.vstack([a, b]).T
|
|
65
|
+
|
|
66
|
+
@property
|
|
67
|
+
def segments(self):
|
|
68
|
+
return self.data.cells
|
|
69
|
+
|
|
70
|
+
@property
|
|
71
|
+
def n_segments(self):
|
|
72
|
+
return self.segments.shape[0]
|
|
@@ -1,43 +1,43 @@
|
|
|
1
|
-
from dataclasses import dataclass
|
|
2
|
-
|
|
3
|
-
from ..base_structures import UnstructuredData
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
@dataclass
|
|
7
|
-
class PointSet:
|
|
8
|
-
"""Class for pointset based data structures.
|
|
9
|
-
|
|
10
|
-
This class uses UnstructuredData.vertex as cloud of points and the
|
|
11
|
-
associated attributes. UnstructuredData.cells are not used.
|
|
12
|
-
|
|
13
|
-
Args:
|
|
14
|
-
data (UnstructuredData): Base object for unstructured data.
|
|
15
|
-
|
|
16
|
-
"""
|
|
17
|
-
data: UnstructuredData
|
|
18
|
-
|
|
19
|
-
def __init__(self, data: UnstructuredData):
|
|
20
|
-
if data.cells.shape[1] > 1:
|
|
21
|
-
raise AttributeError('data.cells must be of the format'
|
|
22
|
-
'NDArray[(Any, 0), IntX] or NDArray[(Any, 1), IntX]')
|
|
23
|
-
|
|
24
|
-
self.data = data
|
|
25
|
-
|
|
26
|
-
@property
|
|
27
|
-
def points(self) -> "np.ndarray":
|
|
28
|
-
"""Fetch the points/vertices dataframe."""
|
|
29
|
-
return self.data.vertex
|
|
30
|
-
|
|
31
|
-
@property
|
|
32
|
-
def n_points(self):
|
|
33
|
-
return self.data.vertex.shape[0]
|
|
34
|
-
|
|
35
|
-
@property
|
|
36
|
-
def point_data(self):
|
|
37
|
-
"""Fetch the scalar data associated with the vertices."""
|
|
38
|
-
return self.data.attributes
|
|
39
|
-
|
|
40
|
-
@property
|
|
41
|
-
def point_data_dict(self):
|
|
42
|
-
"""Fetch the point data as a dictionary of numpy arrays."""
|
|
43
|
-
return self.data.attributes_to_dict
|
|
1
|
+
from dataclasses import dataclass
|
|
2
|
+
|
|
3
|
+
from ..base_structures import UnstructuredData
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
@dataclass
|
|
7
|
+
class PointSet:
|
|
8
|
+
"""Class for pointset based data structures.
|
|
9
|
+
|
|
10
|
+
This class uses UnstructuredData.vertex as cloud of points and the
|
|
11
|
+
associated attributes. UnstructuredData.cells are not used.
|
|
12
|
+
|
|
13
|
+
Args:
|
|
14
|
+
data (UnstructuredData): Base object for unstructured data.
|
|
15
|
+
|
|
16
|
+
"""
|
|
17
|
+
data: UnstructuredData
|
|
18
|
+
|
|
19
|
+
def __init__(self, data: UnstructuredData):
|
|
20
|
+
if data.cells.shape[1] > 1:
|
|
21
|
+
raise AttributeError('data.cells must be of the format'
|
|
22
|
+
'NDArray[(Any, 0), IntX] or NDArray[(Any, 1), IntX]')
|
|
23
|
+
|
|
24
|
+
self.data = data
|
|
25
|
+
|
|
26
|
+
@property
|
|
27
|
+
def points(self) -> "np.ndarray":
|
|
28
|
+
"""Fetch the points/vertices dataframe."""
|
|
29
|
+
return self.data.vertex
|
|
30
|
+
|
|
31
|
+
@property
|
|
32
|
+
def n_points(self):
|
|
33
|
+
return self.data.vertex.shape[0]
|
|
34
|
+
|
|
35
|
+
@property
|
|
36
|
+
def point_data(self):
|
|
37
|
+
"""Fetch the scalar data associated with the vertices."""
|
|
38
|
+
return self.data.attributes
|
|
39
|
+
|
|
40
|
+
@property
|
|
41
|
+
def point_data_dict(self):
|
|
42
|
+
"""Fetch the point data as a dictionary of numpy arrays."""
|
|
43
|
+
return self.data.attributes_to_dict
|
|
@@ -1,35 +1,35 @@
|
|
|
1
|
-
from ..base_structures import UnstructuredData
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
class TetraMesh:
|
|
5
|
-
"""PointSet with tetrahedron cells.
|
|
6
|
-
|
|
7
|
-
This dataset defines cell connectivity between points to create
|
|
8
|
-
tetrahedrons. This is volumetric.
|
|
9
|
-
|
|
10
|
-
Args:
|
|
11
|
-
|
|
12
|
-
data (UnstructuredData): Base object for unstructured data.
|
|
13
|
-
|
|
14
|
-
data.cells represent the indices of the points for each
|
|
15
|
-
tetrahedron in the mesh. Each column corresponds to a tetrahedron.
|
|
16
|
-
Every tetrahedron is defined by the four points; where the first
|
|
17
|
-
three (0,1,2) are the base of the tetrahedron which, using the
|
|
18
|
-
right hand rule, forms a triangle whose normal points in the
|
|
19
|
-
direction of the fourth point.
|
|
20
|
-
|
|
21
|
-
"""
|
|
22
|
-
|
|
23
|
-
def __init__(self, data: UnstructuredData):
|
|
24
|
-
if data.cells.shape[1] != 4:
|
|
25
|
-
raise AttributeError('data.cells must be of the format'
|
|
26
|
-
'NDArray[(Any, 4), IntX]')
|
|
27
|
-
self.data = data
|
|
28
|
-
|
|
29
|
-
@property
|
|
30
|
-
def tetrahedrals(self):
|
|
31
|
-
return self.data.cells
|
|
32
|
-
|
|
33
|
-
@property
|
|
34
|
-
def n_tetrahedrals(self):
|
|
35
|
-
return self.tetrahedrals.shape[0]
|
|
1
|
+
from ..base_structures import UnstructuredData
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class TetraMesh:
|
|
5
|
+
"""PointSet with tetrahedron cells.
|
|
6
|
+
|
|
7
|
+
This dataset defines cell connectivity between points to create
|
|
8
|
+
tetrahedrons. This is volumetric.
|
|
9
|
+
|
|
10
|
+
Args:
|
|
11
|
+
|
|
12
|
+
data (UnstructuredData): Base object for unstructured data.
|
|
13
|
+
|
|
14
|
+
data.cells represent the indices of the points for each
|
|
15
|
+
tetrahedron in the mesh. Each column corresponds to a tetrahedron.
|
|
16
|
+
Every tetrahedron is defined by the four points; where the first
|
|
17
|
+
three (0,1,2) are the base of the tetrahedron which, using the
|
|
18
|
+
right hand rule, forms a triangle whose normal points in the
|
|
19
|
+
direction of the fourth point.
|
|
20
|
+
|
|
21
|
+
"""
|
|
22
|
+
|
|
23
|
+
def __init__(self, data: UnstructuredData):
|
|
24
|
+
if data.cells.shape[1] != 4:
|
|
25
|
+
raise AttributeError('data.cells must be of the format'
|
|
26
|
+
'NDArray[(Any, 4), IntX]')
|
|
27
|
+
self.data = data
|
|
28
|
+
|
|
29
|
+
@property
|
|
30
|
+
def tetrahedrals(self):
|
|
31
|
+
return self.data.cells
|
|
32
|
+
|
|
33
|
+
@property
|
|
34
|
+
def n_tetrahedrals(self):
|
|
35
|
+
return self.tetrahedrals.shape[0]
|
|
@@ -1,62 +1,62 @@
|
|
|
1
|
-
from ..base_structures import UnstructuredData, StructuredData
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
class TriSurf:
|
|
5
|
-
"""PointSet with triangle cells.
|
|
6
|
-
|
|
7
|
-
This dataset defines cell/element connectivity between points to create
|
|
8
|
-
triangulated surface.
|
|
9
|
-
|
|
10
|
-
Uses UnstructuredData.cells for the face connectivity.
|
|
11
|
-
|
|
12
|
-
Args:
|
|
13
|
-
mesh (UnstructuredData): Base object for unstructured data.
|
|
14
|
-
data.cells represent the point indices for each triangle
|
|
15
|
-
in the mesh. Each column corresponds to a triangle edge.
|
|
16
|
-
texture (StructuredData): 2D StructuredData with data to be mapped
|
|
17
|
-
on the mesh
|
|
18
|
-
|
|
19
|
-
Keyword Args:
|
|
20
|
-
texture_origin : tuple(float)
|
|
21
|
-
Length 3 iterable of floats defining the XYZ coordinates of the
|
|
22
|
-
BOTTOM LEFT CORNER of the plane
|
|
23
|
-
|
|
24
|
-
texture_point_u : tuple(float)
|
|
25
|
-
Length 3 iterable of floats defining the XYZ coordinates of the
|
|
26
|
-
BOTTOM RIGHT CORNER of the plane
|
|
27
|
-
|
|
28
|
-
texture_point_v : tuple(float)
|
|
29
|
-
Length 3 iterable of floats defining the XYZ coordinates of the
|
|
30
|
-
TOP LEFT CORNER of the plane
|
|
31
|
-
"""
|
|
32
|
-
|
|
33
|
-
def __init__(self,
|
|
34
|
-
mesh: UnstructuredData,
|
|
35
|
-
texture: StructuredData = None,
|
|
36
|
-
**kwargs
|
|
37
|
-
):
|
|
38
|
-
if mesh.cells.shape[1] != 3:
|
|
39
|
-
raise AttributeError('data.cells must be of the format'
|
|
40
|
-
'NDArray[(Any, 3), IntX]')
|
|
41
|
-
|
|
42
|
-
self.mesh: UnstructuredData = mesh
|
|
43
|
-
self.texture: StructuredData = texture
|
|
44
|
-
self.texture_origin = kwargs.get('texture_origin', None)
|
|
45
|
-
self.texture_point_u = kwargs.get('texture_point_u', None)
|
|
46
|
-
self.texture_point_v = kwargs.get('texture_point_v', None)
|
|
47
|
-
|
|
48
|
-
@property
|
|
49
|
-
def has_texture_data_without_uv(self):
|
|
50
|
-
return self.texture is not None and self.texture_origin is not None and self.texture_point_u is not None and self.texture_point_v is not None
|
|
51
|
-
|
|
52
|
-
@property
|
|
53
|
-
def has_texture_data_with_uv(self):
|
|
54
|
-
return 'u' in self.mesh.points_attributes and 'v' in self.mesh.points_attributes
|
|
55
|
-
|
|
56
|
-
@property
|
|
57
|
-
def triangles(self):
|
|
58
|
-
return self.mesh.cells
|
|
59
|
-
|
|
60
|
-
@property
|
|
61
|
-
def n_triangles(self):
|
|
62
|
-
return self.mesh.cells.shape[0]
|
|
1
|
+
from ..base_structures import UnstructuredData, StructuredData
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class TriSurf:
|
|
5
|
+
"""PointSet with triangle cells.
|
|
6
|
+
|
|
7
|
+
This dataset defines cell/element connectivity between points to create
|
|
8
|
+
triangulated surface.
|
|
9
|
+
|
|
10
|
+
Uses UnstructuredData.cells for the face connectivity.
|
|
11
|
+
|
|
12
|
+
Args:
|
|
13
|
+
mesh (UnstructuredData): Base object for unstructured data.
|
|
14
|
+
data.cells represent the point indices for each triangle
|
|
15
|
+
in the mesh. Each column corresponds to a triangle edge.
|
|
16
|
+
texture (StructuredData): 2D StructuredData with data to be mapped
|
|
17
|
+
on the mesh
|
|
18
|
+
|
|
19
|
+
Keyword Args:
|
|
20
|
+
texture_origin : tuple(float)
|
|
21
|
+
Length 3 iterable of floats defining the XYZ coordinates of the
|
|
22
|
+
BOTTOM LEFT CORNER of the plane
|
|
23
|
+
|
|
24
|
+
texture_point_u : tuple(float)
|
|
25
|
+
Length 3 iterable of floats defining the XYZ coordinates of the
|
|
26
|
+
BOTTOM RIGHT CORNER of the plane
|
|
27
|
+
|
|
28
|
+
texture_point_v : tuple(float)
|
|
29
|
+
Length 3 iterable of floats defining the XYZ coordinates of the
|
|
30
|
+
TOP LEFT CORNER of the plane
|
|
31
|
+
"""
|
|
32
|
+
|
|
33
|
+
def __init__(self,
|
|
34
|
+
mesh: UnstructuredData,
|
|
35
|
+
texture: StructuredData = None,
|
|
36
|
+
**kwargs
|
|
37
|
+
):
|
|
38
|
+
if mesh.cells.shape[1] != 3:
|
|
39
|
+
raise AttributeError('data.cells must be of the format'
|
|
40
|
+
'NDArray[(Any, 3), IntX]')
|
|
41
|
+
|
|
42
|
+
self.mesh: UnstructuredData = mesh
|
|
43
|
+
self.texture: StructuredData = texture
|
|
44
|
+
self.texture_origin = kwargs.get('texture_origin', None)
|
|
45
|
+
self.texture_point_u = kwargs.get('texture_point_u', None)
|
|
46
|
+
self.texture_point_v = kwargs.get('texture_point_v', None)
|
|
47
|
+
|
|
48
|
+
@property
|
|
49
|
+
def has_texture_data_without_uv(self):
|
|
50
|
+
return self.texture is not None and self.texture_origin is not None and self.texture_point_u is not None and self.texture_point_v is not None
|
|
51
|
+
|
|
52
|
+
@property
|
|
53
|
+
def has_texture_data_with_uv(self):
|
|
54
|
+
return 'u' in self.mesh.points_attributes and 'v' in self.mesh.points_attributes
|
|
55
|
+
|
|
56
|
+
@property
|
|
57
|
+
def triangles(self):
|
|
58
|
+
return self.mesh.cells
|
|
59
|
+
|
|
60
|
+
@property
|
|
61
|
+
def n_triangles(self):
|
|
62
|
+
return self.mesh.cells.shape[0]
|
|
@@ -1,38 +1,38 @@
|
|
|
1
|
-
from typing import Union
|
|
2
|
-
|
|
3
|
-
from pathlib import Path
|
|
4
|
-
|
|
5
|
-
from ..structs import StructuredData, UnstructuredData
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
def get_extension(path):
|
|
9
|
-
try:
|
|
10
|
-
p = Path(path)
|
|
11
|
-
return p.suffix
|
|
12
|
-
except TypeError:
|
|
13
|
-
return False
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
def replace_outliers(base_data: Union[StructuredData, UnstructuredData], dim=0, perc=0.99, replace_for=None):
|
|
17
|
-
"""@Edoardo Guerreiro https://stackoverflow.com/questions/60816533/
|
|
18
|
-
is-there-a-built-in-function-in-xarray-to-remove-outliers-from-a-dataset"""
|
|
19
|
-
|
|
20
|
-
data = base_data.data
|
|
21
|
-
# calculate percentile
|
|
22
|
-
threshold = data[dim].quantile(perc)
|
|
23
|
-
|
|
24
|
-
# find outliers and replace them with max among remaining values
|
|
25
|
-
mask = data[dim].where(abs(data[dim]) <= threshold)
|
|
26
|
-
if replace_for == 'max':
|
|
27
|
-
max_value = mask.max().values
|
|
28
|
-
# .where replace outliers with nan
|
|
29
|
-
mask = mask.fillna(max_value)
|
|
30
|
-
elif replace_for == 'min':
|
|
31
|
-
min_value = mask.min().values
|
|
32
|
-
# .where replace outliers with nan
|
|
33
|
-
mask = mask.fillna(min_value)
|
|
34
|
-
|
|
35
|
-
print(mask)
|
|
36
|
-
data[dim] = mask
|
|
37
|
-
|
|
38
|
-
return data
|
|
1
|
+
from typing import Union
|
|
2
|
+
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
|
|
5
|
+
from ..structs import StructuredData, UnstructuredData
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def get_extension(path):
|
|
9
|
+
try:
|
|
10
|
+
p = Path(path)
|
|
11
|
+
return p.suffix
|
|
12
|
+
except TypeError:
|
|
13
|
+
return False
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def replace_outliers(base_data: Union[StructuredData, UnstructuredData], dim=0, perc=0.99, replace_for=None):
|
|
17
|
+
"""@Edoardo Guerreiro https://stackoverflow.com/questions/60816533/
|
|
18
|
+
is-there-a-built-in-function-in-xarray-to-remove-outliers-from-a-dataset"""
|
|
19
|
+
|
|
20
|
+
data = base_data.data
|
|
21
|
+
# calculate percentile
|
|
22
|
+
threshold = data[dim].quantile(perc)
|
|
23
|
+
|
|
24
|
+
# find outliers and replace them with max among remaining values
|
|
25
|
+
mask = data[dim].where(abs(data[dim]) <= threshold)
|
|
26
|
+
if replace_for == 'max':
|
|
27
|
+
max_value = mask.max().values
|
|
28
|
+
# .where replace outliers with nan
|
|
29
|
+
mask = mask.fillna(max_value)
|
|
30
|
+
elif replace_for == 'min':
|
|
31
|
+
min_value = mask.min().values
|
|
32
|
+
# .where replace outliers with nan
|
|
33
|
+
mask = mask.fillna(min_value)
|
|
34
|
+
|
|
35
|
+
print(mask)
|
|
36
|
+
data[dim] = mask
|
|
37
|
+
|
|
38
|
+
return data
|