cars 1.0.0a1__cp311-cp311-musllinux_1_2_i686.whl → 1.0.0a3__cp311-cp311-musllinux_1_2_i686.whl

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

Potentially problematic release.


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

Files changed (70) hide show
  1. cars/applications/application.py +14 -6
  2. cars/applications/application_template.py +22 -0
  3. cars/applications/auxiliary_filling/auxiliary_filling_from_sensors_app.py +15 -10
  4. cars/applications/auxiliary_filling/auxiliary_filling_wrappers.py +7 -6
  5. cars/applications/dem_generation/abstract_dem_generation_app.py +9 -5
  6. cars/applications/dem_generation/dem_generation_wrappers.py +48 -25
  7. cars/applications/dem_generation/dichotomic_generation_app.py +27 -9
  8. cars/applications/dem_generation/rasterization_app.py +85 -32
  9. cars/applications/dense_match_filling/abstract_dense_match_filling_app.py +4 -0
  10. cars/applications/dense_match_filling/cpp/dense_match_filling_cpp.cpython-311-i386-linux-musl.so +0 -0
  11. cars/applications/dense_match_filling/fill_disp_algo.py +41 -12
  12. cars/applications/dense_match_filling/plane_app.py +11 -0
  13. cars/applications/dense_match_filling/zero_padding_app.py +11 -1
  14. cars/applications/dense_matching/census_mccnn_sgm_app.py +254 -548
  15. cars/applications/dense_matching/cpp/dense_matching_cpp.cpython-311-i386-linux-musl.so +0 -0
  16. cars/applications/dense_matching/dense_matching_algo.py +59 -11
  17. cars/applications/dense_matching/dense_matching_wrappers.py +51 -31
  18. cars/applications/dense_matching/disparity_grid_algo.py +566 -0
  19. cars/applications/dense_matching/loaders/config_mapping.json +13 -0
  20. cars/applications/dense_matching/loaders/global_land_cover_map.tif +0 -0
  21. cars/applications/dense_matching/loaders/pandora_loader.py +78 -1
  22. cars/applications/dsm_filling/border_interpolation_app.py +10 -5
  23. cars/applications/dsm_filling/bulldozer_filling_app.py +14 -7
  24. cars/applications/dsm_filling/exogenous_filling_app.py +10 -5
  25. cars/applications/grid_generation/grid_correction_app.py +0 -53
  26. cars/applications/grid_generation/transform_grid.py +5 -5
  27. cars/applications/point_cloud_fusion/pc_fusion_algo.py +17 -11
  28. cars/applications/point_cloud_fusion/pc_fusion_wrappers.py +3 -4
  29. cars/applications/point_cloud_outlier_removal/abstract_outlier_removal_app.py +9 -5
  30. cars/applications/point_cloud_outlier_removal/small_components_app.py +5 -3
  31. cars/applications/point_cloud_outlier_removal/statistical_app.py +4 -2
  32. cars/applications/rasterization/abstract_pc_rasterization_app.py +1 -0
  33. cars/applications/rasterization/rasterization_algo.py +20 -27
  34. cars/applications/rasterization/rasterization_wrappers.py +6 -5
  35. cars/applications/rasterization/simple_gaussian_app.py +30 -17
  36. cars/applications/resampling/resampling_algo.py +44 -49
  37. cars/applications/sparse_matching/sift_app.py +2 -22
  38. cars/applications/sparse_matching/sparse_matching_wrappers.py +0 -49
  39. cars/applications/triangulation/line_of_sight_intersection_app.py +1 -1
  40. cars/applications/triangulation/triangulation_wrappers.py +2 -1
  41. cars/bundleadjustment.py +51 -11
  42. cars/cars.py +15 -5
  43. cars/core/constants.py +1 -1
  44. cars/core/geometry/abstract_geometry.py +166 -12
  45. cars/core/geometry/shareloc_geometry.py +61 -14
  46. cars/core/inputs.py +15 -0
  47. cars/core/projection.py +117 -0
  48. cars/data_structures/cars_dataset.py +7 -5
  49. cars/orchestrator/cluster/log_wrapper.py +1 -1
  50. cars/orchestrator/cluster/mp_cluster/multiprocessing_cluster.py +1 -1
  51. cars/orchestrator/orchestrator.py +1 -1
  52. cars/orchestrator/registry/saver_registry.py +0 -78
  53. cars/pipelines/default/default_pipeline.py +69 -52
  54. cars/pipelines/parameters/advanced_parameters.py +17 -0
  55. cars/pipelines/parameters/advanced_parameters_constants.py +4 -0
  56. cars/pipelines/parameters/depth_map_inputs.py +22 -67
  57. cars/pipelines/parameters/dsm_inputs.py +16 -29
  58. cars/pipelines/parameters/output_parameters.py +44 -8
  59. cars/pipelines/parameters/sensor_inputs.py +117 -24
  60. cars/pipelines/parameters/sensor_loaders/basic_sensor_loader.py +3 -3
  61. cars/pipelines/parameters/sensor_loaders/pivot_sensor_loader.py +2 -2
  62. cars/pipelines/parameters/sensor_loaders/sensor_loader.py +4 -6
  63. cars/pipelines/parameters/sensor_loaders/sensor_loader_template.py +2 -2
  64. cars/pipelines/pipeline.py +8 -8
  65. cars/pipelines/unit/unit_pipeline.py +276 -274
  66. cars/starter.py +20 -1
  67. {cars-1.0.0a1.dist-info → cars-1.0.0a3.dist-info}/METADATA +3 -2
  68. {cars-1.0.0a1.dist-info → cars-1.0.0a3.dist-info}/RECORD +161 -158
  69. {cars-1.0.0a1.dist-info → cars-1.0.0a3.dist-info}/WHEEL +0 -0
  70. {cars-1.0.0a1.dist-info → cars-1.0.0a3.dist-info}/entry_points.txt +0 -0
@@ -26,6 +26,8 @@ This module contains class application factory.
26
26
  # Standard imports
27
27
  import logging
28
28
 
29
+ from cars.applications.application_template import ScalingApplicationTemplate
30
+
29
31
  # CARS imports
30
32
  from cars.conf.input_parameters import ConfigType
31
33
 
@@ -46,6 +48,7 @@ class Application:
46
48
  cls,
47
49
  app_name: str,
48
50
  cfg: ConfigType = None,
51
+ scaling_coeff: float = 1,
49
52
  ):
50
53
  """
51
54
  Return the instance of application associated with the application
@@ -55,12 +58,14 @@ class Application:
55
58
  :type app_name: str
56
59
  :param cfg: configuration {'matching_cost_method': value}
57
60
  :type cfg: dictionary
61
+ :param scaling_coeff: scaling factor for resolution
62
+ :type scaling_coeff: float
58
63
  """
59
64
 
60
- return cls.create_app(app_name, cfg)
65
+ return cls.create_app(app_name, cfg, scaling_coeff)
61
66
 
62
67
  @classmethod
63
- def create_app(cls, name: str, cfg: ConfigType):
68
+ def create_app(cls, name: str, cfg: ConfigType, scaling_coeff: float = 1):
64
69
  """Factory command to create the application
65
70
  Return the instance of application associated with the application
66
71
  name given as parameter
@@ -69,16 +74,19 @@ class Application:
69
74
  :type app_name: str
70
75
  :param cfg: configuration {'matching_cost_method': value}
71
76
  :type cfg: dictionary
77
+ :param scaling_coeff: scaling factor for resolution
78
+ :type scaling_coeff: float
72
79
  """
73
- app = None
74
-
75
80
  try:
76
81
  app_class = cls.available_applications[name]
77
82
  except KeyError:
