NextStatNextStat

Конвейер «нтуплы → 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 статистические неопределённости