ign-pdal-tools 1.15.5__tar.gz → 1.15.6__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.
Files changed (43) hide show
  1. {ign_pdal_tools-1.15.5 → ign_pdal_tools-1.15.6}/PKG-INFO +1 -1
  2. {ign_pdal_tools-1.15.5 → ign_pdal_tools-1.15.6}/ign_pdal_tools.egg-info/PKG-INFO +1 -1
  3. {ign_pdal_tools-1.15.5 → ign_pdal_tools-1.15.6}/pdaltools/_version.py +1 -1
  4. {ign_pdal_tools-1.15.5 → ign_pdal_tools-1.15.6}/pdaltools/add_points_in_pointcloud.py +1 -1
  5. {ign_pdal_tools-1.15.5 → ign_pdal_tools-1.15.6}/pdaltools/color.py +2 -2
  6. {ign_pdal_tools-1.15.5 → ign_pdal_tools-1.15.6}/pdaltools/create_random_laz.py +14 -18
  7. {ign_pdal_tools-1.15.5 → ign_pdal_tools-1.15.6}/pdaltools/download_image.py +1 -1
  8. {ign_pdal_tools-1.15.5 → ign_pdal_tools-1.15.6}/pdaltools/las_add_buffer.py +3 -3
  9. {ign_pdal_tools-1.15.5 → ign_pdal_tools-1.15.6}/pdaltools/las_comparison.py +4 -3
  10. {ign_pdal_tools-1.15.5 → ign_pdal_tools-1.15.6}/pdaltools/las_rename_dimension.py +4 -2
  11. {ign_pdal_tools-1.15.5 → ign_pdal_tools-1.15.6}/pdaltools/replace_area_in_pointcloud.py +1 -1
  12. {ign_pdal_tools-1.15.5 → ign_pdal_tools-1.15.6}/pdaltools/standardize_format.py +42 -25
  13. {ign_pdal_tools-1.15.5 → ign_pdal_tools-1.15.6}/pdaltools/unlock_file.py +1 -2
  14. {ign_pdal_tools-1.15.5 → ign_pdal_tools-1.15.6}/test/test_add_points_in_pointcloud.py +48 -0
  15. {ign_pdal_tools-1.15.5 → ign_pdal_tools-1.15.6}/test/test_create_random_laz.py +30 -17
  16. {ign_pdal_tools-1.15.5 → ign_pdal_tools-1.15.6}/test/test_las_comparison.py +6 -4
  17. {ign_pdal_tools-1.15.5 → ign_pdal_tools-1.15.6}/test/test_las_remove_dimensions.py +4 -4
  18. {ign_pdal_tools-1.15.5 → ign_pdal_tools-1.15.6}/test/test_las_rename_dimension.py +37 -36
  19. {ign_pdal_tools-1.15.5 → ign_pdal_tools-1.15.6}/test/test_pdal.py +4 -4
  20. {ign_pdal_tools-1.15.5 → ign_pdal_tools-1.15.6}/test/test_standardize_format.py +4 -3
  21. {ign_pdal_tools-1.15.5 → ign_pdal_tools-1.15.6}/LICENSE.md +0 -0
  22. {ign_pdal_tools-1.15.5 → ign_pdal_tools-1.15.6}/README.md +0 -0
  23. {ign_pdal_tools-1.15.5 → ign_pdal_tools-1.15.6}/ign_pdal_tools.egg-info/SOURCES.txt +0 -0
  24. {ign_pdal_tools-1.15.5 → ign_pdal_tools-1.15.6}/ign_pdal_tools.egg-info/dependency_links.txt +0 -0
  25. {ign_pdal_tools-1.15.5 → ign_pdal_tools-1.15.6}/ign_pdal_tools.egg-info/top_level.txt +0 -0
  26. {ign_pdal_tools-1.15.5 → ign_pdal_tools-1.15.6}/pdaltools/las_clip.py +0 -0
  27. {ign_pdal_tools-1.15.5 → ign_pdal_tools-1.15.6}/pdaltools/las_info.py +0 -0
  28. {ign_pdal_tools-1.15.5 → ign_pdal_tools-1.15.6}/pdaltools/las_merge.py +0 -0
  29. {ign_pdal_tools-1.15.5 → ign_pdal_tools-1.15.6}/pdaltools/las_remove_dimensions.py +0 -0
  30. {ign_pdal_tools-1.15.5 → ign_pdal_tools-1.15.6}/pdaltools/pcd_info.py +0 -0
  31. {ign_pdal_tools-1.15.5 → ign_pdal_tools-1.15.6}/pdaltools/replace_attribute_in_las.py +0 -0
  32. {ign_pdal_tools-1.15.5 → ign_pdal_tools-1.15.6}/pyproject.toml +0 -0
  33. {ign_pdal_tools-1.15.5 → ign_pdal_tools-1.15.6}/setup.cfg +0 -0
  34. {ign_pdal_tools-1.15.5 → ign_pdal_tools-1.15.6}/test/test_color.py +0 -0
  35. {ign_pdal_tools-1.15.5 → ign_pdal_tools-1.15.6}/test/test_download_image.py +0 -0
  36. {ign_pdal_tools-1.15.5 → ign_pdal_tools-1.15.6}/test/test_las_add_buffer.py +0 -0
  37. {ign_pdal_tools-1.15.5 → ign_pdal_tools-1.15.6}/test/test_las_clip.py +0 -0
  38. {ign_pdal_tools-1.15.5 → ign_pdal_tools-1.15.6}/test/test_las_info.py +0 -0
  39. {ign_pdal_tools-1.15.5 → ign_pdal_tools-1.15.6}/test/test_las_merge.py +0 -0
  40. {ign_pdal_tools-1.15.5 → ign_pdal_tools-1.15.6}/test/test_pcd_info.py +0 -0
  41. {ign_pdal_tools-1.15.5 → ign_pdal_tools-1.15.6}/test/test_replace_area_in_pointcloud.py +0 -0
  42. {ign_pdal_tools-1.15.5 → ign_pdal_tools-1.15.6}/test/test_replace_attribute_in_las.py +0 -0
  43. {ign_pdal_tools-1.15.5 → ign_pdal_tools-1.15.6}/test/test_unlock.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ign-pdal-tools
