subsurface-terra 2025.1.0rc11__tar.gz → 2025.1.0rc13__tar.gz
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_terra-2025.1.0rc11 → subsurface_terra-2025.1.0rc13}/.teamcity/Subsurface/buildTypes/Subsurface_Testing.xml +7 -3
- {subsurface_terra-2025.1.0rc11/subsurface_terra.egg-info → subsurface_terra-2025.1.0rc13}/PKG-INFO +1 -1
- {subsurface_terra-2025.1.0rc11 → subsurface_terra-2025.1.0rc13}/subsurface/_version.py +2 -2
- {subsurface_terra-2025.1.0rc11 → subsurface_terra-2025.1.0rc13}/subsurface/api/__init__.py +2 -1
- {subsurface_terra-2025.1.0rc11 → subsurface_terra-2025.1.0rc13}/subsurface/api/interfaces/stream.py +7 -1
- {subsurface_terra-2025.1.0rc11 → subsurface_terra-2025.1.0rc13}/subsurface/core/structs/base_structures/structured_data.py +19 -2
- {subsurface_terra-2025.1.0rc11 → subsurface_terra-2025.1.0rc13}/subsurface/core/structs/structured_elements/structured_grid.py +4 -0
- {subsurface_terra-2025.1.0rc11 → subsurface_terra-2025.1.0rc13}/subsurface/modules/reader/__init__.py +2 -0
- {subsurface_terra-2025.1.0rc11 → subsurface_terra-2025.1.0rc13}/subsurface/modules/reader/mesh/_trimesh_reader.py +27 -13
- subsurface_terra-2025.1.0rc13/subsurface/modules/reader/volume/read_grav3d.py +428 -0
- {subsurface_terra-2025.1.0rc11 → subsurface_terra-2025.1.0rc13/subsurface_terra.egg-info}/PKG-INFO +1 -1
- {subsurface_terra-2025.1.0rc11 → subsurface_terra-2025.1.0rc13}/subsurface_terra.egg-info/SOURCES.txt +1 -0
- {subsurface_terra-2025.1.0rc11 → subsurface_terra-2025.1.0rc13}/.env.example +0 -0
- {subsurface_terra-2025.1.0rc11 → subsurface_terra-2025.1.0rc13}/.teamcity/Subsurface/buildTypes/Subsurface_ReleaseSubsurface.xml +0 -0
- {subsurface_terra-2025.1.0rc11 → subsurface_terra-2025.1.0rc13}/.teamcity/Subsurface/buildTypes/Subsurface_ReleaseSubsurface_2.xml +0 -0
- {subsurface_terra-2025.1.0rc11 → subsurface_terra-2025.1.0rc13}/.teamcity/Subsurface/project-config.xml +0 -0
- {subsurface_terra-2025.1.0rc11 → subsurface_terra-2025.1.0rc13}/.teamcity/Subsurface/vcsRoots/Subsurface_HttpsGithubComTerranigmaSolutionsSubsurfaceRefsHeadsMain.xml +0 -0
- {subsurface_terra-2025.1.0rc11 → subsurface_terra-2025.1.0rc13}/.teamcity/Subsurface/vcsRoots/Subsurface_HttpsGithubComTerranigmaSolutionsSubsurfaceRefsHeadsMain1.xml +0 -0
- {subsurface_terra-2025.1.0rc11 → subsurface_terra-2025.1.0rc13}/.teamcity/Subsurface/vcsRoots/Subsurface_HttpsGithubComTerranigmaSolutionsSubsurfaceRefsHeadsMain2.xml +0 -0
- {subsurface_terra-2025.1.0rc11 → subsurface_terra-2025.1.0rc13}/LICENSE +0 -0
- {subsurface_terra-2025.1.0rc11 → subsurface_terra-2025.1.0rc13}/README.rst +0 -0
- {subsurface_terra-2025.1.0rc11 → subsurface_terra-2025.1.0rc13}/requirements/requirements.txt +0 -0
- {subsurface_terra-2025.1.0rc11 → subsurface_terra-2025.1.0rc13}/requirements/requirements_all.txt +0 -0
- {subsurface_terra-2025.1.0rc11 → subsurface_terra-2025.1.0rc13}/requirements/requirements_dev.txt +0 -0
- {subsurface_terra-2025.1.0rc11 → subsurface_terra-2025.1.0rc13}/requirements/requirements_geospatial.txt +0 -0
- {subsurface_terra-2025.1.0rc11 → subsurface_terra-2025.1.0rc13}/requirements/requirements_mesh.txt +0 -0
- {subsurface_terra-2025.1.0rc11 → subsurface_terra-2025.1.0rc13}/requirements/requirements_opt.txt +0 -0
- {subsurface_terra-2025.1.0rc11 → subsurface_terra-2025.1.0rc13}/requirements/requirements_plot.txt +0 -0
- {subsurface_terra-2025.1.0rc11 → subsurface_terra-2025.1.0rc13}/requirements/requirements_traces.txt +0 -0
- {subsurface_terra-2025.1.0rc11 → subsurface_terra-2025.1.0rc13}/requirements/requirements_volume.txt +0 -0
- {subsurface_terra-2025.1.0rc11 → subsurface_terra-2025.1.0rc13}/requirements/requirements_wells.txt +0 -0
- {subsurface_terra-2025.1.0rc11 → subsurface_terra-2025.1.0rc13}/setup.cfg +0 -0
- {subsurface_terra-2025.1.0rc11 → subsurface_terra-2025.1.0rc13}/setup.py +0 -0
- {subsurface_terra-2025.1.0rc11 → subsurface_terra-2025.1.0rc13}/subsurface/__init__.py +0 -0
- {subsurface_terra-2025.1.0rc11 → subsurface_terra-2025.1.0rc13}/subsurface/api/interfaces/README.rst +0 -0
- {subsurface_terra-2025.1.0rc11 → subsurface_terra-2025.1.0rc13}/subsurface/api/interfaces/__init__.py +0 -0
- {subsurface_terra-2025.1.0rc11 → subsurface_terra-2025.1.0rc13}/subsurface/api/reader/__init__.py +0 -0
- {subsurface_terra-2025.1.0rc11 → subsurface_terra-2025.1.0rc13}/subsurface/api/reader/read_wells.py +0 -0
- {subsurface_terra-2025.1.0rc11 → subsurface_terra-2025.1.0rc13}/subsurface/core/__init__.py +0 -0
- {subsurface_terra-2025.1.0rc11 → subsurface_terra-2025.1.0rc13}/subsurface/core/geological_formats/__init__.py +0 -0
- {subsurface_terra-2025.1.0rc11 → subsurface_terra-2025.1.0rc13}/subsurface/core/geological_formats/boreholes/__init__.py +0 -0
- {subsurface_terra-2025.1.0rc11 → subsurface_terra-2025.1.0rc13}/subsurface/core/geological_formats/boreholes/_combine_trajectories.py +0 -0
- {subsurface_terra-2025.1.0rc11 → subsurface_terra-2025.1.0rc13}/subsurface/core/geological_formats/boreholes/boreholes.py +0 -0
- {subsurface_terra-2025.1.0rc11 → subsurface_terra-2025.1.0rc13}/subsurface/core/geological_formats/boreholes/collars.py +0 -0
- {subsurface_terra-2025.1.0rc11 → subsurface_terra-2025.1.0rc13}/subsurface/core/geological_formats/boreholes/survey.py +0 -0
- {subsurface_terra-2025.1.0rc11 → subsurface_terra-2025.1.0rc13}/subsurface/core/geological_formats/fault.py +0 -0
- {subsurface_terra-2025.1.0rc11 → subsurface_terra-2025.1.0rc13}/subsurface/core/reader_helpers/__init__.py +0 -0
- {subsurface_terra-2025.1.0rc11 → subsurface_terra-2025.1.0rc13}/subsurface/core/reader_helpers/reader_unstruct.py +0 -0
- {subsurface_terra-2025.1.0rc11 → subsurface_terra-2025.1.0rc13}/subsurface/core/reader_helpers/readers_data.py +0 -0
- {subsurface_terra-2025.1.0rc11 → subsurface_terra-2025.1.0rc13}/subsurface/core/reader_helpers/readers_wells.py +0 -0
- {subsurface_terra-2025.1.0rc11 → subsurface_terra-2025.1.0rc13}/subsurface/core/structs/README.rst +0 -0
- {subsurface_terra-2025.1.0rc11 → subsurface_terra-2025.1.0rc13}/subsurface/core/structs/__init__.py +0 -0
- {subsurface_terra-2025.1.0rc11 → subsurface_terra-2025.1.0rc13}/subsurface/core/structs/base_structures/__init__.py +0 -0
- {subsurface_terra-2025.1.0rc11 → subsurface_terra-2025.1.0rc13}/subsurface/core/structs/base_structures/_liquid_earth_mesh.py +0 -0
- {subsurface_terra-2025.1.0rc11 → subsurface_terra-2025.1.0rc13}/subsurface/core/structs/base_structures/_unstructured_data_constructor.py +0 -0
- {subsurface_terra-2025.1.0rc11 → subsurface_terra-2025.1.0rc13}/subsurface/core/structs/base_structures/base_structures_enum.py +0 -0
- {subsurface_terra-2025.1.0rc11 → subsurface_terra-2025.1.0rc13}/subsurface/core/structs/base_structures/unstructured_data.py +0 -0
- {subsurface_terra-2025.1.0rc11 → subsurface_terra-2025.1.0rc13}/subsurface/core/structs/structured_elements/__init__.py +0 -0
- {subsurface_terra-2025.1.0rc11 → subsurface_terra-2025.1.0rc13}/subsurface/core/structs/structured_elements/octree_mesh.py +0 -0
- {subsurface_terra-2025.1.0rc11 → subsurface_terra-2025.1.0rc13}/subsurface/core/structs/structured_elements/structured_mesh.py +0 -0
- {subsurface_terra-2025.1.0rc11 → subsurface_terra-2025.1.0rc13}/subsurface/core/structs/unstructured_elements/__init__.py +0 -0
- {subsurface_terra-2025.1.0rc11 → subsurface_terra-2025.1.0rc13}/subsurface/core/structs/unstructured_elements/line_set.py +0 -0
- {subsurface_terra-2025.1.0rc11 → subsurface_terra-2025.1.0rc13}/subsurface/core/structs/unstructured_elements/point_set.py +0 -0
- {subsurface_terra-2025.1.0rc11 → subsurface_terra-2025.1.0rc13}/subsurface/core/structs/unstructured_elements/tetrahedron_mesh.py +0 -0
- {subsurface_terra-2025.1.0rc11 → subsurface_terra-2025.1.0rc13}/subsurface/core/structs/unstructured_elements/triangular_surface.py +0 -0
- {subsurface_terra-2025.1.0rc11 → subsurface_terra-2025.1.0rc13}/subsurface/core/utils/__init__.py +0 -0
- {subsurface_terra-2025.1.0rc11 → subsurface_terra-2025.1.0rc13}/subsurface/core/utils/utils_core.py +0 -0
- {subsurface_terra-2025.1.0rc11 → subsurface_terra-2025.1.0rc13}/subsurface/modules/__init__.py +0 -0
- {subsurface_terra-2025.1.0rc11 → subsurface_terra-2025.1.0rc13}/subsurface/modules/reader/README.rst +0 -0
- {subsurface_terra-2025.1.0rc11 → subsurface_terra-2025.1.0rc13}/subsurface/modules/reader/faults/__init__.py +0 -0
- {subsurface_terra-2025.1.0rc11 → subsurface_terra-2025.1.0rc13}/subsurface/modules/reader/faults/faults.py +0 -0
- {subsurface_terra-2025.1.0rc11 → subsurface_terra-2025.1.0rc13}/subsurface/modules/reader/from_binary.py +0 -0
- {subsurface_terra-2025.1.0rc11 → subsurface_terra-2025.1.0rc13}/subsurface/modules/reader/geo_object/__init__.py +0 -0
- {subsurface_terra-2025.1.0rc11 → subsurface_terra-2025.1.0rc13}/subsurface/modules/reader/mesh/NOTES.md +0 -0
- {subsurface_terra-2025.1.0rc11 → subsurface_terra-2025.1.0rc13}/subsurface/modules/reader/mesh/_GOCAD_mesh.py +0 -0
- {subsurface_terra-2025.1.0rc11 → subsurface_terra-2025.1.0rc13}/subsurface/modules/reader/mesh/__init__.py +0 -0
- {subsurface_terra-2025.1.0rc11 → subsurface_terra-2025.1.0rc13}/subsurface/modules/reader/mesh/csv_mesh_reader.py +0 -0
- {subsurface_terra-2025.1.0rc11 → subsurface_terra-2025.1.0rc13}/subsurface/modules/reader/mesh/dxf_reader.py +0 -0
- {subsurface_terra-2025.1.0rc11 → subsurface_terra-2025.1.0rc13}/subsurface/modules/reader/mesh/glb_reader.py +0 -0
- {subsurface_terra-2025.1.0rc11 → subsurface_terra-2025.1.0rc13}/subsurface/modules/reader/mesh/mx_reader.py +0 -0
- {subsurface_terra-2025.1.0rc11 → subsurface_terra-2025.1.0rc13}/subsurface/modules/reader/mesh/obj_reader.py +0 -0
- {subsurface_terra-2025.1.0rc11 → subsurface_terra-2025.1.0rc13}/subsurface/modules/reader/mesh/omf_mesh_reader.py +0 -0
- {subsurface_terra-2025.1.0rc11 → subsurface_terra-2025.1.0rc13}/subsurface/modules/reader/mesh/surface_reader.py +0 -0
- {subsurface_terra-2025.1.0rc11 → subsurface_terra-2025.1.0rc13}/subsurface/modules/reader/mesh/surfaces_api.py +0 -0
- {subsurface_terra-2025.1.0rc11 → subsurface_terra-2025.1.0rc13}/subsurface/modules/reader/petrel/__init__.py +0 -0
- {subsurface_terra-2025.1.0rc11 → subsurface_terra-2025.1.0rc13}/subsurface/modules/reader/profiles/__init__.py +0 -0
- {subsurface_terra-2025.1.0rc11 → subsurface_terra-2025.1.0rc13}/subsurface/modules/reader/profiles/profiles_core.py +0 -0
- {subsurface_terra-2025.1.0rc11 → subsurface_terra-2025.1.0rc13}/subsurface/modules/reader/read_netcdf.py +0 -0
- {subsurface_terra-2025.1.0rc11 → subsurface_terra-2025.1.0rc13}/subsurface/modules/reader/topography/__init__.py +0 -0
- {subsurface_terra-2025.1.0rc11 → subsurface_terra-2025.1.0rc13}/subsurface/modules/reader/topography/topo_core.py +0 -0
- {subsurface_terra-2025.1.0rc11 → subsurface_terra-2025.1.0rc13}/subsurface/modules/reader/volume/__init__.py +0 -0
- {subsurface_terra-2025.1.0rc11 → subsurface_terra-2025.1.0rc13}/subsurface/modules/reader/volume/read_volume.py +0 -0
- {subsurface_terra-2025.1.0rc11 → subsurface_terra-2025.1.0rc13}/subsurface/modules/reader/volume/segy_reader.py +0 -0
- {subsurface_terra-2025.1.0rc11 → subsurface_terra-2025.1.0rc13}/subsurface/modules/reader/volume/seismic.py +0 -0
- {subsurface_terra-2025.1.0rc11 → subsurface_terra-2025.1.0rc13}/subsurface/modules/reader/volume/volume_utils.py +0 -0
- {subsurface_terra-2025.1.0rc11 → subsurface_terra-2025.1.0rc13}/subsurface/modules/reader/wells/DEP/__init__.py +0 -0
- {subsurface_terra-2025.1.0rc11 → subsurface_terra-2025.1.0rc13}/subsurface/modules/reader/wells/DEP/_well_files_reader.py +0 -0
- {subsurface_terra-2025.1.0rc11 → subsurface_terra-2025.1.0rc13}/subsurface/modules/reader/wells/DEP/_wells_api.py +0 -0
- {subsurface_terra-2025.1.0rc11 → subsurface_terra-2025.1.0rc13}/subsurface/modules/reader/wells/DEP/_welly_reader.py +0 -0
- {subsurface_terra-2025.1.0rc11 → subsurface_terra-2025.1.0rc13}/subsurface/modules/reader/wells/DEP/pandas_to_welly.py +0 -0
- {subsurface_terra-2025.1.0rc11 → subsurface_terra-2025.1.0rc13}/subsurface/modules/reader/wells/README.rst +0 -0
- {subsurface_terra-2025.1.0rc11 → subsurface_terra-2025.1.0rc13}/subsurface/modules/reader/wells/__init__.py +0 -0
- {subsurface_terra-2025.1.0rc11 → subsurface_terra-2025.1.0rc13}/subsurface/modules/reader/wells/_read_to_df.py +0 -0
- {subsurface_terra-2025.1.0rc11 → subsurface_terra-2025.1.0rc13}/subsurface/modules/reader/wells/read_borehole_interface.py +0 -0
- {subsurface_terra-2025.1.0rc11 → subsurface_terra-2025.1.0rc13}/subsurface/modules/reader/wells/wells_utils.py +0 -0
- {subsurface_terra-2025.1.0rc11 → subsurface_terra-2025.1.0rc13}/subsurface/modules/tools/__init__.py +0 -0
- {subsurface_terra-2025.1.0rc11 → subsurface_terra-2025.1.0rc13}/subsurface/modules/tools/mocking_aux.py +0 -0
- {subsurface_terra-2025.1.0rc11 → subsurface_terra-2025.1.0rc13}/subsurface/modules/visualization/__init__.py +0 -0
- {subsurface_terra-2025.1.0rc11 → subsurface_terra-2025.1.0rc13}/subsurface/modules/visualization/to_pyvista.py +0 -0
- {subsurface_terra-2025.1.0rc11 → subsurface_terra-2025.1.0rc13}/subsurface/modules/writer/__init__.py +0 -0
- {subsurface_terra-2025.1.0rc11 → subsurface_terra-2025.1.0rc13}/subsurface/modules/writer/to_binary.py +0 -0
- {subsurface_terra-2025.1.0rc11 → subsurface_terra-2025.1.0rc13}/subsurface/modules/writer/to_liquid_earth/__init__.py +0 -0
- {subsurface_terra-2025.1.0rc11 → subsurface_terra-2025.1.0rc13}/subsurface/modules/writer/to_rex/__init__.py +0 -0
- {subsurface_terra-2025.1.0rc11 → subsurface_terra-2025.1.0rc13}/subsurface/modules/writer/to_rex/common.py +0 -0
- {subsurface_terra-2025.1.0rc11 → subsurface_terra-2025.1.0rc13}/subsurface/modules/writer/to_rex/data_struct.py +0 -0
- {subsurface_terra-2025.1.0rc11 → subsurface_terra-2025.1.0rc13}/subsurface/modules/writer/to_rex/doc/rex-spec-v1.md +0 -0
- {subsurface_terra-2025.1.0rc11 → subsurface_terra-2025.1.0rc13}/subsurface/modules/writer/to_rex/doc/right-handed.png +0 -0
- {subsurface_terra-2025.1.0rc11 → subsurface_terra-2025.1.0rc13}/subsurface/modules/writer/to_rex/doc/sketchup_example.jpg +0 -0
- {subsurface_terra-2025.1.0rc11 → subsurface_terra-2025.1.0rc13}/subsurface/modules/writer/to_rex/gempy_to_rexfile.py +0 -0
- {subsurface_terra-2025.1.0rc11 → subsurface_terra-2025.1.0rc13}/subsurface/modules/writer/to_rex/material_encoder.py +0 -0
- {subsurface_terra-2025.1.0rc11 → subsurface_terra-2025.1.0rc13}/subsurface/modules/writer/to_rex/mesh_encoder.py +0 -0
- {subsurface_terra-2025.1.0rc11 → subsurface_terra-2025.1.0rc13}/subsurface/modules/writer/to_rex/to_rex.py +0 -0
- {subsurface_terra-2025.1.0rc11 → subsurface_terra-2025.1.0rc13}/subsurface/modules/writer/to_rex/utils.py +0 -0
- {subsurface_terra-2025.1.0rc11 → subsurface_terra-2025.1.0rc13}/subsurface/optional_requirements.py +0 -0
- {subsurface_terra-2025.1.0rc11 → subsurface_terra-2025.1.0rc13}/subsurface_terra.egg-info/dependency_links.txt +0 -0
- {subsurface_terra-2025.1.0rc11 → subsurface_terra-2025.1.0rc13}/subsurface_terra.egg-info/not-zip-safe +0 -0
- {subsurface_terra-2025.1.0rc11 → subsurface_terra-2025.1.0rc13}/subsurface_terra.egg-info/requires.txt +0 -0
- {subsurface_terra-2025.1.0rc11 → subsurface_terra-2025.1.0rc13}/subsurface_terra.egg-info/top_level.txt +0 -0
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
|
-
<build-type xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" uuid="ed495f4f-4df2-4a37-bbfe-2489430a46e8" xsi:noNamespaceSchemaLocation="https://www.jetbrains.com/teamcity/schemas/
|
|
2
|
+
<build-type xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" uuid="ed495f4f-4df2-4a37-bbfe-2489430a46e8" xsi:noNamespaceSchemaLocation="https://www.jetbrains.com/teamcity/schemas/2025.3/project-config.xsd">
|
|
3
3
|
<name>Testing</name>
|
|
4
4
|
<description />
|
|
5
5
|
<settings>
|
|
6
|
+
<options>
|
|
7
|
+
<option name="shouldFailBuildOnBadExitCode" value="false" />
|
|
8
|
+
</options>
|
|
6
9
|
<parameters>
|
|
7
10
|
<param name="REQUIREMENT_LEVEL" value="READ_MESH" />
|
|
8
11
|
<param name="env.MPLBACKEND" value="Agg" />
|
|
@@ -11,6 +14,9 @@
|
|
|
11
14
|
<param name="env.PATH_TO_BOLIDEN" value="%env.TERRA_PATH_DEVOPS%/combined/Leapfrog_OMF/Garpenberg_global_20220715.omf" />
|
|
12
15
|
<param name="env.PATH_TO_GLB" value="%env.TERRA_PATH_DEVOPS%/meshes/GLB - GLTF/Duck.glb" />
|
|
13
16
|
<param name="env.PATH_TO_GLB_COMPLEX" value="%env.TERRA_PATH_DEVOPS%/meshes/GLB - GLTF/GlbFile.glb" />
|
|
17
|
+
<param name="env.PATH_TO_GRAV3D_MOD" value="%env.TERRA_PATH_DEVOPS%/volume/MSH/19_simpeg_inv_result_25ft_7.62m_psi2_Sep.mod" />
|
|
18
|
+
<param name="env.PATH_TO_GRAV3D_MSH" value="%env.TERRA_PATH_DEVOPS%/volume/MSH/client_voxel.msh" />
|
|
19
|
+
<param name="env.PATH_TO_GRAV3D_MSH_II" value="%env.TERRA_PATH_DEVOPS%/volume/MSH/IDN-65/ubc_mesh_mod" />
|
|
14
20
|
<param name="env.PATH_TO_INTERPRETATION" value="%env.TERRA_PATH_DEVOPS%/meshes/Seismic/Anl2-1.tif" />
|
|
15
21
|
<param name="env.PATH_TO_MAGNETIC_INTERPRETATION" value="%env.TERRA_PATH_DEVOPS%/meshes/Magnetic/Plate 2a - Profile 1 2D inversion.pdf" />
|
|
16
22
|
<param name="env.PATH_TO_MTL" value="%env.TERRA_PATH_DEVOPS%/meshes/OBJ/Broadhaven_Obj/model/model.mtl" />
|
|
@@ -89,7 +95,6 @@ venv\Scripts\python -m pytest --teamcity -v]]></param>
|
|
|
89
95
|
<vcs-settings>
|
|
90
96
|
<vcs-entry-ref root-id="Subsurface_HttpsGithubComTerranigmaSolutionsSubsurfaceRefsHeadsMain2" />
|
|
91
97
|
</vcs-settings>
|
|
92
|
-
<requirements />
|
|
93
98
|
<build-triggers>
|
|
94
99
|
<build-trigger id="TRIGGER_4" type="vcsTrigger">
|
|
95
100
|
<parameters>
|
|
@@ -123,7 +128,6 @@ venv\Scripts\python -m pytest --teamcity -v]]></param>
|
|
|
123
128
|
</parameters>
|
|
124
129
|
</extension>
|
|
125
130
|
</build-extensions>
|
|
126
|
-
<cleanup />
|
|
127
131
|
</settings>
|
|
128
132
|
</build-type>
|
|
129
133
|
|
{subsurface_terra-2025.1.0rc11/subsurface_terra.egg-info → subsurface_terra-2025.1.0rc13}/PKG-INFO
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: subsurface_terra
|
|
3
|
-
Version: 2025.1.
|
|
3
|
+
Version: 2025.1.0rc13
|
|
4
4
|
Summary: Subsurface data types and utilities. This version is the one used by Terranigma Solutions. Please feel free to take anything in this repository for the original one.
|
|
5
5
|
Home-page: https://softwareunderground.github.io/subsurface
|
|
6
6
|
Author: Software Underground
|
|
@@ -17,5 +17,5 @@ __version__: str
|
|
|
17
17
|
__version_tuple__: VERSION_TUPLE
|
|
18
18
|
version_tuple: VERSION_TUPLE
|
|
19
19
|
|
|
20
|
-
__version__ = version = '2025.1.
|
|
21
|
-
__version_tuple__ = version_tuple = (2025, 1, 0)
|
|
20
|
+
__version__ = version = '2025.1.0rc13'
|
|
21
|
+
__version_tuple__ = version_tuple = (2025, 1, 0, 'rc13')
|
{subsurface_terra-2025.1.0rc11 → subsurface_terra-2025.1.0rc13}/subsurface/api/interfaces/stream.py
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import io
|
|
2
2
|
from io import BytesIO
|
|
3
|
-
from typing import TextIO
|
|
3
|
+
from typing import TextIO, Optional
|
|
4
4
|
|
|
5
5
|
import pandas
|
|
6
6
|
|
|
@@ -57,11 +57,17 @@ def GLTF_stream_to_trisurf(gltf_stream: io.BytesIO, coordinate_system: TriMeshTr
|
|
|
57
57
|
tri_mesh: TriSurf = reader.load_gltf_with_trimesh(gltf_stream, coordinate_system)
|
|
58
58
|
return tri_mesh
|
|
59
59
|
|
|
60
|
+
|
|
60
61
|
def VTK_stream_to_struct(stream: BytesIO, attribute_name: str) -> list[StructuredData]:
|
|
61
62
|
struct = read_VTK_structured_grid(stream, attribute_name)
|
|
62
63
|
return [struct]
|
|
63
64
|
|
|
64
65
|
|
|
66
|
+
def MSH_stream_to_struct(grid_stream: TextIO, values_stream: TextIO, missing_value: Optional[float], attr_name: Optional[str]) -> list[StructuredData]:
|
|
67
|
+
struct = reader.read_msh_structured_grid(grid_stream, values_stream, missing_value, attr_name)
|
|
68
|
+
return [struct]
|
|
69
|
+
|
|
70
|
+
|
|
65
71
|
def CSV_wells_stream_to_unstruc(
|
|
66
72
|
collars_reader: GenericReaderFilesHelper,
|
|
67
73
|
surveys_reader: GenericReaderFilesHelper,
|
|
@@ -131,12 +131,29 @@ class StructuredData:
|
|
|
131
131
|
def values(self) -> np.ndarray:
|
|
132
132
|
return self.data[self.active_data_array_name].values
|
|
133
133
|
|
|
134
|
+
_bounds: Tuple[float, float, float, float, float, float] = None
|
|
135
|
+
|
|
134
136
|
@property
|
|
135
137
|
def bounds(self):
|
|
138
|
+
if self._bounds is not None:
|
|
139
|
+
return self._bounds
|
|
140
|
+
|
|
136
141
|
array_: xr.DataArray = self.data[self.active_data_array_name]
|
|
137
|
-
bounds = self.
|
|
142
|
+
bounds = self._get_bounds_from_coord(array_)
|
|
138
143
|
return bounds
|
|
139
144
|
|
|
145
|
+
@bounds.setter
|
|
146
|
+
def bounds(self, bounds: Tuple[float, float, float, float, float, float]):
|
|
147
|
+
"""
|
|
148
|
+
Set the bounds of the structured data. This is useful for defining the
|
|
149
|
+
spatial extent of the data in a structured grid.
|
|
150
|
+
|
|
151
|
+
Args:
|
|
152
|
+
bounds (Tuple[float, float, float, float, float, float]): A tuple containing
|
|
153
|
+
the minimum and maximum values for each dimension (xmin, xmax, ymin, ymax, zmin, zmax).
|
|
154
|
+
"""
|
|
155
|
+
self._bounds = bounds
|
|
156
|
+
|
|
140
157
|
@property
|
|
141
158
|
def shape(self):
|
|
142
159
|
return self.active_data_array.shape
|
|
@@ -146,7 +163,7 @@ class StructuredData:
|
|
|
146
163
|
return self.data[self.active_data_array_name]
|
|
147
164
|
|
|
148
165
|
@staticmethod
|
|
149
|
-
def
|
|
166
|
+
def _get_bounds_from_coord(xr_obj: xr.DataArray):
|
|
150
167
|
bounds = {}
|
|
151
168
|
for coord in xr_obj.coords:
|
|
152
169
|
bounds[coord] = (xr_obj[coord].min().item(), xr_obj[coord].max().item())
|
|
@@ -33,6 +33,10 @@ class StructuredGrid:
|
|
|
33
33
|
grid_3d = np.meshgrid(*cart_coord, indexing='ij')
|
|
34
34
|
return grid_3d
|
|
35
35
|
|
|
36
|
+
@property
|
|
37
|
+
def active_attributes(self) -> np.ndarray:
|
|
38
|
+
return self.ds.data[self.ds.active_data_array_name].values
|
|
39
|
+
|
|
36
40
|
def meshgrid_2d(self, attribute_name_coord_name: str = None) -> list:
|
|
37
41
|
"""
|
|
38
42
|
|
|
@@ -9,3 +9,5 @@ from .mesh.dxf_reader import dxf_stream_to_unstruct_input, dxf_file_to_unstruct_
|
|
|
9
9
|
from .mesh.mx_reader import mx_to_unstruc_from_binary
|
|
10
10
|
from .mesh.obj_reader import load_obj_with_trimesh, load_obj_with_trimesh_from_binary
|
|
11
11
|
from .mesh.glb_reader import load_gltf_with_trimesh
|
|
12
|
+
|
|
13
|
+
from .volume.read_grav3d import read_msh_structured_grid
|
|
@@ -9,9 +9,14 @@ from .... import optional_requirements
|
|
|
9
9
|
from ....core.structs import TriSurf, StructuredData
|
|
10
10
|
|
|
11
11
|
|
|
12
|
-
class TriMeshTransformations(enum.
|
|
13
|
-
|
|
14
|
-
|
|
12
|
+
class TriMeshTransformations(enum.Flag):
|
|
13
|
+
UP_Z = 2**1
|
|
14
|
+
UP_Y = 2**2
|
|
15
|
+
FORWARD_MINUS_Z = 2**3
|
|
16
|
+
FORWARD_PLUS_Z = 2**4
|
|
17
|
+
RIGHT_HANDED_Z_UP_Y_REVERSED = UP_Y | FORWARD_MINUS_Z
|
|
18
|
+
RIGHT_HANDED_Z_UP = UP_Y | FORWARD_PLUS_Z
|
|
19
|
+
ORIGINAL = UP_Z | FORWARD_MINUS_Z
|
|
15
20
|
|
|
16
21
|
|
|
17
22
|
def load_with_trimesh(path_to_file_or_buffer, file_type: Optional[str] = None,
|
|
@@ -23,13 +28,10 @@ def load_with_trimesh(path_to_file_or_buffer, file_type: Optional[str] = None,
|
|
|
23
28
|
trimesh = optional_requirements.require_trimesh()
|
|
24
29
|
scene_or_mesh = LoadWithTrimesh.load_with_trimesh(path_to_file_or_buffer, file_type, plot)
|
|
25
30
|
|
|
26
|
-
# Compute a -90° rotation around the X axis
|
|
27
|
-
angle_rad = np.deg2rad(-90)
|
|
28
|
-
transform = trimesh.transformations.rotation_matrix(angle_rad, [1, 0, 0])
|
|
29
|
-
|
|
30
31
|
match coordinate_system:
|
|
31
32
|
case TriMeshTransformations.ORIGINAL:
|
|
32
33
|
return scene_or_mesh
|
|
34
|
+
# * Forward -Z up Y
|
|
33
35
|
case TriMeshTransformations.RIGHT_HANDED_Z_UP:
|
|
34
36
|
# Transform from Y-up (modeling software) to Z-up (scientific)
|
|
35
37
|
# This rotates the model so that:
|
|
@@ -42,16 +44,24 @@ def load_with_trimesh(path_to_file_or_buffer, file_type: Optional[str] = None,
|
|
|
42
44
|
[0, 1, 0, 0],
|
|
43
45
|
[0, 0, 0, 1]
|
|
44
46
|
])
|
|
45
|
-
|
|
47
|
+
case TriMeshTransformations.RIGHT_HANDED_Z_UP_Y_REVERSED:
|
|
48
|
+
# * Forward Z Up Y
|
|
49
|
+
transform=np.array([
|
|
50
|
+
[-1, 0, 0, 0],
|
|
51
|
+
[0, 0, 1, 0],
|
|
52
|
+
[0, 1, 0, 0],
|
|
53
|
+
[0, 0, 0, 1],
|
|
54
|
+
])
|
|
46
55
|
# Apply the coordinate transformation
|
|
47
|
-
|
|
48
|
-
for geometry in scene_or_mesh.geometry.values():
|
|
49
|
-
geometry.apply_transform(transform)
|
|
50
|
-
else:
|
|
51
|
-
scene_or_mesh.apply_transform(transform)
|
|
56
|
+
# TODO: Add all the options of blender
|
|
52
57
|
case _:
|
|
53
58
|
raise ValueError(f"Invalid coordinate system: {coordinate_system}")
|
|
54
59
|
|
|
60
|
+
if isinstance(scene_or_mesh, trimesh.Scene):
|
|
61
|
+
for geometry in scene_or_mesh.geometry.values():
|
|
62
|
+
geometry.apply_transform(transform)
|
|
63
|
+
else:
|
|
64
|
+
scene_or_mesh.apply_transform(transform)
|
|
55
65
|
return scene_or_mesh
|
|
56
66
|
|
|
57
67
|
|
|
@@ -99,6 +109,10 @@ class LoadWithTrimesh:
|
|
|
99
109
|
# If there's already an image reference in the material, let the user know
|
|
100
110
|
if hasattr(material, 'image') and material.image is not None:
|
|
101
111
|
print(" -> Material already has an image:", material.image)
|
|
112
|
+
|
|
113
|
+
if geometry.visual.uv is None:
|
|
114
|
+
raise ValueError("Geometry does not have UV coordinates for texture mapping, despite having a material."
|
|
115
|
+
"This can also happen if the geometry is given in quads instead of triangles.")
|
|
102
116
|
else:
|
|
103
117
|
print("No material found or no 'material' attribute on this geometry.")
|
|
104
118
|
|
|
@@ -0,0 +1,428 @@
|
|
|
1
|
+
from dataclasses import dataclass, field
|
|
2
|
+
from typing import List, Dict, Any, Tuple, Optional, Union, TextIO
|
|
3
|
+
import numpy as np
|
|
4
|
+
import xarray as xr
|
|
5
|
+
from pathlib import Path
|
|
6
|
+
|
|
7
|
+
from ....core.structs import StructuredData
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
@dataclass
|
|
11
|
+
class GridDimensions:
|
|
12
|
+
"""
|
|
13
|
+
Represents the dimensions of a 3D grid.
|
|
14
|
+
|
|
15
|
+
Attributes:
|
|
16
|
+
nx (int): Number of cells in the x-direction
|
|
17
|
+
ny (int): Number of cells in the y-direction
|
|
18
|
+
nz (int): Number of cells in the z-direction
|
|
19
|
+
"""
|
|
20
|
+
nx: int
|
|
21
|
+
ny: int
|
|
22
|
+
nz: int
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
@dataclass
|
|
26
|
+
class GridOrigin:
|
|
27
|
+
"""
|
|
28
|
+
Represents the origin point of a 3D grid.
|
|
29
|
+
|
|
30
|
+
Attributes:
|
|
31
|
+
x (float): X-coordinate of the origin
|
|
32
|
+
y (float): Y-coordinate of the origin
|
|
33
|
+
z (float): Z-coordinate of the origin
|
|
34
|
+
"""
|
|
35
|
+
x: float
|
|
36
|
+
y: float
|
|
37
|
+
z: float
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
@dataclass
|
|
41
|
+
class GridCellSizes:
|
|
42
|
+
"""
|
|
43
|
+
Represents the cell sizes in each direction of a 3D grid.
|
|
44
|
+
|
|
45
|
+
Attributes:
|
|
46
|
+
x (List[float]): Cell sizes in the x-direction
|
|
47
|
+
y (List[float]): Cell sizes in the y-direction
|
|
48
|
+
z (List[float]): Cell sizes in the z-direction
|
|
49
|
+
"""
|
|
50
|
+
x: List[float]
|
|
51
|
+
y: List[float]
|
|
52
|
+
z: List[float]
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
@dataclass
|
|
56
|
+
class GridData:
|
|
57
|
+
"""
|
|
58
|
+
Represents a 3D grid with dimensions, origin, and cell sizes.
|
|
59
|
+
|
|
60
|
+
Attributes:
|
|
61
|
+
dimensions (GridDimensions): The dimensions of the grid
|
|
62
|
+
origin (GridOrigin): The origin point of the grid
|
|
63
|
+
cell_sizes (GridCellSizes): The cell sizes in each direction
|
|
64
|
+
metadata (Dict[str, Any]): Optional metadata about the grid
|
|
65
|
+
"""
|
|
66
|
+
dimensions: GridDimensions
|
|
67
|
+
origin: GridOrigin
|
|
68
|
+
cell_sizes: GridCellSizes
|
|
69
|
+
metadata: Dict[str, Any] = field(default_factory=dict)
|
|
70
|
+
|
|
71
|
+
@classmethod
|
|
72
|
+
def from_dict(cls, grid_dict: Dict[str, Any]) -> 'GridData':
|
|
73
|
+
"""
|
|
74
|
+
Converts a dictionary containing grid information into a GridData instance.
|
|
75
|
+
|
|
76
|
+
Args:
|
|
77
|
+
grid_dict: Dictionary with grid information
|
|
78
|
+
|
|
79
|
+
Returns:
|
|
80
|
+
GridData: A new GridData instance
|
|
81
|
+
"""
|
|
82
|
+
dims = grid_dict["dimensions"]
|
|
83
|
+
origin_dict = grid_dict["origin"]
|
|
84
|
+
cell_sizes_dict = grid_dict["cell_sizes"]
|
|
85
|
+
|
|
86
|
+
# Handle both new and legacy key names
|
|
87
|
+
nx = dims.get("nx", dims.get("ne"))
|
|
88
|
+
ny = dims.get("ny", dims.get("nn"))
|
|
89
|
+
nz = dims.get("nz", dims.get("nz"))
|
|
90
|
+
|
|
91
|
+
x = origin_dict.get("x", origin_dict.get("x0"))
|
|
92
|
+
y = origin_dict.get("y", origin_dict.get("y0"))
|
|
93
|
+
z = origin_dict.get("z", origin_dict.get("z0"))
|
|
94
|
+
|
|
95
|
+
x_sizes = cell_sizes_dict.get("x", cell_sizes_dict.get("easting"))
|
|
96
|
+
y_sizes = cell_sizes_dict.get("y", cell_sizes_dict.get("northing"))
|
|
97
|
+
z_sizes = cell_sizes_dict.get("z", cell_sizes_dict.get("vertical"))
|
|
98
|
+
|
|
99
|
+
metadata = grid_dict.get("metadata", {})
|
|
100
|
+
|
|
101
|
+
return cls(
|
|
102
|
+
dimensions=GridDimensions(nx=nx, ny=ny, nz=nz),
|
|
103
|
+
origin=GridOrigin(x=x, y=y, z=z),
|
|
104
|
+
cell_sizes=GridCellSizes(x=x_sizes, y=y_sizes, z=z_sizes),
|
|
105
|
+
metadata=metadata
|
|
106
|
+
)
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
def read_msh_structured_grid(grid_stream: TextIO, values_stream: TextIO, missing_value: Optional[float],
|
|
110
|
+
attr_name: Optional[str]) -> StructuredData:
|
|
111
|
+
"""
|
|
112
|
+
Read a structured grid mesh and values from streams and return a StructuredData object.
|
|
113
|
+
|
|
114
|
+
This function is designed to work with streams (e.g., from Azure blob storage)
|
|
115
|
+
rather than file paths.
|
|
116
|
+
|
|
117
|
+
Args:
|
|
118
|
+
grid_stream: TextIO stream containing the grid definition (.msh format)
|
|
119
|
+
values_stream: TextIO stream containing the property values (.mod format)
|
|
120
|
+
|
|
121
|
+
Returns:
|
|
122
|
+
StructuredData object containing the grid and property values
|
|
123
|
+
|
|
124
|
+
Raises:
|
|
125
|
+
ValueError: If the stream format is invalid
|
|
126
|
+
"""
|
|
127
|
+
# Read all lines from the grid stream
|
|
128
|
+
lines = [line.strip() for line in grid_stream if line.strip()]
|
|
129
|
+
|
|
130
|
+
# Create metadata for the grid
|
|
131
|
+
metadata = {
|
|
132
|
+
'file_format': 'grav3d',
|
|
133
|
+
'source' : 'stream'
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
# Parse grid information from lines
|
|
137
|
+
try:
|
|
138
|
+
grid = _parse_grid_from_lines(lines, metadata)
|
|
139
|
+
except ValueError as e:
|
|
140
|
+
# Add context about the stream to the error message
|
|
141
|
+
raise ValueError(f"Error parsing grid stream: {e}") from e
|
|
142
|
+
|
|
143
|
+
# Read values from the values stream
|
|
144
|
+
try:
|
|
145
|
+
# Read all values from the stream
|
|
146
|
+
lines = [line.strip() for line in values_stream if line.strip()]
|
|
147
|
+
|
|
148
|
+
model_array = _parse_mod_file(grid, lines, missing_value=missing_value)
|
|
149
|
+
|
|
150
|
+
except Exception as e:
|
|
151
|
+
# Add context to any errors
|
|
152
|
+
raise ValueError(f"Error reading model stream: {str(e)}") from e
|
|
153
|
+
|
|
154
|
+
# Create and return a StructuredData object
|
|
155
|
+
return structured_data_from(model_array, grid, data_name=attr_name)
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
def read_msh_file(filepath: Union[str, Path]) -> GridData:
|
|
159
|
+
"""
|
|
160
|
+
Read a structured grid mesh file and return a GridData object.
|
|
161
|
+
|
|
162
|
+
Currently supports Grav3D mesh file format (.msh):
|
|
163
|
+
- First line: NX NY NZ (number of cells in X, Y, Z directions)
|
|
164
|
+
- Second line: X Y Z (coordinates of origin in meters)
|
|
165
|
+
- Next section: X cell widths (either expanded or using N*value notation)
|
|
166
|
+
- Next section: Y cell widths (either expanded or using N*value notation)
|
|
167
|
+
- Next section: Z cell thicknesses (either expanded or using N*value notation)
|
|
168
|
+
|
|
169
|
+
Args:
|
|
170
|
+
filepath: Path to the mesh file
|
|
171
|
+
|
|
172
|
+
Returns:
|
|
173
|
+
GridData object containing the mesh information
|
|
174
|
+
|
|
175
|
+
Raises:
|
|
176
|
+
FileNotFoundError: If the file doesn't exist
|
|
177
|
+
ValueError: If the file format is invalid
|
|
178
|
+
"""
|
|
179
|
+
filepath = Path(filepath)
|
|
180
|
+
if not filepath.exists():
|
|
181
|
+
raise FileNotFoundError(f"Mesh file not found: {filepath}")
|
|
182
|
+
|
|
183
|
+
with open(filepath, 'r') as f:
|
|
184
|
+
lines = [line.strip() for line in f.readlines() if line.strip()]
|
|
185
|
+
|
|
186
|
+
metadata = {
|
|
187
|
+
'file_format': 'grav3d',
|
|
188
|
+
'filepath' : str(filepath)
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
try:
|
|
192
|
+
return _parse_grid_from_lines(lines, metadata)
|
|
193
|
+
except ValueError as e:
|
|
194
|
+
# Add context about the file to the error message
|
|
195
|
+
raise ValueError(f"Error parsing mesh file {filepath}: {e}") from e
|
|
196
|
+
|
|
197
|
+
|
|
198
|
+
def read_mod_file(filepath: Union[str, Path], grid: GridData,
|
|
199
|
+
missing_value: float = -99_999.0) -> np.ndarray:
|
|
200
|
+
"""
|
|
201
|
+
Read a model file containing property values for a 3D grid.
|
|
202
|
+
|
|
203
|
+
Currently supports Grav3D model file format (.mod) where each line contains
|
|
204
|
+
a single property value. The values are ordered with the z-direction changing
|
|
205
|
+
fastest, then x, then y.
|
|
206
|
+
|
|
207
|
+
Args:
|
|
208
|
+
filepath: Path to the model file
|
|
209
|
+
grid: GridData object containing the grid dimensions
|
|
210
|
+
missing_value: Value to replace with NaN in the output array (default: -99_999.0)
|
|
211
|
+
|
|
212
|
+
Returns:
|
|
213
|
+
3D numpy array of property values with shape (ny, nx, nz)
|
|
214
|
+
|
|
215
|
+
Raises:
|
|
216
|
+
FileNotFoundError: If the file doesn't exist
|
|
217
|
+
ValueError: If the number of values doesn't match the grid dimensions
|
|
218
|
+
"""
|
|
219
|
+
filepath = Path(filepath)
|
|
220
|
+
if not filepath.exists():
|
|
221
|
+
raise FileNotFoundError(f"Model file not found: {filepath}")
|
|
222
|
+
|
|
223
|
+
try:
|
|
224
|
+
# Read all values from the file
|
|
225
|
+
with open(filepath, 'r') as f:
|
|
226
|
+
lines = [line.strip() for line in f if line.strip()]
|
|
227
|
+
|
|
228
|
+
model_array = _parse_mod_file(grid, lines, missing_value)
|
|
229
|
+
|
|
230
|
+
return model_array
|
|
231
|
+
|
|
232
|
+
except Exception as e:
|
|
233
|
+
# Add context to any errors
|
|
234
|
+
raise ValueError(f"Error reading model file {filepath}: {str(e)}") from e
|
|
235
|
+
|
|
236
|
+
|
|
237
|
+
def _parse_mod_file(grid: GridData, lines: List[str], missing_value: Optional[float]) -> np.ndarray:
|
|
238
|
+
# Convert each line to a float
|
|
239
|
+
values = np.array([float(line) for line in lines], dtype=float)
|
|
240
|
+
# Calculate expected number of values based on grid dimensions
|
|
241
|
+
nx, ny, nz = grid.dimensions.nx, grid.dimensions.ny, grid.dimensions.nz
|
|
242
|
+
expected_count = nx * ny * nz
|
|
243
|
+
if len(values) != expected_count:
|
|
244
|
+
raise ValueError(
|
|
245
|
+
f"Invalid model file: expected {expected_count} values, got {len(values)}"
|
|
246
|
+
)
|
|
247
|
+
# Reshape to (ny, nx, nz) with z changing fastest
|
|
248
|
+
model_array = values.reshape((ny, nx, nz))
|
|
249
|
+
# Replace missing values with NaN
|
|
250
|
+
if missing_value is not None:
|
|
251
|
+
model_array[model_array == missing_value] = np.nan
|
|
252
|
+
return model_array
|
|
253
|
+
|
|
254
|
+
|
|
255
|
+
def structured_data_from(array: np.ndarray, grid: GridData,
|
|
256
|
+
data_name: str = 'model') -> StructuredData:
|
|
257
|
+
"""
|
|
258
|
+
Convert a 3D numpy array and grid information into a StructuredData object.
|
|
259
|
+
|
|
260
|
+
Args:
|
|
261
|
+
array: 3D numpy array of property values with shape (ny, nx, nz)
|
|
262
|
+
grid: GridData object containing grid dimensions, origin, and cell sizes
|
|
263
|
+
data_name: Name for the data array (default: 'model')
|
|
264
|
+
|
|
265
|
+
Returns:
|
|
266
|
+
StructuredData object containing the data array with proper coordinates
|
|
267
|
+
|
|
268
|
+
Raises:
|
|
269
|
+
ValueError: If array shape doesn't match grid dimensions
|
|
270
|
+
"""
|
|
271
|
+
# Verify array shape matches grid dimensions
|
|
272
|
+
expected_shape = (grid.dimensions.ny, grid.dimensions.nx, grid.dimensions.nz)
|
|
273
|
+
if array.shape != expected_shape:
|
|
274
|
+
raise ValueError(
|
|
275
|
+
f"Array shape {array.shape} doesn't match grid dimensions {expected_shape}"
|
|
276
|
+
)
|
|
277
|
+
|
|
278
|
+
# Calculate cell center coordinates
|
|
279
|
+
centers = _calculate_cell_centers(grid)
|
|
280
|
+
|
|
281
|
+
# Create the xarray DataArray with proper coordinates
|
|
282
|
+
xr_data_array = xr.DataArray(
|
|
283
|
+
data=array,
|
|
284
|
+
dims=['y', 'x', 'z'], # Dimensions in the order they appear in the array
|
|
285
|
+
coords={
|
|
286
|
+
'x': centers['x'],
|
|
287
|
+
'y': centers['y'],
|
|
288
|
+
'z': centers['z'],
|
|
289
|
+
},
|
|
290
|
+
name=data_name,
|
|
291
|
+
attrs=grid.metadata # Include grid metadata in the data array
|
|
292
|
+
)
|
|
293
|
+
|
|
294
|
+
# Create a StructuredData instance from the xarray DataArray
|
|
295
|
+
struct = StructuredData.from_data_array(
|
|
296
|
+
data_array=xr_data_array,
|
|
297
|
+
data_array_name=data_name
|
|
298
|
+
)
|
|
299
|
+
|
|
300
|
+
return struct
|
|
301
|
+
|
|
302
|
+
|
|
303
|
+
def _parse_grid_from_lines(lines: List[str], metadata: Dict[str, Any] = None) -> GridData:
|
|
304
|
+
"""
|
|
305
|
+
Parse grid information from a list of lines.
|
|
306
|
+
|
|
307
|
+
Args:
|
|
308
|
+
lines: List of lines containing grid information
|
|
309
|
+
metadata: Optional metadata to include in the GridData object
|
|
310
|
+
|
|
311
|
+
Returns:
|
|
312
|
+
GridData object containing the parsed grid information
|
|
313
|
+
|
|
314
|
+
Raises:
|
|
315
|
+
ValueError: If the lines format is invalid
|
|
316
|
+
"""
|
|
317
|
+
if len(lines) < 2:
|
|
318
|
+
raise ValueError("Invalid format: insufficient data")
|
|
319
|
+
|
|
320
|
+
# Parse dimensions (first line)
|
|
321
|
+
try:
|
|
322
|
+
dims = lines[0].split()
|
|
323
|
+
nx, ny, nz = int(dims[0]), int(dims[1]), int(dims[2])
|
|
324
|
+
except (IndexError, ValueError) as e:
|
|
325
|
+
raise ValueError(f"Invalid dimensions: {e}")
|
|
326
|
+
|
|
327
|
+
# Parse origin coordinates (second line)
|
|
328
|
+
try:
|
|
329
|
+
origin = lines[1].split()
|
|
330
|
+
x, y, z = float(origin[0]), float(origin[1]), float(origin[2])
|
|
331
|
+
except (IndexError, ValueError) as e:
|
|
332
|
+
raise ValueError(f"Invalid origin: {e}")
|
|
333
|
+
|
|
334
|
+
# Parse cell sizes
|
|
335
|
+
try:
|
|
336
|
+
current_line = 2
|
|
337
|
+
x_sizes, current_line = _parse_cell_sizes(lines, current_line, nx)
|
|
338
|
+
y_sizes, current_line = _parse_cell_sizes(lines, current_line, ny)
|
|
339
|
+
z_sizes, _ = _parse_cell_sizes(lines, current_line, nz)
|
|
340
|
+
except (IndexError, ValueError) as e:
|
|
341
|
+
raise ValueError(f"Error parsing cell sizes: {e}")
|
|
342
|
+
|
|
343
|
+
# Create a GridData object with the parsed information
|
|
344
|
+
grid_data_dict = {
|
|
345
|
+
'dimensions': {'nx': nx, 'ny': ny, 'nz': nz},
|
|
346
|
+
'origin' : {'x': x, 'y': y, 'z': z},
|
|
347
|
+
'cell_sizes': {
|
|
348
|
+
'x': x_sizes,
|
|
349
|
+
'y': y_sizes,
|
|
350
|
+
'z': z_sizes
|
|
351
|
+
},
|
|
352
|
+
'metadata' : metadata or {}
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
return GridData.from_dict(grid_data_dict)
|
|
356
|
+
|
|
357
|
+
|
|
358
|
+
def _parse_cell_sizes(lines: List[str], start_index: int, count: int) -> Tuple[List[float], int]:
|
|
359
|
+
"""
|
|
360
|
+
Parse cell sizes from file lines, handling both compact (N*value) and expanded notation.
|
|
361
|
+
|
|
362
|
+
Args:
|
|
363
|
+
lines: List of lines from the file
|
|
364
|
+
start_index: Index to start parsing from
|
|
365
|
+
count: Number of values to parse
|
|
366
|
+
|
|
367
|
+
Returns:
|
|
368
|
+
Tuple containing:
|
|
369
|
+
- List of parsed values
|
|
370
|
+
- Next line index after parsing
|
|
371
|
+
"""
|
|
372
|
+
line = lines[start_index]
|
|
373
|
+
|
|
374
|
+
# Check for compact notation (N*value)
|
|
375
|
+
if '*' in line:
|
|
376
|
+
parts = line.split('*')
|
|
377
|
+
repetition = int(parts[0])
|
|
378
|
+
value = float(parts[1])
|
|
379
|
+
values = [value] * repetition
|
|
380
|
+
return values, start_index + 1
|
|
381
|
+
|
|
382
|
+
# Handle expanded notation across multiple lines
|
|
383
|
+
values = []
|
|
384
|
+
line_index = start_index
|
|
385
|
+
|
|
386
|
+
while len(values) < count and line_index < len(lines):
|
|
387
|
+
current_line = lines[line_index]
|
|
388
|
+
|
|
389
|
+
# If we encounter a line with compact notation while parsing expanded,
|
|
390
|
+
# it's likely the next section
|
|
391
|
+
if '*' in current_line and len(values) > 0:
|
|
392
|
+
break
|
|
393
|
+
|
|
394
|
+
# Add all numbers from the current line
|
|
395
|
+
values.extend([float(x) for x in current_line.split()])
|
|
396
|
+
line_index += 1
|
|
397
|
+
|
|
398
|
+
# Take only the required number of values
|
|
399
|
+
return values[:count], line_index
|
|
400
|
+
|
|
401
|
+
|
|
402
|
+
def _calculate_cell_centers(grid: GridData) -> Dict[str, np.ndarray]:
|
|
403
|
+
"""
|
|
404
|
+
Calculate the center coordinates of each cell in the grid.
|
|
405
|
+
|
|
406
|
+
Args:
|
|
407
|
+
grid: GridData object containing grid dimensions, origin, and cell sizes
|
|
408
|
+
|
|
409
|
+
Returns:
|
|
410
|
+
Dictionary with 'x', 'y', and 'z' keys containing arrays of cell center coordinates
|
|
411
|
+
"""
|
|
412
|
+
# Convert cell sizes to numpy arrays for vectorized operations
|
|
413
|
+
x_sizes = np.array(grid.cell_sizes.x)
|
|
414
|
+
y_sizes = np.array(grid.cell_sizes.y)
|
|
415
|
+
z_sizes = np.array(grid.cell_sizes.z)
|
|
416
|
+
|
|
417
|
+
# Calculate cell centers by adding cumulative sizes and offsetting by half the first cell size
|
|
418
|
+
x_centers = grid.origin.x + np.cumsum(x_sizes) - x_sizes[0] / 2
|
|
419
|
+
y_centers = grid.origin.y + np.cumsum(y_sizes) - y_sizes[0] / 2
|
|
420
|
+
|
|
421
|
+
# For z, cells typically extend downward from the origin
|
|
422
|
+
z_centers = grid.origin.z - (np.cumsum(z_sizes) - z_sizes[0] / 2)
|
|
423
|
+
|
|
424
|
+
return {
|
|
425
|
+
'x': x_centers,
|
|
426
|
+
'y': y_centers,
|
|
427
|
+
'z': z_centers
|
|
428
|
+
}
|
{subsurface_terra-2025.1.0rc11 → subsurface_terra-2025.1.0rc13/subsurface_terra.egg-info}/PKG-INFO
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: subsurface_terra
|
|
3
|
-
Version: 2025.1.
|
|
3
|
+
Version: 2025.1.0rc13
|
|
4
4
|
Summary: Subsurface data types and utilities. This version is the one used by Terranigma Solutions. Please feel free to take anything in this repository for the original one.
|
|
5
5
|
Home-page: https://softwareunderground.github.io/subsurface
|
|
6
6
|
Author: Software Underground
|
|
@@ -85,6 +85,7 @@ subsurface/modules/reader/profiles/profiles_core.py
|
|
|
85
85
|
subsurface/modules/reader/topography/__init__.py
|
|
86
86
|
subsurface/modules/reader/topography/topo_core.py
|
|
87
87
|
subsurface/modules/reader/volume/__init__.py
|
|
88
|
+
subsurface/modules/reader/volume/read_grav3d.py
|
|
88
89
|
subsurface/modules/reader/volume/read_volume.py
|
|
89
90
|
subsurface/modules/reader/volume/segy_reader.py
|
|
90
91
|
subsurface/modules/reader/volume/seismic.py
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{subsurface_terra-2025.1.0rc11 → subsurface_terra-2025.1.0rc13}/requirements/requirements.txt
RENAMED
|
File without changes
|
{subsurface_terra-2025.1.0rc11 → subsurface_terra-2025.1.0rc13}/requirements/requirements_all.txt
RENAMED
|
File without changes
|
{subsurface_terra-2025.1.0rc11 → subsurface_terra-2025.1.0rc13}/requirements/requirements_dev.txt
RENAMED
|
File without changes
|
|
File without changes
|
{subsurface_terra-2025.1.0rc11 → subsurface_terra-2025.1.0rc13}/requirements/requirements_mesh.txt
RENAMED
|
File without changes
|
{subsurface_terra-2025.1.0rc11 → subsurface_terra-2025.1.0rc13}/requirements/requirements_opt.txt
RENAMED
|
File without changes
|
{subsurface_terra-2025.1.0rc11 → subsurface_terra-2025.1.0rc13}/requirements/requirements_plot.txt
RENAMED
|
File without changes
|
{subsurface_terra-2025.1.0rc11 → subsurface_terra-2025.1.0rc13}/requirements/requirements_traces.txt
RENAMED
|
File without changes
|
{subsurface_terra-2025.1.0rc11 → subsurface_terra-2025.1.0rc13}/requirements/requirements_volume.txt
RENAMED
|
File without changes
|
{subsurface_terra-2025.1.0rc11 → subsurface_terra-2025.1.0rc13}/requirements/requirements_wells.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{subsurface_terra-2025.1.0rc11 → subsurface_terra-2025.1.0rc13}/subsurface/api/interfaces/README.rst
RENAMED
|
File without changes
|
|
File without changes
|
{subsurface_terra-2025.1.0rc11 → subsurface_terra-2025.1.0rc13}/subsurface/api/reader/__init__.py
RENAMED
|
File without changes
|
{subsurface_terra-2025.1.0rc11 → subsurface_terra-2025.1.0rc13}/subsurface/api/reader/read_wells.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{subsurface_terra-2025.1.0rc11 → subsurface_terra-2025.1.0rc13}/subsurface/core/structs/README.rst
RENAMED
|
File without changes
|
{subsurface_terra-2025.1.0rc11 → subsurface_terra-2025.1.0rc13}/subsurface/core/structs/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{subsurface_terra-2025.1.0rc11 → subsurface_terra-2025.1.0rc13}/subsurface/core/utils/__init__.py
RENAMED
|
File without changes
|
{subsurface_terra-2025.1.0rc11 → subsurface_terra-2025.1.0rc13}/subsurface/core/utils/utils_core.py
RENAMED
|
File without changes
|
{subsurface_terra-2025.1.0rc11 → subsurface_terra-2025.1.0rc13}/subsurface/modules/__init__.py
RENAMED
|
File without changes
|
{subsurface_terra-2025.1.0rc11 → subsurface_terra-2025.1.0rc13}/subsurface/modules/reader/README.rst
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{subsurface_terra-2025.1.0rc11 → subsurface_terra-2025.1.0rc13}/subsurface/modules/tools/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{subsurface_terra-2025.1.0rc11 → subsurface_terra-2025.1.0rc13}/subsurface/optional_requirements.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|