From e0ca65e6b173eb6a5496350adc65737c845ba938 Mon Sep 17 00:00:00 2001
From: Luc Hermitte <luc.hermitte@cs-soprasteria.com>
Date: Fri, 28 Feb 2025 19:14:08 +0100
Subject: [PATCH 1/5] DOC: Update release_notes about Python 3.8 EOL

---
 docs/release_notes.rst | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/docs/release_notes.rst b/docs/release_notes.rst
index 3c245b1c..4d7cc566 100644
--- a/docs/release_notes.rst
+++ b/docs/release_notes.rst
@@ -10,8 +10,12 @@ v1.2.0 Breaking changes
 +++++++++++++++++++++++
 
 - Compatibility to OTB 7.x (and even 8.x) is no longer actively pursued.
-  S1Tiling may work with older version of OTB, but with no guarantees.
+  S1Tiling may work with older version of OTB, but with no guarantees
   (`#164 <https://gitlab.orfeo-toolbox.org/s1-tiling/s1tiling/-/issues/164>`_).
+- Compatibility to Python 3.8 is no longer actively pursued as Python 3.8 has
+  reached its end-of-life in 2024.
+  S1Tiling may work with older version of Python, but with no guarantees
+  (`#158 <https://gitlab.orfeo-toolbox.org/s1-tiling/s1tiling/-/issues/158>`_).
 
 v1.2.0 Improvements
 +++++++++++++++++++
-- 
GitLab


From 7d1b25e93fd16924b3df09df2342c86f9a50484c Mon Sep 17 00:00:00 2001
From: Luc Hermitte <luc.hermitte@cs-soprasteria.com>
Date: Fri, 28 Feb 2025 22:11:56 +0100
Subject: [PATCH 2/5] ENH: Add extra GeoTIFF `[Metadata]` section in conf

---
 docs/configuration.rst             |  8 ++++++++
 docs/files.rst                     | 24 +++++++++++++++++-------
 docs/release_notes.rst             | 17 ++++++++++-------
 s1tiling/libs/configuration.py     | 26 +++++++++++++++++++++++---
 s1tiling/libs/steps.py             |  5 ++++-
 s1tiling/resources/S1Processor.cfg |  4 ++++
 6 files changed, 66 insertions(+), 18 deletions(-)

diff --git a/docs/configuration.rst b/docs/configuration.rst
index 0668ac3f..9303db9c 100644
--- a/docs/configuration.rst
+++ b/docs/configuration.rst
@@ -749,6 +749,14 @@ You can use this :download:`this template
            V1.0 of S1Tiling.  See Issue `#118
            <https://gitlab.orfeo-toolbox.org/s1-tiling/s1tiling/-/issues/118>`_.
 
+.. _Metadata:
+
+``[Metadata]`` section
+++++++++++++++++++++++
+
+You can place in this section any extra ``key : value`` information that you
+want written in the GeoTIFF metadata of S1Tiling products.
+
 
 .. commented-out-to-be-implemented:
       .. _Filtering.reset_outcore:
diff --git a/docs/files.rst b/docs/files.rst
index e29fa63c..4c7e11b7 100644
--- a/docs/files.rst
+++ b/docs/files.rst
@@ -50,7 +50,11 @@ Orthorectified S2 tiles
     - defined in :ref:`[Processing].creation_options.tiled
       <processing.creation_options.tiled>`
 
-:Metadata: The following metadata is added to the origin S1 images
+:Metadata:
+
+    GeoTIFF metadata will contain: the ones coming from the input S1 GRD
+    products, the extra ones specified in :ref:`[Metadata] <metadata>`
+    configuration section, plus the following ones:
 
     .. list-table::
       :widths: auto
@@ -122,7 +126,6 @@ Mask files
     - defined in :ref:`[Processing].creation_options.mask
       <processing.creation_options.mask>`
 
-
 :Metadata: This file contains the same metadata as the one from :ref:`the S2 tile product <full-S2-tiles>` it has been generated from, with the following as the only difference:
 
     .. list-table::
@@ -168,7 +171,6 @@ Filtered files
     - defined in :ref:`[Processing].creation_options.filtered
       <processing.creation_options.filtered>`
 
-
 :Metadata: This file contains the same metadata as the one from :ref:`the S2 tile product <full-S2-tiles>` it has been generated from, with the following as the only difference:
 
     .. list-table::
@@ -238,8 +240,11 @@ Local Incidence Angle map files
       (/:ref:`[Processing].creation_options.lia_deg
       <processing.creation_options.lia_deg>`)
 
+:Metadata:
 
-:Metadata: The following image metadata is set:
+    GeoTIFF metadata will contain the extra metadata specified in
+    :ref:`[Metadata] <metadata>` configuration section, plus the following
+    ones:
 
     .. list-table::
       :widths: auto
@@ -325,8 +330,11 @@ tile <full-S2-tiles>` from one calibration (β°, σ°, γ°) to another.
       (/:ref:`[Processing].creation_options.ia_deg
       <processing.creation_options.ia_deg>`)
 
+:Metadata:
 
-:Metadata: The following image metadata is set:
+    GeoTIFF metadata will contain the extra metadata specified in
+    :ref:`[Metadata] <metadata>` configuration section, plus the following
+    ones:
 
     .. list-table::
       :widths: auto
@@ -459,8 +467,10 @@ Orthorectified S1 images
 
 :Product encoding: Float32 GeoTIFF, deflate compressed
 
-:Metadata: The metadata listed for :ref:`the S2 tile product <full-S2-tiles>`
-           are actually produced at this step.
+:Metadata:
+
+    The metadata listed for :ref:`the S2 tile product <full-S2-tiles>` are
+    actually produced at this step.
 
 .. note::
    These files are automatically cleaned up.
diff --git a/docs/release_notes.rst b/docs/release_notes.rst
index 4d7cc566..fe035259 100644
--- a/docs/release_notes.rst
+++ b/docs/release_notes.rst
@@ -24,15 +24,18 @@ v1.2.0 Improvements
   Incidence Angle maps <lia-files>`
   (`#151 <https://gitlab.orfeo-toolbox.org/s1-tiling/s1tiling/-/issues/151>`_).
 - Support eodag 3
-  (`#170 <https://gitlab.orfeo-toolbox.org/s1-tiling/s1tiling/-/issues/170>`_),
-  (`#177 <https://gitlab.orfeo-toolbox.org/s1-tiling/s1tiling/-/issues/177>`_),
-  (`#178 <https://gitlab.orfeo-toolbox.org/s1-tiling/s1tiling/-/issues/178>`_).
+  (`#170 <https://gitlab.orfeo-toolbox.org/s1-tiling/s1tiling/-/issues/170>`_,
+  `#177 <https://gitlab.orfeo-toolbox.org/s1-tiling/s1tiling/-/issues/177>`_,
+  `#178 <https://gitlab.orfeo-toolbox.org/s1-tiling/s1tiling/-/issues/178>`_).
   An indirect consequence is that products will be downloaded into
   :samp:`{{s1images}}/{{product_name}}/` instead of
   :samp:`{{s1images}}/{{product_name}}/{{product_name}}.SAFE/`. The old output
   directory structure is still supported for backward compatibility reasons.
 - Generate :ref:`maps of incidence angles to the WGS84 ellipsoid <ia-files>`
   (`#161 <https://gitlab.orfeo-toolbox.org/s1-tiling/s1tiling/-/issues/161>`_).
+- Add :ref:`[Metadata] <metadata>` configuration section to specify extra
+  GeoTIFF metadata that will be set in the images produced by S1Tiling
+  (`#171 <https://gitlab.orfeo-toolbox.org/s1-tiling/s1tiling/-/issues/171>`_).
 
 
 Version 1.1.0
@@ -75,7 +78,7 @@ v1.1.0 Improvements
   :ref:`creation_options.* <Processing.creation_options>` options
   (`#66 <https://gitlab.orfeo-toolbox.org/s1-tiling/s1tiling/-/issues/66>`_).
 - GEOID file is also copied alongside DEM data when :ref:`[Processing].cache_dem_by
-  <Processing.cache_dem_by>` option is on.
+  <Processing.cache_dem_by>` option is on
   (`#123 <https://gitlab.orfeo-toolbox.org/s1-tiling/s1tiling/-/issues/123>`_).
 
 v1.1.0 Bugs fixed
@@ -83,12 +86,12 @@ v1.1.0 Bugs fixed
 
 - Noise correction post-processing shall not transform wide no-data sides from
   Sentinel-1 IPF 2.90+ products into :ref:`minimal signal value
-  <Processing.lower_signal_value>`.
+  <Processing.lower_signal_value>`
   (`#159 <https://gitlab.orfeo-toolbox.org/s1-tiling/s1tiling/-/issues/159>`_).
 
-- Handling of `nodata` values has been improved.
+- Handling of `nodata` values has been improved
   (`#159 <https://gitlab.orfeo-toolbox.org/s1-tiling/s1tiling/-/issues/159>`_,
-  (`#160 <https://gitlab.orfeo-toolbox.org/s1-tiling/s1tiling/-/issues/160>`_).
+  `#160 <https://gitlab.orfeo-toolbox.org/s1-tiling/s1tiling/-/issues/160>`_).
 
 
 v1.1.0 Breaking changes
diff --git a/s1tiling/libs/configuration.py b/s1tiling/libs/configuration.py
index b127d486..849a2c17 100644
--- a/s1tiling/libs/configuration.py
+++ b/s1tiling/libs/configuration.py
@@ -245,6 +245,15 @@ class _ConfigAccessor:
         """Helper function to report errors while extracting boolean configuration options"""
         return getboolean_opt(self.__config, self.config_file, section, name, **kwargs)
 
+    def get_items(self, section: str) -> Dict:
+        """Helper function to return configuration items from a section"""
+        res = {}
+        if self.__config.has_section(section):
+            options = self.__config.options(section) - self.__config.defaults().keys()
+            for option in options:
+                res[option] = self.__config.get(section, option, raw=True)
+        return res
+
 
 # The configuration decoding specific to S1Tiling application
 class Configuration:  # pylint: disable=too-many-instance-attributes
@@ -271,6 +280,7 @@ class Configuration:  # pylint: disable=too-many-instance-attributes
         self.__init_fname_fmt(accessor)
         self.__init_dname_fmt(accessor)
         self.__init_creation_options(accessor)
+        self.__init_extra_metadata(accessor)
 
         # Other options
         #: Type of images handled
@@ -570,6 +580,13 @@ class Configuration:  # pylint: disable=too-many-instance-attributes
 
                 self.creation_options[key] = cos
 
+    # ----------------------------------------------------------------------
+    def __init_extra_metadata(self, accessor: _ConfigAccessor) -> None:
+        # TODO: how can we handle metadata that don't always make sense like DEM kind...
+        # => take the directory of the DEM files, or the ID key or the .gpkg file, or a manual option
+        #: Extra geotiff metadata options to write in all products
+        self.extra_metadata = accessor.get_items('Metadata')
+
     # ----------------------------------------------------------------------
     def show_configuration(self) -> None:  # pylint: disable=too-many-statements
         """
@@ -630,15 +647,18 @@ class Configuration:  # pylint: disable=too-many-instance-attributes
             elif self.filter in ['frost']:
                 logging.info("- deramp                           : %s", self.filter_options['deramp'])
 
+        logging.info('Extra metadata                     : %s', len(self.extra_metadata))
+        for meta, value in self.extra_metadata.items():
+            logging.info('- %s --> %s', meta, value)
         logging.info('Output directories:')
         for k, fmt in self.dname_fmt.items():
-            logging.info(' - %s --> %s', k, fmt)
+            logging.info('- %s --> %s', k, fmt)
         logging.info('Filename formats:')
         for k, fmt in self.fname_fmt.items():
-            logging.info(' - %s --> %s', k, fmt)
+            logging.info('- %s --> %s', k, fmt)
         logging.info('Creation options:')
         for k, co in self.creation_options.items():
-            logging.info(' - %s --> %s', k, co)
+            logging.info('- %s --> %s', k, co)
 
     def init_logger(self, config_log_dir: Path, mode=None) -> None:
         """
diff --git a/s1tiling/libs/steps.py b/s1tiling/libs/steps.py
index 58646a98..921d2576 100644
--- a/s1tiling/libs/steps.py
+++ b/s1tiling/libs/steps.py
@@ -574,6 +574,7 @@ class StepFactory(ABC):
         assert isinstance(name, str), f"{self.__class__.__name__} name is a {name.__class__.__name__}, not a string -> {name!r}"
         self._name               = name
         self.__image_description = kwargs.get('image_description', None)
+        self.__extra_metadata    = kwargs.get('extra_metadata', {})
         # logger.debug("new StepFactory(%s)", name)
 
     @property
@@ -748,6 +749,8 @@ class StepFactory(ABC):
                 imd['TIFFTAG_IMAGEDESCRIPTION'] = self.image_description.format(
                     **meta,
                     flying_unit_code_short=meta.get('flying_unit_code', 'S1?')[1:].upper())
+        for key, value in self.__extra_metadata.items():
+            imd[key] = value
 
     def _get_inputs(self, previous_steps: List[InputList]) -> InputList:
         """
@@ -985,7 +988,7 @@ class _FileProducingStepFactory(StepFactory):
         :func:`build_step_output_tmp_filename` for the usage of ``gen_tmp_dir``,
         ``gen_output_dir`` and ``gen_output_filename``.
         """
-        super().__init__(*argv, **kwargs)
+        super().__init__(*argv, extra_metadata=cfg.extra_metadata, **kwargs)
         is_a_final_step = gen_output_dir and gen_output_dir != gen_tmp_dir
         # logger.debug("%s -> final: %s <== gen_tmp=%s    gen_out=%s", self.name, is_a_final_step, gen_tmp_dir, gen_output_dir)
 
diff --git a/s1tiling/resources/S1Processor.cfg b/s1tiling/resources/S1Processor.cfg
index 45d2a41f..3659ffec 100644
--- a/s1tiling/resources/S1Processor.cfg
+++ b/s1tiling/resources/S1Processor.cfg
@@ -259,3 +259,7 @@ keep_non_filtered_products : True
 # # If True, the outcore of the multiImage filter is reset before filtering. It means that the outcore is recomputed from scratch with the new images only.
 # # If False, the outcore is updated with the new images. Then, the outcore integrates previous images and new images.
 # reset_outcore : True
+
+[Metadata]
+contact : Your Name <your.email@your.wo.rk>
+any thing : you want added in the output image metadata
-- 
GitLab


From 97be55f296734c74fe7d31aac90959e73da2f478 Mon Sep 17 00:00:00 2001
From: Luc Hermitte <luc.hermitte@cs-soprasteria.com>
Date: Sat, 1 Mar 2025 00:39:07 +0100
Subject: [PATCH 3/5] ENH: Write DEM/GEOID interp method in GeoTIFF meta

---
 docs/files.rst                        | 15 +++++++++++++--
 s1tiling/libs/otbwrappers/lia.py      | 21 +++++++++++++++++----
 s1tiling/libs/otbwrappers/s1_to_s2.py |  7 ++++---
 3 files changed, 34 insertions(+), 9 deletions(-)

diff --git a/docs/files.rst b/docs/files.rst
index 4c7e11b7..44c08b67 100644
--- a/docs/files.rst
+++ b/docs/files.rst
@@ -86,6 +86,9 @@ Orthorectified S2 tiles
         - :samp:`{{orbitNumber}}`
       * - ``ORBIT_DIRECTION``
         - :samp:`{{orbitDirection}}`
+      * - ``ORTHORECTIFICATION_INTERPOLATOR``
+        - :ref:`chosen orthorectification interpolation method option
+          <Processing.orthorectification_interpolation_method>`
       * - ``ORTHORECTIFIED``
         - :samp:`true`
       * - ``POLARIZATION``
@@ -258,10 +261,15 @@ Local Incidence Angle map files
         - :samp:`100 * degrees(LIA)` / :samp:`sin(LIA)`
       * - ``DEM_LIST``
         - List of DEM (SRTM currently) tiles used to generate the file
+      * - ``DEM_RESAMPLING_METHOD``
+        - :ref:`chosen DEM resampling method option <Processing.dem_warp_resampling_method>`
       * - ``EOF_FILE``
         - Precise orbit file used to generate the file
       * - ``FLYING_UNIT_CODE``
         - :samp:`s1{{a|b}}`
+      * - ``GEOID_ORTHORECTIFICATION_INTERPOLATOR``
+        - :ref:`chosen orthorectification interpolation_method option
+          <Processing.orthorectification_interpolation_method>`
       * - ``IMAGE_TYPE``
         - :samp:`LIA`
       * - ``RELATIVE_ORBIT_NUMBER``
@@ -357,8 +365,6 @@ tile <full-S2-tiles>` from one calibration (β°, σ°, γ°) to another.
         - :samp:`true`
       * - ``RELATIVE_ORBIT_NUMBER``
         - :samp:`{{orbitnumber}}`
-      * - ``ORTHORECTIFIED``
-        - :samp:`true`
       * - ``S2_TILE_CORRESPONDING_CODE``
         - :samp:`{{tilename}}`
       * - ``SPATIAL_RESOLUTION``
@@ -522,6 +528,8 @@ DEM data projected on S2 tile
 
       * - Metadata
         - Value
+      * - ``DEM_RESAMPLING_METHOD``
+        - :ref:`chosen DEM resampling method option <Processing.dem_warp_resampling_method>`
       * - ``S2_TILE_CORRESPONDING_CODE``
         - :samp:`{{tilename}}`
       * - ``SPATIAL_RESOLUTION``
@@ -556,6 +564,9 @@ Height (DEM+Geoid) projected on S2 tile
 
       * - Metadata
         - Value
+      * - ``GEOID_ORTHORECTIFICATION_INTERPOLATOR``
+        - :ref:`chosen orthorectification interpolation_method option
+          <Processing.orthorectification_interpolation_method>`
       * - ``TIFFTAG_IMAGEDESCRIPTION``
         - :samp:`DEM + GEOID height info projected on S2 tile`
 
diff --git a/s1tiling/libs/otbwrappers/lia.py b/s1tiling/libs/otbwrappers/lia.py
index 554237fb..e6893d2e 100644
--- a/s1tiling/libs/otbwrappers/lia.py
+++ b/s1tiling/libs/otbwrappers/lia.py
@@ -309,9 +309,10 @@ class ProjectGeoidToS2Tile(OTBStepFactory):
         super().update_image_metadata(meta, all_inputs)
         assert 'image_metadata' in meta
         imd = meta['image_metadata']
-        imd['S2_TILE_CORRESPONDING_CODE'] = meta['tile_name']
-        imd['SPATIAL_RESOLUTION']         = str(self.__out_spatial_res)
-        imd['ORTHORECTIFIED']             = 'true'
+        imd['GEOID_ORTHORECTIFICATION_INTERPOLATOR'] = self.__interpolation_method
+        imd['ORTHORECTIFIED']                        = 'true'
+        imd['S2_TILE_CORRESPONDING_CODE']            = meta['tile_name']
+        imd['SPATIAL_RESOLUTION']                    = str(self.__out_spatial_res)
 
     def parameters(self, meta: Meta) -> OTBParameters:
         """
@@ -342,7 +343,6 @@ class SumAllHeights(OTBStepFactory):
     - `nodata.DEM` -- optional
 
     It requires the following information from the metadata dictionary:
-
     """
     def __init__(self, cfg: Configuration) -> None:
         """
@@ -409,6 +409,19 @@ class SumAllHeights(OTBStepFactory):
         assert 'in_s2_geoid' in keys
         return [input['in_s2_geoid'] for input in inputs if 'in_s2_geoid' in input.keys()][0]
 
+    def update_image_metadata(self, meta: Meta, all_inputs: InputList) -> None:
+        """
+        Metadata coming from the DEM image are lost => we fetch them in the DEM file.
+        """
+        super().update_image_metadata(meta, all_inputs)
+
+        in_s2_dem   = fetch_input_data('in_s2_dem',   all_inputs).out_filename
+        dst = gdal.Open(in_s2_dem, gdal.GA_ReadOnly)
+        assert 'image_metadata' in meta
+        imd = meta['image_metadata']
+        imd['DEM_RESAMPLING_METHOD'] = dst.GetMetadataItem('DEM_RESAMPLING_METHOD')
+        del dst
+
     def parameters(self, meta: Meta) -> OTBParameters:
         """
         Returns the parameters to use with :external:doc:`BandMath OTB application
diff --git a/s1tiling/libs/otbwrappers/s1_to_s2.py b/s1tiling/libs/otbwrappers/s1_to_s2.py
index 4754fb4d..45b24cb3 100644
--- a/s1tiling/libs/otbwrappers/s1_to_s2.py
+++ b/s1tiling/libs/otbwrappers/s1_to_s2.py
@@ -656,9 +656,10 @@ class _OrthoRectifierFactory(OTBStepFactory):
         super().update_image_metadata(meta, all_inputs)
         assert 'image_metadata' in meta
         imd = meta['image_metadata']
