Skip to content

RooFit classes with hand-written streamers (RooRealVar, RooLinkedList, ...): implement per root-io-spec RooFit, replacing the framing-layer special cases #71

Open

Description

@nsmith-

🤖 AI generated content

Line item of #9: RooRealVar not declared in the StreamerInfo (uproot-issue49.root, uproot-issue-350.root), and the classes/roofit.root fixture.

Scope (maintainer, updated 2026-09-30): RooFit is in scope. The original decision was to skip RooFit until root-io-spec specified it. The spec now does, in RooFit (added upstream in 5d6a95b and already in our pinned submodule, c65c464). Its §8 erratum 1 withdraws the spec's own earlier "out of scope" decision.

What the spec covers. Five classes have hand-written Streamers (§1): RooRealVar (§2), RooLinkedList (§3), RooAbsBinning (§4.1), RooRefArray (§4.2) and RooCategory below class version 3 (§5). Every other RooFit class, RooVectorDataStore included, is driven by its streamer info. §6 gives the read steps, and §7 gives the invariants. None of the five is extending: each one ends where its byte count says, where it has one.

Our current workarounds, checked against the spec:

Where What it does Spec
src/rootfilespec/dynamic.py:87-89 Raises NotImplementedError for RooRealVar §2: specified. No file has an info for it (§2.3), so it needs a hand-written reader
src/rootfilespec/bootstrap/streamedobject.py:257-260 Reads "extra data after the RooRealVar object" §8 erratum 2: that data is RooRealVar's own tail, inside its byte count (§2.2)
src/rootfilespec/bootstrap/streamedobject.py:170-178 Reads an extra stream header before RooAbsCategory §8 erratum 3: the frame belongs to RooCategory, and only below class version 3 (§5)
src/rootfilespec/container.py:212-214 Reads two collection frames for RooVectorDataStore::RealVector::_vec §8 erratum 5: one collection frame and one class frame (Collections §3.1)
src/rootfilespec/bootstrap/assumed.py:75 RooLinkedList Reads TObject, _hashThresh: >h, fSize: >i, then slots §3.2 / §8 erratum 4: the first two bytes are the version word, _hashThresh is never written, and at versions 2–3 a TString follows the slots. The missing TString is the likely cause of the current classes/roofit.root failure: buffer not empty after reading object of type RooLinkedList

To do:

Severity / size: medium, M. It's more than the original "documented skip", but every class now has a specified layout and a fixture.

Related: #9, #74, #69, #67, ariostas/root-io-spec#1 (items 7–10, corrected by the errata above).

Assisted-by: claude-code:claude-opus-5-5

Activity

  1. changed the title [-]RooFit classes with hand-written streamers (RooRealVar, ...): documented skip, and move the RooFit special cases out of the framing layer[/-] [+]RooFit classes with hand-written streamers (RooRealVar, RooLinkedList, ...): implement per root-io-spec RooFit, replacing the framing-layer special cases[/+] on Sep 30, 2026
  2. nsmith- commented on Sep 30, 2026

    @nsmith-
    OwnerAuthor

    🤖 AI generated content

    Rescoped: RooFit is now in scope, because root-io-spec specifies it in spec/03-classes/RooFit.md, which is already in our pinned submodule (c65c464). I rewrote the body. The main changes:

    • The skip became an implementation plan.
    • Each of our RooFit workarounds is checked against the spec's errata. Three of them rest on claims the spec has since corrected.
    • The classes/roofit.root failure probably comes from RooLinkedList missing its trailing TString.

    The original decision and the notes on the RooRealVar layout are in this issue's edit history.

    Assisted-by: claude-code:claude-opus-5-5

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions