Skip to content

[6.40] [RF][HS3] Don't let evauation artifacts demote top-level pdfs in the export - #23229

Merged
guitargeek merged 2 commits into
root-project:v6-40-00-patchesfrom
root-project-bot:BP_6.40_pull_23224
Sep 2, 2026
Merged

[6.40] [RF][HS3] Don't let evauation artifacts demote top-level pdfs in the export#23229
guitargeek merged 2 commits into
root-project:v6-40-00-patchesfrom
root-project-bot:BP_6.40_pull_23224

Conversation

@root-project-bot

Copy link
Copy Markdown

Backport of #23224, requested by @guitargeek.

The HS3 exporter and `RooJSONFactoryWSTool::cleanWS()` used
`!hasClients()` as the criterion for "this pdf or function is a top-level
object of the workspace". But RooFit also registers objects that live
outside the workspace as clients: the normalization integral that
`RooAbsPdf` caches after `getVal(normSet)`, or the integral returned by
`createIntegral()`. A single normalized evaluation before the export
therefore silently produced a document without any distributions, domains
or parameter values, while `exportJSON()` still returned `true`.

Only count clients that are actually components of the workspace, since
these are the ones that make an object a sub-node of a bigger model.

Closes root-project#23221.

🤖 Done with the help of AI

(cherry picked from commit 4ca8422)
Behaviour-preserving cleanup of roofit/hs3, motivated by keeping the line
count in check after the fix for root-project#23221:

  * Build error messages with string concatenation instead of a
    `std::stringstream` whose only purpose is to feed `error()`, and drop
    the `return`s after `error()`, which is `[[noreturn]]`.
  * Share the "find the category observable" loop between the two dataset
    export functions, and the name-index construction between "functions"
    and "distributions".
  * HistFactory: factor out the repeated modifier node creation and the
    constraint queueing loops, drop the unreachable "optionally" branch of
    `optionallyExportGammaParameters()` (`forceExport` was always true),
    merge `hasStaterror()` into `findStaterror()`, and drop a `std::map`
    presence check that `operator[]` already covers.
  * RooFitCore: `readBinning()` reimplemented `RooJSONFactoryWSTool::readAxes()`,
    the RealSumPdf/RealSumFunc importer and exporter pairs are now
    templates, `writePolynomialBody()` is inlined into its single caller,
    and the manual `push_back` loops use the existing `operator<<` for
    JSON sequences.
  * Drop unused includes and dead locals.

Verified that the exported JSON for HistFactory, RealSum, Polynomial,
Spline and ParamHistFunc models is byte-identical before and after.

🤖 Done with the help of AI

(cherry picked from commit b34bfe6)
@guitargeek
guitargeek merged commit 8e5b0b0 into root-project:v6-40-00-patches Sep 2, 2026
33 of 34 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants