diff --git a/doc/gen/Doxyfile.in b/doc/gen/Doxyfile.in
index 0a58a8fc..c52120d3 100644
--- a/doc/gen/Doxyfile.in
+++ b/doc/gen/Doxyfile.in
@@ -306,6 +306,7 @@ ALIASES += doxygen_on="@endcond"
ALIASES += latex{1}="@f$\1@f$"
# misc
ALIASES += spacer=" "
+ALIASES += creator_note="This algorithm creates a new bank and its definition is found within the \link src/iguana/bankdefs/iguana.json **Iguana Bank Definitions JSON File** \endlink
- For guidance on how to read this JSON file, [see documentation on created banks](#mainpageCreatedBanks).
- See also the return value type of this algorithm's action functions, which may be `struct`s with the same set of variables as the created bank.
"
# 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
@@ -970,7 +971,8 @@ INPUT = @top_srcdir@/src/ \
@top_srcdir@/bind/ \
@top_srcdir@/doc/gen/ \
@top_srcdir@/doc/gen/mainpage.md \
- @top_srcdir@/examples/
+ @top_srcdir@/examples/ \
+ @top_srcdir@/src/iguana/bankdefs/iguana.json
# This tag can be used to specify the character encoding of the source files
# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses
diff --git a/doc/gen/mainpage.md b/doc/gen/mainpage.md
index 96ee9214..1542c6ac 100644
--- a/doc/gen/mainpage.md
+++ b/doc/gen/mainpage.md
@@ -5,13 +5,13 @@ This documentation shows how to use the Iguana algorithms. For more documentatio
| 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 |
+| @spacer [List of Algorithms](#algo) @spacer | @spacer [Examples of Code](#mainpageExample) @spacer |
+| @spacer [List of Action Functions](#action) @spacer | @spacer [Configuring Algorithms](#mainpageConfiguring) @spacer |
-@anchor secExample
+@anchor mainpageExample
## Example Analysis Code Using Iguana
To see Iguana algorithms used in the context of analysis code, with **various languages** and **use cases**, see:
@@ -27,17 +27,17 @@ In summary, the general way to use an Iguana algorithm is as follows; see exampl
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)
+2. Check each algorithm configuration, and [adjust it if you prefer](#mainpageConfiguring)
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)
+ - call `Start(banklist)` if you use [**the HIPO API**](https://github.com/gavalian/hipo) and [Common Functions](#mainpageCommon)
+ - call `Start()` otherwise, _i.e._, if you use [Action Functions](#mainpageAction)
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
+ - in either case, see [guidance on how to run algorithms](#mainpageRunning) 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.
@@ -45,7 +45,7 @@ Please let the maintainers know if your use case is not covered in any examples
-@anchor secAlgorithms
+@anchor mainpageAlgorithms
## Algorithms
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:
@@ -61,23 +61,61 @@ The available algorithms are:
- [Algorithms organized by Namespace](#algo_namespaces)
- [Full List of Algorithms](#algo)
+@anchor mainpageCreatedBanks
+### New Banks from Iguana Creator Algorithms
+
+The definitions of the new banks that are created by **Creator** algorithms are found in:
+- @link src/iguana/bankdefs/iguana.json **Iguana Bank Definitions:** `iguana.json` @endlink
+
+This JSON file follows a similar format as the bank definitions in `coatjava`, where we have:
+
+| Key | Description |
+| --- | --- |
+| name | the name of the new bank |
+| algorithm | the algorithm that creates this bank |
+| group | unique ID numbers for this bank |
+| item | ^ |
+| entries | the list of variables in this bank |
+
+Often the bank name matches the algorithm name, but not always; see the JSON keys \"name\" and \"algorithm\" to be sure.
+
+For each variable in "entries", we have:
+
+| Key | Description |
+| --- | --- |
+| name | the variable name |
+| type | the variable type (see below) |
+| info | the description of this variable |
+
+The variable types and their corresponding accessor methods from `hipo::bank` are:
+
+| Type Specification | `hipo::bank` accessor |
+| --- | --- |
+| B | `getByte` |
+| S | `getShort` |
+| I | `getInt` |
+| L | `getLong` |
+| F | `getFloat` |
+| D | `getDouble` |
+
+
-@anchor secRunning
+@anchor mainpageRunning
## How to Run Algorithms
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
+- [Common Functions](#mainpageCommon): 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](#mainpageAction): 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.
-@anchor secCommon
+@anchor mainpageCommon
### Common Functions
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:
@@ -120,14 +158,14 @@ typically change the particle momentum components.
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)).
+use `hipo::getBanklistIndex` (see [the examples for details](#mainpageExample)).
Internally, `iguana::Algorithm::Run` calls Action Functions, which are described in the next section.
-@anchor secAction
+@anchor mainpageAction
### Action Functions
The action functions do the _real_ work of the algorithm, and are meant to be
@@ -173,7 +211,7 @@ While algorithm developers are encouraged _not_ to make breaking changes to thei
-@anchor secConfiguring
+@anchor mainpageConfiguring
## How to Configure Algorithms
Many algorithms are configurable. An algorithm's configuration parameters and their default values are found in the algorithm's documentation.
diff --git a/meson.build b/meson.build
index 5572baae..b695d2ea 100644
--- a/meson.build
+++ b/meson.build
@@ -205,6 +205,7 @@ endif
# build and install shared libraries
subdir('src/iguana/services')
+subdir('src/iguana/bankdefs')
subdir('src/iguana/algorithms')
subdir('src/iguana/tests')
diff --git a/src/iguana/algorithms/Algorithm.cc b/src/iguana/algorithms/Algorithm.cc
index b6f37a27..d5cc8da6 100644
--- a/src/iguana/algorithms/Algorithm.cc
+++ b/src/iguana/algorithms/Algorithm.cc
@@ -1,7 +1,5 @@
#include "Algorithm.h"
-#include
-
namespace iguana {
void Algorithm::Start()
@@ -223,29 +221,32 @@ namespace iguana {
hipo::schema Algorithm::CreateBank(
hipo::banklist& banks,
hipo::banklist::size_type& bank_idx,
- std::string const& bank_name,
- std::vector schema_def,
- int group_id,
- int item_id) const
+ std::string const& bank_name) const noexcept(false)
{
- if(!AlgorithmFactory::QueryNewBank(bank_name)) {
- m_log->Error("{:?} creates bank {:?}, which is not registered; new banks must be included in `REGISTER_IGUANA_ALGORITHM` arguments", m_class_name, bank_name);
- throw std::runtime_error("CreateBank failed");
- }
- if(schema_def.empty()) {
- m_log->Error("empty schema_def in CreateBank");
- throw std::runtime_error("CreateBank failed");
+ // loop over bank definitions
+ // NOTE: `BANK_DEFS` is generated at build-time using `src/iguana/bankdefs/iguana.json`
+ for(auto const& bank_def : BANK_DEFS) {
+ if(bank_def.name == bank_name) {
+ // make sure the new bank is in REGISTER_IGUANA_ALGORITHM
+ if(!AlgorithmFactory::QueryNewBank(bank_name)) {
+ m_log->Error("{:?} creates bank {:?}, which is not registered; new banks must be included in `REGISTER_IGUANA_ALGORITHM` arguments", m_class_name, bank_name);
+ throw std::runtime_error("CreateBank failed");
+ }
+ // create the schema format string
+ std::vector schema_def;
+ for(auto const& entry : bank_def.entries)
+ schema_def.push_back(entry.name + "/" + entry.type);
+ auto format_string = fmt::format("{}", fmt::join(schema_def, ","));
+ // create the new bank schema
+ hipo::schema bank_schema(bank_name.c_str(), bank_def.group, bank_def.item);
+ bank_schema.parse(format_string);
+ // create the new bank
+ banks.push_back({bank_schema});
+ bank_idx = GetBankIndex(banks, bank_name);
+ return bank_schema;
+ }
}
- hipo::schema bank_schema(bank_name.c_str(), group_id, item_id);
- bank_schema.parse(std::accumulate(
- std::next(schema_def.begin()),
- schema_def.end(),
- schema_def[0],
- [](std::string a, std::string b)
- { return a + "," + b; }));
- banks.push_back({bank_schema});
- bank_idx = GetBankIndex(banks, bank_name);
- return bank_schema;
+ throw std::runtime_error(fmt::format("bank {:?} not found in 'BankDefs.h'; is this bank defined in src/iguana/bankdefs/iguana.json ?", bank_name));
}
///////////////////////////////////////////////////////////////////////////////
diff --git a/src/iguana/algorithms/Algorithm.h b/src/iguana/algorithms/Algorithm.h
index 1700ca5c..8913cec2 100644
--- a/src/iguana/algorithms/Algorithm.h
+++ b/src/iguana/algorithms/Algorithm.h
@@ -6,8 +6,8 @@
#include
-
-#include "iguana/algorithms/AlgorithmBoilerplate.h"
+#include "AlgorithmBoilerplate.h"
+#include "iguana/bankdefs/BankDefs.h"
#include "iguana/services/YAMLReader.h"
#include
@@ -153,21 +153,15 @@ namespace iguana {
/// returns the `hipo::banklist` index of the bank
hipo::banklist::size_type GetBankIndex(hipo::banklist& banks, std::string const& bank_name) const noexcept(false);
- /// Create a new bank and push it to the bank list
+ /// Create a new bank and push it to the bank list. The bank must be defined in `src/iguana/bankdefs/iguana.json`.
/// @param [out] banks the `hipo::banklist` onto which the new bank will be pushed
/// @param [out] bank_idx will be set to the `hipo::banklist` index of the new bank
/// @param [in] bank_name the new bank name
- /// @param [in] schema_def a list of variables for the schema
- /// @param [in] group_id the group ID for the schema
- /// @param [in] item_id the item ID for the schema
/// @returns the bank's schema
hipo::schema CreateBank(
hipo::banklist& banks,
hipo::banklist::size_type& bank_idx,
- std::string const& bank_name,
- std::vector schema_def,
- int group_id, // FIXME: generalize group_id and item_id setting
- int item_id) const noexcept(false);
+ std::string const& bank_name) const noexcept(false);
/// Dump all banks in a `hipo::banklist`
/// @param banks the banks to show
diff --git a/src/iguana/algorithms/clas12/SectorFinder/Algorithm.cc b/src/iguana/algorithms/clas12/SectorFinder/Algorithm.cc
index 0adfa93b..7cce65a2 100644
--- a/src/iguana/algorithms/clas12/SectorFinder/Algorithm.cc
+++ b/src/iguana/algorithms/clas12/SectorFinder/Algorithm.cc
@@ -43,8 +43,7 @@ namespace iguana::clas12 {
}
// create the output bank
- // FIXME: generalize the groupid and itemid
- auto result_schema = CreateBank(banks, b_result, "REC::Particle::Sector", {"sector/I","pindex/S"}, 0xF000, 4);
+ auto result_schema = CreateBank(banks, b_result, "REC::Particle::Sector");
i_sector = result_schema.getEntryOrder("sector");
i_pindex = result_schema.getEntryOrder("pindex");
}
diff --git a/src/iguana/algorithms/clas12/SectorFinder/Algorithm.h b/src/iguana/algorithms/clas12/SectorFinder/Algorithm.h
index 63edee1d..de582b95 100644
--- a/src/iguana/algorithms/clas12/SectorFinder/Algorithm.h
+++ b/src/iguana/algorithms/clas12/SectorFinder/Algorithm.h
@@ -15,6 +15,8 @@ namespace iguana::clas12 {
/// @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
+ ///
+ /// @creator_note
class SectorFinder : public Algorithm
{
diff --git a/src/iguana/algorithms/meson.build b/src/iguana/algorithms/meson.build
index 170b558a..49ff5e98 100644
--- a/src/iguana/algorithms/meson.build
+++ b/src/iguana/algorithms/meson.build
@@ -114,6 +114,7 @@ algo_sources = [
'Algorithm.cc',
'AlgorithmFactory.cc',
'AlgorithmSequence.cc',
+ bankdef_tgt[1], # BankDefs.cc
]
algo_headers = [
'Algorithm.h',
diff --git a/src/iguana/algorithms/physics/Depolarization/Algorithm.cc b/src/iguana/algorithms/physics/Depolarization/Algorithm.cc
index 73954888..49c6f88c 100644
--- a/src/iguana/algorithms/physics/Depolarization/Algorithm.cc
+++ b/src/iguana/algorithms/physics/Depolarization/Algorithm.cc
@@ -10,13 +10,7 @@ namespace iguana::physics {
// create the output bank
// FIXME: generalize the groupid and itemid
- auto result_schema = CreateBank(
- banks,
- b_result,
- GetClassName(),
- {"epsilon/D", "A/D", "B/D", "C/D", "V/D", "W/D"},
- 0xF000,
- 1);
+ auto result_schema = CreateBank(banks, b_result, GetClassName());
i_epsilon = result_schema.getEntryOrder("epsilon");
i_A = result_schema.getEntryOrder("A");
i_B = result_schema.getEntryOrder("B");
diff --git a/src/iguana/algorithms/physics/Depolarization/Algorithm.h b/src/iguana/algorithms/physics/Depolarization/Algorithm.h
index d68f875d..e041d5ad 100644
--- a/src/iguana/algorithms/physics/Depolarization/Algorithm.h
+++ b/src/iguana/algorithms/physics/Depolarization/Algorithm.h
@@ -4,33 +4,18 @@
namespace iguana::physics {
- /// Set of depolarization variables
- struct DepolarizationVars {
- /// @brief @latex{\varepsilon(Q^2,x,y)}, the ratio of transverse and longitudinal photon flux
- double epsilon;
- /// @brief depolarization factor @latex{A(\varepsilon,y)}
- double A;
- /// @brief depolarization factor @latex{B(\varepsilon,y)}
- double B;
- /// @brief depolarization factor @latex{C(\varepsilon,y)}
- double C;
- /// @brief depolarization factor @latex{V(\varepsilon,y)}
- double V;
- /// @brief depolarization factor @latex{W(\varepsilon,y)}
- double W;
- };
-
- /// @brief_algo Calculate depolarization factors defined in `iguana::physics::DepolarizationVars`
+ /// @brief_algo Calculate depolarization factors
+ ///
+ /// @par References
+ /// - https://arxiv.org/pdf/hep-ph/0611265
+ /// - https://arxiv.org/pdf/1408.5721
///
/// @begin_doc_algo{physics::Depolarization | Creator}
/// @input_banks{%physics::InclusiveKinematics}
/// @output_banks{%physics::Depolarization}
/// @end_doc
///
- /// References:
- ///
- /// - https://arxiv.org/pdf/hep-ph/0611265
- /// - https://arxiv.org/pdf/1408.5721
+ /// @creator_note
class Depolarization : public Algorithm
{
diff --git a/src/iguana/algorithms/physics/DihadronKinematics/Algorithm.cc b/src/iguana/algorithms/physics/DihadronKinematics/Algorithm.cc
index 980145e2..ead9ae2a 100644
--- a/src/iguana/algorithms/physics/DihadronKinematics/Algorithm.cc
+++ b/src/iguana/algorithms/physics/DihadronKinematics/Algorithm.cc
@@ -13,28 +13,7 @@ namespace iguana::physics {
b_inc_kin = GetBankIndex(banks, "physics::InclusiveKinematics");
// create the output bank
- // FIXME: generalize the groupid and itemid
- auto result_schema = CreateBank(
- banks,
- b_result,
- GetClassName(),
- {
- "pindex_a/S",
- "pindex_b/S",
- "pdg_a/I",
- "pdg_b/I",
- "Mh/D",
- "z/D",
- "PhPerp/D",
- "MX2/D",
- "xF/D",
- "yB/D",
- "phiH/D",
- "phiR/D",
- "theta/D"
- },
- 0xF000,
- 5);
+ auto result_schema = CreateBank(banks, b_result, GetClassName());
i_pindex_a = result_schema.getEntryOrder("pindex_a");
i_pindex_b = result_schema.getEntryOrder("pindex_b");
i_pdg_a = result_schema.getEntryOrder("pdg_a");
diff --git a/src/iguana/algorithms/physics/DihadronKinematics/Algorithm.h b/src/iguana/algorithms/physics/DihadronKinematics/Algorithm.h
index 5234e876..8052c52e 100644
--- a/src/iguana/algorithms/physics/DihadronKinematics/Algorithm.h
+++ b/src/iguana/algorithms/physics/DihadronKinematics/Algorithm.h
@@ -7,39 +7,6 @@
namespace iguana::physics {
- /// Set of dihadron kinematics variables
- struct DihadronKinematicsVars {
- /// @brief `REC::Particle` row (`pindex`) of hadron A
- int pindex_a;
- /// @brief `REC::Particle` row (`pindex`) of hadron B
- int pindex_b;
- /// @brief PDG code of hadron A
- int pdg_a;
- /// @brief PDG code of hadron B
- int pdg_b;
- /// @brief @latex{M_h}: Invariant mass of the dihadron
- double Mh;
- /// @brief @latex{z}: Momentum fraction of the fragmenting parton carried by the dihadron
- double z;
- /// @brief @latex{P_h^\perp}: transverse momentum of the dihadron in the @latex{\perp}-frame (transverse to @latex{\vec{q}})
- double PhPerp;
- /// @brief @latex{M_X(ehhX)^2}: Missing mass squared of the dihadron
- double MX2;
- /// @brief @latex{x_F}: Feynman-x of the dihadron
- double xF;
- /// @brief @latex{y_{h,B}}: Breit frame rapidity of the dihadron
- double yB;
- /// @brief @latex{\phi_h}: @latex{q}-azimuthal angle between the lepton-scattering plane and the @latex{\vec{q}\times\vec{P}_h} plane;
- /// if the value is `tools::UNDEF`, the calculation failed
- double phiH;
- /// @brief @latex{\phi_R}: @latex{q}-azimuthal angle between the lepton-scattering plane and dihadron plane;
- /// if the value is `tools::UNDEF`, the calculation failed
- double phiR;
- /// @brief @latex{\theta}: The "decay" angle of hadron A in the dihadron rest frame, with respect;
- /// to the dihadron momentum direction
- double theta;
- };
-
/// @brief_algo Calculate semi-inclusive dihadron kinematic quantities defined in `iguana::physics::DihadronKinematicsVars`
///
/// @begin_doc_algo{physics::DihadronKinematics | Creator}
@@ -69,6 +36,8 @@ namespace iguana::physics {
///
/// @par theta calculation methods
/// - `"hadron_a"`: use hadron A's "decay angle" in the dihadron rest frame
+ ///
+ /// @creator_note
class DihadronKinematics : public Algorithm
{
diff --git a/src/iguana/algorithms/physics/InclusiveKinematics/Algorithm.cc b/src/iguana/algorithms/physics/InclusiveKinematics/Algorithm.cc
index 6763a602..399c4ee7 100644
--- a/src/iguana/algorithms/physics/InclusiveKinematics/Algorithm.cc
+++ b/src/iguana/algorithms/physics/InclusiveKinematics/Algorithm.cc
@@ -13,14 +13,7 @@ namespace iguana::physics {
b_config = GetBankIndex(banks, "RUN::config");
// create the output bank
- // FIXME: generalize the groupid and itemid
- auto result_schema = CreateBank(
- banks,
- b_result,
- GetClassName(),
- {"pindex/S", "Q2/D", "x/D", "y/D", "W/D", "nu/D", "qx/D", "qy/D", "qz/D", "qE/D", "beamPz/D", "targetM/D"},
- 0xF000,
- 1);
+ auto result_schema = CreateBank(banks, b_result, GetClassName());
i_pindex = result_schema.getEntryOrder("pindex");
i_Q2 = result_schema.getEntryOrder("Q2");
i_x = result_schema.getEntryOrder("x");
diff --git a/src/iguana/algorithms/physics/InclusiveKinematics/Algorithm.h b/src/iguana/algorithms/physics/InclusiveKinematics/Algorithm.h
index 7b4a9594..12d2e16b 100644
--- a/src/iguana/algorithms/physics/InclusiveKinematics/Algorithm.h
+++ b/src/iguana/algorithms/physics/InclusiveKinematics/Algorithm.h
@@ -7,35 +7,7 @@
namespace iguana::physics {
- /// Set of inclusive kinematics variables
- struct InclusiveKinematicsVars {
- /// @brief `REC::Particle` row (`pindex`) of the scattered electron
- int pindex;
- /// @brief @latex{x}-component of virtual photon momentum @latex{q}
- vector_element_t qx;
- /// @brief @latex{y}-component of virtual photon momentum @latex{q}
- vector_element_t qy;
- /// @brief @latex{z}-component of virtual photon momentum @latex{q}
- vector_element_t qz;
- /// @brief @latex{E}-component of virtual photon momentum @latex{q}
- vector_element_t qE;
- /// @brief @latex{Q^2} (GeV@latex{^2})
- double Q2;
- /// @brief @latex{x_B}
- double x;
- /// @brief @latex{y}
- double y;
- /// @brief @latex{W} (GeV)
- double W;
- /// @brief @latex{\nu}
- double nu;
- /// @brief beam momentum @latex{z}-component (GeV)
- double beamPz;
- /// @brief target mass (GeV)
- double targetM;
- };
-
- /// @brief_algo Calculate inclusive kinematics quantities defined in `iguana::physics::InclusiveKinematicsVars`
+ /// @brief_algo Calculate inclusive kinematics quantities
///
/// @begin_doc_algo{physics::InclusiveKinematics | Creator}
/// @input_banks{REC::Particle, RUN::config}
@@ -49,6 +21,8 @@ namespace iguana::physics {
/// @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
+ ///
+ /// @creator_note
class InclusiveKinematics : public Algorithm
{
diff --git a/src/iguana/algorithms/physics/SingleHadronKinematics/Algorithm.cc b/src/iguana/algorithms/physics/SingleHadronKinematics/Algorithm.cc
index 4b55bfd9..10136d0e 100644
--- a/src/iguana/algorithms/physics/SingleHadronKinematics/Algorithm.cc
+++ b/src/iguana/algorithms/physics/SingleHadronKinematics/Algorithm.cc
@@ -14,24 +14,7 @@ namespace iguana::physics {
b_inc_kin = GetBankIndex(banks, "physics::InclusiveKinematics");
// create the output bank
- // FIXME: generalize the groupid and itemid
- auto result_schema = CreateBank(
- banks,
- b_result,
- GetClassName(),
- {
- "pindex/S",
- "pdg/I",
- "z/D",
- "PhPerp/D",
- "MX2/D",
- "xF/D",
- "yB/D",
- "phiH/D",
- "xi/D"
- },
- 0xF000,
- 7);
+ auto result_schema = CreateBank(banks, b_result, GetClassName());
i_pindex = result_schema.getEntryOrder("pindex");
i_pdg = result_schema.getEntryOrder("pdg");
i_z = result_schema.getEntryOrder("z");
diff --git a/src/iguana/algorithms/physics/SingleHadronKinematics/Algorithm.h b/src/iguana/algorithms/physics/SingleHadronKinematics/Algorithm.h
index 3920d463..3cacca33 100644
--- a/src/iguana/algorithms/physics/SingleHadronKinematics/Algorithm.h
+++ b/src/iguana/algorithms/physics/SingleHadronKinematics/Algorithm.h
@@ -6,30 +6,7 @@
namespace iguana::physics {
- /// Set of hadron kinematics variables
- struct SingleHadronKinematicsVars {
- /// @brief `REC::Particle` row (`pindex`) of the hadron
- int pindex;
- /// @brief PDG code of the hadron
- int pdg;
- /// @brief @latex{z}: Momentum fraction of the fragmenting parton carried by the hadron
- double z;
- /// @brief @latex{P_h^\perp}: transverse momentum of the hadron in the @latex{\perp}-frame (transverse to @latex{\vec{q}})
- double PhPerp;
- /// @brief @latex{M_X(ehX)^2}: Missing mass squared of the hadron
- double MX2;
- /// @brief @latex{x_F}: Feynman-x of the hadron
- double xF;
- /// @brief @latex{y_{h,B}}: Breit frame rapidity of the hadron
- double yB;
- /// @brief @latex{\phi_h}: @latex{q}-azimuthal angle between the lepton-scattering plane and the @latex{\vec{q}\times\vec{P}_h} plane;
- /// if the value is `tools::UNDEF`, the calculation failed
- double phiH;
- /// @brief @latex{\xi_h}: Longitudinal momentum fraction of the nucleon carried by the hadron
- double xi;
- };
-
- /// @brief_algo Calculate semi-inclusive hadron kinematic quantities defined in `iguana::physics::SingleHadronKinematicsVars`
+ /// @brief_algo Calculate semi-inclusive hadron kinematic quantities
///
/// @begin_doc_algo{physics::SingleHadronKinematics | Creator}
/// @input_banks{REC::Particle, %physics::InclusiveKinematics}
@@ -48,6 +25,8 @@ namespace iguana::physics {
/// corresponding row in the output bank will be zeroed, since no calculations are performed for
/// those particles
/// - particles which are not listed in the configuration parameter `hadron_list` will also be filtered out and zeroed
+ ///
+ /// @creator_note
class SingleHadronKinematics : public Algorithm
{
diff --git a/src/iguana/bankdefs/README.md b/src/iguana/bankdefs/README.md
new file mode 100644
index 00000000..96082972
--- /dev/null
+++ b/src/iguana/bankdefs/README.md
@@ -0,0 +1,20 @@
+# Iguana Bank Definitions
+
+Creator algorithms create new banks; the files in this directory describe the new banks, in particular, [`iguana.json`](iguana.json).
+
+This JSON file follows a similar format as the `coatjava` bank definitions and may be used as a reference; the only change is the addition of the `algorithm` key, which is used to inform which algorithm creates the bank. See [the user guide](https://jeffersonlab.github.io/iguana/doxygen) for more general information about the format of this JSON file.
+
+## Additional notes for developers
+- [`bankgen.py`](bankgen.py) will read the JSON file and generate C++ code to handle the bank creation
+ - while you are developing your creator algorithm, you may first update the JSON file, then compile the code; this will run `bankgen.py`, which will generate `BankDefs.h` and `BankDefs.cc` within the _build_ directory, so you may inspect those files for further information if this documentation is not clear
+ - compilation will fail if the JSON syntax is incorrect
+- for action functions' convenience, `bankgen.py` will generate a C++ `struct` with the name `[ALGORITHM_NAME]Vars` (the algorithm name with `Vars` appended)
+ - this `struct` may be used as the _return value_ type of action functions, if needed
+ - the variables in the `struct` have the same name and types as those defined in the bank "entries"; the "info" docstrings are used by `doxygen`
+- add a new bank to the end of the JSON file, and increment the "item" number
+ - the "group" and "item" numbers must be unique for all banks (including those upstream in `coatjava`)
+ - all Iguana banks must use "group" `30000`
+- values of "info" entries must be `doxygen` docstrings
+ - they are used in the documentation generation
+ - all backslashes must be escaped, _i.e._ instead of `\` write `\\`, otherwise the JSON syntax will be invalid
+- our convention is that the bank name matches the algorithm name, but that does not have to be followed (early creator algorithms did not have this convention)
diff --git a/src/iguana/bankdefs/bankgen.py b/src/iguana/bankdefs/bankgen.py
new file mode 100755
index 00000000..6c31ab9c
--- /dev/null
+++ b/src/iguana/bankdefs/bankgen.py
@@ -0,0 +1,154 @@
+#!/usr/bin/env python3
+
+"""
+Reads an input JSON data model file, which defines the bank schema, and
+generates C++ source code for handling these banks in Iguana.
+"""
+
+import sys, json, textwrap
+
+# parse arguments
+if(len(sys.argv) < 3):
+ print(f'USAGE {__file__} [INPUT_JSON] [OUTPUT_BASENAME]')
+ exit(2)
+input_file_name = sys.argv[1]
+output_base_name = sys.argv[2]
+
+# return a comma if `idx` does not point to the last element of list `arr`
+def trailing_comma(arr, idx):
+ if(idx < len(arr)):
+ return ','
+ else:
+ return ''
+
+# map `type` character to C++ type
+type_dict = {
+ 'B': 'int',
+ 'S': 'int',
+ 'I': 'int',
+ 'F': 'float',
+ 'D': 'double',
+ 'L': 'long',
+}
+
+# all iguana banks should have this group ID
+iguana_group_id = 30000
+
+# open the JSON file
+with open(input_file_name) as input_file:
+
+ try:
+ bank_defs = json.load(input_file)
+
+ # start the output C++ files
+ out_h = open(f'{output_base_name}.h', 'w')
+ out_cc = open(f'{output_base_name}.cc', 'w')
+
+ # start the header file with some common structs
+ out_h.write(textwrap.dedent('''\
+ #include
+ #include
+
+ namespace iguana {
+
+ /// A bank column
+ struct BankColDef {
+ /// @brief the name of the column
+ std::string name;
+ /// @brief the type of the column
+ std::string type;
+ };
+
+ /// The definition of a bank
+ struct BankDef {
+ /// @brief the name of the bank
+ std::string name;
+ /// @brief the group ID of the bank
+ int group;
+ /// @brief the item ID of the bank
+ int item;
+ /// @brief the set of columns
+ std::vector entries;
+ };
+
+ /// Definitions of banks that Iguana algorithms may create; this variable is
+ /// defined in code generated by `src/iguana/bankdefs/bankgen.py`
+ extern std::vector const BANK_DEFS;
+
+ }
+
+ '''))
+
+ # the `.cc` source file will define `BANK_DEFS`; start its definition
+ out_cc.write(textwrap.dedent(f'''\
+ #include "BankDefs.h"
+
+ namespace iguana {{
+ std::vector const BANK_DEFS = {{
+ '''))
+
+ # loop over bank definitions in the JSON file
+ i_bank_def = 0
+ unique_item_ids = []
+ for bank_def in bank_defs:
+
+ i_bank_def += 1
+ trail_bank_def = trailing_comma(bank_defs, i_bank_def)
+
+ # make sure the item ID is unique and the group ID is a expected
+ if(bank_def["item"] in unique_item_ids):
+ print(f'ERROR: item ID {bank_def["item"]} is not unique in {input_file_name}', file=sys.stderr)
+ exit(1)
+ unique_item_ids.append(bank_def["item"])
+ if(bank_def["group"] != iguana_group_id):
+ print(f'ERROR: all group IDs must be {iguana_group_id}', file=sys.stderr)
+ exit(1)
+
+ # append this bank to `BANK_DEFS`
+ out_cc.write(textwrap.indent(textwrap.dedent(f'''\
+ {{
+ .name = "{bank_def["name"]}",
+ .group = {bank_def["group"]},
+ .item = {bank_def["item"]},
+ .entries = {{
+ '''), ' '))
+ i_entry = 0
+ for entry in bank_def['entries']:
+ i_entry += 1
+ trail_entry = trailing_comma(bank_def['entries'], i_entry)
+ out_cc.write(f' {{ .name = "{entry["name"]}", .type = "{entry["type"]}" }}{trail_entry}\n')
+ out_cc.write(f' }}\n')
+ out_cc.write(f' }}{trail_bank_def}\n')
+
+ # make a struct for this algorithm's action function output
+ algo_name = bank_def["algorithm"]
+ namespace_name = '::'.join(['iguana', *algo_name.split('::')[0:-1]])
+ struct_name = algo_name.split('::')[-1] + 'Vars'
+ out_h.write(textwrap.dedent(f'''\
+ namespace {namespace_name} {{
+ /// Set of variables created by creator algorithm `iguana::{algo_name}`
+ struct {struct_name} {{
+ '''))
+ for entry in bank_def['entries']:
+ if entry["type"] in type_dict:
+ out_h.write(textwrap.indent(textwrap.dedent(f'''\
+ /// @brief {entry["info"]}
+ {type_dict[entry["type"]]} {entry["name"]};
+ '''), ' '))
+ else:
+ print(f'ERROR: bank entry type "{entry["type"]}" is unknown', file=sys.stderr)
+ exit(1)
+ out_h.write(' };\n')
+ out_h.write('}\n\n')
+
+ out_cc.write(' };\n')
+ out_cc.write('}\n')
+ out_cc.close()
+ out_h.close()
+
+ except json.decoder.JSONDecodeError:
+ print(f'ERROR: failed to parse {input_file_name}; check its JSON syntax', file=sys.stderr)
+ exit(1)
+
+# for ext in ['h', 'cc']:
+# print(f'Generated {output_base_name}.{ext}')
diff --git a/src/iguana/bankdefs/iguana.json b/src/iguana/bankdefs/iguana.json
new file mode 100644
index 00000000..41911661
--- /dev/null
+++ b/src/iguana/bankdefs/iguana.json
@@ -0,0 +1,89 @@
+[
+ {
+ "name": "REC::Particle::Sector",
+ "algorithm": "clas12::SectorFinder",
+ "group": 30000,
+ "item": 1,
+ "info": "",
+ "entries": [
+ { "name": "pindex", "type": "S", "info": "row number in the particle bank" },
+ { "name": "sector", "type": "I", "info": "sector for this particle" }
+ ]
+ },
+ {
+ "name": "physics::InclusiveKinematics",
+ "algorithm": "physics::InclusiveKinematics",
+ "group": 30000,
+ "item": 2,
+ "info": "",
+ "entries": [
+ { "name": "pindex", "type": "S", "info": "`REC::Particle` row (`pindex`) of the scattered electron" },
+ { "name": "Q2", "type": "D", "info": "@latex{Q^2} (GeV@latex{^2})" },
+ { "name": "x", "type": "D", "info": "@latex{x_B}" },
+ { "name": "y", "type": "D", "info": "@latex{y}" },
+ { "name": "W", "type": "D", "info": "@latex{W} (GeV)" },
+ { "name": "nu", "type": "D", "info": "@latex{\\nu}" },
+ { "name": "qx", "type": "D", "info": "@latex{x}-component of virtual photon momentum @latex{q}" },
+ { "name": "qy", "type": "D", "info": "@latex{y}-component of virtual photon momentum @latex{q}" },
+ { "name": "qz", "type": "D", "info": "@latex{z}-component of virtual photon momentum @latex{q}" },
+ { "name": "qE", "type": "D", "info": "@latex{E}-component of virtual photon momentum @latex{q}" },
+ { "name": "beamPz", "type": "D", "info": "beam momentum @latex{z}-component (GeV)" },
+ { "name": "targetM", "type": "D", "info": "target mass (GeV)" }
+ ]
+ },
+ {
+ "name": "physics::SingleHadronKinematics",
+ "algorithm": "physics::SingleHadronKinematics",
+ "group": 30000,
+ "item": 3,
+ "info": "",
+ "entries": [
+ { "name": "pindex", "type": "S", "info": "`REC::Particle` row (`pindex`) of the hadron" },
+ { "name": "pdg", "type": "I", "info": "PDG code of the hadron" },
+ { "name": "z", "type": "D", "info": "@latex{z}: Momentum fraction of the fragmenting parton carried by the hadron" },
+ { "name": "PhPerp", "type": "D", "info": "@latex{P_h^\\perp}: transverse momentum of the hadron in the @latex{\\perp}-frame (transverse to @latex{\\vec{q}})" },
+ { "name": "MX2", "type": "D", "info": "@latex{M_X^2(ehX)}: Missing mass squared of the hadron" },
+ { "name": "xF", "type": "D", "info": "@latex{x_F}: Feynman-x of the hadron" },
+ { "name": "yB", "type": "D", "info": "@latex{y_{h,B}}: Breit frame rapidity of the hadron" },
+ { "name": "phiH", "type": "D", "info": "@latex{\\phi_h}: @latex{q}-azimuthal angle between the lepton-scattering plane and the @latex{\\vec{q}\\times\\vec{P}_h} plane; if the value is `tools::UNDEF`, the calculation failed" },
+ { "name": "xi", "type": "D", "info": "@latex{\\xi_h}: Longitudinal momentum fraction of the nucleon carried by the hadron" }
+ ]
+ },
+ {
+ "name": "physics::DihadronKinematics",
+ "algorithm": "physics::DihadronKinematics",
+ "group": 30000,
+ "item": 4,
+ "info": "",
+ "entries": [
+ { "name": "pindex_a", "type": "S", "info": "`REC::Particle` row (`pindex`) of hadron A" },
+ { "name": "pindex_b", "type": "S", "info": "`REC::Particle` row (`pindex`) of hadron B" },
+ { "name": "pdg_a", "type": "I", "info": "PDG code of hadron A" },
+ { "name": "pdg_b", "type": "I", "info": "PDG code of hadron B" },
+ { "name": "Mh", "type": "D", "info": "@latex{M_h}: Invariant mass of the dihadron" },
+ { "name": "z", "type": "D", "info": "@latex{z}: Momentum fraction of the fragmenting parton carried by the dihadron" },
+ { "name": "PhPerp", "type": "D", "info": "@latex{P_h^\\perp}: transverse momentum of the dihadron in the @latex{\\perp}-frame (transverse to @latex{\\vec{q}})" },
+ { "name": "MX2", "type": "D", "info": "@latex{M_X^2(ehhX)}: Missing mass squared of the dihadron" },
+ { "name": "xF", "type": "D", "info": "@latex{x_F}: Feynman-x of the dihadron" },
+ { "name": "yB", "type": "D", "info": "@latex{y_{h,B}}: Breit frame rapidity of the dihadron" },
+ { "name": "phiH", "type": "D", "info": "@latex{\\phi_h}: @latex{q}-azimuthal angle between the lepton-scattering plane and the @latex{\\vec{q}\\times\\vec{P}_h} plane; if the value is `tools::UNDEF`, the calculation failed" },
+ { "name": "phiR", "type": "D", "info": "@latex{\\phi_R}: @latex{q}-azimuthal angle between the lepton-scattering plane and dihadron plane; if the value is `tools::UNDEF`, the calculation failed" },
+ { "name": "theta", "type": "D", "info": "@latex{\\theta}: The 'decay' angle of hadron A in the dihadron rest frame, with respect; to the dihadron momentum direction" }
+ ]
+ },
+ {
+ "name": "physics::Depolarization",
+ "algorithm": "physics::Depolarization",
+ "group": 30000,
+ "item": 5,
+ "info": "",
+ "entries": [
+ { "name": "epsilon", "type": "D", "info": "@latex{\\varepsilon(Q^2, x, y)}, the ratio of transverse and longitudinal photon flux" },
+ { "name": "A", "type": "D", "info": "depolarization factor @latex{A(\\varepsilon, y)}" },
+ { "name": "B", "type": "D", "info": "depolarization factor @latex{B(\\varepsilon, y)}" },
+ { "name": "C", "type": "D", "info": "depolarization factor @latex{C(\\varepsilon, y)}" },
+ { "name": "V", "type": "D", "info": "depolarization factor @latex{V(\\varepsilon, y)}" },
+ { "name": "W", "type": "D", "info": "depolarization factor @latex{W(\\varepsilon, y)}" }
+ ]
+ }
+]
diff --git a/src/iguana/bankdefs/meson.build b/src/iguana/bankdefs/meson.build
new file mode 100644
index 00000000..664ec46d
--- /dev/null
+++ b/src/iguana/bankdefs/meson.build
@@ -0,0 +1,20 @@
+bankdef_json = files('iguana.json')
+
+prog_bankgen_sources = files('bankgen.py')
+prog_bankgen = find_program(prog_bankgen_sources)
+
+# generate BankDefs.{h,cc} from the JSON data model file
+bankdef_tgt = custom_target(
+ 'bankdefs',
+ input: [
+ bankdef_json,
+ prog_bankgen_sources,
+ ],
+ output: [ 'BankDefs.h', 'BankDefs.cc' ],
+ command: [ prog_bankgen, '@INPUT0@', '@OUTDIR@/BankDefs' ],
+ install: true,
+ install_dir: [ get_option('includedir') / meson.project_name() / 'bankdefs', false ],
+)
+
+# install the JSON data model file; iguana won't need it, but it can be useful for user reference
+install_data(bankdef_json, install_dir: project_etc / 'bankdefs' / 'hipo4')