cars 1.0.0a2__cp313-cp313-win_amd64.whl → 1.0.0a4__cp313-cp313-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.cp313-win_amd64.dll.a +0 -0
  22. cars/applications/dense_matching/cpp/dense_matching_cpp.cp313-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.cp313-win_amd64.dll.a +0 -0
  121. cars/applications/dense_match_filling/cpp/dense_match_filling_cpp.cp313-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
@@ -31,6 +31,8 @@ from typing import Dict
31
31
 
32
32
  import numpy as np
33
33
  import pandora
34
+ import rasterio
35
+ import xarray as xr
34
36
  from json_checker import Checker, Or
35
37
  from pandora.check_configuration import (
36
38
  check_pipeline_section,
@@ -38,8 +40,12 @@ from pandora.check_configuration import (
38
40
  get_config_pipeline,
39
41
  update_conf,
40
42
  )
41
- from pandora.img_tools import get_metadata
42
43
  from pandora.state_machine import PandoraMachine
44
+ from rasterio.mask import mask
45
+ from shapely.geometry import mapping
46
+
47
+ from cars.core.projection import polygon_projection
48
+ from cars.orchestrator.cluster.log_wrapper import cars_profile
43
49
 
44
50
 
45
51
  class PandoraLoader:
@@ -48,7 +54,7 @@ class PandoraLoader:
48
54
 
49
55
  """
50
56
 
51
- def __init__( # noqa: C901
57
+ def __init__( # pylint: disable=too-many-positional-arguments # noqa: C901
52
58
  self,
53
59
  conf=None,
54
60
  method_name=None,
@@ -135,7 +141,7 @@ class PandoraLoader:
135
141
  # read conf
136
142
  with open(conf_file_path, "r", encoding="utf8") as fstream:
137
143
  conf = json.load(fstream)
138
- elif method_name == "census_sgm_default":
144
+ elif method_name in ("census_sgm_default", "auto"):
139
145
  # Use census sgm conf
140
146
  conf_file_path = os.path.join(
141
147
  package_path, "config_census_sgm_default.json"
@@ -266,26 +272,6 @@ class PandoraLoader:
266
272
  if "band" not in filter_conf:
267
273
  conf["pipeline"]["filter"]["band"] = used_band
268
274
 
269
- for key in list(conf.get("pipeline")):
270
- if key.startswith("filter"):
271
- if (
272
- conf["pipeline"][key]["filter_method"]
273
- == "median_for_intervals"
274
- and "validation" in conf["pipeline"]
275
- ):
276
- if (
277
- conf["pipeline"]["validation"]["validation_method"]
278
- == "cross_checking_fast"
279
- ):
280
- conf["pipeline"]["validation"][
281
- "validation_method"
282
- ] = "cross_checking_accurate"
283
- logging.warning(
284
- "You can not use median_for_intervals with "
285
- "the fast cross checking validation for now. "
286
- "It therefore has been overrided to accurate"
287
- )
288
-
289
275
  # Check conf
290
276
  self.pandora_config = conf
291
277
 
@@ -300,15 +286,116 @@ class PandoraLoader:
300
286
 
301
287
  return self.pandora_config
302
288
 
303
- def check_conf(
289
+ def get_classif_bands(self):
290
+ """
291
+ Get the classification bands used in the pandora configuration
292
+
293
+ :return: list of classification bands
294
+ """
295
+
296
+ classif_bands = []
297
+
298
+ def search_classes_recursive(obj):
299
+ """
300
+ Recursive search of keys containing 'classes' in the configuration
301
+ """
302
+ if isinstance(obj, dict):
303
+ for key, value in obj.items():
304
+ if "classes" in key.lower():
305
+ if isinstance(value, list):
306
+ classif_bands.extend(value)
307
+ elif value is not None:
308
+ classif_bands.append(value)
309
+ # Continue recursive search
310
+ search_classes_recursive(value)
311
+
312
+ search_classes_recursive(self.pandora_config)
313
+
314
+ # Remove duplicates and return the list
315
+ return list(set(classif_bands))
316
+
317
+ @cars_profile(name="Find auto conf")
318
+ def find_auto_conf(
319
+ self, intersection_poly, land_cover_map, classif_to_config_mapping, epsg
320
+ ):
321
+ """
322
+ Find the configuration that suits the most on the
323
+ land cover map based on the roi
324
+ """
325
+ package_path = os.path.dirname(__file__)
326
+
327
+ # construct the path to the land_cover_map
328
+ if os.path.dirname(land_cover_map) == "":
329
+ land_cover_map_path = os.path.join(package_path, land_cover_map)
330
+ else:
331
+ land_cover_map_path = land_cover_map
332
+
333
+ with rasterio.open(land_cover_map_path) as src:
334
+ # Project the polygon to the right epsg
335
+ if src.crs != epsg:
336
+ poly = polygon_projection(
337
+ intersection_poly, epsg, src.crs.to_epsg()
338
+ )
339
+ else:
340
+ poly = intersection_poly
341
+
342
+ # Use a buffer because the land_cover_map resolution is coarse
343
+ data_land_cover, _ = mask(
344
+ src, [mapping(poly)], crop=True, all_touched=True
345
+ )
346
+
347
+ # Find the most common class in the roi
348
+ data_squeeze = data_land_cover.squeeze()
349
+ valid_data = data_squeeze[data_squeeze != src.nodata]
350
+
351
+ most_common_class = None
352
+ if valid_data.size > 0:
353
+ classes, counts = np.unique(valid_data, return_counts=True)
354
+ max_index = np.argmax(counts)
355
+ most_common_class = classes[max_index]
356
+
357
+ # Construct the path to the classification to configuration mapping
358
+ if os.path.dirname(classif_to_config_mapping) == "":
359
+ conf_file_path = os.path.join(
360
+ package_path, classif_to_config_mapping
361
+ )
362
+ else:
363
+ conf_file_path = classif_to_config_mapping
364
+
365
+ # read conf
366
+ with open(conf_file_path, "r", encoding="utf8") as fstream:
367
+ conf_mapping = json.load(fstream)
368
+
369
+ # Find the configuration that corresponds to the most common class
370
+ corresponding_conf_name = conf_mapping.get(str(most_common_class), None)
371
+
372
+ # If no equivalence has been found, we use the default configuration
373
+ if corresponding_conf_name is None:
374
+ corresponding_conf_name = "census_sgm_default"
375
+
376
+ logging.info(
377
+ "The conf that has been chosen regarding the "
378
+ "world classification map is {}".format(corresponding_conf_name)
379
+ )
380
+
381
+ # We return the corresponding configuration
382
+ json_conf_name = os.path.join(
383
+ package_path, "config_" + corresponding_conf_name + ".json"
384
+ )
385
+ with open(json_conf_name, "r", encoding="utf8") as fstream:
386
+ conf = json.load(fstream)
387
+
388
+ return conf
389
+
390
+ def check_conf( # pylint: disable=too-many-positional-arguments
304
391
  self,
305
392
  user_cfg,
306
- img_left,
307
- img_right,
393
+ nodata_left,
394
+ nodata_right,
308
395
  bands_left,
309
396
  bands_right,
310
- classif_left=None,
311
- classif_right=None,
397
+ bands_classif_left=None,
398
+ bands_classif_right=None,
312
399
  ):
313
400
  """
314
401
  Check configuration
@@ -320,15 +407,18 @@ class PandoraLoader:
320
407
  :rtype: dict
321
408
 
322
409
  """
323
-
324
410
  # Import plugins before checking configuration
325
411
  pandora.import_plugin()
326
412
  # Check configuration and update the configuration with default values
327
413
  # Instantiate pandora state machine
328
414
  pandora_machine = PandoraMachine()
329
415
  # check pipeline
330
- metadata_left = get_metadata(img_left, classif=classif_left)
331
- metadata_right = get_metadata(img_right, classif=classif_right)
416
+ metadata_left = overide_pandora_get_metadata(
417
+ bands_left, classif_bands=bands_classif_left
418
+ )
419
+ metadata_right = overide_pandora_get_metadata(
420
+ bands_right, classif_bands=bands_classif_right
421
+ )
332
422
 
333
423
  metadata_left = metadata_left.assign_coords(band_im=bands_left)
334
424
  metadata_right = metadata_right.assign_coords(band_im=bands_right)
@@ -345,7 +435,9 @@ class PandoraLoader:
345
435
  saved_schema
346
436
  )
347
437
  # check a part of input section
348
- user_cfg_input = get_config_input_custom_cars(user_cfg)
438
+ user_cfg_input = get_config_input_custom_cars(
439
+ user_cfg, nodata_left, nodata_right
440
+ )
349
441
  cfg_input = check_input_section_custom_cars(user_cfg_input)
350
442
  # concatenate updated config
351
443
  cfg = concat_conf([cfg_input, cfg_pipeline])
@@ -370,7 +462,46 @@ default_short_configuration_input_custom_cars = {
370
462
  }
371
463
 
372
464
 
373
- def get_config_input_custom_cars(user_cfg: Dict[str, dict]) -> Dict[str, dict]:
465
+ def overide_pandora_get_metadata(
466
+ im_bands: list, classif_bands: list = None
467
+ ) -> xr.Dataset:
468
+ """
469
+ Read metadata from image, and return the corresponding xarray.DataSet
470
+
471
+ :param im_bands: list of band names
472
+ :param classif_bands: list of classification band names
473
+ :return: partial xarray.DataSet (attributes and coordinates)
474
+ :rtype: xarray.DataSet
475
+ """
476
+
477
+ coords = {
478
+ "band_im": list(im_bands),
479
+ "row": np.arange(10),
480
+ "col": np.arange(10),
481
+ }
482
+
483
+ data_vars = {
484
+ "image": (["row", "col"], np.zeros((10, 10))),
485
+ }
486
+
487
+ if classif_bands is not None:
488
+ coords["band_classif"] = list(classif_bands)
489
+ data_vars["classif"] = (
490
+ ["row", "col", "band_classif"],
491
+ np.zeros((10, 10, len(classif_bands)), dtype=np.int32),
492
+ )
493
+
494
+ # create the dataset
495
+ dataset = xr.Dataset(data_vars=data_vars, coords=coords)
496
+
497
+ dataset.attrs["disparity_source"] = None
498
+
499
+ return dataset
500
+
501
+
502
+ def get_config_input_custom_cars(
503
+ user_cfg: Dict[str, dict], nodata_left, nodata_right
504
+ ) -> Dict[str, dict]:
374
505
  """
375
506
  Get the input configuration
376
507
 
@@ -387,9 +518,13 @@ def get_config_input_custom_cars(user_cfg: Dict[str, dict]) -> Dict[str, dict]:
387
518
 
388
519
  if "nodata_left" in user_cfg["input"]:
389
520
  cfg["input"]["nodata_left"] = user_cfg["input"]["nodata_left"]
521
+ else:
522
+ cfg["input"]["nodata_left"] = nodata_left
390
523
 
391
524
  if "nodata_right" in user_cfg["input"]:
392
525
  cfg["input"]["nodata_right"] = user_cfg["input"]["nodata_right"]
526
+ else:
527
+ cfg["input"]["nodata_right"] = nodata_right
393
528
 
394
529
  return cfg
395
530
 
@@ -439,7 +574,7 @@ def overload_pandora_conf_with_confidence(conf, confidence_conf):
439
574
 
440
575
  for key in confidence_conf_keys:
441
576
  if key in conf_keys:
442
- logging.error("{} pandora key already in configuration".format(key))
577
+ logging.info("{} pandora key already in configuration".format(key))
443
578
 
444
579
  # update confidence
445
580
  out_dict.update(confidence_conf)
@@ -31,6 +31,7 @@ import rasterio as rio
31
31
  import scipy
32
32
  import skimage
33
33
  from json_checker import Checker, Or
34
+ from pyproj import CRS
34
35
  from shapely import Polygon
35
36
 
36
37
  from cars.core import inputs, projection
@@ -55,7 +56,6 @@ class BorderInterpolation(DsmFilling, short_name="border_interpolation"):
55
56
 
56
57
  # check conf
57
58
  self.used_method = self.used_config["method"]
58
- self.activated = self.used_config["activated"]
59
59
  self.classification = self.used_config["classification"]
60
60
  self.component_min_size = self.used_config["component_min_size"]
61
61
  self.border_size = self.used_config["border_size"]
@@ -73,8 +73,11 @@ class BorderInterpolation(DsmFilling, short_name="border_interpolation"):
73
73
 
74
74
  # Overload conf
75
75
  overloaded_conf["method"] = conf.get("method", "bulldozer")
76
- overloaded_conf["activated"] = conf.get("activated", False)
77
- overloaded_conf["classification"] = conf.get("classification", None)
76
+ overloaded_conf["classification"] = conf.get("classification", "nodata")
77
+ if isinstance(overloaded_conf["classification"], str):
78
+ overloaded_conf["classification"] = [
79
+ overloaded_conf["classification"]
80
+ ]
78
81
  overloaded_conf["component_min_size"] = conf.get(
79
82
  "component_min_size", 5
80
83
  )
@@ -86,7 +89,6 @@ class BorderInterpolation(DsmFilling, short_name="border_interpolation"):
86
89
 
87
90
  rectification_schema = {
88
91
  "method": str,
89
- "activated": bool,
90
92
  "classification": Or(None, [str]),
91
93
  "component_min_size": int,
92
94
  "border_size": int,
@@ -101,7 +103,7 @@ class BorderInterpolation(DsmFilling, short_name="border_interpolation"):
101
103
  return overloaded_conf
102
104
 
103
105
  @cars_profile(name="Border interpolation filling")
104
- def run( # noqa C901
106
+ def run( # pylint: disable=too-many-positional-arguments # noqa C901
105
107
  self,
106
108
  dsm_file,
107
109
  classif_file,
@@ -122,9 +124,6 @@ class BorderInterpolation(DsmFilling, short_name="border_interpolation"):
122
124
  - a Shapely Polygon
123
125
  """
124
126
 
125
- if not self.activated:
126
- return
127
-
128
127
  if self.classification is None:
129
128
  self.classification = ["nodata"]
130
129
  logging.error(
@@ -151,8 +150,8 @@ class BorderInterpolation(DsmFilling, short_name="border_interpolation"):
151
150
  roi_polys_outepsg = []
152
151
  for poly in roi_polys:
153
152
  if isinstance(poly, Polygon):
154
- roi_poly_outepsg = projection.polygon_projection(
155
- poly, roi_epsg, dsm_crs.to_epsg()
153
+ roi_poly_outepsg = projection.polygon_projection_crs(
154
+ poly, CRS(roi_epsg), dsm_crs
156
155
  )
157
156
  roi_polys_outepsg.append(roi_poly_outepsg)
158
157
 
@@ -160,8 +159,8 @@ class BorderInterpolation(DsmFilling, short_name="border_interpolation"):
160
159
  roi_polys_outepsg, out_shape=roi_raster.shape, transform=dsm_tr
161
160
  )
162
161
  elif isinstance(roi_polys, Polygon):
163
- roi_poly_outepsg = projection.polygon_projection(
164
- roi_polys, roi_epsg, dsm_crs.to_epsg()
162
+ roi_poly_outepsg = projection.polygon_projection_crs(
163
+ roi_polys, CRS(roi_epsg), dsm_crs
165
164
  )
166
165
  roi_raster = rio.features.rasterize(
167
166
  [roi_poly_outepsg], out_shape=roi_raster.shape, transform=dsm_tr
@@ -32,6 +32,7 @@ import rasterio as rio
32
32
  import yaml
33
33
  from bulldozer.pipeline.bulldozer_pipeline import dsm_to_dtm
34
34
  from json_checker import Checker, Or
35
+ from pyproj import CRS
35
36
  from shapely import Polygon
36
37
 
37
38
  from cars.core import inputs, projection
@@ -56,7 +57,6 @@ class BulldozerFilling(DsmFilling, short_name="bulldozer"):
56
57
 
57
58
  # check conf
58
59
  self.used_method = self.used_config["method"]
59
- self.activated = self.used_config["activated"]
60
60
  self.classification = self.used_config["classification"]
61
61
  self.save_intermediate_data = self.used_config["save_intermediate_data"]
62
62
 
@@ -71,15 +71,19 @@ class BulldozerFilling(DsmFilling, short_name="bulldozer"):
71
71
 
72
72
  # Overload conf
73
73
  overloaded_conf["method"] = conf.get("method", "bulldozer")
74
- overloaded_conf["activated"] = conf.get("activated", False)
75
- overloaded_conf["classification"] = conf.get("classification", None)
74
+ overloaded_conf["classification"] = conf.get("classification", "nodata")
75
+
76
+ if isinstance(overloaded_conf["classification"], str):
77
+ overloaded_conf["classification"] = [
78
+ overloaded_conf["classification"]
79
+ ]
80
+
76
81
  overloaded_conf["save_intermediate_data"] = conf.get(
77
82
  "save_intermediate_data", False
78
83
  )
79
84
 
80
85
  rectification_schema = {
81
86
  "method": str,
82
- "activated": bool,
83
87
  "classification": Or(None, [str]),
84
88
  "save_intermediate_data": bool,
85
89
  }
@@ -91,7 +95,7 @@ class BulldozerFilling(DsmFilling, short_name="bulldozer"):
91
95
  return overloaded_conf
92
96
 
93
97
  @cars_profile(name="Bulldozer filling")
94
- def run( # noqa C901
98
+ def run( # pylint: disable=too-many-positional-arguments # noqa C901
95
99
  self,
96
100
  dsm_file,
97
101
  classif_file,
@@ -112,9 +116,6 @@ class BulldozerFilling(DsmFilling, short_name="bulldozer"):
112
116
  - a Shapely Polygon
113
117
  """
114
118
 
115
- if not self.activated:
116
- return None
117
-
118
119
  if self.classification is None:
119
120
  self.classification = ["nodata"]
120
121
 
@@ -162,8 +163,8 @@ class BulldozerFilling(DsmFilling, short_name="bulldozer"):
162
163
  roi_polys_outepsg = []
163
164
  for poly in roi_polys:
164
165
  if isinstance(poly, Polygon):
165
- roi_poly_outepsg = projection.polygon_projection(
166
- poly, roi_epsg, dsm_crs.to_epsg()
166
+ roi_poly_outepsg = projection.polygon_projection_crs(
167
+ poly, CRS(roi_epsg), dsm_crs
167
168
  )
168
169
  roi_polys_outepsg.append(roi_poly_outepsg)
169
170
 
@@ -171,8 +172,8 @@ class BulldozerFilling(DsmFilling, short_name="bulldozer"):
171
172
  roi_polys_outepsg, out_shape=roi_raster.shape, transform=dsm_tr
172
173
  )
173
174
  elif isinstance(roi_polys, Polygon):
174
- roi_poly_outepsg = projection.polygon_projection(
175
- roi_polys, roi_epsg, dsm_crs.to_epsg()
175
+ roi_poly_outepsg = projection.polygon_projection_crs(
176
+ roi_polys, CRS(roi_epsg), dsm_crs
176
177
  )
177
178
  roi_raster = rio.features.rasterize(
178
179
  [roi_poly_outepsg], out_shape=roi_raster.shape, transform=dsm_tr
@@ -199,7 +200,7 @@ class BulldozerFilling(DsmFilling, short_name="bulldozer"):
199
200
  ):
200
201
  dsm_to_dtm(bull_conf_path)
201
202
  except Exception:
202
- logging.error(
203
+ logging.warning(
203
204
  "Bulldozer failed on its second execution."
204
205
  + " The DSM could not be filled."
205
206
  )
@@ -211,7 +212,7 @@ class BulldozerFilling(DsmFilling, short_name="bulldozer"):
211
212
  with rio.open(old_dsm_path, "w", **dsm_meta) as out_dsm:
212
213
  out_dsm.write(dsm, 1)
213
214
 
214
- if classif_file is not None:
215
+ if classif_file is not None and os.path.exists(classif_file):
215
216
  classif_descriptions = inputs.get_descriptions_bands(classif_file)
216
217
  else:
217
218
  classif_descriptions = []
@@ -225,7 +226,7 @@ class BulldozerFilling(DsmFilling, short_name="bulldozer"):
225
226
  classif[classif_msk == 0] = 0
226
227
  filling_mask = np.logical_and(classif, roi_raster > 0)
227
228
  elif label == "nodata":
228
- if classif_file is not None:
229
+ if classif_file is not None and os.path.exists(classif_file):
229
230
  with rio.open(classif_file) as in_classif:
230
231
  classif_msk = in_classif.read_masks(1)
231
232
  classif = ~classif_msk
@@ -29,6 +29,7 @@ import shutil
29
29
  import numpy as np
30
30
  import rasterio as rio
31
31
  from json_checker import Checker, Or
32
+ from pyproj import CRS
32
33
  from rasterio.enums import Resampling
33
34
  from rasterio.warp import reproject
34
35
  from shapely import Polygon
@@ -55,7 +56,6 @@ class ExogenousFilling(DsmFilling, short_name="exogenous_filling"):
55
56
 
56
57
  # check conf
57
58
  self.used_method = self.used_config["method"]
58
- self.activated = self.used_config["activated"]
59
59
  self.classification = self.used_config["classification"]
60
60
  self.fill_with_geoid = self.used_config["fill_with_geoid"]
61
61
  self.interpolation_method = self.used_config["interpolation_method"]
@@ -72,18 +72,22 @@ class ExogenousFilling(DsmFilling, short_name="exogenous_filling"):
72
72
 
73
73
  # Overload conf
74
74
  overloaded_conf["method"] = conf.get("method", "bulldozer")
75
- overloaded_conf["activated"] = conf.get("activated", False)
76
- overloaded_conf["classification"] = conf.get("classification", None)
75
+ overloaded_conf["classification"] = conf.get("classification", "nodata")
76
+ if isinstance(overloaded_conf["classification"], str):
77
+ overloaded_conf["classification"] = [
78
+ overloaded_conf["classification"]
79
+ ]
77
80
  overloaded_conf["fill_with_geoid"] = conf.get("fill_with_geoid", None)
78
81
  overloaded_conf["interpolation_method"] = conf.get(
79
82
  "interpolation_method", "bilinear"
80
83
  )
81
84
 
82
85
  if overloaded_conf["interpolation_method"] not in ["bilinear", "cubic"]:
86
+ # pylint: disable=inconsistent-quotes
83
87
  raise RuntimeError(
84
- "Invalid interpolation method"
88
+ f"Invalid interpolation method"
85
89
  f"{overloaded_conf['interpolation_method']}, "
86
- "supported modes are bilinear and cubic."
90
+ f"supported modes are bilinear and cubic."
87
91
  )
88
92
 
89
93
  overloaded_conf["save_intermediate_data"] = conf.get(
@@ -92,7 +96,6 @@ class ExogenousFilling(DsmFilling, short_name="exogenous_filling"):
92
96
 
93
97
  rectification_schema = {
94
98
  "method": str,
95
- "activated": bool,
96
99
  "classification": Or(None, [str]),
97
100
  "fill_with_geoid": Or(None, [str]),
98
101
  "interpolation_method": str,
@@ -106,7 +109,7 @@ class ExogenousFilling(DsmFilling, short_name="exogenous_filling"):
106
109
  return overloaded_conf
107
110
 
108
111
  @cars_profile(name="Exogeneous filling")
109
- def run( # noqa C901
112
+ def run( # pylint: disable=too-many-positional-arguments # noqa C901
110
113
  self,
111
114
  dsm_file,
112
115
  classif_file,
@@ -128,9 +131,6 @@ class ExogenousFilling(DsmFilling, short_name="exogenous_filling"):
128
131
  - a Shapely Polygon
129
132
  """
130
133
 
131
- if not self.activated:
132
- return
133
-
134
134
  if self.classification is None:
135
135
  self.classification = ["nodata"]
136
136
 
@@ -170,8 +170,8 @@ class ExogenousFilling(DsmFilling, short_name="exogenous_filling"):
170
170
  roi_polys_outepsg = []
171
171
  for poly in roi_polys:
172
172
  if isinstance(poly, Polygon):
173
- roi_poly_outepsg = projection.polygon_projection(
174
- poly, roi_epsg, dsm_crs.to_epsg()
173
+ roi_poly_outepsg = projection.polygon_projection_crs(
174
+ poly, CRS(roi_epsg), dsm_crs
175
175
  )
176
176
  roi_polys_outepsg.append(roi_poly_outepsg)
177
177
 
@@ -179,8 +179,8 @@ class ExogenousFilling(DsmFilling, short_name="exogenous_filling"):
179
179
  roi_polys_outepsg, out_shape=roi_raster.shape, transform=dsm_tr
180
180
  )
181
181
  elif isinstance(roi_polys, Polygon):
182
- roi_poly_outepsg = projection.polygon_projection(
183
- roi_polys, roi_epsg, dsm_crs.to_epsg()
182
+ roi_poly_outepsg = projection.polygon_projection_crs(
183
+ roi_polys, CRS(roi_epsg), dsm_crs
184
184
  )
185
185
  roi_raster = rio.features.rasterize(
186
186
  [roi_poly_outepsg], out_shape=roi_raster.shape, transform=dsm_tr
@@ -104,7 +104,7 @@ class GridGeneration(ApplicationTemplate, metaclass=ABCMeta):
104
104
  """
105
105
 
106
106
  @abstractmethod
107
- def run(
107
+ def run( # pylint: disable=too-many-positional-arguments
108
108
  self,
109
109
  image_left,
110
110
  image_right,
@@ -31,7 +31,9 @@ from json_checker import And, Checker
31
31
 
32
32
  import cars.orchestrator.orchestrator as ocht
33
33
  from cars.applications import application_constants
34
- from cars.applications.grid_generation import grid_generation_algo
34
+ from cars.applications.grid_generation import (
35
+ grid_generation_algo,
36
+ )
35
37
  from cars.applications.grid_generation import (
36
38
  grid_generation_constants as grid_constants,
37
39
  )
@@ -119,7 +121,7 @@ class EpipolarGridGeneration(GridGeneration, short_name="epipolar"):
119
121
  return self.save_intermediate_data
120
122
 
121
123
  @cars_profile(name="Epi Grid Generation")
122
- def run(
124
+ def run( # pylint: disable=too-many-positional-arguments
123
125
  self,
124
126
  image_left,
125
127
  image_right,
@@ -37,7 +37,9 @@ from scipy.spatial import Delaunay # pylint: disable=E0611
37
37
 
38
38
  import cars.orchestrator.orchestrator as ocht
39
39
  from cars.applications import application_constants
40
- from cars.applications.grid_generation import grid_generation_algo
40
+ from cars.applications.grid_generation import (
41
+ grid_generation_algo,
42
+ )
41
43
  from cars.applications.grid_generation import (
42
44
  grid_generation_constants as grid_constants,
43
45
  )
@@ -165,6 +167,7 @@ def correct_grid(grid, grid_correction, pair_folder, save_grid=None):
165
167
  return corrected_grid_right
166
168
 
167
169
 
170
+ # pylint: disable=too-many-positional-arguments
168
171
  @cars_profile(name="Grid correction estimation")
169
172
  def estimate_right_grid_correction(
170
173
  matches,
@@ -43,6 +43,7 @@ from cars.applications.triangulation.triangulation_algo import (
43
43
  )
44
44
  from cars.core import constants as cst
45
45
  from cars.core import inputs, projection, tiling
46
+ from cars.orchestrator.cluster.log_wrapper import cars_profile
46
47
 
47
48
 
48
49
  def get_new_path(path):
@@ -106,7 +107,7 @@ def write_grid(grid, fname, origin, spacing):
106
107
  dst.write_band(2, grid[:, :, 1])
107
108
 
108
109
 
109
- def generate_epipolar_grids(
110
+ def generate_epipolar_grids( # pylint: disable=too-many-positional-arguments
110
111
  sensor1, sensor2, geomodel1, geomodel2, geometry_plugin, epipolar_step
111
112
  ):
112
113
  """
@@ -140,6 +141,8 @@ def generate_epipolar_grids(
140
141
  )
141
142
 
142
143
 
144
+ # pylint: disable=too-many-positional-arguments
145
+ @cars_profile(name="Compute epipolar grid min max", interval=0.5)
143
146
  def compute_epipolar_grid_min_max(
144
147
  geometry_plugin,
145
148
  grid,
@@ -239,6 +242,7 @@ def compute_epipolar_grid_min_max(
239
242
  grid1,
240
243
  grid2,
241
244
  matches_min,
245
+ interpolation_method="linear",
242
246
  )
243
247
  pc_max = triangulate_matches(
244
248
  geometry_plugin,
@@ -249,6 +253,7 @@ def compute_epipolar_grid_min_max(
249
253
  grid1,
250
254
  grid2,
251
255
  matches_max,
256
+ interpolation_method="linear",
252
257
  )
253
258
 
254
259
  # Convert to correct EPSG
@@ -278,7 +283,7 @@ def compute_epipolar_grid_min_max(
278
283
  return grid_min, grid_max
279
284
 
280
285
 
281
- def terrain_region_to_epipolar(
286
+ def terrain_region_to_epipolar( # pylint: disable=too-many-positional-arguments
282
287
  region,
283
288
  sensor1,
284
289
  sensor2,
@@ -97,7 +97,7 @@ class GroundTruthReprojection(ApplicationTemplate, metaclass=ABCMeta):
97
97
  super().__init__(conf=conf)
98
98
 
99
99
  @abstractmethod
100
- def run(
100
+ def run( # pylint: disable=too-many-positional-arguments
101
101
  self,
102
102
  sensor_left,
103
103
  sensor_right,