-        imd['S2_TILE_CORRESPONDING_CODE'] = meta['tile_name']
-        imd['ORTHORECTIFIED']             = 'true'
-        imd['SPATIAL_RESOLUTION']         = str(self.__out_spatial_res)
+        imd['ORTHORECTIFICATION_INTERPOLATOR'] = self.__interpolation_method
+        imd['ORTHORECTIFIED']                  = 'true'
+        imd['S2_TILE_CORRESPONDING_CODE']      = meta['tile_name']
+        imd['SPATIAL_RESOLUTION']              = str(self.__out_spatial_res)
         # S1 -> S2 => remove all SAR specific metadata inserted by OTB
         meta_to_remove_in_s2 = (
                 'SARCalib*', 'SAR', 'PRF', 'RadarFrequency', 'RedDisplayChannel',
-- 
GitLab


From 9282b7a579ade9860c11b4e66423e2c97ea58beb Mon Sep 17 00:00:00 2001
From: Luc Hermitte <luc.hermitte@cs-soprasteria.com>
Date: Mon, 3 Mar 2025 11:58:23 +0100
Subject: [PATCH 4/5] ENH: Fill DEM_INFO metadata from [Paths].dem_info

---
 docs/configuration.rst                |  6 ++++
 docs/files.rst                        | 49 ++++++++++++++++++++++-----
 docs/release_notes.rst                |  7 ++--
 s1tiling/libs/configuration.py        |  4 ++-
 s1tiling/libs/otbwrappers/lia.py      | 10 ++++++
 s1tiling/libs/otbwrappers/s1_to_s2.py |  2 ++
 s1tiling/resources/S1Processor.cfg    |  4 +++
 7 files changed, 71 insertions(+), 11 deletions(-)

diff --git a/docs/configuration.rst b/docs/configuration.rst
index 9303db9c..3c114188 100644
--- a/docs/configuration.rst
+++ b/docs/configuration.rst
@@ -92,6 +92,12 @@ You can use this :download:`this template
       the keys from `eotile <https://github.com/CS-SI/eotile>`_ DEM database
       like for instance :file:`{{Product10}}.tif` for Copernicus 30m DEM.
 
+      .. _paths.dem_info:
+  * - ``dem_info``
+    - DEM identifier to inject in the products GeoTIFF metadata under
+      ``DEM_INFO`` key. If not defined, the last part (basename) of
+      :ref:`[Paths].dem_dir <paths.dem_dir>` will be used.
+
       .. _paths.srtm:
   * - ``srtm``
     - **(deprecated)** Use :ref:`[PATHS].dem_dir <paths.dem_dir>`. Path to SRTM files.
diff --git a/docs/files.rst b/docs/files.rst
index 44c08b67..6331afb6 100644
--- a/docs/files.rst
+++ b/docs/files.rst
@@ -1,3 +1,8 @@
+.. # define a hard line break for HTML
+.. |br| raw:: html
+
+   <br />
+
 .. _files:
 
 .. index:: files
@@ -72,6 +77,14 @@ Orthorectified S2 tiles
         - time of the second S1 image (in UTC format since v1.1)
       * - ``CALIBRATION``
         - :ref:`chosen calibration option <Processing.calibration>`
+      * - ``DEM_INFO``
+        - Key to identify which DEM has been used. |br|
+          Comes from :ref:`[Paths].dem_info <paths.dem_info>` or
+          :ref:`basename([Paths].dem_dir) <paths.dem_info>`.
+      * - ``DEM_INFO``
+        - Key to identify which DEM has been used. |br|
+          Comes from :ref:`[Paths].dem_info <paths.dem_info>` or
+          :ref:`basename([Paths].dem_dir) <paths.dem_info>`.
       * - ``FLYING_UNIT_CODE``
         - :samp:`s1{{a|b}}`
       * - ``IMAGE_TYPE``
@@ -259,8 +272,12 @@ Local Incidence Angle map files
 
       * - ``DATA_TYPE``
         - :samp:`100 * degrees(LIA)` / :samp:`sin(LIA)`
+      * - ``DEM_INFO``
+        - Key to identify which DEM has been used. |br|
+          Comes from :ref:`[Paths].dem_info <paths.dem_info>` or
+          :ref:`basename([Paths].dem_dir) <paths.dem_info>`.
       * - ``DEM_LIST``
-        - List of DEM (SRTM currently) tiles used to generate the file
+        - List of DEM tiles used to generate the file
       * - ``DEM_RESAMPLING_METHOD``
         - :ref:`chosen DEM resampling method option <Processing.dem_warp_resampling_method>`
       * - ``EOF_FILE``
@@ -528,16 +545,20 @@ DEM data projected on S2 tile
 
       * - Metadata
         - Value
+      * - ``DEM_INFO``
+        - Key to identify which DEM has been used. |br|
+          Comes from :ref:`[Paths].dem_info <paths.dem_info>` or
+          :ref:`basename([Paths].dem_dir) <paths.dem_info>`.
+      * - ``DEM_LIST``
+        - List of DEM tiles used to generate the file
       * - ``DEM_RESAMPLING_METHOD``
         - :ref:`chosen DEM resampling method option <Processing.dem_warp_resampling_method>`
+      * - ``ORTHORECTIFIED``
+        - :samp:`true`
       * - ``S2_TILE_CORRESPONDING_CODE``
         - :samp:`{{tilename}}`
       * - ``SPATIAL_RESOLUTION``
         - :ref:`chosen output spatial resolution option <Processing.output_spatial_resolution>`
-      * - ``DEM_LIST``
-        - List of DEM (SRTM currently) tiles used to generate the file
-      * - ``ORTHORECTIFIED``
-        - :samp:`true`
       * - ``TIFFTAG_IMAGEDESCRIPTION``
         - :samp:`Warped DEM to S2 tile`
 
@@ -607,8 +628,12 @@ files.
       * - Metadata
         - Value
 
+      * - ``DEM_INFO``
+        - Key to identify which DEM has been used. |br|
+          Comes from :ref:`[Paths].dem_info <paths.dem_info>` or
+          :ref:`basename([Paths].dem_dir) <paths.dem_info>`.
       * - ``DEM_LIST``
-        - List of DEM (SRTM currently) tiles used to generate the file
+        - List of DEM tiles used to generate the file
       * - ``EOF_FILE``
         - Precise orbit file used to generate the file
       * - ``FLYING_UNIT_CODE``
@@ -721,8 +746,12 @@ Files of S1 coordinates projected on DEM geometry (deprecated)
 
       * - ``ACQUISITION_DATETIME``
         - time of the first S1 image (in UTC format since v1.1)
+      * - ``DEM_INFO``
+        - Key to identify which DEM has been used. |br|
+          Comes from :ref:`[Paths].dem_info <paths.dem_info>` or
+          :ref:`basename([Paths].dem_dir) <paths.dem_info>`.
       * - ``DEM_LIST``
-        - List of DEM (SRTM currently) tiles used to generate the file
+        - List of DEM tiles used to generate the file
       * - ``FLYING_UNIT_CODE``
         - :samp:`s1{{a|b}}`
       * - ``IMAGE_TYPE``
@@ -934,8 +963,12 @@ present in Sentinel-1 SAR input products.
 
       * - ``ACQUISITION_DATETIME``
         - time of the first S1 image (in UTC format since v1.1)
+      * - ``DEM_INFO``
+        - Key to identify which DEM has been used. |br|
+          Comes from :ref:`[Paths].dem_info <paths.dem_info>` or
+          :ref:`basename([Paths].dem_dir) <paths.dem_info>`.
       * - ``DEM_LIST``
-        - List of DEM (SRTM currently) tiles used to generate the file
+        - List of DEM tiles used to generate the file
       * - ``FLYING_UNIT_CODE``
         - :samp:`s1{{a|b}}`
       * - ``IMAGE_TYPE``
diff --git a/docs/release_notes.rst b/docs/release_notes.rst
index fe035259..eb36f643 100644
--- a/docs/release_notes.rst
+++ b/docs/release_notes.rst
@@ -33,10 +33,13 @@ v1.2.0 Improvements
   directory structure is still supported for backward compatibility reasons.
 - Generate :ref:`maps of incidence angles to the WGS84 ellipsoid <ia-files>`
   (`#161 <https://gitlab.orfeo-toolbox.org/s1-tiling/s1tiling/-/issues/161>`_).
-- Add :ref:`[Metadata] <metadata>` configuration section to specify extra
-  GeoTIFF metadata that will be set in the images produced by S1Tiling
+- New GeoTIFF metadata are written in the images produced by S1Tiling
   (`#171 <https://gitlab.orfeo-toolbox.org/s1-tiling/s1tiling/-/issues/171>`_).
 
+  - :ref:`DEM_INFO <paths.dem_info>` that will be set when relevant,
+  - and any pairs of ``key=value`` that are specified in the :ref:`[Metadata]
+    <metadata>` configuration section.
+
 
 Version 1.1.0
 -------------
diff --git a/s1tiling/libs/configuration.py b/s1tiling/libs/configuration.py
index 849a2c17..bfb2178f 100644
--- a/s1tiling/libs/configuration.py
+++ b/s1tiling/libs/configuration.py
@@ -319,7 +319,9 @@ class Configuration:  # pylint: disable=too-many-instance-attributes
 
         # "dem_dir" or Fallback to old deprecated key: "srtm"
         #: Where DEM files are expected to be found: See :ref:`[PATHS.dem_dir] <paths.dem_dir>`!
-        self.dem                 = accessor.get('Paths', 'dem_dir', fallback='') or accessor.get('Paths', 'srtm')
+        self.dem                 = accessor.get('Paths', 'dem_dir',  fallback='') or accessor.get('Paths', 'srtm')
+        #: DEM identifier to save in GeoTIFF metadata: See :ref:`[PATHS.dem_info] <paths.dem_info>`!
+        self.dem_info            = accessor.get('Paths', 'dem_info', fallback=os.path.basename(self.dem))
         dem_database             = accessor.get('Paths', 'dem_database', fallback='')
         # TODO: Inject resource_dir/'shapefile' if relative dir and not existing
         #: Path to the internal DEM tiles database: automatically set
diff --git a/s1tiling/libs/otbwrappers/lia.py b/s1tiling/libs/otbwrappers/lia.py
index e6893d2e..e5f8e618 100644
--- a/s1tiling/libs/otbwrappers/lia.py
+++ b/s1tiling/libs/otbwrappers/lia.py
@@ -201,6 +201,7 @@ class ProjectDEMToS2Tile(ExecutableStepFactory):
             gen_output_filename=TemplateOutputFilenameGenerator(fname_fmt),
             image_description="Warped DEM to S2 tile",
         )
+        self.__dem_info          = cfg.dem_info
         self.__out_spatial_res   = cfg.out_spatial_res
         self.__resampling_method = cfg.dem_warp_resampling_method
         self.__nb_threads        = cfg.nb_procs
@@ -226,6 +227,7 @@ class ProjectDEMToS2Tile(ExecutableStepFactory):
         imd = meta['image_metadata']
         imd['S2_TILE_CORRESPONDING_CODE'] = meta['tile_name']
         imd['SPATIAL_RESOLUTION']         = str(self.__out_spatial_res)
+        imd['DEM_INFO']                   = self.__dem_info
         imd['DEM_RESAMPLING_METHOD']      = self.__resampling_method
         imd['ORTHORECTIFIED']             = 'true'
         # TODO: Import DEM_LIST from input VRT image
@@ -486,6 +488,7 @@ class ComputeGroundAndSatPositionsOnDEMFromEOF(OTBStepFactory):
         )
         self.__cfg = cfg  # Will be used to access cached DEM intersecting S2 tile
         self.__nodata = nodata_XYZ(cfg)
