cars 1.0.0a2__cp312-cp312-win_amd64.whl → 1.0.0a4__cp312-cp312-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 (144) hide show
  1. cars/__init__.py +3 -3
  2. cars/applications/__init__.py +0 -3
  3. cars/applications/application.py +14 -6
  4. cars/applications/application_template.py +42 -0
  5. cars/applications/auxiliary_filling/abstract_auxiliary_filling_app.py +12 -2
  6. cars/applications/auxiliary_filling/auxiliary_filling_algo.py +2 -2
  7. cars/applications/auxiliary_filling/auxiliary_filling_from_sensors_app.py +95 -46
  8. cars/applications/auxiliary_filling/auxiliary_filling_wrappers.py +7 -6
  9. cars/applications/dem_generation/abstract_dem_generation_app.py +9 -5
  10. cars/applications/dem_generation/dem_generation_algo.py +1 -1
  11. cars/applications/dem_generation/dem_generation_wrappers.py +44 -59
  12. cars/applications/dem_generation/dichotomic_generation_app.py +9 -6
  13. cars/applications/dem_generation/rasterization_app.py +112 -43
  14. cars/applications/dense_match_filling/__init__.py +1 -1
  15. cars/applications/dense_match_filling/abstract_dense_match_filling_app.py +2 -15
  16. cars/applications/dense_match_filling/fill_disp_algo.py +32 -373
  17. cars/applications/dense_match_filling/fill_disp_wrappers.py +0 -343
  18. cars/applications/dense_match_filling/zero_padding_app.py +10 -5
  19. cars/applications/dense_matching/abstract_dense_matching_app.py +2 -1
  20. cars/applications/dense_matching/census_mccnn_sgm_app.py +48 -60
  21. cars/applications/dense_matching/cpp/dense_matching_cpp.cp312-win_amd64.dll.a +0 -0
  22. cars/applications/dense_matching/cpp/dense_matching_cpp.cp312-win_amd64.pyd +0 -0
  23. cars/applications/dense_matching/dense_matching_algo.py +48 -14
  24. cars/applications/dense_matching/dense_matching_wrappers.py +11 -3
  25. cars/applications/dense_matching/disparity_grid_algo.py +95 -79
  26. cars/applications/dense_matching/loaders/config_mapping.json +13 -0
  27. cars/applications/dense_matching/loaders/global_land_cover_map.tif +0 -0
  28. cars/applications/dense_matching/loaders/pandora_loader.py +169 -34
  29. cars/applications/dsm_filling/border_interpolation_app.py +11 -12
  30. cars/applications/dsm_filling/bulldozer_filling_app.py +16 -15
  31. cars/applications/dsm_filling/exogenous_filling_app.py +14 -14
  32. cars/applications/grid_generation/abstract_grid_generation_app.py +1 -1
  33. cars/applications/grid_generation/epipolar_grid_generation_app.py +4 -2
  34. cars/applications/grid_generation/grid_correction_app.py +4 -1
  35. cars/applications/grid_generation/grid_generation_algo.py +7 -2
  36. cars/applications/ground_truth_reprojection/abstract_ground_truth_reprojection_app.py +1 -1
  37. cars/applications/ground_truth_reprojection/direct_localization_app.py +2 -2
  38. cars/applications/ground_truth_reprojection/ground_truth_reprojection_algo.py +2 -1
  39. cars/applications/point_cloud_fusion/abstract_pc_fusion_app.py +0 -155
  40. cars/applications/point_cloud_fusion/mapping_to_terrain_tiles_app.py +0 -658
  41. cars/applications/point_cloud_fusion/pc_fusion_algo.py +0 -1339
  42. cars/applications/point_cloud_fusion/pc_fusion_wrappers.py +0 -869
  43. cars/applications/point_cloud_outlier_removal/abstract_outlier_removal_app.py +11 -6
  44. cars/applications/point_cloud_outlier_removal/outlier_removal_algo.py +9 -8
  45. cars/applications/point_cloud_outlier_removal/small_components_app.py +101 -270
  46. cars/applications/point_cloud_outlier_removal/statistical_app.py +120 -277
  47. cars/applications/rasterization/abstract_pc_rasterization_app.py +2 -1
  48. cars/applications/rasterization/rasterization_algo.py +18 -6
  49. cars/applications/rasterization/rasterization_wrappers.py +2 -1
  50. cars/applications/rasterization/simple_gaussian_app.py +88 -116
  51. cars/applications/resampling/abstract_resampling_app.py +1 -1
  52. cars/applications/resampling/bicubic_resampling_app.py +3 -1
  53. cars/applications/resampling/resampling_algo.py +60 -53
  54. cars/applications/resampling/resampling_wrappers.py +3 -1
  55. cars/applications/sparse_matching/abstract_sparse_matching_app.py +1 -1
  56. cars/applications/sparse_matching/sift_app.py +5 -25
  57. cars/applications/sparse_matching/sparse_matching_algo.py +3 -2
  58. cars/applications/sparse_matching/sparse_matching_wrappers.py +1 -1
  59. cars/applications/triangulation/abstract_triangulation_app.py +1 -1
  60. cars/applications/triangulation/line_of_sight_intersection_app.py +13 -11
  61. cars/applications/triangulation/pc_transform.py +552 -0
  62. cars/applications/triangulation/triangulation_algo.py +6 -4
  63. cars/applications/triangulation/triangulation_wrappers.py +1 -0
  64. cars/bundleadjustment.py +6 -6
  65. cars/cars.py +11 -9
  66. cars/core/cars_logging.py +80 -49
  67. cars/core/constants.py +0 -1
  68. cars/core/datasets.py +5 -2
  69. cars/core/geometry/abstract_geometry.py +364 -22
  70. cars/core/geometry/shareloc_geometry.py +112 -82
  71. cars/core/inputs.py +72 -19
  72. cars/core/outputs.py +1 -1
  73. cars/core/preprocessing.py +17 -3
  74. cars/core/projection.py +126 -6
  75. cars/core/tiling.py +10 -3
  76. cars/data_structures/cars_dataset.py +12 -10
  77. cars/data_structures/corresponding_tiles_tools.py +0 -103
  78. cars/data_structures/format_transformation.py +4 -1
  79. cars/devibrate.py +6 -3
  80. cars/extractroi.py +20 -21
  81. cars/orchestrator/cluster/abstract_cluster.py +15 -5
  82. cars/orchestrator/cluster/abstract_dask_cluster.py +6 -2
  83. cars/orchestrator/cluster/dask_jobqueue_utils.py +1 -1
  84. cars/orchestrator/cluster/log_wrapper.py +149 -22
  85. cars/orchestrator/cluster/mp_cluster/multiprocessing_cluster.py +12 -4
  86. cars/orchestrator/cluster/mp_cluster/multiprocessing_profiler.py +2 -2
  87. cars/orchestrator/cluster/pbs_dask_cluster.py +1 -1
  88. cars/orchestrator/cluster/sequential_cluster.py +5 -4
  89. cars/orchestrator/cluster/slurm_dask_cluster.py +1 -1
  90. cars/orchestrator/orchestrator.py +15 -4
  91. cars/orchestrator/registry/id_generator.py +1 -0
  92. cars/orchestrator/registry/saver_registry.py +2 -2
  93. cars/pipelines/conf_resolution/conf_final_resolution.json +5 -3
  94. cars/pipelines/default/default_pipeline.py +461 -1052
  95. cars/pipelines/parameters/advanced_parameters.py +91 -64
  96. cars/pipelines/parameters/advanced_parameters_constants.py +6 -5
  97. cars/pipelines/parameters/application_parameters.py +71 -0
  98. cars/pipelines/parameters/depth_map_inputs.py +0 -314
  99. cars/pipelines/parameters/dsm_inputs.py +40 -4
  100. cars/pipelines/parameters/output_parameters.py +44 -8
  101. cars/pipelines/parameters/sensor_inputs.py +122 -73
  102. cars/pipelines/parameters/sensor_inputs_constants.py +0 -2
  103. cars/pipelines/parameters/sensor_loaders/__init__.py +4 -3
  104. cars/pipelines/parameters/sensor_loaders/basic_classif_loader.py +106 -0
  105. cars/pipelines/parameters/sensor_loaders/{basic_sensor_loader.py → basic_image_loader.py} +16 -22
  106. cars/pipelines/parameters/sensor_loaders/pivot_classif_loader.py +121 -0
  107. cars/pipelines/parameters/sensor_loaders/{pivot_sensor_loader.py → pivot_image_loader.py} +10 -21
  108. cars/pipelines/parameters/sensor_loaders/sensor_loader.py +4 -6
  109. cars/pipelines/parameters/sensor_loaders/sensor_loader_template.py +1 -3
  110. cars/pipelines/pipeline_template.py +1 -3
  111. cars/pipelines/unit/unit_pipeline.py +676 -1070
  112. cars/starter.py +4 -3
  113. cars-1.0.0a4.dist-info/DELVEWHEEL +2 -0
  114. {cars-1.0.0a2.dist-info → cars-1.0.0a4.dist-info}/METADATA +135 -53
  115. {cars-1.0.0a2.dist-info → cars-1.0.0a4.dist-info}/RECORD +120 -134
  116. cars.libs/libgcc_s_seh-1-b2494fcbd4d80cf2c98fdd5261f6d850.dll +0 -0
  117. cars.libs/libstdc++-6-e9b0d12ae0e9555bbae55e8dfd08c3f7.dll +0 -0
  118. cars.libs/libwinpthread-1-7882d1b093714ccdfaf4e0789a817792.dll +0 -0
  119. cars/applications/dense_match_filling/cpp/__init__.py +0 -0
  120. cars/applications/dense_match_filling/cpp/dense_match_filling_cpp.cp312-win_amd64.dll.a +0 -0
  121. cars/applications/dense_match_filling/cpp/dense_match_filling_cpp.cp312-win_amd64.pyd +0 -0
  122. cars/applications/dense_match_filling/cpp/dense_match_filling_cpp.py +0 -72
  123. cars/applications/dense_match_filling/cpp/includes/dense_match_filling.hpp +0 -46
  124. cars/applications/dense_match_filling/cpp/meson.build +0 -9
  125. cars/applications/dense_match_filling/cpp/src/bindings.cpp +0 -11
  126. cars/applications/dense_match_filling/cpp/src/dense_match_filling.cpp +0 -142
  127. cars/applications/dense_match_filling/plane_app.py +0 -556
  128. cars/applications/hole_detection/__init__.py +0 -30
  129. cars/applications/hole_detection/abstract_hole_detection_app.py +0 -125
  130. cars/applications/hole_detection/cloud_to_bbox_app.py +0 -346
  131. cars/applications/hole_detection/hole_detection_algo.py +0 -144
  132. cars/applications/hole_detection/hole_detection_wrappers.py +0 -53
  133. cars/applications/point_cloud_denoising/__init__.py +0 -29
  134. cars/applications/point_cloud_denoising/abstract_pc_denoising_app.py +0 -273
  135. cars/applications/point_cloud_fusion/__init__.py +0 -30
  136. cars/applications/point_cloud_fusion/cloud_fusion_constants.py +0 -39
  137. cars/applications/sparse_matching/pandora_sparse_matching_app.py +0 -0
  138. cars/pipelines/parameters/depth_map_inputs_constants.py +0 -25
  139. cars-1.0.0a2.dist-info/DELVEWHEEL +0 -2
  140. cars.libs/libgcc_s_seh-1-f2b6825d483bdf14050493af93b5997d.dll +0 -0
  141. cars.libs/libstdc++-6-6b0059df6bc601df5a0f18a5805eea05.dll +0 -0
  142. cars.libs/libwinpthread-1-e01b8e85fd67c2b861f64d4ccc7df607.dll +0 -0
  143. {cars-1.0.0a2.dist-info → cars-1.0.0a4.dist-info}/WHEEL +0 -0
  144. {cars-1.0.0a2.dist-info → cars-1.0.0a4.dist-info}/entry_points.txt +0 -0
