cars 1.0.0a2__cp313-cp313-win_amd64.whl → 1.0.0a4__cp313-cp313-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 (144) hide show
  1. cars/__init__.py +3 -3
  2. cars/applications/__init__.py +0 -3
  3. cars/applications/application.py +14 -6
  4. cars/applications/application_template.py +42 -0
  5. cars/applications/auxiliary_filling/abstract_auxiliary_filling_app.py +12 -2
  6. cars/applications/auxiliary_filling/auxiliary_filling_algo.py +2 -2
  7. cars/applications/auxiliary_filling/auxiliary_filling_from_sensors_app.py +95 -46
  8. cars/applications/auxiliary_filling/auxiliary_filling_wrappers.py +7 -6
  9. cars/applications/dem_generation/abstract_dem_generation_app.py +9 -5
  10. cars/applications/dem_generation/dem_generation_algo.py +1 -1
  11. cars/applications/dem_generation/dem_generation_wrappers.py +44 -59
  12. cars/applications/dem_generation/dichotomic_generation_app.py +9 -6
  13. cars/applications/dem_generation/rasterization_app.py +112 -43
  14. cars/applications/dense_match_filling/__init__.py +1 -1
  15. cars/applications/dense_match_filling/abstract_dense_match_filling_app.py +2 -15
  16. cars/applications/dense_match_filling/fill_disp_algo.py +32 -373
  17. cars/applications/dense_match_filling/fill_disp_wrappers.py +0 -343
  18. cars/applications/dense_match_filling/zero_padding_app.py +10 -5
  19. cars/applications/dense_matching/abstract_dense_matching_app.py +2 -1
  20. cars/applications/dense_matching/census_mccnn_sgm_app.py +48 -60
  21. cars/applications/dense_matching/cpp/dense_matching_cpp.cp313-win_amd64.dll.a +0 -0
  22. cars/applications/dense_matching/cpp/dense_matching_cpp.cp313-win_amd64.pyd +0 -0
  23. cars/applications/dense_matching/dense_matching_algo.py +48 -14
  24. cars/applications/dense_matching/dense_matching_wrappers.py +11 -3
  25. cars/applications/dense_matching/disparity_grid_algo.py +95 -79
  26. cars/applications/dense_matching/loaders/config_mapping.json +13 -0
  27. cars/applications/dense_matching/loaders/global_land_cover_map.tif +0 -0
  28. cars/applications/dense_matching/loaders/pandora_loader.py +169 -34
  29. cars/applications/dsm_filling/border_interpolation_app.py +11 -12
  30. cars/applications/dsm_filling/bulldozer_filling_app.py +16 -15
  31. cars/applications/dsm_filling/exogenous_filling_app.py +14 -14
  32. cars/applications/grid_generation/abstract_grid_generation_app.py +1 -1
  33. cars/applications/grid_generation/epipolar_grid_generation_app.py +4 -2
  34. cars/applications/grid_generation/grid_correction_app.py +4 -1
  35. cars/applications/grid_generation/grid_generation_algo.py +7 -2
  36. cars/applications/ground_truth_reprojection/abstract_ground_truth_reprojection_app.py +1 -1
  37. cars/applications/ground_truth_reprojection/direct_localization_app.py +2 -2
  38. cars/applications/ground_truth_reprojection/ground_truth_reprojection_algo.py +2 -1
  39. cars/applications/point_cloud_fusion/abstract_pc_fusion_app.py +0 -155
  40. cars/applications/point_cloud_fusion/mapping_to_terrain_tiles_app.py +0 -658
  41. cars/applications/point_cloud_fusion/pc_fusion_algo.py +0 -1339
  42. cars/applications/point_cloud_fusion/pc_fusion_wrappers.py +0 -869
  43. cars/applications/point_cloud_outlier_removal/abstract_outlier_removal_app.py +11 -6
  44. cars/applications/point_cloud_outlier_removal/outlier_removal_algo.py +9 -8
  45. cars/applications/point_cloud_outlier_removal/small_components_app.py +101 -270
  46. cars/applications/point_cloud_outlier_removal/statistical_app.py +120 -277
  47. cars/applications/rasterization/abstract_pc_rasterization_app.py +2 -1
  48. cars/applications/rasterization/rasterization_algo.py +18 -6
  49. cars/applications/rasterization/rasterization_wrappers.py +2 -1
  50. cars/applications/rasterization/simple_gaussian_app.py +88 -116
  51. cars/applications/resampling/abstract_resampling_app.py +1 -1
  52. cars/applications/resampling/bicubic_resampling_app.py +3 -1
  53. cars/applications/resampling/resampling_algo.py +60 -53
  54. cars/applications/resampling/resampling_wrappers.py +3 -1
  55. cars/applications/sparse_matching/abstract_sparse_matching_app.py +1 -1
  56. cars/applications/sparse_matching/sift_app.py +5 -25
  57. cars/applications/sparse_matching/sparse_matching_algo.py +3 -2
  58. cars/applications/sparse_matching/sparse_matching_wrappers.py +1 -1
  59. cars/applications/triangulation/abstract_triangulation_app.py +1 -1
  60. cars/applications/triangulation/line_of_sight_intersection_app.py +13 -11
  61. cars/applications/triangulation/pc_transform.py +552 -0
  62. cars/applications/triangulation/triangulation_algo.py +6 -4
  63. cars/applications/triangulation/triangulation_wrappers.py +1 -0
  64. cars/bundleadjustment.py +6 -6
  65. cars/cars.py +11 -9
  66. cars/core/cars_logging.py +80 -49
  67. cars/core/constants.py +0 -1
  68. cars/core/datasets.py +5 -2
  69. cars/core/geometry/abstract_geometry.py +364 -22
  70. cars/core/geometry/shareloc_geometry.py +112 -82
  71. cars/core/inputs.py +72 -19
  72. cars/core/outputs.py +1 -1
  73. cars/core/preprocessing.py +17 -3
  74. cars/core/projection.py +126 -6
  75. cars/core/tiling.py +10 -3
  76. cars/data_structures/cars_dataset.py +12 -10
  77. cars/data_structures/corresponding_tiles_tools.py +0 -103
  78. cars/data_structures/format_transformation.py +4 -1
  79. cars/devibrate.py +6 -3
  80. cars/extractroi.py +20 -21
  81. cars/orchestrator/cluster/abstract_cluster.py +15 -5
  82. cars/orchestrator/cluster/abstract_dask_cluster.py +6 -2
  83. cars/orchestrator/cluster/dask_jobqueue_utils.py +1 -1
  84. cars/orchestrator/cluster/log_wrapper.py +149 -22
  85. cars/orchestrator/cluster/mp_cluster/multiprocessing_cluster.py +12 -4
  86. cars/orchestrator/cluster/mp_cluster/multiprocessing_profiler.py +2 -2
  87. cars/orchestrator/cluster/pbs_dask_cluster.py +1 -1
  88. cars/orchestrator/cluster/sequential_cluster.py +5 -4
  89. cars/orchestrator/cluster/slurm_dask_cluster.py +1 -1
  90. cars/orchestrator/orchestrator.py +15 -4
  91. cars/orchestrator/registry/id_generator.py +1 -0
  92. cars/orchestrator/registry/saver_registry.py +2 -2
  93. cars/pipelines/conf_resolution/conf_final_resolution.json +5 -3
  94. cars/pipelines/default/default_pipeline.py +461 -1052
  95. cars/pipelines/parameters/advanced_parameters.py +91 -64
  96. cars/pipelines/parameters/advanced_parameters_constants.py +6 -5
  97. cars/pipelines/parameters/application_parameters.py +71 -0
  98. cars/pipelines/parameters/depth_map_inputs.py +0 -314
  99. cars/pipelines/parameters/dsm_inputs.py +40 -4
  100. cars/pipelines/parameters/output_parameters.py +44 -8
  101. cars/pipelines/parameters/sensor_inputs.py +122 -73
  102. cars/pipelines/parameters/sensor_inputs_constants.py +0 -2
  103. cars/pipelines/parameters/sensor_loaders/__init__.py +4 -3
  104. cars/pipelines/parameters/sensor_loaders/basic_classif_loader.py +106 -0
  105. cars/pipelines/parameters/sensor_loaders/{basic_sensor_loader.py → basic_image_loader.py} +16 -22
  106. cars/pipelines/parameters/sensor_loaders/pivot_classif_loader.py +121 -0
  107. cars/pipelines/parameters/sensor_loaders/{pivot_sensor_loader.py → pivot_image_loader.py} +10 -21
  108. cars/pipelines/parameters/sensor_loaders/sensor_loader.py +4 -6
  109. cars/pipelines/parameters/sensor_loaders/sensor_loader_template.py +1 -3
  110. cars/pipelines/pipeline_template.py +1 -3
  111. cars/pipelines/unit/unit_pipeline.py +676 -1070
  112. cars/starter.py +4 -3
  113. cars-1.0.0a4.dist-info/DELVEWHEEL +2 -0
  114. {cars-1.0.0a2.dist-info → cars-1.0.0a4.dist-info}/METADATA +135 -53
  115. {cars-1.0.0a2.dist-info → cars-1.0.0a4.dist-info}/RECORD +120 -134
  116. cars.libs/libgcc_s_seh-1-b2494fcbd4d80cf2c98fdd5261f6d850.dll +0 -0
  117. cars.libs/libstdc++-6-e9b0d12ae0e9555bbae55e8dfd08c3f7.dll +0 -0
  118. cars.libs/libwinpthread-1-7882d1b093714ccdfaf4e0789a817792.dll +0 -0
  119. cars/applications/dense_match_filling/cpp/__init__.py +0 -0
  120. cars/applications/dense_match_filling/cpp/dense_match_filling_cpp.cp313-win_amd64.dll.a +0 -0
  121. cars/applications/dense_match_filling/cpp/dense_match_filling_cpp.cp313-win_amd64.pyd +0 -0
  122. cars/applications/dense_match_filling/cpp/dense_match_filling_cpp.py +0 -72
  123. cars/applications/dense_match_filling/cpp/includes/dense_match_filling.hpp +0 -46
  124. cars/applications/dense_match_filling/cpp/meson.build +0 -9
  125. cars/applications/dense_match_filling/cpp/src/bindings.cpp +0 -11
  126. cars/applications/dense_match_filling/cpp/src/dense_match_filling.cpp +0 -142
  127. cars/applications/dense_match_filling/plane_app.py +0 -556
  128. cars/applications/hole_detection/__init__.py +0 -30
  129. cars/applications/hole_detection/abstract_hole_detection_app.py +0 -125
  130. cars/applications/hole_detection/cloud_to_bbox_app.py +0 -346
  131. cars/applications/hole_detection/hole_detection_algo.py +0 -144
  132. cars/applications/hole_detection/hole_detection_wrappers.py +0 -53
  133. cars/applications/point_cloud_denoising/__init__.py +0 -29
  134. cars/applications/point_cloud_denoising/abstract_pc_denoising_app.py +0 -273
  135. cars/applications/point_cloud_fusion/__init__.py +0 -30
  136. cars/applications/point_cloud_fusion/cloud_fusion_constants.py +0 -39
  137. cars/applications/sparse_matching/pandora_sparse_matching_app.py +0 -0
  138. cars/pipelines/parameters/depth_map_inputs_constants.py +0 -25
  139. cars-1.0.0a2.dist-info/DELVEWHEEL +0 -2
  140. cars.libs/libgcc_s_seh-1-f2b6825d483bdf14050493af93b5997d.dll +0 -0
  141. cars.libs/libstdc++-6-6b0059df6bc601df5a0f18a5805eea05.dll +0 -0
  142. cars.libs/libwinpthread-1-e01b8e85fd67c2b861f64d4ccc7df607.dll +0 -0
  143. {cars-1.0.0a2.dist-info → cars-1.0.0a4.dist-info}/WHEEL +0 -0
  144. {cars-1.0.0a2.dist-info → cars-1.0.0a4.dist-info}/entry_points.txt +0 -0
cars/core/projection.py CHANGED
@@ -22,7 +22,7 @@
22
22
  Projection module:
23
23
  contains some general purpose functions using polygons and data projections
24
24
  """
25
- # pylint: disable=too-many-lines
25
+ # pylint: disable=C0302(too-many-lines)
26
26
 
27
27
  # Standard imports
28
28
  import logging
@@ -42,6 +42,7 @@ from shapely.ops import transform
42
42
 
43
43
  from cars.core import constants as cst
44
44
  from cars.core import inputs, outputs, utils
45
+ from cars.orchestrator.cluster.log_wrapper import cars_profile
45
46
 
46
47
 
47
48
  def compute_dem_intersection_with_poly( # noqa: C901
@@ -182,6 +183,22 @@ def polygon_projection(poly: Polygon, epsg_in: int, epsg_out: int) -> Polygon:
182
183
  return poly
183
184
 
184
185
 
186
+ def polygon_projection_crs(poly: Polygon, crs_in: CRS, crs_out: CRS) -> Polygon:
187
+ """
188
+ Projects a polygon from an initial crs to another
189
+
190
+ :param poly: poly to project
191
+ :param crs_in: initial crs
192
+ :param crs_out: final crs
193
+ :return: The polygon in the final projection
194
+ """
195
+ # Project polygon between CRS (keep always_xy for compatibility)
196
+ project = pyproj.Transformer.from_crs(crs_in, crs_out, always_xy=True)
197
+ poly = transform(project.transform, poly)
198
+
199
+ return poly
200
+
201
+
185
202
  def geo_to_ecef(
186
203
  lat: np.ndarray, lon: np.ndarray, alt: np.ndarray
187
204
  ) -> Tuple[np.ndarray, np.ndarray, np.ndarray]:
@@ -203,7 +220,7 @@ def geo_to_ecef(
203
220
  )[0]
204
221
 
205
222
 
206
- def ecef_to_enu(
223
+ def ecef_to_enu( # pylint: disable=too-many-positional-arguments
207
224
  x_ecef: np.ndarray,
208
225
  y_ecef: np.ndarray,
209
226
  z_ecef: np.ndarray,
@@ -253,7 +270,7 @@ def ecef_to_enu(
253
270
  return x_east, y_north, z_up
254
271
 
255
272
 
256
- def geo_to_enu(
273
+ def geo_to_enu( # pylint: disable=too-many-positional-arguments
257
274
  lat: np.ndarray,
258
275
  lon: np.ndarray,
259
276
  alt: np.ndarray,
@@ -302,7 +319,7 @@ def enu_to_aer(
302
319
  return azimuth, elevation, xyz_range
303
320
 
304
321
 
305
- def geo_to_aer(
322
+ def geo_to_aer( # pylint: disable=too-many-positional-arguments
306
323
  lat: np.ndarray,
307
324
  lon: np.ndarray,
308
325
  alt: np.ndarray,
@@ -351,6 +368,27 @@ def point_cloud_conversion(
351
368
  return cloud_in
352
369
 
353
370
 
371
+ def point_cloud_conversion_crs(
372
+ cloud_in: np.ndarray, crs_in: int, crs_out: int
373
+ ) -> np.ndarray:
374
+ """
375
+ Convert a point cloud from a SRS to another one.
376
+
377
+ :param cloud_in: cloud to project
378
+ :param crs_in: crs of the input SRS
379
+ :param crs_out: crs of the output SRS
380
+ :return: Projected point cloud
381
+ """
382
+ # Project point cloud between CRS (keep always_xy for compatibility)
383
+ cloud_in = np.array(cloud_in).T
384
+ transformer = pyproj.Transformer.from_crs(crs_in, crs_out, always_xy=True)
385
+
386
+ cloud_in = transformer.transform(*cloud_in)
387
+ cloud_in = np.array(cloud_in).T
388
+
389
+ return cloud_in
390
+
391
+
354
392
  def get_xyz_np_array_from_dataset(
355
393
  cloud_in: xr.Dataset,
356
394
  ) -> Tuple[np.array, List[int]]:
@@ -492,6 +530,8 @@ def ground_polygon_from_envelopes(
492
530
  return inter, inter.bounds
493
531
 
494
532
 
533
+ # pylint: disable=too-many-positional-arguments
534
+ @cars_profile(name="Ground intersection envelopes", interval=0.5)
495
535
  def ground_intersection_envelopes(
496
536
  sensor1,
497
537
  sensor2,
@@ -558,7 +598,7 @@ def ground_intersection_envelopes(
558
598
  return inter_poly, (inter_xmin, inter_ymin, inter_xmax, inter_ymax)
559
599
 
560
600
 
561
- def get_ground_direction(
601
+ def get_ground_direction( # pylint: disable=too-many-positional-arguments
562
602
  sensor,
563
603
  geomodel,
564
604
  geometry_plugin: str,
@@ -631,7 +671,7 @@ def get_ground_direction(
631
671
  return np.array([lat0, lon0, alt0, lat, lon, alt])
632
672
 
633
673
 
634
- def get_ground_angles(
674
+ def get_ground_angles( # pylint: disable=too-many-positional-arguments
635
675
  sensor1,
636
676
  sensor2,
637
677
  geomodel1,
@@ -721,3 +761,83 @@ def get_ground_angles(
721
761
  convergence_angle = np.degrees(utils.angle_vectors(enu1, enu2))
722
762
 
723
763
  return az1, elev_angle1, az2, elev_angle2, convergence_angle
764
+
765
+
766
+ def get_output_crs(epsg, out_conf):
767
+ """
768
+ Détermine le CRS de sortie en fonction de la config.
769
+ """
770
+ geoid = out_conf.get("geoid")
771
+ crs_epsg = CRS(f"EPSG:{epsg}")
772
+
773
+ if len(crs_epsg.axis_info) != 2:
774
+ return crs_epsg # the user himself set a 3D CRS
775
+
776
+ geoid_is_path = isinstance(geoid, str)
777
+
778
+ if geoid_is_path: # user given geoid
779
+ vepsg = guess_vcrs_from_file_name(geoid)
780
+ if vepsg is None:
781
+ custom_wkt = (
782
+ 'VERTCRS["Custom geoid height",'
783
+ + f' VDATUM["Custom geoid model (file: {geoid})"],'
784
+ + " CS[vertical,1],"
785
+ + ' AXIS["gravity-related height (h)", up],'
786
+ + ' LENGTHUNIT["metre", 1, ID["EPSG", 9001]]'
787
+ "]"
788
+ )
789
+ logging.warning(
790
+ "Could not create a known VCRS from the geoid file."
791
+ )
792
+ return CRS.from_wkt(
793
+ f'COMPOUNDCRS["EPSG:{epsg} + Custom geoid height",'
794
+ f" {crs_epsg.to_wkt()},"
795
+ f" {custom_wkt}]"
796
+ )
797
+ # a vepsg was found using the geoid file
798
+ return CRS(f"EPSG:{epsg}+{vepsg}")
799
+
800
+ if geoid: # geoid == True
801
+ return CRS(f"EPSG:{epsg}+5773")
802
+
803
+ # geoid == False
804
+ wgs84_wkt = (
805
+ 'VERTCRS["WGS 84 ellipsoidal height",'
806
+ + ' VDATUM["WGS 84"],'
807
+ + " CS[vertical,1],"
808
+ + ' AXIS["ellipsoidal height (h)", up],'
809
+ + ' LENGTHUNIT["metre", 1, ID["EPSG", 9001]]'
810
+ "]"
811
+ )
812
+ logging.warning("The output VCRS is WGS84.")
813
+
814
+ return CRS.from_wkt(
815
+ f'COMPOUNDCRS["EPSG:{epsg} + WGS84 ellipsoidal height",'
816
+ f" {crs_epsg.to_wkt()},"
817
+ f" {wgs84_wkt}]"
818
+ )
819
+
820
+
821
+ def guess_vcrs_from_file_name(filepath):
822
+ """
823
+ Tries to detect the geoid's EPSG from the file name
824
+ """
825
+ filename = os.path.basename(filepath).lower()
826
+
827
+ known_models = {
828
+ "egm96": 5773, # EGM96 height
829
+ "egm_96": 5773, # alias
830
+ "egm 96": 5773, # alias
831
+ "egm1996": 5773, # alias
832
+ "egm08": 3855, # EGM2008 height
833
+ "egm_08": 3855, # alias
834
+ "egm 08": 3855, # alias
835
+ "egm2008": 3855, # alias
836
+ }
837
+
838
+ for key, vepsg in known_models.items():
839
+ if key in filename:
840
+ return vepsg
841
+
842
+ # aucun match connu
843
+ return None
cars/core/tiling.py CHANGED
@@ -40,8 +40,10 @@ from scipy.spatial import tsearch # pylint: disable=no-name-in-module
40
40
  from shapely.geometry import box, mapping
41
41
  from shapely.geometry.multipolygon import MultiPolygon
42
42
 
43
+ from cars.orchestrator.cluster.log_wrapper import cars_profile
43
44
 
44
- def grid(
45
+
46
+ def grid( # pylint: disable=too-many-positional-arguments
45
47
  xmin: float, ymin: float, xmax: float, ymax: float, xsplit: int, ysplit: int
46
48
  ) -> np.ndarray:
47
49
  """
