Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
a422014
HIST-1: hist.graphed — deferred hist filling on graphed task graphs (…
lgray Jun 10, 2026
329f859
ci: hist's test deps are a PEP 735 dependency group — install with --…
lgray Jun 11, 2026
954e68f
freeze-HIST-2: respin to graphed's evaluation idiom — no compute()
lgray Jun 11, 2026
aace67f
ci: graphed-histogram repo renamed to graphed-histogram-mvp
lgray Jun 11, 2026
83c3b1e
M32: import SequentialRunner from graphed_core.execution (was graphed…
lgray Jun 13, 2026
a96160f
refactor(deps): consume the consolidated graphed package
lgray Jul 18, 2026
d4d83b7
test: migrate ProcessExecutor -> ProcessPoolExecutor (exec-local depr…
lgray Jul 18, 2026
a9de0a8
chore: track graphed-exec-local -> graphed-executors + histogram repo…
lgray Jul 18, 2026
282a99e
ci: install graphed-executors + graphed-histogram from PyPI (now rele…
lgray Jul 18, 2026
3d27322
use graphed from pypi as well
lgray Jul 20, 2026
dfb4790
chore(graphed): let mypy ignore missing graphed_histogram stubs
lgray Sep 5, 2026
4e05e1b
fix(graphed): pass variation_axis/unweighted through Hist.fill
lgray Sep 5, 2026
cb48786
ci(graphed): install the graphed stack from git main, not PyPI
lgray Sep 5, 2026
0b9efb1
chore: drop the graphed-project machinery from the upstream PR
lgray Sep 14, 2026
e2f3980
ci: graphed is a test dependency on Python 3.11+
lgray Sep 14, 2026
44f6358
style: ruff
lgray Sep 14, 2026
f1e4108
docs: say what the graphed hooks do without the project's labels
lgray Sep 14, 2026
8bc3281
test: skip the uproot end-to-end fill when uproot lacks uproot.graphed
lgray Sep 14, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,10 @@ test = [
{ include-group = "test-core" },
{ include-group = "fit" },
"awkward>=2.0.7",
# tests/test_graphed.py; graphed requires Python 3.11+
'graphed[awkward,numpy]>=0.0.2;python_version>="3.11"',
'graphed-histogram>=0.0.2;python_version>="3.11"',
'graphed-executors>=0.0.2;python_version>="3.11"',
]
test-core = [
"pytest >=8",
Expand Down Expand Up @@ -158,6 +162,7 @@ module = [
"iminuit.*",
"mplhep.*",
"dask_histogram.*",
"graphed_histogram.*",
]
ignore_missing_imports = true

Expand Down
15 changes: 15 additions & 0 deletions src/hist/graphed/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
from __future__ import annotations

import importlib.util

if not importlib.util.find_spec("graphed_histogram"):
msg = """for hist.graphed, install the 'graphed_histogram' package with:
pip install graphed_histogram"""
raise ModuleNotFoundError(msg)

from .hist import Hist
from .namedhist import NamedHist

new = Hist.new

__all__ = ["Hist", "NamedHist", "new"]
57 changes: 57 additions & 0 deletions src/hist/graphed/hist.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
from __future__ import annotations

from typing import Any, Generic, TypeVar

import boost_histogram as bh
import graphed_histogram.boost as ghb

import hist

from ..hist import Hist as HistInMemory

S = TypeVar("S", bound=bh.storage.Storage)


class FillModeMixin:
"""Routes graphed's fill-MODE flags past hist's named-axis fill.

`BaseHist.fill` resolves every keyword as an axis name, so `variation_axis=`/`unweighted=`
die at `_name_to_index` before reaching `graphed_histogram.boost.Histogram.fill`. When one is
set, resolve the axis names here and call graphed's fill directly; otherwise defer to hist
unchanged.
"""

def fill(
self,
*args: Any,
weight: Any = None,
sample: Any = None,
threads: int | None = None,
unweighted: bool = False,
variation_axis: bool = False,
**kwargs: Any,
) -> Any:
base: Any = self
if not (unweighted or variation_axis):
return super().fill( # type: ignore[misc]
*args, weight=weight, sample=sample, threads=threads, **kwargs
)
by_index = {base._name_to_index(k): v for k, v in kwargs.items()}
return ghb.Histogram.fill(
base,
*args,
*(by_index[i] for i in sorted(by_index)),
weight=weight,
sample=sample,
threads=threads,
unweighted=unweighted,
variation_axis=variation_axis,
)


class Hist(FillModeMixin, HistInMemory[S], ghb.Histogram, Generic[S], family=hist): # type: ignore[misc]
"""A `hist.Hist` whose fills are DEFERRED graphed computations: QuickConstruct
(`Hist.new.Reg(...).Double()`) and named-axis fills record into the graphed IR. Evaluation
is graphed's own idiom — `plan()` + a graphed executor (whose result wraps back into an
in-memory `hist.Hist` via `hist.Hist(value)`), or the reference `session.materialize` on a
fill node."""
23 changes: 23 additions & 0 deletions src/hist/graphed/namedhist.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
from __future__ import annotations

from typing import Generic, TypeVar

import boost_histogram as bh
import graphed_histogram.boost as ghb

import hist

from ..namedhist import NamedHist as NamedHistInMemory
from .hist import FillModeMixin

S = TypeVar("S", bound=bh.storage.Storage)


class NamedHist( # type: ignore[misc]
FillModeMixin,
NamedHistInMemory[S],
ghb.Histogram, # type: ignore[misc]
Generic[S],
family=hist,
):
pass
Loading