@@ -24,18 +24,18 @@ Used for full_res and low_res pipelines
24
24
  """
25
25
 
26
26
  import logging
27
+ import math
27
28
  import os
28
29
 
30
+ import numpy as np
29
31
  import rasterio as rio
30
- from json_checker import Checker, OptionalKey, Or
32
+ from json_checker import Checker, Or
31
33
 
32
34
  # CARS imports
33
- from cars.core import inputs, preprocessing, roi_tools
35
+ from cars.core import inputs, projection
34
36
  from cars.core.geometry.abstract_geometry import AbstractGeometry
35
37
  from cars.core.utils import make_relative_path_absolute
36
- from cars.pipelines.parameters import (
37
- depth_map_inputs_constants as depth_map_cst,
38
- )
38
+ from cars.orchestrator.cluster.log_wrapper import cars_profile
39
39
  from cars.pipelines.parameters import sensor_inputs_constants as sens_cst
40
40
  from cars.pipelines.parameters.sensor_loaders.sensor_loader import SensorLoader
41
41
 
@@ -68,7 +68,6 @@ def sensors_check_inputs(conf, config_dir=None): # noqa: C901
68
68
  sens_cst.PAIRING: Or([[str]], None),
69
69
  sens_cst.INITIAL_ELEVATION: Or(str, dict, None),
70
70
  sens_cst.ROI: Or(str, dict, None),
71
- OptionalKey(depth_map_cst.DEPTH_MAPS): dict,
72
71
  }
73
72
 
74
73
  checker_inputs = Checker(inputs_schema)
@@ -111,12 +110,12 @@ def check_sensors(conf, overloaded_conf, config_dir=None): # noqa: C901
111
110
  sens_cst.INPUT_IMG, None
112
111
  )
113
112
  if isinstance(image, str):
114
- loader_name = "basic"
113
+ loader_name = "basic_image"
115
114
  elif isinstance(image, dict):
116
- loader_name = image.get("loader", "basic")
115
+ loader_name = image.get("loader", "basic_image")
117
116
  else:
118
117
  raise TypeError(f"Image {image} is not of type str or dict")
119
- image_loader = SensorLoader(loader_name, image, "image", config_dir)
118
+ image_loader = SensorLoader(loader_name, image, config_dir)
120
119
  image_as_pivot_format = (
121
120
  image_loader.get_pivot_format() # pylint: disable=E1101
122
121
  )
@@ -145,14 +144,12 @@ def check_sensors(conf, overloaded_conf, config_dir=None): # noqa: C901
145
144
  )
146
145
  if classif is not None:
147
146
  if isinstance(classif, str):
148
- loader_name = "basic"
147
+ loader_name = "basic_classif"
149
148
  elif isinstance(classif, dict):
150
- loader_name = classif.get("loader", "basic")
149
+ loader_name = classif.get("loader", "basic_classif")
151
150
  else:
152
151
  raise TypeError(f"Classif {classif} is not of type str or dict")
153
- classif_loader = SensorLoader(
154
- loader_name, classif, "classification", config_dir
155
- )
152
+ classif_loader = SensorLoader(loader_name, classif, config_dir)
156
153
  classif_as_pivot_format = (
157
154
  classif_loader.get_pivot_format() # pylint: disable=E1101
158
155
  )
@@ -235,7 +232,68 @@ def check_sensors(conf, overloaded_conf, config_dir=None): # noqa: C901
235
232
  return overloaded_conf
236
233
 
237
234
 
238
- def check_geometry_plugin(conf_inputs, conf_geom_plugin):
235
+ def get_sensor_resolution(
236
+ geom_plugin, sensor_path, geomodel, target_epsg=32631
237
+ ):
238
+ """
239
+ Estimate the sensor image resolution in meters per pixel
240
+ using geolocation of 3 corners of the image.
241
+
242
+ :param geom_plugin: geometry plugin instance
243
+ :param sensor_path: path to the sensor image
244
+ :type sensor_path: dict
245
+ :param geomodel: geometric model for the sensor image
246
+ :param target_epsg: target EPSG code for projection
247
+ :type target_epsg: int
248
+ :return: average resolution in meters/pixel along x and y
249
+ :rtype: float
250
+ """
251
+ width, height = inputs.rasterio_get_size(sensor_path[sens_cst.MAIN_FILE])
252
+
253
+ upper_left = (0.5, 0.5)
254
+ upper_right = (width - 0.5, 0.5)
255
+ bottom_left = (0.5, height - 0.5)
256
+
257
+ # get geodetic coordinates
258
+ lat_ul, lon_ul, _ = geom_plugin.direct_loc(
259
+ sensor_path[sens_cst.MAIN_FILE],
260
+ geomodel,
261
+ np.array([upper_left[0]]),
262
+ np.array([upper_left[1]]),
263
+ )
264
+ lat_ur, lon_ur, _ = geom_plugin.direct_loc(
265
+ sensor_path[sens_cst.MAIN_FILE],
266
+ geomodel,
267
+ np.array([upper_right[0]]),
268
+ np.array([upper_right[1]]),
269
+ )
270
+ lat_bl, lon_bl, _ = geom_plugin.direct_loc(
271
+ sensor_path[sens_cst.MAIN_FILE],
272
+ geomodel,
273
+ np.array([bottom_left[0]]),
274
+ np.array([bottom_left[1]]),
275
+ )
276
+
277
+ coords_ll = np.array(
278
+ [[lon_ul, lat_ul, 0], [lon_ur, lat_ur, 0], [lon_bl, lat_bl, 0]]
279
+ )
280
+
281
+ # Convert to target CRS
282
+ coords_xy = projection.point_cloud_conversion(coords_ll, 4326, target_epsg)
283
+
284
+ diff_x = np.linalg.norm(coords_xy[1] - coords_xy[0]) # UL to UR (width)
285
+ diff_y = np.linalg.norm(coords_xy[2] - coords_xy[0]) # UL to BL (height)
286
+
287
+ # resolution in meters per pixel
288
+ res_x = diff_x / (width - 1)
289
+ res_y = diff_y / (height - 1)
290
+
291
+ return (res_x + res_y) / 2
292
+
293
+
294
+ def check_geometry_plugin(
295
+ conf_inputs, conf_geom_plugin, epipolar_resolution, output_dem_dir
296
+ ):
239
297
  """
