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
| Mode | Description |
|---|
| NTUP (default) | Build histograms from ROOT ntuples (TTrees), then convert to pyhf workspace |
| HIST | Import an existing HistFactory XML export with optional filtering |
Global Keys
Top-level keys (outside blocks) or inside a Job: block.
| Key | Aliases | Default | Description |
|---|
| ReadFrom | — | NTUP | Import mode (NTUP | HIST) |
| TreeName | Tree, NtupleName | "events" | Default TTree name in ROOT files |
| Measurement | — | "meas" | Measurement name (maps to pyhf measurement) |
| POI | Poi | "mu" | Parameter of interest |
| HistoPath | HistPath, ExportDir | — | HistFactory export directory (HIST mode) |
| CombinationXml | HistFactoryXml | — | Path to combination.xml (HIST mode) |
Region Block
Region: SR
Variable: mbb
Binning: 0, 50, 100, 150, 200, 300
Selection: njet >= 4
| Key | Aliases | Required | Description |
|---|
| Variable | Var | yes | Variable to histogram. Can include inline binning |
| Binning | BinEdges | yes* | Bin edges. Not needed if encoded in Variable |
| Selection | Cut | no | Selection/cut expression (entries pass if > 0) |
| Weight | — | no | Per-region weight (multiplied into sample weights) |
| DataFile | — | no | ROOT file for observed data |
| DataTreeName | DataTree | no | TTree 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
| Key | Aliases | Required | Description |
|---|
| Type | — | no | SIGNAL, BACKGROUND, or DATA (inferred from name if omitted) |
| File | Path, NtupleFile | yes (NTUP) | ROOT file path |
| NtupleFiles | — | no | Alternative to File; first entry is used |
| TreeName | Tree | no | TTree name override for this sample |
| Weight | MCweight | no | Per-sample weight expression |
| Selection | Cut | no | Per-sample selection |
| Regions | — | no | Region names where this sample contributes (default: all) |
| NormFactor | — | no | Free normalization parameter name (repeatable) |
| NormSys | — | no | Norm systematic: "name lo hi" (repeatable) |
| StatError | — | no | Enable per-bin statistical uncertainties (Barlow-Beeston) |
Systematic Block
Four types: norm, weight, tree, histo.
Common keys (all types)
| Key | Type | Description |
|---|
| Type | enum | norm, weight, tree, or histo (inferred if omitted) |
| Samples | list | Target sample names (default: parent sample if nested) |
| Regions | list | Target region names (default: all) |
Type: norm
Systematic: lumi
Type: norm
Samples: all
Lo: 0.98
Hi: 1.02
| Key | Aliases | Description |
|---|
| Lo | Down | Down factor (e.g. 0.95 = -5%) |
| Hi | Up | Up factor (e.g. 1.05 = +5%) |
| OverallUp | — | Alternative: up shift |
| OverallDown | — | Alternative: down shift |
Type: weight
Systematic: btag
Type: weight
Samples: ttbar
WeightUp: weight_btag_up
WeightDown: weight_btag_down
Three ways to specify (priority order):
| Method | Keys | Example |
|---|
| Direct expressions | WeightUp, WeightDown | WeightUp: weight_btag_up |
| Pre-computed | WeightSufUp, WeightSufDown | WeightSufUp: weight_btag_up |
| Suffix expansion | WeightBase + WeightUpSuffix + WeightDownSuffix | WeightBase: weight_btag / WeightUpSuffix: _up |
Type: tree
Systematic: jer
Type: tree
Samples: signal
FileUp: data/signal_jer_up.root
FileDown: data/signal_jer_down.root
| Key | Aliases | Description |
|---|
| FileUp | UpFile, Up | ROOT file with up variation |
| FileDown | DownFile, Down | ROOT file with down variation |
| TreeName | Tree | TTree name in variation files |
Type: histo
Systematic: model
Type: histo
Samples: signal
HistoNameUp: signal_model_up
HistoNameDown: signal_model_down
| Key | Aliases | Description |
|---|
| HistoNameUp | HistoUp, NameUp | TH1 name for up variation |
| HistoNameDown | HistoDown, NameDown | TH1 name for down variation |
| HistoFileUp | HistoPathUp, FileUp | ROOT file (default: sample file) |
| HistoFileDown | HistoPathDown, FileDown | ROOT file (default: sample file) |
NormFactor Block
NormFactor: mu_ttbar
Samples: ttbar
Nominal: 1.0
Min: 0.0
Max: 10.0
| Key | Default | Description |
|---|
| Samples | all MC samples | Samples to apply this factor |
| Title | — | Display name |
| Nominal | 1.0 | Initial/nominal value |
| Min | — | Lower bound |
| Max | — | Upper bound |
| Constant | false | If true, parameter is fixed (not fitted) |
Expression Language
Variable, Selection, and Weight fields use a bytecode-compiled expression language:
| Feature | Syntax | Example |
|---|
| Arithmetic | +, -, *, / | pt * 0.001 |
| Comparison | ==, !=, <, <=, >, >= | njet >= 4 |
| Logic | &&, ||, ! | njet >= 4 && met > 200 |
| Ternary | cond ? a : b | pt > 100 ? 1.0 : 0.5 |
| Functions | abs, sqrt, log, log10, exp, sin, cos, pow, min, max, atan2 | sqrt(met) |
| Static index | branch[N] | jet_pt[0] |
| Dynamic index | branch[expr] | jet_pt[njet - 1] |
| Branch names | identifiers, dots | jet_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 Sample →
Samples defaults to parent sample name - Sample inside Region → creates region-specific override; merges with top-level Sample
- Systematic inside Region →
Regions 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