Конвейер «нтуплы → workspace»
NextStat предоставляет полный конвейер от ROOT-нтуплов до HistFactory workspace'ов, заменяя TRExFitter нативной Rust-реализацией, которая в ~8.5× быстрее uproot+numpy. Зависимость от ROOT C++ не требуется.
Builder API на Rust
use ns_translate::NtupleWorkspaceBuilder;
let ws = NtupleWorkspaceBuilder::new()
.ntuple_path("ntuples/")
.tree_name("events")
.measurement("meas", "mu")
.add_channel("SR", |ch| {
ch.variable("mbb")
.binning(&[0., 50., 100., 150., 200., 300.])
.selection("njet >= 4 && pt > 25.0")
.data_file("data.root")
.add_sample("signal", |s| {
s.file("ttH.root")
.weight("weight_mc * weight_sf")
.normfactor("mu")
})
.add_sample("background", |s| {
s.file("ttbar.root")
.weight("weight_mc * weight_sf")
.normsys("bkg_norm", 0.9, 1.1)
.weight_sys("jes", "weight_jes_up", "weight_jes_down")
.tree_sys("jer", "jer_up.root", "jer_down.root")
.staterror()
})
})
.build()?; // → Workspace (тот же тип, что и pyhf JSON)Движок выражений
Крейт ns-rootвключает компилируемый движок выражений для строковых селекций и весов:
use ns_root::CompiledExpr;
let expr = CompiledExpr::compile("pt > 25.0 && abs(eta) < 2.5")?;Низкоуровневый доступ к TTree
use ns_root::RootFile;
let file = RootFile::open("data.root")?;
let tree = file.get_tree("events")?;
// Столбцовый доступ
let pt: Vec<f64> = file.branch_data(&tree, "pt")?;
let eta: Vec<f64> = file.branch_data(&tree, "eta")?;Поддерживаемые систематики
- normsys — Нормировочные систематики (факторы up/down)
- weight_sys — Shape-систематики на основе весов
- tree_sys — Shape-систематики через альтернативные деревья
- staterror — Barlow-Beeston lite статистические неопределённости