240
298
  Check the geometry plugin with inputs
241
299
 
@@ -245,6 +303,8 @@ def check_geometry_plugin(conf_inputs, conf_geom_plugin):
245
303
  :type conf_advanced: type
246
304
  :param conf_geom_plugin: name of geometry plugin
247
305
  :type conf_geom_plugin: str
306
+ :param epipolar_resolution: epipolar resolution
307
+ :type epipolar_resolution: int
248
308
  :return: overload inputs conf
249
309
  overloaded geometry plugin conf
250
310
  geometry plugin without dem
@@ -253,11 +313,41 @@ def check_geometry_plugin(conf_inputs, conf_geom_plugin):
253
313
  if conf_geom_plugin is None:
254
314
  conf_geom_plugin = "SharelocGeometry"
255
315
 
316
+ # Initialize a temporary plugin, to get the product's resolution
317
+ temp_geom_plugin = (
318
+ AbstractGeometry( # pylint: disable=abstract-class-instantiated
319
+ conf_geom_plugin,
320
+ default_alt=sens_cst.CARS_DEFAULT_ALT,
321
+ )
322
+ )
323
+ average_sensor_resolution = 0
324
+ for _, sensor_image in conf_inputs[sens_cst.SENSORS].items():
325
+ sensor = sensor_image[sens_cst.INPUT_IMG]
326
+ geomodel = sensor_image[sens_cst.INPUT_GEO_MODEL]
327
+ (
328
+ sensor,
329
+ geomodel,
330
+ ) = temp_geom_plugin.check_product_consistency(sensor, geomodel)
331
+ average_sensor_resolution += (
332
+ get_sensor_resolution(temp_geom_plugin, sensor, geomodel)
333
+ * epipolar_resolution
334
+ )
335
+ average_sensor_resolution /= len(conf_inputs[sens_cst.SENSORS])
336
+ # approximate resolution to the highest digit:
337
+ # 0.47 -> 0.5
338
+ # 7.52 -> 8
339
+ # 12.9 -> 10
340
+ nb_digits = int(math.floor(math.log10(abs(average_sensor_resolution))))
341
+ scaling_coeff = round(average_sensor_resolution, -nb_digits)
342
+ # make it so 0.5 (CO3D) is the baseline for parameters
343
+ scaling_coeff *= 2
344
+
256
345
  # Initialize the desired geometry plugin without elevation information