78
83
  logging.error("No application named {0} supported".format(name))
79
84
  return None
80
- app = app_class(conf=cfg)
81
- return app
85
+
86
+ if issubclass(app_class, ScalingApplicationTemplate):
87
+ return app_class(scaling_coeff=scaling_coeff, conf=cfg)
88
+
89
+ return app_class(conf=cfg)
82
90
 
83
91
  @classmethod
84
92
  def print_applications(cls):
@@ -102,3 +102,25 @@ class ApplicationTemplate(metaclass=ABCMeta):
102
102
  """
103
103
 
104
104
  return self.used_config
105
+
106
+
107
+ class ScalingApplicationTemplate(ApplicationTemplate, metaclass=ABCMeta):
108
+ """
109
+ Template for applications requiring resolution scaling.
110
+
111
+ Inherits from ApplicationTemplate and adds the scaling coefficient
112
+ as a required argument.
113
+ """
114
+
115
+ def __init__(self, scaling_coeff, conf=None):
116
+ """
117
+ Init function of ScalingApplicationTemplate
118
+
119
+ :param scaling_coeff: scaling factor for resolution
120
+ :type scaling_coeff: float
121
+
122
+ :param conf: configuration for application
123
+ :type conf: dict
124
+ """
125
+ self.scaling_coeff = scaling_coeff
126
+ super().__init__(conf=conf)
@@ -30,6 +30,7 @@ import numpy as np
30
30
  import rasterio as rio
31
31
  import xarray as xr
32
32
  from json_checker import Checker
33
+ from pyproj import CRS
33
34
  from shapely.geometry import Polygon
34
35
 
35
36
  import cars.orchestrator.orchestrator as ocht
@@ -191,12 +192,15 @@ class AuxiliaryFillingFromSensors(
191
192
  shutil.move(color_file, color_not_filled_file)
192
193
 
193
194
  classification_not_filled_file = None
195
+ # classif_file could be defined without data attached
196
+ if classif_file is not None and not os.path.exists(classif_file):
197
+ classif_file = None
198
+
194
199
  if classif_file is not None:
195
200
  classification_not_filled_file = os.path.join(
196
201
  dump_dir, "classification_not_filled.tif"
197
202
  )
198
- if os.path.exists(classif_file):
199
- shutil.move(classif_file, classification_not_filled_file)
203
+ shutil.move(classif_file, classification_not_filled_file)
200
204
 
201
205
  # Clean dump_dir at the end of processing if required
202
206
  if not self.used_config["save_intermediate_data"]:
@@ -264,12 +268,12 @@ class AuxiliaryFillingFromSensors(
264
268
  [saving_info] = self.orchestrator.get_saving_infos([aux_filled_image])
265
269
 
266
270
  reference_transform = inputs.rasterio_get_transform(dsm_file)
267
- reference_epsg = inputs.rasterio_get_epsg(dsm_file)
271
+ reference_crs = inputs.rasterio_get_crs(dsm_file)
268
272
 
269
273
  # Pre-compute sensor bounds of all sensors to filter sensors that do
270
274
  # not intersect with tile in tasks
271
275
  sensor_bounds = auxiliary_filling_wrappers.compute_sensor_bounds(
272
- sensor_inputs, geom_plugin, reference_epsg
276
+ sensor_inputs, geom_plugin, reference_crs
273
277
  )
274
278
 
275
279
  for row in range(aux_filled_image.shape[0]):
@@ -296,7 +300,7 @@ class AuxiliaryFillingFromSensors(
296
300
  pairing,
297
301
  window,
298
302
  reference_transform,
299
- reference_epsg,
303
+ reference_crs,
300
304
  full_saving_info,
301
305
  geom_plugin,
302
306
  texture_bands,
@@ -324,7 +328,7 @@ def filling_from_sensor_wrapper(
324
328
  pairing,
325
329
  window,
326
330
  transform,
327
- epsg,
331
+ crs,
328
332
  saving_info,
329
333
  geom_plugin,
330
334
  texture_bands,
@@ -351,8 +355,8 @@ def filling_from_sensor_wrapper(
351
355
  :type window: dict
352
356
  :param transform: input geo transform
353
357
  :type transform: tuple
354
- :param epsg: input epsg
355
- :type epsg: int
358
+ :param crs: input crs
359
+ :type crs: CRS
356
360
  :param saving_info: saving info for cars orchestrator
357
361
  :type saving_info: dict
358
362
  :param geom_plugin: geometry plugin used for inverse locations
@@ -399,8 +403,8 @@ def filling_from_sensor_wrapper(
399
403
 
400
404
  stacked_values = np.vstack([cols_values_2d.ravel(), rows_values_2d.ravel()])
401
405
 
402
- lon_lat = projection.point_cloud_conversion(
403
- stacked_values.transpose(), epsg, 4326
406
+ lon_lat = projection.point_cloud_conversion_crs(
407
+ stacked_values.transpose(), crs, CRS(4326)
404
408
  )
405
409
 
406
410
  rio_window = rio.windows.Window.from_slices(
@@ -458,6 +462,7 @@ def filling_from_sensor_wrapper(
458
462
  number_of_classification_bands = 0
459
463
  classification_values = None
460
464
  classification_band_names = None
465
+
461
466
  if classification_file is not None:
462
467
  if os.path.exists(classification_file):
463
468
  with rio.open(classification_file) as classification_image:
@@ -22,12 +22,13 @@
22
22
  this module contains the AuxiliaryFillingFromSensors application class.
23
23
  """
