cars 1.0.0rc3__cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.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.
Files changed (220) hide show
  1. cars/__init__.py +74 -0
  2. cars/applications/__init__.py +40 -0
  3. cars/applications/application.py +117 -0
  4. cars/applications/application_constants.py +29 -0
  5. cars/applications/application_template.py +146 -0
  6. cars/applications/auxiliary_filling/__init__.py +29 -0
  7. cars/applications/auxiliary_filling/abstract_auxiliary_filling_app.py +105 -0
  8. cars/applications/auxiliary_filling/auxiliary_filling_algo.py +475 -0
  9. cars/applications/auxiliary_filling/auxiliary_filling_from_sensors_app.py +632 -0
  10. cars/applications/auxiliary_filling/auxiliary_filling_wrappers.py +90 -0
  11. cars/applications/dem_generation/__init__.py +30 -0
  12. cars/applications/dem_generation/abstract_dem_generation_app.py +116 -0
  13. cars/applications/dem_generation/bulldozer_config/base_config.yaml +46 -0
  14. cars/applications/dem_generation/bulldozer_dem_app.py +641 -0
  15. cars/applications/dem_generation/bulldozer_memory.py +55 -0
  16. cars/applications/dem_generation/dem_generation_algo.py +107 -0
  17. cars/applications/dem_generation/dem_generation_constants.py +32 -0
  18. cars/applications/dem_generation/dem_generation_wrappers.py +323 -0
  19. cars/applications/dense_match_filling/__init__.py +30 -0
  20. cars/applications/dense_match_filling/abstract_dense_match_filling_app.py +242 -0
  21. cars/applications/dense_match_filling/fill_disp_algo.py +113 -0
  22. cars/applications/dense_match_filling/fill_disp_constants.py +39 -0
  23. cars/applications/dense_match_filling/fill_disp_wrappers.py +83 -0
  24. cars/applications/dense_match_filling/zero_padding_app.py +302 -0
  25. cars/applications/dense_matching/__init__.py +30 -0
  26. cars/applications/dense_matching/abstract_dense_matching_app.py +261 -0
  27. cars/applications/dense_matching/census_mccnn_sgm_app.py +1461 -0
  28. cars/applications/dense_matching/cpp/__init__.py +0 -0
  29. cars/applications/dense_matching/cpp/dense_matching_cpp.cpython-313-x86_64-linux-gnu.so +0 -0
  30. cars/applications/dense_matching/cpp/dense_matching_cpp.py +94 -0
  31. cars/applications/dense_matching/cpp/includes/dense_matching.hpp +58 -0
  32. cars/applications/dense_matching/cpp/meson.build +9 -0
  33. cars/applications/dense_matching/cpp/src/bindings.cpp +13 -0
  34. cars/applications/dense_matching/cpp/src/dense_matching.cpp +207 -0
  35. cars/applications/dense_matching/dense_matching_algo.py +401 -0
  36. cars/applications/dense_matching/dense_matching_constants.py +89 -0
  37. cars/applications/dense_matching/dense_matching_wrappers.py +951 -0
  38. cars/applications/dense_matching/disparity_grid_algo.py +597 -0
  39. cars/applications/dense_matching/loaders/__init__.py +23 -0
  40. cars/applications/dense_matching/loaders/config_census_sgm_default.json +31 -0
  41. cars/applications/dense_matching/loaders/config_census_sgm_homogeneous.json +30 -0
  42. cars/applications/dense_matching/loaders/config_census_sgm_mountain_and_vegetation.json +30 -0
  43. cars/applications/dense_matching/loaders/config_census_sgm_shadow.json +30 -0
  44. cars/applications/dense_matching/loaders/config_census_sgm_sparse.json +36 -0
  45. cars/applications/dense_matching/loaders/config_census_sgm_urban.json +30 -0
  46. cars/applications/dense_matching/loaders/config_mapping.json +13 -0
  47. cars/applications/dense_matching/loaders/config_mccnn.json +28 -0
  48. cars/applications/dense_matching/loaders/global_land_cover_map.tif +0 -0
  49. cars/applications/dense_matching/loaders/pandora_loader.py +593 -0
  50. cars/applications/dsm_filling/__init__.py +32 -0
  51. cars/applications/dsm_filling/abstract_dsm_filling_app.py +101 -0
  52. cars/applications/dsm_filling/border_interpolation_app.py +278 -0
  53. cars/applications/dsm_filling/bulldozer_config/base_config.yaml +44 -0
  54. cars/applications/dsm_filling/bulldozer_filling_app.py +288 -0
  55. cars/applications/dsm_filling/exogenous_filling_app.py +341 -0
  56. cars/applications/dsm_merging/__init__.py +28 -0
  57. cars/applications/dsm_merging/abstract_dsm_merging_app.py +101 -0
  58. cars/applications/dsm_merging/weighted_fusion_app.py +639 -0
  59. cars/applications/grid_correction/__init__.py +30 -0
  60. cars/applications/grid_correction/abstract_grid_correction_app.py +103 -0
  61. cars/applications/grid_correction/grid_correction_app.py +557 -0
  62. cars/applications/grid_generation/__init__.py +30 -0
  63. cars/applications/grid_generation/abstract_grid_generation_app.py +142 -0
  64. cars/applications/grid_generation/epipolar_grid_generation_app.py +327 -0
  65. cars/applications/grid_generation/grid_generation_algo.py +388 -0
  66. cars/applications/grid_generation/grid_generation_constants.py +46 -0
  67. cars/applications/grid_generation/transform_grid.py +88 -0
  68. cars/applications/ground_truth_reprojection/__init__.py +30 -0
  69. cars/applications/ground_truth_reprojection/abstract_ground_truth_reprojection_app.py +137 -0
  70. cars/applications/ground_truth_reprojection/direct_localization_app.py +629 -0
  71. cars/applications/ground_truth_reprojection/ground_truth_reprojection_algo.py +275 -0
  72. cars/applications/point_cloud_outlier_removal/__init__.py +30 -0
  73. cars/applications/point_cloud_outlier_removal/abstract_outlier_removal_app.py +385 -0
  74. cars/applications/point_cloud_outlier_removal/outlier_removal_algo.py +392 -0
  75. cars/applications/point_cloud_outlier_removal/outlier_removal_constants.py +43 -0
  76. cars/applications/point_cloud_outlier_removal/small_components_app.py +522 -0
  77. cars/applications/point_cloud_outlier_removal/statistical_app.py +528 -0
  78. cars/applications/rasterization/__init__.py +30 -0
  79. cars/applications/rasterization/abstract_pc_rasterization_app.py +183 -0
  80. cars/applications/rasterization/rasterization_algo.py +534 -0
  81. cars/applications/rasterization/rasterization_constants.py +38 -0
  82. cars/applications/rasterization/rasterization_wrappers.py +639 -0
  83. cars/applications/rasterization/simple_gaussian_app.py +1152 -0
  84. cars/applications/resampling/__init__.py +28 -0
  85. cars/applications/resampling/abstract_resampling_app.py +187 -0
  86. cars/applications/resampling/bicubic_resampling_app.py +760 -0
  87. cars/applications/resampling/resampling_algo.py +590 -0
  88. cars/applications/resampling/resampling_constants.py +36 -0
  89. cars/applications/resampling/resampling_wrappers.py +309 -0
  90. cars/applications/sensors_subsampling/__init__.py +32 -0
  91. cars/applications/sensors_subsampling/abstract_subsampling_app.py +109 -0
  92. cars/applications/sensors_subsampling/rasterio_subsampling_app.py +420 -0
  93. cars/applications/sensors_subsampling/subsampling_algo.py +108 -0
  94. cars/applications/sparse_matching/__init__.py +30 -0
  95. cars/applications/sparse_matching/abstract_sparse_matching_app.py +599 -0
  96. cars/applications/sparse_matching/sift_app.py +724 -0
  97. cars/applications/sparse_matching/sparse_matching_algo.py +360 -0
  98. cars/applications/sparse_matching/sparse_matching_constants.py +66 -0
  99. cars/applications/sparse_matching/sparse_matching_wrappers.py +282 -0
  100. cars/applications/triangulation/__init__.py +32 -0
  101. cars/applications/triangulation/abstract_triangulation_app.py +227 -0
  102. cars/applications/triangulation/line_of_sight_intersection_app.py +1243 -0
  103. cars/applications/triangulation/pc_transform.py +552 -0
  104. cars/applications/triangulation/triangulation_algo.py +371 -0
  105. cars/applications/triangulation/triangulation_constants.py +38 -0
  106. cars/applications/triangulation/triangulation_wrappers.py +259 -0
  107. cars/bundleadjustment.py +750 -0
  108. cars/cars.py +179 -0
  109. cars/conf/__init__.py +23 -0
  110. cars/conf/geoid/egm96.grd +0 -0
  111. cars/conf/geoid/egm96.grd.hdr +15 -0
  112. cars/conf/input_parameters.py +156 -0
  113. cars/conf/mask_cst.py +35 -0
  114. cars/core/__init__.py +23 -0
  115. cars/core/cars_logging.py +402 -0
  116. cars/core/constants.py +191 -0
  117. cars/core/constants_disparity.py +50 -0
  118. cars/core/datasets.py +140 -0
  119. cars/core/geometry/__init__.py +27 -0
  120. cars/core/geometry/abstract_geometry.py +1130 -0
  121. cars/core/geometry/shareloc_geometry.py +604 -0
  122. cars/core/inputs.py +568 -0
  123. cars/core/outputs.py +176 -0
  124. cars/core/preprocessing.py +722 -0
  125. cars/core/projection.py +843 -0
  126. cars/core/roi_tools.py +215 -0
  127. cars/core/tiling.py +774 -0
  128. cars/core/utils.py +164 -0
  129. cars/data_structures/__init__.py +23 -0
  130. cars/data_structures/cars_dataset.py +1544 -0
  131. cars/data_structures/cars_dict.py +74 -0
  132. cars/data_structures/corresponding_tiles_tools.py +186 -0
  133. cars/data_structures/dataframe_converter.py +185 -0
  134. cars/data_structures/format_transformation.py +297 -0
  135. cars/devibrate.py +689 -0
  136. cars/extractroi.py +264 -0
  137. cars/orchestrator/__init__.py +23 -0
  138. cars/orchestrator/achievement_tracker.py +125 -0
  139. cars/orchestrator/cluster/__init__.py +37 -0
  140. cars/orchestrator/cluster/abstract_cluster.py +250 -0
  141. cars/orchestrator/cluster/abstract_dask_cluster.py +381 -0
  142. cars/orchestrator/cluster/dask_cluster_tools.py +103 -0
  143. cars/orchestrator/cluster/dask_config/README.md +94 -0
  144. cars/orchestrator/cluster/dask_config/dask.yaml +21 -0
  145. cars/orchestrator/cluster/dask_config/distributed.yaml +70 -0
  146. cars/orchestrator/cluster/dask_config/jobqueue.yaml +26 -0
  147. cars/orchestrator/cluster/dask_config/reference_confs/dask-schema.yaml +137 -0
  148. cars/orchestrator/cluster/dask_config/reference_confs/dask.yaml +26 -0
  149. cars/orchestrator/cluster/dask_config/reference_confs/distributed-schema.yaml +1009 -0
  150. cars/orchestrator/cluster/dask_config/reference_confs/distributed.yaml +273 -0
  151. cars/orchestrator/cluster/dask_config/reference_confs/jobqueue.yaml +212 -0
  152. cars/orchestrator/cluster/dask_jobqueue_utils.py +204 -0
  153. cars/orchestrator/cluster/local_dask_cluster.py +116 -0
  154. cars/orchestrator/cluster/log_wrapper.py +728 -0
  155. cars/orchestrator/cluster/mp_cluster/__init__.py +27 -0
  156. cars/orchestrator/cluster/mp_cluster/mp_factorizer.py +212 -0
  157. cars/orchestrator/cluster/mp_cluster/mp_objects.py +535 -0
  158. cars/orchestrator/cluster/mp_cluster/mp_tools.py +93 -0
  159. cars/orchestrator/cluster/mp_cluster/mp_wrapper.py +505 -0
  160. cars/orchestrator/cluster/mp_cluster/multiprocessing_cluster.py +986 -0
  161. cars/orchestrator/cluster/mp_cluster/multiprocessing_profiler.py +399 -0
  162. cars/orchestrator/cluster/pbs_dask_cluster.py +207 -0
  163. cars/orchestrator/cluster/sequential_cluster.py +139 -0
  164. cars/orchestrator/cluster/slurm_dask_cluster.py +234 -0
  165. cars/orchestrator/memory_tools.py +47 -0
  166. cars/orchestrator/orchestrator.py +755 -0
  167. cars/orchestrator/orchestrator_constants.py +29 -0
  168. cars/orchestrator/registry/__init__.py +23 -0
  169. cars/orchestrator/registry/abstract_registry.py +143 -0
  170. cars/orchestrator/registry/compute_registry.py +106 -0
  171. cars/orchestrator/registry/id_generator.py +116 -0
  172. cars/orchestrator/registry/replacer_registry.py +213 -0
  173. cars/orchestrator/registry/saver_registry.py +363 -0
  174. cars/orchestrator/registry/unseen_registry.py +118 -0
  175. cars/orchestrator/tiles_profiler.py +279 -0
  176. cars/pipelines/__init__.py +26 -0
  177. cars/pipelines/conf_resolution/conf_final_resolution.yaml +5 -0
  178. cars/pipelines/conf_resolution/conf_first_resolution.yaml +4 -0
  179. cars/pipelines/conf_resolution/conf_intermediate_resolution.yaml +2 -0
  180. cars/pipelines/default/__init__.py +26 -0
  181. cars/pipelines/default/default_pipeline.py +1095 -0
  182. cars/pipelines/filling/__init__.py +26 -0
  183. cars/pipelines/filling/filling.py +981 -0
  184. cars/pipelines/formatting/__init__.py +26 -0
  185. cars/pipelines/formatting/formatting.py +190 -0
  186. cars/pipelines/merging/__init__.py +26 -0
  187. cars/pipelines/merging/merging.py +439 -0
  188. cars/pipelines/parameters/__init__.py +0 -0
  189. cars/pipelines/parameters/advanced_parameters.py +256 -0
  190. cars/pipelines/parameters/advanced_parameters_constants.py +68 -0
  191. cars/pipelines/parameters/application_parameters.py +72 -0
  192. cars/pipelines/parameters/depth_map_inputs.py +0 -0
  193. cars/pipelines/parameters/dsm_inputs.py +349 -0
  194. cars/pipelines/parameters/dsm_inputs_constants.py +25 -0
  195. cars/pipelines/parameters/output_constants.py +52 -0
  196. cars/pipelines/parameters/output_parameters.py +435 -0
  197. cars/pipelines/parameters/sensor_inputs.py +859 -0
  198. cars/pipelines/parameters/sensor_inputs_constants.py +51 -0
  199. cars/pipelines/parameters/sensor_loaders/__init__.py +29 -0
  200. cars/pipelines/parameters/sensor_loaders/basic_classif_loader.py +86 -0
  201. cars/pipelines/parameters/sensor_loaders/basic_image_loader.py +98 -0
  202. cars/pipelines/parameters/sensor_loaders/pivot_classif_loader.py +90 -0
  203. cars/pipelines/parameters/sensor_loaders/pivot_image_loader.py +105 -0
  204. cars/pipelines/parameters/sensor_loaders/sensor_loader.py +93 -0
  205. cars/pipelines/parameters/sensor_loaders/sensor_loader_template.py +71 -0
  206. cars/pipelines/parameters/sensor_loaders/slurp_classif_loader.py +86 -0
  207. cars/pipelines/pipeline.py +119 -0
  208. cars/pipelines/pipeline_constants.py +38 -0
  209. cars/pipelines/pipeline_template.py +135 -0
  210. cars/pipelines/subsampling/__init__.py +26 -0
  211. cars/pipelines/subsampling/subsampling.py +358 -0
  212. cars/pipelines/surface_modeling/__init__.py +26 -0
  213. cars/pipelines/surface_modeling/surface_modeling.py +2098 -0
  214. cars/pipelines/tie_points/__init__.py +26 -0
  215. cars/pipelines/tie_points/tie_points.py +536 -0
  216. cars/starter.py +167 -0
  217. cars-1.0.0rc3.dist-info/METADATA +289 -0
  218. cars-1.0.0rc3.dist-info/RECORD +220 -0
  219. cars-1.0.0rc3.dist-info/WHEEL +6 -0
  220. cars-1.0.0rc3.dist-info/entry_points.txt +8 -0
