cars 1.0.0a3__cp39-cp39-win_amd64.whl → 1.0.0a4__cp39-cp39-win_amd64.whl

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.

Potentially problematic release.


This version of cars might be problematic. Click here for more details.

Files changed (141) hide show
  1. cars/__init__.py +5 -5
  2. cars/applications/__init__.py +0 -3
  3. cars/applications/application_template.py +20 -0
  4. cars/applications/auxiliary_filling/abstract_auxiliary_filling_app.py +12 -2
  5. cars/applications/auxiliary_filling/auxiliary_filling_algo.py +2 -2
  6. cars/applications/auxiliary_filling/auxiliary_filling_from_sensors_app.py +80 -36
  7. cars/applications/dem_generation/dem_generation_algo.py +1 -1
  8. cars/applications/dem_generation/dem_generation_wrappers.py +23 -57
  9. cars/applications/dem_generation/dichotomic_generation_app.py +3 -3
  10. cars/applications/dem_generation/rasterization_app.py +100 -41
  11. cars/applications/dense_match_filling/__init__.py +1 -1
  12. cars/applications/dense_match_filling/abstract_dense_match_filling_app.py +2 -15
  13. cars/applications/dense_match_filling/fill_disp_algo.py +32 -373
  14. cars/applications/dense_match_filling/fill_disp_wrappers.py +0 -343
  15. cars/applications/dense_match_filling/zero_padding_app.py +10 -5
  16. cars/applications/dense_matching/abstract_dense_matching_app.py +2 -1
  17. cars/applications/dense_matching/census_mccnn_sgm_app.py +38 -39
  18. cars/applications/dense_matching/cpp/dense_matching_cpp.cp39-win_amd64.dll.a +0 -0
  19. cars/applications/dense_matching/cpp/dense_matching_cpp.cp39-win_amd64.pyd +0 -0
  20. cars/applications/dense_matching/dense_matching_algo.py +48 -14
  21. cars/applications/dense_matching/dense_matching_wrappers.py +11 -3
  22. cars/applications/dense_matching/disparity_grid_algo.py +84 -62
  23. cars/applications/dense_matching/loaders/pandora_loader.py +91 -33
  24. cars/applications/dsm_filling/border_interpolation_app.py +1 -7
  25. cars/applications/dsm_filling/bulldozer_filling_app.py +2 -8
  26. cars/applications/dsm_filling/exogenous_filling_app.py +4 -9
  27. cars/applications/grid_generation/abstract_grid_generation_app.py +1 -1
  28. cars/applications/grid_generation/epipolar_grid_generation_app.py +4 -2
  29. cars/applications/grid_generation/grid_correction_app.py +4 -1
  30. cars/applications/grid_generation/grid_generation_algo.py +7 -2
  31. cars/applications/ground_truth_reprojection/abstract_ground_truth_reprojection_app.py +1 -1
  32. cars/applications/ground_truth_reprojection/direct_localization_app.py +2 -2
  33. cars/applications/ground_truth_reprojection/ground_truth_reprojection_algo.py +2 -1
  34. cars/applications/point_cloud_fusion/abstract_pc_fusion_app.py +0 -155
  35. cars/applications/point_cloud_fusion/mapping_to_terrain_tiles_app.py +0 -658
  36. cars/applications/point_cloud_fusion/pc_fusion_algo.py +0 -1339
  37. cars/applications/point_cloud_fusion/pc_fusion_wrappers.py +0 -869
  38. cars/applications/point_cloud_outlier_removal/abstract_outlier_removal_app.py +2 -1
  39. cars/applications/point_cloud_outlier_removal/outlier_removal_algo.py +9 -8
  40. cars/applications/point_cloud_outlier_removal/small_components_app.py +96 -267
  41. cars/applications/point_cloud_outlier_removal/statistical_app.py +116 -275
  42. cars/applications/rasterization/abstract_pc_rasterization_app.py +1 -1
  43. cars/applications/rasterization/rasterization_algo.py +18 -6
  44. cars/applications/rasterization/rasterization_wrappers.py +2 -1
  45. cars/applications/rasterization/simple_gaussian_app.py +60 -113
  46. cars/applications/resampling/abstract_resampling_app.py +1 -1
  47. cars/applications/resampling/bicubic_resampling_app.py +3 -1
  48. cars/applications/resampling/resampling_algo.py +16 -4
  49. cars/applications/resampling/resampling_wrappers.py +3 -1
  50. cars/applications/sparse_matching/abstract_sparse_matching_app.py +1 -1
  51. cars/applications/sparse_matching/sift_app.py +3 -3
  52. cars/applications/sparse_matching/sparse_matching_algo.py +3 -2
  53. cars/applications/sparse_matching/sparse_matching_wrappers.py +1 -1
  54. cars/applications/triangulation/abstract_triangulation_app.py +1 -1
  55. cars/applications/triangulation/line_of_sight_intersection_app.py +13 -11
  56. cars/applications/triangulation/pc_transform.py +552 -0
  57. cars/applications/triangulation/triangulation_algo.py +6 -4
  58. cars/applications/triangulation/triangulation_wrappers.py +1 -0
  59. cars/bundleadjustment.py +6 -6
  60. cars/cars.py +11 -9
  61. cars/core/cars_logging.py +80 -49
  62. cars/core/constants.py +0 -1
  63. cars/core/datasets.py +5 -2
  64. cars/core/geometry/abstract_geometry.py +256 -25
  65. cars/core/geometry/shareloc_geometry.py +110 -82
  66. cars/core/inputs.py +57 -19
  67. cars/core/outputs.py +1 -1
  68. cars/core/preprocessing.py +17 -3
  69. cars/core/projection.py +9 -6
  70. cars/core/tiling.py +10 -3
  71. cars/data_structures/cars_dataset.py +5 -5
  72. cars/data_structures/corresponding_tiles_tools.py +0 -103
  73. cars/data_structures/format_transformation.py +4 -1
  74. cars/devibrate.py +6 -3
  75. cars/extractroi.py +20 -21
  76. cars/orchestrator/cluster/abstract_cluster.py +15 -5
  77. cars/orchestrator/cluster/abstract_dask_cluster.py +6 -2
  78. cars/orchestrator/cluster/dask_jobqueue_utils.py +1 -1
  79. cars/orchestrator/cluster/log_wrapper.py +148 -21
  80. cars/orchestrator/cluster/mp_cluster/multiprocessing_cluster.py +11 -3
  81. cars/orchestrator/cluster/mp_cluster/multiprocessing_profiler.py +2 -2
  82. cars/orchestrator/cluster/pbs_dask_cluster.py +1 -1
  83. cars/orchestrator/cluster/sequential_cluster.py +5 -4
  84. cars/orchestrator/cluster/slurm_dask_cluster.py +1 -1
  85. cars/orchestrator/orchestrator.py +14 -3
  86. cars/orchestrator/registry/id_generator.py +1 -0
  87. cars/orchestrator/registry/saver_registry.py +2 -2
  88. cars/pipelines/conf_resolution/conf_final_resolution.json +5 -3
  89. cars/pipelines/default/default_pipeline.py +462 -1073
  90. cars/pipelines/parameters/advanced_parameters.py +74 -64
  91. cars/pipelines/parameters/advanced_parameters_constants.py +2 -5
  92. cars/pipelines/parameters/application_parameters.py +71 -0
  93. cars/pipelines/parameters/depth_map_inputs.py +0 -314
  94. cars/pipelines/parameters/dsm_inputs.py +40 -4
  95. cars/pipelines/parameters/output_parameters.py +2 -2
  96. cars/pipelines/parameters/sensor_inputs.py +30 -75
  97. cars/pipelines/parameters/sensor_inputs_constants.py +0 -2
  98. cars/pipelines/parameters/sensor_loaders/__init__.py +4 -3
  99. cars/pipelines/parameters/sensor_loaders/basic_classif_loader.py +106 -0
  100. cars/pipelines/parameters/sensor_loaders/{basic_sensor_loader.py → basic_image_loader.py} +16 -22
  101. cars/pipelines/parameters/sensor_loaders/pivot_classif_loader.py +121 -0
  102. cars/pipelines/parameters/sensor_loaders/{pivot_sensor_loader.py → pivot_image_loader.py} +10 -21
  103. cars/pipelines/parameters/sensor_loaders/sensor_loader.py +4 -6
  104. cars/pipelines/parameters/sensor_loaders/sensor_loader_template.py +1 -3
  105. cars/pipelines/pipeline_template.py +1 -3
  106. cars/pipelines/unit/unit_pipeline.py +527 -1016
  107. cars/starter.py +4 -3
  108. cars-1.0.0a4.dist-info/DELVEWHEEL +2 -0
  109. {cars-1.0.0a3.dist-info → cars-1.0.0a4.dist-info}/METADATA +135 -53
  110. {cars-1.0.0a3.dist-info → cars-1.0.0a4.dist-info}/RECORD +116 -132
  111. cars.libs/.load-order-cars-1.0.0a4 +3 -0
  112. cars.libs/libgcc_s_seh-1-b2494fcbd4d80cf2c98fdd5261f6d850.dll +0 -0
  113. cars.libs/libstdc++-6-e9b0d12ae0e9555bbae55e8dfd08c3f7.dll +0 -0
  114. cars.libs/libwinpthread-1-7882d1b093714ccdfaf4e0789a817792.dll +0 -0
  115. cars/applications/dense_match_filling/cpp/__init__.py +0 -0
  116. cars/applications/dense_match_filling/cpp/dense_match_filling_cpp.cp39-win_amd64.dll.a +0 -0
  117. cars/applications/dense_match_filling/cpp/dense_match_filling_cpp.cp39-win_amd64.pyd +0 -0
  118. cars/applications/dense_match_filling/cpp/dense_match_filling_cpp.py +0 -72
  119. cars/applications/dense_match_filling/cpp/includes/dense_match_filling.hpp +0 -46
  120. cars/applications/dense_match_filling/cpp/meson.build +0 -9
  121. cars/applications/dense_match_filling/cpp/src/bindings.cpp +0 -11
  122. cars/applications/dense_match_filling/cpp/src/dense_match_filling.cpp +0 -142
  123. cars/applications/dense_match_filling/plane_app.py +0 -556
  124. cars/applications/hole_detection/__init__.py +0 -30
  125. cars/applications/hole_detection/abstract_hole_detection_app.py +0 -125
  126. cars/applications/hole_detection/cloud_to_bbox_app.py +0 -346
  127. cars/applications/hole_detection/hole_detection_algo.py +0 -144
  128. cars/applications/hole_detection/hole_detection_wrappers.py +0 -53
  129. cars/applications/point_cloud_denoising/__init__.py +0 -29
  130. cars/applications/point_cloud_denoising/abstract_pc_denoising_app.py +0 -273
  131. cars/applications/point_cloud_fusion/__init__.py +0 -30
  132. cars/applications/point_cloud_fusion/cloud_fusion_constants.py +0 -39
  133. cars/applications/sparse_matching/pandora_sparse_matching_app.py +0 -0
  134. cars/pipelines/parameters/depth_map_inputs_constants.py +0 -25
  135. cars-1.0.0a3.dist-info/DELVEWHEEL +0 -2
  136. cars.libs/.load-order-cars-1.0.0a3 +0 -3
  137. cars.libs/libgcc_s_seh-1-ca70890bbc5723b6d0ea31e9c9cded2b.dll +0 -0
  138. cars.libs/libstdc++-6-00ee19f73d5122a1277c137b1c218401.dll +0 -0
  139. cars.libs/libwinpthread-1-f5042e8e3d21edce20c1bc99445f551b.dll +0 -0
  140. {cars-1.0.0a3.dist-info → cars-1.0.0a4.dist-info}/WHEEL +0 -0
  141. {cars-1.0.0a3.dist-info → cars-1.0.0a4.dist-info}/entry_points.txt +0 -0
cars/__init__.py CHANGED
@@ -24,7 +24,7 @@ Cars module init file
24
24
 
25
25
 
26
26
  # start delvewheel patch
27
- def _delvewheel_patch_1_11_1():
27
+ def _delvewheel_patch_1_11_2():
28
28
  import ctypes
29
29
  import os
30
30
  import platform
@@ -35,10 +35,10 @@ def _delvewheel_patch_1_11_1():
35
35
  if os.path.isdir(libs_dir):
36
36
  os.add_dll_directory(libs_dir)
37
37
  else:
38
- load_order_filepath = os.path.join(libs_dir, '.load-order-cars-1.0.0a3')
38
+ load_order_filepath = os.path.join(libs_dir, '.load-order-cars-1.0.0a4')
39
39
  if os.path.isfile(load_order_filepath):
40
40
  import ctypes.wintypes
41
- with open(os.path.join(libs_dir, '.load-order-cars-1.0.0a3')) as file:
41
+ with open(os.path.join(libs_dir, '.load-order-cars-1.0.0a4')) as file:
42
42
  load_order = file.read().split()
43
43
  kernel32 = ctypes.WinDLL('kernel32', use_last_error=True)
44
44
  kernel32.LoadLibraryExW.restype = ctypes.wintypes.HMODULE
