Postprocessing Overview

The postprocessing system is a separate, configuration-driven framework for producing plots, tables, and other outputs from the .result files generated by the analysis. It operates entirely independently of the analysis itself – you can rerun postprocessing without rerunning the analysis.

Pipeline Overview

The postprocessing pipeline has the following stages:

  1. Load: .result files are loaded and optionally filtered to only include results matching specified patterns.

  2. Merge and Scale: Samples within each dataset are merged, and MC results are scaled to physical units using luminosity * cross_section / processed_events.

  3. Process: Each configured processor iterates over its inputs, applies grouping and transforms, and produces output files (plots, tables, etc.).

The merge-and-scale step can be disabled with do_merge_and_scale: false if you want to work with per-sample results directly.

Processor Architecture

Each processor in the configuration has three key parts:

inputs

Path patterns that select which results to operate on. These are matched against the result tree structure (dataset/sample/pipeline/result_name).

structure

A GroupBuilder that defines how to filter, group, transform, and sub-divide the selected results. This is where the real logic of the postprocessing is defined.

output_name

A template string for the output file path, with placeholders filled from result metadata.

The GroupBuilder

The GroupBuilder is the core abstraction of postprocessing. It applies a sequence of operations to the results:

  1. ``select``: Filter results by metadata. Only results matching the pattern are kept.

  2. ``group``: Group results by captured metadata values. For example, grouping by era produces one group per era.

  3. ``transforms``: Apply transformations to each group (e.g., selecting histogram axis values, rebinning).

  4. ``subgroups``: Recursively apply sub-builders to create nested structures.

These operations are applied in order, and the result is passed to the processor’s getRunFuncs() method.

A common pattern is to use subgroups to separate results into “numerator” and “denominator” for ratio plots, or “signal” and “background” for significance calculations.

Metadata Flow

Each result carries metadata from the analysis – dataset name, sample type, era, pipeline, result name, etc. This metadata flows through the postprocessing pipeline and can be used in:

  • select and group patterns (see Pattern Matching)

  • output_name templates via {key} syntax

  • Style rules for pattern-matched plot styling

Nested metadata is accessed with dot notation: {era.name}, {other_data.stop_mass}. The output_name template uses a simplified form of Python’s str.format() syntax, with metadata keys flattened using dot notation.