@@ -0,0 +1,435 @@
1
+ #!/usr/bin/env python
2
+ # coding: utf8
3
+ #
4
+ # Copyright (c) 2020 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
+ """
23
+ This module contains the output definition
24
+ """
25
+
26
+ import logging
27
+ import os
28
+
29
+ from json_checker import And, Checker, Or
30
+ from pyproj import CRS
31
+
32
+ import cars.core.constants as cst
33
+ from cars.core.utils import safe_makedirs
34
+ from cars.pipelines.parameters import output_constants
35
+ from cars.pipelines.parameters import sensor_inputs_constants as sens_cst
36
+
37
+
38
+ def is_valid_epsg(epsg) -> bool:
39
+ """
40
+ Check if the given EPSG code is valid using pyproj.
41
+ """
42
+ if epsg is None:
43
+ return True
44
+
45
+ try:
46
+ # Try creating a CRS
47
+ CRS(f"EPSG:{epsg}")
48
+ return True
49
+ except Exception:
50
+ return False
51
+
52
+
53
+ def check_output_parameters( # noqa: C901 : too complex
54
+ inputs, conf, scaling_coeff=None
55
+ ):
56
+ """
57
+ Check the output json configuration and fill in default values
58
+
59
+ :param conf: configuration of output
60
+ :type conf: dict
61
+ :param scaling_coeff: scaling factor for resolution
62
+ :type scaling_coeff: float
63
+ :param pipeline_name: name of corresponding pipeline
64
+ :type pipeline_name: str
65
+ """
66
+ overloaded_conf = conf.copy()
67
+ out_dir = conf[output_constants.OUT_DIRECTORY]
68
+ out_dir = os.path.abspath(out_dir)
69
+ # Ensure that output directory and its subdirectories exist
70
+ safe_makedirs(out_dir)
71
+
72
+ # Overload some parameters
73
+ overloaded_conf[output_constants.OUT_DIRECTORY] = out_dir
74
+
75
+ overloaded_conf[output_constants.PRODUCT_LEVEL] = overloaded_conf.get(
76
+ output_constants.PRODUCT_LEVEL, "dsm"
77
+ )
78
+ if isinstance(overloaded_conf[output_constants.PRODUCT_LEVEL], str):
79
+ overloaded_conf[output_constants.PRODUCT_LEVEL] = [
80
+ overloaded_conf[output_constants.PRODUCT_LEVEL]
81
+ ]
82
+ for level in overloaded_conf[output_constants.PRODUCT_LEVEL]:
83
+ if level not in ["dsm", "depth_map", "point_cloud"]:
84
+ raise RuntimeError("Unknown product level {}".format(level))
85
+
86
+ overloaded_conf[output_constants.OUT_GEOID] = overloaded_conf.get(
87
+ output_constants.OUT_GEOID, True
88
+ )
89
+ overloaded_conf[output_constants.EPSG] = overloaded_conf.get(
90
+ output_constants.EPSG, None
91
+ )
92
+
93
+ resolution = None
94
+ if overloaded_conf.get(output_constants.RESOLUTION, None) is not None:
95
+ resolution = overloaded_conf[output_constants.RESOLUTION]
96
+ overloaded_scaling_coeff = scaling_coeff
97
+ if scaling_coeff is not None:
98
+ if resolution is not None:
99
+ if resolution < 0.5 * scaling_coeff:
100
+ logging.warning(
101
+ "The requested DSM resolution of "
102
+ f"{overloaded_conf[output_constants.RESOLUTION]} seems "
103
+ "too low for the sensor images' resolution. "
104
+ "The pipeline will still continue with it."
105
+ )
106
+ else:
107
+ resolution = float(0.5 * scaling_coeff)
108
+ logging.info(
109
+ "The resolution of the output DSM will be "
110
+ f"{resolution} meters. "
111
+ )
112
+
113
+ overloaded_conf[output_constants.RESOLUTION] = resolution
114
+
115
+ overloaded_conf[output_constants.SAVE_BY_PAIR] = overloaded_conf.get(
116
+ output_constants.SAVE_BY_PAIR, False
117
+ )
118
+
119
+ # Load auxiliary and subfields
120
+ overloaded_conf[output_constants.AUXILIARY] = overloaded_conf.get(
121
+ output_constants.AUXILIARY, {}
122
+ )
123
+
124
+ # Load auxiliary and subfields
125
+ overloaded_conf[output_constants.AUXILIARY][output_constants.AUX_IMAGE] = (
126
+ overloaded_conf[output_constants.AUXILIARY].get(
127
+ output_constants.AUX_IMAGE, True
128
+ )
129
+ )
130
+ overloaded_conf[output_constants.AUXILIARY][
131
+ output_constants.AUX_WEIGHTS
132
+ ] = overloaded_conf[output_constants.AUXILIARY].get(
133
+ output_constants.AUX_WEIGHTS, False
134
+ )
135
+ overloaded_conf[output_constants.AUXILIARY][
136
+ output_constants.AUX_CLASSIFICATION
137
+ ] = overloaded_conf[output_constants.AUXILIARY].get(
138
+ output_constants.AUX_CLASSIFICATION, False
139
+ )
140
+ overloaded_conf[output_constants.AUXILIARY][
141
+ output_constants.AUX_PERFORMANCE_MAP
142
+ ] = overloaded_conf[output_constants.AUXILIARY].get(
143
+ output_constants.AUX_PERFORMANCE_MAP, False
144
+ )
145
+ overloaded_conf[output_constants.AUXILIARY][
146
+ output_constants.AUX_CONTRIBUTING_PAIR
147
+ ] = overloaded_conf[output_constants.AUXILIARY].get(
148
+ output_constants.AUX_CONTRIBUTING_PAIR, False
149
+ )
150
+ overloaded_conf[output_constants.AUXILIARY][
151
+ output_constants.AUX_FILLING
152
+ ] = overloaded_conf[output_constants.AUXILIARY].get(
153
+ output_constants.AUX_FILLING, False
154
+ )
155
+ overloaded_conf[output_constants.AUXILIARY][
156
+ output_constants.AUX_AMBIGUITY
157
+ ] = overloaded_conf[output_constants.AUXILIARY].get(
158
+ output_constants.AUX_AMBIGUITY, False
159
+ )
160
+
161
+ # Check schema
162
+ output_schema = {
163
+ output_constants.OUT_DIRECTORY: str,
164
+ output_constants.PRODUCT_LEVEL: list,
165
+ output_constants.OUT_GEOID: Or(bool, str),
166
+ output_constants.EPSG: And(Or(int, str, None), is_valid_epsg),
167
+ output_constants.RESOLUTION: Or(int, float, None),
168
+ output_constants.SAVE_BY_PAIR: bool,
169
+ output_constants.AUXILIARY: dict,
170
+ }
171
+ checker_output = Checker(output_schema)
172
+ checker_output.validate(overloaded_conf)
173
+
174
+ # check auxiliary keys
175
+ auxiliary_schema = {
176
+ output_constants.AUX_IMAGE: Or(bool, str, list),
177
+ output_constants.AUX_WEIGHTS: bool,
178
+ output_constants.AUX_CLASSIFICATION: Or(bool, dict, list),
179
+ output_constants.AUX_PERFORMANCE_MAP: Or(bool, list),
180
+ output_constants.AUX_CONTRIBUTING_PAIR: bool,
181
+ output_constants.AUX_FILLING: Or(bool, dict),
182
+ output_constants.AUX_AMBIGUITY: bool,
183
+ }
184
+
185
+ # Check and overload classification parameter
186
+ check_classification_parameter(inputs, overloaded_conf)
187
+
188
+ # Check and overload image parameter
189
+ check_texture_bands(inputs, overloaded_conf)
190
+
191
+ # Check and overload performance_map parameter
192
+ check_performance_classes(overloaded_conf)
193
+
194
+ # Check and overload filling parameter
195
+ check_filling_parameter(overloaded_conf)
196
+
197
+ checker_auxiliary = Checker(auxiliary_schema)
198
+ checker_auxiliary.validate(overloaded_conf[output_constants.AUXILIARY])
199
+
200
+ if "epsg" in overloaded_conf and overloaded_conf["epsg"]:
201
+ spatial_ref = CRS.from_epsg(overloaded_conf["epsg"])
202
+ if spatial_ref.is_geographic:
203
+ if overloaded_conf[output_constants.RESOLUTION] > 10e-3:
204
+ logging.warning(
205
+ "The resolution of the "
206
+ + "point_cloud_rasterization should be "
207
+ + "fixed according to the epsg"
208
+ )
209
+
210
+ return overloaded_conf, overloaded_scaling_coeff
211
+
212
+
213
+ def check_filling_parameter(overloaded_conf):
214
+ """
215
+ Check and overload filling parameter
216
+ """
217
+
218
+ filling_param = overloaded_conf[output_constants.AUXILIARY][
219
+ output_constants.AUX_FILLING
220
+ ]
221
+
222
+ valid_names = [
223
+ "fill_with_geoid",
224
+ "interpolate_from_borders",
225
+ "fill_with_endogenous_dem",
226
+ "fill_with_exogenous_dem",
227
+ "other",
228
+ ]
229
+
230
+ if isinstance(filling_param, dict):
231
+ for _, value in filling_param.items():
232
+ if isinstance(value, str):
233
+ value = [value]
234
+ if any(elem not in valid_names for elem in value):
235
+ raise RuntimeError(
236
+ "Those filling methods are not available in CARS"
237
+ )
238
+ elif filling_param is True:
239
+ overloaded_conf[output_constants.AUXILIARY][
240
+ output_constants.AUX_FILLING
241
+ ] = {i + 1: name for i, name in enumerate(valid_names)}
242
+
243
+
244
+ def check_texture_bands(inputs, overloaded_conf):
245
+ """
246
+ Check and overload texture bands
247
+ """
248
+ texture_bands = overloaded_conf[output_constants.AUXILIARY][
249
+ output_constants.AUX_IMAGE
250
+ ]
251
+
252
+ if inputs[sens_cst.SENSORS] is not None:
253
+ first_key = list(inputs[sens_cst.SENSORS].keys())[0]
254
+ image = inputs[sens_cst.SENSORS][first_key][sens_cst.INPUT_IMG]
255
+ bands = set(image["bands"].keys())
256
+
257
+ if isinstance(texture_bands, list):
258
+ for elem in texture_bands:
259
+ if not isinstance(elem, str):
260
+ raise RuntimeError(
261
+ "The image parameter of auxiliary should "
262
+ "be a boolean, a string or a list of string"
263
+ )
264
+ if elem not in bands:
265
+ raise RuntimeError(
266
+ f"The band {elem} is "
267
+ f"not an existing band of "
268
+ f"the input image"
269
+ )
270
+ elif isinstance(texture_bands, str):
271
+ overloaded_conf[output_constants.AUXILIARY][
272
+ output_constants.AUX_IMAGE
273
+ ] = [texture_bands]
274
+
275
+ if texture_bands not in bands:
276
+ raise RuntimeError(
277
+ f"The band {texture_bands} is "
278
+ f"not an existing band of "
279
+ f"the input image"
280
+ )
281
+ elif texture_bands is True:
282
+ overloaded_conf[output_constants.AUXILIARY][
283
+ output_constants.AUX_IMAGE
284
+ ] = sorted(bands)
285
+
286
+
287
+ def check_classification_parameter(inputs, overloaded_conf):
288
+ """
289
+ Check and overload classification parameter
290
+ """
291
+ classification_formatting = overloaded_conf[output_constants.AUXILIARY][
292
+ output_constants.AUX_CLASSIFICATION
293
+ ]
294
+
295
+ if inputs[sens_cst.SENSORS] is not None:
296
+ first_key = list(inputs[sens_cst.SENSORS].keys())[0]
297
+
298
+ if (
299
+ "classification" in inputs[sens_cst.SENSORS][first_key]
300
+ and inputs[sens_cst.SENSORS][first_key]["classification"]
301
+ is not None
302
+ ):
303
+ classif = inputs[sens_cst.SENSORS][first_key][
304
+ sens_cst.INPUT_CLASSIFICATION
305
+ ]
306
+ bands_classif = classif["values"]
307
+
308
+ if isinstance(classification_formatting, list):
309
+ overloaded_conf[output_constants.AUXILIARY][
310
+ output_constants.AUX_CLASSIFICATION
311
+ ] = {val: val for val in classification_formatting}
312
+
313
+ for elem in classification_formatting:
314
+ if not isinstance(elem, int):
315
+ raise RuntimeError(
316
+ "The image parameter of auxiliary should "
317
+ "be a boolean, a string or a list of int"
318
+ )
319
+
320
+ if elem not in bands_classif:
321
+ raise RuntimeError(
322
+ f"If you want to use {elem} as a band num, "
323
+ f"you should use a dictionary, not a list"
324
+ )
325
+ elif classification_formatting is True:
326
+ overloaded_conf[output_constants.AUXILIARY][
327
+ output_constants.AUX_CLASSIFICATION
328
+ ] = {int(name): name for val, name in enumerate(bands_classif)}
329
+ elif isinstance(classification_formatting, dict):
330
+ for _, value in classification_formatting.items():
331
+ if isinstance(value, int):
332
+ value = [value]
333
+
334
+ if any(elem not in bands_classif for elem in value):
335
+ raise RuntimeError(
336
+ f"The band {value} is "
337
+ f"not an existing band of "
338
+ f"the input classification"
339
+ )
340
+
341
+
342
+ def check_performance_classes(overloaded_conf):
343
+ """
344
+ Check performance classes
345
+ """
346
+ performance_map_classes = overloaded_conf[output_constants.AUXILIARY][
347
+ output_constants.AUX_PERFORMANCE_MAP
348
+ ]
349
+
350
+ if isinstance(performance_map_classes, list):
351
+ for elem in performance_map_classes:
352
+ if not isinstance(elem, (int, float)):
353
+ raise RuntimeError(
354
+ "The performance_map parameter of auxiliary should"
355
+ "be a boolean or a list of float/int"
356
+ )
357
+ if len(performance_map_classes) < 2:
358
+ raise RuntimeError("Not enough step for performance_map_classes")
359
+ if performance_map_classes:
360
+ previous_step = -1
361
+ for step in performance_map_classes:
362
+ if step < 0:
363
+ raise RuntimeError(
364
+ "All step in performance_map_classes must be >=0"
365
+ )
366
+ if step <= previous_step:
367
+ raise RuntimeError(
368
+ "performance_map_classes list must be ordered."
369
+ )
370
+ previous_step = step
371
+ elif performance_map_classes is True:
372
+ # default classes, in meters:
373
+ default_performance_classes = [
374
+ 0,
375
+ 0.968,
376
+ 1.13375,
377
+ 1.295,
378
+ 1.604,
379
+ 2.423,
380
+ 3.428,
381
+ ]
382
+
383
+ overloaded_conf[output_constants.AUXILIARY][
384
+ output_constants.AUX_PERFORMANCE_MAP
385
+ ] = default_performance_classes
386
+
387
+
388
+ def intialize_product_index(orchestrator, product_levels, input_pairs):
389
+ """
390
+ Initialize the index dictionary according to requested levels with None
391
+ values for all paths.
392
+
393
+ :param orchestrator: cars orchestrator
394
+ :type orchestrator: Orchestrator
395
+ :param product_levels: name of corresponding pipeline
396
+ :type product_levels: list
397
+ :param input_pairs: list containing the pair names
398
+ :type input_pairs: list
399
+ """
400
+
401
+ index = {}
402
+
403
+ if "dsm" in product_levels:
404
+ index["dsm"] = {
405
+ cst.INDEX_DSM_ALT: None,
406
+ cst.INDEX_DSM_COLOR: None,
407
+ cst.INDEX_DSM_MASK: None,
408
+ cst.INDEX_DSM_CLASSIFICATION: None,
409
+ cst.INDEX_DSM_PERFORMANCE_MAP: None,
410
+ cst.INDEX_DSM_CONTRIBUTING_PAIR: None,
411
+ cst.INDEX_DSM_FILLING: None,
412
+ cst.INDEX_DSM_WEIGHTS: None,
413
+ }
414
+
415
+ if "point_cloud" in product_levels:
416
+ # Initialize an empty index for point cloud because its content is
417
+ # unknown at this point (tile name, save by pair or not)
418
+ index["point_cloud"] = {}
419
+
420
+ if "depth_map" in product_levels:
421
+ index["depth_map"] = {}
422
+ for pair in input_pairs:
423
+ index["depth_map"][pair] = {
424
+ cst.INDEX_DEPTH_MAP_X: None,
425
+ cst.INDEX_DEPTH_MAP_Y: None,
426
+ cst.INDEX_DEPTH_MAP_Z: None,
427
+ cst.INDEX_DEPTH_MAP_COLOR: None,
428
+ cst.INDEX_DEPTH_MAP_MASK: None,
429
+ cst.INDEX_DEPTH_MAP_CLASSIFICATION: None,
430
+ cst.INDEX_DEPTH_MAP_PERFORMANCE_MAP: None,
431
+ cst.INDEX_DEPTH_MAP_FILLING: None,
432
+ cst.INDEX_DEPTH_MAP_EPSG: None,
433
+ }
434
+
435
+ orchestrator.update_index(index)