eclear
Event and case log enrichment widget for Python notebooks.
eclear sits between loading an event log and analysing it. It derives new
columns on the event log (binning, arithmetic, time deltas, running
aggregations) and folds the event log into a case log (activity counts,
first/last occurrence, delays, attribute tracking) — through a widget, so the
columns are chosen by clicking rather than by writing another groupby.
Every applied column records the spec that produced it on the frame's attrs,
so an enriched log carries its own provenance and can be replayed.
pip install eclear
Use
Hand it an event log and the three column names that identify its axes:
from eclear import EnrichmentWidget
enricher = EnrichmentWidget(
event_log,
case_id_col="case:concept:name",
time_col="time:timestamp",
activity_col="concept:name",
)
enricher
Stage the enrichments you want in the widget, preview them on a handful of real cases, then apply. Two frames come back out:
enricher.event_log # the enriched event log
enricher.case_log # the case log folded out of it
Both are ordinary pandas DataFrames — adjust either by hand afterwards.
In a reactive notebook (marimo), pass on_apply so downstream cells re-run when
the user applies:
enricher = EnrichmentWidget(event_log, ..., on_apply=lambda: set_applied(True))
How staging works
Enrichments are staged, not applied on click. Staging is free — it costs a chip in the schema rail and nothing else — so you can assemble a whole batch, see what it would do to the schema, preview the values, and only then pay for the computation over the full log. Removals stage the same way, which is what makes an over-enriched log recoverable without starting over.
Applying recomputes rather than patches: the surviving specs are re-applied to a
fresh base log. Both apply_specs and apply_event_specs are idempotent, so
this is cheap insurance against a column drifting out of step with the spec that
claims to have produced it.
An applied event column becomes a source the case tab can track, which is also why removing one can be refused.
Requirements
Python 3.13+, and pandas 3. The engine itself needs nothing but pandas and
numpy; the widget adds anywidget and traitlets. Rendering needs a notebook
that speaks anywidget — marimo, Jupyter, VS Code.
Development
uv sync
uv run pytest
The frontend is React + TypeScript, bundled with esbuild:
cd js
npm install
npm run build # writes ../eclear/static/enrichment.js
npm test # vitest
npm run typecheck
eclear/static/enrichment.js is committed on purpose. It is what the widget
loads at import, so installing from PyPI needs no Node toolchain. Rebuild and
commit it whenever the frontend changes.
Cross-language contracts
Three functions are written twice, once in Python and once in TypeScript.
eclear/contracts/*.json holds tables asserted by both suites, so a change to
one half fails on the other. Python is the reference: a spec is stored on the
frame and replayed through Python, so Python's answer is the one that has to
survive. See eclear/contracts/README.md.
Implementation notes
enrichment/enrichers.pyfoldsappendwithgroupby.apply(list)rather thanagg(list). On pandas 3 the latter tries to fit the list back into the column's own dtype and raises on a categorical, which is what every binning enrichment produces. Pinned bytest_tracking_a_categorical_column.- Two tests assert that a missing-activity column is a timedelta without pinning
its resolution: pandas infers that from the log's timestamps and changed it
between 2.x (
ns) and 3.x (us).
License
GNU Affero General Public License v3.0 or later — see LICENSE.
Metadata
Release files for eclear 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| eclear-0.1.0.tar.gz | 347.0 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| eclear-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 603.6 kB
Release files / eclear-0.1.0.tar.gz
| Download URL | eclear-0.1.0.tar.gz |
|---|---|
| Size | 347.0 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
8feb06697b97c962f07c7ad59a53a801910faf91e3d9e619fb3ddaea0207ceaa
|
|
BLAKE2b-256 checksum How to use checksums |
21bd8c1f1012ac15e7d78e3136602783ac1498cb4e6f1c9d0118317c2b337a1f
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.11.12 {"installer":{"name":"uv","version":"0.11.12","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Fedora Linux","version":"44","id":"","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
|
Release files / eclear-0.1.0-py3-none-any.whl
| Download URL | eclear-0.1.0-py3-none-any.whl |
|---|---|
| Size | 256.6 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
5c492aaef2bf382dd212d7c5ba6e7ad2ba658380093cb0d00365d92d58488e63
|
|
BLAKE2b-256 checksum How to use checksums |
921198da39f46cf311bf69d6628822b195a3fc1df38499559d9f228179523c35
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.11.12 {"installer":{"name":"uv","version":"0.11.12","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Fedora Linux","version":"44","id":"","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
|