+        self.__dem_info = cfg.dem_info
 
     def _update_filename_meta_post_hook(self, meta: Meta) -> None:
         """
@@ -557,6 +560,7 @@ class ComputeGroundAndSatPositionsOnDEMFromEOF(OTBStepFactory):
         assert 'image_metadata' in meta
         imd = meta['image_metadata']
         imd['POLARIZATION']             = ""  # Clear polarization information (makes no sense here)
+        imd['DEM_INFO']                 = self.__dem_info
         imd['DEM_LIST']                 = ', '.join(meta['dems'])
         imd['band.DirectionToScanDEM*'] = ''
         imd['band.Gain']                = ''
@@ -649,6 +653,7 @@ class ComputeGroundAndSatPositionsOnDEM(OTBStepFactory):
         )
         self.__cfg = cfg  # Will be used to access cached DEM intersecting S2 tile
         self.__nodata = nodata_XYZ(cfg)
+        self.__dem_info = cfg.dem_info
 
     @staticmethod
     def reduce_inputs(inputs: List[Meta]) -> List:
@@ -771,6 +776,7 @@ class ComputeGroundAndSatPositionsOnDEM(OTBStepFactory):
         assert 'image_metadata' in meta
         imd = meta['image_metadata']
         imd['POLARIZATION']             = ""  # Clear polarization information (makes no sense here)
+        imd['DEM_INFO']                 = self.__dem_info
         imd['DEM_LIST']                 = ', '.join(meta['dems'])
         imd['band.DirectionToScanDEM*'] = ''
         imd['band.Gain']                = ''
@@ -1445,6 +1451,7 @@ class SARDEMProjection(OTBStepFactory):
         self.__dem_db_filepath     = cfg.dem_db_filepath
         self.__dem_field_ids       = cfg.dem_field_ids
         self.__dem_main_field_id   = cfg.dem_main_field_id
+        self.__dem_info            = cfg.dem_info
 
     def _update_filename_meta_pre_hook(self, meta: Meta) -> Meta:
         """
@@ -1492,6 +1499,7 @@ class SARDEMProjection(OTBStepFactory):
         assert 'image_metadata' in meta
         imd = meta['image_metadata']
         imd['POLARIZATION'] = ""  # Clear polarization information (makes no sense here)
+        imd['DEM_INFO']     = self.__dem_info
         imd['DEM_LIST']     = ', '.join(meta['dems'])
 
     def add_image_metadata(self, meta: Meta, app) -> None:
@@ -1869,6 +1877,7 @@ class ConcatenateLIA(_ConcatenatorFactory):
             'LIA'     : extended_filename_lia_degree(cfg),
             'sin_LIA' : extended_filename_lia_sin(cfg),
         }
+        self.__dem_info = cfg.dem_info
 
     def _update_filename_meta_post_hook(self, meta: Meta) -> None:
         """
@@ -1885,6 +1894,7 @@ class ConcatenateLIA(_ConcatenatorFactory):
         """
         super().update_image_metadata(meta, all_inputs)
         imd = meta['image_metadata']
+        imd['DEM_INFO']  = self.__dem_info
         imd['DEM_LIST']  = ""  # Clear DEM_LIST information (a merge of 2 lists should be done actually)
 
     def complete_meta(self, meta: Meta, all_inputs: InputList) -> Meta:
diff --git a/s1tiling/libs/otbwrappers/s1_to_s2.py b/s1tiling/libs/otbwrappers/s1_to_s2.py
index 45b24cb3..6cabff3a 100644
--- a/s1tiling/libs/otbwrappers/s1_to_s2.py
+++ b/s1tiling/libs/otbwrappers/s1_to_s2.py
@@ -636,6 +636,7 @@ class _OrthoRectifierFactory(OTBStepFactory):
         self.__grid_spacing         = cfg.grid_spacing
         self.__interpolation_method = cfg.interpolation_method
         self.__tmp_dem_dir          = cfg.tmp_dem_dir
+        self.__dem_info             = cfg.dem_info
         # self.__tmpdir               = cfg.tmpdir
         # Some workaround when ortho is not sequenced along with calibration
         # (and locally override calibration type in case of normlim calibration)
@@ -660,6 +661,7 @@ class _OrthoRectifierFactory(OTBStepFactory):
         imd['ORTHORECTIFIED']                  = 'true'
         imd['S2_TILE_CORRESPONDING_CODE']      = meta['tile_name']
         imd['SPATIAL_RESOLUTION']              = str(self.__out_spatial_res)
