Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add fn to remove dimensions into las #47

Merged
merged 5 commits into from
Jul 1, 2024
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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*
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# 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.
- las_remove_dimension: new tool to remove one or many dimensions

# 1.5.2
- refactor tool to propagate header infos from one pipeline to another to use it by itself
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()
Loading