.. _raster.s104:

================================================================================
S104 -- S-104 Water Level Information for Surface Navigation Product
================================================================================

.. shortname:: S104

.. build_dependencies:: libhdf5

.. versionadded:: 3.9

This driver provides support for water level data in the S-104 format,
which is a specific product profile in an HDF5 file.

S-104 files have two image bands representing water level height (band 1)
and water level trend (band 2) values for each cell in a raster grid area.
An optional third band can contain the uncertainty in water level height.

When opening a S-104 file, no raster band is directly available. But a list of
subdatasets will be reported, one for each timestamp available in the file.

An actual dataset can be opened through such a subdataset, with a syntax like
``S104:"{filename.h5}":Group_001``.

Georeferencing is reported.

Note that the driver currently only supports regularly gridded S104 datasets.

Since GDAL 3.12, multiple feature instance groups per dataset (to encode grids
using different vertical datums) are supported. In that case, each feature
instance group and timestamp group is exposed as a GDAL subdataset, whose name
is of the form ``S104:"{filename.h5}":WaterLevel.{XX}:Group_{YYY}``.

Write support for S-104 v2.0 has been added in GDAL 3.13

Driver capabilities
-------------------

.. supports_createcopy::

.. supports_georeferencing::

.. supports_virtualio::

Open options
------------

|about-open-options|
The following open options are supported:

- .. oo:: NORTH_UP
     :choices: YES, NO
     :default: YES

     Whether the top line of the dataset should be the northern-most one.

     This is the default behavior of most GDAL formats, but the native
     organization of the data in S-104 products is to have the first line of
     the grid being the southern-most one. This native organization can be
     exposed by the driver by setting this option to NO (in which case the
     6th term of the geotransform matrix will be positive)

Write support
-------------

.. versionadded:: 3.13

Creation of a S-104 v2.0 dataset from another existing GDAL supported dataset is
possible using the :cpp:func:`GDALDriver::CreateCopy` function, or utilities
like :ref:`gdal_translate` or :ref:`gdal_raster_convert`. The input dataset
must have two or three bands. The first band must represent height in meters, and the second band
must contain the water level trend value with the following codes:

- 0 = nodata
- 1 = decreasing
- 2 = increasing
- 3 = steady

The third band when present must contain the uncertainty of water level heights
(in meters).

If several grids are available at different timestamps, they can be provided with
the :co:`DATASETS` creation option, possibly with the  :co:`DATASETS_TIME_POINT` creation option
if the datasets do not have a ``timePoint`` metadata item.

If several vertical datums are needed, the :co:`APPEND_SUBDATASET` creation option
can be set to ``YES`` to add an extra feature instance group ("WaterLevel.XX")
to an existing S-104 dataset.

The following creation options are available:

-  .. co:: TIME_POINT
      :choices: <string>

      Timestamp as YYYYMMDDTHHMMSSZ format (required).

-  .. co:: VERTICAL_DATUM
      :choices: <string>

      Vertical datum. This is a required creation option.

      Possible values are either:

      - a S100 vertical datum. Expressed as numeric code in the
        1 to 30 range, or value 44, 46, 47, 48, 49. Or their string meaning or
        abbreviation among
        the following list:

          * 1: ``meanLowWaterSprings`` / ``MLWS``
          * 2: ``meanLowerLowWaterSprings``
          * 3: ``meanSeaLevel`` / ``MSL``
          * 4: ``lowestLowWater``
          * 5: ``meanLowWater`` / ``MLW``
          * 6: ``lowestLowWaterSprings``
          * 7: ``approximateMeanLowWaterSprings``
          * 8: ``indianSpringLowWater``
          * 9: ``lowWaterSprings``
          * 10: ``approximateLowestAstronomicalTide``
          * 11: ``nearlyLowestLowWater``
          * 12: ``meanLowerLowWater`` / ``MLLW``
          * 13: ``lowWater`` / ``LW``
          * 14: ``approximateMeanLowWater``
          * 15: ``approximateMeanLowerLowWater``
          * 16: ``meanHighWater`` / ``MHW``
          * 17: ``meanHighWaterSprings`` / ``MHWS``
          * 18: ``highWater`` / ``HW``
          * 19: ``approximateMeanSeaLevel``
          * 20: ``highWaterSprings``
          * 21: ``meanHigherHighWater`` / ``MHHW``
          * 22: ``equinoctialSpringLowWater``
          * 23: ``lowestAstronomicalTide`` / ``LAT``
          * 24: ``localDatum``
          * 25: ``internationalGreatLakesDatum1985``
          * 26: ``meanWaterLevel``
          * 27: ``lowerLowWaterLargeTide``
          * 28: ``higherHighWaterLargeTide``
          * 29: ``nearlyHighestHighWater``
          * 30: ``highestAstronomicalTide`` / ``HAT``
          * 44: ``balticSeaChartDatum2000``
          * 46: ``internationalGreatLakesDatum2020``
          * 47: ``seaFloor``
          * 48: ``seaSurface``
          * 49: ``hydrographicZero``

      - an EPSG vertical datum code

-  .. co:: VERTICAL_CS
      :choices: DEPTH or HEIGHT

      Vertical coordinate system. This is a required creation option.

      Depth is the down direction relative to the vertical datum surface, with meter unit.
      Height is the up direction relative to the vertical datum surface, with meter unit.

-  .. co:: WATER_LEVEL_TREND_THRESHOLD
      :choices: <number>

      Critical value used to determine steady water level trend.
      Units are meters/hour (m/hr).
      This is a required creation option.

-  .. co:: DATA_DYNAMICITY
      :choices: observation, astronomicalPrediction, analysisOrHybrid or hydrodynamicForecast

      Classification of data according to the relationship between the time of
      its collection, generation, or calculation of generation parameters,
      in relation to the time of publication of the dataset.
      This is a required creation option.

-  .. co:: DATASETS
      :choices: <string>

      Comma-separated list of datasets at different timestamps. If each dataset
      does not have a ``timePoint`` metadata item, the :co:`DATASETS_TIME_POINT`
      creation option must be specified.

      The source dataset may or may not be put in the DATASETS creation option.

-  .. co:: DATASETS_TIME_POINT
      :choices: <string>

      Comma-separated list of different timestamps. If must have the same number
      of values as the :co:`DATASETS` creation option.
      Each time point value must be specified as a ``YYYYMMDDTHHMMSSZ`` timestamp.

-  .. co:: ISSUE_DATE
      :choices: <string> as <YYYYMMDD>

      If not specified, defaults to the current date.

-  .. co:: ISSUE_TIME
      :choices: <string>

      Issue time as <hhmmssZ> or <hhmmss[+-]HHMM>

      If not specified, defaults to the current time (in Z timezone).

-  .. co:: TREND_INTERVAL
      :choices: <number>

      Interval, in minutes, over which trend at a a particular time is calculated

-  .. co:: DATASET_DELIVERY_INTERVAL
      :choices: <string>

      Expected time interval between availability of successive datasets for
      time-varying data.
      Must be formatted as ``PnYnMnDTnHnMnS`` (ISO-8601 duration)

-  .. co:: TIME_RECORD_INTERVAL
      :choices: <number>

      Interval in seconds between time records.

-  .. co:: COMMON_POINT_RULE
      :choices: average, low, high, all
      :default: all

      Procedure used for evaluating the coverage at a position that falls on
      the boundary or in an area of overlap between geographic objects.

-  .. co:: UNCERTAINTY
      :choices: <number>

      Uncertainty of depth values in meter

-  .. co:: HORIZONTAL_POSITION_UNCERTAINTY
      :choices: <number>

      Horizontal position uncertainty in meter

-  .. co:: VERTICAL_UNCERTAINTY
      :choices: <number>

      Vertical uncertainty in meter

-  .. co:: TIME_UNCERTAINTY
      :choices: <number>

      Time uncertainty in second

-  .. co:: COMPRESS
      :choices: NONE, DEFLATE
      :default: DEFLATE

      Compression for elevation and uncertainty grids.

-  .. co:: ZLEVEL
      :choices: 1-9
      :default: 6

      Deflate compression level.

-  .. co:: BLOCK_SIZE
      :choices: <integer>

      Chunking size of the HDF5 arrays. Default
      to 100, or the maximum dimension of the raster if smaller than 100.

-  .. co:: APPEND_SUBDATASET
      :choices: YES, NO
      :default: NO

      Whether to append the new dataset to an existing S-104 dataset as
      an extra feature instance group ("WaterLevel.XX")


Validation script
-----------------

.. versionadded:: 3.13

The Python script :source_file:`swig/python/gdal-utils/osgeo_utils/samples/validate_s104.py`
can be used to validate the conformity of a S-104 v2.0 dataset against the specification.
It requires the `h5py <https://www.h5py.org/>`__ Python module to be installed
(typically through "pip install h5py")

Its usage is:

::

    $ python validate_s104.py 104TESTXXXX.h5


Note that the GDAL S-104 reader is more tolerant that the validation script and
can read files with slight non-conformities.


Examples
--------

-  Converting a GeoTIFF with water level height and trend, with the minimum required metadata items:

   ::

      $ gdal_translate water_level_height_and_trend.tif 104TESTXXXX.h5 -of S104 \
          -co TIME_POINT=20251105T012600Z \
          -co VERTICAL_DATUM=MMLW \
          -co VERTICAL_CS=HEIGHT \
          -co WATER_LEVEL_TREND_THRESHOLD=0.2 \
          -co DATA_DYNAMICITY=hydrodynamicForecast


See Also
--------

-  Implemented as :source_file:`frmts/hdf5/s104dataset.cpp`.
-  `S-104 Bathymetric Surface Product Specification <https://registry.iho.int/productspec/view.do?idx=198&product_ID=S-104&statusS=5&domainS=20&category=product_ID&searchValue=S-104>`__
-  :ref:`BAG driver <raster.bag>`
-  :ref:`S-102 driver <raster.s102>`
-  :ref:`S-111 driver <raster.s111>`


.. below is an allow-list for spelling checker.

.. spelling:word-list::
    hhmmssZ
    hhmmss
    HHMM
