Structure of NA64SW project =========================== ``na64sw`` API provides a number of various classes and functions. To maintain some sort of reasonable order, they are split onto few libraries with well-defined functionality. This is what we called a *core libraries*. Besides of core libraries a set of utility applications and scripts is provided by the distribution to utilize this core infrastructure for needs of NA64 experiment (yet, core libs are assumed to be experiment-agnostic). Libraries --------- The core set of libraries with their roles and dependency graph is summed up on the following diagram: .. figure:: ../images/core-libs-component-diagram.png :align: center Core libraries of NA64sw package. One component here normally corresponds to one static or dynamic library. Note, that part of the library set depends on the code synthesed based on ``.yaml`` files (``event-struct`` artifact). The project relies on static polymorphism regarding data being processed. Besides of significant performance benefit (compared to more traditional RTTI-based C++ polymorphism), this makes possible for most of the routines become generic to the particular event data types *before the compilation*. However, the *compiled* implementation becomes data-specific. Effectively, if one would like to adopt this framework to another experiment, with different event data topology one has to change what is described in ``event-struct`` manifests (``.yaml`` files) and re-compile the code. Core libraries and their roles: * ``na64util`` common purpose utility functions and classes shared across other specialized libraries. Provides various utilities used by other libraries: logging system (via third-party library), string interpolation, URI and path parsing and tokenization, files lookup, etc. * ``na64detID`` library implements detector identification functions: the ``DetID`` C++ type with to/from string conversion with ``DetectorNaming`` class responsible for such conversions. Details on detectors naming are documented in :ref:`detectors naming` section of this manual. * ``na64calib`` provides calibration data management classes implementing publisher/subscriber pattern, calibration data loader and dispatcher abstractions. * ``na64event`` provides physical event data representation with corresponding hits structures. Sources for this library are partially generated automatically. * ``na64dp`` contains a data pipeline API implementation * ``na64app`` is high-level API designed for applications. Defines common logic for gearing things up within executable or third-party codes (resolving environment variables, discovering calibration data and building its dependency graph, etc). Library settings get initialized at the runtime (typically, from within ``na64app``'s high-level calls) from few major configuration files. By default the logging sub-system gets configured from ``logging.yaml`` config file, the calibration settings are read from ``calibration.yaml`` where ``naming.yaml`` is referenced as a part of calibration info to be further used together with ``na64detID`` routines. .. figure:: ../images/core-libs-component-diagram-w-configs.png :align: center Core libraries of NA64sw package and default configuration sources. Note, that particular location of these files can be overloaded at the runtime. In the repository core libraries are implemented in the corresponding subdirectories of ``./include/`` and ``./src/`` first-level dirs, artifacts (config files) are located in ``presets/`` dir. Applications ------------ A (limited) set of applications utilizing core library interfaces is provided: * ``na64sw-pipe`` is the pipeline application (perhaps, most important one). * ``na64sw-tests`` (built optionally) performs unit-testing. Depends on Google's testing framework and won't be compiled if ``gtest`` is not found in the system. * ``na64-get-fts`` is the helper utility to retrieve various information from file produced by pipeline application (quantity distributions data, approximations, frequencies, etc). Applications source codes reside in the appropriate subdirectories of ``utils/`` first-level folder. Plug-ins and Extensions ----------------------- Plug-ins are meant to be loaded at the runtime. Each plugin brings extensions of certain types that meant to be added in the framework to extend the following software capabilities: * *handler* entity represents a single and usually extremely simple event processing procedure. Best way to think of it as of simple standalone program capable to access, add and modify any data within an event. Interface required by data processing component (``na64dp`` library). Interface provided by ``handlers`` and ``exp-handlers`` libraries. * *data source* entity produces events. It usually receives the subject (phys.event) data from external source -- a file, web socket or shared memory. *Data source* instance transcodes the event from external source into framework's representation to be processed by the handlers. Interface required by data processing component (``na64dp`` library), provided by extensions like ``ddd`` (``DaqDataDecoding`` library implementing NA64 raw data reading) or ``avro`` (implements data serialization based on Apache Avro) * *getter* is a (pure) function used to retrieve certain data from subject datum object (phys. event). Getters are even more simpler than handler, they are stateless and usually used by some *generalized* handlersevent. For instance, "calo\_edep" getter will provide generic plotting handler with the energy deposition in calorimeters. Interface is required by event component (``na64event`` library) and implemented statically, within the same library, based on event manifest specification. Consider reading :ref:`event structure` for details on event data topology. * so-called *runtime app. extension* is a special interface implementation designed to interoperate with main application logic. Various GUI event displays (like one based on GenFit), network recievers and dispatchers provide this type of interface to start/stop event processing based on external stimuli (e.g. user's actions at GUI). This interface is required by application component (partially implemented in ``na64app`` lib). .. figure:: ../images/core-libs-component-diagram-w-exts.png :align: center Core libraries of NA64sw package as components and some extensions provided in the default source code distro. The ``handlers`` and ``exp-handlers`` extensions are experiment-specific and tightly bound to data topology. Though advanced users are encouraged to develop their own plugins in local projects, a somewhat common set may be found in the ``extensions/`` directory: ``handlers``, ``avro``, currently reside there. Source code structure --------------------- The following structure must be respected: * ``doc/`` lists the documentation assets (guideline pages, examples, etc.) * ``extensions/`` a set of default runtime extensions -- plug-ins (handlers, data sources and so on) * ``include/`` is for C/C++ header files of the main libraries * ``presets/`` is for configuration files, common calibraion data, geometry sources, etc. * ``src/`` is for C/C++ inplementation files * ``utils/`` is for miscellaneous utils, tiny related subprojects, etc. * ``CMakeLists.txt`` file is main file that performs build procedure of the project (to be precise, instructs the CMake application how to generate a ``Makefile`` that is then used by ``make`` to build up everything). Automatically generated code ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Few parts of the framework are generated with automated tools (lake beforementioned event data topology implementation on C++). Although the source code is generated and thus depends on third-party utils and its input, we decided to not to include it as a standard build stage (for instance, detector selectors language or event structure generator) and keep generated output in the repo. This way one can build the project with fewer dependencies. If, however, one faced it, take note that following parts are generated automatically: - :ref:`DSuL parser ` - :ref:`Event structure ` Environment variables --------------------- Following environment variables affect evaluation of the ``na64sw`` routines: * ``NA64SW_PREFIX`` installation prefix for ``na64sw``. Used to define various assets' locations: source configs, calibration files, extension modules, run configuration files, etc. By default, the one configured by CMake is used. * ``NA64SW_RUN_CFG_PATH`` colon-separated list of the runtime configuration files. Assumed to ``.:$NA64SW_PREFIX/etc/na64sw/run`` by default. Used in ``include`` definitions of runtime configs. * ``NA64SW_MODULES_PATH`` colon-separated list of the directories for modules lookup. Assumed to ``.:$NA64SW_PREFIX/lib/na64sw/extensions`` by default. * ``P348_CONDDB_PATH`` -- path for calibration files lookup. Not used directly from C/C++ code but may be referred in calibration configuration files. * ``P348RECO_DIR`` -- some extensions (DDD data source and p348reco data source) may rely on this variable to locate DAQ mappings for raw data decoding. If it is not explicitly set, it will be assumed to whatever path was found for ``p348-daq`` repo during configuration stage. Installation Prefix (FHS) ------------------------- Standard UNIX prefix-based package installation structure `(FHS) implies`_ that package is deployed with respect of some path prefix in a following form: .. _(FHS) implies: https://en.wikipedia.org/wiki/Filesystem_Hierarchy_Standard * ``/prefix/lib`` or ``/prefix/usr/lib64`` is for libraries * ``/prefix/include`` is for header files * ``/prefix/bin`` is for utilities * ``/prefix/etc`` is for configuration files * ``/prefix/share`` is for various assets System packages (like ``binutils``) usually installed at ``/`` prefix, while user's system-wide packages (so called *secondary hierarchy*) are deployed under ``/usr`` prefix. You are doubtly interested in system-wide installation of ``na64sw`` but it is better to stick to this classic convention for compatibility reasons, so do we.