@@ -74,6 +76,7 @@ def grid(
74
76
  return out_grid
75
77
 
76
78
 
79
+ @cars_profile(name="Transform four layers to two layers grid", interval=0.5)
77
80
  def transform_four_layers_to_two_layers_grid(tiling_grid, terrain=False):
78
81
  """
79
82
  Transform a 4 layer grid: (N, M, 4) containing
@@ -115,6 +118,7 @@ def transform_four_layers_to_two_layers_grid(tiling_grid, terrain=False):
115
118
  return arr
116
119
 
117
120
 
121
+ @cars_profile(name="Transform disp range grid to two layers", interval=0.5)
118
122
  def transform_disp_range_grid_to_two_layers(disp_min_grid, disp_max_grid):
119
123
  """
120
124
  Transform tiling disp min and max to N+1 M+1 array corresponding
@@ -154,7 +158,7 @@ def transform_disp_range_grid_to_two_layers(disp_min_grid, disp_max_grid):
154
158
  return disp_min, disp_max
155
159
 
156
160
 
157
- def generate_tiling_grid(
161
+ def generate_tiling_grid( # pylint: disable=too-many-positional-arguments
158
162
  row_min: float,
159
163
  col_min: float,
160
164
  row_max: float,
@@ -199,7 +203,9 @@ def generate_tiling_grid(
199
203
  return out_grid
200
204
 
201
205
 
202
- def split(xmin, ymin, xmax, ymax, xsplit, ysplit):
206
+ def split(
207
+ xmin, ymin, xmax, ymax, xsplit, ysplit
208
+ ): # pylint: disable=too-many-positional-arguments
203
209
  """
204
210
  Split a region defined by [xmin, xmax] x [ymin, ymax]
205
211
  in splits of xsplit x ysplit size
@@ -561,6 +567,7 @@ def region_hash_string(region: Tuple):
561
567
  return "{}_{}_{}_{}".format(region[0], region[1], region[2], region[3])
562
568
 
563
569
 
570
+ # pylint: disable=too-many-positional-arguments
564
571
  def get_corresponding_tiles_row_col(
565
572
  terrain_tiling_grid: np.ndarray,
566
573
  row: int,
@@ -38,6 +38,7 @@ from typing import Dict
38
38
  # Third party imports
39
39
  import numpy as np
40
40
  import pandas
41
+ import pyproj
41
42
  import rasterio as rio
42
43
  import xarray as xr
43
44
  from rasterio.profiles import DefaultGTiffProfile
@@ -338,7 +339,7 @@ class CarsDataset:
338
339
 
339
340
  return new_window
340
341
 
341
- def create_grid(
342
+ def create_grid( # pylint: disable=too-many-positional-arguments
342
343
  self,
343
344
  nb_col: int,
344
345
  nb_row: int,
@@ -434,7 +435,7 @@ class CarsDataset:
434
435
  tiles_row.append(None)
435
436
  self.tiles.append(tiles_row)
436
437
 
437
- def generate_descriptor(
438
+ def generate_descriptor( # pylint: disable=too-many-positional-arguments
438
439
  self, future_result, file_name, tag=None, dtype=None, nodata=None
439
440
  ):
440
441
  """
@@ -578,7 +579,7 @@ def run_save_arrays(future_result, file_name, tag=None, descriptor=None):
578
579
  )
579
580
 
580
581
 
581
- def run_save_points(
582
+ def run_save_points( # pylint: disable=too-many-positional-arguments
582
583
  future_result,
583
584
  file_name,
584
585
  overwrite=False,
@@ -839,7 +840,7 @@ def save_single_tile_dict(dict_cars, tile_path_name: str):
839
840
  dict_cars.attrs = saved_dict_cars_attrs
840
841
 
841
842
 
842
- def fill_dataset(
843
+ def fill_dataset( # pylint: disable=too-many-positional-arguments
843
844
  dataset,
844
845
  saving_info=None,
845
846
  window=None,
@@ -938,7 +939,7 @@ def fill_dict(data_dict, saving_info=None, attributes=None):
938
939
  data_dict.attrs[SAVING_INFO] = saving_info
939
940
 
940
941
 
941
- def save_all_dataframe(
942
+ def save_all_dataframe( # pylint: disable=too-many-positional-arguments
942
943
  dataframe,
943
944
  file_name,
944
945
  save_by_pair=False,
@@ -1327,12 +1328,13 @@ def dict_profile_to_rio_profile(dict_profile: Dict) -> Dict:
1327
1328
  crs = None
1328
1329
  if "crs" in dict_profile:
1329
1330
  if dict_profile["crs"] is not None:
1330
- if isinstance(dict_profile["crs"], str):
1331
- crs = rio.crs.CRS.from_epsg(
1332
- dict_profile["crs"].replace("EPSG:", "")
1333
- )
1331
+ if (
1332
+ isinstance(dict_profile["crs"], str)
1333
+ and "EPSG:" in dict_profile["crs"]
1334
+ ):
1335
+ crs = pyproj.CRS(dict_profile["crs"].replace("EPSG:", ""))
1334
1336
  else:
1335
- crs = rio.crs.CRS.from_epsg(dict_profile["crs"])
1337
+ crs = pyproj.CRS(dict_profile["crs"])
1336
1338
 
1337
1339
  rio_profile["crs"] = crs
1338
1340
  rio_profile["transform"] = transform
@@ -27,8 +27,6 @@ Contains functions for array reconstructions and crop for multiple tiles
27
27
  import numpy as np
28
28
  import xarray as xr
29
29
 
30
- import cars.core.constants as cst
31
-
32
30
 
33
31
  def reconstruct_data(tiles, window, overlap): # noqa: C901
34
32
  """
@@ -186,104 +184,3 @@ def reconstruct_data(tiles, window, overlap): # noqa: C901
186
184
  dims=dims,
187
185
  ).astype(data_type)
188
186
  return new_dataset, row_min - ol_row_min, col_min - ol_col_min
189
-
190
-
191
- def find_tile_dataset(corresponding_tiles, window):
192
- """
193
- Find the dataset corresponding to window, in the list of tiles.
194
-
195
- :param corresponding_tiles: list of tiles
196
- :type corresponding_tiles: list(tuple)
197
- :param window: window of base tile [row min, row max, col min col max]
198
- :type window: list
199
-
200
- :return: dataset corresponding to window
201
- :rtype: xr.Dataset
202
-
203
- """
204
-
205
- dataset = None
206
- for tile_window, _, tile_dataset in corresponding_tiles:
207
- if tuple(tile_window) == tuple(window):
208
- dataset = tile_dataset
209
-
210
- return dataset
211
-
212
-
213
- def crop_dataset(full_dataset, in_dataset, window, overlap, row_min, col_min):
214
- """
215
- Crop full dataset to fit with a given tile dataset
216
-
217
- :param full_dataset: Combined dataset
218
- :type full_dataset: xr.Dataset
219
- :param in_dataset: dataset to use as template dataset
220
- :type in_dataset: xr.Dataset
221
- :param window: window of base tile [row min, row max, col min col max]
222
- :type window: list
223
- :param overlap: overlap of base tile [row min, row max, col min col max]
224
- :type overlap: list
225
- :param row_min: position of row min in full image
226
- :type row_min: int
227
- :param col_min: position of col min in full image
228
- :type col_min: int
229
-
230
- :return: cropped dataset
231
- :rtype: xr.Dataset
232
-
233
- """
234
- cropped = xr.Dataset()
235
-
236
- coords = {}
237
- if cst.ROW in in_dataset:
238
- coords[cst.ROW] = in_dataset.coords[cst.ROW]
239
- if cst.COL in in_dataset:
240
- coords[cst.COL] = in_dataset.coords[cst.COL]
241
-
242
- list_tags = list(full_dataset.keys())
243
-
244
- for tag in list_tags:
245
- full_data = full_dataset[tag].values
246
-
247
- offset_row = int(window[0] - overlap[0] - row_min)
248
- offset_col = int(window[2] - overlap[2] - col_min)
249
-
250
- if len(full_data.shape) == 2:
251
- nb_row = int(in_dataset[tag].values.shape[0])
252
- nb_col = int(in_dataset[tag].values.shape[1])
253
-
254
- values = np.ascontiguousarray(
255
- full_data[
256
- offset_row : offset_row + nb_row,
257
- offset_col : offset_col + nb_col,
258
- ]
259
- )
260
-
261
- else:
262
- nb_row = int(in_dataset[tag].values.shape[1])
263
- nb_col = int(in_dataset[tag].values.shape[2])
264
-
265
- values = np.ascontiguousarray(
266
- full_data[
267
- :,
268
- offset_row : offset_row + nb_row,
269
- offset_col : offset_col + nb_col,
270
- ]
271
- )
272
-
273
- xarray_coords = {}
274
- for coord_tag in full_dataset[tag].coords:
275
- if coord_tag in coords:
276
- xarray_coords[coord_tag] = coords[coord_tag]
277
- else:
278
- xarray_coords[coord_tag] = full_dataset[tag].coords[coord_tag]
279
-
280
- dims = full_dataset[tag].dims
281
-
282
- data_array = xr.DataArray(values, coords=xarray_coords, dims=dims)
283
- if tag in in_dataset:
284
- data_array.attrs = in_dataset[tag].attrs
285
- cropped[tag] = data_array
286
-
287
- cropped.attrs = in_dataset.attrs
288
-
289
- return cropped
@@ -30,9 +30,12 @@ import math
30
30
  import numpy as np
31
31
  import xarray as xr
32
32
 
33
+ from cars.orchestrator.cluster.log_wrapper import cars_profile
34
+
33
35
  # CARS imports
34
36
 
35
37
 
38
+ @cars_profile(name="Grid margins 2 overlaps", interval=0.5)
36
39
  def grid_margins_2_overlaps(grid, margins_fun):
37
40
  """
38
41
  Convert margins to overlap grid format used in CarsDatasets
@@ -48,7 +51,7 @@ def grid_margins_2_overlaps(grid, margins_fun):
48
51
 
49
52
  """
50
53
 
51
- def fill_overlap(
54
+ def fill_overlap( # pylint: disable=too-many-positional-arguments
52
55
  cars_ds_overlaps,
53
56
  margins,
54
57
  row_up,
cars/devibrate.py CHANGED
@@ -95,7 +95,7 @@ def acquisition_direction(
95
95
  return time_direction_vector, vec1, vec2
96
96
 
97
97
 
98
- def get_time_ground_direction(
98
+ def get_time_ground_direction( # pylint: disable=too-many-positional-arguments
99
99
  sensor,
100
100
  geomodel,
101
101
  geometry_plugin,
@@ -180,6 +180,7 @@ def project_coordinates_on_line(
180
180
  return dist_to_origin * np.cos(proj_angle)
181
181
 
182
182
 
183
+ # pylint: disable=too-many-positional-arguments
183
184
  def lowres_initial_dem_splines_fit(
184
185
  lowres_dsm_from_matches: xr.Dataset,
185
186
  lowres_initial_dem: xr.Dataset,
@@ -379,7 +380,7 @@ def read_lowres_dsm(srtm_path, startx, starty, endx, endy):
379
380
  return dsm_as_ds, newstartx, newstarty, sizex, sizey, resolution
380
381
 
381
382
 
382
- def compute_splines(
383
+ def compute_splines( # pylint: disable=too-many-positional-arguments
383
384
  sensor1,
384
385
  geomodel1,
385
386
  sensor2,
@@ -507,7 +508,7 @@ def compute_splines(
507
508
  }
508
509
 
509
510
 
510
- def cars_devibrate(
511
+ def cars_devibrate( # pylint: disable=too-many-positional-arguments
511
512
  used_conf,
512
513
  srtm_path,
513
514
  geoid_path,
@@ -594,6 +595,8 @@ def cars_devibrate(
594
595
  )
595
596
 
596
597
  x_values_2d, y_values_2d = np.meshgrid(x_values_1d, y_values_1d)
598
+
599
+ positions = None
597
600
  if src.crs != "EPSG:4326":
598
601
  transformer = pyproj.Transformer.from_crs(
599
602
  src.crs, "EPSG:4326", always_xy=True
cars/extractroi.py CHANGED
@@ -29,6 +29,7 @@ import numpy as np
29
29
  import rasterio as rio
30
30
  from affine import Affine
31
31
  from shapely.geometry import box
32
+ from shareloc.geomodels.rpc_writers import write_rio_rpc_as_rpb
32
33
 
33
34
 
34
35
  def is_bbx_in_image(bbx, image_dataset):
@@ -75,7 +76,7 @@ def get_slices_from_bbx(image_dataset, bbx, rpc_options):
75
76
 
76
77
 
77
78
  def process_image_file(
78
- bbx, input_image_path, output_image_path, geom_file_path, rpc_options
79
+ bbx, input_image_path, output_image_path, rpb_file_path, rpc_options
79
80
  ):
80
81
  """
81
82
  Processes an image file by extracting a region based on the given geometry.
@@ -84,7 +85,7 @@ def process_image_file(
84
85
  region_geometry (dict): GeoJSON-like dictionary defining the region.
85
86
  input_image_path (str): Path to the input image file.
86
87
  output_image_path (str): Path to save the output image.
87
- geom_file_path (str): Path to save the .geom file.
88
+ rpb_file_path (str): Path to save the .RPB file.
88
89
  rpc_options (dict): Options for GDALCreateRPCTransformer.
89
90
  """
90
91
 
@@ -110,7 +111,8 @@ def process_image_file(
110
111
  # copy rpc
111
112
  dst.rpcs = image_dataset.rpcs
112
113
 
113
- create_geom_file(image_dataset, geom_file_path)
114
+ if rpb_file_path is not None:
115
+ create_rpb_file(image_dataset, rpb_file_path)
114
116
 
115
117
 
116
118
  def get_human_readable_bbox(image_dataset, rpc_options):
@@ -167,34 +169,23 @@ def validate_bounding_box(bbx, image_dataset, rpc_options):
167
169
  image_dataset, rpc_options
168
170
  )
169
171
  raise ValueError(
170
- f"Coordinates must between "
172
+ f"Coordinates must be between "
171
173
  f"({min_x}, {min_y}) and ({max_x}, {max_y})"
172
174
  )
173
175
 
174
176
 
175
- def create_geom_file(image_dataset, geom_filename):
177
+ def create_rpb_file(image_dataset, rpb_filename):
176
178
  """
177
- Create and save a .geom file from a rasterio dataset
179
+ Create and save a .RPB file from a rasterio dataset
178
180
 
179
181
  Parameters:
180
182
  image_dataset (rio.DatasetReader): Opened image dataset.
181
- geom_filename (str): Path to save the .geom file.
183
+ rpb_filename (str): Path to save the .RPB file.
182
184
  """
183
185
  if not image_dataset.rpcs:
184
186
  raise ValueError("Image dataset has no RPCs")
185
187
  rpcs_as_dict = image_dataset.rpcs.to_dict()
186
- with open(geom_filename, "w", encoding="utf-8") as writer:
187
- for key in rpcs_as_dict:
188
- if isinstance(rpcs_as_dict[key], list):
189
- for idx, coef in enumerate(rpcs_as_dict[key]):
190
- writer.write(key + "_%02d" % idx + ": " + str(coef))
191
- writer.write("\n")
192
- else:
193
- writer.write(key + ": " + str(rpcs_as_dict[key]))
194
- writer.write("\n")
195
-
196
- writer.write("type: ossimRpcModel\n")
197
- writer.write("polynomial_format: B\n")
188
+ write_rio_rpc_as_rpb(rpcs_as_dict, rpb_filename)
198
189
 
199
190
 
200
191
  def main():
@@ -240,6 +231,12 @@ def main():
240
231
  help="Digital Elevation Model used for projection",
241
232
  )
242
233
 
234
+ parser.add_argument(
235
+ "--generate_rpb",
236
+ action="store_true",
237
+ help="Generate RPB file",
238
+ )
239
+
243
240
  args = parser.parse_args()
244
241
  if not os.path.exists(args.out):
245
242
  os.makedirs(args.out)
@@ -254,10 +251,12 @@ def main():
254
251
  # check first input in list to determine pipeline
255
252
  for idx, image_path in enumerate(args.il):
256
253
  output_image_path = os.path.join(args.out, "ext_%03d.tif" % idx)
257
- geom_file_path = os.path.splitext(output_image_path)[0] + ".geom"
254
+ rpb_file_path = None
255
+ if args.generate_rpb:
256
+ rpb_file_path = os.path.splitext(output_image_path)[0] + ".RPB"
258
257
 
259
258
  process_image_file(
260
- args.bbx, image_path, output_image_path, geom_file_path, rpc_options
259
+ args.bbx, image_path, output_image_path, rpb_file_path, rpc_options
261
260
  )
262
261
 
263
262
 
@@ -48,8 +48,13 @@ class AbstractCluster(metaclass=ABCMeta):
48
48
  # cluster mode output directory
49
49
  out_dir: str
50
50
 
51
- def __new__( # pylint: disable=W0613
52
- cls, conf_cluster, out_dir, launch_worker=True, data_to_propagate=None
51
+ def __new__( # pylint: disable=too-many-positional-arguments
52
+ cls,
53
+ conf_cluster,
54
+ out_dir,
55
+ log_dir,
56
+ launch_worker=True,
57
+ data_to_propagate=None,
53
58
  ):
54
59
  """
55
60
  Return the required cluster
@@ -98,8 +103,13 @@ class AbstractCluster(metaclass=ABCMeta):
98
103
 
99
104
  return decorator
100
105
 
101
- def __init__(
102
- self, conf_cluster, out_dir, launch_worker=True, data_to_propagate=None
106
+ def __init__( # pylint: disable=too-many-positional-arguments
107
+ self,
108
+ conf_cluster,
109
+ out_dir,
110
+ log_dir,
111
+ launch_worker=True,
112
+ data_to_propagate=None,
103
113
  ): # pylint: disable=W0613
104
114
  """
105
115
  Init function of AbstractCluster
@@ -114,7 +124,7 @@ class AbstractCluster(metaclass=ABCMeta):
114
124
  # data to propagate
115
125
  self.data_to_propagate = data_to_propagate
116
126
 
117
- self.worker_log_dir = os.path.join(out_dir, "logs", "workers_log")
127
+ self.worker_log_dir = os.path.join(log_dir, "workers_log")
118
128
  if not os.path.exists(self.worker_log_dir):
119
129
  os.makedirs(self.worker_log_dir)
120
130
 
@@ -56,7 +56,7 @@ class AbstractDaskCluster(
56
56
  AbstractDaskCluster
57
57
  """
58
58
 
59
- def __init__(self, conf_cluster, out_dir, launch_worker=True):
59
+ def __init__(self, conf_cluster, out_dir, log_dir, launch_worker=True):
60
60
  """
61
61
  Init function of AbstractDaskCluster
62
62
 
@@ -64,8 +64,12 @@ class AbstractDaskCluster(
64
64
 
65
65
  """
66
66
 
67
+ print("cluster log_dir", log_dir)
68
+
67
69
  # call parent init
68
- super().__init__(conf_cluster, out_dir, launch_worker=launch_worker)
70
+ super().__init__(
71
+ conf_cluster, out_dir, log_dir, launch_worker=launch_worker
72
+ )
69
73
  # retrieve parameters
70
74
  self.nb_workers = self.checked_conf_cluster["nb_workers"]
71
75
  self.task_timeout = self.checked_conf_cluster["task_timeout"]
@@ -30,7 +30,7 @@ import warnings
30
30
  from datetime import timedelta
31
31
 
32
32
 
33
- def init_cluster_variables(
33
+ def init_cluster_variables( # pylint: disable=too-many-positional-arguments
34
34
  nb_workers,
35
35
  walltime,
36
36
  out_dir,