.. _architecture: Architecture ============ HydroMT supports a large variety of models, which all require different types of data. It is therefore important that the API that HydroMT exposes is extendable. HydroMT is composed of a small set of key classes that support extension. In this section we walk through these classes and describe their main responsibilities and where they interact. .. currentmodule:: hydromt.model Model ----- The :Class:`Model` is the main representation of the model that is being built. A model is built step by step by adding :Class:`~components.base.ModelComponent` s to the Model. :ref:`Plugins` can define steps which act on these components to implement complex interactions between different components. The area of interest for the model can be defined by the :Class:`~components.spatial.SpatialModelComponent`. The complete model building workflow can be encoded in a :ref:`workflow file <model_workflow>` file. ModelComponent -------------- A :Class:`Model` can be populated with many different :Class:`~components.base.ModelComponent` s. A component can represent any type of data you have on your area of interest. This component can have many properties, but always has a :meth:`~components.base.ModelComponent.read` and :meth:`~components.base.ModelComponent.write` component to read in and write out data. A :Class:`Model` must have at least one :Class:`~components.base.ModelComponent`. .. currentmodule:: hydromt.data_catalog DataCatalog ----------- :Class:`Model` s need data. Where the data should be found and how it should be loaded is defined in the :Class:`~data_Catalog.DataCatalog`. Each item in the catalog is a :Class:`~sources.data_source.DataSource`. Users can create their own catalogs, using a `yaml` format, or they can share their :Class:`~predefined_catalog.PredefinedCatalog` using the :ref:`plugins` system. DataSource ---------- The :class:`~sources.data_source.DataSource` is the python representation of a parsed entry in the :class:`~DataCatalog`. The source is responsible for validating the catalog entry. It also carries the :class:`DataAdapter<adapters.data_adapter_base.DataAdapterBase>`, :class:`~uri_resolvers.URIResolver` and :class:`Driver<drivers.base_driver.BaseDriver>` and serves as an entrypoint to the data. Per HydroMT data type (e.g. ``RasterDataset``, ``GeoDataFrame``), HydroMT has one :Class:`~sources.data_source.DataSource`, e.g. :Class:`~source.rasterdataset.RasterDatasetSource`, :Class:`sources.geodataframe.GeoDataFrameSource`. The :meth:`~sources.datasource.DataSource.read` method governs the full process of discovery with the :Class:`~uri_resolvers.URIResolver`, reading data with the :Class:`Driver<drivers.base_driver.BaseDriver>`, and transforming the data to a HydroMT standard with a :class:`DataAdapter<adapters.data_adapter_base.DataAdapterBase>`. URIResolver ----------- .. currentmodule:: hydromt.data_catalog.uri_resolvers Finding the right address where the requested data is stored is not always straightforward. Searching for data differs between finding data in a web-service, database, a catalog or when dealing with a certain naming convention. Exploring where the right data can be found is implemented in the :Class:`URIResolver`. The :Class:`URIResolver` takes a single `uri` from the data catalog, and the query parameters from the model, such as the region, or the time range, and returns multiple absolute paths, or `uri` s, that can be read into a single python representation (e.g. `xarray.Dataset`). The :Class:`URIResolver` is extendable, so :ref:`Plugins` or other code can subclass the Abstract :Class:`URIResolver` class to implement their own conventions for data discovery. Driver ------ .. currentmodule:: hydromt.data_catalog The :Class:`Driver<drivers.base_driver.BaseDriver>` class is responsible for reading a set of geospatial data formats, like a ``geojson`` file or ``zarr`` archive, into their python in-memory representations: :Class:`geopandas.GeoDataFrame` or :Class:`xarray.Dataset` respectively. This class can also be extended using the :ref:`plugins`. Because the merging of different files from different :Class:`~sources.data_source.DataSource` s can be non-trivial, the driver is responsible to merge the different python objects coming from the driver to a single representation. This is then returned from the :meth:`read` method. The query parameters vary per HydroMT data type, so there is is a different driver interface per type, e.g. :Class:`~drivers.raster.raster_dataset_driver.RasterDatasetDriver`, :Class:`~drivers.geodataframe.geodataframe_driver.GeoDataFrameDriver`. To help with different filesystems, the driver class is handed a :class:`fsspec.Filesystem`. DataAdapter ----------- .. currentmodule:: hydromt.data_catalog The :Class:`DataAdapter<adapters.data_adapter_base.DataAdapterBase>` homogenizes the data coming from the :Class:`Driver<drivers.base_driver.BaseDriver>`. This means slicing the data to the right region, renaming variables, changing units, regridding and more. The adapter has a :meth:`transform` method that takes a python object and returns the same type, e.g. an `xr.Dataset`. This method also accepts query parameters based on the data type, so there is a single :Class:`DataAdapter<adapters.data_adapter_base.DataAdapterBase>` per HydroMT data type. Architecture Diagram ==================== The above is summarized in the following architecture diagram. Only the aforementioned methods and properties are used. .. image:: ../../drawio/exported/HydroMT-Architecture-OverArching.drawio.png :width: 800 :alt: HydroMT main classes