257
346
  geom_plugin_without_dem_and_geoid = (
258
347
  AbstractGeometry( # pylint: disable=abstract-class-instantiated
259
348
  conf_geom_plugin,
260
349
  default_alt=sens_cst.CARS_DEFAULT_ALT,
350
+ scaling_coeff=scaling_coeff,
261
351
  )
262
352
  )
263
353
 
@@ -280,75 +370,29 @@ def check_geometry_plugin(conf_inputs, conf_geom_plugin):
280
370
  ] = geomodel
281
371
 
282
372
  geom_plugin_with_dem_and_geoid = generate_geometry_plugin_with_dem(
283
- conf_geom_plugin, conf_inputs
373
+ conf_geom_plugin,
374
+ conf_inputs,
375
+ scaling_coeff=scaling_coeff,
376
+ output_dem_dir=output_dem_dir,
284
377
  )
285
378
 
286
- # Check dem is big enough
287
- dem_generation_roi_poly = None
288
- needed_dem_roi = geom_plugin_with_dem_and_geoid.dem_roi
289
- needed_dem_roi_epsg = geom_plugin_with_dem_and_geoid.dem_roi_epsg
290
- if needed_dem_roi is not None:
291
- needed_dem_roi_poly = roi_tools.bounds_to_poly(needed_dem_roi)
292
- # convert to 4326 roi
293
- dem_generation_roi_poly = preprocessing.compute_roi_poly(
294
- needed_dem_roi_poly, needed_dem_roi_epsg, 4326
295
- )
296
-
297
- if (
298
- conf_inputs[sens_cst.INITIAL_ELEVATION][sens_cst.DEM_PATH]
299
- is not None
300
- ):
301
- # get dem total roi
302
- total_input_roi_poly = roi_tools.bounds_to_poly(
303
- inputs.rasterio_get_bounds(
304
- conf_inputs[sens_cst.INITIAL_ELEVATION][sens_cst.DEM_PATH]
305
- )
306
- )
307
- total_input_roi_epsg = inputs.rasterio_get_epsg_code(
308
- conf_inputs[sens_cst.INITIAL_ELEVATION][sens_cst.DEM_PATH]
309
- )
310
- if not isinstance(total_input_roi_epsg, int):
311
- total_input_roi_epsg = total_input_roi_epsg.to_epsg()
312
- total_input_roi_poly = preprocessing.compute_roi_poly(
313
- total_input_roi_poly, total_input_roi_epsg, 4326
314
- )
315
-
316
- # if needed roi not inside dem, raise error
317
- if not total_input_roi_poly.contains_properly(
318
- dem_generation_roi_poly
319
- ):
320
- base_message = (
321
- "Given initial elevation ROI is not covering needed ROI: "
322
- " EPSG:4326, ROI: {}".format(dem_generation_roi_poly.bounds)
323
- )
324
-
325
- if total_input_roi_poly.intersects(dem_generation_roi_poly):
326
- logging.warning(
327
- "{}. Only a part of it intersects. "
328
- "Errors might occur".format(base_message)
329
- )
330
- else:
331
- # Exit, Error is certain to occur
332
- raise RuntimeError(base_message)
333
-
334
- else:
335
- logging.warning(
336
- "Current geometry plugin doesnt compute dem roi needed "
337
- "for later computations. Errors related to unsufficient "
338
- "dem roi might occur."
339
- )
340
-
341
379
  return (
342
380
  overloaded_conf_inputs,
343
381
  conf_geom_plugin,
344
382
  geom_plugin_without_dem_and_geoid,
345
383
  geom_plugin_with_dem_and_geoid,
346
- dem_generation_roi_poly,
384
+ scaling_coeff,
347
385
  )
348
386
 
349
387
 
388
+ # pylint: disable=too-many-positional-arguments
350
389
  def generate_geometry_plugin_with_dem(
351
- conf_geom_plugin, conf_inputs, dem=None, crop_dem=True
390
+ conf_geom_plugin,
391
+ conf_inputs,
392
+ dem=None,
393
+ crop_dem=True,
394
+ output_dem_dir=None,
395
+ scaling_coeff=1,
352
396
  ):
353
397
  """
354
398
  Generate geometry plugin with dem and geoid
@@ -356,6 +400,8 @@ def generate_geometry_plugin_with_dem(
356
400
  :param conf_geom_plugin: plugin configuration
357
401
  :param conf_inputs: inputs configuration
358
402
  :param dem: dem to overide the one in inputs
403
+ :param scaling_coeff: scaling factor for resolution
404
+ :type scaling_coeff: float
359
405
 
360
406
  :return: geometry plugin object, with a dem
361
407
  """
@@ -389,6 +435,8 @@ def generate_geometry_plugin_with_dem(
389
435
  geoid=conf_inputs[sens_cst.INITIAL_ELEVATION][sens_cst.GEOID],
390
436
  default_alt=sens_cst.CARS_DEFAULT_ALT,
391
437
  pairs_for_roi=pairs_for_roi,
438
+ scaling_coeff=scaling_coeff,
439
+ output_dem_dir=output_dem_dir,
392
440
  )
