Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: use RCDB to get the beam energy #256

Draft
wants to merge 9 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion doc/gen/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -21,5 +21,5 @@ doc_tgt = custom_target(
build_by_default: true,
command: [ prog_doxygen, doxyfile ],
install: true,
install_dir: join_paths(get_option('datadir'), 'doc', meson.project_name()),
install_dir: get_option('datadir') / 'doc' / meson.project_name(),
)
2 changes: 1 addition & 1 deletion doc/ifarm.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
```bash
meson/resolve-dependencies.py --help # prints the usage guide
```
Use the `--env` option and set the resulting environment variables.
Use the resulting arguments when setting up or configuring your build directory.

## Build and Install

Expand Down
25 changes: 20 additions & 5 deletions doc/setup.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ The following sections (🟩) list the dependencies and how to obtain them.
> git log --tags --decorate --simplify-by-decoration --oneline # list all the tags (latest first)
> git checkout 1.0.0 # checkout the tag '1.0.0'
> ```
<!--`-->

### 🟩 `meson`: Build system used by Iguana
<https://mesonbuild.com/>
Expand Down Expand Up @@ -63,6 +64,16 @@ cmake --install build-hipo
- After installation, depending on ROOT's installation prefix you may also need to set your environment so
ROOT may be found; this is typically done by `source /path/to/root/bin/thisroot.sh`

### 🟩 Optional: `RCDB`: Run Condition Database
<https://github.com/JeffersonLab/rcdb>
- RCDB is optional, but needed for algorithms that use, _e.g._, the beam energy
- You do not need to compile RCDB, just clone the repository

> [!NOTE]
> As of July 2024, the most recent tagged version of RCDB is quite far behind
> the current main branch, so you may just use the latest main branch version
> (`master`).

<a name="building"></a>
## 🟠 Building and Installing

Expand All @@ -80,10 +91,9 @@ Use [`meson/resolve-dependencies.py`](../meson/resolve-dependencies.py) to help
/path/to/iguana-source/meson/resolve-dependencies.py --help # prints the usage guide
```
Tell it where your dependencies are installed and it will tell you the build options
that you need for Step 2; you can also choose to write those build options to an INI (native) file.
that you need for Step 2.

Alternatively, you may use environment variables; see the [note on dependency
resolution](dependency_resolution.md) for more general guidance.
See the [note on dependency resolution](dependency_resolution.md) for more general guidance.


### 🟩 Step 2: Generate a build directory
Expand Down Expand Up @@ -111,16 +121,20 @@ All build options, their current values, and their descriptions may be found by
meson configure # outputs in a pager (`less`); you may scroll, or press 'q' to quit
meson configure --no-pager # do not use a pager
```
**but that's a _lot_ of text!** The _most important_ build options are near the bottom, under **"Project options"**.
**but that's a _lot_ of text!** The _most important_ build options are under the **"Project options"**
sections: the first such section is for `iguana`, and the rest are for subprojects (_e.g._, `rcdb`).

Alternatively, see [`meson.options`](/meson.options) for the list of project options, and some more details.
Alternatively, see [`meson.options`](/meson.options) for the list of `iguana` project options, and some more details.

To set any build option, _e.g._ `install_examples` to `true`, run:
```bash
meson configure -Dinstall_examples=true
```
You can add as many `-D<option>=<value>` arguments as you need.

> [!NOTE]
> To set a subproject's option, you must prefix the subproject name. For example, for `rcdb`, use `-Drcdb:<option>=<value>`.

