KAHIBARO
Discord Login Register

23.7 Reproducible Analysis

Why Reproducibility Matters

Reproducible analysis means that someone else, or you in six months, can rerun your work and obtain the same results, starting from the same input data. For ROOT analyses this is especially important because studies often evolve over years, involve many small changes, and contribute to published results.

Reproducibility is not only about code. It combines code, configuration, data, software environment, and documentation. The aim is that every analysis step can be traced, understood, and repeated, rather than reconstructed from memory.

A ROOT analysis is reproducible if:

  1. All inputs (data, configuration, code, environment) are clearly specified.
  2. All processing steps are automated, not performed manually in interactive sessions.
  3. Running the documented commands regenerates the same outputs from the same inputs.

Reproducible analysis saves time by reducing confusion about which version of code or which selection was used. It also makes debugging easier, supports collaboration, and is expected in serious scientific work, especially when results might be reviewed or reanalyzed.

From Interactive ROOT to Scripts

Interactive ROOT sessions are ideal for exploration and trying ideas. However, interactive commands typed into the prompt are easy to lose and hard to exactly repeat. To move toward reproducibility, you should convert successful interactive steps into scripts or macros as soon as they become important.

A good pattern is to begin in the ROOT shell or in a C++ or PyROOT notebook and, once a sequence of commands produces a useful plot or value, copy those commands into a macro or source file. That file becomes the authoritative record of how a particular result was produced.

Every figure or numeric result that might enter a document or a report should correspond to a script that can regenerate it. The script should not depend on manual actions that are difficult to repeat or describe, such as clicking in GUIs or manually editing histograms.

Recording the Full Analysis Chain

A ROOT analysis typically consists of several steps, such as converting raw data to ROOT files, skimming or reducing TTrees, applying selections and calibrations, producing histograms, fitting them, and exporting final plots or numbers. Reproducibility requires that the whole chain be encoded and documented, not only the last plotting step.

It is useful to think in terms of transformations of data. Each step reads some input and writes some output, such as a TTree, a set of histograms, or a ROOT file. To be reproducible, each of these transformations must be described by code and configuration that you keep in your project, not only in temporary directories or hand-edited files.

Whenever you manually create intermediate ROOT files or histograms, for example by using the browser and saving objects by hand, consider whether this should be automated instead. If the intermediate data cannot be recreated by running code, then the chain is incomplete and difficult to reproduce if something is lost or needs to change.

Automation and Batch Execution

Automating ROOT analyses means that important steps are run by non-interactive commands. Instead of opening a canvas, drawing histograms, and clicking through options by hand, the analysis should be able to run from start to finish by executing scripts such as ROOT macros, compiled programs, or Python scripts with PyROOT.

This does not prevent interactive exploration, but any step that matters for final results should have an automated counterpart. For example, you might have one script that reads TTrees and fills histograms, another that performs fits, and a final one that formats plots for publication. Each script should be callable from the command line or from ROOT without user interaction.

Batch execution is especially important when running on remote machines or computing clusters. If you can trigger your full analysis with a small number of commands, you can schedule it, track logs, and rerun it whenever input files or configuration change. Interactive workflows with many manual steps are fragile and difficult to move between systems.

Randomness and Seeds

Many ROOT analyses include random processes, such as toy Monte Carlo simulations, resampling, or generation of pseudo-experiments with TRandom or TRandom3. Random numbers can make results differ from one run to another, which is acceptable for exploration but problematic when a specific output must be reproducible.

To control this, you should explicitly set seeds for your random number generators. This ensures that each call sequence produces the same random numbers every time you run the code with the same seed and ROOT version. When you need varied runs, you can change the seed in a controlled way, but for a baseline reproducible analysis you should fix it.

To obtain reproducible random results in ROOT:

  1. Use a TRandom subclass, such as TRandom3.
  2. Call SetSeed with an explicit integer value at the beginning of your code.
  3. Record the seed value along with other configuration for the analysis.

If you rely on built-in global random generators without setting seeds, or if you change random number generators between runs without recording the details, you may find that you cannot reproduce specific distributions or fitted parameter values exactly, even with the same code and data.

Configuration Files and Input Parameters

Hard-coding analysis parameters directly inside ROOT source files makes it difficult to understand exactly which values were used and to compare different configurations. To improve reproducibility, separate the parameters that define an analysis from the code that implements it.

Typical parameters include selection cuts, binning descriptions, calibration constants, file paths, branches to read, and fit ranges. Keeping them in configuration files or at least in a clearly separated configuration section of your code makes it easier to see what changed between runs and to track analysis variations.

For example, instead of editing numeric literals inside loops across multiple macros, centralize them in a single place or in a simple text-based configuration file that the analysis scripts read at runtime. That way, when you refer to “the version with tighter selection cuts” or “the updated calibration,” you can point to an explicit file that encodes those changes.

Documenting Data and Inputs

Reproducibility requires that the data you analyze can be identified and retrieved. This means you should record exactly which ROOT files were used, where they came from, and, if possible, which versions or production tags they correspond to.

Within your project directory, it is often useful to include a simple description of external datasets. This can be a text or markdown file that lists data sources, filenames or directory paths, and any preprocessing steps applied before they entered your main analysis. For internal datasets, you may also record the commands or scripts that produced them.

If your analysis uses only a subset of available data or applies specific filters at an early stage, document those choices, because they affect the interpretation of the results. It should be possible to check whether new data can be integrated by re-running the same steps or whether a slightly different selection might change conclusions.

Logging, Metadata, and Outputs

When an analysis runs automatically it is helpful to capture logs and metadata that describe what happened. For ROOT analyses, this can include simple text logs printed by std::cout, command line arguments, configuration summaries, and information about software versions.

One practical approach is to write a short summary object to your output ROOT files, for instance as a TNamed or a small TTree, that contains strings with configuration details, git commit identifiers, random seeds, or data tags. When you open the file later, you can inspect this summary and recover how it was produced.

Outputs should be organised so that multiple runs do not overwrite each other silently. Including timestamps, configuration names, or code version identifiers in output file names can help distinguish different analysis variants. This makes it easier to relate a specific plot or ROOT file to the state of the analysis that created it.

Environment and Version Control

ROOT analyses depend on the software environment, including the ROOT version, the compiler, and any external libraries. Different ROOT versions may change default behaviors or algorithms. For reproducibility, you should record which environment you used and ideally rely on a consistent environment when rerunning the analysis.

At the same time, the analysis code itself should be stored in a version-controlled repository. This is closely related to reproducibility, but version control is discussed in a separate chapter about using Git. The key idea is that every set of outputs corresponds to a specific version of the code, and you should be able to return to that version later.

When you combine a controlled environment, such as a stable ROOT installation managed through a package manager or a container, with version-controlled analysis code and clearly documented inputs and configuration, you establish a strong basis for reproducible ROOT analysis that can be sustained and extended over time.

Views: 15

Comments

Please login to add a comment.

Don't have an account? Register now!