393
441
  )
394
442
 
@@ -644,6 +692,7 @@ def check_all_nbits_equal_one(nbits):
644
692
  return False
645
693
 
646
694
 
695
+ @cars_profile(name="Generate inputs")
647
696
  def generate_inputs(conf, geometry_plugin):
648
697
  """
649
698
  Generate sensors inputs form inputs conf :
@@ -34,8 +34,6 @@ CHECK_INPUTS = "check_inputs"
34
34
  ROI = "roi"
35
35
  GEOID = "geoid"
36
36
  DEM_PATH = "dem"
37
- ALTITUDE_DELTA_MIN = "altitude_delta_min"
38
- ALTITUDE_DELTA_MAX = "altitude_delta_max"
39
37
 
40
38
  INPUT_IMG = "image"
41
39
  INPUT_MSK = "mask"
@@ -22,6 +22,7 @@
22
22
  CARS application module init file
23
23
  """
24
24
 
25
- # Imports needed in order to register application for Application factory
26
- from .basic_sensor_loader import BasicSensorLoader # noqa: F401
27
- from .pivot_sensor_loader import PivotSensorLoader # noqa: F401
25
+ from .basic_classif_loader import BasicClassifSensorLoader # noqa: F401
26
+ from .basic_image_loader import BasicImageSensorLoader # noqa: F401
27
+ from .pivot_classif_loader import PivotClassifSensorLoader # noqa: F401
28
+ from .pivot_image_loader import PivotImageSensorLoader # noqa: F401
@@ -0,0 +1,106 @@
1
+ # !/usr/bin/env python
2
+ # coding: utf8
3
+ #
4
+ # Copyright (c) 2024 Centre National d'Etudes Spatiales (CNES).
5
+ #
6
+ # This file is part of CARS
7
+ # (see https://github.com/CNES/cars).
8
+ #
9
+ # Licensed under the Apache License, Version 2.0 (the "License");
10
+ # you may not use this file except in compliance with the License.
11
+ # You may obtain a copy of the License at
12
+ #
13
+ # http://www.apache.org/licenses/LICENSE-2.0
14
+ #
15
+ # Unless required by applicable law or agreed to in writing, software
16
+ # distributed under the License is distributed on an "AS IS" BASIS,
17
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18
+ # See the License for the specific language governing permissions and
19
+ # limitations under the License.
20
+ #
21
+ """
22
+ This module contains the ClassifSensorLoader class.
23
+ """
24
+
25
+ from json_checker import Checker
26
+
27
+ from cars.core import inputs
28
+ from cars.core.utils import make_relative_path_absolute
29
+ from cars.pipelines.parameters.sensor_loaders.pivot_classif_loader import (
30
+ PivotClassifSensorLoader,
31
+ )
32
+ from cars.pipelines.parameters.sensor_loaders.sensor_loader import SensorLoader
33
+ from cars.pipelines.parameters.sensor_loaders.sensor_loader_template import (
34
+ SensorLoaderTemplate,
35
+ )
36
+
37
+
38
+ @SensorLoader.register("basic_classif")
39
+ class BasicClassifSensorLoader(SensorLoaderTemplate):
40
+ """
41
+ Default sensor loader (used when no sensor loader is specified)
42
+ """
43
+
44
+ def check_conf(self, conf):
45
+ """
46
+ Check configuration
47
+
48
+ :param conf: configuration to check
49
+
50
+ :return: overloaded configuration
51
+ :rtype: dict
52
+ """
53
+ default_filling = {
54
+ "fill_with_geoid": "b0",
55
+ "interpolate_from_borders": "b1",
56
+ "fill_with_endogenous_dem": "b2",
57
+ "fill_with_exogenous_dem": "b3",
58
+ }
59
+ if isinstance(conf, str):
60
+ overloaded_conf = {}
61
+ image_path = make_relative_path_absolute(conf, self.config_dir)
62
+ overloaded_conf["path"] = image_path
63
+ overloaded_conf["loader"] = "basic_classif"
64
+ overloaded_conf["filling"] = default_filling
65
+ elif isinstance(conf, dict):
66
+ overloaded_conf = conf.copy()
67
+ image_path = make_relative_path_absolute(
68
+ conf["path"], self.config_dir
69
+ )
70
+ overloaded_conf["path"] = image_path
71
+ overloaded_conf["loader"] = conf.get("loader", "basic")
72
+ overloaded_conf["filling"] = conf.get("filling", default_filling)
73
+ else:
74
+ raise TypeError(f"Input {conf} is not a string ot dict")
75
+
76
+ sensor_schema = {"loader": str, "path": str, "filling": dict}
77
+
78
+ # Check conf
79
+ checker = Checker(sensor_schema)
80
+ checker.validate(overloaded_conf)
81
+
82
+ return overloaded_conf
83
+
84
+ def set_pivot_format(self):
85
+ """
86
+ Transform input configuration to pivot format and store it
87
+ """
88
+ pivot_config = {
89
+ "loader": "pivot_classif",
90
+ "main_file": self.used_config["path"],
91
+ "filling": self.used_config["filling"],
92
+ }
93
+ pivot_config["bands"] = {}
94
+ for band_id in range(
95
+ inputs.rasterio_get_nb_bands(self.used_config["path"])
96
+ ):
97
+ band_name = "b" + str(band_id)
98
+ pivot_config["bands"][band_name] = {
99
+ "path": self.used_config["path"],
100
+ "band": band_id,
101
+ }
102
+ pivot_config["texture_bands"] = None
103
+ pivot_sensor_loader = PivotClassifSensorLoader(
104
+ pivot_config, self.config_dir
105
+ )
106
+ self.pivot_format = pivot_sensor_loader.get_pivot_format()
@@ -19,7 +19,7 @@
19
19
  # limitations under the License.
20
20
  #
21
21
  """
22
- this module contains the BasicSensorLoader class.
22
+ This module contains the BasicImageSensorLoader class.
23
23
  """
24
24
 
25
25
  from json_checker import Checker, Or
@@ -27,8 +27,8 @@ from json_checker import Checker, Or
27
27
  from cars.core import inputs
28
28
  from cars.core.utils import make_relative_path_absolute
29
29
  from cars.pipelines.parameters import sensor_inputs_constants as sens_cst
30
- from cars.pipelines.parameters.sensor_loaders.pivot_sensor_loader import (
31
- PivotSensorLoader,
30
+ from cars.pipelines.parameters.sensor_loaders.pivot_image_loader import (
31
+ PivotImageSensorLoader,
32
32
  )
33
33
  from cars.pipelines.parameters.sensor_loaders.sensor_loader import SensorLoader
34
34
  from cars.pipelines.parameters.sensor_loaders.sensor_loader_template import (
@@ -36,10 +36,10 @@ from cars.pipelines.parameters.sensor_loaders.sensor_loader_template import (
36
36
  )
37
37
 
38
38
 
39
- @SensorLoader.register("basic")
40
- class BasicSensorLoader(SensorLoaderTemplate):
39
+ @SensorLoader.register("basic_image")
40
+ class BasicImageSensorLoader(SensorLoaderTemplate):
41
41
  """
42
- Default sensor loader (used when no sensor loader is specified)
42
+ Default sensor loader for image (used when no sensor loader is specified)
43
43
  """
44
44
 
45
45
  def check_conf(self, conf):
@@ -55,26 +55,20 @@ class BasicSensorLoader(SensorLoaderTemplate):
55
55
  overloaded_conf = {}
56
56
  image_path = make_relative_path_absolute(conf, self.config_dir)
57
57
  overloaded_conf["path"] = image_path
58
- overloaded_conf["loader"] = "basic"
59
- if self.input_type == "image":
60
- overloaded_conf[sens_cst.INPUT_NODATA] = 0
61
- else:
62
- overloaded_conf[sens_cst.INPUT_NODATA] = None
58
+ overloaded_conf["loader"] = "basic_image"
59
+ overloaded_conf[sens_cst.INPUT_NODATA] = 0
63
60
  elif isinstance(conf, dict):
64
61
  overloaded_conf = conf.copy()
65
62
  image_path = make_relative_path_absolute(
66
63
  conf["path"], self.config_dir
67
64
  )
68
65
  overloaded_conf["path"] = image_path
69
- overloaded_conf["loader"] = conf.get("loader", "basic")
70
- if self.input_type == "image":
71
- overloaded_conf[sens_cst.INPUT_NODATA] = conf.get(
72
- sens_cst.INPUT_NODATA, 0
73
- )
74
- else:
75
- overloaded_conf[sens_cst.INPUT_NODATA] = None
66
+ overloaded_conf["loader"] = conf.get("loader", "basic_image")
67
+ overloaded_conf[sens_cst.INPUT_NODATA] = conf.get(
68
+ sens_cst.INPUT_NODATA, 0
69
+ )
76
70
  else:
77
- raise TypeError(f"Input {self.input_type} is not a string ot dict")
71
+ raise TypeError(f"Input {conf} is not a string ot dict")
78
72
 
79
73
  sensor_schema = {"loader": str, "path": str, "no_data": Or(None, int)}
80
74
 
@@ -89,7 +83,7 @@ class BasicSensorLoader(SensorLoaderTemplate):
89
83
  Transform input configuration to pivot format and store it
90
84
  """
91
85
  pivot_config = {
92
- "loader": "pivot",
86
+ "loader": "pivot_image",
93
87
  "main_file": self.used_config["path"],
94
88
  }
95
89
  pivot_config["bands"] = {}
@@ -102,7 +96,7 @@ class BasicSensorLoader(SensorLoaderTemplate):
102
96
  "band": band_id,
103
97
  }
104
98
  pivot_config["texture_bands"] = None
105
- pivot_sensor_loader = PivotSensorLoader(
106
- pivot_config, self.input_type, self.config_dir
99
+ pivot_sensor_loader = PivotImageSensorLoader(
100
+ pivot_config, self.config_dir
107
101
  )
108
102
  self.pivot_format = pivot_sensor_loader.get_pivot_format()
@@ -0,0 +1,121 @@
1
+ # !/usr/bin/env python
2
+ # coding: utf8
3
+ #
4
+ # Copyright (c) 2024 Centre National d'Etudes Spatiales (CNES).
5
+ #
6
+ # This file is part of CARS
7
+ # (see https://github.com/CNES/cars).
8
+ #
9
+ # Licensed under the Apache License, Version 2.0 (the "License");
10
+ # you may not use this file except in compliance with the License.
11
+ # You may obtain a copy of the License at
12
+ #
13
+ # http://www.apache.org/licenses/LICENSE-2.0
14
+ #
15
+ # Unless required by applicable law or agreed to in writing, software
16
+ # distributed under the License is distributed on an "AS IS" BASIS,
17
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18
+ # See the License for the specific language governing permissions and
19
+ # limitations under the License.
20
+ #
21
+ """
22
+ this module contains the PivotImageSensorLoader class.
23
+ """
24
+
25
+ from json_checker import Checker, Or
26
+
27
+ from cars.core import inputs
28
+ from cars.core.utils import make_relative_path_absolute
29
+ from cars.pipelines.parameters.sensor_loaders.sensor_loader import SensorLoader
30
+ from cars.pipelines.parameters.sensor_loaders.sensor_loader_template import (
31
+ SensorLoaderTemplate,
32
+ )
33
+
34
+
35
+ @SensorLoader.register("pivot_classif")
36
+ class PivotClassifSensorLoader(SensorLoaderTemplate):
37
+ """
38
+ Pivot image sensor loader : used by CARS to read inputs
39
+ """
40
+
41
+ def check_conf(self, conf):
42
+ """
43
+ Check configuration
44
+
45
+ :param conf: configuration to check
46
+
47
+ :return: overloaded configuration
48
+ :rtype: dict
49
+ """
50
+ default_filling = {
51
+ "fill_with_geoid": "b0",
52
+ "interpolate_from_borders": "b1",
53
+ "fill_with_endogenous_dem": "b2",
54
+ "fill_with_exogenous_dem": "b3",
55
+ }
56
+ overloaded_conf = conf.copy()
57
+ # Make relative paths absolutes
58
+ for band in overloaded_conf["bands"]:
59
+ overloaded_conf["bands"][band]["path"] = (
60
+ make_relative_path_absolute(
61
+ overloaded_conf["bands"][band]["path"], self.config_dir
62
+ )
63
+ )
64
+ # Check consistency between files
65
+ b0_path = overloaded_conf["bands"]["b0"]["path"]
66
+ b0_size = inputs.rasterio_get_size(b0_path)
67
+ b0_transform = inputs.rasterio_get_transform(b0_path)
68
+ for band in overloaded_conf["bands"]:
69
+ band_path = overloaded_conf["bands"][band]["path"]
70
+ band_id = overloaded_conf["bands"][band]["band"]
71
+ nb_bands = inputs.rasterio_get_nb_bands(band_path)
72
+ if band_id >= nb_bands:
73
+ raise RuntimeError(
74
+ "Band id {} is not valid for sensor which "
75
+ "has only {} bands".format(band_id, nb_bands)
76
+ )
77
+ if band_path != b0_path:
78
+ band_size = inputs.rasterio_get_size(band_path)
79
+ band_transform = inputs.rasterio_get_transform(band_path)
80
+ if b0_size != band_size:
81
+ raise RuntimeError(
82
+ "The files {} and {} do not have the same size"
83
+ "but are in the same image".format(b0_path, band_path)
84
+ )
85
+ if b0_transform != band_transform:
86
+ raise RuntimeError(
87
+ "The files {} and {} do not have the same size"
88
+ "but are in the same image".format(
89
+ b0_transform,
90
+ band_transform,
91
+ )
92
+ )
93
+ overloaded_conf["main_file"] = overloaded_conf["bands"]["b0"]["path"]
94
+ overloaded_conf["filling"] = conf.get("filling", default_filling)
95
+ overloaded_conf["texture_bands"] = conf.get("texture_bands", None)
96
+ if overloaded_conf["texture_bands"] is not None:
97
+ for texture_band in overloaded_conf["texture_bands"]:
98
+ if texture_band not in overloaded_conf["bands"]:
99
+ raise RuntimeError(
100
+ "Texture band {} not found in bands {} "
101
+ "of sensor image".format(
102
+ texture_band, overloaded_conf["bands"]
103
+ )
104
+ )
105
+
106
+ sensor_schema = {
107
+ "loader": str,
108
+ "main_file": str,
109
+ "bands": dict,
110
+ "filling": dict,
111
+ "texture_bands": Or(None, [str]),
112
+ }
113
+
114
+ # Check conf
115
+ checker = Checker(sensor_schema)
116
+ checker.validate(overloaded_conf)
117
+
118
+ return overloaded_conf
119
+
120
+ def set_pivot_format(self):
121
+ self.pivot_format = self.used_config