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,755 @@
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
+ this module contains the orchestrator class
23
+ """
24
+
25
+ # pylint: disable=C0302
26
+
27
+ import collections
28
+ import logging
29
+
30
+ # Standard imports
31
+ import os
32
+ import platform
33
+ import shutil
34
+ import sys
35
+
36
+ # Third party imports
37
+ import tempfile
38
+ import threading
39
+ import time
40
+ import traceback
41
+
42
+ import pandas
43
+ import xarray
44
+ from tqdm import tqdm
45
+
46
+ from cars.core import constants as cst
47
+
48
+ # CARS imports
49
+ from cars.core.cars_logging import add_progress_message
50
+ from cars.core.utils import safe_makedirs
51
+ from cars.data_structures import cars_dataset
52
+ from cars.orchestrator import achievement_tracker
53
+ from cars.orchestrator.cluster.abstract_cluster import AbstractCluster
54
+ from cars.orchestrator.cluster.log_wrapper import cars_profile
55
+ from cars.orchestrator.memory_tools import get_available_ram
56
+ from cars.orchestrator.orchestrator_constants import (
57
+ CARS_DATASET_KEY,
58
+ CARS_DS_COL,
59
+ CARS_DS_ROW,
60
+ )
61
+ from cars.orchestrator.registry import compute_registry
62
+ from cars.orchestrator.registry import id_generator as id_gen
63
+ from cars.orchestrator.registry import replacer_registry, saver_registry
64
+ from cars.orchestrator.tiles_profiler import TileProfiler
65
+
66
+ SYS_PLATFORM = platform.system().lower()
67
+ IS_WIN = "windows" == SYS_PLATFORM
68
+ RAM_THRESHOLD_MB = 500
69
+ RAM_CHECK_SLEEP_TIME = 5
70
+
71
+
72
+ class Orchestrator:
73
+ """
74
+ Orchestrator
75
+ """
76
+
77
+ # pylint: disable=too-many-instance-attributes
78
+
79
+ # flake8: noqa: C901
80
+ def __init__( # pylint: disable=too-many-positional-arguments
81
+ self,
82
+ orchestrator_conf=None,
83
+ out_dir=None,
84
+ log_dir=None,
85
+ launch_worker=True,
86
+ out_yaml_path=None,
87
+ ):
88
+ """
89
+ Init function of Orchestrator.
90
+ Creates Cluster and Registry for CarsDatasets
91
+
92
+ :param orchestrator_conf: configuration of distribution
93
+
94
+ """
95
+ # init list of path to clean at the end
96
+ self.tmp_dir_list = []
97
+
98
+ # out_dir
99
+ if out_dir is not None:
100
+ self.out_dir = out_dir
101
+ else:
102
+ self.out_dir = tempfile.mkdtemp()
103
+ self.add_to_clean(self.out_dir)
104
+ logging.debug("No out_dir defined")
105
+
106
+ if log_dir is not None:
107
+ self.log_dir = log_dir
108
+ else:
109
+ self.log_dir = os.path.join(self.out_dir, "logs")
110
+
111
+ self.launch_worker = launch_worker
112
+
113
+ # overload orchestrator_conf
114
+ if orchestrator_conf is None:
115
+ if orchestrator_conf is None:
116
+ logging.info(
117
+ "No orchestrator configuration given: "
118
+ " multiprocessing mode is used"
119
+ )
120
+
121
+ self.orchestrator_conf = orchestrator_conf
122
+
123
+ # init cluster
124
+ self.cluster = AbstractCluster( # pylint: disable=E0110
125
+ orchestrator_conf,
126
+ self.out_dir,
127
+ self.log_dir,
128
+ launch_worker=self.launch_worker,
129
+ )
130
+ self.conf = self.cluster.get_conf()
131
+
132
+ self.task_timeout = self.conf.get("task_timeout", 600)
133
+
134
+ # Init IdGenerator
135
+ self.id_generator = id_gen.IdGenerator()
136
+ # init CarsDataset savers registry
137
+ self.cars_ds_savers_registry = saver_registry.CarsDatasetsRegistrySaver(
138
+ self.id_generator
139
+ )
140
+ # init CarsDataset replacement registry
141
+ self.cars_ds_replacer_registry = (
142
+ replacer_registry.CarsDatasetRegistryReplacer(self.id_generator)
143
+ )
144
+ # init CarsDataset compute registry
145
+ self.cars_ds_compute_registry = (
146
+ compute_registry.CarsDatasetRegistryCompute(self.id_generator)
147
+ )
148
+
149
+ # Achievement tracker
150
+ self.achievement_tracker = achievement_tracker.AchievementTracker()
151
+
152
+ # init tile profiler
153
+ self.dir_tile_profiling = os.path.join(
154
+ self.out_dir, "dump_dir", "tile_processing"
155
+ )
156
+ if not os.path.exists(self.dir_tile_profiling):
157
+ os.makedirs(self.dir_tile_profiling)
158
+ self.tile_profiler = TileProfiler(
159
+ self.dir_tile_profiling,
160
+ self.cars_ds_savers_registry,
161
+ self.cars_ds_replacer_registry,
162
+ )
163
+
164
+ # init cars_ds_names_info for pbar printing
165
+ self.cars_ds_names_info = []
166
+
167
+ # outjson
168
+ self.out_yaml_path = out_yaml_path
169
+ if self.out_yaml_path is None:
170
+ os.path.join(self.out_dir, "metadata.yaml")
171
+ self.out_yaml = {}
172
+
173
+ # product index file
174
+ self.product_index = {}
175
+
176
+ # Start tread used in ram check
177
+ ram_check_thread = threading.Thread(target=check_ram_usage)
178
+ ram_check_thread.daemon = True
179
+ ram_check_thread.start()
180
+
181
+ def add_to_clean(self, tmp_dir):
182
+ self.tmp_dir_list.append(tmp_dir)
183
+
184
+ def get_conf(self):
185
+ """
186
+ Get orchestrator conf
187
+
188
+ :return: orchestrator conf
189
+ """
190
+
191
+ return self.conf
192
+
193
+ @cars_profile(name="Add to save lists", interval=0.5)
194
+ def add_to_save_lists( # pylint: disable=too-many-positional-arguments
195
+ self,
196
+ file_name,
197
+ tag,
198
+ cars_ds,
199
+ dtype="float32",
200
+ nodata=0,
201
+ cars_ds_name=None,
202
+ optional_data=False,
203
+ save_by_pair=False,
204
+ ):
205
+ """
206
+ Save file to list in order to be saved later
207
+
208
+ :param file_name: file name
209
+ :param tag: tag
210
+ :param cars_ds: cars dataset to register
211
+ :param cars_ds_name: name corresponding to CarsDataset,
212
+ for information during logging
213
+ :param optional_data: True if the data is optionnal
214
+ :type optional_data: bool
215
+ :param save_by_pair: True if data by pair
216
+ :type save_by_pair: bool
217
+ """
218
+
219
+ self.cars_ds_savers_registry.add_file_to_save(
220
+ file_name,
221
+ cars_ds,
222
+ tag=tag,
223
+ dtype=dtype,
224
+ nodata=nodata,
225
+ optional_data=optional_data,
226
+ save_by_pair=save_by_pair,
227
+ )
228
+
229
+ # add name if exists
230
+ if cars_ds_name is not None:
231
+ self.cars_ds_names_info.append(cars_ds_name)
232
+
233
+ # add to tracking
234
+ self.achievement_tracker.track(
235
+ cars_ds, self.get_saving_infos([cars_ds])[0][CARS_DATASET_KEY]
236
+ )
237
+
238
+ def add_to_replace_lists(self, cars_ds, cars_ds_name=None):
239
+ """
240
+ Add CarsDataset to replacing Registry
241
+
242
+ :param cars_ds: CarsDataset to replace
243
+ :type cars_ds: CarsDataset
244
+ :param cars_ds_name: name corresponding to CarsDataset,
245
+ for information during logging
246
+ """
247
+
248
+ self.cars_ds_replacer_registry.add_cars_ds_to_replace(cars_ds)
249
+
250
+ # add name if exists
251
+ if cars_ds_name is not None:
252
+ self.cars_ds_names_info.append(cars_ds_name)
253
+
254
+ # add to tracking
255
+ self.achievement_tracker.track(
256
+ cars_ds, self.get_saving_infos([cars_ds])[0][CARS_DATASET_KEY]
257
+ )
258
+
259
+ def add_to_compute_lists(self, cars_ds, cars_ds_name=None):
260
+ """
261
+ Add CarsDataset to compute Registry: computed, but not used
262
+ in main process
263
+
264
+ :param cars_ds: CarsDataset to comput
265
+ :type cars_ds: CarsDataset
266
+ :param cars_ds_name: name corresponding to CarsDataset,
267
+ for information during logging
268
+ """
269
+
270
+ self.cars_ds_compute_registry.add_cars_ds_to_compute(cars_ds)
271
+
272
+ # add name if exists
273
+ if cars_ds_name is not None:
274
+ self.cars_ds_names_info.append(cars_ds_name)
275
+
276
+ # add to tracking
277
+ self.achievement_tracker.track(
278
+ cars_ds, self.get_saving_infos([cars_ds])[0][CARS_DATASET_KEY]
279
+ )
280
+
281
+ def save_out_yaml(self):
282
+ """
283
+ Check out_file and save it to file
284
+ """
285
+
286
+ # TODO check schema ?
287
+
288
+ # dump file
289
+ if self.out_yaml_path is not None:
290
+ cars_dataset.save_dict(self.out_yaml, self.out_yaml_path)
291
+
292
+ def save_index(self):
293
+ """
294
+ Save all product index files
295
+ """
296
+
297
+ for product, index in self.product_index.items():
298
+ index_directory = os.path.join(self.out_dir, product)
299
+ safe_makedirs(index_directory)
300
+ cars_dataset.save_dict(
301
+ index,
302
+ os.path.join(index_directory, "index.yaml"),
303
+ )
304
+
305
+ def update_out_info(self, new_dict):
306
+ """
307
+ Update self.out_file with new dict
308
+
309
+ :param new_dict: dict to merge
310
+ :type new_dict: dict
311
+ """
312
+
313
+ # TODO merge with safe creation of new keys of application
314
+ # when 2 same applications are used
315
+
316
+ merge_dicts(self.out_yaml, new_dict)
317
+
318
+ def update_index(self, new_dict):
319
+ """
320
+ Update self.product_index with new dict
321
+
322
+ :param new_dict: dict to merge
323
+ :type new_dict: dict
324
+ """
325
+
326
+ merge_dicts(self.product_index, new_dict)
327
+
328
+ def get_saving_infos(self, cars_ds_list):
329
+ """
330
+ Get saving infos of given cars datasets
331
+
332
+ :param cars_ds_list: list of cars datasets
333
+ :type cars_ds_list: list[CarsDataset]
334
+
335
+ :return : list of saving infos
336
+ :rtype: list[dict]
337
+ """
338
+
339
+ saving_infos = []
340
+
341
+ for cars_ds in cars_ds_list:
342
+ saving_infos.append(self.id_generator.get_saving_infos(cars_ds))
343
+
344
+ return saving_infos
345
+
346
+ def get_data(self, tag, future_object):
347
+ """
348
+ Get data already on disk corresponding to window of object
349
+
350
+ :param tag: tag
351
+ :type tag: str
352
+ :param future_object: object
353
+ :type future_object: xarray Dataset
354
+
355
+ :return: data on disk corresponding to tag
356
+ :rtype: np.ndarray
357
+ """
358
+ data = None
359
+
360
+ # Get descriptor if exists
361
+ obj_id = self.cars_ds_savers_registry.get_future_cars_dataset_id(
362
+ future_object
363
+ )
364
+ cars_ds_saver = (
365
+ self.cars_ds_savers_registry.get_cars_ds_saver_corresponding_id(
366
+ obj_id
367
+ )
368
+ )
369
+
370
+ if len(cars_ds_saver.descriptors) == 0 or tag not in cars_ds_saver.tags:
371
+ # nothing is written yet
372
+ return data, None
373
+
374
+ index = cars_ds_saver.tags.index(tag)
375
+ descriptor = cars_ds_saver.descriptors[index]
376
+ nodata = cars_ds_saver.nodatas[index]
377
+
378
+ # Get window
379
+ window = cars_dataset.get_window_dataset(future_object)
380
+ rio_window = cars_dataset.generate_rasterio_window(window)
381
+
382
+ # Read data window
383
+ # Read data window
384
+ data = descriptor.read(window=rio_window)
385
+
386
+ return data, nodata
387
+
388
+ def compute_futures(self, only_remaining_delayed=None):
389
+ """
390
+ Compute all futures from regitries
391
+
392
+ :param only_remaining_delayed: list of delayed if second run
393
+
394
+ """
395
+
396
+ # save json
397
+ if self.launch_worker:
398
+ self.save_out_yaml()
399
+ self.save_index()
400
+
401
+ # run compute and save files
402
+ logging.info("Compute delayed ...")
403
+ # Flatten to list
404
+ if only_remaining_delayed is None:
405
+ delayed_objects = flatten_object(
406
+ self.cars_ds_savers_registry.get_cars_datasets_list()
407
+ + self.cars_ds_replacer_registry.get_cars_datasets_list()
408
+ + self.cars_ds_compute_registry.get_cars_datasets_list(),
409
+ self.cluster.get_delayed_type(),
410
+ )
411
+ else:
412
+ delayed_objects = only_remaining_delayed
413
+
414
+ if len(delayed_objects) == 0:
415
+ logging.info("No Object to compute")
416
+ return
417
+ # Compute delayed
418
+ future_objects = self.cluster.start_tasks(delayed_objects)
419
+
420
+ # Save objects when they are computed
421
+ logging.info("Wait for futures results ...")
422
+ add_progress_message(
423
+ "Data list to process: [ {} ] ...".format(
424
+ " , ".join(list(set(self.cars_ds_names_info)))
425
+ )
426
+ )
427
+ tqdm_message = "Tiles processing: "
428
+ # if loglevel > PROGRESS level tqdm display the data list
429
+ if logging.getLogger().getEffectiveLevel() > 21:
430
+ tqdm_message = "Processing Tiles: [ {} ] ...".format(
431
+ " , ".join(list(set(self.cars_ds_names_info)))
432
+ )
433
+ pbar = tqdm(
434
+ total=len(future_objects),
435
+ desc=tqdm_message,
436
+ position=0,
437
+ leave=True,
438
+ file=sys.stdout,
439
+ )
440
+ nb_tiles_computed = 0
441
+
442
+ interval_was_cropped = False
443
+ try:
444
+ for future_obj in self.cluster.future_iterator(
445
+ future_objects, timeout=self.task_timeout
446
+ ):
447
+ # get corresponding CarsDataset and save tile
448
+ if future_obj is not None:
449
+ if get_disparity_range_cropped(future_obj):
450
+ interval_was_cropped = True
451
+ # Apply function if exists
452
+ final_function = None
453
+ current_cars_ds = (
454
+ self.cars_ds_savers_registry.get_cars_ds(future_obj)
455
+ )
456
+ if current_cars_ds is None:
457
+ self.cars_ds_replacer_registry.get_cars_ds(
458
+ future_obj
459
+ )
460
+ if current_cars_ds is not None:
461
+ final_function = current_cars_ds.final_function
462
+ if final_function is not None:
463
+ future_obj = final_function(self, future_obj)
464
+ # Save future if needs to
465
+ self.cars_ds_savers_registry.save(future_obj)
466
+ # Replace future in cars_ds if needs to
467
+ self.cars_ds_replacer_registry.replace(future_obj)
468
+ # notify tile profiler for new tile
469
+ self.tile_profiler.add_tile(future_obj)
470
+ # update achievement
471
+ self.achievement_tracker.add_tile(future_obj)
472
+ nb_tiles_computed += 1
473
+ else:
474
+ logging.debug("None tile: not saved")
475
+ pbar.update()
476
+
477
+ except TimeoutError:
478
+ logging.error("TimeOut")
479
+
480
+ if interval_was_cropped:
481
+ logging.warning(
482
+ "Disparity range was cropped in DenseMatching, "
483
+ "due to a lack of available memory for estimated"
484
+ " disparity range"
485
+ )
486
+
487
+ remaining_tiles = self.achievement_tracker.get_remaining_tiles()
488
+ if len(remaining_tiles) > 0:
489
+ # Some tiles have not been computed
490
+ logging.info(
491
+ "{} tiles have not been computed".format(
492
+ len(remaining_tiles)
493
+ )
494
+ )
495
+ if only_remaining_delayed is None:
496
+ # First try
497
+ logging.info("Retry failed tasks ...")
498
+ self.reset_cluster()
499
+ del pbar
500
+ self.compute_futures(only_remaining_delayed=remaining_tiles)
501
+ else:
502
+ # Second try
503
+ logging.error("Pipeline will pursue without failed tiles")
504
+ self.cars_ds_replacer_registry.replace_lasting_jobs(
505
+ self.cluster.get_delayed_type()
506
+ )
507
+ self.reset_registries()
508
+
509
+ if nb_tiles_computed == 0:
510
+ logging.warning(
511
+ "Result have not been saved because all tiles are None"
512
+ )
513
+
514
+ # close files
515
+ logging.info("Close files ...")
516
+ self.cars_ds_savers_registry.cleanup()
517
+ else:
518
+ logging.debug(
519
+ "orchestrator launch_worker is False, no metadata.json saved"
520
+ )
521
+
522
+ def reset_cluster(self):
523
+ """
524
+ Reset Cluster
525
+
526
+ """
527
+
528
+ data_to_propagate = self.cluster.data_to_propagate
529
+
530
+ if self.launch_worker:
531
+ self.cluster.cleanup(keep_shared_dir=True)
532
+ self.cluster = AbstractCluster( # pylint: disable=E0110
533
+ self.orchestrator_conf,
534
+ self.out_dir,
535
+ self.log_dir,
536
+ launch_worker=self.launch_worker,
537
+ data_to_propagate=data_to_propagate,
538
+ )
539
+
540
+ def reset_registries(self):
541
+ """
542
+ Reset registries
543
+ """
544
+
545
+ # cleanup the current registry before replacing it, to save files
546
+ self.cars_ds_savers_registry.cleanup()
547
+
548
+ # reset registries
549
+ # CarsDataset savers registry
550
+ self.cars_ds_savers_registry = saver_registry.CarsDatasetsRegistrySaver(
551
+ self.id_generator
552
+ )
553
+
554
+ # CarsDataset replacement registry
555
+ self.cars_ds_replacer_registry = (
556
+ replacer_registry.CarsDatasetRegistryReplacer(self.id_generator)
557
+ )
558
+ # Compute registry
559
+ self.cars_ds_compute_registry = (
560
+ compute_registry.CarsDatasetRegistryCompute(self.id_generator)
561
+ )
562
+
563
+ # tile profiler
564
+ self.tile_profiler = TileProfiler(
565
+ self.dir_tile_profiling,
566
+ self.cars_ds_savers_registry,
567
+ self.cars_ds_replacer_registry,
568
+ )
569
+
570
+ # achievement tracker
571
+ self.achievement_tracker = achievement_tracker.AchievementTracker()
572
+
573
+ # reset cars_ds names infos
574
+ self.cars_ds_names_info = []
575
+
576
+ @cars_profile(name="Compute futures")
577
+ def breakpoint(self):
578
+ """
579
+ Breakpoint : compute all delayed, save and replace data
580
+ in CarsDatasets
581
+
582
+ """
583
+
584
+ # Compute futures
585
+ try:
586
+ self.compute_futures()
587
+ except Exception as exc:
588
+ # reset registries
589
+ self.reset_registries()
590
+ raise RuntimeError(traceback.format_exc()) from exc
591
+
592
+ # reset registries
593
+ self.reset_registries()
594
+
595
+ def cleanup(self):
596
+ """
597
+ Cleanup orchestrator
598
+
599
+ """
600
+
601
+ # close cluster
602
+ logging.info("Close cluster ...")
603
+ if self.launch_worker:
604
+ self.cluster.cleanup()
605
+
606
+ # # clean tmp dir
607
+ for tmp_dir in self.tmp_dir_list:
608
+ if tmp_dir is not None and os.path.exists(tmp_dir):
609
+ shutil.rmtree(tmp_dir)
610
+
611
+ def __enter__(self):
612
+ """
613
+ Function run on enter
614
+
615
+ """
616
+
617
+ return self
618
+
619
+ def __exit__(self, exc_type, exc_value, traceback_msg):
620
+ """
621
+ Function run on exit.
622
+
623
+ Compute cluster tasks, save futures to be saved, and cleanup cluster
624
+ and files
625
+
626
+ """
627
+
628
+ # Compute futures
629
+ self.breakpoint()
630
+
631
+ # save outjson
632
+ # TODO
633
+
634
+ # TODO : check_json
635
+
636
+ # cleanup
637
+ self.cleanup()
638
+
639
+
640
+ def merge_dicts(dict1, dict2):
641
+ """
642
+ Merge dict2 into dict 1
643
+
644
+ :param dict1: dict 1
645
+ :type dict1: dict
646
+ :param dict2: dict 2
647
+ :type dict2: dict
648
+
649
+ """
650
+
651
+ for key, value2 in dict2.items():
652
+ value1 = dict1.get(key)
653
+ if isinstance(value1, collections.abc.Mapping) and isinstance(
654
+ value2, collections.abc.Mapping
655
+ ):
656
+ merge_dicts(value1, value2)
657
+ else:
658
+ dict1[key] = value2
659
+
660
+
661
+ def flatten_object(cars_ds_list, delayed_type):
662
+ """
663
+ Flatten list of CarsDatasets to list of delayed
664
+
665
+ :param cars_ds_list: list of cars datasets flatten
666
+ :type cars_ds_list: list[CarsDataset]
667
+ :param delayed_type: type of delayed
668
+
669
+ :return: list of delayed
670
+ :rtype: list[Delayed]
671
+ """
672
+
673
+ # remove duplicates
674
+ cleaned_cars_ds_list = list(dict.fromkeys(cars_ds_list))
675
+
676
+ # flatten datasets
677
+ flattened_objects = []
678
+
679
+ if len(cleaned_cars_ds_list) == 1 and cleaned_cars_ds_list[0] is None:
680
+ return []
681
+
682
+ # add obj flattened
683
+ for cars_ds in cleaned_cars_ds_list:
684
+ flattened_objects += [
685
+ obj
686
+ for obj_list in cars_ds.tiles
687
+ for obj in obj_list
688
+ if isinstance(obj, delayed_type) and obj is not None
689
+ ]
690
+
691
+ return flattened_objects
692
+
693
+
694
+ def update_saving_infos(saving_info_left, row=None, col=None):
695
+ """
696
+ Update saving infos dict with row and col arguments
697
+
698
+ :param saving_info_left: saving infos
699
+ :type saving_info_left: dict
700
+ :param row: row
701
+ :type row: int
702
+ :param col: col
703
+ :type col: int
704
+
705
+ :return: updated saving infos dict
706
+ :rtype: dict
707
+ """
708
+
709
+ full_saving_infos = saving_info_left.copy()
710
+
711
+ if row is not None:
712
+ full_saving_infos[CARS_DS_ROW] = row
713
+
714
+ if col is not None:
715
+ full_saving_infos[CARS_DS_COL] = col
716
+
717
+ return full_saving_infos
718
+
719
+
720
+ def get_disparity_range_cropped(obj):
721
+ """
722
+ Get CROPPED_DISPARITY_RANGE value in attributes
723
+
724
+ :param obj: object to look in
725
+
726
+ :rtype bool
727
+ """
728
+
729
+ value = False
730
+
731
+ if isinstance(obj, (xarray.Dataset, pandas.DataFrame)):
732
+ obj_attributes = cars_dataset.get_attributes(obj)
733
+ if obj_attributes is not None:
734
+ value = obj_attributes.get(cst.CROPPED_DISPARITY_RANGE, False)
735
+
736
+ return value
737
+
738
+
739
+ def check_ram_usage():
740
+ """
741
+ Check RAM usage
742
+ """
743
+ while True:
744
+ # Get Ram information
745
+ available_ram_mb = get_available_ram()
746
+
747
+ if available_ram_mb < RAM_THRESHOLD_MB:
748
+ logging.warning(
749
+ "RAM available < {} Mb, available ram: {} Mb."
750
+ " Freeze might ocure".format(
751
+ RAM_THRESHOLD_MB, int(available_ram_mb)
752
+ )
753
+ )
754
+
755
+ time.sleep(RAM_CHECK_SLEEP_TIME)