+        imd['DEM_INFO']                        = self.__dem_info
         # S1 -> S2 => remove all SAR specific metadata inserted by OTB
         meta_to_remove_in_s2 = (
                 'SARCalib*', 'SAR', 'PRF', 'RadarFrequency', 'RedDisplayChannel',
diff --git a/s1tiling/resources/S1Processor.cfg b/s1tiling/resources/S1Processor.cfg
index 3659ffec..e28d66b1 100644
--- a/s1tiling/resources/S1Processor.cfg
+++ b/s1tiling/resources/S1Processor.cfg
@@ -20,6 +20,10 @@ s1_images : /datalocal2/share2/Asia/raw
 # Path where Precise Orbit EOF files are downloaded
 eof_dir : /datalocal2/share2/Asia/eof
 
+# Special information to write in GeoTIFF metadata
+# Unlike information in [Metadata], this will be written only when DEM are used
+dem_info : STRM 30m
+
 # Path to SRTM/DEM files
 dem_dir : /datalocal/share/SRTM
 
-- 
GitLab


From 174b2d65c6984b5586bb3b9acf605a0bde1b86da Mon Sep 17 00:00:00 2001
From: Luc Hermitte <luc.hermitte@cs-soprasteria.com>
Date: Mon, 3 Mar 2025 14:46:03 +0100
Subject: [PATCH 5/5] TST: Update tests for new metadata

---
 s1tiling/libs/otbwrappers/lia.py              |  15 +-
 tests/mock_helpers.py                         |   1 +
 .../test_build_dependencies_and_tasks.py      |   2 +
 tests/test_0200306-NR.py                      | 301 ++++++++++--------
 4 files changed, 177 insertions(+), 142 deletions(-)

diff --git a/s1tiling/libs/otbwrappers/lia.py b/s1tiling/libs/otbwrappers/lia.py
index e5f8e618..af980257 100644
--- a/s1tiling/libs/otbwrappers/lia.py
+++ b/s1tiling/libs/otbwrappers/lia.py
@@ -411,6 +411,17 @@ class SumAllHeights(OTBStepFactory):
         assert 'in_s2_geoid' in keys
         return [input['in_s2_geoid'] for input in inputs if 'in_s2_geoid' in input.keys()][0]
 
+    def fetch_upstream_dem_resampling_method(self, inputpath: str, meta: Meta):
+        logger.debug("Fetch DEM_RESAMPLING_METHOD from '%s'", inputpath)
+        if not is_running_dry(meta):  # FIXME: this info is no longer in meta!
+            dst = gdal.Open(inputpath, gdal.GA_ReadOnly)
+            if not dst:
+                raise RuntimeError(f"Cannot open DEM/S2 file '{inputpath}' to collect DEM_RESAMPLING_METHOD metadata.")
+            res = dst.GetMetadataItem('DEM_RESAMPLING_METHOD')
+            del dst
+            return res
+        return 'No idea in dry run mode'
+
     def update_image_metadata(self, meta: Meta, all_inputs: InputList) -> None:
         """
         Metadata coming from the DEM image are lost => we fetch them in the DEM file.
@@ -418,11 +429,9 @@ class SumAllHeights(OTBStepFactory):
         super().update_image_metadata(meta, all_inputs)
 
         in_s2_dem   = fetch_input_data('in_s2_dem',   all_inputs).out_filename
-        dst = gdal.Open(in_s2_dem, gdal.GA_ReadOnly)
         assert 'image_metadata' in meta
         imd = meta['image_metadata']
-        imd['DEM_RESAMPLING_METHOD'] = dst.GetMetadataItem('DEM_RESAMPLING_METHOD')
-        del dst
+        imd['DEM_RESAMPLING_METHOD'] = self.fetch_upstream_dem_resampling_method(in_s2_dem, meta)
 
     def parameters(self, meta: Meta) -> OTBParameters:
         """
diff --git a/tests/mock_helpers.py b/tests/mock_helpers.py
index 340bccdc..66fe2031 100644
--- a/tests/mock_helpers.py
+++ b/tests/mock_helpers.py
@@ -138,6 +138,7 @@ def declare_know_files(
         meta['gain']                = 42
         return meta
     mocker.patch('s1tiling.libs.otbwrappers.SARCartesianMeanEstimation.fetch_direction', lambda slf, ip, mt : mock_direction_to_scan(slf, mt))
+    mocker.patch('s1tiling.libs.otbwrappers.SumAllHeights.fetch_upstream_dem_resampling_method', lambda slf, ip, mt : 'cubic')
 
     def mock_fetch_nodata_value(inputpath, is_running_dry, default_value, band_nr:int = 1) -> float:
         return default_value
diff --git a/tests/step_defs/test_build_dependencies_and_tasks.py b/tests/step_defs/test_build_dependencies_and_tasks.py
index 9dfc7e85..f23c17e9 100644
--- a/tests/step_defs/test_build_dependencies_and_tasks.py
+++ b/tests/step_defs/test_build_dependencies_and_tasks.py
@@ -270,6 +270,8 @@ class Configuration():
         }
         self.dname_fmt                         = {}
         self.creation_options                  = {}
+        self.extra_metadata                    = {}
+        self.dem_info                          = ''
 
 
 def isfile(filename, existing_files) -> bool:
diff --git a/tests/test_0200306-NR.py b/tests/test_0200306-NR.py
index 025b35c7..a2b38d01 100644
--- a/tests/test_0200306-NR.py
+++ b/tests/test_0200306-NR.py
@@ -141,25 +141,27 @@ def test_33NWB_202001_NR_execute_OTB(baselinedir, outputdir, liadir, tmpdir, dem
                     ("Comparison of %s against %s failed" % (produced, expected))
             # expected_md = comparable_metadata(expected)
             expected_md = {
-                    'ACQUISITION_DATETIME'       : '2020:01:08T04:41:50Z',
-                    'ACQUISITION_DATETIME_1'     : '2020:01:08T04:41:50Z',
-                    'ACQUISITION_DATETIME_2'     : '2020:01:08T04:42:15Z',
-                    'AREA_OR_POINT'              : 'Area',
-                    'CALIBRATION'                : 'sigma',
-                    'FLYING_UNIT_CODE'           : 's1a',
-                    'IMAGE_TYPE'                 : image_type,
-                    'INPUT_S1_IMAGES'            : 'S1A_IW_GRDH_1SDV_20200108T044150_20200108T044215_030704_038506_C7F5, S1A_IW_GRDH_1SDV_20200108T044215_20200108T044240_030704_038506_D953',
-                    'NOISE_REMOVED'              : 'False',
-                    'ORBIT_DIRECTION'            : 'DES',
-                    'ORBIT_NUMBER'               : '030704',
-                    'ORTHORECTIFIED'             : 'true',
-                    'POLARIZATION'               : polar,
-                    'RELATIVE_ORBIT_NUMBER'      : '007',
-                    'S2_TILE_CORRESPONDING_CODE' : '33NWB',
-                    'SPATIAL_RESOLUTION'         : '10.0',
-                    'TIFFTAG_IMAGEDESCRIPTION'   : descr,
-                    'TIFFTAG_SOFTWARE'           : 'S1 Tiling',
-                    }
+                'ACQUISITION_DATETIME'           : '2020:01:08T04:41:50Z',
+                'ACQUISITION_DATETIME_1'         : '2020:01:08T04:41:50Z',
+                'ACQUISITION_DATETIME_2'         : '2020:01:08T04:42:15Z',
+                'AREA_OR_POINT'                  : 'Area',
+                'CALIBRATION'                    : 'sigma',
+                'DEM_INFO'                       : 'SRTM_30_hgt',
+                'FLYING_UNIT_CODE'               : 's1a',
+                'IMAGE_TYPE'                     : image_type,
+                'INPUT_S1_IMAGES'                : 'S1A_IW_GRDH_1SDV_20200108T044150_20200108T044215_030704_038506_C7F5, S1A_IW_GRDH_1SDV_20200108T044215_20200108T044240_030704_038506_D953',
+                'NOISE_REMOVED'                  : 'False',
+                'ORBIT_DIRECTION'                : 'DES',
+                'ORBIT_NUMBER'                   : '030704',
+                'ORTHORECTIFICATION_INTERPOLATOR': 'nn',
+                'ORTHORECTIFIED'                 : 'true',
+                'POLARIZATION'                   : polar,
+                'RELATIVE_ORBIT_NUMBER'          : '007',
+                'S2_TILE_CORRESPONDING_CODE'     : '33NWB',
+                'SPATIAL_RESOLUTION'             : '10.0',
+                'TIFFTAG_IMAGEDESCRIPTION'       : descr,
+                'TIFFTAG_SOFTWARE'               : 'S1 Tiling',
+            }
             assert expected_md == comparable_metadata(produced)
         # The following line permits to test otb_compare correctly detect differences when
         # called from pytest.
@@ -223,27 +225,29 @@ def test_33NWB_202001_NR_masks_only_execute_OTB(baselinedir, outputdir, liadir,
                 ("Comparison of %s against %s failed" % (produced, expected))
         # expected_md = comparable_metadata(expected)
         expected_md = {
-                'ACQUISITION_DATETIME'       : '2020:01:08T04:41:50Z',  # Start point has it
-                # For now, the start points don't have this...
-                'ACQUISITION_DATETIME_1'     : '2020:01:08T04:41:50Z',
-                'ACQUISITION_DATETIME_2'     : '2020:01:08T04:42:15Z',
-                'AREA_OR_POINT'              : 'Area',
-                'CALIBRATION'                : 'sigma',
-                'FLYING_UNIT_CODE'           : 's1a',
-                'IMAGE_TYPE'                 : 'MASK',
-                'INPUT_S1_IMAGES'            : 'S1A_IW_GRDH_1SDV_20200108T044150_20200108T044215_030704_038506_C7F5, S1A_IW_GRDH_1SDV_20200108T044215_20200108T044240_030704_038506_D953',
-                # For now, the start points don't have this...
-                'NOISE_REMOVED'              : 'False',
-                'ORBIT_DIRECTION'            : 'DES',
-                'ORBIT_NUMBER'               : '030704',
-                'ORTHORECTIFIED'             : 'true',
-                'POLARIZATION'               : polar,
-                'RELATIVE_ORBIT_NUMBER'      : '007',
-                'S2_TILE_CORRESPONDING_CODE' : '33NWB',
-                'SPATIAL_RESOLUTION'         : '10.0',
-                'TIFFTAG_IMAGEDESCRIPTION'   : 'Orthorectified Sentinel-1A IW GRD smoothed border mask S2 tile',
-                'TIFFTAG_SOFTWARE'           : 'S1 Tiling',
-                }
+            'ACQUISITION_DATETIME'           : '2020:01:08T04:41:50Z',  # Start point has it
+            # For now, the start points don't have this...
+            'ACQUISITION_DATETIME_1'         : '2020:01:08T04:41:50Z',
+            'ACQUISITION_DATETIME_2'         : '2020:01:08T04:42:15Z',
+            'AREA_OR_POINT'                  : 'Area',
+            'CALIBRATION'                    : 'sigma',
+            'DEM_INFO'                       : 'SRTM_30_hgt',
+            'FLYING_UNIT_CODE'               : 's1a',
+            'IMAGE_TYPE'                     : 'MASK',
+            'INPUT_S1_IMAGES'                : 'S1A_IW_GRDH_1SDV_20200108T044150_20200108T044215_030704_038506_C7F5, S1A_IW_GRDH_1SDV_20200108T044215_20200108T044240_030704_038506_D953',
+            # For now, the start points don't have this...
+            'NOISE_REMOVED'                  : 'False',
+            'ORBIT_DIRECTION'                : 'DES',
+            'ORBIT_NUMBER'                   : '030704',
+            'ORTHORECTIFICATION_INTERPOLATOR': 'nn',
+            'ORTHORECTIFIED'                 : 'true',
+            'POLARIZATION'                   : polar,
+            'RELATIVE_ORBIT_NUMBER'          : '007',
+            'S2_TILE_CORRESPONDING_CODE'     : '33NWB',
+            'SPATIAL_RESOLUTION'             : '10.0',
+            'TIFFTAG_IMAGEDESCRIPTION'       : 'Orthorectified Sentinel-1A IW GRD smoothed border mask S2 tile',
+            'TIFFTAG_SOFTWARE'               : 'S1 Tiling',
+        }
         assert expected_md == comparable_metadata(produced)
 
 
@@ -362,35 +366,37 @@ def mock_upto_concat_S2(
             'io.out'          : orthofile,
             }, None,
             {
-                'ORTHORECTIFIED'            : 'true',
-                'S2_TILE_CORRESPONDING_CODE': '33NWB',
-                'SPATIAL_RESOLUTION'        : '10.0',
-                'TIFFTAG_IMAGEDESCRIPTION'  : f'{raw_calibration} calibrated orthorectified Sentinel-1A IW GRD',
-                'AbsoluteCalibrationConstant' : '',
-                'AcquisitionDate'             : '',
-                'AcquisitionStartTime'        : '',
-                'AcquisitionStopTime'         : '',
-                'AverageSceneHeight'          : '',
-                'BeamMode'                    : '',
-                'BeamSwath'                   : '',
-                'BlueDisplayChannel'          : '',
-                'GreenDisplayChannel'         : '',
-                'Instrument'                  : '',
-                'LineSpacing'                 : '',
-                'Mission'                     : '',
-                'Mode'                        : '',
-                'NumberOfColumns'             : '',
-                'NumberOfLines'               : '',
-                'OrbitDirection'              : '',
-                'OrbitNumber'                 : '',
-                'PRF'                         : '',
-                'PixelSpacing'                : '',
-                'RadarFrequency'              : '',
-                'RedDisplayChannel'           : '',
-                'SAR'                         : '',
-                'SARCalib*'                   : '',
-                'SensorID'                    : '',
-                'Swath'                       : '',
+                'DEM_INFO'                       : 'SRTM_30_hgt',
+                'ORTHORECTIFICATION_INTERPOLATOR': 'nn',
+                'ORTHORECTIFIED'                 : 'true',
+                'S2_TILE_CORRESPONDING_CODE'     : '33NWB',
+                'SPATIAL_RESOLUTION'             : '10.0',
+                'TIFFTAG_IMAGEDESCRIPTION'       : f'{raw_calibration} calibrated orthorectified Sentinel-1A IW GRD',
+                'AbsoluteCalibrationConstant'    : '',
+                'AcquisitionDate'                : '',
+                'AcquisitionStartTime'           : '',
+                'AcquisitionStopTime'            : '',
+                'AverageSceneHeight'             : '',
+                'BeamMode'                       : '',
+                'BeamSwath'                      : '',
+                'BlueDisplayChannel'             : '',
+                'GreenDisplayChannel'            : '',
+                'Instrument'                     : '',
+                'LineSpacing'                    : '',
+                'Mission'                        : '',
+                'Mode'                           : '',
+                'NumberOfColumns'                : '',
+                'NumberOfLines'                  : '',
+                'OrbitDirection'                 : '',
+                'OrbitNumber'                    : '',
+                'PRF'                            : '',
+                'PixelSpacing'                   : '',
+                'RadarFrequency'                 : '',
+                'RedDisplayChannel'              : '',
+                'SAR'                            : '',
+                'SARCalib*'                      : '',
+                'SensorID'                       : '',
+                'Swath'                          : '',
                 })
 
     if N == 1:
