diff --git a/apps/sa-ews1/CMakeLists.txt b/apps/sa-ews1/CMakeLists.txt new file mode 100644 index 0000000..35e02bc --- /dev/null +++ b/apps/sa-ews1/CMakeLists.txt @@ -0,0 +1,3 @@ +ROSA_add_app(sa-ews1 sa-ews1.cpp) +ROSA_add_library_dependencies(sa-ews1 ROSAConfig) +ROSA_add_library_dependencies(sa-ews1 ROSADeluxe) diff --git a/apps/sa-ews1/sa-ews1.cpp b/apps/sa-ews1/sa-ews1.cpp new file mode 100644 index 0000000..67a1ac6 --- /dev/null +++ b/apps/sa-ews1/sa-ews1.cpp @@ -0,0 +1,316 @@ +//===-- apps/sa-ews1/sa-ews1.cpp --------------------------------*- C++ -*-===// +// +// The RoSA Framework -- Application SA-EWS1 +// +//===----------------------------------------------------------------------===// +/// +/// \file apps/sa-ews1/sa-ews1.cpp +/// +/// \author David Juhasz (david.juhasz@tuwien.ac.at) +/// +/// \date 2017-2019 +/// +/// \brief The application SA-EWS1 implements the case study from the paper: +/// M. Götzinger, N. Taherinejad, A. M. Rahmani, P. Liljeberg, A. Jantsch, and +/// H. Tenhunen: Enhancing the Early Warning Score System Using Data Confidence +/// DOI: 10.1007/978-3-319-58877-3_12 +//===----------------------------------------------------------------------===// + +#include "rosa/agent/Abstraction.hpp" +#include "rosa/agent/Confidence.hpp" + +#include "rosa/config/version.h" + +#include "rosa/deluxe/DeluxeContext.hpp" + +#include "rosa/support/csv/CSVReader.hpp" +#include "rosa/support/csv/CSVWriter.hpp" + +#include + +using namespace rosa; +using namespace rosa::agent; +using namespace rosa::deluxe; +using namespace rosa::terminal; + +const std::string AppName = "SA-EWS1"; + +/// Paths for the CSV files for simulation. +/// +///@{ +const std::string HRCSVPath = "HR.csv"; +const std::string BRCSVPath = "BR.csv"; +const std::string SpO2CSVPath = "SpO2.csv"; +const std::string BPSysCSVPath = "BPSys.csv"; +const std::string BodyTempCSVPath = "BodyTemp.csv"; +const std::string ScoreCSVPath = "Score.csv"; +///@} + +/// How many cycles of simulation to perform. +const size_t NumberOfSimulationCycles = 16; + +/// Warning levels for abstraction. +enum WarningScore { No = 0, Low = 1, High = 2, Emergency = 3 }; + +/// Helper function creating a deluxe agent for pre-processing sensory values. +/// +/// Received values are first validated for confidence. Values which the +/// validator does not mark confident are ignored. Confident values are +/// abstracted into a \c WarningScore value, which is the result of the +/// processing function. +/// +/// \note The result, \c WarningScore, is returned as \c uint32_t because +/// enumeration types are not integrated into built-in types. Hence, a master +/// to these agents receives its input as \c uint32_t values, and may cast them +/// to \c WarningScore explicitly. +/// +/// \tparam T type of values to receive from the sensor +/// +/// \param C the deluxe context to create the agent in +/// \param Name name of the new agent +/// \param CC confidence validator to use +/// \param A abstraction to use +/// +/// \return handle for the new agent +template +AgentHandle createLowLevelAgent(std::unique_ptr &C, + const std::string &Name, + const Confidence &CC, + const Abstraction &A) { + using handler = DeluxeAgent::D; + using result = Optional; + return C->createAgent( + Name, handler([&, Name](std::pair I) -> result { + LOG_INFO_STREAM << "\n******\n" + << Name << " " << (I.second ? "" : "") + << " value: " << I.first << "\n******\n"; + return (I.second && CC(I.first)) ? result(A(I.first)) : result(); + })); +} + +int main(void) { + LOG_INFO_STREAM + << '\n' + << library_string() << " -- " << Color::Red << AppName << "app" + << Color::Default << '\n' + << Color::Yellow + << "CSV files are read from and written to the current working directory." + << Color::Default << '\n'; + + std::unique_ptr C = DeluxeContext::create(AppName); + + // + // Create deluxe sensors. + // + LOG_INFO("Creating sensors."); + + // All sensors are created without defining a normal generator function, but + // with the default value of the second argument. That, however, requires the + // data type to be explicitly defined. This is good for simulation only. + AgentHandle HRSensor = C->createSensor("HR Sensor"); + AgentHandle BRSensor = C->createSensor("BR Sensor"); + AgentHandle SpO2Sensor = C->createSensor("SpO2 Sensor"); + AgentHandle BPSysSensor = C->createSensor("BPSys Sensor"); + AgentHandle BodyTempSensor = C->createSensor("BodyTemp Sensor"); + + // + // Create functionalities. + // + LOG_INFO("Creating Functionalities for Agents."); + + // + // Define confidence validators. + // + // Lower bounds are inclusive and upper bounds are exclusive. + + Confidence HRConfidence(0, 501); + Confidence BRConfidence(0, 301); + Confidence SpO2Confidence(0, 101); + Confidence BPSysConfidence(0,501); + Confidence BodyTempConfidence(-60, + nextRepresentableFloatingPoint(50.0f)); + + // + // Define abstractions. + // + + RangeAbstraction HRAbstraction( + {{{0, 40}, Emergency}, + {{40, 51}, High}, + {{51, 60}, Low}, + {{60, 100}, No}, + {{100, 110}, Low}, + {{110, 129}, High}, + {{129, 200}, Emergency}}, + Emergency); + + RangeAbstraction BRAbstraction({{{0, 9}, High}, + {{9, 14}, No}, + {{14, 20}, Low}, + {{20, 29}, High}, + {{29, 50}, Emergency}}, + Emergency); + + RangeAbstraction SpO2Abstraction({{{1, 85}, Emergency}, + {{85, 90}, High}, + {{90, 95}, Low}, + {{95, 100}, No}}, + Emergency); + + RangeAbstraction BPSysAbstraction( + {{{0, 70}, Emergency}, + {{70, 81}, High}, + {{81, 101}, Low}, + {{101, 149}, No}, + {{149, 169}, Low}, + {{169, 179}, High}, + {{179, 200}, Emergency}}, + Emergency); + + RangeAbstraction BodyTempAbstraction( + {{{0.f, 28.f}, Emergency}, + {{28.f, 32.f}, High}, + {{32.f, 35.f}, Low}, + {{35.f, 38.f}, No}, + {{38.f, 39.5f}, High}, + {{39.5f, 100.f}, Emergency}}, + Emergency); + + // + // Create low-level deluxe agents with \c createLowLevelAgent. + // + LOG_INFO("Creating low-level agents."); + + AgentHandle HRAgent = + createLowLevelAgent(C, "HR Agent", HRConfidence, HRAbstraction); + AgentHandle BRAgent = + createLowLevelAgent(C, "BR Agent", BRConfidence, BRAbstraction); + AgentHandle SpO2Agent = + createLowLevelAgent(C, "SpO2 Agent", SpO2Confidence, SpO2Abstraction); + AgentHandle BPSysAgent = + createLowLevelAgent(C, "BPSys Agent", BPSysConfidence, BPSysAbstraction); + AgentHandle BodyTempAgent = createLowLevelAgent( + C, "BodyTemp Agent", BodyTempConfidence, BodyTempAbstraction); + + // + // Connect sensors to low-level agents. + // + LOG_INFO("Connect sensors to their corresponding low-level agents."); + + C->connectSensor(HRAgent, 0, HRSensor, "HR Sensor Channel"); + C->connectSensor(BRAgent, 0, BRSensor, "BR Sensor Channel"); + C->connectSensor(SpO2Agent, 0, SpO2Sensor, "SpO2 Sensor Channel"); + C->connectSensor(BPSysAgent, 0, BPSysSensor, "BPSys Sensor Channel"); + C->connectSensor(BodyTempAgent, 0, BodyTempSensor, "BodyTemp Sensor Channel"); + + // + // Create a high-level deluxe agent. + // + LOG_INFO("Create high-level agent."); + + // The new agent logs its input values and results in the the sum of them. + AgentHandle BodyAgent = C->createAgent( + "Body Agent", + DeluxeAgent::D( + [](std::pair HR, std::pair BR, + std::pair SpO2, std::pair BPSys, + std::pair BodyTemp) -> Optional { + LOG_INFO_STREAM << "\n*******\nBody Agent trigged with values:\n" + << (HR.second ? "" : "") + << " HR warning score: " << HR.first << "\n" + << (BR.second ? "" : "") + << " BR warning score: " << BR.first << "\n" + << (SpO2.second ? "" : "") + << " SpO2 warning score: " << SpO2.first << "\n" + << (BPSys.second ? "" : "") + << " BPSys warning score: " << BPSys.first << "\n" + << (BodyTemp.second ? "" : "") + << " BodyTemp warning score: " << BodyTemp.first + << "\n******\n"; + return {HR.first + BR.first + SpO2.first + BPSys.first + + BodyTemp.first}; + })); + + // + // Connect low-level agents to the high-level agent. + // + LOG_INFO("Connect low-level agents to the high-level agent."); + + C->connectAgents(BodyAgent, 0, HRAgent, "HR Agent Channel"); + C->connectAgents(BodyAgent, 1, BRAgent, "BR Agent Channel"); + C->connectAgents(BodyAgent, 2, SpO2Agent, "SpO2 Agent Channel"); + C->connectAgents(BodyAgent, 3, BPSysAgent, "BPSys Agent Channel"); + C->connectAgents(BodyAgent, 4, BodyTempAgent, "BodyTemp Agent Channel"); + + // + // For simulation output, create a logger agent writing the output of the + // high-level agent into a CSV file. + // + LOG_INFO("Create a logger agent."); + + // Create CSV writer. + std::ofstream ScoreCSV(ScoreCSVPath); + csv::CSVWriter ScoreWriter(ScoreCSV); + + // The agent writes each new input value into a CSV file and produces nothing. + AgentHandle LoggerAgent = C->createAgent( + "Logger Agent", + DeluxeAgent::D( + [&ScoreWriter](std::pair Score) -> Optional { + if (Score.second) { + // The state of \p ScoreWriter is not checked, expecting good. + ScoreWriter << Score.first; + } + return {}; + })); + + // + // Connect the high-level agent to the logger agent. + // + LOG_INFO("Connect the high-level agent to the logger agent."); + + C->connectAgents(LoggerAgent, 0, BodyAgent, "Body Agent Channel"); + + // + // Do simulation. + // + LOG_INFO("Setting up and performing simulation."); + + // + // Initialize deluxe context for simulation. + // + + C->initializeSimulation(); + + // + // Open CSV files and register them for their corresponding sensors. + // + + // Type aliases for iterators. + using CSVInt = csv::CSVFlatIterator; + using CSVFloat = csv::CSVFlatIterator; + + std::ifstream HRCSV(HRCSVPath); + C->registerSensorValues(HRSensor, CSVInt(HRCSV), CSVInt()); + + std::ifstream BRCSV(BRCSVPath); + C->registerSensorValues(BRSensor, CSVInt(BRCSV), CSVInt()); + + std::ifstream SpO2CSV(SpO2CSVPath); + C->registerSensorValues(SpO2Sensor, CSVInt(SpO2CSV), CSVInt()); + + std::ifstream BPSysCSV(BPSysCSVPath); + C->registerSensorValues(BPSysSensor, CSVInt(BPSysCSV), CSVInt()); + + std::ifstream BodyTempCSV(BodyTempCSVPath); + C->registerSensorValues(BodyTempSensor, CSVFloat(BodyTempCSV), CSVFloat()); + + // + // Simulate. + // + + C->simulate(NumberOfSimulationCycles); + + return 0; +} diff --git a/docs/Build.rst b/docs/Build.rst index 042b40d..c0e19f4 100755 --- a/docs/Build.rst +++ b/docs/Build.rst @@ -1,321 +1,322 @@ =========================== Building the RoSA Framework =========================== .. contents:: :local: .. _build_deps: Build Dependencies ================== In order to build RoSA, the following tools are required: * `CMake `_ (minimum version 3.6.0 if clang-tidy is used, 3.3.0 otherwise); * Build system of your choice that can be targeted by CMake -- including a compiler supporting *C++17*. * Clang/LLVM -- minimum version 5.0.0 * Visual Studio 2017 -- minimum version 15.7 The following additional tools are required to generate documentation: * `Doxygen `_ -- for generating API documentation; * `Graphviz `_ -- not necessary, but the API documentation has nicer graphics when `dot` is available; * `Sphinx `_ (with *Python 2*) -- for generating documentation. The following additional tools are required to check and possibly enforce coding standard: * `clang-tidy `_ * `clang-format `_ General notes ============= * The framework is delivered with a CMake project, which can be used to generate build projects to build the framework. * The provided CMake project supports out-of-tree builds only, i.e. one must use a separate build directory outside of the RoSA source directory. .. _doxygen-warnings: * Doxygen warnings -- typically indicating actual errors -- are printed to `stderr`, do check that when generating API documentation. .. _cmake-variables: CMake Variables =============== Beyond the usual CMake variables, the following project-related options are available: `ROSA_INCLUDE_APPS` Generate build targets for the defined RoSA applications. The option is a string that is a list of app names. All apps that are present in the option are built, others are ignored. All apps are built by default. `ROSA_INCLUDE_TOOLS` Generate build targets for RoSA tools. The tools are also built when the option is set to `ON`, which is the default setting. `ROSA_INCLUDE_EXAMPLES` Generate build targets for RoSA examples. The examples are also built when the option is set to `ON`, which is the default setting. `ROSA_ENABLE_PEDANTIC` Compile the framework with using `-pedantic` for GCC-compatible compilers, otherwise ignored. The option defaults to `ON`. `ROSA_ENABLE_ASSERTIONS` Enable assertions for non-Debug builds, which defaults to `OFF`. Note that assertions are always enabled for Debug builds and this option is ignored for such builds. .. _CMake_clang_tidy: `ROSA_ENABLE_CLANG_TIDY` Run *clang-tidy* checks when building RoSA, which defaults to `OFF`. When the variable is enabled, build targets created by *Makefile* and *Ninja* generators include calls for clang-tidy. Other generators ignore this option. Note that CMake variables `CMAKE__CLANG_TIDY` are set when enabled. Settings for clang-tidy are defined by the file `.clang-tidy` in the RoSA source directory. Consider the following options when the option is enabled: `ROSA_CLANG_TIDY_PATH` Custom path for `clang-tidy` executable. In order to use clang-tidy, CMake needs to find the `clang-tidy` executable. If `clang-tidy` to be used is available via `PATH`, just leave the option empty -- which is default. Set the absolute path of the directory containing the `clang-tidy` executable otherwise, in which case no default path is searched for `clang-tidy`. `ROSA_CLANG_TIDY_FIX` Apply suggested clang-tidy fixes to the sources, which defaults to `OFF`. Enable the option only if you know what you are doing. .. _CMake_clang_format: `ROSA_INCLUDE_CLANG_FORMAT` **[experimental]** Generate build target -- `format-rosa` -- for formatting RoSA sources with *clang-format*, which defatuls to `OFF`. When the variable is enabled and *CMake is not running on a Windows host*, a build target is generated which can be used to have all the RoSA sources formatted with clang-format. Settings for clang-format are defined by the file `.clang-format` in the RoSA source directory. Note that executing build target `format-rosa` will reformat all the source files *inplace*. Consider the following option when a build target for clang-format is to be generated: `ROSA_CLANG_FORMAT_PATH` Custom path for `clang-format` executable. In order to use clang-format, CMake needs to find the `clang-format` executable. If `clang-format` to be used is available via `PATH`, just leave the option empty -- which is default. Set the absolute path of the directory containing the `clang-format` executable otherwise, in which case no default path is search for `clang-format`. `ROSA_LOG_LEVEL` Level of logging to be used, use one of the following valid integer values. ======== ========= Variable Log Level ======== ========= `0` `ERROR` `1` `WARNING` `2` `INFO` `3` `DEBUG` `4` `TRACE` `5` *disabled* ======== ========= Level of logging defaults to *disabled*. `ROSA_INCLUDE_DOCS` Generate build targets for RoSA documentation, defaults to `ON`. Note that the automatic execution of the generated build targets is controlled by the option `ROSA_BUILD_DOCS`. The actual documentations to build are controlled by the options `ROSA_ENABLE_DOXYGEN` and `ROSA_ENABLE_SPHINX`. `ROSA_BUILD_DOCS` Build RoSA documentation automatically as part of the build process. The option defaults to `OFF` and takes effect only if the option `ROSA_INCLUDE_DOCS` is enabled. .. _CMake_doxygen: `ROSA_ENABLE_DOXYGEN` Use *doxygen* to generate RoSA API documentation. The option defaults to `OFF` and takes effect only if the option `ROSA_INCLUDE_DOCS` is enabled. Doxygen documentation may be generated by executing build target `doxygen-rosa`, which is done as part of the default build process if `ROSA_BUILD_DOCS` is enabled. Doxygen must be available via `PATH` if the option is enabled. The following options are also available to tune doxygen: `ROSA_DOXYGEN_SVG` Use *svg* instead of *png* files for doxygen graphs. The option defaults to `OFF` and takes effect if the tool *dot* is available via `PATH` to be used to generated graph images. `ROSA_DOXYGEN_EXTERNAL_SEARCH` Enable doxygen external search, which defatuls to `OFF`. The following options need to be set if the option is enabled: `ROSA_DOXYGEN_SEARCHENGINE_URL` URL to use for external search. `ROSA_DOXYGEN_SEARCH_MAPPINGS` Doxygen Search Mappings. .. _CMake_sphinx: `ROSA_ENABLE_SPHINX` Use *Sphinx* to generate RoSA documentation. The option defaults to `OFF` and takes effect only if the option `ROSA_INCLUDE_DOCS` is enabled. Sphinx must be available via `PATH` if the option is enabled. The following options are also available to tune Sphinx: `SPHINX_OUTPUT_HTML` Output standalone HTML files. The option defaults to `ON`. Documentation may be generated by executing build target `docs-rosa-html`, which is done as part of the default build process if `ROSA_BUILD_DOCS` is enabled. `SPHINX_OUTPUT_MAN` - Output man pages for RoSA tools. The option defaults to `ON`. + Output man pages for RoSA applications and tools. The option defaults to + `ON`. Man pages may be generated by executing build target `docs-rosa-man`, which is done as part of the default build process if `ROSA_BUILD_DOCS` is enabled. `SPHINX_WARNINGS_AS_ERRORS` When building documentation, treat Sphinx warnings as errors. The option defaults to `ON`. Building RoSA Step-by-Step ========================== Building on Linux with Make --------------------------- Configuring and building the framework on Linux using *Make* is a straightforward process which does not require performing any tricks. Set C and C++ compilers with the variables `CC` and `CXX`, respectively. Use the CMake variable `CMAKE_BUILD_TYPE` to set the type of build: `Debug`, `Release`. Follows an example on building the framework with all options turned on. CMake variables may be skipped as necessary. You need to have RoSA sources on your computer.:: rosa-src$ cd .. $ mkdir rosa-build $ cd rosa-build rosa-build$ CC= CXX= -G "Unix Makefiles" -DROSA_ENABLE_CLANG_TIDY=ON -DROSA_CLANG_TIDY_PATH= -DROSA_INCLUDE_CLANG_FORMAT=ON -DROSA_CLANG_FORMAT_PATH= -DROSA_LOG_LEVEL=4 -DROSA_ENABLE_DOXYGEN=ON -DROSA_DOXYGEN_SVG=ON -DROSA_ENABLE_SPHINX=ON -DCMAKE_BUILD_TYPE=Debug ../rosa-src [CMake configures and generates without errors] $ make [Make builds the project] You just need to re-run Make in order to re-build the project after changing the source code and the CMake project. In case the CMake project is changed, Make automatically calls CMake to update the build project. In order to build documentation and enforce coding standard, refer to corresponding :ref:`cmake-variables`. .. _Build_VS: Building on Windows with Visual Studio -------------------------------------- This is how to use the native MSVC compiler to build RoSA. Having your build system prepared (see `Build Dependencies`_) and RoSA sources fetched to your computer, configure and build the framework like this: #. Generate Visual Studio solution with CMake: #. Start CMake. #. Define *source directory* and a separate *build directory* in CMake. #. Click *Configure*. #. Select the proper *generator* for your version of Visual Studio. #. Click *Finish*. #. Tune CMake variables as you wish. * Note that Visual Studio Generators are multi-configuration generators, hence you cannot set `CMAKE_BUILD_TYPE`. You need to select a configuration to build in Visual Studio. #. Click *Generate*. #. Build the framework with Visual Studio: #. Open the generated `RoSA.sln` from the build directory with Visual Studio. #. Build the project `ALL_BUILD`. You just need to re-build the project in Visual Studio after changing the source code and the CMake project. In case the CMake project is changed, Visual Studio automatically calls CMake the update the build project. Build Result ============ The build process works in the build directory. After a successful build, one can find the following final outputs there -- besides some intermediate files. .. _Build_Result_Software: Software -------- In the build directory, `include` contains header files which are generated by CMake and provide configuration-specific information. The build process generates static libraries in `lib` and executables -- examples, apps, and tools -- in `bin`. Projects generated by a multi-configuration generator result in the actual libraries and executables being located in subdirectories corresponding to different build configurations. .. _Build_Result_Documentation: Documentation ------------- Documentation is generated in `docs`. The general documentation can be found in `docs/html`. Man pages for apps and tools can be found in `docs/man`. The API documentation can be found in `docs/doxygen/html`. .. rubric:: Footnotes diff --git a/docs/CommandGuide/dummy.rst b/docs/CommandGuide/dummy.rst deleted file mode 100755 index 31a92d8..0000000 --- a/docs/CommandGuide/dummy.rst +++ /dev/null @@ -1,6 +0,0 @@ -dummy - Just an empty file here -=============================== - -This is just a placeholder until a real man-page is defined. -That is for keeping the build system doing its work without complaining about -not having any documentation in the CommandGuide directory. diff --git a/docs/CommandGuide/index.rst b/docs/CommandGuide/index.rst index 939bff8..93990a8 100755 --- a/docs/CommandGuide/index.rst +++ b/docs/CommandGuide/index.rst @@ -1,13 +1,18 @@ -========== -RoSA Tools -========== +=========================== +RoSA Applications and Tools +=========================== Overview ======== -TODO CommandGuide, these are tool documentations... +Below is documentation for applications and tools .. toctree:: + :caption: Applications :maxdepth: 1 - dummy + sa-ews1 + +.. toctree:: + :caption: Tools + :maxdepth: 1 diff --git a/docs/CommandGuide/sa-ews1.rst b/docs/CommandGuide/sa-ews1.rst new file mode 100644 index 0000000..10b6e70 --- /dev/null +++ b/docs/CommandGuide/sa-ews1.rst @@ -0,0 +1,14 @@ +SA-EWS1 - Enhancing the Early Warning Score System Using Data Confidence +======================================================================== + +The application implements the case study from the paper: +M. Götzinger, N. Taherinejad, A. M. Rahmani, P. Liljeberg, A. Jantsch, and H. +Tenhunen: Enhancing the Early Warning Score System Using Data Confidence +`DOI: 10.1007/978-3-319-58877-3_12 `_. + +TODO: Describe how to execute the app, how input is read and output is +generated, command line arguments, etc. but no need to describe what it does +exactly because that is in the paper. + +TODO: Should provide some example data, perhaps that used for the paper in a +subdirectory next to the app? diff --git a/docs/index.rst b/docs/index.rst index cc82f79..6a9b649 100755 --- a/docs/index.rst +++ b/docs/index.rst @@ -1,72 +1,71 @@ ================== The RoSA Framework ================== .. contents:: :local: Overview ======== The RoSA (Research on Self-Awareness) Framework is intended to be used as a tool for experimenting and evaluating new ways of implementing self-aware applications. This documentation was generated for RoSA version |release| on |today|. Documentation ============= .. toctree:: :hidden: Changelog Use Build Dev Issues Release Plan CommandGuide/index :doc:`Use` Describes how to create your own software based on RoSA. :doc:`Build` Describes how to build RoSA. :doc:`Dev` Provides basic information for developers on how to contribute to RoSA. :doc:`Issues` Known issues and things to do with the current implementation of RoSA. :doc:`Release` Describes for maintainers how to make a new release of RoSA. :doc:`Plan` Discusses future work and possible ways to develop RoSA. -.. - :doc:`CommandGuide/index` - Documentation for RoSA tools. +:doc:`CommandGuide/index` + Documentation for RoSA applications and tools. Changes ======= Refer to :doc:`Changelog`. .. _API_Documentation: API Documentation ================= For details of the provided interface, refer to our `API documentation`_. .. _API documentation: ../doxygen/html/index.html Indices and Tables ================== * :ref:`genindex` * :ref:`search`