cars 1.0.0rc2__cp312-cp312-win_amd64.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of cars might be problematic. Click here for more details.

Files changed (225) hide show
  1. cars/__init__.py +86 -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 +42 -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.cp312-win_amd64.dll.a +0 -0
  30. cars/applications/dense_matching/cpp/dense_matching_cpp.cp312-win_amd64.pyd +0 -0
  31. cars/applications/dense_matching/cpp/dense_matching_cpp.py +94 -0
  32. cars/applications/dense_matching/cpp/includes/dense_matching.hpp +58 -0
  33. cars/applications/dense_matching/cpp/meson.build +9 -0
  34. cars/applications/dense_matching/cpp/src/bindings.cpp +13 -0
  35. cars/applications/dense_matching/cpp/src/dense_matching.cpp +207 -0
  36. cars/applications/dense_matching/dense_matching_algo.py +401 -0
  37. cars/applications/dense_matching/dense_matching_constants.py +89 -0
  38. cars/applications/dense_matching/dense_matching_wrappers.py +951 -0
  39. cars/applications/dense_matching/disparity_grid_algo.py +597 -0
  40. cars/applications/dense_matching/loaders/__init__.py +23 -0
  41. cars/applications/dense_matching/loaders/config_census_sgm_default.json +31 -0
  42. cars/applications/dense_matching/loaders/config_census_sgm_homogeneous.json +30 -0
  43. cars/applications/dense_matching/loaders/config_census_sgm_mountain_and_vegetation.json +30 -0
  44. cars/applications/dense_matching/loaders/config_census_sgm_shadow.json +30 -0
  45. cars/applications/dense_matching/loaders/config_census_sgm_sparse.json +36 -0
  46. cars/applications/dense_matching/loaders/config_census_sgm_urban.json +30 -0
  47. cars/applications/dense_matching/loaders/config_mapping.json +13 -0
  48. cars/applications/dense_matching/loaders/config_mccnn.json +28 -0
  49. cars/applications/dense_matching/loaders/global_land_cover_map.tif +0 -0
  50. cars/applications/dense_matching/loaders/pandora_loader.py +593 -0
  51. cars/applications/dsm_filling/__init__.py +32 -0
  52. cars/applications/dsm_filling/abstract_dsm_filling_app.py +101 -0
  53. cars/applications/dsm_filling/border_interpolation_app.py +278 -0
  54. cars/applications/dsm_filling/bulldozer_config/base_config.yaml +44 -0
  55. cars/applications/dsm_filling/bulldozer_filling_app.py +288 -0
  56. cars/applications/dsm_filling/exogenous_filling_app.py +341 -0
  57. cars/applications/dsm_merging/__init__.py +28 -0
  58. cars/applications/dsm_merging/abstract_dsm_merging_app.py +101 -0
  59. cars/applications/dsm_merging/weighted_fusion_app.py +639 -0
  60. cars/applications/grid_correction/__init__.py +30 -0
  61. cars/applications/grid_correction/abstract_grid_correction_app.py +103 -0
  62. cars/applications/grid_correction/grid_correction_app.py +557 -0
  63. cars/applications/grid_generation/__init__.py +30 -0
  64. cars/applications/grid_generation/abstract_grid_generation_app.py +142 -0
  65. cars/applications/grid_generation/epipolar_grid_generation_app.py +327 -0
  66. cars/applications/grid_generation/grid_generation_algo.py +388 -0
  67. cars/applications/grid_generation/grid_generation_constants.py +46 -0
  68. cars/applications/grid_generation/transform_grid.py +88 -0
  69. cars/applications/ground_truth_reprojection/__init__.py +30 -0
  70. cars/applications/ground_truth_reprojection/abstract_ground_truth_reprojection_app.py +137 -0
  71. cars/applications/ground_truth_reprojection/direct_localization_app.py +629 -0
  72. cars/applications/ground_truth_reprojection/ground_truth_reprojection_algo.py +275 -0
  73. cars/applications/point_cloud_outlier_removal/__init__.py +30 -0
  74. cars/applications/point_cloud_outlier_removal/abstract_outlier_removal_app.py +385 -0
  75. cars/applications/point_cloud_outlier_removal/outlier_removal_algo.py +392 -0
  76. cars/applications/point_cloud_outlier_removal/outlier_removal_constants.py +43 -0
  77. cars/applications/point_cloud_outlier_removal/small_components_app.py +522 -0
  78. cars/applications/point_cloud_outlier_removal/statistical_app.py +528 -0
  79. cars/applications/rasterization/__init__.py +30 -0
  80. cars/applications/rasterization/abstract_pc_rasterization_app.py +183 -0
  81. cars/applications/rasterization/rasterization_algo.py +534 -0
  82. cars/applications/rasterization/rasterization_constants.py +38 -0
  83. cars/applications/rasterization/rasterization_wrappers.py +639 -0
  84. cars/applications/rasterization/simple_gaussian_app.py +1152 -0
  85. cars/applications/resampling/__init__.py +28 -0
  86. cars/applications/resampling/abstract_resampling_app.py +187 -0
  87. cars/applications/resampling/bicubic_resampling_app.py +760 -0
  88. cars/applications/resampling/resampling_algo.py +590 -0
  89. cars/applications/resampling/resampling_constants.py +36 -0
  90. cars/applications/resampling/resampling_wrappers.py +309 -0
  91. cars/applications/sensors_subsampling/__init__.py +32 -0
  92. cars/applications/sensors_subsampling/abstract_subsampling_app.py +109 -0
  93. cars/applications/sensors_subsampling/rasterio_subsampling_app.py +420 -0
  94. cars/applications/sensors_subsampling/subsampling_algo.py +108 -0
  95. cars/applications/sparse_matching/__init__.py +30 -0
  96. cars/applications/sparse_matching/abstract_sparse_matching_app.py +599 -0
  97. cars/applications/sparse_matching/sift_app.py +724 -0
  98. cars/applications/sparse_matching/sparse_matching_algo.py +360 -0
  99. cars/applications/sparse_matching/sparse_matching_constants.py +66 -0
  100. cars/applications/sparse_matching/sparse_matching_wrappers.py +282 -0
  101. cars/applications/triangulation/__init__.py +32 -0
  102. cars/applications/triangulation/abstract_triangulation_app.py +227 -0
  103. cars/applications/triangulation/line_of_sight_intersection_app.py +1243 -0
  104. cars/applications/triangulation/pc_transform.py +552 -0
  105. cars/applications/triangulation/triangulation_algo.py +371 -0
  106. cars/applications/triangulation/triangulation_constants.py +38 -0
  107. cars/applications/triangulation/triangulation_wrappers.py +259 -0
  108. cars/bundleadjustment.py +750 -0
  109. cars/cars.py +179 -0
  110. cars/conf/__init__.py +23 -0
  111. cars/conf/geoid/egm96.grd +0 -0
  112. cars/conf/geoid/egm96.grd.hdr +15 -0
  113. cars/conf/input_parameters.py +156 -0
  114. cars/conf/mask_cst.py +35 -0
  115. cars/core/__init__.py +23 -0
  116. cars/core/cars_logging.py +402 -0
  117. cars/core/constants.py +191 -0
  118. cars/core/constants_disparity.py +50 -0
  119. cars/core/datasets.py +140 -0
  120. cars/core/geometry/__init__.py +27 -0
  121. cars/core/geometry/abstract_geometry.py +1119 -0
  122. cars/core/geometry/shareloc_geometry.py +598 -0
  123. cars/core/inputs.py +568 -0
  124. cars/core/outputs.py +176 -0
  125. cars/core/preprocessing.py +722 -0
  126. cars/core/projection.py +843 -0
  127. cars/core/roi_tools.py +215 -0
  128. cars/core/tiling.py +774 -0
  129. cars/core/utils.py +164 -0
  130. cars/data_structures/__init__.py +23 -0
  131. cars/data_structures/cars_dataset.py +1544 -0
  132. cars/data_structures/cars_dict.py +74 -0
  133. cars/data_structures/corresponding_tiles_tools.py +186 -0
  134. cars/data_structures/dataframe_converter.py +185 -0
  135. cars/data_structures/format_transformation.py +297 -0
  136. cars/devibrate.py +689 -0
  137. cars/extractroi.py +264 -0
  138. cars/orchestrator/__init__.py +23 -0
  139. cars/orchestrator/achievement_tracker.py +125 -0
  140. cars/orchestrator/cluster/__init__.py +37 -0
  141. cars/orchestrator/cluster/abstract_cluster.py +250 -0
  142. cars/orchestrator/cluster/abstract_dask_cluster.py +381 -0
  143. cars/orchestrator/cluster/dask_cluster_tools.py +103 -0
  144. cars/orchestrator/cluster/dask_config/README.md +94 -0
  145. cars/orchestrator/cluster/dask_config/dask.yaml +21 -0
  146. cars/orchestrator/cluster/dask_config/distributed.yaml +70 -0
  147. cars/orchestrator/cluster/dask_config/jobqueue.yaml +26 -0
  148. cars/orchestrator/cluster/dask_config/reference_confs/dask-schema.yaml +137 -0
  149. cars/orchestrator/cluster/dask_config/reference_confs/dask.yaml +26 -0
  150. cars/orchestrator/cluster/dask_config/reference_confs/distributed-schema.yaml +1009 -0
  151. cars/orchestrator/cluster/dask_config/reference_confs/distributed.yaml +273 -0
  152. cars/orchestrator/cluster/dask_config/reference_confs/jobqueue.yaml +212 -0
  153. cars/orchestrator/cluster/dask_jobqueue_utils.py +204 -0
  154. cars/orchestrator/cluster/local_dask_cluster.py +116 -0
  155. cars/orchestrator/cluster/log_wrapper.py +728 -0
  156. cars/orchestrator/cluster/mp_cluster/__init__.py +27 -0
  157. cars/orchestrator/cluster/mp_cluster/mp_factorizer.py +212 -0
  158. cars/orchestrator/cluster/mp_cluster/mp_objects.py +535 -0
  159. cars/orchestrator/cluster/mp_cluster/mp_tools.py +93 -0
  160. cars/orchestrator/cluster/mp_cluster/mp_wrapper.py +505 -0
  161. cars/orchestrator/cluster/mp_cluster/multiprocessing_cluster.py +986 -0
  162. cars/orchestrator/cluster/mp_cluster/multiprocessing_profiler.py +399 -0
  163. cars/orchestrator/cluster/pbs_dask_cluster.py +207 -0
  164. cars/orchestrator/cluster/sequential_cluster.py +139 -0
  165. cars/orchestrator/cluster/slurm_dask_cluster.py +234 -0
  166. cars/orchestrator/memory_tools.py +47 -0
  167. cars/orchestrator/orchestrator.py +755 -0
  168. cars/orchestrator/orchestrator_constants.py +29 -0
  169. cars/orchestrator/registry/__init__.py +23 -0
  170. cars/orchestrator/registry/abstract_registry.py +143 -0
  171. cars/orchestrator/registry/compute_registry.py +106 -0
  172. cars/orchestrator/registry/id_generator.py +116 -0
  173. cars/orchestrator/registry/replacer_registry.py +213 -0
  174. cars/orchestrator/registry/saver_registry.py +363 -0
  175. cars/orchestrator/registry/unseen_registry.py +118 -0
  176. cars/orchestrator/tiles_profiler.py +279 -0
  177. cars/pipelines/__init__.py +26 -0
  178. cars/pipelines/conf_resolution/conf_final_resolution.yaml +5 -0
  179. cars/pipelines/conf_resolution/conf_first_resolution.yaml +4 -0
  180. cars/pipelines/conf_resolution/conf_intermediate_resolution.yaml +2 -0
  181. cars/pipelines/default/__init__.py +26 -0
  182. cars/pipelines/default/default_pipeline.py +1088 -0
  183. cars/pipelines/filling/__init__.py +26 -0
  184. cars/pipelines/filling/filling.py +981 -0
  185. cars/pipelines/formatting/__init__.py +26 -0
  186. cars/pipelines/formatting/formatting.py +186 -0
  187. cars/pipelines/merging/__init__.py +26 -0
  188. cars/pipelines/merging/merging.py +439 -0
  189. cars/pipelines/parameters/__init__.py +0 -0
  190. cars/pipelines/parameters/advanced_parameters.py +256 -0
  191. cars/pipelines/parameters/advanced_parameters_constants.py +68 -0
  192. cars/pipelines/parameters/application_parameters.py +72 -0
  193. cars/pipelines/parameters/depth_map_inputs.py +0 -0
  194. cars/pipelines/parameters/dsm_inputs.py +349 -0
  195. cars/pipelines/parameters/dsm_inputs_constants.py +25 -0
  196. cars/pipelines/parameters/output_constants.py +52 -0
  197. cars/pipelines/parameters/output_parameters.py +438 -0
  198. cars/pipelines/parameters/sensor_inputs.py +859 -0
  199. cars/pipelines/parameters/sensor_inputs_constants.py +51 -0
  200. cars/pipelines/parameters/sensor_loaders/__init__.py +29 -0
  201. cars/pipelines/parameters/sensor_loaders/basic_classif_loader.py +86 -0
  202. cars/pipelines/parameters/sensor_loaders/basic_image_loader.py +98 -0
  203. cars/pipelines/parameters/sensor_loaders/pivot_classif_loader.py +90 -0
  204. cars/pipelines/parameters/sensor_loaders/pivot_image_loader.py +105 -0
  205. cars/pipelines/parameters/sensor_loaders/sensor_loader.py +93 -0
  206. cars/pipelines/parameters/sensor_loaders/sensor_loader_template.py +71 -0
  207. cars/pipelines/parameters/sensor_loaders/slurp_classif_loader.py +86 -0
  208. cars/pipelines/pipeline.py +119 -0
  209. cars/pipelines/pipeline_constants.py +38 -0
  210. cars/pipelines/pipeline_template.py +135 -0
  211. cars/pipelines/subsampling/__init__.py +26 -0
  212. cars/pipelines/subsampling/subsampling.py +358 -0
  213. cars/pipelines/surface_modeling/__init__.py +26 -0
  214. cars/pipelines/surface_modeling/surface_modeling.py +2098 -0
  215. cars/pipelines/tie_points/__init__.py +26 -0
  216. cars/pipelines/tie_points/tie_points.py +536 -0
  217. cars/starter.py +167 -0
  218. cars-1.0.0rc2.dist-info/DELVEWHEEL +2 -0
  219. cars-1.0.0rc2.dist-info/METADATA +289 -0
  220. cars-1.0.0rc2.dist-info/RECORD +225 -0
  221. cars-1.0.0rc2.dist-info/WHEEL +4 -0
  222. cars-1.0.0rc2.dist-info/entry_points.txt +8 -0
  223. cars.libs/libgcc_s_seh-1-b2494fcbd4d80cf2c98fdd5261f6d850.dll +0 -0
  224. cars.libs/libstdc++-6-e9b0d12ae0e9555bbae55e8dfd08c3f7.dll +0 -0
  225. cars.libs/libwinpthread-1-7882d1b093714ccdfaf4e0789a817792.dll +0 -0
