leds
An event viewer for the LEGEND experiment: a Panel dashboard with event display, waveforms, spectra, dataset-metadata and validation views over a legend-dataflow production cycle.
Running
pip install legend-leds # or: uv pip install .
leds app /path/to/production_cycle # local single-user browser tab
leds app --desktop /path/to/cycle # native window (needs leds[desktop])
leds serve /path/to/cycle --port 5006 # hosted multi-user server
The production-cycle path (a directory containing dataflow-config.yaml, or a
directory of such cycles) can also come from $LEDS_BASE_PATH; several paths
may be listed separated by :.
Deployment (NERSC Spin)
The Dockerfile builds a slim two-stage image by cloning this repository:
docker build -t registry.nersc.gov/<project>/leds:latest \
--build-arg LEDS_REPO=https://github.com/legend-exp/leds.git \
--build-arg LEDS_REF=main .
docker push registry.nersc.gov/<project>/leds:latest
(Point LEDS_REPO at a fork while changes are not upstream yet.) The container
listens on port 5006 and runs under an arbitrary non-root UID, as Spin requires.
Service environment
| Variable | Required | Meaning |
|---|---|---|
LEDS_BASE_PATH |
yes | production cycle(s) on the mounted filesystem (e.g. CFS) |
BOKEH_ALLOW_WS_ORIGIN |
yes | public hostname (host[:port]) allowed to open the websocket, i.e. the Spin ingress name |
NUM_PROCS |
no (default 2) | Panel worker processes; sessions in one process share its caches (and its HDF5 lock, see Threads) |
NUM_THREADS |
no (default 4) | thread pool per worker that callbacks run on, so one session's slow read does not freeze the others; 0 disables it (see Threads) |
LEDS_PREWARM |
no (default on) | scan cycles and build the newest channelmap before forking workers, so the first session of each is warm; delays the listening socket; 0 disables |
LEDS_CACHE_TTL |
no (default 3600) | seconds a metadata-derived entry (channelmaps, statuses, calibration pars) is reused before being re-read |
LEDS_SCAN_TTL |
no (default 300) | seconds a directory scan is reused; bounds how long a newly-written run stays invisible |
LEDS_MAX_CACHED_RUN_SPECTRA |
no (default 4) | whole runs of per-hit energies held per worker; the dominant memory line |
LEDS_MAX_CACHED_CAL_PARS |
no (default 4) | parsed par_hit calibration files held per worker; MB-scale each |
Sessions in one worker share the read-only data they have in common —
channelmaps, detector statuses, directory scans, per-run reductions — so a
second user on the same cycle starts nearly instantly and does not duplicate
that memory. All the bounds above are per worker process, so multiply by
NUM_PROCS when sizing the Spin memory limit.
Because that sharing includes the parsed metadata, an updated metadata checkout
is picked up within LEDS_CACHE_TTL rather than immediately. Lower it if the
deployment updates metadata often; restarting the service always picks it up at
once.
Threads
NUM_THREADS (passed by the image to leds serve --num-threads, like
NUM_PROCS to --num-procs) runs callbacks on a thread pool instead of the
worker's single event loop. Without it, one session's slow operation — a first
visit to the Validation tab, a raw read stalling on CFS — freezes the UI of
every other session in that worker until it finishes. With it those sessions
keep responding, and work that is not HDF5 (parsing a channelmap, evaluating
cuts, building Bokeh models) runs in parallel.
What it does not buy: h5py serialises every HDF5 call behind one process-wide
lock, so two sessions' raw reads still take turns within a worker. NUM_PROCS
is the lever for that; the two combine.
Per-session state — the viewer's caches and open HDF5 handles, the spectrum accumulator, the tab bookkeeping — is guarded by one lock per session, so a session's own callbacks never overlap even though they run on the pool. Open HDF5 handles are per session and never shared across sessions or forked workers. A playback tick that arrives while the previous frame is still rendering is dropped rather than queued.
Login (Spin secrets)
Without any of the variables below the server is open. In all authenticated
setups set a fixed LEDS_COOKIE_SECRET — with an ephemeral one, logins
break on every restart and across the NUM_PROCS workers.
Option A — shared password / user list: set LEDS_BASIC_AUTH to either a
single shared password or a path to a mounted JSON file of
{"username": "password"}.
Option B — LDAP (takes precedence over LEDS_BASIC_AUTH): users sign in
with their directory credentials. Fill the values in from the LEGEND LDAP
administrators:
| Variable | Required | Meaning |
|---|---|---|
LEDS_LDAP_SERVER |
yes (enables LDAP) | e.g. ldaps://ldap.legend.example:636 |
LEDS_LDAP_USER_DN_TEMPLATE |
direct-bind mode | e.g. uid={username},ou=people,dc=legend,dc=example |
LEDS_LDAP_BIND_DN / LEDS_LDAP_BIND_PASSWORD |
search-bind mode | read-only service account (as a Spin secret) |
LEDS_LDAP_SEARCH_BASE |
search-bind mode | subtree searched for the user entry |
LEDS_LDAP_USER_FILTER |
no (default (uid={username})) |
search filter template |
LEDS_LDAP_GROUP_DN |
no | if set, only members (member/uniqueMember/memberUid) of this group may log in |
LEDS_LDAP_STARTTLS |
no | 1 upgrades an ldap:// connection via StartTLS |
LEDS_LDAP_CA_FILE |
no | CA bundle path (mount as a secret); defaults to certifi's bundle |
Configure either LEDS_LDAP_USER_DN_TEMPLATE (direct bind) or the three
search-bind variables; if both are present, direct bind wins. Server
certificates are always verified. Bad credentials, unknown users and non-members
all get the same generic login error; infrastructure failures are reported as
"authentication service unavailable" with details in the container log only.
To try the LDAP flow locally against a throwaway directory:
docker run --rm -d -p 1389:1389 -e LDAP_ADMIN_PASSWORD=adminpw \
-e LDAP_USERS=alice -e LDAP_PASSWORDS=alicepw bitnamilegacy/openldap
LEDS_LDAP_SERVER=ldap://localhost:1389 \
LEDS_LDAP_USER_DN_TEMPLATE="cn={username},ou=users,dc=example,dc=org" \
LEDS_COOKIE_SECRET=devsecret leds serve /path/to/cycle
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file legend_leds-0.0.3.tar.gz.
File metadata
- Download URL: legend_leds-0.0.3.tar.gz
- Upload date:
- Size: 135.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b657a8178887e5271aca9bc32bd5c79a526e0e4e8cd4dd35e1200079a6083ad4
|
|
| MD5 |
2db21f330cf8b8ec93c88937cb811dd2
|
|
| BLAKE2b-256 |
cded14d43372b6c630bf53914a4c7502b0073c1cccaa0df271c7a0638dbe6dd3
|
Provenance
The following attestation bundles were made for legend_leds-0.0.3.tar.gz:
Publisher:
distribution.yml on legend-exp/leds
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
legend_leds-0.0.3.tar.gz -
Subject digest:
b657a8178887e5271aca9bc32bd5c79a526e0e4e8cd4dd35e1200079a6083ad4 - Sigstore transparency entry: 2692400116
- Sigstore integration time:
-
Permalink:
legend-exp/leds@40d1863c7bf372f1f91bfca118305672181c7490 -
Branch / Tag:
refs/tags/v0.0.3 - Owner: https://github.com/legend-exp
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
distribution.yml@40d1863c7bf372f1f91bfca118305672181c7490 -
Trigger Event:
release
-
Statement type:
File details
Details for the file legend_leds-0.0.3-py3-none-any.whl.
File metadata
- Download URL: legend_leds-0.0.3-py3-none-any.whl
- Upload date:
- Size: 124.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
4e0a69e5463eeb7f03fc78d12f1129e3ff77be31dc15eeb3d94f473d666547fa
|
|
| MD5 |
43150c3ed94b631c4695e8a93e9dd2c0
|
|
| BLAKE2b-256 |
f2be0dd86b9b0f7cf7933caca9d899d914329d983f8f9498ba82c786393eb208
|
Provenance
The following attestation bundles were made for legend_leds-0.0.3-py3-none-any.whl:
Publisher:
distribution.yml on legend-exp/leds
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
legend_leds-0.0.3-py3-none-any.whl -
Subject digest:
4e0a69e5463eeb7f03fc78d12f1129e3ff77be31dc15eeb3d94f473d666547fa - Sigstore transparency entry: 2692400436
- Sigstore integration time:
-
Permalink:
legend-exp/leds@40d1863c7bf372f1f91bfca118305672181c7490 -
Branch / Tag:
refs/tags/v0.0.3 - Owner: https://github.com/legend-exp
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
distribution.yml@40d1863c7bf372f1f91bfca118305672181c7490 -
Trigger Event:
release
-
Statement type: