diff --git a/.gitignore b/.gitignore
index 350e856f..a75b1a50 100644
--- a/.gitignore
+++ b/.gitignore
@@ -19,7 +19,8 @@ chameleon-tree
*.png
# overrides
-!doc/logo.png
+!doc/gen/logo.png
+!doc/gen/logo_small.png
# misc. artifacts
.DS_Store
diff --git a/README.md b/README.md
index fa186450..7c287586 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,4 @@
-
+
## Iguana: Implementation Guardian of Analysis Algorithms
@@ -16,7 +16,6 @@ Iguana is not a framework for _reading_ data, rather it is a set of algorithms t
### For Users
1. [**Iguana User's Guide**](https://jeffersonlab.github.io/iguana/doxygen)
1. [Setup Guide - how to build and install Iguana](doc/setup.md)
-1. [Configuring the Algorithms](doc/configuration.md)
1. [Troubleshooting](doc/troubleshooting.md)
#### Language Bindings
@@ -24,7 +23,6 @@ Iguana is not a framework for _reading_ data, rather it is a set of algorithms t
1. [All others: see the Iguana User's guide](https://jeffersonlab.github.io/iguana/doxygen)
### For Developers
-1. [Design Notes](doc/design.md)
1. [Developing a new Algorithm](src/iguana/algorithms/example/ExampleAlgorithm/README.md)
1. [Algorithm Tests and Validators](doc/testing.md)
1. [Repository Maintenance](doc/maintenance.md)
diff --git a/bind/python/iguana_ex_python_00_run_functions.py b/bind/python/iguana_ex_python_00_run_functions.py
index f958303a..adab8591 100755
--- a/bind/python/iguana_ex_python_00_run_functions.py
+++ b/bind/python/iguana_ex_python_00_run_functions.py
@@ -27,6 +27,7 @@
"REC::Calorimeter",
"REC::Track",
"REC::Scintillator"])
+b_particle = hipo.getBanklistIndex(banks, "REC::Particle")
seq = iguana.AlgorithmSequence('pyiguana')
seq.Add('clas12::EventBuilderFilter')
@@ -47,9 +48,9 @@ def prettyPrint(message, bank):
seq.Start(banks)
while(reader.next(banks) and (numEvents==0 or iEvent < numEvents)):
iEvent += 1
- prettyPrint("BEFORE", banks[1])
+ prettyPrint("BEFORE", banks[b_particle])
seq.Run(banks)
- prettyPrint("AFTER", banks[1])
+ prettyPrint("AFTER", banks[b_particle])
seq.Stop()
diff --git a/bind/python/iguana_ex_python_01_action_functions.py b/bind/python/iguana_ex_python_01_action_functions.py
index 34eebcda..25a816ef 100755
--- a/bind/python/iguana_ex_python_01_action_functions.py
+++ b/bind/python/iguana_ex_python_01_action_functions.py
@@ -27,6 +27,9 @@
reader = hipo.reader(inFile)
banks = reader.getBanks(["REC::Particle", "RUN::config"]);
+b_particle = hipo.getBanklistIndex(banks, "REC::Particle")
+b_config = hipo.getBanklistIndex(banks, "RUN::config")
+
algo_eventbuilder_filter = iguana.clas12.EventBuilderFilter()
algo_momentum_correction = iguana.clas12.MomentumCorrection()
@@ -41,8 +44,8 @@
while(reader.next(banks) and (numEvents==0 or iEvent < numEvents)):
iEvent += 1
- particleBank = banks[0]
- configBank = banks[1]
+ particleBank = banks[b_particle]
+ configBank = banks[b_config]
particleBank.show()
for row in particleBank.getRowList():
diff --git a/doc/configuration.md b/doc/configuration.md
deleted file mode 100644
index 9592ff69..00000000
--- a/doc/configuration.md
+++ /dev/null
@@ -1,58 +0,0 @@
-# Configuring the Algorithms
-
-Most of the algorithms are configurable using a YAML configuration file. If you are using Iguana for your analysis, you likely want to customize the algorithm configurations.
-
-The default configuration is installed in the `etc/` subdirectory of the Iguana installation. If you have set the Iguana environment variables using, _e.g._ `source this_iguana.sh`, or if you are using the version of Iguana installed on `ifarm`, you will have the environment variable `$IGUANA_CONFIG_PATH` set to include this `etc/` directory.
-
-There are a few ways to configure the algorithms; see the sections below for the options
-
-> [!IMPORTANT]
-> While algorithm developers are encouraged _not_ to make breaking changes to their algorithms or configuration, in some cases certain changes cannot be prevented. Thus if you have your own algorithm configurations, you may want to keep up-to-date on any changes of the algorithm. We will try to announce all breaking changes in the Iguana release notes.
-
-> [!NOTE]
-> If the Iguana installation is relocated, the environment variable `$IGUANA_CONFIG_PATH` _must_ be used at runtime.
-
-## Option 1: Copy the default directory, and modify
-
-First, copy the default configuration directory to your work area, or to your analysis code source tree; we'll call the copied directory `my_iguana_config`, as an example. If `$IGUANA_CONFIG_PATH` is the default configuration directory (_i.e._ you have not set or modified this variable yourself), you may run:
-```bash
-cp -r $IGUANA_CONFIG_PATH my_iguana_config
-```
-
-You may then freely modify any configuration file within `my_iguana_config/`. To use this directory in your algorithms, you may do any one of the following:
-
-1. Since `$IGUANA_CONFIG_PATH` allows multiple paths, delimited by colons (`:`), prepend `my_iguana_config/` to `$IGUANA_CONFIG_PATH`; the safest way is to use an absolute path:
-```bash
-export IGUANA_CONFIG_PATH=`pwd`/my_iguana_config:$IGUANA_CONFIG_PATH # bash or zsh
-setenv IGUANA_CONFIG_PATH `pwd`/my_iguana_config:$IGUANA_CONFIG_PATH # tcsh or csh
-```
-The algorithms will then search `my_iguana_config` for the configuration before searching the default paths. You may add multiple paths, if needed.
-Paths which appear first in `$IGUANA_CONFIG_PATH` will be prioritized when the algorithm searches for configuration parameters; this behavior is similar to that of `$PATH` or `$LD_LIBRARY_PATH`.
-
-2. Use `Algorithm::SetConfigDirectory` instead of prepending `$IGUANA_CONFIG_PATH`.
-
-## Option 2: Write your own YAML file
-
-Make a new YAML file, containing just the options you want to override; use `Algorithm::SetConfigFile` to use this file for each algorithm.
-See existing algorithms' configuration, and just copy what you need into your own YAML file; be mindful of the indentation, and that the top-level set of YAML nodes are the algorithm names. For example:
-
-Algorithm default configuration files:
-```yaml
-### default configuration file 1
-physics::AlgorithmA
- cuts: [-1, 1]
-```
-```yaml
-### default configuration file 2
-physics::AlgorithmB
- value: 3
-```
-Custom YAML file, widening `AlgorithmA`'s `cuts` and increasing `AlgorithmB`'s `value`:
-```yaml
-### custom YAML file
-physics::AlgorithmA
- cuts: [-2, 2]
-
-physics::AlgorithmB
- value: 5
-```
diff --git a/doc/design.md b/doc/design.md
deleted file mode 100644
index 478feb62..00000000
--- a/doc/design.md
+++ /dev/null
@@ -1,142 +0,0 @@
-# Design
-
-## Graphs
-
-### Class Diagram
-
-```mermaid
-flowchart LR
- classDef cls fill:#88ff88,color:black
- classDef algo fill:#ff8888,color:black
- classDef other fill:#ff88ff,color:black
-
- subgraph services
- Logger:::cls
- Object:::cls
- end
-
- subgraph algorithms
- Algorithm:::cls
- FiducialCuts:::algo
- MomentumCorrection:::algo
- AlgorithmSequence:::algo
- bindings(language
bindings):::other
- end
-
- FiducialCuts -.-> Algorithm
- MomentumCorrection -.-> Algorithm
- AlgorithmSequence -.-> Algorithm
- Algorithm -.-> Object
-
- Object ---> Logger
- AlgorithmSequence ---> MomentumCorrection
- AlgorithmSequence ---> FiducialCuts
-
- AlgorithmSequence -.- bindings
-
-```
-
-#### Legend
-
-```mermaid
-flowchart TB
- classDef cls fill:#88ff88,color:black
-
- subgraph Inheritance
- b[Base Class]:::cls
- d[Derived Class]:::cls
- end
- d -.-> b
-
- subgraph Ownership
- c[Class]:::cls
- o[Object owned by Class]:::cls
- end
- c ---> o
-```
-
-### Dependency Graph
-
-```mermaid
-flowchart TB
- classDef lib fill:#ffff88,color:black
- classDef ext fill:#88ffff,color:black
-
- algorithms{{libIguanaAlgorithms}}:::lib
- services{{libIguanaServices}}:::lib
-
- hipo{{libhipo4}}:::ext
- fmt{{libfmt}}:::ext
-
- hipo ---> services
- fmt ---> services
- services ---> algorithms
-```
-
-## Algorithm Design
-
-### Common Methods
-
-Base class `Algorithm` has virtual methods:
-
-#### `Start`
-- runs before any event processing
-- configuration
-- set up data structures
-
-#### `Run`
-- runs on every event
-- input and output are a set of banks
-- runs the algorithm for a given event's bank(s)
-- should be thread-safe, _e.g._, no modification of instance members
-- usage:
- - called on every event in an event loop
- - part of a lambda for a data frame transformation
-- analyses that operate on bank rows rather than full banks require exposure
- of some function that does the _primary_ action of the algorithm
- - useful to have
- - wide variety of function signatures, so not easy to generalize and therefore not required
-
-#### `Stop`
-- runs after event processing
-- cleanup, if needed
-
-
-### Usage Options for Users
-
-- Instantiate and run algorithms as they are
- - No need for `AlgorithmSequence` instance
- - Algorithms do not depend on `AlgorithmSequence`, just on services
- - All algorithms are available in a separate shared library
- - Drawback: language bindings are not planned at the algorithm level
-- Use `AlgorithmSequence`
- - `AlgorithmSequence` will only instantiate the algorithms the user intends to use, owning
- an instance of each
- - User runs the algorithms using `AlgorithmSequence` "sugar"
- - Language bindings can be made available at this level
-
-
-### Algorithm Types
-
-#### Filter
-- return an input bank with some rows masked (or removed)
- - masking preferred to preserve bank linking
- - options for masking a row:
- - zero all elements
- - add a boolean item to the _end_ of the schema to store whether a row is masked
-- public `bool Cut(float...)` function
- - expose the _primary_ action of the algorithm for users that operate on bank rows
- - not required, since difficult to generalize at the `Algorithm` (or `AlgorithmSequence`) level
- - similar to `chanser`'s RG-A criteria implementations
-
-#### Transformer
-- return an input bank with some elements modified
-- public `Transorm(...)` function that exposes the _primary_ algorithm action would be useful,
- but not required
-
-#### Creator
-- return a new bank with a new schema
-- many reconstruction algorithms are creators
-
-#### Hybrid
-- any combination of the above
diff --git a/doc/gen/Doxyfile.in b/doc/gen/Doxyfile.in
index c923bc87..0a58a8fc 100644
--- a/doc/gen/Doxyfile.in
+++ b/doc/gen/Doxyfile.in
@@ -61,7 +61,7 @@ PROJECT_BRIEF = "Implementation Guardian of Analysis Algorithms"
# pixels and the maximum width should not exceed 200 pixels. Doxygen will copy
# the logo to the output directory.
-PROJECT_LOGO =
+PROJECT_LOGO = @top_srcdir@/doc/gen/logo_small.png
# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path
# into which the generated documentation will be written. If a relative path is
@@ -291,7 +291,7 @@ ALIASES += input_banks{1}="
**Input Banks** | `\1` |
"
ALIASES += output_banks{1}="**Output Banks** | `\1` |
"
ALIASES += end_doc=""
# configuration options
-ALIASES += begin_doc_config="\par Configuration Options:^^Name | Type | Description |
"
+ALIASES += begin_doc_config{1}="\par Configuration Options:^^YAML configuration, which includes the default option values:^^@include \1/Config.yaml ^^Table of options and descriptions:^^Name | Type | Description |
"
ALIASES += config_param{3|}="`\1` | `\2` | \3 |
"
# action functions
ALIASES += action_function{1}="\xrefitem action \"Function Type\" \"List of all Action Functions\" \1 \brief **Action Function:** "
@@ -304,6 +304,8 @@ ALIASES += doxygen_off="@cond NO_DOC"
ALIASES += doxygen_on="@endcond"
# latex
ALIASES += latex{1}="@f$\1@f$"
+# misc
+ALIASES += spacer=" "
# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources
# only. Doxygen will then generate output that is more tailored for C. For
@@ -1010,6 +1012,7 @@ INPUT_FILE_ENCODING =
FILE_PATTERNS = *.dox \
*.h \
+ Config.yaml \
chameleon_*_bind.cc \
iguana_ex_*.cc \
iguana_ex_*.py \
@@ -1059,7 +1062,7 @@ EXCLUDE_SYMBOLS =
# that contain example code fragments that are included (see the \include
# command).
-EXAMPLE_PATH =
+EXAMPLE_PATH = @top_srcdir@/src/iguana/algorithms
# If the value of the EXAMPLE_PATH tag contains directories, you can use the
# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and
@@ -1079,7 +1082,7 @@ EXAMPLE_RECURSIVE = NO
# that contain images that are to be included in the documentation (see the
# \image command).
-IMAGE_PATH =
+IMAGE_PATH = @top_srcdir@/doc/gen/logo.png
# The INPUT_FILTER tag can be used to specify a program that doxygen should
# invoke to filter for each input file. Doxygen will invoke the filter program
@@ -1362,7 +1365,7 @@ HTML_EXTRA_FILES =
# The default value is: AUTO_LIGHT.
# This tag requires that the tag GENERATE_HTML is set to YES.
-HTML_COLORSTYLE = AUTO_LIGHT
+HTML_COLORSTYLE = TOGGLE
# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen
# will adjust the colors in the style sheet and background images according to
@@ -1373,7 +1376,7 @@ HTML_COLORSTYLE = AUTO_LIGHT
# Minimum value: 0, maximum value: 359, default value: 220.
# This tag requires that the tag GENERATE_HTML is set to YES.
-HTML_COLORSTYLE_HUE = 220
+HTML_COLORSTYLE_HUE = 120
# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of the colors
# in the HTML output. For a value of 0 the output will use gray-scales only. A
@@ -1392,7 +1395,7 @@ HTML_COLORSTYLE_SAT = 100
# Minimum value: 40, maximum value: 240, default value: 80.
# This tag requires that the tag GENERATE_HTML is set to YES.
-HTML_COLORSTYLE_GAMMA = 80
+HTML_COLORSTYLE_GAMMA = 100
# If the HTML_DYNAMIC_MENUS tag is set to YES then the generated HTML
# documentation will contain a main index with vertical navigation menus that
@@ -1670,7 +1673,7 @@ DISABLE_INDEX = NO
# The default value is: NO.
# This tag requires that the tag GENERATE_HTML is set to YES.
-GENERATE_TREEVIEW = NO
+GENERATE_TREEVIEW = YES
# When both GENERATE_TREEVIEW and DISABLE_INDEX are set to YES, then the
# FULL_SIDEBAR option determines if the side bar is limited to only the treeview
diff --git a/doc/gen/examples.dox b/doc/gen/examples.dox
index 70c7b9e8..639202cb 100644
--- a/doc/gen/examples.dox
+++ b/doc/gen/examples.dox
@@ -1,13 +1,3 @@
-/*!
-@defgroup examples_frontpage Examples
-Iguana usage examples, organized by language and use cases:
-- @ref examples_cpp "C++ examples"
-- @ref examples_python "Python examples"
-- @ref examples_fortran "Fortran examples"
-*/
-
-//////////////////////////////////////////////////////////////////////////////////
-
/*!
@defgroup examples_cpp Examples in C++
Iguana usage examples in C++
@@ -23,6 +13,9 @@ they each show how build `iguana_ex_cpp_00_run_functions.cc`, which "consumes" I
- [**Meson consumer example**](https://github.com/JeffersonLab/iguana/tree/main/examples/build_with_meson)
- [**CMake consumer example**](https://github.com/JeffersonLab/iguana/tree/main/examples/build_with_cmake)
- [**Makefile consumer example**](https://github.com/JeffersonLab/iguana/tree/main/examples/build_with_make)
+
+@note To see the actual _source code_ of an example, you'll need to follow the link "Definition in file ....." or
+"Go to the source code of this file" within, since each example link below just takes you to its documentation page.
*/
//////////////////////////////////////////////////////////////////////////////////
@@ -38,6 +31,9 @@ The examples here are analogous to the C++ examples
- Examples without a number are specific to this language, showing certain use cases
@see @ref examples_cpp "C++ examples"
+
+@note To see the actual _source code_ of an example, you'll need to follow the link "Definition in file ....." or
+"Go to the source code of this file" within, since each example link below just takes you to its documentation page.
*/
//////////////////////////////////////////////////////////////////////////////////
@@ -45,5 +41,9 @@ The examples here are analogous to the C++ examples
/*!
@defgroup examples_fortran Examples in Fortran
Iguana usage examples in Fortran
-@note Before reading the examples, see @ref fortran_usage_guide
+
+@important Before reading the examples, see @ref fortran_usage_guide
+
+@note To see the actual _source code_ of an example, you'll need to follow the link "Definition in file ....." or
+"Go to the source code of this file" within, since each example link below just takes you to its documentation page.
*/
diff --git a/doc/logo.png b/doc/gen/logo.png
similarity index 100%
rename from doc/logo.png
rename to doc/gen/logo.png
diff --git a/doc/gen/logo_small.png b/doc/gen/logo_small.png
new file mode 100644
index 00000000..b792504e
Binary files /dev/null and b/doc/gen/logo_small.png differ
diff --git a/doc/gen/mainpage.md b/doc/gen/mainpage.md
index 2159bb17..96ee9214 100644
--- a/doc/gen/mainpage.md
+++ b/doc/gen/mainpage.md
@@ -1,79 +1,253 @@
# Iguana User's Guide
+
-This documentation shows how to use the Iguana algorithms.
+This documentation shows how to use the Iguana algorithms. For more documentation, see the [**Documentation Front Page**](https://github.com/JeffersonLab/iguana/blob/main/README.md)
-For more documentation, see
-- [**Documentation Front Page**](https://github.com/JeffersonLab/iguana/blob/main/README.md)
+| Quick Links ||
+| --- | --- |
+| @spacer [List of Algorithms](#algo) @spacer | @spacer [Examples of Code](#secExample) @spacer |
+| @spacer [List of Action Functions](#action) @spacer | @spacer [Configuring Algorithms](#secConfiguring) @spacer |
-## Example Code in C++, Python, and Fortran
+
+
+
+@anchor secExample
+## Example Analysis Code Using Iguana
To see Iguana algorithms used in the context of analysis code, with **various languages** and **use cases**, see:
-- \ref examples_frontpage "Examples of Analysis Code"
-**NOTE:** If you're not familiar with Iguana, please read the sections below first.
+| @spacer Examples @spacer ||
+| --- | --- |
+| @spacer [C++ Examples](#examples_cpp) @spacer | For users of `ROOT`, `clas12root`, _etc_. |
+| ^ | Includes guidance on how to build Iguana with your C++ code |
+| @spacer [Python examples](#examples_python) @spacer | For users of Python tools, such as `PyROOT` |
+| @spacer [Fortran examples](#examples_fortran) @spacer | See also the [Fortran usage guide](#fortran_usage_guide) |
+
+In summary, the general way to use an Iguana algorithm is as follows; see examples and documentation below for more details.
+
+1. Decide [which algorithms](#algo) you want to use
+ - Tip: you may use `iguana::AlgorithmSequence` to help run a _sequence_ of algorithms
+2. Check each algorithm configuration, and [adjust it if you prefer](#secConfiguring)
+3. Start each algorithm, which "locks in" its configuration:
+ - call `Start(banklist)` if you use [**the HIPO API**](https://github.com/gavalian/hipo) and [Common Functions](#secCommon)
+ - call `Start()` otherwise, _i.e._, if you use [Action Functions](#secAction)
+4. In the event loop, run the algorithm:
+ - call `Run(...)` if you use Common Functions
+ - call the Action Function(s) otherwise
+5. Proceed with your analysis
+ - if you called `Run(...)`, the banks will be filtered, transformed, and/or created
+ - if you called action functions, you will need to handle their output yourself
+ - in either case, see [guidance on how to run algorithms](#secRunning) for more details
+6. After your event loop, stop each algorithm by calling `Stop()`
+
+Please let the maintainers know if your use case is not covered in any examples or if you need any help.
+
+
+
+
+@anchor secAlgorithms
+## Algorithms
-## Language Bindings
+An Iguana algorithm is a function that maps input HIPO bank data to output data. There are a few different types of algorithms, based on how they act on HIPO data:
-Iguana algorithms are in C++; to use Iguana with other languages, see:
-- \ref fortran_usage_guide
+| Type | Description | Example |
+| --- | --- | --- |
+| **Filter** | Filters rows of a bank based on a Boolean condition | `iguana::clas12::FiducialFilter`: filter particles with fiducial cuts |
+| **Transformer** | Transform (mutate) elements of a bank | `iguana::clas12::MomentumCorrection`: correct particle momenta |
+| **Creator** | Create a new bank | `iguana::physics::InclusiveKinematics`: calculate inclusive kinematics @latex{x}, @latex{Q^2}, _etc_. |
-## Algorithms
+The available algorithms are:
-An Iguana algorithm is a function that maps input HIPO bank data to output data. The available algorithms are:
+- [Algorithms organized by Namespace](#algo_namespaces)
+- [Full List of Algorithms](#algo)
-- \ref algo_namespaces "Algorithms organized by Namespace"
-- \ref algo "Full List of Algorithms"
+
-The algorithm types are defined based on what they do to HIPO bank data:
+
+@anchor secRunning
+## How to Run Algorithms
-
- **Filter** | Remove rows of a bank based on some `bool` condition |
- **Transformer** | Transform (mutate) elements of a bank |
- **Creator** | Create a new bank |
-
+Algorithms may be run using either:
+
+- [Common Functions](#secCommon): for users of the [**the HIPO API**](https://github.com/gavalian/hipo), which is likely the case if you are using C++, _e.g._, via `clas12root`
+- [Action Functions](#secAction): for all other users
+
+The next sections describe each of these.
+
+@important It is highly recommended to read an algorithm's documentation carefully before using it.
-Most algorithms are configurable:
-- [**Algorithm Configuration Guide**](https://github.com/JeffersonLab/iguana/blob/main/doc/configuration.md)
+
+@anchor secCommon
+### Common Functions
-### Algorithm Common Functions: for HIPO C++ Users
+All algorithms have the following **Common Functions**, which may be used in analysis code that uses [**the HIPO API**](https://github.com/gavalian/hipo). These functions act on `hipo::bank` objects, and are designed to be called at certain points in an analysis of HIPO data:
-All algorithms have the following functions, which may be used in analysis code
-that uses [**the HIPO C++ API**](https://github.com/gavalian/hipo); for
-analysis code that does not, skip to the **Action Functions** section.
+| Common Functions ||
+| --- | --- |
+| `iguana::Algorithm::Start` | To be called before event processing |
+| `iguana::Algorithm::Run` | To be called for every event |
+| `iguana::Algorithm::Stop` | To be called after event processing |
+
+The algorithms are implemented in C++ classes which inherit from the base class `iguana::Algorithm`; these three class methods are overridden in each algorithm.
+
+The `iguana::Algorithm::Run` function should be called on every event; the general consequence, that is, how the user should handle the algorithm's results, depends on the
+algorithm type:
- `iguana::Algorithm::Start` | Run before event processing |
- `iguana::Algorithm::Run` | Run for every event |
- `iguana::Algorithm::Stop` | Run after event processing |
+ Type | How to handle the results |
+ **Filter** |
+The involved banks will be filtered.
+To iterate over _filtered_ bank rows, use the function `hipo::bank::getRowList`,
+rather than iterating from `0` up to `hipo::bank::getRows()`; for example, given a
+bank object named `particle_bank`:
+```cpp
+for(auto const& row : particle_bank.getRowList()) {
+ // loops over only the rows which pass the filter
+}
+```
+```cpp
+for(int row = 0; row < particle_bank.getRows(); row++) {
+ // loops over ALL rows, regardless of whether they pass the filter
+}
+```
+ |
+ **Transformer** |
+The transformed `hipo::bank` will simply have
+the relevant bank elements changed. For example, momentum correction algorithms
+typically change the particle momentum components.
+ |
+ **Creator** |
+Creator-type algorithms will simply create a new `hipo::bank` object, appending
+it to the end of the input `hipo::banklist`. An initial version is created upon calling
+`iguana::Algorithm::Start`, so that you may begin to reference it; it is helpful to
+use `hipo::getBanklistIndex` (see [the examples for details](#secExample)).
+ |
-### Algorithm Action Functions: for All Users
+Internally, `iguana::Algorithm::Run` calls Action Functions, which are described in the next section.
+
+
+@anchor secAction
+### Action Functions
The action functions do the _real_ work of the algorithm, and are meant to be
easily callable from _any_ analysis, even if HIPO banks are not directly used.
These functions are unique to each algorithm, so view the algorithm
documentation for details, or browse the full list:
-- \ref action "List of all Action Functions"
-
-The action functions have types that correspond to the algorithm types.
-Furthermore, some action functions can only be useful if all of the rows of a
-bank are included in its inputs, which motivates the following additional
-classification:
-
- **Scalar** |
-All inputs and outputs are scalar quantities (single values).
-This type of function may be used on a single bank row.
- |
- **Vector** |
-All inputs and outputs are vector quantities (lists of values).
-This type of action function needs values from all of the bank rows.
- |
- **Mixed** |
-Inputs and outputs are scalar or vector quantities.
- |
-
-To maximize compatibility with user analysis code, these functions are
-overloaded, _e.g._, for every scalar function there is a corresponding vector
-function that calls it on each element of its input vectors.
-
+- [List of all Action Functions](#action)
+
+Action function parameters are supposed to be _simple_: numbers or lists of numbers, preferably obtainable _directly_
+from HIPO bank rows. The return type of an action function depends on the algorithm type:
+
+| Algorithm Type | Action Function Output |
+| --- | --- |
+| **Filter** | Returns `bool` whether or not the filter passes |
+| **Transformer** | Returns the transformed parameters |
+| **Creator** | Returns a simple `struct` of parameters (corresponding to a created bank row) |
+
+Some algorithms have action functions which require a number from _all_ of the rows of a bank; this distinction
+motivates further classification of action functions:
+
+| Action Function Type | Description |
+| --- | --- |
+| **Scalar** | All inputs and outputs are scalar quantities (single values). This type of function may be used on a single bank row. |
+| **Vector** | All inputs and outputs are vector quantities (lists of values). This type of action function needs values from all of the bank rows. |
+| **Mixed** | Inputs and outputs are scalar or vector quantities. |
+
+To maximize compatibility with user analysis code, these functions are overloaded:
+- for every scalar function, there should be a vector function which calls the scalar function iteratively
+- not every vector function can have a corresponding scalar function, since some action functions need data from more than one bank row
+
+Finally, it is important to note _when_ to call action functions in the analysis code. For example, some action functions should be
+called _once_ every event, while others should be called for every particle of the `REC::Particle` bank. Some algorithms
+have _both_ of these types of functions, for example:
+- `iguana::clas12::ZVertexFilter::PrepareEvent`, which must be called first, at the beginning of an event's analysis
+- `iguana::clas12::ZVertexFilter::Filter`, which must be called on every particle, using the _output_ of `PrepareEvent` in one of its input parameters
+
+It is highly recommended to read an algorithm's documentation carefully before using it, _especially_ if you use action functions.
+
+@important
+While algorithm developers are encouraged _not_ to make breaking changes to their algorithms' action functions, in some cases certain changes cannot be prevented. Thus if you use an algorithm's action functions, keep up-to-date on any changes of the algorithm. We will try to announce all breaking changes in the Iguana release notes.
+
+
+
+
+@anchor secConfiguring
+## How to Configure Algorithms
+
+Many algorithms are configurable. An algorithm's configuration parameters and their default values are found in the algorithm's documentation.
+
+Iguana provides a few ways to configure algorithms; in general, you may either:
+- use YAML for configuration that gets applied at runtime, _i.e._, no need to recompile
+- use `iguana::Algorithm::SetOption` to configure an algorithm more directly, which may require recompilation, depending on how you use Iguana algorithms
+
+The default configuration YAML files are installed in the `etc/` subdirectory of the Iguana installation. If you have set the Iguana environment variables using, _e.g._ `source this_iguana.sh`, or if you are using the version of Iguana installed on `ifarm`, you will have the environment variable `$IGUANA_CONFIG_PATH` set to include this `etc/` directory.
+
+There are a few ways to configure the algorithms with YAML; see the sections below for the options
+
+@important
+While algorithm developers are encouraged _not_ to make breaking changes to their algorithms or configuration, in some cases certain changes cannot be prevented. Thus if you have your own algorithm configurations, keep up-to-date on any changes of the algorithm. We will try to announce all breaking changes in the Iguana release notes.
+
+### Option 1: Write your own YAML file
+
+Start your own YAML file by first copying the default YAML configurations from each algorithm that you want to use. See [algorithm documentation](#algo) or the `Config.yaml` files installed in `$IGUANA_CONFIG_PATH` for the algorithms' default YAML configurations.
+- Be mindful of indentation in your YAML file
+ - The top level (no indentation) contains the algorithm names
+ - Under each algorithm name is its configuration (one indentation level)
+ - Further indentation levels or lists of configurations may be used within; see each algorithm's documentation for more information
+- Note that _excluding_ a configuration option in your YAML file means that the default value will be used.
+
+For example, suppose you want to use algorithms which have the following YAML configurations:
+```yaml
+### default configuration file 1
+physics::AlgorithmA
+ cuts: [-1, 1]
+```
+```yaml
+### default configuration file 2
+physics::AlgorithmB
+ valueA: 3
+ valueB: 0.14
+ reptiles:
+ reptileA: gecko
+ reptileB: tuatara
+```
+Custom YAML file, with some changes such as widening `AlgorithmA`'s `cuts`:
+```yaml
+### custom YAML file
+physics::AlgorithmA
+ cuts: [-2, 2]
+
+physics::AlgorithmB
+ valueA: 5
+ valueB: 0.14
+ reptiles:
+ reptileA: alligator
+ reptileB: caiman
+```
+
+Once you have a YAML file, you just need to tell each algorithm to use it:
+- use `iguana::Algorithm::SetConfigFile` on each algorithm
+- if you use `iguana::AlgorithmSequence`, use `iguana::AlgorithmSequence::SetConfigFileForEachAlgorithm` to use this file for each algorithm in the algorithm sequence
+
+### Option 2: Copy the default directory, and modify
+
+First, copy the default configuration directory to your work area, or to your analysis source code; we'll call the copied directory `my_iguana_config`, as an example. If `$IGUANA_CONFIG_PATH` is the default configuration directory (_i.e._ you have not set or modified this variable yourself), you may run:
+```bash
+cp -rv $IGUANA_CONFIG_PATH my_iguana_config
+```
+
+You may then freely modify any configuration file within `my_iguana_config/`.
+
+To use this directory in your algorithms, you may do any one of the following:
+
+1. Since `$IGUANA_CONFIG_PATH` allows multiple paths, delimited by colons (`:`), prepend `my_iguana_config/` to `$IGUANA_CONFIG_PATH`; the safest way is to use an absolute path:
+```bash
+export IGUANA_CONFIG_PATH=`pwd`/my_iguana_config:$IGUANA_CONFIG_PATH # bash or zsh
+setenv IGUANA_CONFIG_PATH `pwd`/my_iguana_config:$IGUANA_CONFIG_PATH # tcsh or csh
+```
+The algorithms will then search `my_iguana_config` for the configuration before searching the default paths. You may add multiple paths, if needed.
+Paths which appear first in `$IGUANA_CONFIG_PATH` will be prioritized when the algorithm searches for configuration parameters; this behavior is similar to that of `$PATH` or `$LD_LIBRARY_PATH`.
+
+2. Use `iguana::Algorithm::SetConfigDirectory` instead of prepending `$IGUANA_CONFIG_PATH` (and if you use an algorithm sequence, use `iguana::AlgorithmSequence::SetConfigDirectoryForEachAlgorithm`)
diff --git a/examples/iguana_ex_cpp_00_run_functions.cc b/examples/iguana_ex_cpp_00_run_functions.cc
index 8444bf43..6de33b85 100644
--- a/examples/iguana_ex_cpp_00_run_functions.cc
+++ b/examples/iguana_ex_cpp_00_run_functions.cc
@@ -37,20 +37,24 @@ int main(int argc, char** argv)
// read input file
hipo::reader reader(inFileName,{0});
- // set banks
+ // set list of banks to be read
hipo::banklist banks = reader.getBanks({"RUN::config",
"REC::Particle",
"REC::Calorimeter",
"REC::Track",
"REC::Scintillator"});
- enum banks_enum { b_config,
- b_particle }; // TODO: users shouldn't have to do this
+
+ // get bank index, for each bank we want to use after Iguana algorithms run
+ auto b_particle = hipo::getBanklistIndex(banks, "REC::Particle");
// iguana algorithm sequence
iguana::AlgorithmSequence seq;
seq.Add("clas12::EventBuilderFilter"); // filter by Event Builder PID
seq.Add("clas12::SectorFinder"); // get the sector for each particle
seq.Add("clas12::MomentumCorrection"); // momentum corrections
+ // TODO:
+ // - getRowList for filter
+ // - add a creator algo
// set log levels
seq.SetOption("clas12::EventBuilderFilter", "log", "debug");
diff --git a/examples/iguana_ex_cpp_01_action_functions.cc b/examples/iguana_ex_cpp_01_action_functions.cc
index 57e2094a..15f7959b 100644
--- a/examples/iguana_ex_cpp_01_action_functions.cc
+++ b/examples/iguana_ex_cpp_01_action_functions.cc
@@ -11,6 +11,10 @@
/// NUM_EVENTS the number of events to analyze;
/// set to zero to analyze all events
/// ```
+///
+/// @note while this example _does_ use `hipo::bank` objects to read HIPO data, it demonstrates
+/// using action functions called with the data _from_ these banks.
+///
/// @end_doc_example
#include
#include
@@ -28,10 +32,12 @@ int main(int argc, char** argv)
// read input file
hipo::reader reader(inFileName,{0});
- // set banks
+ // set list of banks to be read
hipo::banklist banks = reader.getBanks({"REC::Particle", "RUN::config"});
- enum banks_enum { b_particle,
- b_config }; // TODO: users shouldn't have to do this
+
+ // get bank index, for each bank we want to use after Iguana algorithms run
+ auto b_particle = hipo::getBanklistIndex(banks, "REC::Particle");
+ auto b_config = hipo::getBanklistIndex(banks, "RUN::config");
// set the concurrency model to single-threaded, since this example is single-threaded;
// not doing this will use the thread-safe model, `"memoize"`
diff --git a/src/iguana/algorithms/AlgorithmSequence.h b/src/iguana/algorithms/AlgorithmSequence.h
index 04e9b61b..f2cca6bb 100644
--- a/src/iguana/algorithms/AlgorithmSequence.h
+++ b/src/iguana/algorithms/AlgorithmSequence.h
@@ -4,7 +4,7 @@
namespace iguana {
- /// @brief User-level class for running a sequence of algorithms
+ /// @brief An algorithm that can run a sequence of algorithms
///
/// The `Start`, `Run`, and `Stop` methods will sequentially call the corresponding algorithms' methods,
/// in the order the algorithms were added to the sequence by `AlgorithmSequence::Add`.
diff --git a/src/iguana/algorithms/clas12/EventBuilderFilter/Algorithm.h b/src/iguana/algorithms/clas12/EventBuilderFilter/Algorithm.h
index dc65804c..21e258a8 100644
--- a/src/iguana/algorithms/clas12/EventBuilderFilter/Algorithm.h
+++ b/src/iguana/algorithms/clas12/EventBuilderFilter/Algorithm.h
@@ -11,7 +11,7 @@ namespace iguana::clas12 {
/// @output_banks{REC::Particle}
/// @end_doc
///
- /// @begin_doc_config
+ /// @begin_doc_config{clas12/EventBuilderFilter}
/// @config_param{pids | list[int] | list of PDG codes to filter}
/// @end_doc
class EventBuilderFilter : public Algorithm
diff --git a/src/iguana/algorithms/clas12/FiducialFilter/Algorithm.cc b/src/iguana/algorithms/clas12/FiducialFilter/Algorithm.cc
index d4012bfe..a3c035a0 100644
--- a/src/iguana/algorithms/clas12/FiducialFilter/Algorithm.cc
+++ b/src/iguana/algorithms/clas12/FiducialFilter/Algorithm.cc
@@ -14,7 +14,7 @@ namespace iguana::clas12 {
b_traj = GetBankIndex(banks, "REC::Traj");
b_config = GetBankIndex(banks, "RUN::config");
- o_pass = GetCachedOption("pass").value_or(1);
+ o_pass = GetOptionScalar("pass");
if(o_pass!=1){
m_log->Warn("FiducialFilter only contains fiducial cuts for pass1...we will default to using those...");
}
diff --git a/src/iguana/algorithms/clas12/FiducialFilter/Algorithm.h b/src/iguana/algorithms/clas12/FiducialFilter/Algorithm.h
index 35cd8863..83163e36 100644
--- a/src/iguana/algorithms/clas12/FiducialFilter/Algorithm.h
+++ b/src/iguana/algorithms/clas12/FiducialFilter/Algorithm.h
@@ -11,7 +11,7 @@ namespace iguana::clas12 {
/// @output_banks{REC::Particle}
/// @end_doc
///
- /// @begin_doc_config
+ /// @begin_doc_config{clas12/FiducialFilter}
/// @config_param{pass | int | cook type to use for assigning fiducial cuts}
/// @end_doc
class FiducialFilter : public Algorithm
diff --git a/src/iguana/algorithms/clas12/PhotonGBTFilter/Algorithm.cc b/src/iguana/algorithms/clas12/PhotonGBTFilter/Algorithm.cc
index 51ddc500..d0895d41 100644
--- a/src/iguana/algorithms/clas12/PhotonGBTFilter/Algorithm.cc
+++ b/src/iguana/algorithms/clas12/PhotonGBTFilter/Algorithm.cc
@@ -12,8 +12,8 @@ namespace iguana::clas12 {
b_calorimeter = GetBankIndex(banks, "REC::Calorimeter");
b_config = GetBankIndex(banks, "RUN::config");
- o_pass = GetOptionScalar("pass",{});
- o_threshold = GetOptionScalar("threshold",{});
+ o_pass = GetOptionScalar("pass");
+ o_threshold = GetOptionScalar("threshold");
}
diff --git a/src/iguana/algorithms/clas12/PhotonGBTFilter/Algorithm.h b/src/iguana/algorithms/clas12/PhotonGBTFilter/Algorithm.h
index fb87f499..45c97dc9 100644
--- a/src/iguana/algorithms/clas12/PhotonGBTFilter/Algorithm.h
+++ b/src/iguana/algorithms/clas12/PhotonGBTFilter/Algorithm.h
@@ -23,7 +23,7 @@ namespace iguana::clas12 {
/// @output_banks{REC::Particle}
/// @end_doc
///
- /// @begin_doc_config
+ /// @begin_doc_config{clas12/PhotonGBTFilter}
/// @config_param{pass | int | cook type}
/// @config_param{threshold | double | minimum value to qualify a photon as "true"}
/// @end_doc
diff --git a/src/iguana/algorithms/clas12/SectorFinder/Algorithm.h b/src/iguana/algorithms/clas12/SectorFinder/Algorithm.h
index 279b145c..63edee1d 100644
--- a/src/iguana/algorithms/clas12/SectorFinder/Algorithm.h
+++ b/src/iguana/algorithms/clas12/SectorFinder/Algorithm.h
@@ -11,8 +11,9 @@ namespace iguana::clas12 {
/// @output_banks{%REC::Particle::Sector}
/// @end_doc
///
- /// @begin_doc_config
- /// @config_param{bank | string | if not `default`, use this bank for sector finding}
+ /// @begin_doc_config{clas12/SectorFinder}
+ /// @config_param{bank_charged | string | if not `default`, use this bank for sector finding of charged particles}
+ /// @config_param{bank_uncharged | string | if not `default`, use this bank for sector finding of neutral particles}
/// @end_doc
class SectorFinder : public Algorithm
{
diff --git a/src/iguana/algorithms/clas12/ZVertexFilter/Algorithm.h b/src/iguana/algorithms/clas12/ZVertexFilter/Algorithm.h
index 32bbd606..91715892 100644
--- a/src/iguana/algorithms/clas12/ZVertexFilter/Algorithm.h
+++ b/src/iguana/algorithms/clas12/ZVertexFilter/Algorithm.h
@@ -12,7 +12,7 @@ namespace iguana::clas12 {
/// @output_banks{REC::Particle}
/// @end_doc
///
- /// @begin_doc_config
+ /// @begin_doc_config{clas12/ZVertexFilter}
/// @config_param{electron_vz | list[double] | lower and upper electron @f$z@f$-vertex cuts; run-range dependent; cuts are not applied to FT electrons (FD and CD only)}
/// @end_doc
class ZVertexFilter : public Algorithm
diff --git a/src/iguana/algorithms/example/ExampleAlgorithm/Algorithm.h b/src/iguana/algorithms/example/ExampleAlgorithm/Algorithm.h
index 00813d8f..64137e93 100644
--- a/src/iguana/algorithms/example/ExampleAlgorithm/Algorithm.h
+++ b/src/iguana/algorithms/example/ExampleAlgorithm/Algorithm.h
@@ -35,7 +35,7 @@ namespace iguana::example {
/// @output_banks{REC::Particle}
/// @end_doc
///
- /// @begin_doc_config
+ /// @begin_doc_config{example/ExampleAlgorithm}
/// @config_param{exampleInt | int | an example `integer` configuration parameter}
/// @config_param{exampleDouble | double | an example `double` configuration parameter}
/// @end_doc
diff --git a/src/iguana/algorithms/physics/DihadronKinematics/Algorithm.h b/src/iguana/algorithms/physics/DihadronKinematics/Algorithm.h
index 40cab186..5234e876 100644
--- a/src/iguana/algorithms/physics/DihadronKinematics/Algorithm.h
+++ b/src/iguana/algorithms/physics/DihadronKinematics/Algorithm.h
@@ -47,7 +47,7 @@ namespace iguana::physics {
/// @output_banks{%physics::DihadronKinematics}
/// @end_doc
///
- /// @begin_doc_config
+ /// @begin_doc_config{physics/DihadronKinematics}
/// @config_param{hadron_a_list | list[int] | list of "hadron A" PDGs}
/// @config_param{hadron_b_list | list[int] | list of "hadron B" PDGs}
/// @config_param{phi_r_method | string | method used to calculate @latex{\phi_R} (see section "phiR calculation methods" below)}
diff --git a/src/iguana/algorithms/physics/InclusiveKinematics/Algorithm.cc b/src/iguana/algorithms/physics/InclusiveKinematics/Algorithm.cc
index 2d008db7..90971d3d 100644
--- a/src/iguana/algorithms/physics/InclusiveKinematics/Algorithm.cc
+++ b/src/iguana/algorithms/physics/InclusiveKinematics/Algorithm.cc
@@ -44,7 +44,7 @@ namespace iguana::physics {
o_beam_PxPyPzM = ConcurrentParamFactory::Create>();
// get reconstruction method configuration
- auto method_reconstruction_str = GetOptionScalar("method_reconstruction", {"method", "reconstruction"});
+ auto method_reconstruction_str = GetOptionScalar("reconstruction", {"method", "reconstruction"});
if(method_reconstruction_str == "scattered_lepton") {
o_method_reconstruction = method_reconstruction::scattered_lepton;
}
@@ -54,7 +54,7 @@ namespace iguana::physics {
}
// get scattered lepton finder configuration
- auto method_lepton_finder_str = GetOptionScalar("method_lepton_finder", {"method", "lepton_finder"});
+ auto method_lepton_finder_str = GetOptionScalar("lepton_finder", {"method", "lepton_finder"});
if(method_lepton_finder_str == "highest_energy_FD_trigger") {
o_method_lepton_finder = method_lepton_finder::highest_energy_FD_trigger;
}
@@ -65,7 +65,7 @@ namespace iguana::physics {
// get beam PDG and mass
o_beam_pdg = 0;
- auto beam_particle = GetOptionScalar("beam_pdg", {"method", "beam_particle"});
+ auto beam_particle = GetOptionScalar("beam_particle", {"method", "beam_particle"});
for(auto const& [pdg, name] : particle::name) {
if(name == beam_particle) {
o_beam_pdg = pdg;
diff --git a/src/iguana/algorithms/physics/InclusiveKinematics/Algorithm.h b/src/iguana/algorithms/physics/InclusiveKinematics/Algorithm.h
index c60c3e91..7b4a9594 100644
--- a/src/iguana/algorithms/physics/InclusiveKinematics/Algorithm.h
+++ b/src/iguana/algorithms/physics/InclusiveKinematics/Algorithm.h
@@ -42,13 +42,12 @@ namespace iguana::physics {
/// @output_banks{%physics::InclusiveKinematics}
/// @end_doc
///
- /// @begin_doc_config
- /// @config_param{initial_state:beam_energy | double | beam energy [GeV]}
- /// @config_param{initial_state:beam_direction | list[double] | beam direction vector}
- /// @config_param{initial_state:target_particle | string | target particle}
- /// @config_param{method:beam_particle | string | beam particle}
- /// @config_param{method:reconstruction | string | kinematics reconstruction method; only `scattered_lepton` is available}
- /// @config_param{method:lepton_finder | string | algorithm to find the scattered lepton; only `highest_energy_FD_trigger` is available}
+ /// @begin_doc_config{physics/InclusiveKinematics}
+ /// @config_param{beam_direction | list[double] | beam direction vector}
+ /// @config_param{target_particle | string | target particle}
+ /// @config_param{beam_particle | string | beam particle}
+ /// @config_param{reconstruction | string | kinematics reconstruction method; only `scattered_lepton` is available at this time}
+ /// @config_param{lepton_finder | string | algorithm to find the scattered lepton; only `highest_energy_FD_trigger` is available at this time}
/// @end_doc
class InclusiveKinematics : public Algorithm
{
diff --git a/src/iguana/algorithms/physics/SingleHadronKinematics/Algorithm.h b/src/iguana/algorithms/physics/SingleHadronKinematics/Algorithm.h
index 9405f5eb..3920d463 100644
--- a/src/iguana/algorithms/physics/SingleHadronKinematics/Algorithm.h
+++ b/src/iguana/algorithms/physics/SingleHadronKinematics/Algorithm.h
@@ -36,8 +36,8 @@ namespace iguana::physics {
/// @output_banks{%physics::SingleHadronKinematics}
/// @end_doc
///
- /// @begin_doc_config
- /// @config_param{hadron_list | list[int] | list of hadron PDGs}
+ /// @begin_doc_config{physics/SingleHadronKinematics}
+ /// @config_param{hadron_list | list[int] | calculate kinematics for these hadron PDGs}
/// @end_doc
///
/// The output bank `%physics::SingleHadronKinematics` will have the same number of rows as the input particle bank `REC::Particle`