diff --git a/doc/gen/Doxyfile.in b/doc/gen/Doxyfile.in
index c923bc87..1385851b 100644
--- a/doc/gen/Doxyfile.in
+++ b/doc/gen/Doxyfile.in
@@ -965,10 +965,12 @@ WARN_LOGFILE =
INPUT = @top_srcdir@/src/ \
@top_builddir@/src/iguana/algorithms \
+ @top_builddir@/src/iguana/bankdefs \
@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 2159bb17..98c2262d 100644
--- a/doc/gen/mainpage.md
+++ b/doc/gen/mainpage.md
@@ -32,6 +32,9 @@ The algorithm types are defined based on what they do to HIPO bank data:
**Creator** | Create a new bank |
+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
+
Most algorithms are configurable:
- [**Algorithm Configuration Guide**](https://github.com/JeffersonLab/iguana/blob/main/doc/configuration.md)
diff --git a/meson.build b/meson.build
index 50a6bb97..9b2c97a0 100644
--- a/meson.build
+++ b/meson.build
@@ -209,6 +209,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..a559006a 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,31 @@ 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
+ 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'", bank_name));
}
///////////////////////////////////////////////////////////////////////////////
diff --git a/src/iguana/algorithms/Algorithm.h b/src/iguana/algorithms/Algorithm.h
index 1700ca5c..4c9e34cd 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 `BANK_DEFS`, which is generated at build time from `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/meson.build b/src/iguana/algorithms/meson.build
index 7ac67bcb..ecdd204a 100644
--- a/src/iguana/algorithms/meson.build
+++ b/src/iguana/algorithms/meson.build
@@ -105,6 +105,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/DihadronKinematics/Algorithm.cc b/src/iguana/algorithms/physics/DihadronKinematics/Algorithm.cc
index 0835c366..11d11a59 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 40cab186..2c2b9b2c 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}
diff --git a/src/iguana/algorithms/physics/InclusiveKinematics/Algorithm.cc b/src/iguana/algorithms/physics/InclusiveKinematics/Algorithm.cc
index 2d008db7..3d9920cc 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 c60c3e91..fead3fbb 100644
--- a/src/iguana/algorithms/physics/InclusiveKinematics/Algorithm.h
+++ b/src/iguana/algorithms/physics/InclusiveKinematics/Algorithm.h
@@ -7,34 +7,6 @@
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`
///
/// @begin_doc_algo{physics::InclusiveKinematics | Creator}
diff --git a/src/iguana/algorithms/physics/SingleHadronKinematics/Algorithm.cc b/src/iguana/algorithms/physics/SingleHadronKinematics/Algorithm.cc
index 47fb6fbb..58bb28cd 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 9405f5eb..ce0f3bd0 100644
--- a/src/iguana/algorithms/physics/SingleHadronKinematics/Algorithm.h
+++ b/src/iguana/algorithms/physics/SingleHadronKinematics/Algorithm.h
@@ -6,29 +6,6 @@
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`
///
/// @begin_doc_algo{physics::SingleHadronKinematics | Creator}
diff --git a/src/iguana/bankdefs/README.md b/src/iguana/bankdefs/README.md
new file mode 100644
index 00000000..73d565b4
--- /dev/null
+++ b/src/iguana/bankdefs/README.md
@@ -0,0 +1,5 @@
+# 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 the same format as the `coatjava` bank definitions and may be used as a reference; this `json` file is also installed in `etc/iguana/bankdefs/`.
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..a7a210c7
--- /dev/null
+++ b/src/iguana/bankdefs/iguana.json
@@ -0,0 +1,74 @@
+[
+ {
+ "name": "REC::Particle::Sector",
+ "group": 30000,
+ "item": 1,
+ "info": "",
+ "algorithm": "clas12::SectorFinder",
+ "entries": [
+ { "name": "pindex", "type": "S", "info": "row number in the particle bank" },
+ { "name": "sector", "type": "I", "info": "sector for this particle" }
+ ]
+ },
+ {
+ "name": "physics::InclusiveKinematics",
+ "group": 30000,
+ "item": 2,
+ "info": "",
+ "algorithm": "physics::InclusiveKinematics",
+ "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",
+ "group": 30000,
+ "item": 3,
+ "info": "",
+ "algorithm": "physics::SingleHadronKinematics",
+ "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",
+ "group": 30000,
+ "item": 4,
+ "info": "",
+ "algorithm": "physics::DihadronKinematics",
+ "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" }
+ ]
+ }
+]
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')