-
Notifications
You must be signed in to change notification settings - Fork 3
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
Generalize the APPLgrid exporter #285
base: master
Are you sure you want to change the base?
Changes from 2 commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,7 @@ | ||
use anyhow::{anyhow, bail, Result}; | ||
use cxx::{let_cxx_string, UniquePtr}; | ||
use float_cmp::approx_eq; | ||
use itertools::Itertools; | ||
use ndarray::{s, Axis}; | ||
use pineappl::grid::{Grid, Order}; | ||
use pineappl::subgrid::{Mu2, Subgrid, SubgridParams}; | ||
|
@@ -18,32 +19,61 @@ fn reconstruct_subgrid_params(grid: &Grid, order: usize, bin: usize) -> Result<S | |
.subgrids() | ||
.slice(s![order, bin, ..]) | ||
.iter() | ||
.map(|subgrid| { | ||
.flat_map(|subgrid| { | ||
subgrid | ||
.mu2_grid() | ||
.iter() | ||
.into_iter() | ||
.map(|&Mu2 { ren, fac }| { | ||
if !approx_eq!(f64, ren, fac, ulps = 128) { | ||
bail!("subgrid has mur2 != muf2, which APPLgrid does not support"); | ||
} | ||
|
||
Ok(fac) | ||
}) | ||
.collect::<Result<Vec<_>>>() | ||
.collect_vec() | ||
}) | ||
.collect::<Result<_>>()?; | ||
let mut mu2_grid: Vec<_> = mu2_grid.into_iter().flatten().collect(); | ||
mu2_grid.dedup_by(|a, b| approx_eq!(f64, *a, *b, ulps = 128)); | ||
let mu2_grid = mu2_grid.as_slice(); | ||
|
||
if let &[fac] = mu2_grid { | ||
result.set_q2_bins(1); | ||
result.set_q2_max(fac); | ||
result.set_q2_min(fac); | ||
.collect::<Result<Vec<_>>>()? | ||
.into_iter() | ||
.sorted_unstable_by(|a, b| a.total_cmp(b)) | ||
.dedup_by(|&a, &b| approx_eq!(f64, a, b, ulps = 128)) | ||
.collect_vec(); | ||
|
||
let x_grid = grid | ||
.subgrids() | ||
.slice(s![order, bin, ..]) | ||
.iter() | ||
.flat_map(|subgrid| { | ||
[ | ||
subgrid.x1_grid().into_owned(), | ||
subgrid.x2_grid().into_owned(), | ||
] | ||
.into_iter() | ||
}) | ||
.flatten() | ||
.sorted_unstable_by(|a, b| a.total_cmp(b)) | ||
.dedup_by(|&a, &b| approx_eq!(f64, a, b, ulps = 128)) | ||
.collect_vec(); | ||
|
||
result.set_q2_bins(mu2_grid.len()); | ||
result.set_q2_min(*mu2_grid.first().unwrap()); | ||
result.set_q2_max(*mu2_grid.last().unwrap()); | ||
if mu2_grid.len() == 1 { | ||
result.set_q2_order(0); | ||
} else { | ||
// TODO: reconstruct the interpolation order. for now leave it as the default | ||
// result.set_q2_order(...); | ||
} | ||
|
||
result.set_x_bins(x_grid.len()); | ||
result.set_x_min(*x_grid.first().unwrap()); | ||
result.set_x_max(*x_grid.last().unwrap()); | ||
if x_grid.len() == 1 { | ||
result.set_x_order(0); | ||
} else { | ||
// TODO: reconstruct the interpolation order. for now leave it as the default | ||
// result.set_x_order(...); | ||
} | ||
|
||
// TODO: implement the general case | ||
Ok(result) | ||
} | ||
|
||
|
@@ -55,15 +85,9 @@ pub fn convert_into_applgrid( | |
let bin_info = grid.bin_info(); | ||
let dim = bin_info.dimensions(); | ||
|
||
if dim > 1 { | ||
bail!( | ||
"grid has {} dimensions, but APPLgrid only supports one-dimensional distributions", | ||
dim | ||
); | ||
} | ||
|
||
if bin_info.slices().len() != 1 { | ||
bail!("grid has non-consecutive bin limits, which APPLgrid does not support"); | ||
let integer_bin_limits = dim > 1 || bin_info.slices().len() > 1; | ||
if integer_bin_limits { | ||
println!("Info: APPLgrid only supports one-dimensional consecutive bin limits, so the bin limits will be set to [0, {}] in steps of 1, corresponding to the ordering given by `pineappl read --bins <GRID>`.", bin_info.bins()); | ||
} | ||
|
||
let lumis = grid.lumi().len(); | ||
|
@@ -100,11 +124,15 @@ pub fn convert_into_applgrid( | |
ffi::make_lumi_pdf(id, &combinations).into_raw(); | ||
|
||
let limits = &bin_info.limits(); | ||
let limits: Vec<_> = limits | ||
.iter() | ||
.map(|vec| vec[0].0) | ||
.chain(limits.last().map(|vec| vec[0].1)) | ||
.collect(); | ||
let limits = if integer_bin_limits { | ||
(0..=limits.len()).map(|x| x as f64).collect::<Vec<_>>() | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Here there's very likely a normalization factor missing. If you change the bin sizes you must correct the cross sections. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You're right, thanks. Does APPLgrid also divide by the bin widths in the end? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. AFAICR yes! |
||
} else { | ||
limits | ||
.iter() | ||
.map(|vec| vec[0].0) | ||
.chain(limits.last().map(|vec| vec[0].1)) | ||
.collect_vec() | ||
}; | ||
|
||
let order_mask = Order::create_mask(grid.orders(), 3, 0, false); | ||
let orders_with_mask: Vec<_> = grid | ||
|
@@ -209,12 +237,12 @@ pub fn convert_into_applgrid( | |
.map(|&x1| { | ||
appl_x1 | ||
.iter() | ||
.position(|&x| approx_eq!(f64, x, x1, ulps = 128)) | ||
.position(|&x| approx_eq!(f64, x, x1, ulps = 512)) | ||
.map_or_else( | ||
|| { | ||
Err(anyhow!( | ||
"momentum fraction x1 = {} not found in APPLgrid", | ||
x1 | ||
"momentum fraction x1 = {} not found in APPLgrid, the closest is {}", | ||
x1, appl_x1.iter().min_by(|&a, &b| (a - x1).abs().total_cmp(&(b - x1).abs())).unwrap() | ||
)) | ||
}, | ||
|idx| Ok(idx.try_into().unwrap()), | ||
|
@@ -226,12 +254,13 @@ pub fn convert_into_applgrid( | |
.map(|&x2| { | ||
appl_x2 | ||
.iter() | ||
.position(|&x| approx_eq!(f64, x, x2, ulps = 128)) | ||
// .position(|&x| approx_eq!(f64, x, x2, ulps = 128, epsilon = 1e-12)) | ||
cschwan marked this conversation as resolved.
Show resolved
Hide resolved
|
||
.position(|&x| approx_eq!(f64, x, x2, ulps = 512)) | ||
.map_or_else( | ||
|| { | ||
Err(anyhow!( | ||
"momentum fraction x2 = {} not found in APPLgrid", | ||
x2 | ||
"momentum fraction x2 = {} not found in APPLgrid, the closest is {}", | ||
x2, appl_x2.iter().min_by(|&a, &b| (a - x2).abs().total_cmp(&(b - x2).abs())).unwrap() | ||
)) | ||
}, | ||
|idx| Ok(idx.try_into().unwrap()), | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This probably doesn't work quite as expected. APPLgrid stores different channels in a single
appl_igrid
, which has common parameter valuesNQ2
,NQ2min
,NQ2max
,NQorder
,Nx
,xmin
,xmax
,xorder
. This means that:SubgridParam
/ExtraSubgridParam
values we should error out, unless this is a DIS grid in which we ignore the second dimension. In PineAPPL the second dimension can be eitherx1
orx2
flat_map
should therefore probably be a simplemap
and we must make sure that for all channels the entries are the samemu_grid
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The
OPTIMIZE_SUBGRID_TYPE
optimization can change the ends of thex
andmu2
grid points, right? So I would check if the grid points are equal modulo some endpoints, and then use the union as thex
points that will be passed to APPLgrid?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This would address one point of it, yes. It'll get interesting if you've got a single channel with different minimums/maximums.