cars 1.0.0rc1__cp313-cp313-musllinux_1_2_i686.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.
- cars/__init__.py +74 -0
- cars/applications/__init__.py +37 -0
- cars/applications/application.py +117 -0
- cars/applications/application_constants.py +29 -0
- cars/applications/application_template.py +146 -0
- cars/applications/auxiliary_filling/__init__.py +29 -0
- cars/applications/auxiliary_filling/abstract_auxiliary_filling_app.py +104 -0
- cars/applications/auxiliary_filling/auxiliary_filling_algo.py +475 -0
- cars/applications/auxiliary_filling/auxiliary_filling_from_sensors_app.py +630 -0
- cars/applications/auxiliary_filling/auxiliary_filling_wrappers.py +90 -0
- cars/applications/dem_generation/__init__.py +30 -0
- cars/applications/dem_generation/abstract_dem_generation_app.py +116 -0
- cars/applications/dem_generation/bulldozer_config/base_config.yaml +42 -0
- cars/applications/dem_generation/bulldozer_dem_app.py +655 -0
- cars/applications/dem_generation/bulldozer_memory.py +55 -0
- cars/applications/dem_generation/dem_generation_algo.py +107 -0
- cars/applications/dem_generation/dem_generation_constants.py +32 -0
- cars/applications/dem_generation/dem_generation_wrappers.py +323 -0
- cars/applications/dense_match_filling/__init__.py +30 -0
- cars/applications/dense_match_filling/abstract_dense_match_filling_app.py +242 -0
- cars/applications/dense_match_filling/fill_disp_algo.py +113 -0
- cars/applications/dense_match_filling/fill_disp_constants.py +39 -0
- cars/applications/dense_match_filling/fill_disp_wrappers.py +83 -0
- cars/applications/dense_match_filling/zero_padding_app.py +302 -0
- cars/applications/dense_matching/__init__.py +30 -0
- cars/applications/dense_matching/abstract_dense_matching_app.py +261 -0
- cars/applications/dense_matching/census_mccnn_sgm_app.py +1460 -0
- cars/applications/dense_matching/cpp/__init__.py +0 -0
- cars/applications/dense_matching/cpp/dense_matching_cpp.cpython-313-i386-linux-musl.so +0 -0
- cars/applications/dense_matching/cpp/dense_matching_cpp.py +94 -0
- cars/applications/dense_matching/cpp/includes/dense_matching.hpp +58 -0
- cars/applications/dense_matching/cpp/meson.build +9 -0
- cars/applications/dense_matching/cpp/src/bindings.cpp +13 -0
- cars/applications/dense_matching/cpp/src/dense_matching.cpp +207 -0
- cars/applications/dense_matching/dense_matching_algo.py +401 -0
- cars/applications/dense_matching/dense_matching_constants.py +89 -0
- cars/applications/dense_matching/dense_matching_wrappers.py +951 -0
- cars/applications/dense_matching/disparity_grid_algo.py +588 -0
- cars/applications/dense_matching/loaders/__init__.py +23 -0
- cars/applications/dense_matching/loaders/config_census_sgm_default.json +31 -0
- cars/applications/dense_matching/loaders/config_census_sgm_homogeneous.json +30 -0
- cars/applications/dense_matching/loaders/config_census_sgm_mountain_and_vegetation.json +30 -0
- cars/applications/dense_matching/loaders/config_census_sgm_shadow.json +30 -0
- cars/applications/dense_matching/loaders/config_census_sgm_sparse.json +36 -0
- cars/applications/dense_matching/loaders/config_census_sgm_urban.json +30 -0
- cars/applications/dense_matching/loaders/config_mapping.json +13 -0
- cars/applications/dense_matching/loaders/config_mccnn.json +28 -0
- cars/applications/dense_matching/loaders/global_land_cover_map.tif +0 -0
- cars/applications/dense_matching/loaders/pandora_loader.py +593 -0
- cars/applications/dsm_filling/__init__.py +32 -0
- cars/applications/dsm_filling/abstract_dsm_filling_app.py +101 -0
- cars/applications/dsm_filling/border_interpolation_app.py +270 -0
- cars/applications/dsm_filling/bulldozer_config/base_config.yaml +44 -0
- cars/applications/dsm_filling/bulldozer_filling_app.py +279 -0
- cars/applications/dsm_filling/exogenous_filling_app.py +333 -0
- cars/applications/grid_generation/__init__.py +30 -0
- cars/applications/grid_generation/abstract_grid_generation_app.py +142 -0
- cars/applications/grid_generation/epipolar_grid_generation_app.py +327 -0
- cars/applications/grid_generation/grid_correction_app.py +496 -0
- cars/applications/grid_generation/grid_generation_algo.py +388 -0
- cars/applications/grid_generation/grid_generation_constants.py +46 -0
- cars/applications/grid_generation/transform_grid.py +88 -0
- cars/applications/ground_truth_reprojection/__init__.py +30 -0
- cars/applications/ground_truth_reprojection/abstract_ground_truth_reprojection_app.py +137 -0
- cars/applications/ground_truth_reprojection/direct_localization_app.py +629 -0
- cars/applications/ground_truth_reprojection/ground_truth_reprojection_algo.py +275 -0
- cars/applications/point_cloud_outlier_removal/__init__.py +30 -0
- cars/applications/point_cloud_outlier_removal/abstract_outlier_removal_app.py +385 -0
- cars/applications/point_cloud_outlier_removal/outlier_removal_algo.py +392 -0
- cars/applications/point_cloud_outlier_removal/outlier_removal_constants.py +43 -0
- cars/applications/point_cloud_outlier_removal/small_components_app.py +527 -0
- cars/applications/point_cloud_outlier_removal/statistical_app.py +531 -0
- cars/applications/rasterization/__init__.py +30 -0
- cars/applications/rasterization/abstract_pc_rasterization_app.py +183 -0
- cars/applications/rasterization/rasterization_algo.py +534 -0
- cars/applications/rasterization/rasterization_constants.py +38 -0
- cars/applications/rasterization/rasterization_wrappers.py +634 -0
- cars/applications/rasterization/simple_gaussian_app.py +1152 -0
- cars/applications/resampling/__init__.py +28 -0
- cars/applications/resampling/abstract_resampling_app.py +187 -0
- cars/applications/resampling/bicubic_resampling_app.py +762 -0
- cars/applications/resampling/resampling_algo.py +614 -0
- cars/applications/resampling/resampling_constants.py +36 -0
- cars/applications/resampling/resampling_wrappers.py +309 -0
- cars/applications/sparse_matching/__init__.py +30 -0
- cars/applications/sparse_matching/abstract_sparse_matching_app.py +498 -0
- cars/applications/sparse_matching/sift_app.py +735 -0
- cars/applications/sparse_matching/sparse_matching_algo.py +360 -0
- cars/applications/sparse_matching/sparse_matching_constants.py +68 -0
- cars/applications/sparse_matching/sparse_matching_wrappers.py +238 -0
- cars/applications/triangulation/__init__.py +32 -0
- cars/applications/triangulation/abstract_triangulation_app.py +227 -0
- cars/applications/triangulation/line_of_sight_intersection_app.py +1243 -0
- cars/applications/triangulation/pc_transform.py +552 -0
- cars/applications/triangulation/triangulation_algo.py +371 -0
- cars/applications/triangulation/triangulation_constants.py +38 -0
- cars/applications/triangulation/triangulation_wrappers.py +259 -0
- cars/bundleadjustment.py +757 -0
- cars/cars.py +177 -0
- cars/conf/__init__.py +23 -0
- cars/conf/geoid/egm96.grd +0 -0
- cars/conf/geoid/egm96.grd.hdr +15 -0
- cars/conf/input_parameters.py +156 -0
- cars/conf/mask_cst.py +35 -0
- cars/core/__init__.py +23 -0
- cars/core/cars_logging.py +402 -0
- cars/core/constants.py +191 -0
- cars/core/constants_disparity.py +50 -0
- cars/core/datasets.py +140 -0
- cars/core/geometry/__init__.py +27 -0
- cars/core/geometry/abstract_geometry.py +1119 -0
- cars/core/geometry/shareloc_geometry.py +598 -0
- cars/core/inputs.py +568 -0
- cars/core/outputs.py +176 -0
- cars/core/preprocessing.py +722 -0
- cars/core/projection.py +843 -0
- cars/core/roi_tools.py +215 -0
- cars/core/tiling.py +774 -0
- cars/core/utils.py +164 -0
- cars/data_structures/__init__.py +23 -0
- cars/data_structures/cars_dataset.py +1541 -0
- cars/data_structures/cars_dict.py +74 -0
- cars/data_structures/corresponding_tiles_tools.py +186 -0
- cars/data_structures/dataframe_converter.py +185 -0
- cars/data_structures/format_transformation.py +297 -0
- cars/devibrate.py +689 -0
- cars/extractroi.py +264 -0
- cars/orchestrator/__init__.py +23 -0
- cars/orchestrator/achievement_tracker.py +125 -0
- cars/orchestrator/cluster/__init__.py +37 -0
- cars/orchestrator/cluster/abstract_cluster.py +244 -0
- cars/orchestrator/cluster/abstract_dask_cluster.py +375 -0
- cars/orchestrator/cluster/dask_cluster_tools.py +103 -0
- cars/orchestrator/cluster/dask_config/README.md +94 -0
- cars/orchestrator/cluster/dask_config/dask.yaml +21 -0
- cars/orchestrator/cluster/dask_config/distributed.yaml +70 -0
- cars/orchestrator/cluster/dask_config/jobqueue.yaml +26 -0
- cars/orchestrator/cluster/dask_config/reference_confs/dask-schema.yaml +137 -0
- cars/orchestrator/cluster/dask_config/reference_confs/dask.yaml +26 -0
- cars/orchestrator/cluster/dask_config/reference_confs/distributed-schema.yaml +1009 -0
- cars/orchestrator/cluster/dask_config/reference_confs/distributed.yaml +273 -0
- cars/orchestrator/cluster/dask_config/reference_confs/jobqueue.yaml +212 -0
- cars/orchestrator/cluster/dask_jobqueue_utils.py +204 -0
- cars/orchestrator/cluster/local_dask_cluster.py +116 -0
- cars/orchestrator/cluster/log_wrapper.py +1075 -0
- cars/orchestrator/cluster/mp_cluster/__init__.py +27 -0
- cars/orchestrator/cluster/mp_cluster/mp_factorizer.py +212 -0
- cars/orchestrator/cluster/mp_cluster/mp_objects.py +535 -0
- cars/orchestrator/cluster/mp_cluster/mp_tools.py +93 -0
- cars/orchestrator/cluster/mp_cluster/mp_wrapper.py +505 -0
- cars/orchestrator/cluster/mp_cluster/multiprocessing_cluster.py +873 -0
- cars/orchestrator/cluster/mp_cluster/multiprocessing_profiler.py +399 -0
- cars/orchestrator/cluster/pbs_dask_cluster.py +207 -0
- cars/orchestrator/cluster/sequential_cluster.py +139 -0
- cars/orchestrator/cluster/slurm_dask_cluster.py +234 -0
- cars/orchestrator/orchestrator.py +905 -0
- cars/orchestrator/orchestrator_constants.py +29 -0
- cars/orchestrator/registry/__init__.py +23 -0
- cars/orchestrator/registry/abstract_registry.py +143 -0
- cars/orchestrator/registry/compute_registry.py +106 -0
- cars/orchestrator/registry/id_generator.py +116 -0
- cars/orchestrator/registry/replacer_registry.py +213 -0
- cars/orchestrator/registry/saver_registry.py +363 -0
- cars/orchestrator/registry/unseen_registry.py +118 -0
- cars/orchestrator/tiles_profiler.py +279 -0
- cars/pipelines/__init__.py +26 -0
- cars/pipelines/conf_resolution/conf_final_resolution.yaml +5 -0
- cars/pipelines/conf_resolution/conf_first_resolution.yaml +2 -0
- cars/pipelines/conf_resolution/conf_intermediate_resolution.yaml +2 -0
- cars/pipelines/default/__init__.py +26 -0
- cars/pipelines/default/default_pipeline.py +786 -0
- cars/pipelines/parameters/__init__.py +0 -0
- cars/pipelines/parameters/advanced_parameters.py +417 -0
- cars/pipelines/parameters/advanced_parameters_constants.py +69 -0
- cars/pipelines/parameters/application_parameters.py +71 -0
- cars/pipelines/parameters/depth_map_inputs.py +0 -0
- cars/pipelines/parameters/dsm_inputs.py +918 -0
- cars/pipelines/parameters/dsm_inputs_constants.py +25 -0
- cars/pipelines/parameters/output_constants.py +52 -0
- cars/pipelines/parameters/output_parameters.py +454 -0
- cars/pipelines/parameters/sensor_inputs.py +842 -0
- cars/pipelines/parameters/sensor_inputs_constants.py +49 -0
- cars/pipelines/parameters/sensor_loaders/__init__.py +29 -0
- cars/pipelines/parameters/sensor_loaders/basic_classif_loader.py +86 -0
- cars/pipelines/parameters/sensor_loaders/basic_image_loader.py +98 -0
- cars/pipelines/parameters/sensor_loaders/pivot_classif_loader.py +90 -0
- cars/pipelines/parameters/sensor_loaders/pivot_image_loader.py +105 -0
- cars/pipelines/parameters/sensor_loaders/sensor_loader.py +93 -0
- cars/pipelines/parameters/sensor_loaders/sensor_loader_template.py +71 -0
- cars/pipelines/parameters/sensor_loaders/slurp_classif_loader.py +86 -0
- cars/pipelines/pipeline.py +119 -0
- cars/pipelines/pipeline_constants.py +31 -0
- cars/pipelines/pipeline_template.py +139 -0
- cars/pipelines/unit/__init__.py +26 -0
- cars/pipelines/unit/unit_pipeline.py +2850 -0
- cars/starter.py +167 -0
- cars-1.0.0rc1.dist-info/METADATA +292 -0
- cars-1.0.0rc1.dist-info/RECORD +202 -0
- cars-1.0.0rc1.dist-info/WHEEL +5 -0
- cars-1.0.0rc1.dist-info/entry_points.txt +8 -0
- cars.libs/libgcc_s-1257a076.so.1 +0 -0
- cars.libs/libstdc++-0530927c.so.6.0.32 +0 -0
|
@@ -0,0 +1,905 @@
|
|
|
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 multiprocessing
|
|
32
|
+
import os
|
|
33
|
+
import platform
|
|
34
|
+
import re
|
|
35
|
+
import shutil
|
|
36
|
+
import subprocess
|
|
37
|
+
import sys
|
|
38
|
+
|
|
39
|
+
# Third party imports
|
|
40
|
+
import tempfile
|
|
41
|
+
import threading
|
|
42
|
+
import time
|
|
43
|
+
import traceback
|
|
44
|
+
|
|
45
|
+
import pandas
|
|
46
|
+
import psutil
|
|
47
|
+
import xarray
|
|
48
|
+
from tqdm import tqdm
|
|
49
|
+
|
|
50
|
+
from cars.core import constants as cst
|
|
51
|
+
|
|
52
|
+
# CARS imports
|
|
53
|
+
from cars.core.cars_logging import add_progress_message
|
|
54
|
+
from cars.core.utils import safe_makedirs
|
|
55
|
+
from cars.data_structures import cars_dataset
|
|
56
|
+
from cars.orchestrator import achievement_tracker
|
|
57
|
+
from cars.orchestrator.cluster.abstract_cluster import AbstractCluster
|
|
58
|
+
from cars.orchestrator.cluster.log_wrapper import cars_profile
|
|
59
|
+
from cars.orchestrator.orchestrator_constants import (
|
|
60
|
+
CARS_DATASET_KEY,
|
|
61
|
+
CARS_DS_COL,
|
|
62
|
+
CARS_DS_ROW,
|
|
63
|
+
)
|
|
64
|
+
from cars.orchestrator.registry import compute_registry
|
|
65
|
+
from cars.orchestrator.registry import id_generator as id_gen
|
|
66
|
+
from cars.orchestrator.registry import replacer_registry, saver_registry
|
|
67
|
+
from cars.orchestrator.tiles_profiler import TileProfiler
|
|
68
|
+
|
|
69
|
+
SYS_PLATFORM = platform.system().lower()
|
|
70
|
+
IS_WIN = "windows" == SYS_PLATFORM
|
|
71
|
+
RAM_THRESHOLD_MB = 500
|
|
72
|
+
RAM_CHECK_SLEEP_TIME = 5
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
class Orchestrator:
|
|
76
|
+
"""
|
|
77
|
+
Orchestrator
|
|
78
|
+
"""
|
|
79
|
+
|
|
80
|
+
# pylint: disable=too-many-instance-attributes
|
|
81
|
+
|
|
82
|
+
# flake8: noqa: C901
|
|
83
|
+
def __init__( # pylint: disable=too-many-positional-arguments
|
|
84
|
+
self,
|
|
85
|
+
orchestrator_conf=None,
|
|
86
|
+
out_dir=None,
|
|
87
|
+
log_dir=None,
|
|
88
|
+
launch_worker=True,
|
|
89
|
+
out_yaml_path=None,
|
|
90
|
+
):
|
|
91
|
+
"""
|
|
92
|
+
Init function of Orchestrator.
|
|
93
|
+
Creates Cluster and Registry for CarsDatasets
|
|
94
|
+
|
|
95
|
+
:param orchestrator_conf: configuration of distribution
|
|
96
|
+
|
|
97
|
+
"""
|
|
98
|
+
# init list of path to clean at the end
|
|
99
|
+
self.tmp_dir_list = []
|
|
100
|
+
|
|
101
|
+
# out_dir
|
|
102
|
+
if out_dir is not None:
|
|
103
|
+
self.out_dir = out_dir
|
|
104
|
+
else:
|
|
105
|
+
self.out_dir = tempfile.mkdtemp()
|
|
106
|
+
self.add_to_clean(self.out_dir)
|
|
107
|
+
logging.debug("No out_dir defined")
|
|
108
|
+
|
|
109
|
+
if log_dir is not None:
|
|
110
|
+
self.log_dir = log_dir
|
|
111
|
+
else:
|
|
112
|
+
self.log_dir = os.path.join(self.out_dir, "logs")
|
|
113
|
+
|
|
114
|
+
self.launch_worker = launch_worker
|
|
115
|
+
|
|
116
|
+
# overload orchestrator_conf
|
|
117
|
+
if orchestrator_conf is None or (
|
|
118
|
+
"mode" in orchestrator_conf and orchestrator_conf["mode"] == "auto"
|
|
119
|
+
):
|
|
120
|
+
if orchestrator_conf is None:
|
|
121
|
+
logging.info(
|
|
122
|
+
"No orchestrator configuration given: auto mode is used"
|
|
123
|
+
)
|
|
124
|
+
logging.info(
|
|
125
|
+
"Auto mode is used for orchestrator: "
|
|
126
|
+
"number of workers and memory allocated per worker "
|
|
127
|
+
"will be set automatically"
|
|
128
|
+
)
|
|
129
|
+
if orchestrator_conf is not None and len(orchestrator_conf) > 1:
|
|
130
|
+
logging.warning(
|
|
131
|
+
"Auto mode is used for orchestator: "
|
|
132
|
+
"parameters set by user are ignored"
|
|
133
|
+
)
|
|
134
|
+
# Compute parameters for auto mode
|
|
135
|
+
nb_workers, max_ram_per_worker = compute_conf_auto_mode(IS_WIN)
|
|
136
|
+
orchestrator_conf = {
|
|
137
|
+
"mode": "multiprocessing",
|
|
138
|
+
"nb_workers": nb_workers,
|
|
139
|
+
"max_ram_per_worker": max_ram_per_worker,
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
self.orchestrator_conf = orchestrator_conf
|
|
143
|
+
|
|
144
|
+
# init cluster
|
|
145
|
+
self.cluster = AbstractCluster( # pylint: disable=E0110
|
|
146
|
+
orchestrator_conf,
|
|
147
|
+
self.out_dir,
|
|
148
|
+
self.log_dir,
|
|
149
|
+
launch_worker=self.launch_worker,
|
|
150
|
+
)
|
|
151
|
+
self.conf = self.cluster.get_conf()
|
|
152
|
+
|
|
153
|
+
self.task_timeout = self.conf.get("task_timeout", 600)
|
|
154
|
+
|
|
155
|
+
# Init IdGenerator
|
|
156
|
+
self.id_generator = id_gen.IdGenerator()
|
|
157
|
+
# init CarsDataset savers registry
|
|
158
|
+
self.cars_ds_savers_registry = saver_registry.CarsDatasetsRegistrySaver(
|
|
159
|
+
self.id_generator
|
|
160
|
+
)
|
|
161
|
+
# init CarsDataset replacement registry
|
|
162
|
+
self.cars_ds_replacer_registry = (
|
|
163
|
+
replacer_registry.CarsDatasetRegistryReplacer(self.id_generator)
|
|
164
|
+
)
|
|
165
|
+
# init CarsDataset compute registry
|
|
166
|
+
self.cars_ds_compute_registry = (
|
|
167
|
+
compute_registry.CarsDatasetRegistryCompute(self.id_generator)
|
|
168
|
+
)
|
|
169
|
+
|
|
170
|
+
# Achievement tracker
|
|
171
|
+
self.achievement_tracker = achievement_tracker.AchievementTracker()
|
|
172
|
+
|
|
173
|
+
# init tile profiler
|
|
174
|
+
self.dir_tile_profiling = os.path.join(
|
|
175
|
+
self.out_dir, "dump_dir", "tile_processing"
|
|
176
|
+
)
|
|
177
|
+
if not os.path.exists(self.dir_tile_profiling):
|
|
178
|
+
os.makedirs(self.dir_tile_profiling)
|
|
179
|
+
self.tile_profiler = TileProfiler(
|
|
180
|
+
self.dir_tile_profiling,
|
|
181
|
+
self.cars_ds_savers_registry,
|
|
182
|
+
self.cars_ds_replacer_registry,
|
|
183
|
+
)
|
|
184
|
+
|
|
185
|
+
# init cars_ds_names_info for pbar printing
|
|
186
|
+
self.cars_ds_names_info = []
|
|
187
|
+
|
|
188
|
+
# outjson
|
|
189
|
+
self.out_yaml_path = out_yaml_path
|
|
190
|
+
if self.out_yaml_path is None:
|
|
191
|
+
os.path.join(self.out_dir, "metadata.yaml")
|
|
192
|
+
self.out_yaml = {}
|
|
193
|
+
|
|
194
|
+
# product index file
|
|
195
|
+
self.product_index = {}
|
|
196
|
+
|
|
197
|
+
# Start tread used in ram check
|
|
198
|
+
ram_check_thread = threading.Thread(target=check_ram_usage)
|
|
199
|
+
ram_check_thread.daemon = True
|
|
200
|
+
ram_check_thread.start()
|
|
201
|
+
|
|
202
|
+
def add_to_clean(self, tmp_dir):
|
|
203
|
+
self.tmp_dir_list.append(tmp_dir)
|
|
204
|
+
|
|
205
|
+
def get_conf(self):
|
|
206
|
+
"""
|
|
207
|
+
Get orchestrator conf
|
|
208
|
+
|
|
209
|
+
:return: orchestrator conf
|
|
210
|
+
"""
|
|
211
|
+
|
|
212
|
+
return self.conf
|
|
213
|
+
|
|
214
|
+
@cars_profile(name="Add to save lists", interval=0.5)
|
|
215
|
+
def add_to_save_lists( # pylint: disable=too-many-positional-arguments
|
|
216
|
+
self,
|
|
217
|
+
file_name,
|
|
218
|
+
tag,
|
|
219
|
+
cars_ds,
|
|
220
|
+
dtype="float32",
|
|
221
|
+
nodata=0,
|
|
222
|
+
cars_ds_name=None,
|
|
223
|
+
optional_data=False,
|
|
224
|
+
save_by_pair=False,
|
|
225
|
+
):
|
|
226
|
+
"""
|
|
227
|
+
Save file to list in order to be saved later
|
|
228
|
+
|
|
229
|
+
:param file_name: file name
|
|
230
|
+
:param tag: tag
|
|
231
|
+
:param cars_ds: cars dataset to register
|
|
232
|
+
:param cars_ds_name: name corresponding to CarsDataset,
|
|
233
|
+
for information during logging
|
|
234
|
+
:param optional_data: True if the data is optionnal
|
|
235
|
+
:type optional_data: bool
|
|
236
|
+
:param save_by_pair: True if data by pair
|
|
237
|
+
:type save_by_pair: bool
|
|
238
|
+
"""
|
|
239
|
+
|
|
240
|
+
self.cars_ds_savers_registry.add_file_to_save(
|
|
241
|
+
file_name,
|
|
242
|
+
cars_ds,
|
|
243
|
+
tag=tag,
|
|
244
|
+
dtype=dtype,
|
|
245
|
+
nodata=nodata,
|
|
246
|
+
optional_data=optional_data,
|
|
247
|
+
save_by_pair=save_by_pair,
|
|
248
|
+
)
|
|
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_replace_lists(self, cars_ds, cars_ds_name=None):
|
|
260
|
+
"""
|
|
261
|
+
Add CarsDataset to replacing Registry
|
|
262
|
+
|
|
263
|
+
:param cars_ds: CarsDataset to replace
|
|
264
|
+
:type cars_ds: CarsDataset
|
|
265
|
+
:param cars_ds_name: name corresponding to CarsDataset,
|
|
266
|
+
for information during logging
|
|
267
|
+
"""
|
|
268
|
+
|
|
269
|
+
self.cars_ds_replacer_registry.add_cars_ds_to_replace(cars_ds)
|
|
270
|
+
|
|
271
|
+
# add name if exists
|
|
272
|
+
if cars_ds_name is not None:
|
|
273
|
+
self.cars_ds_names_info.append(cars_ds_name)
|
|
274
|
+
|
|
275
|
+
# add to tracking
|
|
276
|
+
self.achievement_tracker.track(
|
|
277
|
+
cars_ds, self.get_saving_infos([cars_ds])[0][CARS_DATASET_KEY]
|
|
278
|
+
)
|
|
279
|
+
|
|
280
|
+
def add_to_compute_lists(self, cars_ds, cars_ds_name=None):
|
|
281
|
+
"""
|
|
282
|
+
Add CarsDataset to compute Registry: computed, but not used
|
|
283
|
+
in main process
|
|
284
|
+
|
|
285
|
+
:param cars_ds: CarsDataset to comput
|
|
286
|
+
:type cars_ds: CarsDataset
|
|
287
|
+
:param cars_ds_name: name corresponding to CarsDataset,
|
|
288
|
+
for information during logging
|
|
289
|
+
"""
|
|
290
|
+
|
|
291
|
+
self.cars_ds_compute_registry.add_cars_ds_to_compute(cars_ds)
|
|
292
|
+
|
|
293
|
+
# add name if exists
|
|
294
|
+
if cars_ds_name is not None:
|
|
295
|
+
self.cars_ds_names_info.append(cars_ds_name)
|
|
296
|
+
|
|
297
|
+
# add to tracking
|
|
298
|
+
self.achievement_tracker.track(
|
|
299
|
+
cars_ds, self.get_saving_infos([cars_ds])[0][CARS_DATASET_KEY]
|
|
300
|
+
)
|
|
301
|
+
|
|
302
|
+
def save_out_yaml(self):
|
|
303
|
+
"""
|
|
304
|
+
Check out_file and save it to file
|
|
305
|
+
"""
|
|
306
|
+
|
|
307
|
+
# TODO check schema ?
|
|
308
|
+
|
|
309
|
+
# dump file
|
|
310
|
+
if self.out_yaml_path is not None:
|
|
311
|
+
cars_dataset.save_dict(self.out_yaml, self.out_yaml_path)
|
|
312
|
+
|
|
313
|
+
def save_index(self):
|
|
314
|
+
"""
|
|
315
|
+
Save all product index files
|
|
316
|
+
"""
|
|
317
|
+
|
|
318
|
+
for product, index in self.product_index.items():
|
|
319
|
+
index_directory = os.path.join(self.out_dir, product)
|
|
320
|
+
safe_makedirs(index_directory)
|
|
321
|
+
cars_dataset.save_dict(
|
|
322
|
+
index,
|
|
323
|
+
os.path.join(index_directory, "index.yaml"),
|
|
324
|
+
)
|
|
325
|
+
|
|
326
|
+
def update_out_info(self, new_dict):
|
|
327
|
+
"""
|
|
328
|
+
Update self.out_file with new dict
|
|
329
|
+
|
|
330
|
+
:param new_dict: dict to merge
|
|
331
|
+
:type new_dict: dict
|
|
332
|
+
"""
|
|
333
|
+
|
|
334
|
+
# TODO merge with safe creation of new keys of application
|
|
335
|
+
# when 2 same applications are used
|
|
336
|
+
|
|
337
|
+
merge_dicts(self.out_yaml, new_dict)
|
|
338
|
+
|
|
339
|
+
def update_index(self, new_dict):
|
|
340
|
+
"""
|
|
341
|
+
Update self.product_index with new dict
|
|
342
|
+
|
|
343
|
+
:param new_dict: dict to merge
|
|
344
|
+
:type new_dict: dict
|
|
345
|
+
"""
|
|
346
|
+
|
|
347
|
+
merge_dicts(self.product_index, new_dict)
|
|
348
|
+
|
|
349
|
+
def get_saving_infos(self, cars_ds_list):
|
|
350
|
+
"""
|
|
351
|
+
Get saving infos of given cars datasets
|
|
352
|
+
|
|
353
|
+
:param cars_ds_list: list of cars datasets
|
|
354
|
+
:type cars_ds_list: list[CarsDataset]
|
|
355
|
+
|
|
356
|
+
:return : list of saving infos
|
|
357
|
+
:rtype: list[dict]
|
|
358
|
+
"""
|
|
359
|
+
|
|
360
|
+
saving_infos = []
|
|
361
|
+
|
|
362
|
+
for cars_ds in cars_ds_list:
|
|
363
|
+
saving_infos.append(self.id_generator.get_saving_infos(cars_ds))
|
|
364
|
+
|
|
365
|
+
return saving_infos
|
|
366
|
+
|
|
367
|
+
def get_data(self, tag, future_object):
|
|
368
|
+
"""
|
|
369
|
+
Get data already on disk corresponding to window of object
|
|
370
|
+
|
|
371
|
+
:param tag: tag
|
|
372
|
+
:type tag: str
|
|
373
|
+
:param future_object: object
|
|
374
|
+
:type future_object: xarray Dataset
|
|
375
|
+
|
|
376
|
+
:return: data on disk corresponding to tag
|
|
377
|
+
:rtype: np.ndarray
|
|
378
|
+
"""
|
|
379
|
+
data = None
|
|
380
|
+
|
|
381
|
+
# Get descriptor if exists
|
|
382
|
+
obj_id = self.cars_ds_savers_registry.get_future_cars_dataset_id(
|
|
383
|
+
future_object
|
|
384
|
+
)
|
|
385
|
+
cars_ds_saver = (
|
|
386
|
+
self.cars_ds_savers_registry.get_cars_ds_saver_corresponding_id(
|
|
387
|
+
obj_id
|
|
388
|
+
)
|
|
389
|
+
)
|
|
390
|
+
|
|
391
|
+
if len(cars_ds_saver.descriptors) == 0 or tag not in cars_ds_saver.tags:
|
|
392
|
+
# nothing is written yet
|
|
393
|
+
return data, None
|
|
394
|
+
|
|
395
|
+
index = cars_ds_saver.tags.index(tag)
|
|
396
|
+
descriptor = cars_ds_saver.descriptors[index]
|
|
397
|
+
nodata = cars_ds_saver.nodatas[index]
|
|
398
|
+
|
|
399
|
+
# Get window
|
|
400
|
+
window = cars_dataset.get_window_dataset(future_object)
|
|
401
|
+
rio_window = cars_dataset.generate_rasterio_window(window)
|
|
402
|
+
|
|
403
|
+
# Read data window
|
|
404
|
+
# Read data window
|
|
405
|
+
data = descriptor.read(window=rio_window)
|
|
406
|
+
|
|
407
|
+
return data, nodata
|
|
408
|
+
|
|
409
|
+
def compute_futures(self, only_remaining_delayed=None):
|
|
410
|
+
"""
|
|
411
|
+
Compute all futures from regitries
|
|
412
|
+
|
|
413
|
+
:param only_remaining_delayed: list of delayed if second run
|
|
414
|
+
|
|
415
|
+
"""
|
|
416
|
+
|
|
417
|
+
# save json
|
|
418
|
+
if self.launch_worker:
|
|
419
|
+
self.save_out_yaml()
|
|
420
|
+
self.save_index()
|
|
421
|
+
|
|
422
|
+
# run compute and save files
|
|
423
|
+
logging.info("Compute delayed ...")
|
|
424
|
+
# Flatten to list
|
|
425
|
+
if only_remaining_delayed is None:
|
|
426
|
+
delayed_objects = flatten_object(
|
|
427
|
+
self.cars_ds_savers_registry.get_cars_datasets_list()
|
|
428
|
+
+ self.cars_ds_replacer_registry.get_cars_datasets_list()
|
|
429
|
+
+ self.cars_ds_compute_registry.get_cars_datasets_list(),
|
|
430
|
+
self.cluster.get_delayed_type(),
|
|
431
|
+
)
|
|
432
|
+
else:
|
|
433
|
+
delayed_objects = only_remaining_delayed
|
|
434
|
+
|
|
435
|
+
if len(delayed_objects) == 0:
|
|
436
|
+
logging.info("No Object to compute")
|
|
437
|
+
return
|
|
438
|
+
# Compute delayed
|
|
439
|
+
future_objects = self.cluster.start_tasks(delayed_objects)
|
|
440
|
+
|
|
441
|
+
# Save objects when they are computed
|
|
442
|
+
logging.info("Wait for futures results ...")
|
|
443
|
+
add_progress_message(
|
|
444
|
+
"Data list to process: [ {} ] ...".format(
|
|
445
|
+
" , ".join(list(set(self.cars_ds_names_info)))
|
|
446
|
+
)
|
|
447
|
+
)
|
|
448
|
+
tqdm_message = "Tiles processing: "
|
|
449
|
+
# if loglevel > PROGRESS level tqdm display the data list
|
|
450
|
+
if logging.getLogger().getEffectiveLevel() > 21:
|
|
451
|
+
tqdm_message = "Processing Tiles: [ {} ] ...".format(
|
|
452
|
+
" , ".join(list(set(self.cars_ds_names_info)))
|
|
453
|
+
)
|
|
454
|
+
pbar = tqdm(
|
|
455
|
+
total=len(future_objects),
|
|
456
|
+
desc=tqdm_message,
|
|
457
|
+
position=0,
|
|
458
|
+
leave=True,
|
|
459
|
+
file=sys.stdout,
|
|
460
|
+
)
|
|
461
|
+
nb_tiles_computed = 0
|
|
462
|
+
|
|
463
|
+
interval_was_cropped = False
|
|
464
|
+
try:
|
|
465
|
+
for future_obj in self.cluster.future_iterator(
|
|
466
|
+
future_objects, timeout=self.task_timeout
|
|
467
|
+
):
|
|
468
|
+
# get corresponding CarsDataset and save tile
|
|
469
|
+
if future_obj is not None:
|
|
470
|
+
if get_disparity_range_cropped(future_obj):
|
|
471
|
+
interval_was_cropped = True
|
|
472
|
+
# Apply function if exists
|
|
473
|
+
final_function = None
|
|
474
|
+
current_cars_ds = (
|
|
475
|
+
self.cars_ds_savers_registry.get_cars_ds(future_obj)
|
|
476
|
+
)
|
|
477
|
+
if current_cars_ds is None:
|
|
478
|
+
self.cars_ds_replacer_registry.get_cars_ds(
|
|
479
|
+
future_obj
|
|
480
|
+
)
|
|
481
|
+
if current_cars_ds is not None:
|
|
482
|
+
final_function = current_cars_ds.final_function
|
|
483
|
+
if final_function is not None:
|
|
484
|
+
future_obj = final_function(self, future_obj)
|
|
485
|
+
# Save future if needs to
|
|
486
|
+
self.cars_ds_savers_registry.save(future_obj)
|
|
487
|
+
# Replace future in cars_ds if needs to
|
|
488
|
+
self.cars_ds_replacer_registry.replace(future_obj)
|
|
489
|
+
# notify tile profiler for new tile
|
|
490
|
+
self.tile_profiler.add_tile(future_obj)
|
|
491
|
+
# update achievement
|
|
492
|
+
self.achievement_tracker.add_tile(future_obj)
|
|
493
|
+
nb_tiles_computed += 1
|
|
494
|
+
else:
|
|
495
|
+
logging.debug("None tile: not saved")
|
|
496
|
+
pbar.update()
|
|
497
|
+
|
|
498
|
+
except TimeoutError:
|
|
499
|
+
logging.error("TimeOut")
|
|
500
|
+
|
|
501
|
+
if interval_was_cropped:
|
|
502
|
+
logging.warning(
|
|
503
|
+
"Disparity range was cropped in DenseMatching, "
|
|
504
|
+
"due to a lack of available memory for estimated"
|
|
505
|
+
" disparity range"
|
|
506
|
+
)
|
|
507
|
+
|
|
508
|
+
remaining_tiles = self.achievement_tracker.get_remaining_tiles()
|
|
509
|
+
if len(remaining_tiles) > 0:
|
|
510
|
+
# Some tiles have not been computed
|
|
511
|
+
logging.info(
|
|
512
|
+
"{} tiles have not been computed".format(
|
|
513
|
+
len(remaining_tiles)
|
|
514
|
+
)
|
|
515
|
+
)
|
|
516
|
+
if only_remaining_delayed is None:
|
|
517
|
+
# First try
|
|
518
|
+
logging.info("Retry failed tasks ...")
|
|
519
|
+
self.reset_cluster()
|
|
520
|
+
del pbar
|
|
521
|
+
self.compute_futures(only_remaining_delayed=remaining_tiles)
|
|
522
|
+
else:
|
|
523
|
+
# Second try
|
|
524
|
+
logging.error("Pipeline will pursue without failed tiles")
|
|
525
|
+
self.cars_ds_replacer_registry.replace_lasting_jobs(
|
|
526
|
+
self.cluster.get_delayed_type()
|
|
527
|
+
)
|
|
528
|
+
self.reset_registries()
|
|
529
|
+
|
|
530
|
+
if nb_tiles_computed == 0:
|
|
531
|
+
logging.warning(
|
|
532
|
+
"Result have not been saved because all tiles are None"
|
|
533
|
+
)
|
|
534
|
+
|
|
535
|
+
# close files
|
|
536
|
+
logging.info("Close files ...")
|
|
537
|
+
self.cars_ds_savers_registry.cleanup()
|
|
538
|
+
else:
|
|
539
|
+
logging.debug(
|
|
540
|
+
"orchestrator launch_worker is False, no metadata.json saved"
|
|
541
|
+
)
|
|
542
|
+
|
|
543
|
+
def reset_cluster(self):
|
|
544
|
+
"""
|
|
545
|
+
Reset Cluster
|
|
546
|
+
|
|
547
|
+
"""
|
|
548
|
+
|
|
549
|
+
data_to_propagate = self.cluster.data_to_propagate
|
|
550
|
+
|
|
551
|
+
if self.launch_worker:
|
|
552
|
+
self.cluster.cleanup(keep_shared_dir=True)
|
|
553
|
+
self.cluster = AbstractCluster( # pylint: disable=E0110
|
|
554
|
+
self.orchestrator_conf,
|
|
555
|
+
self.out_dir,
|
|
556
|
+
self.log_dir,
|
|
557
|
+
launch_worker=self.launch_worker,
|
|
558
|
+
data_to_propagate=data_to_propagate,
|
|
559
|
+
)
|
|
560
|
+
|
|
561
|
+
def reset_registries(self):
|
|
562
|
+
"""
|
|
563
|
+
Reset registries
|
|
564
|
+
"""
|
|
565
|
+
|
|
566
|
+
# cleanup the current registry before replacing it, to save files
|
|
567
|
+
self.cars_ds_savers_registry.cleanup()
|
|
568
|
+
|
|
569
|
+
# reset registries
|
|
570
|
+
# CarsDataset savers registry
|
|
571
|
+
self.cars_ds_savers_registry = saver_registry.CarsDatasetsRegistrySaver(
|
|
572
|
+
self.id_generator
|
|
573
|
+
)
|
|
574
|
+
|
|
575
|
+
# CarsDataset replacement registry
|
|
576
|
+
self.cars_ds_replacer_registry = (
|
|
577
|
+
replacer_registry.CarsDatasetRegistryReplacer(self.id_generator)
|
|
578
|
+
)
|
|
579
|
+
# Compute registry
|
|
580
|
+
self.cars_ds_compute_registry = (
|
|
581
|
+
compute_registry.CarsDatasetRegistryCompute(self.id_generator)
|
|
582
|
+
)
|
|
583
|
+
|
|
584
|
+
# tile profiler
|
|
585
|
+
self.tile_profiler = TileProfiler(
|
|
586
|
+
self.dir_tile_profiling,
|
|
587
|
+
self.cars_ds_savers_registry,
|
|
588
|
+
self.cars_ds_replacer_registry,
|
|
589
|
+
)
|
|
590
|
+
|
|
591
|
+
# achievement tracker
|
|
592
|
+
self.achievement_tracker = achievement_tracker.AchievementTracker()
|
|
593
|
+
|
|
594
|
+
# reset cars_ds names infos
|
|
595
|
+
self.cars_ds_names_info = []
|
|
596
|
+
|
|
597
|
+
@cars_profile(name="Compute futures")
|
|
598
|
+
def breakpoint(self):
|
|
599
|
+
"""
|
|
600
|
+
Breakpoint : compute all delayed, save and replace data
|
|
601
|
+
in CarsDatasets
|
|
602
|
+
|
|
603
|
+
"""
|
|
604
|
+
|
|
605
|
+
# Compute futures
|
|
606
|
+
try:
|
|
607
|
+
self.compute_futures()
|
|
608
|
+
except Exception as exc:
|
|
609
|
+
# reset registries
|
|
610
|
+
self.reset_registries()
|
|
611
|
+
raise RuntimeError(traceback.format_exc()) from exc
|
|
612
|
+
|
|
613
|
+
# reset registries
|
|
614
|
+
self.reset_registries()
|
|
615
|
+
|
|
616
|
+
def cleanup(self):
|
|
617
|
+
"""
|
|
618
|
+
Cleanup orchestrator
|
|
619
|
+
|
|
620
|
+
"""
|
|
621
|
+
|
|
622
|
+
# close cluster
|
|
623
|
+
logging.info("Close cluster ...")
|
|
624
|
+
if self.launch_worker:
|
|
625
|
+
self.cluster.cleanup()
|
|
626
|
+
|
|
627
|
+
# # clean tmp dir
|
|
628
|
+
for tmp_dir in self.tmp_dir_list:
|
|
629
|
+
if tmp_dir is not None and os.path.exists(tmp_dir):
|
|
630
|
+
shutil.rmtree(tmp_dir)
|
|
631
|
+
|
|
632
|
+
def __enter__(self):
|
|
633
|
+
"""
|
|
634
|
+
Function run on enter
|
|
635
|
+
|
|
636
|
+
"""
|
|
637
|
+
|
|
638
|
+
return self
|
|
639
|
+
|
|
640
|
+
def __exit__(self, exc_type, exc_value, traceback_msg):
|
|
641
|
+
"""
|
|
642
|
+
Function run on exit.
|
|
643
|
+
|
|
644
|
+
Compute cluster tasks, save futures to be saved, and cleanup cluster
|
|
645
|
+
and files
|
|
646
|
+
|
|
647
|
+
"""
|
|
648
|
+
|
|
649
|
+
# Compute futures
|
|
650
|
+
self.breakpoint()
|
|
651
|
+
|
|
652
|
+
# save outjson
|
|
653
|
+
# TODO
|
|
654
|
+
|
|
655
|
+
# TODO : check_json
|
|
656
|
+
|
|
657
|
+
# cleanup
|
|
658
|
+
self.cleanup()
|
|
659
|
+
|
|
660
|
+
|
|
661
|
+
def merge_dicts(dict1, dict2):
|
|
662
|
+
"""
|
|
663
|
+
Merge dict2 into dict 1
|
|
664
|
+
|
|
665
|
+
:param dict1: dict 1
|
|
666
|
+
:type dict1: dict
|
|
667
|
+
:param dict2: dict 2
|
|
668
|
+
:type dict2: dict
|
|
669
|
+
|
|
670
|
+
"""
|
|
671
|
+
|
|
672
|
+
for key, value2 in dict2.items():
|
|
673
|
+
value1 = dict1.get(key)
|
|
674
|
+
if isinstance(value1, collections.abc.Mapping) and isinstance(
|
|
675
|
+
value2, collections.abc.Mapping
|
|
676
|
+
):
|
|
677
|
+
merge_dicts(value1, value2)
|
|
678
|
+
else:
|
|
679
|
+
dict1[key] = value2
|
|
680
|
+
|
|
681
|
+
|
|
682
|
+
def flatten_object(cars_ds_list, delayed_type):
|
|
683
|
+
"""
|
|
684
|
+
Flatten list of CarsDatasets to list of delayed
|
|
685
|
+
|
|
686
|
+
:param cars_ds_list: list of cars datasets flatten
|
|
687
|
+
:type cars_ds_list: list[CarsDataset]
|
|
688
|
+
:param delayed_type: type of delayed
|
|
689
|
+
|
|
690
|
+
:return: list of delayed
|
|
691
|
+
:rtype: list[Delayed]
|
|
692
|
+
"""
|
|
693
|
+
|
|
694
|
+
# remove duplicates
|
|
695
|
+
cleaned_cars_ds_list = list(dict.fromkeys(cars_ds_list))
|
|
696
|
+
|
|
697
|
+
# flatten datasets
|
|
698
|
+
flattened_objects = []
|
|
699
|
+
|
|
700
|
+
if len(cleaned_cars_ds_list) == 1 and cleaned_cars_ds_list[0] is None:
|
|
701
|
+
return []
|
|
702
|
+
|
|
703
|
+
# add obj flattened
|
|
704
|
+
for cars_ds in cleaned_cars_ds_list:
|
|
705
|
+
flattened_objects += [
|
|
706
|
+
obj
|
|
707
|
+
for obj_list in cars_ds.tiles
|
|
708
|
+
for obj in obj_list
|
|
709
|
+
if isinstance(obj, delayed_type) and obj is not None
|
|
710
|
+
]
|
|
711
|
+
|
|
712
|
+
return flattened_objects
|
|
713
|
+
|
|
714
|
+
|
|
715
|
+
def update_saving_infos(saving_info_left, row=None, col=None):
|
|
716
|
+
"""
|
|
717
|
+
Update saving infos dict with row and col arguments
|
|
718
|
+
|
|
719
|
+
:param saving_info_left: saving infos
|
|
720
|
+
:type saving_info_left: dict
|
|
721
|
+
:param row: row
|
|
722
|
+
:type row: int
|
|
723
|
+
:param col: col
|
|
724
|
+
:type col: int
|
|
725
|
+
|
|
726
|
+
:return: updated saving infos dict
|
|
727
|
+
:rtype: dict
|
|
728
|
+
"""
|
|
729
|
+
|
|
730
|
+
full_saving_infos = saving_info_left.copy()
|
|
731
|
+
|
|
732
|
+
if row is not None:
|
|
733
|
+
full_saving_infos[CARS_DS_ROW] = row
|
|
734
|
+
|
|
735
|
+
if col is not None:
|
|
736
|
+
full_saving_infos[CARS_DS_COL] = col
|
|
737
|
+
|
|
738
|
+
return full_saving_infos
|
|
739
|
+
|
|
740
|
+
|
|
741
|
+
def get_disparity_range_cropped(obj):
|
|
742
|
+
"""
|
|
743
|
+
Get CROPPED_DISPARITY_RANGE value in attributes
|
|
744
|
+
|
|
745
|
+
:param obj: object to look in
|
|
746
|
+
|
|
747
|
+
:rtype bool
|
|
748
|
+
"""
|
|
749
|
+
|
|
750
|
+
value = False
|
|
751
|
+
|
|
752
|
+
if isinstance(obj, (xarray.Dataset, pandas.DataFrame)):
|
|
753
|
+
obj_attributes = cars_dataset.get_attributes(obj)
|
|
754
|
+
if obj_attributes is not None:
|
|
755
|
+
value = obj_attributes.get(cst.CROPPED_DISPARITY_RANGE, False)
|
|
756
|
+
|
|
757
|
+
return value
|
|
758
|
+
|
|
759
|
+
|
|
760
|
+
def get_slurm_data():
|
|
761
|
+
"""
|
|
762
|
+
Get slurm data
|
|
763
|
+
"""
|
|
764
|
+
|
|
765
|
+
def get_data(chain, pattern):
|
|
766
|
+
"""
|
|
767
|
+
Get data from pattern
|
|
768
|
+
|
|
769
|
+
:param chain: chain of character to parse
|
|
770
|
+
:param pattern: pattern to find
|
|
771
|
+
|
|
772
|
+
:return: found data
|
|
773
|
+
"""
|
|
774
|
+
|
|
775
|
+
match = re.search(pattern, chain)
|
|
776
|
+
value = None
|
|
777
|
+
if match:
|
|
778
|
+
value = match.group(1)
|
|
779
|
+
return int(value)
|
|
780
|
+
|
|
781
|
+
on_slurm = False
|
|
782
|
+
slurm_nb_cpu = None
|
|
783
|
+
slurm_max_ram = None
|
|
784
|
+
try:
|
|
785
|
+
sub_res = subprocess.run(
|
|
786
|
+
"scontrol show job $SLURM_JOB_ID",
|
|
787
|
+
shell=True,
|
|
788
|
+
capture_output=True,
|
|
789
|
+
text=True,
|
|
790
|
+
check=False,
|
|
791
|
+
)
|
|
792
|
+
slurm_infos = sub_res.stdout
|
|
793
|
+
|
|
794
|
+
slurm_nb_cpu = get_data(slurm_infos, r"ReqTRES=cpu=(\d+)")
|
|
795
|
+
slurm_max_ram = get_data(slurm_infos, r"ReqTRES=cpu=.*?mem=(\d+)")
|
|
796
|
+
# convert to Mb
|
|
797
|
+
slurm_max_ram *= 1024
|
|
798
|
+
logging.info("Available CPUs in SLURM : {}".format(slurm_nb_cpu))
|
|
799
|
+
logging.info("Available RAM in SLURM : {}".format(slurm_max_ram))
|
|
800
|
+
|
|
801
|
+
except Exception as _:
|
|
802
|
+
logging.debug("Not on Slurm cluster")
|
|
803
|
+
|
|
804
|
+
if slurm_nb_cpu is not None and slurm_max_ram is not None:
|
|
805
|
+
on_slurm = True
|
|
806
|
+
|
|
807
|
+
return on_slurm, slurm_nb_cpu, slurm_max_ram
|
|
808
|
+
|
|
809
|
+
|
|
810
|
+
def compute_conf_auto_mode(is_windows):
|
|
811
|
+
"""
|
|
812
|
+
Compute confuration to use in auto mode
|
|
813
|
+
|
|
814
|
+
:param is_windows: True if runs on windows
|
|
815
|
+
:type is_windows: bool
|
|
816
|
+
"""
|
|
817
|
+
|
|
818
|
+
on_slurm, nb_cpu_slurm, max_ram_slurm = get_slurm_data()
|
|
819
|
+
|
|
820
|
+
if on_slurm:
|
|
821
|
+
available_cpu = nb_cpu_slurm
|
|
822
|
+
else:
|
|
823
|
+
available_cpu = (
|
|
824
|
+
multiprocessing.cpu_count()
|
|
825
|
+
if is_windows
|
|
826
|
+
else len(os.sched_getaffinity(0))
|
|
827
|
+
)
|
|
828
|
+
logging.info("available cpu : {}".format(available_cpu))
|
|
829
|
+
|
|
830
|
+
if available_cpu == 1:
|
|
831
|
+
logging.warning("Only one CPU detected.")
|
|
832
|
+
available_cpu = 2
|
|
833
|
+
elif available_cpu == 0:
|
|
834
|
+
logging.warning("No CPU detected.")
|
|
835
|
+
available_cpu = 2
|
|
836
|
+
|
|
837
|
+
if on_slurm:
|
|
838
|
+
ram_to_use = max_ram_slurm
|
|
839
|
+
else:
|
|
840
|
+
ram_to_use = get_total_ram()
|
|
841
|
+
logging.info("total ram : {}".format(ram_to_use))
|
|
842
|
+
|
|
843
|
+
# use 50% of total ram
|
|
844
|
+
ram_to_use *= 0.5
|
|
845
|
+
|
|
846
|
+
# non configurable
|
|
847
|
+
max_ram_per_worker = 2000
|
|
848
|
+
possible_workers = int(ram_to_use // max_ram_per_worker)
|
|
849
|
+
if possible_workers == 0:
|
|
850
|
+
logging.warning("Not enough memory available : failure might occur")
|
|
851
|
+
nb_workers_to_use = max(1, min(possible_workers, available_cpu - 1))
|
|
852
|
+
|
|
853
|
+
logging.info("Number of workers : {}".format(nb_workers_to_use))
|
|
854
|
+
logging.info("Max memory per worker : {} MB".format(max_ram_per_worker))
|
|
855
|
+
|
|
856
|
+
# Check with available ram
|
|
857
|
+
available_ram = get_available_ram()
|
|
858
|
+
if int(nb_workers_to_use) * int(max_ram_per_worker) > available_ram:
|
|
859
|
+
logging.warning(
|
|
860
|
+
"CARS will use 50% of total RAM, "
|
|
861
|
+
" more than currently available RAM"
|
|
862
|
+
)
|
|
863
|
+
|
|
864
|
+
return int(nb_workers_to_use), int(max_ram_per_worker)
|
|
865
|
+
|
|
866
|
+
|
|
867
|
+
def get_available_ram():
|
|
868
|
+
"""
|
|
869
|
+
Get available ram
|
|
870
|
+
|
|
871
|
+
:return : available ram in Mb
|
|
872
|
+
"""
|
|
873
|
+
ram = psutil.virtual_memory()
|
|
874
|
+
available_ram_mb = ram.available / (1024 * 1024)
|
|
875
|
+
return available_ram_mb
|
|
876
|
+
|
|
877
|
+
|
|
878
|
+
def get_total_ram():
|
|
879
|
+
"""
|
|
880
|
+
Get total ram
|
|
881
|
+
|
|
882
|
+
:return : available ram in Mb
|
|
883
|
+
"""
|
|
884
|
+
ram = psutil.virtual_memory()
|
|
885
|
+
total_ram_mb = ram.available / (1024 * 1024)
|
|
886
|
+
return total_ram_mb
|
|
887
|
+
|
|
888
|
+
|
|
889
|
+
def check_ram_usage():
|
|
890
|
+
"""
|
|
891
|
+
Check RAM usage
|
|
892
|
+
"""
|
|
893
|
+
while True:
|
|
894
|
+
# Get Ram information
|
|
895
|
+
available_ram_mb = get_available_ram()
|
|
896
|
+
|
|
897
|
+
if available_ram_mb < RAM_THRESHOLD_MB:
|
|
898
|
+
logging.warning(
|
|
899
|
+
"RAM available < {} Mb, available ram: {} Mb."
|
|
900
|
+
" Freeze might ocure".format(
|
|
901
|
+
RAM_THRESHOLD_MB, int(available_ram_mb)
|
|
902
|
+
)
|
|
903
|
+
)
|
|
904
|
+
|
|
905
|
+
time.sleep(RAM_CHECK_SLEEP_TIME)
|