@@ -49,8 +49,8 @@ def _delvewheel_patch_1_11_1():
49
49
  raise OSError('Error loading {}; {}'.format(lib, ctypes.FormatError(ctypes.get_last_error())))
50
50
 
51
51
 
52
- _delvewheel_patch_1_11_1()
53
- del _delvewheel_patch_1_11_1
52
+ _delvewheel_patch_1_11_2()
53
+ del _delvewheel_patch_1_11_2
54
54
  # end delvewheel patch
55
55
 
56
56
  import os
@@ -30,9 +30,6 @@ from . import dense_matching # noqa: F401
30
30
  from . import dsm_filling # noqa: F401
31
31
  from . import grid_generation # noqa: F401
32
32
  from . import ground_truth_reprojection # noqa: F401
33
- from . import hole_detection # noqa: F401
34
- from . import point_cloud_denoising # noqa: F401
35
- from . import point_cloud_fusion # noqa: F401
36
33
  from . import point_cloud_outlier_removal # noqa: F401
37
34
  from . import rasterization # noqa: F401
38
35
  from . import resampling # noqa: F401
@@ -29,6 +29,7 @@ in sub application classes
29
29
 
30
30
  # Standard imports
31
31
  import logging
32
+ import os
32
33
  import pprint
33
34
  from abc import ABCMeta, abstractmethod
