Basis architectuur Toolbox Continu Inzicht

De architectuur van de Toolbox Continu Inzicht is ontworpen om flexibel te zijn.

Configuratie

Per systeem kunnen de wensen van de gebruiker veranderen. Het systeem is dan ook te configureren voor verschillende databronnen. Door middel van een yaml configuratiebestand wordt de juist informatie meegegeven aan de modules en de data-adapter.

Het kopje GlobalVariables is verplicht met minimaal een rootdir: dit is een map waarin de data bestanden staan en weggeschreven worden. De DataAdapter is ook verplicht, met minimaal één data adapter. De naam van de data adapter is vrij te kiezen. Er kunnen zoveel data adapters aangemaakt worden als gewenst.

GlobalVariables:
    rootdir: "C:/data/toobox/"

DataAdapter:
    EenTypeDataAdapter:
        type: csv
        file: "eerste_voorbeeld.csv"

Onder GlobalVariables kan per datatype een variabele worden meegegeven die voor alle adapters van dit type gelden. Voor csv kan dit bijvoorbeeld het scheidingsteken zijn. Alle data adapters met het type csv krijgen nu de extra variabele mee.

GlobalVariables:
    rootdir: "C:/data/toobox/"

DataAdapter:
    default_options:
        csv:
            sep: ";"
    EenTypeDataAdapter:
        type: csv
        file: "eerste_voorbeeld.csv"
    CSV_output:
        type: csv
        file: "voorbeeld_output.csv"

Naast de data-adapters worden modules ook geconfigureerd in de GlobalVariables. Zo worden de opties voor de module LoadsMatroos ook mee gegeven in de GlobalVariables.

GlobalVariables:
    rootdir: "C:/data/toobox/"

    LoadsMatroos:
        website: "noos"
        source: "dcsm6_kf"
        parameters: ["waterlevel"]
        MISSING_VALUE: 999

DataAdapter:
    ...

De tijd waarop de berekening van de toolbox plaatsvindt is ook te configureren met calc_time. Deze tijd moet in het ISO 8601 format zijn en wordt uitgelezen met datetime.datetime.fromisoformat. Indien geen tijd wordt meegegeven, maakt de Config klasse deze zelf aan met het tijdstip van runnen.

GlobalVariables:
    rootdir: "C:/data/toobox/"
    calc_time: '2024-11-18 08:00:00'

    LoadsMatroos:
        website: "noos"
        source: "dcsm6_kf"
        parameters: ["waterlevel"]
        MISSING_VALUE: 999

DataAdapter:
    ...

Data-adapter

De data-adapter wordt gebruikt om verschillende datatypes in en uit te lezen. Op dit moment zijn dit de volgende dataformaten:

  1. CSV
  2. NetCDF
  3. PostgreSQL
  4. Excel
  5. Shape

Deze wordt geconfigureerd in de een .yaml configuratiebestand. Een voorbeeld van een csv-bestand wordt hieronder weergegeven. Hierbij zijn type en file of path verplicht. In het voorbeeld hieronder wordt een relatief pad meegegeven als rootdir, dit wordt ook ondersteund.

GlobalVariables:
    rootdir: "data_sets"

DataAdapter:
    my_csv_in:
        type: csv
        file: "test_csv_in.csv"
    my_csv_out:
        type: csv
        file: "test_csv_out.csv"
...

Indien een bestand buiten de root directory valt kan in plaats van file ook een absoluut path worden meegegeven.

DataAdapter:
    MyCSV_anders:
        type: csv
        path: "C:/data/Ander/pad_naar_csv.csv"
...

Naast de verplichte waardes van een data-adapter worden ook alle overige opties doorgegeven. Voor de generieke data-adapters is er een check of de extra opgegeven opties ondersteund worden. Zo maakt de csv data adapter gebruik van pandas.read_csv en de NetCDF data adapter xarray.open_dataset. Voor PostgreSQL zijn alleen drie standaardopties beschikbaar: database, schema en table.

Zelf adapter locaties doorgeven

In de python module worden alles bestanden vanuit de map base.adapters gebruikt, mits ze beginnen met input_ of output_ om de twee uit elkaar te houden. Naast de geleverde data adapters, kan je via de global_variables ook een input_plugin_path en output_plugin_path definiëren. Alle python bestanden (.py) in deze mappen worden ingelezen en functies met input_ of output_ worden toegevoegd aan de mogelijke opties.

def input_test_text(input_config: dict):
    """Function to read a text file given a path"""
    # input_config contains all the information from reading the config file
    path = input_config["abs_path"]
    # we check with `get_kwargs` which options are compatible
    kwargs = get_kwargs(open, input_config)
    kwargs.pop("file")  # use the abs path instead of file
    with open(path, **kwargs) as f:
        data = f.read()
    # return the data in a dataframe, this is just an example
    return pd.DataFrame([data], columns=["text"])
GlobalVariables:
    rootdir: 'data_sets'
    input_plugin_path: 'data_sets'

DataAdapter:
    example_test:
        type: test_text
        file: 'test.txt'
from toolbox_continu_inzicht import Config, DataAdapter
config = Config(config_path="config.yaml")
config.lees_config()
data_adapter = DataAdapter(config=config)
df_in = data_adapter.input("example_test")

Optie 2:

GlobalVariables:
    rootdir: "data_sets"

DataAdapter:
    my_csv_in:
        type: csv
        file: "test_csv_in.csv"
...
config = Config(config_path="config.yaml")
config.lees_config()
data_adapter = DataAdapter(config=config)
data_adapter.set_dataframe_adapter("my_new_data_adapter", input_df, if_not_exist="create")

Adapters aanmaken vanuit Python

Naast het definiëren van data adapters via het configuratiebestand, kan dit ook vanuit Python zelf gedaan worden met de functie set_dataframe_adapter.

Dit kan op twee manieren:

  1. De data adapter wordt vooraf in de configuratie opgegeven met het type Python. De functie geeft het desbetreffende dataframe door.
  2. Er is geen data-adapter gedefinieerd. Deze wordt aangemaakt bij het runnen van de code. Let op: het configuratiebestand verandert niet mee.

Optie 1:

GlobalVariables:
    rootdir: "data_sets"

DataAdapter:
    my_df_in:
        type: python
...
config = Config(config_path="config.yaml")
config.lees_config()
data_adapter = DataAdapter(config=config)
data_adapter.set_dataframe_adapter("my_df_in", input_df, if_not_exist="raise")
...

Optie 2:

GlobalVariables:
    rootdir: "data_sets"

DataAdapter:
    my_csv_in:
        type: csv
        file: "test_csv_in.csv"
...
config = Config(config_path="config.yaml")
config.lees_config()
data_adapter = DataAdapter(config=config)
data_adapter.set_dataframe_adapter("my_new_data_adapter", input_df, if_not_exist="create")

Wachtwoorden

Voor bepaalde diensten, zoals het toegang krijgen tot een database, is een wachtwoord vereist. Deze kunnen in de “environmental variables” worden meegegeven, in de vorm van een .env bestand.

postgresql_host="xxx.xx.xx.xx"
postgresql_database="xxxxxxx"
postgresql_port="xxxx"
postgresql_password="xxxx"
postgresql_user="xx"