NextStatNextStat

Configuration Format Reference

stable

NextStat uses a block-based text configuration format for defining statistical analyses. The format is compatible with TRExFitter configs (common subset), but is a first-class NextStat feature — not a compatibility shim.

Quick Start

# NTUP mode: build workspace from ROOT ntuples
nextstat import trex-config --config analysis.config --output workspace.json

# HIST mode: import existing HistFactory export
nextstat import trex-config --config analysis.config --output workspace.json

# One-step: build histograms + workspace
nextstat build-hists --config analysis.config --out-dir output/

# Full pipeline via analysis spec (YAML)
nextstat run --config analysis.yaml

Syntax

# Comments: '#', '//', or '%' (quote-aware)
Key: Value
Key: "quoted value with # inside"

Region: SR
  Variable: mbb
  Binning: 0, 50, 100, 200

Sample: signal
  Type: SIGNAL
  File: data/signal.root
  • All keys are case-insensitive (ReadFrom, readfrom, READFROM are equivalent)
  • Values can be quoted or bare
  • Lists: a, b, c / [a, b, c] / a; b; c
  • Blocks start with BlockType: name and extend until the next block header
  • Blocks can nest: Sample inside Region, Systematic inside Sample

Modes

ModeDescription
NTUP (default)Build histograms from ROOT ntuples (TTrees), then convert to pyhf workspace
HISTImport an existing HistFactory XML export with optional filtering

Global Keys

Top-level keys (outside blocks) or inside a Job: block.

KeyAliasesDefaultDescription
ReadFromNTUPImport mode (NTUP | HIST)
TreeNameTree, NtupleName"events"Default TTree name in ROOT files
Measurement"meas"Measurement name (maps to pyhf measurement)
POIPoi"mu"Parameter of interest
HistoPathHistPath, ExportDirHistFactory export directory (HIST mode)
CombinationXmlHistFactoryXmlPath to combination.xml (HIST mode)

Region Block

Region: SR
  Variable: mbb
  Binning: 0, 50, 100, 150, 200, 300
  Selection: njet >= 4
KeyAliasesRequiredDescription
VariableVaryesVariable to histogram. Can include inline binning
BinningBinEdgesyes*Bin edges. Not needed if encoded in Variable
SelectionCutnoSelection/cut expression (entries pass if > 0)
WeightnoPer-region weight (multiplied into sample weights)
DataFilenoROOT file for observed data
DataTreeNameDataTreenoTTree name for data file

Variable + Binning formats

# Inline equal-width bins:
Variable: "jet_pt", 10, 0, 100    # 10 bins from 0 to 100

# Inline explicit edges:
Variable: "jet_pt", 0, 50, 100, 200, 500

# Separate keys:
Variable: jet_pt
Binning: 0, 50, 100, 200, 500

Sample Block

Sample: ttbar
  Type: BACKGROUND
  File: data/ttbar.root
  Weight: weight_mc * weight_sf
  Regions: SR; CR
  NormFactor: mu_ttbar
  StatError: true
KeyAliasesRequiredDescription
TypenoSIGNAL, BACKGROUND, or DATA (inferred from name if omitted)
FilePath, NtupleFileyes (NTUP)ROOT file path
NtupleFilesnoAlternative to File; first entry is used
TreeNameTreenoTTree name override for this sample
WeightMCweightnoPer-sample weight expression
SelectionCutnoPer-sample selection
RegionsnoRegion names where this sample contributes (default: all)
NormFactornoFree normalization parameter name (repeatable)
NormSysnoNorm systematic: "name lo hi" (repeatable)
StatErrornoEnable per-bin statistical uncertainties (Barlow-Beeston)

Systematic Block

Four types: norm, weight, tree, histo.

Common keys (all types)

KeyTypeDescription
Typeenumnorm, weight, tree, or histo (inferred if omitted)
SampleslistTarget sample names (default: parent sample if nested)
RegionslistTarget region names (default: all)

Type: norm

Systematic: lumi
  Type: norm
  Samples: all
  Lo: 0.98
  Hi: 1.02
KeyAliasesDescription
LoDownDown factor (e.g. 0.95 = -5%)
HiUpUp factor (e.g. 1.05 = +5%)
OverallUpAlternative: up shift
OverallDownAlternative: down shift

Type: weight

Systematic: btag
  Type: weight
  Samples: ttbar
  WeightUp: weight_btag_up
  WeightDown: weight_btag_down

Three ways to specify (priority order):

MethodKeysExample
Direct expressionsWeightUp, WeightDownWeightUp: weight_btag_up
Pre-computedWeightSufUp, WeightSufDownWeightSufUp: weight_btag_up
Suffix expansionWeightBase + WeightUpSuffix + WeightDownSuffixWeightBase: weight_btag / WeightUpSuffix: _up

Type: tree

Systematic: jer
  Type: tree
  Samples: signal
  FileUp: data/signal_jer_up.root
  FileDown: data/signal_jer_down.root
KeyAliasesDescription
FileUpUpFile, UpROOT file with up variation
FileDownDownFile, DownROOT file with down variation
TreeNameTreeTTree name in variation files

Type: histo

Systematic: model
  Type: histo
  Samples: signal
  HistoNameUp: signal_model_up
  HistoNameDown: signal_model_down
KeyAliasesDescription
HistoNameUpHistoUp, NameUpTH1 name for up variation
HistoNameDownHistoDown, NameDownTH1 name for down variation
HistoFileUpHistoPathUp, FileUpROOT file (default: sample file)
HistoFileDownHistoPathDown, FileDownROOT file (default: sample file)

NormFactor Block

NormFactor: mu_ttbar
  Samples: ttbar
  Nominal: 1.0
  Min: 0.0
  Max: 10.0
KeyDefaultDescription
Samplesall MC samplesSamples to apply this factor
TitleDisplay name
Nominal1.0Initial/nominal value
MinLower bound
MaxUpper bound
ConstantfalseIf true, parameter is fixed (not fitted)

Expression Language

Variable, Selection, and Weight fields use a bytecode-compiled expression language:

FeatureSyntaxExample
Arithmetic+, -, *, /pt * 0.001
Comparison==, !=, <, <=, >, >=njet >= 4
Logic&&, ||, !njet >= 4 && met > 200
Ternarycond ? a : bpt > 100 ? 1.0 : 0.5
Functionsabs, sqrt, log, log10, exp, sin, cos, pow, min, max, atan2sqrt(met)
Static indexbranch[N]jet_pt[0]
Dynamic indexbranch[expr]jet_pt[njet - 1]
Branch namesidentifiers, dotsjet_pt, el.pt

Block Nesting & Scoping

Region: SR
  Variable: mbb
  Binning: 0, 50, 100, 200

  Sample: signal                    # region-specific override
    Weight: weight_mc * 1.1         # overrides weight in SR only

    Systematic: jes_sr_only         # applies to "signal" in "SR" only
      Type: norm
      Lo: 0.95
      Hi: 1.05

Sample: signal                      # top-level definition
  Type: SIGNAL
  File: data/signal.root
  Weight: weight_mc
  • Systematic inside SampleSamples defaults to parent sample name
  • Sample inside Region → creates region-specific override; merges with top-level Sample
  • Systematic inside RegionRegions defaults to parent region name

HIST Mode

ReadFrom: HIST
HistoPath: path/to/histfactory_export

# Optional: filter to specific regions/samples
Region: SR
Region: CR_ttbar

Sample: signal
Sample: ttbar
  • HistoPath or CombinationXml points to the HistFactory export
  • Region and Sample blocks act as filters — only listed items are kept
  • No Variable, Binning, File, or Weight keys needed
  • Systematics are imported from the XML, not re-defined

Coverage Reports

# Unknown-attribute report
nextstat import trex-config --config analysis.config \
  --output workspace.json \
  --coverage-json coverage.json

# Expression compilation report
nextstat import trex-config --config analysis.config \
  --output workspace.json \
  --expr-coverage-json expr_coverage.json
  • Coverage report: every unrecognized key with line number and block scope
  • Expression coverage report: compiled expressions, required branches, compilation errors

Analysis Spec (YAML Wrapper)

$schema: https://nextstat.io/schemas/trex/analysis_spec_v0.schema.json
schema_version: trex_analysis_spec_v0

inputs:
  mode: trex_config_txt
  trex_config_txt:
    config_path: analysis.config
    base_dir: null

execution:
  determinism: { threads: 1, parity: true }
  import:
    enabled: true
    output_json: workspace.json
  fit:
    enabled: true
    output_json: fit.json
  profile_scan:
    enabled: true
    start: 0.0
    stop: 5.0
    points: 21
    output_json: scan.json
nextstat run --config analysis.yaml
nextstat validate --config analysis.yaml   # schema check only

Complete Example (NTUP)

ReadFrom: NTUP
TreeName: nominal
Measurement: meas
POI: mu_sig

# ── Regions ──────────────────────────────

Region: SR
  Variable: mbb
  Binning: 0, 50, 100, 150, 200, 300, 500
  Selection: njet >= 4 && nbtag >= 2

Region: CR_ttbar
  Variable: mbb
  Binning: 0, 100, 200, 500
  Selection: njet >= 4 && nbtag == 1

# ── Samples ──────────────────────────────

Sample: data
  Type: DATA
  File: data/data.root

Sample: signal
  Type: SIGNAL
  File: data/signal.root
  Weight: weight_mc * weight_pileup
  NormFactor: mu_sig
  StatError: true

Sample: ttbar
  Type: BACKGROUND
  File: data/ttbar.root
  Weight: weight_mc * weight_pileup
  Regions: SR; CR_ttbar
  NormFactor: mu_ttbar
  StatError: true

# ── Systematics ──────────────────────────

Systematic: lumi
  Type: norm
  Samples: signal; ttbar
  Lo: 0.98
  Hi: 1.02

Systematic: jes
  Type: weight
  Samples: signal; ttbar
  WeightUp: weight_jes_up
  WeightDown: weight_jes_down

Systematic: btag
  Type: weight
  Samples: signal; ttbar
  WeightBase: weight_btag
  WeightUpSuffix: _up
  WeightDownSuffix: _down

Systematic: ttbar_gen
  Type: tree
  Samples: ttbar
  FileUp: data/ttbar_gen_up.root
  FileDown: data/ttbar_gen_down.root

NormFactor: mu_ttbar
  Samples: ttbar
  Nominal: 1.0
  Min: 0.0
  Max: 10.0