@@ -490,6 +496,7 @@ def mock_LIA_v1_0(application_mocker: OTBApplicationsMockContext, file_db: FileD
             }, None,
             {
                 'ACQUISITION_DATETIME'     : file_db.start_time(idx),
+                'DEM_INFO'                 : 'SRTM_30_hgt',
                 'DEM_LIST'                 : ', '.join(exp_dem_names),
                 'FLYING_UNIT_CODE'         : 's1a',
                 'IMAGE_TYPE'               : 'GRD',
@@ -564,36 +571,38 @@ def mock_LIA_v1_0(application_mocker: OTBApplicationsMockContext, file_db: FileD
             'io.out'          : file_db.orthodegLIAfile(idx, True),
             }, {'io.out': otb.ImagePixelType_int16},
             {
-                'DATA_TYPE'                 : '100 * degrees(LIA)',
-                'ORTHORECTIFIED'            : 'true',
-                'S2_TILE_CORRESPONDING_CODE': '33NWB',
-                'SPATIAL_RESOLUTION'        : '10.0',
-                'TIFFTAG_IMAGEDESCRIPTION'  : 'Orthorectified LIA Sentinel-1A IW GRD',
-                'AbsoluteCalibrationConstant' : '',
-                'AcquisitionDate'             : '',
-                'AcquisitionStartTime'        : '',
-                'AcquisitionStopTime'         : '',
-                'AverageSceneHeight'          : '',
-                'BeamMode'                    : '',
-                'BeamSwath'                   : '',
-                'BlueDisplayChannel'          : '',
-                'GreenDisplayChannel'         : '',
-                'Instrument'                  : '',
-                'LineSpacing'                 : '',
-                'Mission'                     : '',
-                'Mode'                        : '',
-                'NumberOfColumns'             : '',
-                'NumberOfLines'               : '',
-                'OrbitDirection'              : '',
-                'OrbitNumber'                 : '',
-                'PRF'                         : '',
-                'PixelSpacing'                : '',
-                'RadarFrequency'              : '',
-                'RedDisplayChannel'           : '',
-                'SAR'                         : '',
-                'SARCalib*'                   : '',
-                'SensorID'                    : '',
-                'Swath'                       : '',
+                'DATA_TYPE'                      : '100 * degrees(LIA)',
+                'DEM_INFO'                       : 'SRTM_30_hgt',
+                'ORTHORECTIFICATION_INTERPOLATOR': 'nn',
+                'ORTHORECTIFIED'                 : 'true',
+                'S2_TILE_CORRESPONDING_CODE'     : '33NWB',
+                'SPATIAL_RESOLUTION'             : '10.0',
+                'TIFFTAG_IMAGEDESCRIPTION'       : 'Orthorectified LIA Sentinel-1A IW GRD',
+                'AbsoluteCalibrationConstant'    : '',
+                'AcquisitionDate'                : '',
+                'AcquisitionStartTime'           : '',
+                'AcquisitionStopTime'            : '',
+                'AverageSceneHeight'             : '',
+                'BeamMode'                       : '',
+                'BeamSwath'                      : '',
+                'BlueDisplayChannel'             : '',
+                'GreenDisplayChannel'            : '',
+                'Instrument'                     : '',
+                'LineSpacing'                    : '',
+                'Mission'                        : '',
+                'Mode'                           : '',
+                'NumberOfColumns'                : '',
+                'NumberOfLines'                  : '',
+                'OrbitDirection'                 : '',
+                'OrbitNumber'                    : '',
+                'PRF'                            : '',
+                'PixelSpacing'                   : '',
+                'RadarFrequency'                 : '',
+                'RedDisplayChannel'              : '',
+                'SAR'                            : '',
+                'SARCalib*'                      : '',
+                'SensorID'                       : '',
+                'Swath'                          : '',
             })
 
         application_mocker.set_expectations('OrthoRectification', {
@@ -615,36 +624,38 @@ def mock_LIA_v1_0(application_mocker: OTBApplicationsMockContext, file_db: FileD
             'io.out'          : file_db.orthosinLIAfile(idx, True),
             }, None,
             {
-                'DATA_TYPE'                 : 'sin(LIA)',
-                'ORTHORECTIFIED'            : 'true',
-                'S2_TILE_CORRESPONDING_CODE': '33NWB',
-                'SPATIAL_RESOLUTION'        : '10.0',
-                'TIFFTAG_IMAGEDESCRIPTION'  : 'Orthorectified sin_LIA Sentinel-1A IW GRD',
-                'AbsoluteCalibrationConstant' : '',
-                'AcquisitionDate'             : '',
-                'AcquisitionStartTime'        : '',
-                'AcquisitionStopTime'         : '',
-                'AverageSceneHeight'          : '',
-                'BeamMode'                    : '',
-                'BeamSwath'                   : '',
-                'BlueDisplayChannel'          : '',
-                'GreenDisplayChannel'         : '',
-                'Instrument'                  : '',
-                'LineSpacing'                 : '',
-                'Mission'                     : '',
-                'Mode'                        : '',
-                'NumberOfColumns'             : '',
-                'NumberOfLines'               : '',
-                'OrbitDirection'              : '',
-                'OrbitNumber'                 : '',
-                'PRF'                         : '',
-                'PixelSpacing'                : '',
-                'RadarFrequency'              : '',
-                'RedDisplayChannel'           : '',
-                'SAR'                         : '',
-                'SARCalib*'                   : '',
-                'SensorID'                    : '',
-                'Swath'                       : '',
+                'DATA_TYPE'                      : 'sin(LIA)',
+                'DEM_INFO'                       : 'SRTM_30_hgt',
+                'ORTHORECTIFICATION_INTERPOLATOR': 'nn',
+                'ORTHORECTIFIED'                 : 'true',
+                'S2_TILE_CORRESPONDING_CODE'     : '33NWB',
+                'SPATIAL_RESOLUTION'             : '10.0',
+                'TIFFTAG_IMAGEDESCRIPTION'       : 'Orthorectified sin_LIA Sentinel-1A IW GRD',
+                'AbsoluteCalibrationConstant'    : '',
+                'AcquisitionDate'                : '',
+                'AcquisitionStartTime'           : '',
+                'AcquisitionStopTime'            : '',
+                'AverageSceneHeight'             : '',
+                'BeamMode'                       : '',
+                'BeamSwath'                      : '',
+                'BlueDisplayChannel'             : '',
+                'GreenDisplayChannel'            : '',
+                'Instrument'                     : '',
+                'LineSpacing'                    : '',
+                'Mission'                        : '',
+                'Mode'                           : '',
+                'NumberOfColumns'                : '',
+                'NumberOfLines'                  : '',
+                'OrbitDirection'                 : '',
+                'OrbitNumber'                    : '',
+                'PRF'                            : '',
+                'PixelSpacing'                   : '',
+                'RadarFrequency'                 : '',
+                'RedDisplayChannel'              : '',
+                'SAR'                            : '',
+                'SARCalib*'                      : '',
+                'SensorID'                       : '',
+                'Swath'                          : '',
             })
 
     # endfor on 2 consecutive images
@@ -658,6 +669,7 @@ def mock_LIA_v1_0(application_mocker: OTBApplicationsMockContext, file_db: FileD
             'ACQUISITION_DATETIME'     : file_db.start_time_for_two(0),
             'ACQUISITION_DATETIME_1'   : file_db.start_time(0),
             'ACQUISITION_DATETIME_2'   : file_db.start_time(1),
+            'DEM_INFO'                 : 'SRTM_30_hgt',
             'DEM_LIST'                 : '',  # <=> Removing the key
             'INPUT_S1_IMAGES'          : '%s, %s' % (file_db.product_name(0), file_db.product_name(1)),
             'TIFFTAG_IMAGEDESCRIPTION' : 'Orthorectified LIA Sentinel-1A IW GRD',
@@ -672,6 +684,7 @@ def mock_LIA_v1_0(application_mocker: OTBApplicationsMockContext, file_db: FileD
             'ACQUISITION_DATETIME'     : file_db.start_time_for_two(0),
             'ACQUISITION_DATETIME_1'   : file_db.start_time(0),
             'ACQUISITION_DATETIME_2'   : file_db.start_time(1),
+            'DEM_INFO'                 : 'SRTM_30_hgt',
             'DEM_LIST'                 : '',  # <=> Removing the key
             'INPUT_S1_IMAGES'          : '%s, %s' % (file_db.product_name(0), file_db.product_name(1)),
             'TIFFTAG_IMAGEDESCRIPTION' : 'Orthorectified sin_LIA Sentinel-1A IW GRD',
@@ -713,6 +726,7 @@ def mock_LIA_v1_1(application_mocker: OTBApplicationsMockContext, file_db: FileD
             ], None, {
                 'S2_TILE_CORRESPONDING_CODE' : '33NWB',
                 'SPATIAL_RESOLUTION'         : f"{spacing}",
+                'DEM_INFO'                   : 'SRTM_30_hgt',
                 'DEM_RESAMPLING_METHOD'      : 'cubic',
                 'TIFFTAG_IMAGEDESCRIPTION'   : 'Warped DEM to S2 tile',
                 'ORTHORECTIFIED'             : 'true',
@@ -731,9 +745,11 @@ def mock_LIA_v1_1(application_mocker: OTBApplicationsMockContext, file_db: FileD
     }, None, {
         # 'ACQUISITION_DATETIME'       : file_db.start_time(0),
         # 'DEM_LIST'                   : ', '.join(exp_dem_names),
-        'S2_TILE_CORRESPONDING_CODE' : '33NWB',
-        'SPATIAL_RESOLUTION'         : f"{spacing}",
-        'TIFFTAG_IMAGEDESCRIPTION'   : 'Geoid superimposed on S2 tile',
+        'S2_TILE_CORRESPONDING_CODE'           : '33NWB',
+        'SPATIAL_RESOLUTION'                   : f"{spacing}",
+        'TIFFTAG_IMAGEDESCRIPTION'             : 'Geoid superimposed on S2 tile',
+        'GEOID_ORTHORECTIFICATION_INTERPOLATOR': 'nn',
+        'ORTHORECTIFIED'                       : 'true',
     })
 
     # Sum DEM + GEOID
@@ -748,8 +764,9 @@ def mock_LIA_v1_1(application_mocker: OTBApplicationsMockContext, file_db: FileD
         'exp'        : f'{is_nodata_DEM_bandmath} ? {nodata_DEM} : im1b1+im2b1',
         'out'        : file_db.height_on_s2(True),
     }, None, {
-        'TIFFTAG_IMAGEDESCRIPTION'   : 'DEM + GEOID height info projected on S2 tile',
-        'ORTHORECTIFIED'             : 'true',
+        'TIFFTAG_IMAGEDESCRIPTION' : 'DEM + GEOID height info projected on S2 tile',
+        'DEM_RESAMPLING_METHOD'    : 'cubic',
+        'ORTHORECTIFIED'           : 'true',
     })
     # ComputeGroundAndSatPositionsOnDEM
     application_mocker.set_expectations('SARDEMProjection2', {
@@ -764,6 +781,7 @@ def mock_LIA_v1_1(application_mocker: OTBApplicationsMockContext, file_db: FileD
         'out'        : file_db.xyz_on_s2(True),
     }, None, {
         # 'ACQUISITION_DATETIME'     : file_db.start_time(0),
+        'DEM_INFO'                 : 'SRTM_30_hgt',
         'DEM_LIST'                 : ', '.join(exp_dem_names),
         'IMAGE_TYPE'               : 'XYZ',
         'TIFFTAG_IMAGEDESCRIPTION' : 'XYZ ground and satellite positions on S2 tile',
@@ -833,6 +851,7 @@ def mock_LIA_v1_2(application_mocker: OTBApplicationsMockContext, file_db: FileD
             ], None, {
                 'S2_TILE_CORRESPONDING_CODE' : '33NWB',
                 'SPATIAL_RESOLUTION'         : f"{spacing}",
+                'DEM_INFO'                   : 'SRTM_30_hgt',
                 'DEM_RESAMPLING_METHOD'      : 'cubic',
                 'TIFFTAG_IMAGEDESCRIPTION'   : 'Warped DEM to S2 tile',
                 'ORTHORECTIFIED'             : 'true',
@@ -851,9 +870,11 @@ def mock_LIA_v1_2(application_mocker: OTBApplicationsMockContext, file_db: FileD
     }, None, {
         # 'ACQUISITION_DATETIME'       : file_db.start_time(0),
         # 'DEM_LIST'                   : ', '.join(exp_dem_names),
-        'S2_TILE_CORRESPONDING_CODE' : '33NWB',
-        'SPATIAL_RESOLUTION'         : f"{spacing}",
-        'TIFFTAG_IMAGEDESCRIPTION'   : 'Geoid superimposed on S2 tile',
+        'S2_TILE_CORRESPONDING_CODE'           : '33NWB',
+        'SPATIAL_RESOLUTION'                   : f"{spacing}",
+        'TIFFTAG_IMAGEDESCRIPTION'             : 'Geoid superimposed on S2 tile',
+        'GEOID_ORTHORECTIFICATION_INTERPOLATOR': 'nn',
+        'ORTHORECTIFIED'                       : 'true',
     })
 
     # Sum DEM + GEOID
@@ -868,8 +889,9 @@ def mock_LIA_v1_2(application_mocker: OTBApplicationsMockContext, file_db: FileD
         'exp'        : f'{is_nodata_DEM_bandmath} ? {nodata_DEM} : im1b1+im2b1',
         'out'        : file_db.height_on_s2(True),
     }, None, {
-        'TIFFTAG_IMAGEDESCRIPTION'   : 'DEM + GEOID height info projected on S2 tile',
-        'ORTHORECTIFIED'             : 'true',
+        'TIFFTAG_IMAGEDESCRIPTION' : 'DEM + GEOID height info projected on S2 tile',
+        'DEM_RESAMPLING_METHOD'    : 'cubic',
+        'ORTHORECTIFIED'           : 'true',
     })
     # ComputeGroundAndSatPositionsOnDEM
     application_mocker.set_expectations('SARComputeGroundAndSatPositionsOnDEM', {
@@ -884,6 +906,7 @@ def mock_LIA_v1_2(application_mocker: OTBApplicationsMockContext, file_db: FileD
         'out'        : file_db.xyz_on_s2(True),
     }, None, {
         # 'ACQUISITION_DATETIME'     : file_db.start_time(0),
+        'DEM_INFO'                 : 'SRTM_30_hgt',
         'DEM_LIST'                 : ', '.join(exp_dem_names),
         'EOF_FILE'                 : os.path.basename(file_db.eof_for_s2()),
         'FLYING_UNIT_CODE'         : 's1a',
-- 
GitLab