Skip to main content

Histogramming as a Service

Project description

Histogramming as a Service (HistServ)

PyPI version Conda-Forge PyPI platforms

Install from PyPI

pip install histserv

Install from conda-forge

conda install -c conda-forge histserv

Quickstart

Start the async gRPC server (or just ./example/start_server.sh):

histserv --port 50051
# 2026-03-26 11:58:00.643 INFO:histserv:server (listening at [::]:50051) started with port=50051, prune_after=24.00 h, prune_interval=5.00 min, stats_interval=5.00 s

Then run:

from hist import Hist
from histserv import Client
import numpy as np


# initialize hist locally
H_local = Hist.new.Reg(30, -3, 3, name="x", label="x-axis").Double()

with Client(address="[::]:50051") as client:
    # initialize it on the server and receive a remote hist to interact with it
    H_remote = client.init(H_local)
    # fill the remote hist; the client pre-bins locally and sends dense storage
    H_remote.fill(x=np.random.normal(size=1000))
    # retrieve it back as a ChunkedHist, drop it from the server, and materialize it locally
    H_snapshot = H_remote.snapshot(delete_from_server=True)
    print(H_snapshot.to_hist())


# local hist hasn't been filled
assert np.all(H_local.view(True) == 0)

Output in ipython:

┌────────────────────────────────────────────────────────────────────────────┐
[-inf,   -3) 1  │▋                                                           [  -3, -2.8) 0                                                              [-2.8, -2.6) 1  │▋                                                           [-2.6, -2.4) 1  │▋                                                           [-2.4, -2.2) 6  │████                                                        [-2.2,   -2) 11 │███████▍                                                    [  -2, -1.8) 12 │████████                                                    [-1.8, -1.6) 20 │█████████████▍                                              [-1.6, -1.4) 19 │████████████▊                                               [-1.4, -1.2) 33 │██████████████████████▏                                     [-1.2,   -1) 50 │█████████████████████████████████▌                          [  -1, -0.8) 70 │██████████████████████████████████████████████▉             [-0.8, -0.6) 49 │████████████████████████████████▉                           [-0.6, -0.4) 88 │███████████████████████████████████████████████████████████ [-0.4, -0.2) 63 │██████████████████████████████████████████▎                 [-0.2,    0) 65 │███████████████████████████████████████████▋                [   0,  0.2) 85 │█████████████████████████████████████████████████████████   [ 0.2,  0.4) 77 │███████████████████████████████████████████████████▋        [ 0.4,  0.6) 65 │███████████████████████████████████████████▋                [ 0.6,  0.8) 61 │████████████████████████████████████████▉                   [ 0.8,    1) 63 │██████████████████████████████████████████▎                 [   1,  1.2) 45 │██████████████████████████████▏                             [ 1.2,  1.4) 36 │████████████████████████▏                                   [ 1.4,  1.6) 32 │█████████████████████▌                                      [ 1.6,  1.8) 15 │██████████                                                  [ 1.8,    2) 11 │███████▍                                                    [   2,  2.2) 10 │██████▊                                                     [ 2.2,  2.4) 3  │██                                                          [ 2.4,  2.6) 5  │███▍                                                        [ 2.6,  2.8) 2  │█▍                                                          [ 2.8,    3) 1  │▋                                                           [   3,  inf) 0                                                              │
└────────────────────────────────────────────────────────────────────────────┘

Dashboard

histserv includes an optional real-time observability dashboard. It is a read-only web UI that shows server health, lists live histograms, and renders them as they are filled.

Install the dashboard extra

pip install "histserv[dashboard]"

This pulls in FastAPI, uvicorn, and httpx alongside the base install.

Start the server with the dashboard

Pass --dashboard-port to expose the observability interface:

histserv --port 50051 --dashboard-port 8050

Open http://localhost:8050 in a browser (once a frontend bundle has been built; see below) or connect directly to the WebSocket at ws://localhost:8050/ws.

The dashboard port exposes:

Path Description
GET /api/histograms/{hist_id}/metadata Histogram metadata including chunk-axis categories
GET /api/histograms/{hist_id} One-shot JSON snapshot of a selected dense chunk
WS /ws Subscription-based streaming protocol (primary)
/* Serves the built Svelte frontend (production only)

WebSocket protocol

All messages share an envelope:

{ "type": "string", "ts": 1712500000.123, "payload": { ... } }

Client → server

type payload description
subscribe { "streams": ["stats", "hist_list"] } Periodic server stats and histogram list
subscribe_hist { "hist_id": "…", "selection": { "dataset": "data" }, "rate_limit_hz": 1 } Stream one dense chunk
unsubscribe_hist { "hist_id": "…", "selection": { "dataset": "data" } } Stop streaming one dense chunk
get_hist { "hist_id": "…", "selection": { "dataset": "data" } } One-shot dense chunk fetch

Server → client

type description
stats Server health (uptime, rpc counts, cpu, memory) — ~1 s
hist_list Live histogram summaries, including current chunk-axis categories — ~2 s
hist_meta One-shot dense histogram schema for a selected histogram
hist_data Dense chunk payload (selection, values, version)
error { "message": "…", "code": "NOT_FOUND" | "INTERNAL" }

Dashboard histogram fetches always require a full chunk selection expressed as a JSON object keyed by chunk-axis name. For histograms without chunk axes, the selection is the empty object encoded as {}:

/api/histograms/<hist_id>?selection=%7B%7D

Examples

See example/ for more examples.

Run example client:

python example/client.py
# Remote hist initialized: RemoteHist(hist_id='52c77c93da8146f2a72c53af269d1ab5', address='[::]:50051', token=None)
# Remote hist fill succeeded.
# Snapshotting current hist: ChunkedHist(...)
# Remote hist fill succeeded.
# Remote hist fill succeeded.
# Remote hist flushed successfully to hist.h5.

Or check out how to use remote histogram filling with an example coffea Processor in example/coffea_processor.py.

Useful client methods on RemoteHist:

  • fill(...)
  • fill_many([...])
  • snapshot(delete_from_server=False)
  • reset()
  • exists()
  • get_connection_info()
  • RemoteHist.from_connection_info(...)
  • flush(destination="hist.h5")
  • delete()

Current supported types

Axis support:

  • hist.axis.Regular without transforms
  • hist.axis.Boolean
  • hist.axis.Variable
  • hist.axis.Integer
  • hist.axis.IntCategory
  • hist.axis.StrCategory

Storage support:

  • hist.storage.Double
  • hist.storage.Int64
  • boost_histogram.storage.AtomicInt64
  • hist.storage.Weight
  • boost_histogram.storage.Unlimited

Unsupported today:

  • transformed hist.axis.Regular
  • boost_histogram.storage.Mean
  • boost_histogram.storage.WeightedMean

Notes:

  • Growable categorical axes (IntCategory, StrCategory) are treated as chunk keys rather than dense axes.
  • Histograms with one or more growable categorical axes are supported; the categorical values must be provided as scalars when filling.
  • On the wire, fills are sent as dense per-chunk payloads rather than as generic Python objects.
  • RemoteHist.snapshot() returns a ChunkedHist; call .to_hist() to materialize a local hist.Hist.
  • fill_many(...) is useful for bundling several fills into one gRPC request.
  • Dense ndarray transport is generic over NumPy dtypes, but object arrays are not supported on the wire.

Developer Info

Install

uv sync --dev

Test

python -m pytest -q
uvx ty check src

Protobuf Codegen

python -m grpc_tools.protoc -Isrc/histserv/protos --python_out=src/histserv/protos --pyi_out=src/histserv/protos --grpc_python_out=src/histserv/protos src/histserv/protos/hist.proto

After regeneration, ensure src/histserv/protos/hist_pb2_grpc.py keeps the package-relative import:

from . import hist_pb2 as hist__pb2

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

histserv-0.1.9.tar.gz (41.2 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

histserv-0.1.9-py3-none-any.whl (38.8 kB view details)

Uploaded Python 3

File details

Details for the file histserv-0.1.9.tar.gz.

File metadata

  • Download URL: histserv-0.1.9.tar.gz
  • Upload date:
  • Size: 41.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for histserv-0.1.9.tar.gz
Algorithm Hash digest
SHA256 cedffcbe1716b48d3543ac52a07241154e8e5f74e7a6bc4f9283ef8132f51574
MD5 1b304104d7c3eaebce165f99d5d0f451
BLAKE2b-256 3289d4b5622c62e82cfa6f509cd9edc1d0187f97d0bea7f65ed43157aa344af5

See more details on using hashes here.

Provenance

The following attestation bundles were made for histserv-0.1.9.tar.gz:

Publisher: cd.yml on pfackeldey/histserv

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file histserv-0.1.9-py3-none-any.whl.

File metadata

  • Download URL: histserv-0.1.9-py3-none-any.whl
  • Upload date:
  • Size: 38.8 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for histserv-0.1.9-py3-none-any.whl
Algorithm Hash digest
SHA256 5296b60d8c70accafc97c6d1884be46170530d70e329ded882529e9a621b8d59
MD5 e8e54eda55730e4915bb8c1aa9230ec9
BLAKE2b-256 29d5f42814511f6cf9f9a360d6c37513ee379363cd900b0cb592929d020d1a07

See more details on using hashes here.

Provenance

The following attestation bundles were made for histserv-0.1.9-py3-none-any.whl:

Publisher: cd.yml on pfackeldey/histserv

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page