34
35
 
@@ -103,6 +104,25 @@ class ApplicationTemplate(metaclass=ABCMeta):
103
104
 
104
105
  return self.used_config
105
106
 
107
+ def generate_unknown_dump_dir(self, orchestrator):
108
+ """
109
+ Generate dump dir from orchestrator
110
+
111
+ :param orchestrator: orchestrator
112
+
113
+ :return: dump dir
114
+ """
115
+
116
+ dump_dir = None
117
+ if orchestrator is not None:
118
+ orch_out_dir = orchestrator.out_dir
119
+ dump_dir = os.path.join(
120
+ orch_out_dir,
121
+ "unknown_dump",
122
+ self.__class__.__bases__[0].__name__,
123
+ )
124
+ return dump_dir
125
+
106
126
 
107
127
  class ScalingApplicationTemplate(ApplicationTemplate, metaclass=ABCMeta):
108
128
  """
@@ -86,8 +86,18 @@ class AuxiliaryFilling(ApplicationTemplate, metaclass=ABCMeta):
86
86
  cls.available_applications[short_name] = cls
87
87
 
88
88
  @abstractmethod
89
- def run(
90
- self, dsm_file, color_file, classif_file, dump_dir, orchestrator=None
89
+ def run( # pylint: disable=too-many-positional-arguments
90
+ self,
91
+ dsm_file,
92
+ color_file,
93
+ classif_file,
94
+ dump_dir,
95
+ sensor_inputs,
96
+ pairing,
97
+ geom_plugin,
98
+ texture_bands,
99
+ output_geoid,
100
+ orchestrator=None,
91
101
  ):
92
102
  """
93
103
  Run Auxiliary filling
@@ -28,7 +28,7 @@ import rasterio as rio
28
28
  from scipy import interpolate
29
29
 
30
30
 
