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,38 @@
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
+ file contains all the constants used in rasterization module
23
+ """
24
+
25
+ RASTERIZATION_RUN_TAG = "rasterization"
26
+
27
+ # Params
28
+ METHOD = "method"
29
+ DSM_RADIUS = "dsm_radius"
30
+ SIGMA = "sigma"
31
+ GRID_POINTS_DIVISION_FACTOR = "grid_points_division_factor"
32
+ RESOLUTION = "resolution"
33
+
34
+
35
+ # Run infos
36
+ EPSG_TAG = "epsg"
37
+ DSM_NO_DATA_TAG = "dsm_no_data"
38
+ TEXTURE_NO_DATA_TAG = "texture_no_data"
@@ -0,0 +1,639 @@
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
+ # pylint: disable=too-many-lines
22
+
23
+ """
24
+ This module is responsible for the rasterization step:
25
+ - it contains all functions related to 3D representation on a 2D raster grid
26
+ TODO: refactor in several files and remove too-many-lines
27
+ """
28
+
29
+ # Standard imports
30
+ import logging
31
+ from typing import List, Tuple
32
+
33
+ # Third party imports
34
+ import numpy as np
35
+ import pandas
36
+
37
+ # cars-rasterize
38
+ import xarray as xr
39
+
40
+ # CARS imports
41
+ from cars.core import constants as cst
42
+
43
+
44
+ def compute_xy_starts_and_sizes(
45
+ resolution: float, cloud: pandas.DataFrame
46
+ ) -> Tuple[float, float, int, int]:
47
+ """
48
+ Compute xstart, ystart, xsize and ysize
49
+ of the rasterization grid from a set of points
50
+
51
+ :param resolution: Resolution of rasterized cells,
52
+ expressed in cloud CRS units
53
+ :param cloud: set of points as returned
54
+ by the create_combined_cloud function
55
+ :return: a tuple (xstart, ystart, xsize, ysize)
56
+ """
57
+
58
+ # Derive xstart
59
+ xmin = np.nanmin(cloud[cst.X].values)
60
+ xmax = np.nanmax(cloud[cst.X].values)
61
+ logging.debug("Points x coordinate range: [{},{}]".format(xmin, xmax))
62
+
63
+ # Clamp to a regular grid
64
+ x_start = np.floor(xmin / resolution) * resolution
65
+
66
+ # Derive ystart
67
+ ymin = np.nanmin(cloud[cst.Y].values)
68
+ ymax = np.nanmax(cloud[cst.Y].values)
69
+ logging.debug("Points y coordinate range: [{},{}]".format(ymin, ymax))
70
+
71
+ # Clamp to a regular grid
72
+ y_start = np.ceil(ymax / resolution) * resolution
73
+
74
+ x_size = int(1 + np.floor((xmax - x_start) / resolution))
75
+ y_size = int(1 + np.floor((y_start - ymin) / resolution))
76
+
77
+ return x_start, y_start, x_size, y_size
78
+
79
+
80
+ def compute_values_1d(
81
+ x_start: float, y_start: float, x_size: int, y_size: int, resolution: float
82
+ ) -> Tuple[np.ndarray, np.ndarray]:
83
+ """
84
+ Compute the x and y values as 1d arrays
85
+
86
+ :param x_start: x start of the rasterization grid
87
+ :param y_start: y start of the rasterization grid
88
+ :param x_size: x size of the rasterization grid
89
+ :param y_size: y size of the rasterization grid
90
+ :param resolution: Resolution of rasterized cells,
91
+ in cloud CRS units or None.
92
+ :return: a tuple composed of the x and y 1d arrays
93
+ """
94
+ x_values_1d = np.linspace(
95
+ x_start + 0.5 * resolution,
96
+ x_start + resolution * (x_size + 0.5),
97
+ x_size,
98
+ endpoint=False,
99
+ )
100
+ y_values_1d = np.linspace(
101
+ y_start - 0.5 * resolution,
102
+ y_start - resolution * (y_size + 0.5),
103
+ y_size,
104
+ endpoint=False,
105
+ )
106
+
107
+ return x_values_1d, y_values_1d
108
+
109
+
110
+ def substring_in_list(src_list, substring):
111
+ """
112
+ Check if the list contains substring
113
+ """
114
+ res = list(filter(lambda x: substring in x, src_list))
115
+ return len(res) > 0
116
+
117
+
118
+ def phased_dsm(start: float, phase: float, resolution: float):
119
+ """
120
+ Phased the dsm
121
+
122
+ :param start: start of the roi
123
+ :param phase: the point for phasing
124
+ :param resolution: resolution of the dsm
125
+ """
126
+
127
+ div = np.abs(start - phase) / resolution
128
+
129
+ if phase > start:
130
+ start = phase - resolution * np.floor(div)
131
+ else:
132
+ start = resolution * np.floor(div) + phase
133
+
134
+ return start
135
+
136
+
137
+ def find_indexes_in_point_cloud(
138
+ cloud: pandas.DataFrame, tag: str, list_computed_layers: List[str] = None
139
+ ) -> List[str]:
140
+ """
141
+ Find all indexes in point cloud that contains the key tag
142
+ if it needs to be computed
143
+ :param cloud: Combined cloud
144
+ :param tag: substring of desired columns in cloud
145
+ :param list_computed_layers: list of computed output data
146
+ """
147
+ indexes = []
148
+ if list_computed_layers is None or substring_in_list(
149
+ list_computed_layers, tag
150
+ ):
151
+ for key in cloud.columns:
152
+ if tag in key:
153
+ indexes.append(key)
154
+ return indexes
155
+
156
+
157
+ # pylint: disable=too-many-positional-arguments
158
+ def create_raster_dataset( # noqa: C901
159
+ raster: np.ndarray,
160
+ weights_sum: np.ndarray,
161
+ x_start: float,
162
+ y_start: float,
163
+ x_size: int,
164
+ y_size: int,
165
+ resolution: float,
166
+ hgt_no_data: int,
167
+ texture_no_data: int,
168
+ msk_no_data: int,
169
+ epsg: int,
170
+ mean: np.ndarray,
171
+ stdev: np.ndarray,
172
+ n_pts: np.ndarray,
173
+ n_in_cell: np.ndarray,
174
+ msk: np.ndarray = None,
175
+ band_im: List[str] = None,
176
+ classif: np.ndarray = None,
177
+ band_classif: List[str] = None,
178
+ ambiguity: np.ndarray = None,
179
+ layers_inf_sup: np.ndarray = None,
180
+ layers_inf_sup_stat_index: List[int] = None,
181
+ layer_inf_sup_indexes: List[str] = None,
182
+ source_pc: np.ndarray = None,
183
+ source_pc_names: List[str] = None,
184
+ filling: np.ndarray = None,
185
+ band_filling: List[str] = None,
186
+ performance_map: np.ndarray = None,
187
+ performance_map_classified: np.ndarray = None,
188
+ performance_map_classified_index: list = None,
189
+ band_performance_map: List[str] = None,
190
+ ) -> xr.Dataset:
191
+ """
192
+ Create final raster xarray dataset
193
+
194
+ :param raster: height and colors
195
+ :param x_start: x start of the rasterization grid
196
+ :param y_start: y start of the rasterization grid
197
+ :param x_size: x size of the rasterization grid
198
+ :param y_size: y size of the rasterization grid
199
+ :param resolution: Resolution of rasterized cells,
200
+ expressed in cloud CRS units or None.
201
+ :param hgt_no_data: no data value to use for height
202
+ :param texture_no_data: no data value to use for color
203
+ :param msk_no_data: no data value to use for mask and classif
204
+ :param epsg: epsg code for the CRS of the final raster
205
+ :param mean: mean of height and colors
206
+ :param stdev: standard deviation of height and colors
207
+ :param n_pts: number of points that are stricty in a cell
208
+ :param n_in_cell: number of points which contribute to a cell
209
+ :param msk: raster msk
210
+ :param classif: raster classif
211
+ :param ambiguity: raster containing the ambiguity
212
+ :param layers_inf_sup: raster containing intervals inf and sup
213
+ :param layers_inf_sup_stat_index: list containing index of
214
+ intervals in mean and stdev rasters
215
+ :param layer_inf_sup_indexes: list of band names
216
+ :param source_pc: binary raster with source point cloud information
217
+ :param source_pc_names: list of names of point cloud before merging :
218
+ name of sensors pair or name of point cloud file
219
+ :param performance_map: raster containing the raw performance map
220
+ :param performance_map_classified: raster containing the classified
221
+ performance map
222
+ :param performance_map_classified_index: indexes of
223
+ performance_map_classified
224
+ :param band_performance_map: list of band names :
225
+ max 2 bands: risk / interval
226
+ :return: the raster xarray dataset
227
+ """
228
+ raster_dims = (cst.Y, cst.X)
229
+ n_layers = raster.shape[0]
230
+ x_values_1d, y_values_1d = compute_values_1d(
231
+ x_start, y_start, x_size, y_size, resolution
232
+ )
233
+ raster_coords = {cst.X: x_values_1d, cst.Y: y_values_1d}
234
+ hgt = np.nan_to_num(raster[0], nan=hgt_no_data)
235
+ raster_out = xr.Dataset(
236
+ {
237
+ cst.RASTER_HGT: ([cst.Y, cst.X], hgt),
238
+ cst.RASTER_WEIGHTS_SUM: ([cst.Y, cst.X], weights_sum),
239
+ },
240
+ coords=raster_coords,
241
+ )
242
+
243
+ if raster.shape[0] > 1: # rasterizer produced color output
244
+ color = np.nan_to_num(raster[1:], nan=texture_no_data)
245
+ for idx, band_name in enumerate(band_im):
246
+ band_im[idx] = band_name.replace(
247
+ cst.POINT_CLOUD_CLR_KEY_ROOT + "_", ""
248
+ )
249
+ color_out = xr.Dataset(
250
+ {
251
+ cst.RASTER_COLOR_IMG: (
252
+ [cst.BAND_IM, cst.Y, cst.X],
253
+ color,
254
+ )
255
+ },
256
+ coords={**raster_coords, cst.BAND_IM: band_im},
257
+ )
258
+ # update raster output with classification data
259
+ raster_out = xr.merge((raster_out, color_out))
260
+
261
+ raster_out.attrs[cst.EPSG] = epsg
262
+ raster_out.attrs[cst.RESOLUTION] = resolution
263
+
264
+ # statistics layer for height output
265
+ raster_out[cst.RASTER_HGT_MEAN] = xr.DataArray(
266
+ mean[..., 0], coords=raster_coords, dims=raster_dims
267
+ )
268
+ raster_out[cst.RASTER_HGT_STD_DEV] = xr.DataArray(
269
+ stdev[..., 0], coords=raster_coords, dims=raster_dims
270
+ )
271
+
272
+ # add each band statistics
273
+ for i_layer in range(1, n_layers):
274
+ raster_out["{}{}".format(cst.RASTER_BAND_MEAN, i_layer)] = xr.DataArray(
275
+ mean[..., i_layer],
276
+ coords=raster_coords,
277
+ dims=raster_dims,
278
+ )
279
+ raster_out["{}{}".format(cst.RASTER_BAND_STD_DEV, i_layer)] = (
280
+ xr.DataArray(
281
+ stdev[..., i_layer],
282
+ coords=raster_coords,
283
+ dims=raster_dims,
284
+ )
285
+ )
286
+
287
+ raster_out[cst.RASTER_NB_PTS] = xr.DataArray(n_pts, dims=raster_dims)
288
+ raster_out[cst.RASTER_NB_PTS_IN_CELL] = xr.DataArray(
289
+ n_in_cell, dims=raster_dims
290
+ )
291
+
292
+ if msk is not None: # rasterizer produced mask output
293
+ msk = np.nan_to_num(msk, nan=msk_no_data)
294
+ raster_out[cst.RASTER_MSK] = xr.DataArray(msk, dims=raster_dims)
295
+
296
+ if classif is not None: # rasterizer produced classif output
297
+ classif = np.nan_to_num(classif, nan=msk_no_data)
298
+ for idx, band_name in enumerate(band_classif):
299
+ band_classif[idx] = band_name.replace(
300
+ cst.POINT_CLOUD_CLASSIF_KEY_ROOT + "_", ""
301
+ )
302
+ classif_out = xr.Dataset(
303
+ {
304
+ cst.RASTER_CLASSIF: (
305
+ [cst.BAND_CLASSIF, cst.Y, cst.X],
306
+ classif,
307
+ )
308
+ },
309
+ coords={**raster_coords, cst.BAND_CLASSIF: band_classif},
310
+ )
311
+ # update raster output with classification data
312
+ raster_out = xr.merge((raster_out, classif_out))
313
+
314
+ if ambiguity is not None: # rasterizer produced color output
315
+ raster_out[cst.RASTER_AMBIGUITY] = xr.DataArray(
316
+ ambiguity[0], dims=raster_dims
317
+ )
318
+
319
+ if layers_inf_sup is not None:
320
+ # Get inf data
321
+ hgt_layers_list_inf = []
322
+ hgt_layers_list_sup = []
323
+ hgt_mean_layers_list_inf = []
324
+ hgt_mean_layers_list_sup = []
325
+ hgt_stdev_layers_list_inf = []
326
+ hgt_stdev_layers_list_sup = []
327
+ bands_sup = []
328
+ bands_inf = []
329
+ # Get Data
330
+ for current_layer, _ in enumerate(layers_inf_sup):
331
+ if "inf" in layer_inf_sup_indexes[current_layer]:
332
+ hgt_layers_list_inf.append(layers_inf_sup[current_layer])
333
+ hgt_mean_layers_list_inf.append(
334
+ mean[..., layers_inf_sup_stat_index[current_layer]]
335
+ )
336
+ hgt_stdev_layers_list_inf.append(
337
+ stdev[..., layers_inf_sup_stat_index[current_layer]]
338
+ )
339
+ bands_inf.append(layer_inf_sup_indexes[current_layer])
340
+ else:
341
+ hgt_layers_list_sup.append(layers_inf_sup[current_layer])
342
+ hgt_mean_layers_list_sup.append(
343
+ mean[..., layers_inf_sup_stat_index[current_layer]]
344
+ )
345
+ hgt_stdev_layers_list_sup.append(
346
+ stdev[..., layers_inf_sup_stat_index[current_layer]]
347
+ )
348
+ bands_sup.append(layer_inf_sup_indexes[current_layer])
349
+
350
+ for (
351
+ data_layer_list,
352
+ dataset_key,
353
+ band_key,
354
+ bands_name,
355
+ ) in zip( # noqa: B905
356
+ [
357
+ hgt_layers_list_inf,
358
+ hgt_mean_layers_list_inf,
359
+ hgt_stdev_layers_list_inf,
360
+ hgt_layers_list_sup,
361
+ hgt_mean_layers_list_sup,
362
+ hgt_stdev_layers_list_sup,
363
+ ],
364
+ [
365
+ cst.RASTER_HGT_INF,
366
+ cst.RASTER_HGT_INF_MEAN,
367
+ cst.RASTER_HGT_INF_STD_DEV,
368
+ cst.RASTER_HGT_SUP,
369
+ cst.RASTER_HGT_SUP_MEAN,
370
+ cst.RASTER_HGT_SUP_STD_DEV,
371
+ ],
372
+ [
373
+ cst.BAND_LAYER_INF,
374
+ cst.BAND_LAYER_INF,
375
+ cst.BAND_LAYER_INF,
376
+ cst.BAND_LAYER_SUP,
377
+ cst.BAND_LAYER_SUP,
378
+ cst.BAND_LAYER_SUP,
379
+ ],
380
+ [bands_inf, bands_inf, bands_inf, bands_sup, bands_sup, bands_sup],
381
+ ):
382
+ # Stack data
383
+ data_layer = np.nan_to_num(
384
+ np.stack(data_layer_list, axis=0), nan=hgt_no_data
385
+ )
386
+ # Add to datasets
387
+ layer_out = xr.Dataset(
388
+ {
389
+ dataset_key: (
390
+ [band_key, cst.Y, cst.X],
391
+ data_layer,
392
+ )
393
+ },
394
+ coords={**raster_coords, band_key: bands_name},
395
+ )
396
+ # update raster output with filling information
397
+ raster_out = xr.merge((raster_out, layer_out))
398
+
399
+ if source_pc is not None and source_pc_names is not None:
400
+ source_pc = np.nan_to_num(source_pc, nan=msk_no_data)
401
+ source_pc_out = xr.Dataset(
402
+ {
403
+ cst.RASTER_SOURCE_PC: (
404
+ [cst.BAND_SOURCE_PC, cst.Y, cst.X],
405
+ source_pc,
406
+ )
407
+ },
408
+ coords={**raster_coords, cst.BAND_SOURCE_PC: source_pc_names},
409
+ )
410
+ # update raster output with classification data
411
+ raster_out = xr.merge((raster_out, source_pc_out))
412
+
413
+ if filling is not None: # rasterizer produced filling info output
414
+ filling = np.nan_to_num(filling, nan=msk_no_data)
415
+ for idx, band_name in enumerate(band_filling):
416
+ band_filling[idx] = band_name.replace(
417
+ cst.POINT_CLOUD_FILLING_KEY_ROOT + "_", ""
418
+ )
419
+ filling_out = xr.Dataset(
420
+ {
421
+ cst.RASTER_FILLING: (
422
+ [cst.BAND_FILLING, cst.Y, cst.X],
423
+ filling,
424
+ )
425
+ },
426
+ coords={**raster_coords, cst.BAND_FILLING: band_filling},
427
+ )
428
+ # update raster output with filling information
429
+ raster_out = xr.merge((raster_out, filling_out))
430
+
431
+ if performance_map is not None:
432
+ performance_map = np.nan_to_num(performance_map, nan=msk_no_data)
433
+ if len(performance_map.shape) == 3 and performance_map.shape[0] == 2:
434
+ # Has both performance from risk and intervals
435
+ perf_out = xr.Dataset(
436
+ {
437
+ cst.RASTER_PERFORMANCE_MAP_RAW: (
438
+ [cst.BAND_PERFORMANCE_MAP, cst.Y, cst.X],
439
+ performance_map,
440
+ )
441
+ },
442
+ coords={
443
+ **raster_coords,
444
+ cst.BAND_PERFORMANCE_MAP: band_performance_map,
445
+ },
446
+ )
447
+ # update raster output with performance information
448
+ raster_out = xr.merge((raster_out, perf_out))
449
+
450
+ else:
451
+ # Only one performance map
452
+ raster_out[cst.RASTER_PERFORMANCE_MAP_RAW] = xr.DataArray(
453
+ performance_map[0, :, :], dims=raster_dims
454
+ )
455
+ if performance_map_classified is not None:
456
+ if (
457
+ len(performance_map_classified.shape) == 3
458
+ and performance_map_classified.shape[0] == 2
459
+ ):
460
+ # Has both performance from risk and intervals
461
+ perf_classified_out = xr.Dataset(
462
+ {
463
+ cst.RASTER_PERFORMANCE_MAP: (
464
+ [cst.BAND_PERFORMANCE_MAP, cst.Y, cst.X],
465
+ performance_map_classified,
466
+ )
467
+ },
468
+ coords={
469
+ **raster_coords,
470
+ cst.BAND_PERFORMANCE_MAP: band_performance_map,
471
+ },
472
+ )
473
+ # update raster output with performance information
474
+ raster_out = xr.merge((raster_out, perf_classified_out))
475
+ else:
476
+ # Only one performance map
477
+ raster_out[cst.RASTER_PERFORMANCE_MAP] = xr.DataArray(
478
+ performance_map_classified[0, :, :], dims=raster_dims
479
+ )
480
+ raster_out.attrs[cst.RIO_TAG_PERFORMANCE_MAP_CLASSES] = (
481
+ performance_map_classified_index
482
+ )
483
+
484
+ return raster_out
485
+
486
+
487
+ def classify_performance_map(
488
+ performance_map_raw, performance_map_classes, msk_no_data
489
+ ):
490
+ """
491
+ Classify performance map with given classes
492
+ """
493
+ if performance_map_classes[0] != 0:
494
+ performance_map_classes = [0] + performance_map_classes
495
+ if performance_map_classes[-1] != np.inf:
496
+ performance_map_classes.append(np.inf)
497
+
498
+ performance_map_classified_infos = {}
499
+
500
+ performance_map_classified = msk_no_data * np.ones(
501
+ performance_map_raw.shape, dtype=np.uint8
502
+ )
503
+
504
+ index_start, index_end = 0, 1
505
+ value = 0
506
+ while index_end < len(performance_map_classes):
507
+ current_class = (
508
+ performance_map_classes[index_start],
509
+ performance_map_classes[index_end],
510
+ )
511
+
512
+ # update information
513
+ performance_map_classified_infos[value] = current_class
514
+
515
+ # create classified performance map
516
+ performance_map_classified[
517
+ np.logical_and(
518
+ performance_map_raw >= current_class[0],
519
+ performance_map_raw < current_class[1],
520
+ )
521
+ ] = value
522
+
523
+ # next class
524
+ index_start += 1
525
+ index_end += 1
526
+ value += 1
527
+
528
+ return performance_map_classified, performance_map_classified_infos
529
+
530
+
531
+ def update_weights(old_weights, weights):
532
+ """
533
+ Update weights
534
+
535
+ :param weights: current weights
536
+ :param old_weights: old weights
537
+
538
+ :return: updated weights
539
+ """
540
+
541
+ new_weights = weights
542
+ if old_weights is not None:
543
+ current_nan = weights == 0
544
+ old_nan = old_weights == 0
545
+ weights[current_nan] = 0
546
+ old_weights[old_nan] = 0
547
+ new_weights = old_weights + weights
548
+
549
+ return new_weights
550
+
551
+
552
+ def update_data( # pylint: disable=too-many-positional-arguments
553
+ old_data, current_data, weights, old_weights, nodata, method="basic"
554
+ ):
555
+ """
556
+ Update current data with old data and weigths
557
+
558
+ :param old_data: old data
559
+ :param current_data: current data
560
+ :param weights: current weights
561
+ :param old_weights: old weights
562
+ :param nodata: nodata associated to tag
563
+
564
+ :return: updated current data
565
+ """
566
+
567
+ new_data = current_data
568
+ data = old_data
569
+ if old_data is not None:
570
+ old_data = np.squeeze(old_data)
571
+ old_weights = np.squeeze(old_weights)
572
+ shape = old_data.shape
573
+ if len(data.shape) == 3 and data.shape[0] > 1:
574
+ old_weights = np.repeat(
575
+ np.expand_dims(old_weights, axis=0), old_data.shape[0], axis=0
576
+ )
577
+
578
+ current_data = np.squeeze(current_data)
579
+ weights = np.squeeze(weights)
580
+ if len(new_data.shape) == 3 and new_data.shape[0] > 1:
581
+ weights = np.repeat(
582
+ np.expand_dims(weights, axis=0), current_data.shape[0], axis=0
583
+ )
584
+
585
+ # compute masks
586
+ current_valid = weights != 0
587
+ old_valid = old_weights != 0
588
+
589
+ both_valid = np.logical_and(current_valid, old_valid)
590
+
591
+ total_weights = np.zeros(shape)
592
+
593
+ total_weights[both_valid] = (
594
+ weights[both_valid] + old_weights[both_valid]
595
+ )
596
+
597
+ # current factor
598
+ current_factor = np.zeros(shape)
599
+ current_factor[current_valid] = 1
600
+ current_factor[both_valid] = (
601
+ weights[both_valid] / total_weights[both_valid]
602
+ )
603
+
604
+ # old factor
605
+ old_factor = np.zeros(shape)
606
+ old_factor[old_valid] = 1
607
+ old_factor[both_valid] = (
608
+ old_weights[both_valid] / total_weights[both_valid]
609
+ )
610
+
611
+ # assign old weights
612
+ new_data = np.zeros(shape)
613
+ if method == "basic":
614
+ new_data[old_valid] = old_data[old_valid] * old_factor[old_valid]
615
+ new_data[current_valid] += (
616
+ current_data[current_valid] * current_factor[current_valid]
617
+ )
618
+ elif method == "bool":
619
+ new_data[old_valid] = old_data[old_valid]
620
+ new_data[current_valid] = np.logical_or(
621
+ current_data[current_valid], new_data[current_valid]
622
+ )
623
+ elif method == "sum":
624
+ new_data[old_valid] = old_data[old_valid]
625
+ new_data[current_valid] += current_data[current_valid]
626
+ elif method == "max":
627
+ new_data[old_valid] = old_data[old_valid]
628
+ new_data[current_valid] = np.maximum(
629
+ new_data[current_valid], current_data[current_valid]
630
+ )
631
+
632
+ # round result if saved as integer
633
+ if np.issubdtype(current_data.dtype, np.integer):
634
+ new_data = np.round(new_data).astype(current_data.dtype)
635
+
636
+ # set nodata
637
+ all_nodata = (current_valid + old_valid) == 0
638
+ new_data[all_nodata] = nodata
639
+ return new_data