3
- Version: 1.15.5
3
+ Version: 1.15.6
4
4
  Summary: Library for common LAS files manipulation with PDAL
5
5
  Author-email: Guillaume Liegard <guillaume.liegard@ign.fr>
6
6
  Description-Content-Type: text/markdown
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ign-pdal-tools
3
- Version: 1.15.5
3
+ Version: 1.15.6
4
4
  Summary: Library for common LAS files manipulation with PDAL
5
5
  Author-email: Guillaume Liegard <guillaume.liegard@ign.fr>
6
6
  Description-Content-Type: text/markdown
@@ -1,4 +1,4 @@
1
- __version__ = "1.15.5"
1
+ __version__ = "1.15.6"
2
2
 
3
3
 
4
4
  if __name__ == "__main__":
@@ -156,7 +156,7 @@ def add_points_to_las(
156
156
  new_points.z = z_coords.astype(new_points.z.dtype)
157
157
  new_points.classification = classes.astype(new_points.classification.dtype)
158
158
 
159
- with tempfile.NamedTemporaryFile(suffix="_new_points.las") as tmp:
159
+ with tempfile.NamedTemporaryFile(suffix="_new_points.las", delete_on_close=False) as tmp:
160
160
  with laspy.open(tmp.name, mode="w", header=header) as las_file:
161
161
  las_file.write_points(new_points)
162
162
 
@@ -101,7 +101,7 @@ def color(
101
101
 
102
102
  tmp_ortho = None
103
103
  if color_rvb_enabled:
104
- tmp_ortho = tempfile.NamedTemporaryFile(suffix="_rvb.tif")
104
+ tmp_ortho = tempfile.NamedTemporaryFile(suffix="_rvb.tif", delete_on_close=False)
105
105
  download_image(
106
106
  proj,
107
107
  stream_RGB,
@@ -124,7 +124,7 @@ def color(
124
124
 
125
125
  tmp_ortho_irc = None
126
126
  if color_ir_enabled:
127
- tmp_ortho_irc = tempfile.NamedTemporaryFile(suffix="_irc.tif")
127
+ tmp_ortho_irc = tempfile.NamedTemporaryFile(suffix="_irc.tif", delete_on_close=False)
128
128
  download_image(
129
129
  proj,
130
130
  stream_IRC,
@@ -1,10 +1,11 @@
1
- import numpy as np
2
- import laspy
3
- from pathlib import Path
4
1
  import argparse
5
- from pyproj import CRS
2
+ from pathlib import Path
6
3
  from typing import List, Tuple
7
4
 
5
+ import laspy
6
+ import numpy as np
7
+ from pyproj import CRS
8
+
8
9
 
9
10
  def create_random_laz(
10
11
  output_file: str,
@@ -27,7 +28,7 @@ def create_random_laz(
27
28
  (default: (650000, 6810000) ; around Paris)
28
29
  extra_dims: List of tuples (dimension_name, dimension_type) where type can be:
29
30
  'float32', 'float64', 'int8', 'int16', 'int32', 'int64', 'uint8', 'uint16', 'uint32', 'uint64'
30
- classifications: Optional list of classification values.
31
+ classifications: Optional list of classification values.
31
32
  """
32
33
 
33
34
  # Create a new point cloud
@@ -103,7 +104,6 @@ def create_random_laz(
103
104
 
104
105
 
105
106
  def test_output_file(result: dict, output_file: str):
106
-
107
107
  # Validate output file path
108
108
  output_path = Path(output_file)
109
109
  if not output_path.exists():
@@ -126,12 +126,14 @@ def parse_args():
126
126
  )
127
127
  parser.add_argument("--crs", type=int, default=2154, help="Projection code")
128
128
  parser.add_argument(
129
- "--center", type=float, nargs=2, default=[650000.0, 6810000.0],
130
- help="Center coordinates (x y) of the area to generate points in (space-separated)"
129
+ "--center",
130
+ type=float,
131
+ nargs=2,
132
+ default=[650000.0, 6810000.0],
133
+ help="Center coordinates (x y) of the area to generate points in (space-separated)",
131
134
  )
132
135
  parser.add_argument(
133
- "--classifications", type=int, nargs='+',
134
- help="List of classification values (space-separated)"
136
+ "--classifications", type=int, nargs="+", help="List of classification values (space-separated)"
135
137
  )
136
138
  return parser.parse_args()
137
139
 
@@ -145,19 +147,13 @@ def main():
145
147
 
146
148
  # Parse center
147
149
  center = tuple(args.center[:2]) # Only take first 2 values if more are provided
148
-
150
+
149
151
  # Parse classifications if provided
150
152
  classifications = args.classifications
151
153
 
152
154
  # Call create_random_laz
153
155
  result = create_random_laz(
154
- args.output_file,
155
- args.point_format,
156
- args.num_points,
157
- args.crs,
158
- center,
159
- extra_dims,
160
- classifications
156
+ args.output_file, args.point_format, args.num_points, args.crs, center, extra_dims, classifications
161
157
  )
162
158
 
163
159
  # Test output file
@@ -185,7 +185,7 @@ def download_image(proj, layer, minx, miny, maxx, maxy, pixel_per_meter, outfile
185
185
  tmp_gpg_ortho.append(cells_ortho_paths)
186
186
 
187
187
  # merge the cells
188
- with tempfile.NamedTemporaryFile(suffix="_gpf.vrt") as tmp_vrt:
188
+ with tempfile.NamedTemporaryFile(suffix="_gpf.vrt", delete_on_close=False) as tmp_vrt:
189
189
  gdal.BuildVRT(tmp_vrt.name, tmp_gpg_ortho)
190
190
  gdal.Translate(outfile, tmp_vrt.name)
191
191
 
@@ -153,7 +153,7 @@ def remove_points_from_buffer(input_file: str, output_file: str):
153
153
  input_file (str): path to the input file containing the "is_in_original" dimension
154
154
  output_file (str): path to the output_file
155
155
  """
156
- with tempfile.NamedTemporaryFile(suffix="_with_additional_dim.las") as tmp_las:
156
+ with tempfile.NamedTemporaryFile(suffix="_with_additional_dim.las", delete_on_close=False) as tmp_las:
157
157
  pipeline = pdal.Pipeline() | pdal.Reader.las(input_file)
158
158
  pipeline |= pdal.Filter.range(limits=f"{ORIGINAL_TILE_TAG}[1:1]")
159
159
  pipeline |= pdal.Writer.las(filename=tmp_las.name, forward="all", extra_dims="all")
@@ -217,8 +217,8 @@ def run_on_buffered_las(
217
217
  )
218
218
 
219
219
  with (
220
- tempfile.NamedTemporaryFile(suffix="_buffered_input.laz", dir=".") as buf_in,
221
- tempfile.NamedTemporaryFile(suffix="_buffered_output.laz", dir=".") as buf_out,
220
+ tempfile.NamedTemporaryFile(suffix="_buffered_input.laz", dir=".", delete_on_close=False) as buf_in,
221
+ tempfile.NamedTemporaryFile(suffix="_buffered_output.laz", dir=".", delete_on_close=False) as buf_out,
222
222
  ):
223
223
  create_las_with_buffer(
224
224
  Path(input_file).parent,
@@ -1,9 +1,10 @@
1
- import laspy
2
- from pathlib import Path
3
- import numpy as np
4
1
  import argparse
2
+ from pathlib import Path
5
3
  from typing import Tuple
6
4
 
5
+ import laspy
6
+ import numpy as np
7
+
7
8
 
8
9
  def compare_las_dimensions(file1: Path, file2: Path, dimensions: list = None) -> Tuple[bool, int, float]:
9
10
  """
@@ -6,11 +6,13 @@ This script allows renaming dimensions in a LAS file while preserving all other
6
6
 
7
7
  import argparse
8
8
  import logging
9
- import pdal
10
9
  import sys
11
10
  from pathlib import Path
12
- from pdaltools.las_remove_dimensions import remove_dimensions_from_points
11
+
12
+ import pdal
13
+
13
14
  from pdaltools.las_info import las_info_metadata
15
+ from pdaltools.las_remove_dimensions import remove_dimensions_from_points
14
16
 
15
17
 
16
18
  def rename_dimension(input_file: str, output_file: str, old_dims: list[str], new_dims: list[str]):
@@ -271,7 +271,7 @@ def replace_area(
271
271
  points = pipeline.execute()
272
272
 
273
273
  end = time.time()
274
- print(f"Step 3: merge: { points }, points in {end-t3:.2f} seconds")
274
+ print(f"Step 3: merge: {points}, points in {end-t3:.2f} seconds")
275
275
  print("all steps done in ", f"{end-start:.2f}", " seconds")
276
276
 
277
277
 
@@ -9,13 +9,14 @@
9
9
  """
10
10
 
11
11
  import argparse
12
+ import os
12
13
  import tempfile
13
14
  from typing import Dict, List
14
15
 
15
16
  import pdal
16
17
 
17
- from pdaltools.unlock_file import copy_and_hack_decorator
18
18
  from pdaltools.las_rename_dimension import rename_dimension
19
+ from pdaltools.unlock_file import copy_and_hack_decorator
19
20
 
20
21
  # Standard parameters to pass to the pdal writer
21
22
  STANDARD_PARAMETERS = dict(
@@ -76,34 +77,50 @@ def get_writer_parameters(new_parameters: Dict) -> Dict:
76
77
  params = STANDARD_PARAMETERS | new_parameters
77
78
  return params
78
79
 
80
+
79
81
  @copy_and_hack_decorator
80
82
  def standardize(
81
- input_file: str, output_file: str, params_from_parser: Dict, classes_to_remove: List = [], rename_dims: List = []
83
+ input_file: str,
84
+ output_file: str,
85
+ params_from_parser: Dict,
86
+ classes_to_remove: List = [],
87
+ rename_dims: List = []
82
88
  ) -> None:
89
+ """
90
+ Standardize a LAS/LAZ file with improved error handling and resource management.
91
+
92
+ Args:
93
+ input_file: Input file path
94
+ output_file: Output file path
95
+ params_from_parser: Parameters for the PDAL writer
96
+ classes_to_remove: List of classification classes to remove
97
+ rename_dims: List of dimension names to rename (pairs of old_name, new_name)
98
+ """
83
99
  params = get_writer_parameters(params_from_parser)
84
-
85
- # Create temporary file for dimension renaming if needed
86
- if rename_dims:
87
- with tempfile.NamedTemporaryFile(suffix=".laz", delete=False) as tmp_file:
88
- tmp_file_name = tmp_file.name
89
-
90
- # Rename dimensions
91
- old_dims = rename_dims[::2]
92
- new_dims = rename_dims[1::2]
93
- rename_dimension(input_file, tmp_file_name, old_dims, new_dims)
94
-
95
- # Use renamed file as input
96
- input_file = tmp_file_name
97
- else:
98
- tmp_file_name = input_file
99
-
100
- pipeline = pdal.Pipeline()
101
- pipeline |= pdal.Reader.las(tmp_file_name)
102
- if classes_to_remove:
103
- expression = "&&".join([f"Classification != {c}" for c in classes_to_remove])
104
- pipeline |= pdal.Filter.expression(expression=expression)
105
- pipeline |= pdal.Writer(filename=output_file, forward="all", **params)
106
- pipeline.execute()
100
+ tmp_file_name = None
101
+
102
+ try:
103
+ # Create temporary file for dimension renaming if needed
104
+ if rename_dims:
105
+ with tempfile.NamedTemporaryFile(suffix=".laz", delete=False) as tmp_file:
106
+ tmp_file_name = tmp_file.name
107
+ old_dims = rename_dims[::2]
108
+ new_dims = rename_dims[1::2]
109
+ rename_dimension(input_file, tmp_file_name, old_dims, new_dims)
110
+ input_file = tmp_file_name
111
+
112
+ pipeline = pdal.Pipeline()
113
+ pipeline |= pdal.Reader.las(input_file)
114
+ if classes_to_remove:
115
+ expression = "&&".join([f"Classification != {c}" for c in classes_to_remove])
116
+ pipeline |= pdal.Filter.expression(expression=expression)
117
+ pipeline |= pdal.Writer(filename=output_file, forward="all", **params)
118
+ pipeline.execute()
119
+
120
+ finally:
121
+ # Clean up temporary file
122
+ if tmp_file_name and os.path.exists(tmp_file_name):
123
+ os.remove(tmp_file_name)
107
124
 
108
125
 
109
126
  def main():
@@ -39,10 +39,9 @@ def copy_and_hack_decorator(func):
39
39
  if "readers.las: Global encoding WKT flag not set for point format 6 - 10." in str(e):
40
40
  args = list(args)
41
41
  in_file = args[0]
42
- with tempfile.NamedTemporaryFile(suffix=os.path.splitext(in_file)[-1]) as tmp:
42
+ with tempfile.NamedTemporaryFile(suffix=os.path.splitext(in_file)[-1], delete_on_close=False) as tmp:
43
43
  copy_and_hack_input_file(in_file, tmp.name)
44
44
  args[0] = tmp.name
45
-
46
45
  return func(*args, **kwargs)
47
46
 
48
47
  else:
@@ -1,10 +1,12 @@
1
1
  import inspect
2
2
  import os
3
+ import tempfile
3
4
  from pathlib import Path
4
5
 
5
6
  import geopandas as gpd
6
7
  import laspy
7
8
  import numpy as np
9
+ import pdal
8
10
  import pytest
9
11
  from shapely.geometry import LineString, MultiPoint, Point
10
12
 
@@ -424,3 +426,49 @@ def test_parse_args():
424
426
  parsed_args_keys = args.__dict__.keys()
425
427
  main_parameters = inspect.signature(add_points_in_pointcloud.add_points_from_geometry_to_las).parameters.keys()
426
428
  assert set(parsed_args_keys) == set(main_parameters)
429
+
430
+
431
+ def test_namedtemporaryfile_delete_on_close_false():
432
+ """Test that NamedTemporaryFile could be used on windows in the context with delete_on_close=False"""
433
+ temp_file_path = None
434
+
435
+ with tempfile.NamedTemporaryFile(suffix="_test.las", delete_on_close=False) as tmp:
436
+ temp_file_path = tmp.name
437
+ # Verify that the file exists during the context
438
+ assert os.path.exists(temp_file_path)
439
+
440
+ # Write some data to the temporary file
441
+ with open(temp_file_path, "w") as f:
442
+ f.write("test data")
443
+ f.close()
444
+
445
+ # Verify that the file still exists after exiting the context
446
+ assert not os.path.exists(
447
+ temp_file_path
448
+ ), f"Temporary file {temp_file_path} should not exist oustside the context with delete_on_close=False"
449
+
450
+
451
+ def test_namedtemporaryfile_delete_false_with_pdal():
452
+ """Test that NamedTemporaryFile could be used on windows in the context
453
+ with delete_on_close=False and some pdal operations"""
454
+
455
+ def read_las(input_las, tmp):
456
+ pipeline = pdal.Pipeline()
457
+ pipeline |= pdal.Reader.las(filename=input_las)
458
+ pipeline |= pdal.Writer.las(filename=tmp.name, forward="all", extra_dims="all")
459
+ pipeline.execute()
460
+
461
+ input_las = os.path.join(TEST_PATH, "data/crop_duplicate.laz")
462
+ temp_file_path = None
463
+ with tempfile.NamedTemporaryFile(suffix="_test.las", delete_on_close=False) as tmp:
464
+ temp_file_path = tmp.name
465
+ read_las(input_las, tmp)
466
+ pipeline = pdal.Pipeline()
467
+ pipeline |= pdal.Reader.las(filename=tmp.name)
468
+ pipeline.execute()
469
+ assert os.path.exists(tmp.name)
470
+
471
+ # Verify that the file still exists after exiting the context
472
+ assert not os.path.exists(
473
+ temp_file_path
474
+ ), f"Temporary file {temp_file_path} should not exist oustside the context with delete_on_close=False"
@@ -1,9 +1,10 @@
1
1
  import os
2
- import pytest
3
- import numpy as np
4
- import laspy
5
2
  import sys
6
3
 
4
+ import laspy
5
+ import numpy as np
6
+ import pytest
7
+
7
8
  from pdaltools.create_random_laz import create_random_laz, main
8
9
 
9
10
  TEST_PATH = os.path.dirname(os.path.abspath(__file__))
@@ -138,13 +139,14 @@ def test_create_random_laz_data_ranges():
138
139
  assert np.all(las.uint_dim >= 0)
139
140
  assert np.all(las.uint_dim <= 100)
140
141
 
142
+
141
143
  @pytest.mark.parametrize(
142
144
  "classifications",
143
145
  [
144
146
  [1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
145
147
  [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20],
146
- [1, 2, 3, 66, 68]
147
- ]
148
+ [1, 2, 3, 66, 68],
149
+ ],
148
150
  )
149
151
  def test_create_random_laz_classifications(classifications):
150
152
  """Test that generated data is within expected ranges for different types"""
@@ -158,18 +160,18 @@ def test_create_random_laz_classifications(classifications):
158
160
 
159
161
  with laspy.open(output_file) as las_file:
160
162
  las = las_file.read()
161
-
163
+
162
164
  # Convert to set for faster lookups
163
165
  valid_classifications = set(classifications)
164
-
166
+
165
167
  # Check that all classification values are in the provided list
166
168
  unique_classes = set(np.unique(las.classification))
167
- assert unique_classes.issubset(valid_classifications), \
168
- f"Found unexpected classification values: {unique_classes - valid_classifications}"
169
-
169
+ assert unique_classes.issubset(
170
+ valid_classifications
171
+ ), f"Found unexpected classification values: {unique_classes - valid_classifications}"
172
+
170
173
  # Also check that we have the expected number of points
171
- assert len(las.classification) == 1000, \
172
- f"Expected 1000 points, got {len(las.classification)}"
174
+ assert len(las.classification) == 1000, f"Expected 1000 points, got {len(las.classification)}"
173
175
 
174
176
 
175
177
  def test_main():
@@ -191,11 +193,21 @@ def test_main():
191
193
  "--crs",
192
194
  "2154",
193
195
  "--center",
194
- "650000", "6810000",
196
+ "650000",
197
+ "6810000",
195
198
  "--extra_dims",
196
199
  "height:float32",
197
200
  "--classifications",
198
- "1", "2", "3", "4", "5", "6", "7", "8", "9", "10"
201
+ "1",
202
+ "2",
203
+ "3",
204
+ "4",
205
+ "5",
206
+ "6",
207
+ "7",
208
+ "8",
209
+ "9",
210
+ "10",
199
211
  ]
200
212
 
201
213
  # Run main function
@@ -209,12 +221,13 @@ def test_main():
209
221
  las = las_file.read()
210
222
  assert len(las.points) == 50
211
223
  assert "height" in las.point_format.dimension_names
212
-
224
+
213
225
  # Verify classifications are within the provided range
214
226
  unique_classes = set(np.unique(las.classification))
215
227
  expected_classes = set(range(1, 11)) # 1-10
216
- assert unique_classes.issubset(expected_classes), \
217
- f"Found unexpected classification values: {unique_classes - expected_classes}"
228
+ assert unique_classes.issubset(
229
+ expected_classes
230
+ ), f"Found unexpected classification values: {unique_classes - expected_classes}"
218
231
 
219
232
  finally:
220
233
  # Restore original sys.argv
@@ -1,10 +1,12 @@
1
- import pytest
2
1
  import tempfile
3
- import numpy as np
4
2
  from pathlib import Path
3
+ from typing import Tuple
4
+
5
5
  import laspy
6
+ import numpy as np
7
+ import pytest
8
+
6
9
  from pdaltools.las_comparison import compare_las_dimensions, main
7
- from typing import Tuple
8
10
 
9
11
 
10
12
  def create_test_las_file(x: np.ndarray, y: np.ndarray, z: np.ndarray, dimensions: dict = None) -> Path:
@@ -236,8 +238,8 @@ def test_single_point():
236
238
  def test_main_function():
237
239
  """Test the main function with direct sys.argv"""
238
240
  import sys
239
- from io import StringIO
240
241
  from contextlib import redirect_stdout
242
+ from io import StringIO
241
243
 
242
244
  # Test with identical files
243
245
  points = 100
@@ -37,9 +37,9 @@ def test_remove_all_dimension():
37
37
  # get initial data
38
38
  points_ini = get_points(ini_las)
39
39
 
40
- with tempfile.NamedTemporaryFile(suffix="_add.las") as tmp_las:
40
+ with tempfile.NamedTemporaryFile(suffix="_add.las", delete_on_close=False) as tmp_las:
41
41
  append_dimension(ini_las, tmp_las.name)
42
- with tempfile.NamedTemporaryFile(suffix="_rm.las") as tmp_las_rm:
42
+ with tempfile.NamedTemporaryFile(suffix="_rm.las", delete_on_close=False) as tmp_las_rm:
43
43
  # remove all dimensions
44
44
  las_remove_dimensions.remove_dimensions_from_las(tmp_las.name, added_dimensions, tmp_las_rm.name)
45
45
  points_end = get_points(tmp_las_rm.name)
@@ -50,9 +50,9 @@ def test_remove_one_dimension():
50
50
  # get initial data
51
51
  points_ini = get_points(ini_las)
52
52
 
53
- with tempfile.NamedTemporaryFile(suffix="_add.las") as tmp_las:
53
+ with tempfile.NamedTemporaryFile(suffix="_add.las", delete_on_close=False) as tmp_las:
54
54
  append_dimension(ini_las, tmp_las.name)
55
- with tempfile.NamedTemporaryFile(suffix="_rm.las") as tmp_las_rm:
55
+ with tempfile.NamedTemporaryFile(suffix="_rm.las", delete_on_close=False) as tmp_las_rm:
56
56
  # remove one dimension
57
57
  las_remove_dimensions.remove_dimensions_from_las(tmp_las.name, ["DIM_1"], tmp_las_rm.name)
58
58
  points_end = get_points(tmp_las_rm.name)
@@ -1,13 +1,15 @@
1
+ import logging
1
2
  import os
2
- import pytest
3
+ import sys
3
4
  import tempfile
4
- import numpy as np
5
+
5
6
  import laspy
6
- import sys
7
- import logging
8
- from pdaltools.las_rename_dimension import rename_dimension, main
7
+ import numpy as np
8
+ import pytest
9
9
  from pyproj import CRS
10
10
 
11
+ from pdaltools.las_rename_dimension import main, rename_dimension
12
+
11
13
 
12
14
  def create_test_las_file():
13
15
  """Create a temporary LAS file with test data."""
@@ -72,24 +74,24 @@ def test_rename_dimension():
72
74
  def test_rename_nonexistent_dimension(caplog):
73
75
  """Test attempting to rename a dimension that doesn't exist."""
74
76
  input_file = create_test_las_file()
75
-
77
+
76
78
  with tempfile.NamedTemporaryFile(suffix=".las", delete=False) as tmp_file:
77
79
  output_file = tmp_file.name
78
-
79
- try:
80
- # Clear any existing log records
81
- caplog.clear()
82
-
83
- # Set the logging level to capture WARNING
84
- with caplog.at_level(logging.WARNING):
85
- rename_dimension(input_file, output_file, ["nonexistent_dim"], ["new_dim"])
86
-
87
- # Check that the warning was logged
88
- assert len(caplog.records) == 1
89
- assert "Dimension nonexistent_dim not found in input file" in caplog.records[0].message
90
- finally:
91
- os.unlink(input_file)
92
- os.unlink(output_file)
80
+
81
+ try:
82
+ # Clear any existing log records
83
+ caplog.clear()
84
+
85
+ # Set the logging level to capture WARNING
86
+ with caplog.at_level(logging.WARNING):
87
+ rename_dimension(input_file, output_file, ["nonexistent_dim"], ["new_dim"])
88
+
89
+ # Check that the warning was logged
90
+ assert len(caplog.records) == 1
91
+ assert "Dimension nonexistent_dim not found in input file" in caplog.records[0].message
92
+ finally:
93
+ os.unlink(input_file)
94
+ os.unlink(output_file)
93
95
 
94
96
 
95
97
  def test_rename_to_existing_dimension():
@@ -113,22 +115,21 @@ def test_rename_dimension_case_sensitive(caplog):
113
115
 
114
116
  with tempfile.NamedTemporaryFile(suffix=".las", delete=False) as tmp_file:
115
117
  output_file = tmp_file.name
116
-
117
- try:
118
- # Clear any existing log records
119
- caplog.clear()
120
-
121
- # Set the logging level to capture WARNING
122
- with caplog.at_level(logging.WARNING):
123
- rename_dimension(input_file, output_file, ["TEST_DIM"], ["new_dim"])
124
-
125
- # Check that the warning was logged
126
- assert len(caplog.records) == 1
127
- assert "Dimension TEST_DIM not found in input file" in caplog.records[0].message
128
- finally:
129
- os.unlink(input_file)
130
- os.unlink(output_file)
131
118
 
119
+ try:
120
+ # Clear any existing log records
121
+ caplog.clear()
122
+
123
+ # Set the logging level to capture WARNING
124
+ with caplog.at_level(logging.WARNING):
125
+ rename_dimension(input_file, output_file, ["TEST_DIM"], ["new_dim"])
126
+
127
+ # Check that the warning was logged
128
+ assert len(caplog.records) == 1
129
+ assert "Dimension TEST_DIM not found in input file" in caplog.records[0].message
130
+ finally:
131
+ os.unlink(input_file)
132
+ os.unlink(output_file)
132
133
 
133
134
 
134
135
  def test_rename_dimension_main():
@@ -1,15 +1,15 @@
1
1
  import os
2
2
 
3
3
  import pdal
4
- import pytest
5
4
 
6
5
  TEST_PATH = os.path.dirname(os.path.abspath(__file__))
7
6
 
8
- #this test files concatenate somes tests on PDAL features
9
- #it allows us to test the PDAL version used in the library is modern enough
7
+ # this test files concatenate somes tests on PDAL features
8
+ # it allows us to test the PDAL version used in the library is modern enough
9
+
10
10
 
11
11
  def test_pdal_read_severals_extra_dims():
12
- # test that we can read a las file with several extra dims
12
+ # test that we can read a las file with several extra dims
13
13
  test_file = os.path.join(TEST_PATH, "data/las_with_several_extra_byte_bloc.laz")
14
14
 
15
15
  pipeline = pdal.Reader.las(filename=test_file).pipeline()
@@ -3,17 +3,18 @@ import os
3
3
  import platform
4
4
  import shutil
5
5
  import subprocess as sp
6
+ import sys
6
7
  from test.utils import EXPECTED_DIMS_BY_DATAFORMAT, get_pdal_infos_summary
8
+
7
9
  import laspy
8
10
  import pdal
9
11
  import pytest
10
- import sys
11
12
 
12
13
  from pdaltools.count_occurences.count_occurences_for_attribute import (
13
14
  compute_count_one_file,
14
15
  )
15
- from pdaltools.standardize_format import standardize, main
16
16
  from pdaltools.las_comparison import compare_las_dimensions
17
+ from pdaltools.standardize_format import main, standardize
17
18
 
18
19
  TEST_PATH = os.path.dirname(os.path.abspath(__file__))
19
20
  TMP_PATH = os.path.join(TEST_PATH, "tmp")
@@ -277,7 +278,7 @@ def test_standardize_with_extra_dims_origin_and_dxm_marker():
277
278
 
278
279
  # check output file is same as input file for origin and dxm_marker
279
280
  result, _, _ = compare_las_dimensions(input_file, output_file, ["origin", "dsm_marker", "dtm_marker"])
280
- assert result == True
281
+ assert result is True
281
282
 
282
283
 
283
284
  def test_main_with_rename_dimensions():