24
24
 
25
+ from pyproj import CRS
25
26
  from shapely.geometry import Polygon
26
27
 
27
- from cars.core.projection import polygon_projection
28
+ from cars.core.projection import polygon_projection_crs
28
29
 
29
30
 
30
- def compute_sensor_bounds(sensor_inputs, geom_plugin, output_epsg):
31
+ def compute_sensor_bounds(sensor_inputs, geom_plugin, output_crs):
31
32
  """
32
33
  Compute bounds of each input sensor that have an associated color or
33
34
  classification image
@@ -38,8 +39,8 @@ def compute_sensor_bounds(sensor_inputs, geom_plugin, output_epsg):
38
39
  :type geom_plugin: AbstractGeometry
39
40
  :param geom_plugin: geometry plugin used for inverse locations
40
41
  :type geom_plugin: AbstractGeometry
41
- :param output_epsg: epsg of the output polygons
42
- :type output_epsg: int
42
+ :param output_crs: crs of the output polygons
43
+ :type output_crs: CRS
43
44
 
44
45
  :return: a dictionary containing a Polygon in output geometry for each
45
46
  valid input sensor
@@ -59,8 +60,8 @@ def compute_sensor_bounds(sensor_inputs, geom_plugin, output_epsg):
59
60
 
60
61
  poly_geo = Polygon([u_l, u_r, l_r, l_l, u_l])
61
62
 
62
- sensor_bounds[sensor_name] = polygon_projection(
63
- poly_geo, 4326, output_epsg
63
+ sensor_bounds[sensor_name] = polygon_projection_crs(
64
+ poly_geo, CRS(4326), output_crs
64
65
  )
65
66
 
66
67
  return sensor_bounds
@@ -26,11 +26,11 @@ from abc import ABCMeta, abstractmethod
26
26
  from typing import Dict
27
27
 
28
28
  from cars.applications.application import Application
29
- from cars.applications.application_template import ApplicationTemplate
29
+ from cars.applications.application_template import ScalingApplicationTemplate
30
30
 
31
31
 
32
32
  @Application.register("dem_generation")
33
- class DemGeneration(ApplicationTemplate, metaclass=ABCMeta):
33
+ class DemGeneration(ScalingApplicationTemplate, metaclass=ABCMeta):
34
34
  """
