{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Tech Meeting 2024 Q1 - Run with(out) `ini` files" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The technical meeting that took place on 2024.04.03 related to the Q1 sprints covered the following topics:\n", "\n", "1. Running an analysis whilst modifying the `.ini` configuration files.\n", "2. Usage of enumerations within `ra2ce`.\n", "3. Discussion on long term views for `ra2ce` subprojects.\n", "4. Walk-through, on how to add new analyses to the current solution.\n", "\n", "This jupyter notebook will covers the first point." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 1. Running an analysis whilst modifying the `.ini` configuration files" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "It is entirely possible to generate a ra2ce analysis (or just a network) without having to generate `.ini` files. However, most of the times we will only want to modify a few properties of a given `network.ini` or `analysis.ini` file.\n", "At the current version `v0.8.1` we can solve both options as follows:\n", "\n", "1. Load the `.ini` files and then modify them at our own choice.\n", "2. Fully creating a `Ra2ceHandler` instance based on python objects ( `NetworkConfigData` and `AnalysisConfigData`)." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 1.1. Modify existing configurations from code" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Given our most common use case, we want to load a network and analysis and potentially modifying some of its properties. This was already accomplished in the \"ra2ce hackathon 2024 Q1\".\n", "\n", "To achieve it, simply use the regular `Ra2ceHandler` with your desired `ini` files and then access the corresponding `NetworkConfigData` and `AnalysisConfigData` properties. See the example below." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "1. Initialize the Ra2ce handler with valid `.ini` files." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "from pathlib import Path\n", "\n", "from ra2ce.ra2ce_handler import Ra2ceHandler\n", "\n", "# Define the location of our example test data.\n", "_root_dir = Path(\"...\", \"data\", \"damages_analysis\")\n", "assert _root_dir.exists()\n", "\n", "_network_file = _root_dir.joinpath(\"network.ini\")\n", "assert _network_file.exists()\n", "\n", "_analysis_file = _root_dir.joinpath(\"analysis.ini\")\n", "assert _analysis_file.exists()\n", "\n", "# Initialize handler\n", "_handler = Ra2ceHandler(_network_file, _analysis_file)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "2. In addition, we can verify if the analysis and network are correctly set." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "from ra2ce.network.network_config_data.network_config_data import NetworkConfigData\n", "from ra2ce.analysis.analysis_config_data.analysis_config_data import AnalysisConfigData\n", "\n", "assert isinstance(_handler.input_config.network_config.config_data, NetworkConfigData)\n", "assert isinstance(_handler.input_config.analysis_config.config_data, AnalysisConfigData)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "3. Configure the network and analyses" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "_handler.configure()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "4. Run the analysis." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "_handler.run_analysis()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 1.2. Create Ra2ce Handler without `ini` files" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "__DISCLAIMER!__\n", "This functionality will be streamlined as resolution of issue [#389](https://github.com/Deltares/ra2ce/issues/389)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "This step, however longer than required, will demonstrate how to emulate the usage of `ini` files. We relate the `.ini` files as:\n", "\n", "- `network.ini` to `NetworkConfigData`,\n", "- `analysis.ini` to `AnalysisConfigData`.\n", "\n", "Both `ConfigData` items are python objects (`dataclasses`) as such, it is entirely possible to manually manipulate them via code, therefore avoiding the need of definition and usage of their related `ini` files." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "1. Initialize the objects representing the `.ini` files." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "from ra2ce.network.network_config_data.network_config_data import NetworkConfigData\n", "from ra2ce.analysis.analysis_config_data.analysis_config_data import AnalysisConfigData\n", "\n", "_network_config_data = NetworkConfigData()\n", "_analysis_config_data = AnalysisConfigData()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "2. (Optional) Initialize logger." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "from ra2ce.ra2ce_logging import Ra2ceLogger\n", "\n", "# Initialize logger.\n", "_output_logger_path = Path(\"..\", \"data\", \"logging\")\n", "if _output_logger_path.exists():\n", " import shutil\n", " shutil.rmtree(_output_logger_path)\n", "_output_logger_path.mkdir(parents=True)\n", "\n", "Ra2ceLogger(logging_dir=_output_logger_path, logger_name=\"RA2CE\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "3. Put said objects together in the config wrapper." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# Define network config wrapper\n", "from ra2ce.network.network_config_wrapper import NetworkConfigWrapper\n", "\n", "_network_config_wrapper = NetworkConfigWrapper()\n", "_network_config_wrapper.config_data = _network_config_data\n", "_network_config_wrapper.configure()\n", "\n", "# Define analysis config wrapper\n", "from ra2ce.analysis.analysis_config_wrapper import AnalysisConfigWrapper\n", "\n", "_analysis_config_wrapper = AnalysisConfigWrapper()\n", "_analysis_config_wrapper.config_data = _analysis_config_data\n", "_analysis_config_wrapper.config_data.network = _network_config_wrapper.config_data.network\n", "_analysis_config_wrapper.config_data.origins_destinations = (\n", " _network_config_wrapper.config_data.origins_destinations\n", ")\n", "_analysis_config_wrapper.graph_files = _network_config_wrapper.graph_files\n", "_analysis_config_wrapper.configure()\n", "\n", "# Initialize wrapper\n", "from ra2ce.configuration.config_wrapper import ConfigWrapper\n", "\n", "_config_wrapper = ConfigWrapper()\n", "_config_wrapper.analysis_config = _analysis_config_wrapper\n", "_config_wrapper.network_config = _network_config_wrapper\n", "\n", "_config_wrapper.configure()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "4. Run analysis" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# Run analysis\n", "from ra2ce.runners import AnalysisRunnerFactory\n", "\n", "_runner = AnalysisRunnerFactory.get_runner(_config_wrapper)\n", "_runner.run(_config_wrapper.analysis_config)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 1.3. Create Ra2ce Handler without `ini` files - after #389\n", "\n", "In this example the network and analysis configuration are read from file before creation of the `Ra2ceHandler`.\n", "This can be replaced by any other way of creating your configuration, e.g. by creating it from scratch by `NetworkConfigWData()` and `AnalysisConfigData()`.\n", "The handler doesn't need file at creation time.\n", "The analysis should yield the same results as `example_damages.ipynb`.\n", "Note that the logfile isn't created." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "from pathlib import Path\n", "\n", "from ra2ce.analysis.analysis_config_data.analysis_config_data_reader import AnalysisConfigDataReader\n", "from ra2ce.network.network_config_data.network_config_data_reader import NetworkConfigDataReader\n", "from ra2ce.ra2ce_handler import Ra2ceHandler\n", "from ra2ce.runners import AnalysisRunnerFactory\n", "\n", "# Initialize configuration (replace this with your own configuration)\n", "_data_dir = Path(\"..\", \"data\", \"damages_analysis\")\n", "_network_ini = _data_dir.joinpath(\"network.ini\")\n", "_network = NetworkConfigDataReader().read(_network_ini)\n", "_network.root_path = _data_dir.parent\n", "_network.input_path = _data_dir.joinpath(\"input\")\n", "_network.static_path = _data_dir.joinpath(\"static\")\n", "_network.output_path = _data_dir.joinpath(\"output\")\n", "_analysis_ini = _data_dir.joinpath(\"analysis.ini\")\n", "_analysis = AnalysisConfigDataReader().read(_analysis_ini)\n", "\n", "# Initialize handler from configuration\n", "_handler = Ra2ceHandler.from_config(_network, _analysis)\n", "\n", "# Configure handler\n", "_handler.configure()\n", "\n", "# Run analysis\n", "_runner = AnalysisRunnerFactory.get_runner(_handler.input_config)\n", "_runner.run(_handler.input_config.analysis_config)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 1.4. Run an analysis with one line of code!\n", "\n", "From issue [#460](https://github.com/Deltares/ra2ce/issues/460) it is possible to simply run an anlysis without having to do the two extra steps `.configure()` and `.run_analysis()`.\n", "\n", "We can now chose to:\n", "- 1. Run directly an analysis providing two files with (`Ra2ceHandler.run_with_ini_files(Path, Path)`).\n", "- 2. Run an analysis by providing two configuration files (`Ra2ceHandler.run_with_config_data(NetworkConfigData, AnalysisConfigData)`)." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### 1.4.1. Run an analysis providing two files." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "from pathlib import Path\n", "\n", "from ra2ce.ra2ce_handler import Ra2ceHandler, AnalysisResultWrapper\n", "from ra2ce.analysis.analysis_config_data.analysis_config_data_reader import AnalysisConfigDataReader\n", "from ra2ce.network.network_config_data.network_config_data_reader import NetworkConfigDataReader\n", "\n", "# Initialize configuration (replace this with your own configuration)\n", "_data_dir = Path(\"..\", \"data\", \"single_link_redun\")\n", "\n", "# Network file\n", "_network_ini = _data_dir.joinpath(\"network.ini\")\n", "assert _network_ini.exists()\n", "\n", "# Analysis file\n", "_analysis_ini = _data_dir.joinpath(\"analyses.ini\")\n", "assert _analysis_ini.exists()\n", "\n", "# Get directly the results without extra steps.\n", "_results = Ra2ceHandler.run_with_ini_files(_network_ini, _analysis_ini)\n", "\n", "assert any(_results)\n", "assert all(isinstance(_result_wrapper, AnalysisResultWrapper) for _result_wrapper in _results)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### 1.4.2. Run an anlysis providing `NetworkConfigData` and `AnalysisConfigData`" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "from pathlib import Path\n", "\n", "from ra2ce.ra2ce_handler import Ra2ceHandler, AnalysisResultWrapper\n", "from ra2ce.analysis.analysis_config_data.analysis_config_data_reader import AnalysisConfigDataReader, AnalysisConfigData\n", "from ra2ce.network.network_config_data.network_config_data_reader import NetworkConfigDataReader, NetworkConfigData\n", "\n", "# Initialize configuration (replace this with your own configuration)\n", "_data_dir = Path(\"..\", \"data\", \"single_link_redun\")\n", "\n", "# NOTE! For simplicity we just load \"valid\" ini files instead of generating our own\n", "# config data.\n", "\n", "# Network file\n", "_network_config_data = NetworkConfigDataReader().read(_data_dir.joinpath(\"network.ini\"))\n", "assert isinstance(_network_config_data, NetworkConfigData)\n", "\n", "# Analysis file\n", "_analysis_config_data = AnalysisConfigDataReader().read(_data_dir.joinpath(\"analyses.ini\"))\n", "assert isinstance(_analysis_config_data, AnalysisConfigData)\n", "\n", "# Get directly the results without extra steps.\n", "_results = Ra2ceHandler.run_with_config_data(_network_config_data, _analysis_config_data)\n", "\n", "assert any(_results)\n", "assert all(isinstance(_result_wrapper, AnalysisResultWrapper) for _result_wrapper in _results)" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.10.13" } }, "nbformat": 4, "nbformat_minor": 2 }