KAHIBARO
Discord Login Register

25.10 J. Recommended ROOT Analysis Workflow

Overview

This appendix gives you a practical, repeatable workflow for ROOT-based analyses. It is not a strict recipe, but a checklist that helps you move from raw data to final plots and numbers in a structured way. You can adapt it to both small toy problems and large experimental datasets.

The focus here is on the sequence of steps, the roles of key ROOT tools at each step, and habits that make your analysis reproducible and maintainable.

Step 1: Clarify the Physics (or Analysis) Question

Before touching ROOT, define what you are trying to measure or demonstrate. Examples include measuring a mean energy, extracting a peak position, or estimating a cross section.

Write down, ideally in a text file inside your project, the following items.

Measurement goal. What quantity or distribution do you want to obtain using ROOT, for example a peak position and width, an event rate, or an efficiency.

Inputs. Which datasets or files you will use, for example ROOT files, text or CSV files, simulated samples.

Outputs. What you plan to produce, for example histograms, graphs, summary tables, final figures, written numbers with uncertainties.

Selection and assumptions. Roughly what event selection or cuts you expect to use, and any basic assumptions, for example background model type, energy range of interest.

This short planning step will guide which ROOT tools you use later and helps you avoid writing code that you will not need.

Step 2: Organize the Analysis Project

Create a small but consistent directory structure for your project so that code, inputs, and outputs are clearly separated.

A typical layout might be stored in a directory named after the project and contain subdirectories such as one for source code and macros, one for configuration files, one for raw input files such as ROOT, TXT, or CSV, one for intermediate ROOT files and TTrees, and one for plots and final outputs.

Use relative paths in ROOT macros and scripts, for example open files like "data/file.root" instead of hard coded absolute paths. This makes the analysis portable between machines and colleagues.

Keep configuration in central files where possible. Numerical values like selection thresholds, histogram ranges, and file lists can be stored in C++ header files, JSON, or simple text files and read by your macros. That way you do not need to modify code to change a cut.

Use version control. Initialize a Git repository in your project directory and commit your macros, configuration, and possibly small test data files. This allows you to track changes in scripts that use ROOT and to reproduce older versions of your analysis.

Step 3: Inspect and Understand the Input Data

Whether your input is plain text or ROOT files with TTrees, first spend time exploring the structure and content without doing full analysis.

If your data is already in ROOT files, open them interactively with the ROOT shell, use file listing commands to see available TTrees, histograms, and directories, and explore the ROOT browser to click through objects. For TTrees, inspect their branches with printing and scanning tools and draw some quick one dimensional histograms of key variables directly from the tree. This helps reveal ranges, units, and potential outliers.

If your data is in text or CSV format, open a few lines in a text editor to check column order and separators. Then write a small ROOT macro to read a limited sample of rows, create a temporary TTree or direct histograms, and visualize basic distributions. Confirm that units and column interpretations match the documentation or your expectations.

During this inspection, keep a note of useful information like variable names and types, typical ranges and any extremes, potential bad values such as negative energies or sentinel codes, and event weights if present.

Having this mental map of your data will inform your later choice of binning, cuts, and models.

Step 4: Convert and Preprocess the Data into ROOT-Friendly Form

Once you understand the inputs, prepare a clean, consistent ROOT representation of your data to facilitate fast and flexible analysis.

If your starting point is not ROOT, write a dedicated import macro or script that reads text or CSV files, parses each line, and fills a TTree with meaningful branches. Store this TTree in a dedicated ROOT file. During this conversion handle missing or invalid entries explicitly by skipping events or flagging them in separate branches.

If you start from ROOT but with many loosely organized objects, consider writing a preprocessing macro that reads the raw TTrees, applies minimal technical cleaning such as removing unphysical values or transforming units, and writes out a simplified TTree with the most relevant branches for your analysis. Use TChain or lists of filenames if many input files are involved.

Apply basic cleaning and calibration at this stage when it is conceptually simple to do so. For example, you might replace raw channel counts by calibrated energies using fixed calibration constants stored in configuration, or discard clearly nonsensical events. However, avoid baking in complex physics selections at this stage. Keep this step separate and focused on making data technically consistent and analysis ready.

Use descriptive branch names that correspond to physical quantities, for example energy or time, and document what each branch means in a short note or header comment.

Step 5: Define and Implement the Event Selection

Event selection determines which entries are considered signal, which are background, and which are discarded as noise or invalid. Design this step in a way that is transparent and adjustable.