31
- def fill_auxiliary(
31
+ def fill_auxiliary( # pylint: disable=too-many-positional-arguments
32
32
  sensor_inputs,
33
33
  pairing,
34
34
  longitudes,
@@ -156,7 +156,7 @@ def fill_auxiliary(
156
156
  return filled_color, filled_classif
157
157
 
158
158
 
159
- def fill_from_one_sensor( # noqa C901
159
+ def fill_from_one_sensor( # pylint: disable=too-many-positional-arguments # noqa C901
160
160
  sensor,
161
161
  filled_color,
162
162
  filled_classif,
@@ -31,6 +31,8 @@ import rasterio as rio
31
31
  import xarray as xr
32
32
  from json_checker import Checker
33
33
  from pyproj import CRS
34
+ from rasterio.enums import Resampling
35
+ from rasterio.warp import reproject
34
36
  from shapely.geometry import Polygon
35
37
 
36
38
  import cars.orchestrator.orchestrator as ocht
@@ -94,10 +96,11 @@ class AuxiliaryFillingFromSensors(
94
96
  overloaded_conf["mode"] = conf.get("mode", "fill_nan")
95
97
 
96
98
  if overloaded_conf["mode"] not in ["fill_nan", "full"]:
99
+ # pylint: disable=inconsistent-quotes
97
100
  raise RuntimeError(
98
101
  f"Invalid mode {overloaded_conf['mode']} for "
99
- "AuxiliaryFilling, supported modes are fill_nan "
100
- "and full"
102
+ f"AuxiliaryFilling, supported modes are fill_nan "
103
+ f"and full"
101
104
  )
102
105
 
103
106
  overloaded_conf["texture_interpolator"] = conf.get(
@@ -126,7 +129,8 @@ class AuxiliaryFillingFromSensors(
126
129
 
127
130
  return overloaded_conf
128
131
 
129
- def run(
132
+ # pylint: disable=too-many-positional-arguments
133
+ def run( # noqa: C901
130
134
  self,
131
135
  dsm_file,
132
136
  color_file,
@@ -136,6 +140,7 @@ class AuxiliaryFillingFromSensors(
136
140
  pairing,
137
141
  geom_plugin,
138
142
  texture_bands,
143
+ output_geoid,
139
144
  orchestrator=None,
140
145
  ):
141
146
  """
@@ -158,6 +163,10 @@ class AuxiliaryFillingFromSensors(
158
163
  :type geom_plugin: AbstractGeometry
159
164
  :param texture_bands: list of band names used for output texture
160
165
  :type texture_bands: list
166
+ :param output_geoid: output geoid filename as vertical reference for the
167
+ input DSM. If a boolean is provided instead of a filename True means
168
+ defined relative to cars internal geoid, and false on ellipsoid
169
+ :type output_geoid: OR(bool, str)
161
170
  :param orchestrator: orchestrator used
162
171
  :type orchestrator: Orchestrator
163
172
  """
@@ -188,7 +197,7 @@ class AuxiliaryFillingFromSensors(
188
197
  os.makedirs(dump_dir)
189
198
 
190
199
  color_not_filled_file = os.path.join(dump_dir, "texture_not_filled.tif")
191
- if os.path.exists(color_file):
200
+ if color_file is not None and os.path.exists(color_file):
192
201
  shutil.move(color_file, color_not_filled_file)
193
202
 
194
203
  classification_not_filled_file = None
@@ -233,19 +242,20 @@ class AuxiliaryFillingFromSensors(
233
242
  color_dtype = np.float32
234
243
  classif_dtype = np.uint8
235
244
 
236
- if os.path.exists(color_not_filled_file):
237
- with rio.open(color_not_filled_file, "r") as descriptor:
238
- texture_no_data_value = descriptor.nodata
239
- color_dtype = descriptor.profile.get("dtype", np.float32)
240
-
241
- self.orchestrator.add_to_save_lists(
242
- os.path.join(dump_dir, color_file),
243
- cst.RASTER_COLOR_IMG,
244
- aux_filled_image,
245
- nodata=texture_no_data_value,
246
- dtype=color_dtype,
247
- cars_ds_name="filled_texture",
248
- )
245
+ if color_file is not None:
246
+ if os.path.exists(color_not_filled_file):
247
+ with rio.open(color_not_filled_file, "r") as descriptor:
248
+ texture_no_data_value = descriptor.nodata
249
+ color_dtype = descriptor.profile.get("dtype", np.float32)
250
+
251
+ self.orchestrator.add_to_save_lists(
252
+ os.path.join(dump_dir, color_file),
253
+ cst.RASTER_COLOR_IMG,
254
+ aux_filled_image,
255
+ nodata=texture_no_data_value,
256
+ dtype=color_dtype,
257
+ cars_ds_name="filled_texture",
258
+ )
249
259
 
250
260
  if classif_file is not None:
251
261
  if os.path.exists(classification_not_filled_file):
@@ -304,6 +314,7 @@ class AuxiliaryFillingFromSensors(
304
314
  full_saving_info,
305
315
  geom_plugin,
306
316
  texture_bands,
317
+ output_geoid,
307
318
  mode=self.used_config["mode"],
308
319
  texture_interpolator=self.used_config[
309
320
  "texture_interpolator"
@@ -319,6 +330,7 @@ class AuxiliaryFillingFromSensors(
319
330
  return aux_filled_image
320
331
 
321
332
 
333
+ # pylint: disable=too-many-positional-arguments
322
334
  def filling_from_sensor_wrapper(
323
335
  dsm_file,
324
336
  color_file,
@@ -332,6 +344,7 @@ def filling_from_sensor_wrapper(
332
344
  saving_info,
333
345
  geom_plugin,
334
346
  texture_bands,
347
+ output_geoid,
335
348
  mode,
336
349
  texture_interpolator,
337
350
  use_mask,
@@ -363,6 +376,10 @@ def filling_from_sensor_wrapper(
363
376
  :type geom_plugin: AbstractGeometry
364
377
  :param texture_bands: list of band names used for output texture
365
378
  :type texture_bands: list
379
+ :param output_geoid: output geoid filename as vertical reference for the
380
+ input DSM. If a boolean is provided instead of a filename True means
381
+ defined relative to cars internal geoid, and false on ellipsoid
382
+ :type output_geoid: OR(bool, str)
366
383
  :param mode: geometry plugin used for inverse locations
367
384
  :type mode: str
368
385
  :param texture_interpolator: scipy interpolator use to interpolate color
@@ -370,13 +387,17 @@ def filling_from_sensor_wrapper(
370
387
  :type texture_interpolator: str
371
388
  :param use_mask: use mask information from sensors in color computation
372
389
  :type use_mask: bool
373
-
374
390
  """
375
391
 
376
- col_min_ground = window["col_min"] * transform[0] + transform[2]
377
- col_max_ground = window["col_max"] * transform[0] + transform[2]
378
- row_min_ground = window["row_min"] * transform[4] + transform[5]
379
- row_max_ground = window["row_max"] * transform[4] + transform[5]
392
+ col_min = window["col_min"]
393
+ col_max = window["col_max"]
394
+ row_min = window["row_min"]
395
+ row_max = window["row_max"]
396
+
397
+ col_min_ground = col_min * transform[0] + transform[2]
398
+ col_max_ground = col_max * transform[0] + transform[2]
399
+ row_min_ground = row_min * transform[4] + transform[5]
400
+ row_max_ground = row_max * transform[4] + transform[5]
380
401
 
381
402
  ground_polygon = Polygon(
382
403
  [
@@ -388,15 +409,13 @@ def filling_from_sensor_wrapper(
388
409
  ]
389
410
  )
390
411
 
391
- cols = np.arange(
392
- col_min_ground,
393
- col_max_ground,
394
- transform[0],
412
+ cols = (
413
+ np.linspace(col_min, col_max, col_max - col_min) * transform[0]
414
+ + transform[2]
395
415
  )
396
- rows = np.arange(
397
- row_min_ground,
398
- row_max_ground,
399
- transform[4],
416
+ rows = (
417
+ np.linspace(row_min, row_max, row_max - row_min) * transform[4]
418
+ + transform[5]
400
419
  )
401
420
 
402
421
  cols_values_2d, rows_values_2d = np.meshgrid(cols, rows)
@@ -409,12 +428,12 @@ def filling_from_sensor_wrapper(
409
428
 
410
429
  rio_window = rio.windows.Window.from_slices(
411
430
  (
412
- window["row_min"],
413
- window["row_max"],
431
+ row_min,
432
+ row_max,
414
433
  ),
415
434
  (
416
- window["col_min"],
417
- window["col_max"],
435
+ col_min,
436
+ col_max,
418
437
  ),
419
438
  )
420
439
 
@@ -428,6 +447,28 @@ def filling_from_sensor_wrapper(
428
447
  target_mask = dsm_image.read_masks(1, window=rio_window)
429
448
  dsm_profile = dsm_image.profile
430
449
 
450
+ if output_geoid:
451
+ if output_geoid is True:
452
+ geoid_file = geom_plugin.geoid
453
+ else:
454
+ geoid_file = output_geoid
455
+ with rio.open(geoid_file) as in_geoid:
456
+ # Reproject the geoid data to match the DSM
457
+ output_geoid_data = np.empty(
458
+ alt_values.shape, dtype=in_geoid.dtypes[0]
459
+ )
460
+
461
+ reproject(
462
+ source=rio.band(in_geoid, 1),
463
+ destination=output_geoid_data,
464
+ src_transform=in_geoid.transform,
465
+ src_crs=in_geoid.crs,
466
+ dst_transform=transform,
467
+ dst_crs=crs,
468
+ resampling=Resampling.bilinear,
469
+ )
470
+ alt_values += output_geoid_data
471
+
431
472
  nodata_color = None
432
473
  nodata_classif = None
433
474
 
@@ -543,8 +584,8 @@ def filling_from_sensor_wrapper(
543
584
  classification_values_filled[band_index, :],
544
585
  )
545
586
 
546
- row_arr = np.array(range(window["row_min"], window["row_max"]))
547
- col_arr = np.array(range(window["col_min"], window["col_max"]))
587
+ row_arr = np.array(range(row_min, row_max))
588
+ col_arr = np.array(range(col_min, col_max))
548
589
 
549
590
  values = {}
550
591
  coords = {cst.ROW: row_arr, cst.COL: col_arr}
@@ -573,6 +614,9 @@ def filling_from_sensor_wrapper(
573
614
  values,
574
615
  coords=coords,
575
616
  )
617
+
618
+ profile.update(crs=crs.to_wkt())
619
+
576
620
  cars_dataset.fill_dataset(
577
621
  dataset,
578
622
  saving_info=saving_info,
@@ -108,7 +108,7 @@ def launch_bulldozer(
108
108
  return output_dem
109
109
 
110
110
 
111
- def multi_res_rec(
111
+ def multi_res_rec( # pylint: disable=too-many-positional-arguments
112
112
  pd_pc,
113
113
  list_fun,
114
114
  x_grid,
@@ -26,7 +26,6 @@ import logging
26
26
  import os
27
27
 
28
28
  import numpy as np
29
- import pyproj
30
29
  import rasterio as rio
31
30
  import xdem
32
31
 
@@ -37,8 +36,6 @@ from rasterio.enums import Resampling
37
36
  from rasterio.warp import calculate_default_transform, reproject
38
37
  from scipy.ndimage import median_filter
39
38
 
40
- from cars.core import preprocessing
41
-
42
39
 
43
40
  def fit_initial_elevation_on_dem_median(
44
41
  dem_to_fit_path: str, dem_ref_path: str, dem_out_path: str
@@ -136,7 +133,7 @@ def add_margin(bbox, ratio=1):
136
133
  return new_bbox
137
134
 
138
135
 
139
- def generate_grid(
136
+ def generate_grid( # pylint: disable=too-many-positional-arguments
140
137
  pd_pc, resolution, xmin=None, xmax=None, ymin=None, ymax=None
141
138
  ):
142
139
  """
@@ -247,7 +244,8 @@ def reverse_dem(input_dem):
247
244
  def downsample_dem(
248
245
  input_dem,
249
246
  scale,
250
- median_filter_size=7,
247
+ interpolator,
248
+ median_filter_size=None,
251
249
  default_alt=0,
252
250
  ):
253
251
  """
@@ -272,6 +270,13 @@ def downsample_dem(
272
270
  metadata["height"] = dst_height
273
271
  metadata["width"] = dst_width
274
272
  dem_data = np.zeros((dst_height, dst_width))
273
+ interpolator_dict = {
274
+ "min": Resampling.min,
275
+ "median": Resampling.med,
276
+ "max": Resampling.max,
277
+ "nearest": Resampling.nearest,
278
+ }
279
+ interpolator = interpolator_dict[interpolator]
275
280
  reproject(
276
281
  data,
277
282
  dem_data,
@@ -280,13 +285,14 @@ def downsample_dem(
280
285
  dst_transform=dst_transform,
281
286
  dst_crs=crs,
282
287
  dst_nodata=nodata,
283
- resampling=Resampling.med,
288
+ resampling=interpolator,
284
289
  )
285
290
 
286
291
  # Post-processing
287
292
 
288
293
  # Median filter
289
- dem_data = median_filter(dem_data, size=median_filter_size)
294
+ if median_filter_size is not None:
295
+ dem_data = median_filter(dem_data, size=median_filter_size)
290
296
 
291
297
  # Fill nodata
292
298
  dem_data = rio.fill.fillnodata(
@@ -300,65 +306,25 @@ def downsample_dem(
300
306
  dst.write(dem_data, 1)
301
307
 
302
308
 
303
- def modify_terrain_bounds(
304
- bounds_poly, in_epsg, out_epsg, constant_margin, linear_margin=0
305
- ):
309
+ def modify_terrain_bounds(terrain_bounds, linear_margin, constant_margin):
306
310
  """
307
311
  Modify the terrain bounds
308
312
 
309
- :param bounds_poly: Input region of interest for DEM
310
- :type bounds_poly: list
311
- :param in_epsg: EPSG code of dem_roi_to_use
312
- :type in_epsg: int
313
- :param out_epsg: EPSG code of dem_roi_to_use
314
- :type out_epsg: int
313
+ :param terrain_bounds: Input region of interest for DEM
314
+ :type terrain_bounds: list
315
315
  :param margin: Margin of the output ROI in meters
316
316
  :type margin: int
317
317
  """
318
- # Get bounds
319
- xmin = min(bounds_poly[0], bounds_poly[2])
320
- xmax = max(bounds_poly[0], bounds_poly[2])
321
- ymin = min(bounds_poly[1], bounds_poly[3])
322
- ymax = max(bounds_poly[1], bounds_poly[3])
323
-
324
- bounds_cloud = [xmin, ymin, xmax, ymax]
325
-
326
- if in_epsg == 4326:
327
- # Convert resolution and margin to degrees
328
- utm_epsg = preprocessing.get_utm_zone_as_epsg_code(xmin, ymin)
329
- conversion_factor = preprocessing.get_conversion_factor(
330
- bounds_cloud, 4326, utm_epsg
331
- )
332
- constant_margin *= conversion_factor
333
-
334
- # Get borders, adding margin
335
- xmin = xmin - constant_margin - linear_margin * (xmax - xmin)
336
- ymin = ymin - constant_margin - linear_margin * (ymax - ymin)
337
- xmax = xmax + constant_margin + linear_margin * (xmax - xmin)
338
- ymax = ymax + constant_margin + linear_margin * (ymax - ymin)
318
+ xsize = terrain_bounds[2] - terrain_bounds[0]
319
+ ysize = terrain_bounds[3] - terrain_bounds[1]
320
+ xmin = terrain_bounds[0] - linear_margin * xsize - constant_margin
321
+ ymin = terrain_bounds[1] - linear_margin * ysize - constant_margin
322
+ xmax = terrain_bounds[2] + linear_margin * xsize + constant_margin
323
+ ymax = terrain_bounds[3] + linear_margin * ysize + constant_margin
339
324
 
340
325
  terrain_bounds = [xmin, ymin, xmax, ymax]
341
326
 
342
- if out_epsg != in_epsg:
343
- crs_in = pyproj.CRS.from_epsg(in_epsg)
344
- crs_out = pyproj.CRS.from_epsg(out_epsg)
345
-
346
- transformer = pyproj.Transformer.from_crs(
347
- crs_in, crs_out, always_xy=True
348
- )
349
-
350
- xymin = transformer.transform(terrain_bounds[0], terrain_bounds[1])
351
- xymax = transformer.transform(terrain_bounds[2], terrain_bounds[3])
352
-
353
- xmin, ymin = xymin if isinstance(xymin, tuple) else (None, None)
354
- xmax, ymax = xymax if isinstance(xymax, tuple) else (None, None)
355
-
356
- if None in (xmin, ymin, xmax, ymax):
357
- raise RuntimeError("An error occured during the projection")
358
-
359
- new_terrain_bounds = [xmin, ymin, xmax, ymax]
360
-
361
- return new_terrain_bounds
327
+ return terrain_bounds
362
328
 
363
329
 
364
330
  def reproject_dem(dsm_file_name, epsg_out, out_file_name):
@@ -129,7 +129,7 @@ class DichotomicGeneration(DemGeneration, short_name="dichotomic"):
129
129
  overloaded_conf["resolution"] = conf.get("resolution", 90)
130
130
  # default margin: (z max - zmin) * tan(teta)
131
131
  # with z max = 9000, z min = 0, teta = 30 degrees
132
- overloaded_conf["margin"] = conf.get("margin", 6000)
132
+ overloaded_conf["margin"] = conf.get("margin", [0, 6000])
133
133
  overloaded_conf["height_margin"] = conf.get("height_margin", 20)
134
134
  overloaded_conf["percentile"] = conf.get("percentile", 1)
135
135
  overloaded_conf["min_number_matches"] = conf.get(
@@ -154,7 +154,7 @@ class DichotomicGeneration(DemGeneration, short_name="dichotomic"):
154
154
  rectification_schema = {
155
155
  "method": str,
156
156
  "resolution": And(Or(float, int), lambda x: x > 0),
157
- "margin": And(Or(float, int), lambda x: x > 0),
157
+ "margin": [Or(float, int)],
158
158
  "height_margin": Or(list, int),
159
159
  "percentile": And(Or(int, float), lambda x: x >= 0),
160
160
  "min_number_matches": And(int, lambda x: x > 0),
@@ -173,7 +173,7 @@ class DichotomicGeneration(DemGeneration, short_name="dichotomic"):
173
173
  return overloaded_conf
174
174
 
175
175
  @cars_profile(name="DEM Generation")
176
- def run(
176
+ def run( # pylint: disable=too-many-positional-arguments
177
177
  self,
178
178
  triangulated_matches_list,
179
179
  output_dir,