diff --git a/CHANGELOG.md b/CHANGELOG.md index 2399b8e2..06f359ee 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,9 +9,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added -- added `Grid::dedup_channels` and the C function - `pineappl_grid_dedup_channels` to detect equal subgrids and reduce the space - requirements of a grid +- added `Grid::dedup_channels`, the C function `pineappl_grid_dedup_channels` + the new switch `--dedup-channels` to the CLI to detect equal subgrids and + reduce the space requirements of a grid - added a new panel `double_ratio_pdf` to the `pineappl plot` tool - added a Python binding for the `Grid::merge` method diff --git a/pineappl_cli/src/write.rs b/pineappl_cli/src/write.rs index d311e66a..bdb2f55e 100644 --- a/pineappl_cli/src/write.rs +++ b/pineappl_cli/src/write.rs @@ -32,6 +32,7 @@ pub struct Opts { enum OpsArg { Cc1(bool), Cc2(bool), + DedupChannels(i64), DeleteBins(Vec>), DeleteKey(String), MergeBins(Vec>), @@ -101,6 +102,21 @@ impl FromArgMatches for MoreArgs { }); } } + "dedup_channels" => { + let arguments: Vec> = matches + .remove_occurrences(&id) + .unwrap() + .map(Iterator::collect) + .collect(); + + for (index, arg) in indices.into_iter().zip(arguments.into_iter()) { + assert_eq!(arg.len(), 1); + args[index] = Some(match id.as_str() { + "dedup_channels" => OpsArg::DedupChannels(arg[0]), + _ => unreachable!(), + }); + } + } "delete_key" | "remap" => { let arguments: Vec> = matches .remove_occurrences(&id) @@ -235,6 +251,17 @@ impl Args for MoreArgs { .value_name("ENABLE") .value_parser(clap::value_parser!(bool)), ) + .arg( + Arg::new("dedup_channels") + .action(ArgAction::Append) + .default_missing_value("64") + .help("Deduplicate channels assuming numbers differing by ULPS are the same") + .long("dedup-channels") + .num_args(0..=1) + .require_equals(true) + .value_name("ULPS") + .value_parser(value_parser!(i64)), + ) .arg( Arg::new("delete_bins") .action(ArgAction::Append) @@ -443,6 +470,9 @@ impl Subcommand for Opts { grid.set_key_value("initial_state_2", &initial_state_2.to_string()); grid.set_lumis(lumis); } + OpsArg::DedupChannels(ulps) => { + grid.dedup_channels(*ulps); + } OpsArg::DeleteBins(ranges) => { grid.delete_bins(&ranges.iter().flat_map(|r| r.clone()).collect::>()) } diff --git a/pineappl_cli/tests/write.rs b/pineappl_cli/tests/write.rs index c3119496..e84b3b17 100644 --- a/pineappl_cli/tests/write.rs +++ b/pineappl_cli/tests/write.rs @@ -12,6 +12,7 @@ Arguments: Options: --cc1[=] Charge conjugate the first initial state [possible values: true, false] --cc2[=] Charge conjugate the second initial state [possible values: true, false] + --dedup-channels[=] Deduplicate channels assuming numbers differing by ULPS are the same --delete-bins Delete bins with the specified indices --delete-key Delete an internal key-value pair --merge-bins Merge specific bins together @@ -30,6 +31,27 @@ Options: -h, --help Print help "; +const CHANNEL_STR: &str = "l entry entry +-+------------+------------ +0 1 × ( 2, -1) 1 × ( 4, -3) +1 1 × (21, -3) 1 × (21, -1) +2 1 × (22, -3) 1 × (22, -1) +3 1 × ( 2, 21) 1 × ( 4, 21) +4 1 × ( 2, 22) 1 × ( 4, 22) +"; + +const DEDUP_CHANNEL_DIFF_STR: &str = "b x1 O(as^0 a^2) O(as^0 a^3) O(as^1 a^2) +-+----+----+-----------+-----------+-------+-------------+-------------+-------+-----------+-----------+------- +0 2 2.25 6.5070305e2 6.5070305e2 0.000e0 -7.8692484e0 -7.8692484e0 0.000e0 1.1175729e2 1.1175729e2 0.000e0 +1 2.25 2.5 5.9601236e2 5.9601236e2 0.000e0 -6.5623495e0 -6.5623495e0 0.000e0 1.0083341e2 1.0083341e2 0.000e0 +2 2.5 2.75 5.1561247e2 5.1561247e2 0.000e0 -5.2348261e0 -5.2348261e0 0.000e0 8.9874343e1 8.9874343e1 0.000e0 +3 2.75 3 4.1534629e2 4.1534629e2 0.000e0 -3.7590420e0 -3.7590420e0 0.000e0 7.3935106e1 7.3935106e1 0.000e0 +4 3 3.25 3.0812719e2 3.0812719e2 0.000e0 -2.5871885e0 -2.5871885e0 0.000e0 5.6414554e1 5.6414554e1 0.000e0 +5 3.25 3.5 2.0807482e2 2.0807482e2 0.000e0 -1.6762487e0 -1.6762487e0 0.000e0 3.9468336e1 3.9468336e1 0.000e0 +6 3.5 4 9.6856769e1 9.6856769e1 0.000e0 -8.1027456e-1 -8.1027456e-1 0.000e0 1.9822014e1 1.9822014e1 0.000e0 +7 4 4.5 2.2383492e1 2.2383492e1 0.000e0 -2.2022770e-1 -2.2022770e-1 0.000e0 5.3540011e0 5.3540011e0 0.000e0 +"; + const DEFAULT_STR: &str = "b etal dsig/detal [] [pb] -+----+----+----------- @@ -546,6 +568,49 @@ fn split_lumi() { .stdout(SPLIT_LUMI_STR); } +#[test] +fn dedup_channels() { + let output = NamedTempFile::new("dedup-channels.pineappl.lz4").unwrap(); + + Command::cargo_bin("pineappl") + .unwrap() + .args([ + "write", + "--split-lumi", + "--dedup-channels", + "../test-data/LHCB_WP_7TEV.pineappl.lz4", + output.path().to_str().unwrap(), + ]) + .assert() + .success() + .stdout(""); + + Command::cargo_bin("pineappl") + .unwrap() + .args([ + "--silence-lhapdf", + "diff", + "../test-data/LHCB_WP_7TEV.pineappl.lz4", + output.path().to_str().unwrap(), + "NNPDF31_nlo_as_0118_luxqed", + ]) + .assert() + .success() + .stdout(DEDUP_CHANNEL_DIFF_STR); + + Command::cargo_bin("pineappl") + .unwrap() + .args([ + "--silence-lhapdf", + "read", + "--lumis", + output.path().to_str().unwrap(), + ]) + .assert() + .success() + .stdout(CHANNEL_STR); +} + #[test] fn upgrade() { let output = NamedTempFile::new("upgraded.pineappl.lz4").unwrap();