### 🟩 Step 4: Compile and Install
Now compile and install Iguana:
```bash
Expand All @@ -138,6 +152,7 @@ meson install # installs Iguana to your prefix (build option 'prefix')
> meson setup --wipe /path/to/iguana-source
> ```
> This will preserve your build options; then try to rebuild.
<!--`-->


<a name="env"></a>
Expand Down
25 changes: 19 additions & 6 deletions meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,14 @@ add_languages('fortran', native: false, required: get_option('bind_fortran'))
pkg = import('pkgconfig')
fs = import('fs')

# build subprojects
rcdb_subproj = subproject(
'rcdb',
default_options: {
'home': run_command('meson' / 'get-env.py', 'RCDB_HOME', check: false).stdout().strip(),
}
)

# resolve dependencies
# NOTE: those that are typically installed by package managers should use `meson/minimum-version.sh`
fmt_dep = dependency(
Expand All @@ -45,13 +53,15 @@ ROOT_dep = dependency(
method: 'cmake',
version: run_command('meson' / 'minimum-version.sh', 'ROOT', check: true).stdout().strip(),
)
rcdb_dep = dependency('rcdb', fallback: ['rcdb', 'rcdb_dep'], required: false)

# list of dependencies
# FIXME: for users which use LD_LIBRARY_PATH, we should try to keep this list
# ordered such that the ones users are *least likely* to try to build
# themselves are listed last (see FIXME in meson/this_iguana.sh.in)
# NOTE: omit ROOT (handled differently, and most ROOT users already have it in their environment)
dep_list = []
foreach dep : [ hipo_dep, fmt_dep, yamlcpp_dep, ROOT_dep ]
foreach dep : [ hipo_dep, fmt_dep, yamlcpp_dep, rcdb_dep ]
if dep.found()
dep_list += dep
endif
Expand All @@ -64,9 +74,6 @@ dep_pkgconfig_dirs = []
foreach dep : dep_list

# get library and include dirs
if dep.name() == 'ROOT'
continue # skip ROOT (handled differently, and most ROOT users already have it in their environment)
endif
if dep.type_name() == 'pkgconfig'
libdirs = [ dep.get_variable(pkgconfig: 'libdir') ]
incdirs = [ dep.get_variable(pkgconfig: 'includedir') ]
Expand All @@ -77,7 +84,13 @@ foreach dep : dep_list
endforeach
incdirs = ROOT_dep.get_variable(cmake: 'PACKAGE_INCLUDE_DIRS').split(';')
else
error('Cannot determine how dependency "' + dep.name() + '" was found')
name = dep.get_variable(internal: 'name', default_value: dep.name())
if name == 'rcdb'
incdirs = [ dep.get_variable(internal: 'includedir') ]
else
warning(f'Unknown dependency "@name@"')
continue
endif
endif

# append to `dep_*_dirs` arrays, uniquely
Expand Down Expand Up @@ -137,7 +150,7 @@ endif
# general project vars
project_inc = include_directories('src')
project_libs = []
project_deps = declare_dependency(dependencies: [ fmt_dep, yamlcpp_dep, hipo_dep ]) # do NOT include ROOT here
project_deps = declare_dependency(dependencies: dep_list) # do NOT include ROOT here
project_etc = get_option('sysconfdir') / meson.project_name()
project_test_env = environment()
project_pkg_vars = [
Expand Down
21 changes: 21 additions & 0 deletions meson/get-env.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
#!/usr/bin/env python3

# Meson forbids custom environment variables; however, our primary deployment
# platform uses Environment Modules, which heavily relies on environment
# variables. Assuming most of our users don't want to worry about this
# constraint, this script grants Meson access to certain environment variables
# from dependencies that need them.
#
# Build options are provided which take prioroty over such environment
# variables; usage of this script should ONLY be a last resort.
#
# Details: https://github.com/mesonbuild/meson/issues/9

from sys import argv, exit
from os import environ

if(len(argv) != 2):
exit(1)
if argv[1] not in environ:
exit(1)
print(environ[argv[1]])
103 changes: 40 additions & 63 deletions meson/resolve-dependencies.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,21 +22,20 @@ class Formatter(argparse.ArgumentDefaultsHelpFormatter, argparse.RawDescriptionH
parser_deps.add_argument('--fmt', default=SYSTEM_ASSUMPTION, type=str, help='path to `fmt` installation')
parser_deps.add_argument('--yaml', default=SYSTEM_ASSUMPTION, type=str, help='path to `yaml-cpp` installation')
parser_deps.add_argument('--root', default=SYSTEM_ASSUMPTION, type=str, help='path to `ROOT` installation')
parser_deps.add_argument('--rcdb', default='$RCDB_HOME', type=str, help='path to `RCDB` installation')
parser_output = parser.add_argument_group('output control')
parser_output.add_argument('--cli', default=False, action=argparse.BooleanOptionalAction, help='only print the `meson` CLI options, and nothing else')
parser_output.add_argument('--env', default=False, action=argparse.BooleanOptionalAction, help='generate environment variable `export` commands instead')
parser_output.add_argument('--ini', default=NOT_USED, type=str, help='if set, generate an INI file (meson native file) with this name; you may then use it with `meson setup --native-file=_____`')
parser_output.add_argument('--verbose', default=False, action=argparse.BooleanOptionalAction, help='verbose output')
args = parser.parse_args()

# verbosity
verbose = not args.cli
def print_verbose(message):
if(verbose):
if(args.verbose):
print(message)

# functions to set dependency paths
pkg_config_path = set()
cmake_prefix_path = set()
extra_args = []
def use_system(dep):
print_verbose(f'{dep}: {SYSTEM_ASSUMPTION}')
def use_pkg_config(dep, pc_file, arg):
Expand All @@ -63,71 +62,49 @@ def use_cmake(dep, arg):
cmake_prefix_path.add(path)
else:
use_system(dep)
def use_env_var(dep, build_var_name, user_val, env_var_name):
if(user_val == f'${env_var_name}'):
if env_var_name in os.environ:
print_verbose(f'{dep}: using environment variable "{env_var_name}" for build variable "{build_var_name}"')
extra_args.append([build_var_name, os.environ[env_var_name]])
else:
print(f'{dep}: you did not specify where {dep} is found, and the fallback environment variable "${env_var_name}" is not set; {dep} will be ignored', file=sys.stderr)
else:
print_verbose(f'{dep}: using user value "{user_val}" for build variable "{build_var_name}"')
extra_args.append([build_var_name, user_val])

# resolve dependencies #########################
use_pkg_config('hipo', 'hipo4.pc', args.hipo)
use_pkg_config('fmt', 'fmt.pc', args.fmt)
use_pkg_config('yaml', 'yaml-cpp.pc', args.yaml)
use_cmake('ROOT', args.root)
use_env_var('rcdb', 'rcdb:home', args.rcdb, 'RCDB_HOME')
################################################


# generate a native file
if(args.ini!=NOT_USED):
def ini_string_arr(arr):
contents = ','.join(map(lambda s: f'\'{s}\'', arr))
return f'[{contents}]'
ini_config = ConfigParser(allow_no_value=True)
ini_config.add_section('built-in options')
if(len(cmake_prefix_path) > 0):
ini_config.set('built-in options', 'cmake_prefix_path', ini_string_arr(cmake_prefix_path))
if(len(pkg_config_path) > 0):
ini_config.set('built-in options', 'pkg_config_path', ini_string_arr(pkg_config_path))
with open(args.ini, 'w') as fp:
ini_config.write(fp)

# generate CLI options
if(verbose or args.cli):
if(len(pkg_config_path)==0 and len(cmake_prefix_path)==0):
print_verbose(textwrap.dedent(f'''
==========================================================================================
All of your dependencies are assumed to be in the system default locations.
- If they are not, please run:
{sys.argv[0]} --help
- Otherwise, you do not need to set or modify any build options for dependency resolution.
==========================================================================================
'''))
exit(0)
else:
if(args.env):
print_verbose(textwrap.dedent('''
==================================================
| Here are the environment variables you need: |
==================================================
'''))
else:
print_verbose(textwrap.dedent('''
===============================================
| Here are the build options that you need: |
===============================================
'''))
cli_opts = []
if(len(pkg_config_path) > 0):
if(args.env):
cli_opts.append(f'export PKG_CONFIG_PATH={":".join(pkg_config_path)}' + '${PKG_CONFIG_PATH:+:${PKG_CONFIG_PATH}}')
else:
cli_opts.append(f'--pkg-config-path={",".join(pkg_config_path)}')
if(len(cmake_prefix_path) > 0):
if(args.env):
cli_opts.append(f'export CMAKE_PREFIX_PATH={":".join(cmake_prefix_path)}' + '${CMAKE_PREFIX_PATH:+:${CMAKE_PREFIX_PATH}}')
else:
cli_opts.append(f'--cmake-prefix-path={",".join(cmake_prefix_path)}')
if(args.ini==NOT_USED):
if(args.env):
for cli_opt in cli_opts:
print(cli_opt)
else:
print(f'{" ".join(cli_opts)}')
else:
print(f'--native-file={args.ini}')
print_verbose('\n')
if(len(pkg_config_path)==0 and len(cmake_prefix_path)==0 and len(extra_args)==0):
print_verbose(textwrap.dedent(f'''
==========================================================================================
All of your dependencies are assumed to be in the system default locations.
- If they are not, please run:
{sys.argv[0]} --help
- Otherwise, you do not need to set or modify any build options for dependency resolution.
==========================================================================================
'''))
else:
print_verbose(textwrap.dedent('''
===============================================
| Here are the build options that you need: |
===============================================
'''))
cli_opts = []
if(len(pkg_config_path) > 0):
cli_opts.append(f'--pkg-config-path={",".join(pkg_config_path)}')
if(len(cmake_prefix_path) > 0):
cli_opts.append(f'--cmake-prefix-path={",".join(cmake_prefix_path)}')
if(len(extra_args) > 0):
for extra_arg in extra_args:
cli_opts.append(f'-D{extra_arg[0]}={extra_arg[1]}')
print(f'{" ".join(cli_opts)}')
print_verbose('\n')
2 changes: 1 addition & 1 deletion src/chameleon/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,5 @@ chameleon_sources = files(
'src' / 'bind_c.rb',
)

ruby = find_program('ruby', version: '>=3.0.0', required: use_chameleon)
ruby = find_program('ruby', version: '>=2.7.4', required: use_chameleon)
chameleon_gen = find_program(chameleon_sources[0], required: use_chameleon)
11 changes: 7 additions & 4 deletions src/iguana/algorithms/physics/InclusiveKinematics/Algorithm.cc
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,13 @@ namespace iguana::physics {

// parse config file
ParseYAMLConfig();
o_runnum = GetCachedOption<int>("runnum").value_or(0); // FIXME: should be set from RUN::conig
o_runnum = GetCachedOption<int>("runnum").value_or(6666); // FIXME: should be set from RUN::conig
// get the beam energy
m_rcdb = std::make_unique<RCDBReader>("RCDB|" + GetName());
m_beam_energy = m_rcdb->GetBeamEnergy(o_runnum);
m_log->Error("Beam energy = {}", m_beam_energy);

// get initial state configuration
o_beam_energy = GetOptionScalar<double>("beam_energy", {"initial_state", GetConfig()->InRange("runs", o_runnum), "beam_energy"});
o_beam_direction = GetOptionVector<double>("beam_direction", {"initial_state", GetConfig()->InRange("runs", o_runnum), "beam_direction"});
o_beam_particle = GetOptionScalar<std::string>("beam_particle", {"initial_state", GetConfig()->InRange("runs", o_runnum), "beam_particle"});
o_target_particle = GetOptionScalar<std::string>("target_particle", {"initial_state", GetConfig()->InRange("runs", o_runnum), "target_particle"});
Expand Down Expand Up @@ -86,7 +89,7 @@ namespace iguana::physics {
o_beam_direction = {0.0, 0.0, 1.0};
}
auto dir_mag = std::hypot(o_beam_direction[0], o_beam_direction[1], o_beam_direction[2]);
auto beam_p = std::sqrt(std::pow(o_beam_energy, 2) - std::pow(m_beam.mass, 2));
auto beam_p = std::sqrt(std::pow(m_beam_energy, 2) - std::pow(m_beam.mass, 2));
if(dir_mag > 0) {
m_beam.px = o_beam_direction[0] * beam_p / dir_mag;
m_beam.py = o_beam_direction[1] * beam_p / dir_mag;
Expand All @@ -102,7 +105,7 @@ namespace iguana::physics {

// print the configuration
m_log->Debug(Logger::Header("CONFIGURATION"));
m_log->Debug("{:>30}: {}", "beam energy", o_beam_energy);
m_log->Debug("{:>30}: {}", "beam energy", m_beam_energy);
m_log->Debug("{:>30}: {}, mass = {}, p = ({}, {}, {})", "beam particle", o_beam_particle, m_beam.mass, m_beam.px, m_beam.py, m_beam.pz);
m_log->Debug("{:>30}: {}, mass = {}, p = ({}, {}, {})", "target particle", o_target_particle, m_target.mass, m_target.px, m_target.py, m_target.pz);
m_log->Debug("{:>30}: {}", "reconstruction method", method_reconstruction_str);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

#include "iguana/algorithms/Algorithm.h"
#include "iguana/algorithms/TypeDefs.h"
#include "iguana/services/RCDBReader.h"

namespace iguana::physics {

Expand Down Expand Up @@ -89,7 +90,6 @@ namespace iguana::physics {

// config options
int o_runnum;
double o_beam_energy;
std::vector<double> o_beam_direction;
std::string o_beam_particle;
std::string o_target_particle;
Expand All @@ -108,6 +108,8 @@ namespace iguana::physics {
};
particle_t m_beam;
particle_t m_target;
double m_beam_energy;
std::unique_ptr<RCDBReader> m_rcdb;
};

}
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
physics::InclusiveKinematics:

initial_state: # FIXME: add run ranges
initial_state:
- default:
beam_energy: 10.6
beam_direction: [ 0.0, 0.0, 1.0 ]
beam_particle: electron
target_particle: proton
Expand Down
Loading