Start interactively. Use TTree drawing commands or RDataFrame filters in the ROOT prompt to experiment with simple conditions. Look at how histograms change as you vary thresholds to get a feeling for which cuts are useful and how tight they should be.

Then formalize the selection into code. Encapsulate selection logic in functions or clearly structured conditions. Avoid having long chains of opaque cuts scattered throughout your code. Group related cuts together such as basic quality cuts, physics region definitions, and category definitions like signal or control regions.

Whenever possible, keep numeric thresholds in configuration instead of hard coding them inside the selection code. For instance, store a minimum energy as a constant in a header file or config text and refer to that symbol in your selection macros.

Use selections to define distinct regions. For many analyses you will have at least one signal region where you expect your signal enriched distribution, and one or more control or background regions where signal is suppressed and background behavior can be studied.

Document selection criteria clearly. Maintain a text file or comments listing each cut, its purpose, and its current value. This greatly helps later when writing your analysis report or debugging mismatches with collaborators.

Step 6: Structure Event Loops or Use RDataFrame

At the core of many analyses is looping over events, applying selections, computing derived quantities, and filling histograms or other objects. ROOT offers both traditional loops over TTrees and the higher level RDataFrame interface.

With traditional event loops, you typically enable only the branches you need, set branch addresses or create C++ variables to read entries, loop over all entries with selection checks, and fill histograms or accumulate quantities. Keep the loop body as simple and clear as possible. Offload complex computations to helper functions defined elsewhere, so the main loop reads like a description of the analysis steps.

With RDataFrame, you follow a declarative style. You create a dataframe from a TTree or a file, define new columns for derived quantities using expressions or C++ lambdas, apply filters for selections, and finally create histograms or statistical results. RDataFrame handles the looping internally and can transparently use multithreading.

Regardless of which style you choose, prefer structuring your code so that each macro or script has a clear role, for example defining derived variables, running selections and histograms, or doing fits and plotting. This keeps your workflow modular and easier to maintain.

Step 7: Create and Manage Histograms and Graphs

Histograms and graphs are key intermediate products. Create them systematically and consistently.

Plan the variables to histogram. Based on your physics question and data exploration, decide which observables you should histogram at each stage, such as before selection, after basic quality cuts, and in the final signal region. This can reveal where cuts act strongly and where backgrounds remain.

Choose sensible binning and ranges based on your earlier inspections. Avoid extremely fine bins if your statistics are low, and avoid ranges that are too wide since they waste resolution and can hide structure.

Name histograms and graphs meaningfully, such as hEnergySignal or gEfficiencyVsEnergy instead of anonymous names. Use titles that clearly describe the content, since these will appear in plot axes and legends.

Separate technical and final histograms. You may create many internal histograms for debugging and efficiency studies. Keep them in separate directories in your ROOT files or name them systematically so they do not clutter your final result space.

When working with graphs such as TGraph or TGraphErrors, use them for quantities that are naturally represented as point values with uncertainties, like efficiency as a function of a threshold or calibration points. Make sure to fill both central values and error bars appropriately.

Step 8: Perform Fits and Extract Quantities

Once you have the relevant distributions, you often need to extract parameters by fitting functions to histograms or graphs.

Begin with visual inspection. Plot your histogram with a reasonable axis range and try a simple function such as a Gaussian or low order polynomial, depending on your physics model. Use interactive fitting tools to experiment with function ranges and starting parameter values.

Then encode the chosen model and fitting strategy in a macro. Define your fit function explicitly, set initial parameter guesses and parameter limits if needed, run the fitting procedures programmatically, and retrieve the fit results programmatically as well. Store fit parameters, uncertainties, and quality metrics like chi square and number of degrees of freedom.

Always save and later report both parameter values and their uncertainties together with an appropriate measure of the fit quality such as the reduced chi square. A parameter without its uncertainty is not a complete result.

Take care when choosing fit ranges. Fitting too wide a range can bias parameters if the model does not describe all features. Fitting too narrow a range can ignore important background or tails. Often you will define signal and sideband regions and fit combined signal plus background models.

When models are more complex, encapsulate them in C++ functions rather than long string expressions. This makes the code easier to read and debug.

Step 9: Estimate Statistical and Systematic Uncertainties

Any numerical result needs an uncertainty estimate. ROOT provides tools for statistical uncertainties through histogram errors and fit parameter errors, but you also need to design how to estimate systematic effects.

For statistical uncertainties, rely on bin errors produced by proper histogram filling. If you are using variable event weights, be sure to enable proper error handling before filling. When you create functions from fits, use the parameter covariance matrix which is automatically produced by fitting routines to propagate statistical uncertainties on fit-derived quantities.

For systematic uncertainties, vary analysis choices that might influence your results and observe the change in the derived quantities. Examples include changing selection cuts within reasonable ranges, varying histogram binning, modifying background models, or using alternative calibration constants. For each variation, rerun your analysis chain or at least the downstream part and compare outputs.

You can then combine systematic variations into an overall systematic uncertainty, for example by adding independent contributions in quadrature. Keep clear records of which variations were tested and how the combined systematic was computed.

Never quote a final result without stating how its uncertainty was obtained and what types of uncertainties are included. Distinguish clearly between statistical and systematic components when reporting.

Store intermediate numerical results such as yields, efficiencies, correction factors, and uncertainties in structured forms, for example text tables, ROOT objects, or small ROOT trees, so that you can revisit or recombine them later.

Step 10: Produce Clean, Consistent Plots

Once your analysis logic and results are stable, focus on producing clear and consistent figures suitable for presentations or publications.

Set up a common style. Use ROOT style objects or small setup macros to define font sizes, line widths, marker styles, and color palettes. Apply this style consistently to all plots rather than configuring each one differently.

For each key distribution, create a plotting macro that draws the relevant histograms or graphs, applies axis titles with units, sets sensible ranges and scales, including logarithmic axes where appropriate, and adds legends and text annotations to identify datasets and conditions. Separate plotting code from analysis code as much as possible so that visualization tweaks do not risk breaking the analysis logic.

Export plots in appropriate formats. For documents, vector formats such as PDF and SVG are usually better because they scale cleanly. For quick checks or web use, PNG is often sufficient. Also save a ROOT version of the canvas so that you can re-open and modify the plot later without rerunning everything.

Use consistent naming and directory placement for output images, for example storing them in a dedicated plots directory and using filenames that encode the observable, selection, and version. This makes it easier to locate and compare plots over time.

Step 11: Save and Archive Analysis Outputs

Beyond plots, you should save the intermediate and final data products that your analysis creates so you can reuse or inspect them without recomputing.

Store important histograms, graphs, fit functions, and derived TTrees in dedicated ROOT files, organized with directories inside those files when helpful. Use file names and internal directory names that reflect the analysis step and selection, for example preselection, final selection, or systematic variations.

When using RDataFrame, consider creating snapshots which write filtered or augmented datasets to new ROOT files. These snapshots can serve as convenient inputs for later stages of your workflow or for sharing with collaborators.

Keep summary outputs in human readable forms as well. For example, export tables of fit results or efficiencies as simple text or CSV files in an output directory. These can be imported easily into other tools or included in reports.

Use your version control system to tag analysis milestones. When you reach a stable result that you may need to reference later, create a tag or branch. Then your macros and configuration at that point are frozen and can be restored exactly, helping with long term reproducibility.

Step 12: Document and Report the Analysis

The final step of a recommended workflow is explicit documentation. This goes beyond ROOT code and ensures that another person, or your future self, can understand and reproduce the analysis.

Maintain a short analysis note inside the project directory that explains the goal of the analysis, the data sources and preprocessing, the selection strategy and main cuts, the key histograms and fits and what they represent, the final results with both statistical and systematic uncertainties, and the main checks of analysis robustness.

Whenever possible, refer in your note to specific macros or scripts and configuration files, so there is a clear link between text and code. For example, mention which macro performs the main event loop or which file defines the selection cuts.

Connect your documentation to your ROOT outputs by including or referencing key figures and tables produced by your plotting and summary macros. Indicate which ROOT files contain final histograms and derived TTrees.

This kind of integrated documentation transforms your ROOT scripts from one off experiments into a coherent analysis that others can read, check, and extend.

Putting It All Together

In practice, you will iterate across several of these steps rather than following them strictly in order. For instance, after first fits you may revisit data cleaning, or after estimating systematic uncertainties you may adjust selections. The key is to keep these steps modular and traceable.

A well structured ROOT analysis workflow therefore consists of clarifying your question, organizing files and configuration, understanding and converting your data into ROOT structures, designing and implementing selections, performing structured event processing, histogramming and fitting, estimating uncertainties, producing consistent plots, saving intermediate results, and documenting all of the above.

If you treat this list as a checklist for each new project, you will steadily develop ROOT analyses that are not only correct, but also reproducible, shareable, and easier to maintain over time.

Views: 9

Comments

Please login to add a comment.

Don't have an account? Register now!