@@ -0,0 +1,399 @@
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
+ Contains multiprocessing_profiler class
23
+ """
24
+
25
+ import logging
26
+ import os
27
+ import threading
28
+ import time
29
+
30
+ import matplotlib
31
+ import matplotlib.pyplot as plt
32
+ import pandas as pd
33
+ import psutil
34
+
35
+ # Agg backend for non interactive
36
+ matplotlib.use("Agg")
37
+
38
+ TERMINATE = 1
39
+ RUN = 0
40
+ RAM_PER_WORKER_CHECK_SLEEP_TIME = 2
41
+ INTERVAL_CPU = 0.2
42
+ SAVE_TIME = 120
43
+
44
+ TIME = "time"
45
+ MAIN_MEMORY = "main_memory"
46
+ MAX_PROCESS_MEMORY = "max_process_memory"
47
+ MAIN_AND_PROCESS = "main_and_processes"
48
+ TOTAL_PROCESS_MEMORY = "total_process_memory"
49
+ AVAILABLE_RAM = "available_ram"
50
+ TOTAL_RAM = "total_ram"
51
+
52
+ MAIN_CPU_USAGE = "main_cpu_usage"
53
+ TOTAL_PROCESS_CPU_USAGE = "total Proces_cpu_usage"
54
+ MAIN_AND_PROCESS_CPU = "main_and_process_cpu"
55
+
56
+
57
+ class Timer: # pylint: disable=too-few-public-methods
58
+ """
59
+ Start time
60
+ """
61
+
62
+ def __init__(self):
63
+ """
64
+ Init
65
+ """
66
+ self.timer = time.time()
67
+
68
+
69
+ class MultiprocessingProfiler: # pylint: disable=too-few-public-methods
70
+ """
71
+ MultiprocessingProfiler
72
+
73
+ Used to profile memory in processes
74
+ """
75
+
76
+ def __init__( # pylint: disable=too-many-positional-arguments
77
+ self, pool, out_dir, max_ram_per_worker, mp_dataframe=None, timer=None
78
+ ):
79
+ """
80
+ Init function of MultiprocessingProfiler
81
+
82
+ :param pool: pool process to monitor
83
+ :param out_dir: out_dir to save graph
84
+ :param max_ram_per_worker: max ram per worker to use
85
+ """
86
+
87
+ self.main_pid = os.getpid()
88
+ self.pool = pool
89
+ self.out_dir = out_dir
90
+ self.file_plot = os.path.join(
91
+ self.out_dir, "profiling", "memory_profiling.png"
92
+ )
93
+ os.makedirs(os.path.dirname(self.file_plot), exist_ok=True)
94
+ self.max_ram_per_worker = max_ram_per_worker
95
+
96
+ if mp_dataframe is not None and timer is not None:
97
+ self.memory_data = mp_dataframe
98
+ self.timer = timer
99
+ else:
100
+ self.timer = Timer()
101
+ self.memory_data = pd.DataFrame(
102
+ columns=[
103
+ TIME,
104
+ MAIN_MEMORY,
105
+ MAX_PROCESS_MEMORY,
106
+ MAIN_AND_PROCESS,
107
+ TOTAL_PROCESS_MEMORY,
108
+ AVAILABLE_RAM,
109
+ TOTAL_RAM,
110
+ MAIN_CPU_USAGE,
111
+ TOTAL_PROCESS_CPU_USAGE,
112
+ MAIN_AND_PROCESS_CPU,
113
+ ]
114
+ )
115
+
116
+ # Memory usage of Pool
117
+ self.monitor_thread = threading.Thread(
118
+ target=check_pool_memory_usage,
119
+ args=(
120
+ self.main_pid,
121
+ self.pool,
122
+ self.max_ram_per_worker,
123
+ self.memory_data,
124
+ self.timer,
125
+ ),
126
+ )
127
+ self.monitor_thread.daemon = True
128
+ self.monitor_thread._state = RUN
129
+ self.monitor_thread.start()
130
+
131
+ self.saver_thread = threading.Thread(
132
+ target=save_figure_in_thread,
133
+ args=(self.memory_data, self.file_plot),
134
+ )
135
+ self.saver_thread.daemon = True
136
+ self.saver_thread._state = RUN
137
+ self.saver_thread.start()
138
+
139
+ def cleanup(self):
140
+ """
141
+ Cleanup
142
+ """
143
+
144
+ clean_thread(self.monitor_thread)
145
+ clean_thread(self.saver_thread)
146
+
147
+ def save_plot(self):
148
+ """
149
+ Save plots
150
+ """
151
+ logging.info("Save profiling plots ...")
152
+ try:
153
+ save_data(self.memory_data, self.file_plot)
154
+ except Exception as exc:
155
+ logging.warning("unable to save monitoring graph : {}".format(exc))
156
+
157
+
158
+ def clean_thread(thread):
159
+ """
160
+ Clean thread
161
+
162
+ :param thread: thread to clean
163
+ """
164
+ # Terminate worker
165
+ thread._state = TERMINATE # pylint: disable=W0212
166
+ while thread.is_alive():
167
+ time.sleep(0)
168
+
169
+
170
+ def get_process_memory(process):
171
+ """
172
+ Get process current memory
173
+
174
+ :param process
175
+
176
+ :return: memory Mb
177
+ """
178
+ return process.memory_info().rss / (1024 * 1024)
179
+
180
+
181
+ def get_cpu_usage(process):
182
+ """
183
+ Get cpu usage
184
+
185
+ :param process: Process to monitor
186
+ """
187
+
188
+ try:
189
+ cpu_usage = process.cpu_percent(interval=0.1)
190
+ except Exception:
191
+ cpu_usage = 0
192
+
193
+ return cpu_usage
194
+
195
+
196
+ def save_figure_in_thread(to_fill_dataframe, file_path):
197
+ """
198
+ Save data during compute
199
+
200
+ :param to_fill_dataframe: dataframe to fill
201
+ :param file_path: path to save path
202
+ """
203
+
204
+ thread = threading.current_thread()
205
+
206
+ start_time = time.time()
207
+ while thread._state == RUN: # pylint: disable=protected-access
208
+ time.sleep(RAM_PER_WORKER_CHECK_SLEEP_TIME)
209
+ if time.time() - start_time > SAVE_TIME:
210
+ start_time = time.time()
211
+ # Save file
212
+ try:
213
+ save_data(to_fill_dataframe, file_path)
214
+ except Exception as exc:
215
+ logging.warning(
216
+ "unable to save monitoring graph : {}".format(exc)
217
+ )
218
+
219
+
220
+ def check_pool_memory_usage(
221
+ main_process_id, pool, max_ram_per_worker, to_fill_dataframe, timer
222
+ ):
223
+ """
224
+ Check memory usage of each worker in pool
225
+
226
+ :param main_process_id: main process id
227
+ :param pool: pool of worker
228
+ :param max_ram_per_worker: max ram to use per worker
229
+ :param to_fill_dataframe: dataframe to fill
230
+ :param timer: timer
231
+ """
232
+
233
+ thread = threading.current_thread()
234
+
235
+ main_process = psutil.Process(main_process_id)
236
+ start_time = timer.timer
237
+
238
+ while thread._state == RUN: # pylint: disable=protected-access
239
+ # Get time
240
+ current_time = time.time() - start_time
241
+ minutes = current_time / 60
242
+
243
+ # Get available memory
244
+ ram = psutil.virtual_memory()
245
+ total_ram = ram.total / (1024 * 1024)
246
+ available = ram.available / (1024 * 1024)
247
+
248
+ # Check main process
249
+ main_current_memory = get_process_memory(main_process)
250
+ main_process_cpu = get_cpu_usage(main_process)
251
+
252
+ # Check workers
253
+ main_and_processes_total = main_current_memory
254
+ total_memory = 0
255
+ max_process_ram = 0
256
+ processes_cpu = 0
257
+ total_cpu = main_process_cpu
258
+
259
+ size_pool = len(pool._pool) # pylint: disable=protected-access
260
+ sleep_time = max(
261
+ 0, RAM_PER_WORKER_CHECK_SLEEP_TIME - INTERVAL_CPU * size_pool
262
+ )
263
+ for worker in pool._pool: # pylint: disable=protected-access
264
+ pid = worker.pid
265
+ try:
266
+ process = psutil.Process(pid)
267
+ memory_usage_mb = get_process_memory(process)
268
+
269
+ # Add to metrics
270
+ max_process_ram = max(max_process_ram, memory_usage_mb)
271
+ total_memory += memory_usage_mb
272
+ processes_cpu += get_cpu_usage(process)
273
+
274
+ # Check memory to inform user
275
+ if memory_usage_mb > max_ram_per_worker:
276
+ logging.info(
277
+ "Process {} is using {} Mb > "
278
+ "max_ram_per_worker = {} Mb".format(
279
+ pid, memory_usage_mb, max_ram_per_worker
280
+ )
281
+ )
282
+ except psutil.NoSuchProcess:
283
+ # Process no longer exists
284
+ pass
285
+
286
+ main_and_processes_total += total_memory
287
+ available_ram_mb = main_and_processes_total + available
288
+
289
+ total_cpu += processes_cpu
290
+
291
+ # Add to dataframe
292
+ to_fill_dataframe.loc[len(to_fill_dataframe)] = [
293
+ minutes,
294
+ main_current_memory,
295
+ max_process_ram,
296
+ main_and_processes_total,
297
+ total_memory,
298
+ available_ram_mb,
299
+ total_ram,
300
+ main_process_cpu,
301
+ processes_cpu,
302
+ total_cpu,
303
+ ]
304
+
305
+ time.sleep(sleep_time)
306
+
307
+
308
+ def save_data(dataframe, file_path):
309
+ """
310
+ Save dataframe to disk
311
+
312
+ :param dataframe: file
313
+ :param file_path:
314
+ """
315
+
316
+ fig, axs = plt.subplots(5, 1, figsize=(10, 25))
317
+
318
+ axs[0].set_title("Total memory used by CARS Mb")
319
+ axs[0].set_xlabel("Time (min)")
320
+ axs[0].set_ylabel("Memory (MB)")
321
+ dataframe.plot(
322
+ x=TIME,
323
+ y=MAIN_AND_PROCESS,
324
+ ax=axs[0],
325
+ label="Main + Processes memory",
326
+ color="blue",
327
+ )
328
+ dataframe.plot(
329
+ x=TIME, y=TOTAL_RAM, ax=axs[0], label="Machine max memory", color="red"
330
+ )
331
+ dataframe.plot(
332
+ x=TIME,
333
+ y=AVAILABLE_RAM,
334
+ ax=axs[0],
335
+ label=" total CARS + still Available memory",
336
+ color="green",
337
+ )
338
+
339
+ axs[1].set_title("Main CARS Process Memory Mb")
340
+ axs[1].set_xlabel("Time (min)")
341
+ axs[1].set_ylabel("Memory (MB)")
342
+ dataframe.plot(
343
+ x=TIME,
344
+ y=MAIN_MEMORY,
345
+ ax=axs[1],
346
+ label="CARS main process",
347
+ color="blue",
348
+ )
349
+ dataframe.plot(
350
+ x=TIME,
351
+ y=MAX_PROCESS_MEMORY,
352
+ ax=axs[1],
353
+ label="CARS max of workers ",
354
+ color="red",
355
+ )
356
+
357
+ axs[2].set_title("CARS workers Process Memory Mb")
358
+ axs[2].set_xlabel("Time (min)")
359
+ axs[2].set_ylabel("Memory (MB)")
360
+ dataframe.plot(
361
+ x=TIME,
362
+ y=TOTAL_PROCESS_MEMORY,
363
+ ax=axs[2],
364
+ label="Total Process Memory",
365
+ color="blue",
366
+ )
367
+
368
+ axs[3].set_title("CARS CPU Usage")
369
+ axs[3].set_xlabel("Time (min)")
370
+ axs[3].set_ylabel("CPU (%")
371
+ dataframe.plot(
372
+ x=TIME,
373
+ y=TOTAL_PROCESS_CPU_USAGE,
374
+ ax=axs[3],
375
+ label="Total Process CPU ",
376
+ color="blue",
377
+ )
378
+ dataframe.plot(
379
+ x=TIME,
380
+ y=MAIN_AND_PROCESS_CPU,
381
+ ax=axs[3],
382
+ label="MAIN + Total Process CPU",
383
+ color="red",
384
+ )
385
+
386
+ axs[4].set_title("CARS CPU Usage of main process")
387
+ axs[4].set_xlabel("Time (min)")
388
+ axs[4].set_ylabel("CPU (%")
389
+ dataframe.plot(
390
+ x=TIME,
391
+ y=MAIN_CPU_USAGE,
392
+ ax=axs[4],
393
+ label="Main Process CPU ",
394
+ color="blue",
395
+ )
396
+
397
+ plt.savefig(file_path, format="png")
398
+
399
+ plt.close(fig)
@@ -0,0 +1,207 @@
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
+ Contains abstract function for PBS dask Cluster
23
+ """
24
+
25
+ # Standard imports
26
+ import logging
27
+ import os
28
+ import warnings
29
+
30
+ # Third party imports
31
+ from dask.distributed import Client
32
+
33
+ from cars.orchestrator.cluster.dask_cluster_tools import (
34
+ check_configuration,
35
+ create_checker_schema,
36
+ )
37
+ from cars.orchestrator.cluster.dask_jobqueue_utils import (
38
+ get_dashboard_link,
39
+ init_cluster_variables,
40
+ stop_cluster,
41
+ )
42
+
43
+ with warnings.catch_warnings():
44
+ # Ignore some internal dask_jobqueue warnings
45
+ warnings.filterwarnings(
46
+ "ignore",
47
+ category=FutureWarning,
48
+ message=".*format_bytes is deprecated.*",
49
+ )
50
+ warnings.filterwarnings(
51
+ "ignore",
52
+ category=FutureWarning,
53
+ message=".*parse_bytes is deprecated.*",
54
+ )
55
+ warnings.filterwarnings(
56
+ "ignore",
57
+ category=FutureWarning,
58
+ message=".*tmpfile is deprecated.*",
59
+ )
60
+ from dask_jobqueue import PBSCluster
61
+
62
+ # CARS imports
63
+ from cars.orchestrator.cluster import ( # pylint: disable=C0412
64
+ abstract_cluster,
65
+ abstract_dask_cluster,
66
+ )
67
+
68
+
69
+ @abstract_cluster.AbstractCluster.register_subclass("pbs_dask")
70
+ class PbsDaskCluster(abstract_dask_cluster.AbstractDaskCluster):
71
+ """
72
+ PbsDaskCluster
73
+ """
74
+
75
+ def check_conf(self, conf):
76
+ """
77
+ Check configuration
78
+
79
+ :param conf: configuration to check
80
+ :type conf: dict
81
+
82
+ :return: overloaded configuration
83
+ :rtype: dict
84
+
85
+ """
86
+
87
+ return check_configuration(*create_checker_schema(conf))
88
+
89
+ def start_dask_cluster(self):
90
+ """
91
+ Start dask cluster
92
+ """
93
+
94
+ return start_cluster(
95
+ self.nb_workers,
96
+ self.walltime,
97
+ self.out_dir,
98
+ activate_dashboard=self.activate_dashboard,
99
+ python=self.python,
100
+ )
101
+
102
+ def cleanup(self):
103
+ """
104
+ Cleanup cluster
105
+
106
+ """
107
+ stop_cluster(self.cluster, self.client)
108
+ logging.info("Dask cluster closed")
109
+
110
+
111
+ def start_cluster( # pylint: disable=too-many-positional-arguments
112
+ nb_workers,
113
+ walltime,
114
+ out_dir,
115
+ timeout=600,
116
+ activate_dashboard=False,
117
+ python=None,
118
+ ):
119
+ """Create a Dask cluster.
120
+
121
+ Each worker will be spawned in an independent job with a single CPU
122
+ allocated to it, and will use a single process. This is done to maximize
123
+ CPU utilization and minimize scheduling delay.
124
+
125
+ The CARS_PBS_QUEUE environment variable, if defined, is used to specify the
126
+ queue in which worker jobs are scheduled.
127
+
128
+ :param nb_workers: Number of dask workers
129
+ :type nb_workers: int
130
+ :param walltime: Walltime for each dask worker
131
+ :type walltime: string
132
+ :param out_dir: Output directory
133
+ :type out_dir: string
134
+ :return: Dask cluster and dask client
135
+ :rtype: (dask_jobqueue.PBSCluster, dask.distributed.Client) tuple
136
+ """
137
+
138
+ (
139
+ python,
140
+ nb_workers_per_job,
141
+ memory,
142
+ nb_cpus,
143
+ stagger,
144
+ lifetime_with_margin,
145
+ scheduler_options,
146
+ envs,
147
+ log_directory,
148
+ local_directory,
149
+ ) = init_cluster_variables(
150
+ nb_workers,
151
+ walltime,
152
+ out_dir,
153
+ activate_dashboard,
154
+ python,
155
+ core_memory=5000,
156
+ cluster_name="PBS",
157
+ )
158
+
159
+ # Retrieve PBS queue
160
+ pbs_queue = os.environ.get("CARS_PBS_QUEUE")
161
+
162
+ with warnings.catch_warnings():
163
+ # Ignore some internal dask_jobqueue warnings
164
+ # TODO remove when Future warning do not exist anymore
165
+ warnings.filterwarnings(
166
+ "ignore",
167
+ category=FutureWarning,
168
+ message=".*extra has been renamed to worker_extra_args*",
169
+ )
170
+ warnings.filterwarnings(
171
+ "ignore",
172
+ category=FutureWarning,
173
+ message=".*job_extra has been renamed to job_extra_directives*",
174
+ )
175
+ warnings.filterwarnings(
176
+ "ignore",
177
+ category=FutureWarning,
178
+ message=".*env_extra has been renamed to job_script_prologue*",
179
+ )
180
+ cluster = PBSCluster(
181
+ processes=nb_workers_per_job,
182
+ cores=nb_workers_per_job,
183
+ memory="{}MiB".format(memory),
184
+ local_directory=local_directory,
185
+ account="dask-test",
186
+ walltime=walltime,
187
+ interface="ib0",
188
+ queue=pbs_queue,
189
+ job_script_prologue=envs,
190
+ log_directory=log_directory,
191
+ python=python,
192
+ worker_extra_args=[
193
+ "--lifetime",
194
+ f"{int(lifetime_with_margin.total_seconds())}s",
195
+ "--lifetime-stagger",
196
+ f"{int(stagger.total_seconds())}s",
197
+ ],
198
+ scheduler_options=scheduler_options,
199
+ resource_spec="select=1:ncpus={}:mem={}MB".format(nb_cpus, memory),
200
+ )
201
+ logging.info("Dask cluster started")
202
+ cluster.adapt(minimum=nb_workers, maximum=nb_workers)
203
+ client = Client(cluster, timeout=timeout)
204
+ logging.info(
205
+ "Dashboard started at {}".format(get_dashboard_link(cluster))
206
+ )
207
+ return cluster, client