use super::helpers::{self, ConvFuns, ConvoluteMode};
use super::{GlobalConfiguration, Subcommand};
use anyhow::Result;
use clap::{Parser, ValueHint};
use prettytable::{Row, cell};
use std::path::PathBuf;
use std::process::ExitCode;
#[derive(Parser)]
pub struct Opts {
#[arg(value_hint = ValueHint::FilePath)]
input: PathBuf,
conv_funs: ConvFuns,
#[arg(long, short)]
absolute: bool,
#[arg(long, short)]
integrated: bool,
#[arg(
conflicts_with = "absolute",
long,
num_args = 1,
short,
value_delimiter = ',',
value_parser = helpers::parse_order
)]
normalize: Vec<(u8, u8)>,
#[arg(default_value_t = 7, long, value_name = "ABS")]
digits_abs: usize,
#[arg(default_value_t = 2, long, value_name = "REL")]
digits_rel: usize,
}
impl Subcommand for Opts {
fn run(&self, cfg: &GlobalConfiguration) -> Result<ExitCode> {
let grid = helpers::read_grid(&self.input)?;
let mut conv_funs = helpers::create_conv_funs(&self.conv_funs)?;
let mut orders: Vec<_> = grid
.orders()
.iter()
.filter(|order| (order.logxir == 0) && (order.logxif == 0))
.collect();
orders.sort();
let orders = orders;
let limits = helpers::convolve_limits(
&grid,
&[],
if self.integrated {
ConvoluteMode::Integrated
} else {
ConvoluteMode::Normal
},
);
let results: Vec<Vec<f64>> = orders
.iter()
.map(|order| {
helpers::convolve(
&grid,
&mut conv_funs,
&self.conv_funs.conv_types,
&[(order.alphas, order.alpha)],
&[],
&[],
1,
if self.integrated {
ConvoluteMode::Integrated
} else {
ConvoluteMode::Normal
},
cfg,
)
})
.collect();
let lo_power = {
let order = orders.first().unwrap();
order.alphas + order.alpha
};
let (x, y_label, y_unit) = helpers::labels_and_units(&grid, self.integrated);
let mut title = Row::empty();
title.add_cell(cell!(c->"b"));
for (x_label, x_unit) in x {
let mut cell = cell!(c->format!("{x_label}\n[{x_unit}]"));
cell.set_hspan(2);
title.add_cell(cell);
}
title.add_cell(cell!(c->format!("{y_label}\n[{y_unit}]")));
for order in &orders {
title.add_cell(cell!(c->format!("O(as^{} a^{})\n[{}]", order.alphas, order.alpha, if self.absolute { y_unit } else { "%" })));
}
let mut table = helpers::create_table();
table.set_titles(title);
for (bin, limits) in limits.iter().enumerate() {
let row = table.add_empty_row();
row.add_cell(cell!(r->format!("{bin}")));
for (left, right) in limits {
row.add_cell(cell!(r->format!("{left}")));
row.add_cell(cell!(r->format!("{right}")));
}
row.add_cell(cell!(r->format!("{:.*e}", self.digits_abs,
results.iter().fold(0.0, |value, results| value + results[bin]))));
let mut normalization = 0.0;
for (index, order) in orders.iter().enumerate() {
if (self.normalize.is_empty() && ((order.alphas + order.alpha) == lo_power))
|| (self.normalize.contains(&(order.alphas, order.alpha)))
{
normalization += results[index][bin];
}
}
for result in results.iter().map(|vec| vec[bin]) {
if self.absolute {
row.add_cell(cell!(r->format!("{:.*e}", self.digits_abs, result)));
} else {
row.add_cell(
cell!(r->format!("{:.*}", self.digits_rel, result / normalization * 100.0)),
);
}
}
}
table.printstd();
Ok(ExitCode::SUCCESS)
}
}