Skip to content

Conversation

@guitargeek
Copy link
Collaborator

@guitargeek guitargeek commented Nov 14, 2025

Alternative to #1182 that works without creating dictionaries for the "Combine" class in Combine.h, which would imply parsing of the boost headers that doesn't always work.

Summary by CodeRabbit

  • New Features

    • CI now runs a FastScan template analysis step to validate scans automatically.
  • Refactor

    • Introduced a new, Python-accessible utility façade to streamline NLL creation.
    • Internal class registration updated for improved Python interoperability.
  • User-facing improvements

    • Per-parameter plot canvases now use distinct names and output PDFs are written with descriptive filename prefixes.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Nov 14, 2025

Walkthrough

Refactors the global combineCreateNLL access into a new CombineUtils class with a static wrapper, updates Python call sites to use ROOT.CombineUtils.combineCreateNLL, adds CombineUtils to build/export metadata, and inserts a FastScan template-analysis CI step.

Changes

Cohort / File(s) Summary
Header refactor & wrapper
interface/Combine.h, interface/CombineUtils.h
Removed the free-function declaration from Combine.h; added interface/CombineUtils.h which declares the global combineCreateNLL and introduces class CombineUtils with a static combineCreateNLL wrapper delegating to the global function.
Python call-site updates
python/tool_base/FastScan.py, python/tool_base/TaylorExpand.py
Replaced calls from ROOT.combineCreateNLL(...) to ROOT.CombineUtils.combineCreateNLL(...). Also minor TCanvas naming and output filename adjustments in FastScan.py.
Build / ROOT dictionary export
src/classes.h, src/classes_def.xml
Added #include "interface/CombineUtils.h" to src/classes.h and exported CombineUtils in src/classes_def.xml (lcgdict) so the class is available to ROOT/Python bindings.
CI workflow
.github/workflows/cvmfs-ci.yml
Inserted a new GitHub Actions step that runs a FastScan template analysis for CMSHistFunc via the local .github/actions/run-in-cvmfs action, placed before the "Prepare code coverage report" step.

Sequence Diagram(s)

sequenceDiagram
    autonumber
    participant Py as Python tool (FastScan/TaylorExpand)
    participant ROOT as ROOT Python bindings
    participant Cpp as C++ global function

    Note over Py,ROOT: NLL creation flow (changed)
    Py->>ROOT: Call ROOT.CombineUtils.combineCreateNLL(pdf, data, ...)
    activate ROOT
    ROOT->>Cpp: Invoke ::combineCreateNLL(pdf, data, ...)
    activate Cpp
    Cpp-->>ROOT: std::unique_ptr<RooAbsReal> (NLL)
    deactivate Cpp
    ROOT-->>Py: RooAbsReal NLL pointer
    deactivate ROOT
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

  • Attention suggested for:
    • Ensuring the new header inclusion and classes_def.xml entry produce correct ROOT dictionary bindings.
    • Verifying that Python can import ROOT.CombineUtils and that returned smart pointer lifetime is handled correctly in Python.
    • Small behavior change in FastScan canvas naming/output filenames.

Possibly related PRs

Poem

🐰 A wrapper snug in header light,
Python hops in, NLL in sight.
CombineUtils calls, tidy and bright,
Canvases named, outputs right —
A rabbit cheers: refactor delight! 🥕✨

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 25.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main objective of the PR: exposing the combineCreateNLL function to Python through a new utility class wrapper.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 1e5a2b6 and fc08972.

📒 Files selected for processing (7)
  • .github/workflows/cvmfs-ci.yml (1 hunks)
  • interface/Combine.h (1 hunks)
  • interface/CombineUtils.h (1 hunks)
  • python/tool_base/FastScan.py (1 hunks)
  • python/tool_base/TaylorExpand.py (1 hunks)
  • src/classes.h (1 hunks)
  • src/classes_def.xml (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (2)
python/tool_base/FastScan.py (2)
interface/CombineUtils.h (1)
  • CombineUtils (11-20)
src/Combine.cc (2)
  • combineCreateNLL (1278-1338)
  • combineCreateNLL (1278-1279)
python/tool_base/TaylorExpand.py (2)
interface/CombineUtils.h (1)
  • CombineUtils (11-20)
src/Combine.cc (2)
  • combineCreateNLL (1278-1338)
  • combineCreateNLL (1278-1279)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (10)
  • GitHub Check: Compile (py3.10, root6.32.2)
  • GitHub Check: Compile (py3.12, root6.34.4)
  • GitHub Check: Compile (py3.10, root6.26.4)
  • GitHub Check: LCG_108 - ROOT 6.36.02
  • GitHub Check: CMSSW_14_1_0_pre4 - ROOT 6.30.07
  • GitHub Check: LCG_102 - ROOT 6.26.04
  • GitHub Check: CMSSW_14_0_0_pre1 - ROOT 6.26.11
  • GitHub Check: CMSSW_11_3_4 - ROOT 6.22.09
  • GitHub Check: dev3/latest - ROOT LCG master
  • GitHub Check: LCG_106 - ROOT 6.32.02
🔇 Additional comments (6)
src/classes.h (1)

66-66: LGTM! Include added correctly.

The addition of CombineUtils.h properly exposes the new utility class for dictionary generation and Python bindings.

src/classes_def.xml (1)

223-223: LGTM! Dictionary export configured correctly.

Adding CombineUtils to the lcgdict properly exposes the class to Python via ROOT's dictionary generation.

.github/workflows/cvmfs-ci.yml (1)

286-291: LGTM! CI test validates the new Python API.

The new workflow step appropriately tests the FastScan functionality with the updated CombineUtils interface.

python/tool_base/FastScan.py (1)

60-60: LGTM! Python API call updated correctly.

The call site properly uses the new CombineUtils.combineCreateNLL interface while maintaining the same functionality.

python/tool_base/TaylorExpand.py (1)

189-189: LGTM! Python API call updated consistently.

The call site correctly uses the new CombineUtils.combineCreateNLL interface, matching the update pattern in FastScan.py.

interface/Combine.h (1)

10-11: LGTM! Header dependency updated correctly.

The inclusion of CombineUtils.h properly exposes the moved combineCreateNLL declaration and provides the new utility class interface.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (1)
python/tool_base/FastScan.py (1)

117-118: Improved canvas naming for uniqueness.

The canvas name now uses "par_%s" % par.GetName() instead of the generic self.args.output, which gives each parameter's canvas a unique, descriptive name. This prevents potential canvas name conflicts in ROOT.

Consider sanitizing the parameter name to handle any potential special characters:

-            canv_name = "par_%s" % par.GetName()
+            canv_name = "par_%s" % re.sub(r'[^\w]', '_', par.GetName())
             canv = ROOT.TCanvas(canv_name, canv_name)

This is likely unnecessary since RooFit parameter names are typically alphanumeric with underscores, but provides defensive coding against edge cases.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between fc08972 and dfdc8a6.

📒 Files selected for processing (7)
  • .github/workflows/cvmfs-ci.yml (1 hunks)
  • interface/Combine.h (1 hunks)
  • interface/CombineUtils.h (1 hunks)
  • python/tool_base/FastScan.py (3 hunks)
  • python/tool_base/TaylorExpand.py (1 hunks)
  • src/classes.h (1 hunks)
  • src/classes_def.xml (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (3)
  • interface/Combine.h
  • python/tool_base/TaylorExpand.py
  • .github/workflows/cvmfs-ci.yml
🧰 Additional context used
🧬 Code graph analysis (1)
python/tool_base/FastScan.py (2)
interface/CombineUtils.h (1)
  • CombineUtils (18-27)
src/Combine.cc (2)
  • combineCreateNLL (1278-1338)
  • combineCreateNLL (1278-1279)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (10)
  • GitHub Check: dev3/latest - ROOT LCG master
  • GitHub Check: CMSSW_14_0_0_pre1 - ROOT 6.26.11
  • GitHub Check: LCG_108 - ROOT 6.36.02
  • GitHub Check: CMSSW_14_1_0_pre4 - ROOT 6.30.07
  • GitHub Check: LCG_106 - ROOT 6.32.02
  • GitHub Check: LCG_102 - ROOT 6.26.04
  • GitHub Check: CMSSW_11_3_4 - ROOT 6.22.09
  • GitHub Check: Compile (py3.10, root6.26.4)
  • GitHub Check: Compile (py3.12, root6.34.4)
  • GitHub Check: Compile (py3.10, root6.32.2)
🔇 Additional comments (7)
src/classes.h (1)

66-66: LGTM! Include added for dictionary generation.

The include for CombineUtils.h is correctly placed and necessary for generating Python bindings for the new CombineUtils class.

src/classes_def.xml (1)

223-223: LGTM! Dictionary entry correctly registered.

The CombineUtils class is properly registered in the lcgdict section, enabling Python bindings via ROOT's dictionary generation mechanism.

python/tool_base/FastScan.py (2)

60-60: LGTM! NLL creation updated to use CombineUtils wrapper.

The change from ROOT.combineCreateNLL to ROOT.CombineUtils.combineCreateNLL correctly uses the new static wrapper method, aligning with the PR's objective to expose this functionality through a utility class.


147-147: Excellent bug fix for output file naming!

The old code canv.Print(".pdf%s" % extra) would create a hidden file named .pdf (on Unix systems), which was clearly incorrect. The new code canv.Print("%s.pdf%s" % (self.args.output, extra)) properly creates a file named <output_name>.pdf with correct multi-page PDF syntax.

interface/CombineUtils.h (3)

1-9: LGTM! Header structure is correct.

The include guards, necessary includes, and forward declarations are properly structured. The forward declarations minimize compilation dependencies, and <memory> is correctly included for std::unique_ptr.


11-15: LGTM! Global function declaration.

The free function declaration with default parameters is clean and well-defined. This function will be called by the static wrapper in the CombineUtils class.


17-27: LGTM! Clean wrapper design for Python bindings.

The CombineUtils class provides a stateless facade with a static method that simply delegates to the global function. This approach is cleaner for ROOT's dictionary generation than exposing free functions, as noted in the comment. The parameter signatures match perfectly between the wrapper and the global function.

@codecov
Copy link

codecov bot commented Nov 14, 2025

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 22.25%. Comparing base (1e5a2b6) to head (dfdc8a6).
⚠️ Report is 4 commits behind head on main.

Additional details and impacted files

Impacted file tree graph

@@           Coverage Diff           @@
##             main    #1183   +/-   ##
=======================================
  Coverage   22.25%   22.25%           
=======================================
  Files         195      195           
  Lines       26154    26154           
  Branches     3883     3884    +1     
=======================================
  Hits         5820     5820           
  Misses      20334    20334           
Files with missing lines Coverage Δ
interface/Combine.h 100.00% <ø> (ø)
Files with missing lines Coverage Δ
interface/Combine.h 100.00% <ø> (ø)
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@anigamova
Copy link
Collaborator

Thank you @guitargeek!

@anigamova anigamova merged commit f89b178 into cms-analysis:main Nov 14, 2025
17 checks passed
@guitargeek guitargeek deleted the combineCreateNLL branch November 14, 2025 10:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants