Skip to content

Commit

Permalink
Merge pull request #47 from IGNF/add_remove_dimensions
Browse files Browse the repository at this point in the history
add fn to remove dimensions into las
  • Loading branch information
alavenant authored Jul 1, 2024
2 parents a9fe436 + 71f73ea commit 6c69115
Show file tree
Hide file tree
Showing 4 changed files with 128 additions and 0 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@ tmp
__pycache__
ign_pdal_tools.egg-info
dist
*.idea*
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
- las_remove_dimension: new tool to remove one or many dimensions

# 1.6.0
- color: choose streams for RGB colorization, and IRC colorization (doc https://geoservices.ign.fr/services-web-experts-ortho)
- color: detect white images.
Expand Down
58 changes: 58 additions & 0 deletions pdaltools/las_remove_dimensions.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import argparse
import os

import pdal
from pdaltools.las_info import get_writer_parameters_from_reader_metadata

def remove_dimensions_from_las(input_las: str, dimensions: [str], output_las: str):
"""
export new las without some dimensions
"""
pipeline = pdal.Pipeline() | pdal.Reader.las(input_las)
pipeline.execute()
points = pipeline.arrays[0]
input_dimensions = list(points.dtype.fields.keys())
output_dimensions = [dim for dim in input_dimensions if dim not in dimensions]
points_pruned = points[output_dimensions]
params = get_writer_parameters_from_reader_metadata(pipeline.metadata)
pipeline_end = pdal.Pipeline(arrays=[points_pruned])
pipeline_end |= pdal.Writer.las(output_las, forward="all", **params)
pipeline_end.execute()


def parse_args():
parser = argparse.ArgumentParser("Remove dimensions from las")
parser.add_argument(
"--input_las",
"-i",
type=str,
required=True,
help="Path to the the las for which the dimensions will be removed",
)
parser.add_argument(
"--output_las",
"-o",
type=str,
required=False,
help="Path to the the output las ; if none, we replace the input las",
)
parser.add_argument(
"--dimensions",
"-d",
type=str,
required=True,
nargs="+",
help="The dimension we would like to remove from the point cloud file ; be aware to not remove mandatory "
"dimensions of las"
)

return parser.parse_args()


if __name__ == "__main__":
args = parse_args()
remove_dimensions_from_las(
input_las=args.input_las,
dimensions=args.dimensions,
output_las=args.input_las if args.output_las is None else args.output_las,
)
67 changes: 67 additions & 0 deletions test/test_las_remove_dimensions.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import tempfile
import pdal
import numpy
import os
import logging
import pytest

from pdaltools import las_remove_dimensions

TEST_PATH = os.path.dirname(os.path.abspath(__file__))
INPUT_DIR = os.path.join(TEST_PATH, "data")

ini_las = os.path.join(INPUT_DIR, "test_data_77055_627760_LA93_IGN69.laz")
added_dimensions = ["DIM_1", "DIM_2"]

def get_points(input_las : str):
pipeline_read_ini = pdal.Pipeline() | pdal.Reader.las(input_las)
pipeline_read_ini.execute()
return pipeline_read_ini.arrays[0]

def append_dimension(input_las : str, output_las : str):
pipeline = pdal.Pipeline()
pipeline |= pdal.Reader.las(input_las)
pipeline |= pdal.Filter.ferry(dimensions="=>" + ", =>".join(added_dimensions))
pipeline |= pdal.Writer.las(output_las, extra_dims="all", forward="all", )
pipeline.execute()


def test_remove_all_dimension():

# get initial data
points_ini = get_points(ini_las)

with tempfile.NamedTemporaryFile(suffix="_add.las") as tmp_las:
append_dimension(ini_las, tmp_las.name)
with tempfile.NamedTemporaryFile(suffix="_rm.las") as tmp_las_rm:
# remove all dimensions
las_remove_dimensions.remove_dimensions_from_las(tmp_las.name, added_dimensions, tmp_las_rm.name)
points_end = get_points(tmp_las_rm.name)
assert numpy.array_equal(points_ini, points_end) # output data should be the same


def test_remove_one_dimension():

# get initial data
points_ini = get_points(ini_las)

with tempfile.NamedTemporaryFile(suffix="_add.las") as tmp_las:
append_dimension(ini_las, tmp_las.name)
with tempfile.NamedTemporaryFile(suffix="_rm.las") as tmp_las_rm:
# remove one dimension
las_remove_dimensions.remove_dimensions_from_las(tmp_las.name, ["DIM_1"], tmp_las_rm.name)
points_end = get_points(tmp_las_rm.name)

assert list(points_end.dtype.fields.keys()).index("DIM_2") >= 0# should still contains DIM_2

with pytest.raises(ValueError):
list(points_end.dtype.fields.keys()).index("DIM_1") # should not have DIM_1

with pytest.raises(TypeError):
numpy.array_equal(points_ini, points_end) # output data should not be the same


if __name__ == "__main__":
logging.basicConfig(level=logging.INFO)
test_remove_all_dimension()
test_remove_one_dimension()

0 comments on commit 6c69115

Please sign in to comment.