Mesh data processing
Project description
Basics
MDAL Python integration allows you to access and manipulation geospatial mesh data sets using MDAL in Python.
Currently, this integration can:
read and write all MDAL compatible file formats
access vertex, face, edge and volume data as numpy arrays
write vertex, face, edge and volume data from numpy arrays
access and write scalar and vector datasets
beta level read and write integration with meshio
beta level read integration with Open3D
Drivers
[‘2DM Mesh File’, ‘XMS Tin Mesh File’, ‘Selafin File’, ‘Esri TIN’, ‘Stanford PLY Ascii Mesh File’, ‘Flo2D’, ‘HEC-RAS 2D’, ‘TUFLOW FV’, ‘AnuGA’, ‘UGRID Results’, ‘GDAL NetCDF’, ‘GDAL Grib’, ‘DAT’, ‘Binary DAT’, ‘TUFLOW XMDF’, ‘XDMF’]
Installation
Conda
MDAL Python support is installable via Conda:
conda install -c conda-forge mdal-python
PyPI
MDAL Python support can be installed using pip
pip install mdal
This will ONLY work if there is a valid and working installation of MDAL on the device and accessible through the device library search path.
GitHub
The repository for MDAL’s Python extension is available at https://github.com/ViRGIS-Team/mdal-python
Usage
The basic usage can be seen in this code snippet:
from mdal import Datasource, Info, last_status, PyMesh, drivers, MDAL_DataLocation
print(f"MDAL Version: {Info.version}")
print(f"MDAL Driver Count :{Info.driver_count}")
print(last_status().name)
for driver in Info.drivers:
print(driver)
ds = Datasource("data/ply/test_mesh.ply")
print(ds.meshes)
with ds.load(0) as mesh:
print(f"Driver : {mesh.driver_name}")
print(f"Format : {mesh.get_metadata('format')}")
print(f"Vertex Count : {mesh.vertex_count}")
print(f"Face Count : {mesh.face_count}")
print(f"Largest Face: {mesh.largest_face}")
print(f"Edge Count : {mesh.edge_count}")
print(f"CRS : {mesh.projection}")
print(f"Mesh extent : {mesh.extent}")
print(f"Metadata : {mesh.metadata}")
print(f"CRS Metadata : {mesh.get_metadata('crs')}")
mesh.add_metadata("test", "value")
print(f"Metadate set eqiuality : {mesh.get_metadata('test') == 'value'}")
vertex = mesh.vertices
print(f"Vertex Array Shape : {vertex.shape}")
faces = mesh.faces
print(f"Face Array Shape : {faces.shape}")
edges = mesh.edges
print(f"Edges Array Shape : {edges.shape}")
print("")
group = mesh.group(0)
print(f"DatasetGroup Name : {group.name}")
print(f"DatasetGroup Location : {group.location.name}")
print(f"Dataset Count : {group.dataset_count}")
print(f"Group has scalar values : {group.has_scalar}")
print(f"Group has temporal values : {group.is_temporal}")
print(f"Reference Time : {group.reference_time}")
print(f"Maximum Vertical Level Count : {group.level_count}")
print(f"Minimum / Maximum ; {group.minmax}")
print(f"Metadata : {group.metadata}")
print(f"Name Metadata : {group.get_metadata('name')}")
group.add_metadata("test", "value")
print(
f"Metadate set eqiuality : {group.get_metadata('test') == 'value'}")
print("")
for i in range(0, group.dataset_count):
data = group.data(i)
time = group.dataset_time(i)
print(f"Dataset Shape for time {time} : {data.shape}")
print("")
test = PyMesh()
test.vertices = mesh.vertices
test.faces = mesh.faces
test.edges = mesh.edges
print(f"Mesh Copy Equality : {test == mesh}")
print(
f"Mesh Vertex Size equality: {test.vertex_count == mesh.vertex_count}")
print(f"Mesh Face Size equality: {test.face_count == mesh.face_count}")
test.save("data/save_test.nc")
test2 = PyMesh(drivers()[0])
print(f"Mesh created by Driver : {test2.driver_name}")
ds2 = Datasource("data/save_test.nc")
test4 = ds2.load(0)
print(f"Save equality : {test4 == test}")
del(test)
del(test4)
mesh.save("save_test.ply")
with Datasource("data/ply/all_features.ply").load(0) as mesh:
mesh.save("save_test_2.ply")
with Datasource("save_test_2.ply").load(0) as mesh2:
print(f"Save equality 2 : {mesh == mesh2}")
with Datasource("data/tuflowfv/withMaxes/trap_steady_05_3D.nc").load() as mesh:
group = mesh.groups[1]
a, b, c = group.volumetric(0)
ds2 = Datasource("test_vol.ply")
with ds2.add_mesh() as mesh2:
mesh2.vertices = mesh.vertices
mesh2.faces = mesh.faces
print(f"Vertex Count :{mesh.vertex_count}")
print(f"Face Count : {mesh.face_count}")
group2 = mesh2.add_group(
"test", location=MDAL_DataLocation.DataOnVolumes)
group2.add_volumetric(group.data(), a, b)
print(f"Level Count: {group2.level_count}")
print(f"Location: {group2.location}")
print(f"MinMax: {group2.minmax}")
print(f"Dataset Count: {group2.dataset_count}")
data = group2.data(0)
print(f"Data Value Count: {len(data)}")
print(f"{data}")
print(f"{group2.volumetric(0)}")
a, b, c = group2.volumetric(0)
print(f"Number of Extrusion values : {len(b)}")
mesh2.save()
with ds2.load() as mesh3:
mesh3.info()
group3 = mesh3.groups[1]
print(f"{group3.location}")
d, e, f = group3.volumetric(0)
print(f"{group3.volumetric(0)}")
print(f"{group3.data(0)}")
print("Mesh Equality : {mesh2 == mesh3}")
"""deep copy test"""
with Datasource("data/ply/all_features.ply").load() as mesh:
with ds.add_mesh("test") as mesh2:
mesh2.deep_copy(mesh)
mesh2.data_copy(mesh)
print(f"{mesh2.info()}")
print("all finished !")
Integration with meshio
There is read and write integration with the meshio package. Any MDAL mesh can be converted to a meshio object and vice versa.
This integration is beta at the moment.
There are the following constraints:
MDAL_transform.to_meshio can take as an argument either a Mesh or a Dataset Group,
Only scalar MDAL datasets can be converted to meshio,
Volumetric data must be passed as a Dataset Group,
Volumetric meshio meshes and data are not currently converted, and
MDAL_transform.from_meshio only converts cells of types [“line”, “triangle”, “quad”].
from mdal import Datasource,MDAL_transform
"""meshio tests"""
with Datasource("data/ply/all_features.ply").load() as mesh:
mio = MDAL_transform.to_meshio(mesh)
print(f"{mio}")
mio.write("test.vtk")
group = mesh.group(1)
mio2 = MDAL_transform.to_meshio(group)
print(f"{mio2}")
mesh2 = MDAL_transform.from_meshio(mio)
print(f"{mesh2.info()}")
print(f"{mesh2.group(0).data()}")
print(f"{mesh2.vertex_count}")
print(f"{mesh2.face_count}")
with Datasource("test_vol.ply").load() as mesh:
group = mesh.group(1)
mio2 = MDAL_transform.to_meshio(group)
print(f"{mio2}")
print("all finished !")
Integration with Open3D
There is read-only integration with Open3D.
The MDAL_transform.to_triangle_mesh function converts any MDAL mesh to an Open3D TriangleMesh. The function can take as an argument an MDAL mesh or Dataset Group. In the former case if there are colour Datasets then these are converted to the TraingleMesh colours. In the later case, the data is converted to a false colur using a simple process - scalar data is loaded into the red values and vector data to the red and blue values.
The MDAL_transform.to_point_cloud converts a MDAL volumetric DatasetGroup to an Open3D PointCloud with the data values converted to color as above.
This integration is beta at the moment.
from mdal import Datasource, MDAL_transform
import numpy as np
import open3d as o3d
"""
Open3d Tests
"""
with Datasource("data/ply/test_mesh.ply").load() as mesh:
tm = MDAL_transform.to_triangle_mesh(mesh)
print(tm)
tm2 = o3d.io.read_triangle_mesh("data/ply/test_mesh.ply")
tmc = np.asarray(tm.vertex_colors)
tmc2 = np.asarray(tm2.vertex_colors)
for i in range(len(tmc)):
value = tmc[i] - tmc2[i]
if not (value == [0, 0, 0]).all():
print(value)
break
with Datasource("test_vol.ply").load() as mesh:
pc = MDAL_transform.to_point_cloud(mesh.group(1))
print(pc)
print("all finished !")
Documentation
The documentation is currently WIP and can be found at https://virgis-team.github.io/mdal-python/html/index.html
Requirements
MDAL 0.9.0 +
Python >=3.8
Cython (eg
pip install cython
)Numpy (eg
pip install numpy
)Packaging (eg
pip install packaging
)scikit-build (eg
pip install scikit-build
)
Credit
This package borrowed heavily from the PDAL-Python package.
Changes
1.1.0
Updates the NUMPy ABI to 2.0
Fix the CI deprecation (#20)
1.0.3
fix debug message error (#15)
Deprecate mdal-python (#16)
1.0.2
fix memory leaks and inconsistencies around the Datagroup object (#11)
1.0.1
Add the PyPI package
1.0.0
First Read / Write Release
read and write all MDAL compatible file formats
access vertex, face, edge and volume data as numpy arrays
write vertex, face, edge and volume data from numpy arrays
access and write scalar and vector datasets
beta level read and write integration with meshio
beta level read integration with Open3D
0.9.0
First release. This is beta software and has not been completely tested yet:
Currently, this integration can:
read all MDAL compatible file formats,
access the metadata for the source,
access the vertex, face and edge data as numpy arrays,
access ‘double’ datasets (both scalar and vector) as numpy arrays, and
convert the MDAL source mesh into a meshio mesh object (with some restrictions currently).
This version does not currently allow the MDAL source mesh to be written or ammended.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distributions
Hashes for mdal-1.1.0-cp312-cp312-win_amd64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 75ecd6015cb6a5409bf72eaded224bdb9053a663c7721d88aa3fd8ca4fe6b1f8 |
|
MD5 | 6f735c74e9049bbf9ef76ff1ea1725c6 |
|
BLAKE2b-256 | 95a413709598c2aedcae9a8ea679b87de2f019abc02dc082149ab5b31907956d |
Hashes for mdal-1.1.0-cp312-cp312-macosx_12_0_x86_64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | be57faf86c5a1cab0442a698d59675e99737363328dc109abc14f8753ad70be1 |
|
MD5 | a903c16c66fa2f1895bafa84dd2b4d72 |
|
BLAKE2b-256 | e80eea34126f1568b718ce0d9ce24a40f1c3a6a7e437f6767099fb611e59c90e |
Hashes for mdal-1.1.0-cp311-cp311-win_amd64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 3857c05fe5331d49dd02595a6c1abacc49c89d42b10feb1d405664e49b222bfb |
|
MD5 | 8feeb4f3fdf0c647104ce58d63a5ac12 |
|
BLAKE2b-256 | 8d5399751067a8814acbf7012c6c800b72056f8d941aa86abbb1e6bc39e21b17 |
Hashes for mdal-1.1.0-cp311-cp311-macosx_12_0_x86_64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 706361d5c1032a33eec6b5a68db675fdb96291cdd09cb4471037cf949d0fbac0 |
|
MD5 | 5789ab85a26cbfe64ced1f3950d78c12 |
|
BLAKE2b-256 | 9220f490d622bd0c0b5577e80be1ed4f6cdc3d43fe3ecbe9ab8f4cb6a3d71b9e |
Hashes for mdal-1.1.0-cp310-cp310-win_amd64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 3071f921ca732453058e714396de96b8643518b8169a223a64e3e133ba81b49a |
|
MD5 | ea93550e28bf3abe691207baaa7aca8e |
|
BLAKE2b-256 | 82c732bc016a659b5c00f230d36265f98f44998e31d1dad589d00dec7be379a5 |
Hashes for mdal-1.1.0-cp310-cp310-macosx_12_0_x86_64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | f98b6dca3504a209de953f5584c060f6bee4ff7821fe8d405df504faa6f2a54e |
|
MD5 | 5ced3b517038a3e88513cf526e8d4fc5 |
|
BLAKE2b-256 | 773500d48689635e93ffbe5391cb01e6ff1ffb2efe7e161dc7ebd07aa38edf6c |
Hashes for mdal-1.1.0-cp39-cp39-win_amd64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 048268c2e4539b5e0bb4f310e539d2e46c0c166a273092a9d9c857c259a293e7 |
|
MD5 | 33abb9c4bcf3b1a57a68906d93f5e3e1 |
|
BLAKE2b-256 | aac14551319a66f11cd0e48bd79996e43eb9e288b5b6aef7b2385ba5059ce7a2 |
Hashes for mdal-1.1.0-cp39-cp39-macosx_12_0_x86_64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | af0cbbd434e7516be86bcb924c738dafebf94bc6944394aa5d05520b0df992c0 |
|
MD5 | 8f67c5dc20fce67199097a53a11c555a |
|
BLAKE2b-256 | f24bebdd14e8b82657832cf742b1c2ed4c48a4cb8f56c30ef53b33f9b0510307 |