35
35
  DemGeneration
36
36
  """
@@ -38,13 +38,15 @@ class DemGeneration(ApplicationTemplate, metaclass=ABCMeta):
38
38
  available_applications: Dict = {}
39
39
  default_application = "bulldozer_on_raster"
40
40
 
41
- def __new__(cls, conf=None): # pylint: disable=W0613
41
+ def __new__(cls, scaling_coeff, conf=None): # pylint: disable=W0613
42
42
  """
43
43
  Return the required application
44
44
  :raises:
45
45
  - KeyError when the required application is not registered
46
46
 
47
47
  :param orchestrator: orchestrator used
48
+ :param scaling_coeff: scaling factor for resolution
49
+ :type scaling_coeff: float
48
50
  :param conf: configuration for resampling
49
51
  :return: an application_to_use object
50
52
  """
@@ -84,15 +86,17 @@ class DemGeneration(ApplicationTemplate, metaclass=ABCMeta):
84
86
  super().__init_subclass__(**kwargs)
85
87
  cls.available_applications[short_name] = cls
86
88
 
87
- def __init__(self, conf=None):
89
+ def __init__(self, scaling_coeff, conf=None):
88
90
  """
89
91
  Init function of MntGeneration
90
92
 
93
+ :param scaling_coeff: scaling factor for resolution
94
+ :type scaling_coeff: float
91
95
  :param conf: configuration
92
96
  :return: an application_to_use object
93
97
  """
94
98
 
95
- super().__init__(conf=conf)
99
+ super().__init__(scaling_coeff, conf=conf)
96
100
 
97
101
  @abstractmethod
98
102
  def run(self, triangulated_matches_list, output_dir):
@@ -35,6 +35,7 @@ from affine import Affine
35
35
  from rasterio.coords import BoundingBox
36
36
  from rasterio.enums import Resampling
37
37
  from rasterio.warp import calculate_default_transform, reproject
38
+ from scipy.ndimage import median_filter
38
39
 
39
40
  from cars.core import preprocessing
40
41
 
@@ -243,7 +244,12 @@ def reverse_dem(input_dem):
243
244
  out_dem.nodata = -nodata
244
245
 
245
246
 
246
- def downsample_dem(input_dem, scale):
247
+ def downsample_dem(
248
+ input_dem,
249
+ scale,
250
+ median_filter_size=7,
251
+ default_alt=0,
252
+ ):
247
253
  """
248
254
  Downsample median DEM with median resampling
249
255
 
@@ -265,10 +271,10 @@ def downsample_dem(input_dem, scale):
265
271
  metadata["transform"] = dst_transform
266
272
  metadata["height"] = dst_height
267
273
  metadata["width"] = dst_width
268
- output = np.zeros((dst_height, dst_width))
274
+ dem_data = np.zeros((dst_height, dst_width))
269
275
  reproject(
270
276
  data,
271
- output,
277
+ dem_data,
272
278
  src_transform=src_transform,
273
279
  src_crs=crs,
274
280
  dst_transform=dst_transform,
@@ -277,23 +283,39 @@ def downsample_dem(input_dem, scale):
277
283
  resampling=Resampling.med,
278
284
  )
279
285
 
286
+ # Post-processing
287
+
288
+ # Median filter
289
+ dem_data = median_filter(dem_data, size=median_filter_size)
290
+
291
+ # Fill nodata
292
+ dem_data = rio.fill.fillnodata(
293
+ dem_data,
294
+ mask=~(dem_data == nodata),
295
+ )
296
+
297
+ dem_data[dem_data == nodata] = default_alt
298
+
280
299
  with rio.open(input_dem, "w", **metadata) as dst:
281
- dst.write(output, 1)
300
+ dst.write(dem_data, 1)
282
301
 
283
302
 
284
- def modify_terrain_bounds(dem_roi_to_use, epsg, margin):
303
+ def modify_terrain_bounds(
304
+ bounds_poly, in_epsg, out_epsg, constant_margin, linear_margin=0
305
+ ):
285
306
  """
286
307
  Modify the terrain bounds
287
308
 
288
- :param dem_roi_to_use: the dem roi
289
- :type dem_roi_to_use: polygon
290
- :param epsg: the epsg code
291
- :type epsg: int
292
- :param margin: the margin
309
+ :param bounds_poly: Input region of interest for DEM
310
+ :type bounds_poly: list
311
+ :param in_epsg: EPSG code of dem_roi_to_use
312
+ :type in_epsg: int
313
+ :param out_epsg: EPSG code of dem_roi_to_use
314
+ :type out_epsg: int
315
+ :param margin: Margin of the output ROI in meters
293
316
  :type margin: int
294
317
  """
295
318
  # Get bounds
296
- bounds_poly = dem_roi_to_use.bounds
297
319
  xmin = min(bounds_poly[0], bounds_poly[2])
298
320
  xmax = max(bounds_poly[0], bounds_poly[2])
299
321
  ymin = min(bounds_poly[1], bounds_poly[3])
@@ -301,24 +323,25 @@ def modify_terrain_bounds(dem_roi_to_use, epsg, margin):
301
323
 
302
324
  bounds_cloud = [xmin, ymin, xmax, ymax]
303
325
 
304
- # Convert resolution and margin to degrees
305
- utm_epsg = preprocessing.get_utm_zone_as_epsg_code(xmin, ymin)
306
- conversion_factor = preprocessing.get_conversion_factor(
307
- bounds_cloud, 4326, utm_epsg
308
- )
309
- margin_in_degrees = margin * conversion_factor
326
+ if in_epsg == 4326:
327
+ # Convert resolution and margin to degrees
328
+ utm_epsg = preprocessing.get_utm_zone_as_epsg_code(xmin, ymin)
329
+ conversion_factor = preprocessing.get_conversion_factor(
330
+ bounds_cloud, 4326, utm_epsg
331
+ )
332
+ constant_margin *= conversion_factor
310
333
 
311
334
  # Get borders, adding margin
312
- xmin = xmin - margin_in_degrees
313
- ymin = ymin - margin_in_degrees
314
- xmax = xmax + margin_in_degrees
315
- ymax = ymax + margin_in_degrees
335
+ xmin = xmin - constant_margin - linear_margin * (xmax - xmin)
336
+ ymin = ymin - constant_margin - linear_margin * (ymax - ymin)
337
+ xmax = xmax + constant_margin + linear_margin * (xmax - xmin)
338
+ ymax = ymax + constant_margin + linear_margin * (ymax - ymin)
316
339
 
317
340
  terrain_bounds = [xmin, ymin, xmax, ymax]
318
341
 
319
- if epsg != 4326:
320
- crs_in = pyproj.CRS.from_epsg(4326)
321
- crs_out = pyproj.CRS.from_epsg(epsg)
342
+ if out_epsg != in_epsg:
343
+ crs_in = pyproj.CRS.from_epsg(in_epsg)
344
+ crs_out = pyproj.CRS.from_epsg(out_epsg)
322
345
 
323
346
  transformer = pyproj.Transformer.from_crs(
324
347
  crs_in, crs_out, always_xy=True
@@ -340,7 +363,7 @@ def modify_terrain_bounds(dem_roi_to_use, epsg, margin):
340
363
 
341
364
  def reproject_dem(dsm_file_name, epsg_out, out_file_name):
342
365
  """
343
- Reproject the dem
366
+ Reproject the DEM
344
367
 
345
368
  :param dsm_file_name: the path to dsm
346
369
  :type dsm_file_name: str
@@ -64,14 +64,16 @@ class DichotomicGeneration(DemGeneration, short_name="dichotomic"):
64
64
 
65
65
  # pylint: disable=too-many-instance-attributes
66
66
 
67
- def __init__(self, conf=None):
67
+ def __init__(self, scaling_coeff, conf=None):
68
68
  """
69
69
  Init function of DichotomicGeneration
70
70
 
71
+ :param scaling_coeff: scaling factor for resolution
72
+ :type scaling_coeff: float
71
73
  :param conf: configuration for DichotomicGeneration
72
74
  :return: an application_to_use object
73
75
  """
74
- super().__init__(conf=conf)
76
+ super().__init__(scaling_coeff, conf=conf)
75
77
 
76
78
  # check conf
77
79
  self.used_method = self.used_config["method"]
@@ -175,11 +177,13 @@ class DichotomicGeneration(DemGeneration, short_name="dichotomic"):
175
177
  self,
176
178
  triangulated_matches_list,
177
179
  output_dir,
178
- geoid_path,
180
+ input_geoid,
181
+ output_geoid,
179
182
  dem_roi_to_use=None,
180
183
  initial_elevation=None,
184
+ default_alt=0,
181
185
  cars_orchestrator=None,
182
- ):
186
+ ): # pylint: disable=W0613
183
187
  """
184
188
  Run dichotomic dem generation using matches
185
189
 
@@ -188,7 +192,8 @@ class DichotomicGeneration(DemGeneration, short_name="dichotomic"):
188
192
  :type triangulated_matches_list: list(pandas.Dataframe)
189
193
  :param output_dir: directory to save dem
190
194
  :type output_dir: str
191
- :param geoid_path: geoid path
195
+ :param input_geoid: input geoid path
196
+ :param output_geoid: output geoid path
192
197
  :param cars_orchrestrator: the main cars orchestrator
193
198
  :param dem_roi_to_use: dem roi polygon to use as roi
194
199
  :param initial_elevation: the path to the initial elevation file
@@ -208,6 +213,11 @@ class DichotomicGeneration(DemGeneration, short_name="dichotomic"):
208
213
  # Generate point cloud
209
214
  epsg = 4326
210
215
 
216
+ # Optimize the case when input and output geoid are the same
217
+ if output_geoid is True:
218
+ input_geoid = False
219
+ output_geoid = False
220
+
211
221
  for pair_pc in triangulated_matches_list:
212
222
  # convert to degrees for geoid offset
213
223
  if pair_pc.attrs["epsg"] != epsg:
@@ -312,9 +322,14 @@ class DichotomicGeneration(DemGeneration, short_name="dichotomic"):
312
322
  # Transform to lon lat
313
323
  projection.point_cloud_conversion_dataset(alti_zeros_dataset, 4326)
314
324
 
315
- geoid_offset = triangulation_wrappers.geoid_offset(
316
- alti_zeros_dataset, geoid_path
317
- )
325
+ if input_geoid:
326
+ input_geoid = triangulation_wrappers.geoid_offset(
327
+ alti_zeros_dataset, input_geoid
328
+ )
329
+ if output_geoid:
330
+ output_geoid = triangulation_wrappers.geoid_offset(
331
+ alti_zeros_dataset, output_geoid
332
+ )
318
333
 
319
334
  # fillnodata
320
335
  valid = np.isfinite(list_z_grid[0])
@@ -323,7 +338,10 @@ class DichotomicGeneration(DemGeneration, short_name="dichotomic"):
323
338
  list_z_grid[idx] = rasterio.fill.fillnodata(
324
339
  list_z_grid[idx], mask=valid, max_search_distance=msd
325
340
  )
326
- list_z_grid[idx] += geoid_offset[cst.Z].values
341
+ if input_geoid:
342
+ list_z_grid[idx] += input_geoid[cst.Z].values
343
+ if output_geoid:
344
+ list_z_grid[idx] -= output_geoid[cst.Z].values
327
345
 
328
346
  dem_median = list_z_grid[0]
329
347
  dem_min = list_z_grid[1]