Skip to main content

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.py folds append with groupby.apply(list) rather than agg(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 by test_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)

Source distribution for eclear 0.1.0
File Size Uploaded
eclear-0.1.0.tar.gz 347.0 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for eclear 0.1.0
File Interpreter ABI Platform
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}

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page