Skip to main content

Niagara

Niagara is a causal discovery method for interval-based event sequences. It models event starts, active intervals, and event ends, and selects causal mechanisms between events using a minimum-description-length score.

This repository contains the reusable implementation accompanying the AAAI 2026 paper Causal Discovery from Interval-Based Event Sequences (see citation below). Version 0.1.0 retains the behaviour of the implementation used for the experiments in the publication. The latest version is recommended for any further experimentation.

Installation

pip install niagara-cd

Five-minute example

Provide one row per event occurrence. The columns are the event name, start time, and end time; an optional fourth column identifies a sequence. Sequences are treated as independent timelines while sharing one fitted graph and set of distribution parameters; do not offset sequences to make their timestamps non-overlapping. Times are elapsed values starting at 0 within each sequence, rather than absolute calendar dates. Pass one horizon for equal-length recordings or a mapping such as {"Sydney": 24, "London": 12} for different lengths. If omitted, each sequence's maximum recorded timestamp is used; provide it explicitly when observation continued silently after the final event.

import numpy as np

from niagara import fit

intervals = np.array(
    [
        ["rain", 0.0, 2.0],
        ["traffic", 1.0, 3.0],
        ["rain", 5.0, 7.0],
        ["traffic", 6.0, 8.0],
    ],
    dtype=object,
)

result = fit(intervals, horizon=10.0)

print(result.feature_names)
print(result.adjacency)
print(result.edges)
print(result.mechanisms)

This example produces an event-level edge from rain to traffic:

('rain', 'traffic')
[[0. 1.]
 [0. 0.]]

The feature order gives the row and column labels of the adjacency matrix. Rows are causes (parents), columns are effects (children), and a value of 1 at position [i, j] means feature_names[i] → feature_names[j]. Here, the value at row rain and column traffic is 1.

result.edges provides the same event-level result without requiring matrix indexing:

print(result.edges)
# (('rain', 'traffic'),)

To inspect whether the mechanism concerns an event starting, being ongoing, or ending, use result.mechanisms:

mechanism = result.mechanisms[0]

print(mechanism.parents)
# (Endpoint(event='rain', kind='interval'),)

print(mechanism.child)
# Endpoint(event='traffic', kind='start')

print(mechanism.operator)
# None

This means that rain being ongoing is selected as a cause of traffic starting. Endpoint kinds are start, interval, and end. For a logical mechanism with two parents, operator is and, or, or xor; it is None for a single-parent mechanism.

A Pandas DataFrame may be supplied instead when it has event, start, and end columns, plus an optional sequence column. Rows are kept in their supplied order, and event names are preserved.

Public API

fit(data, *, horizon=None, feature_names=None, config=None) fits Niagara and returns a NiagaraResult.

NiagaraConfig controls exhaustive or partial search, the maximum error proportion, the OR heuristic, and MDL precision. Defaults match the publication implementation.

Niagara discovers causes of event starts only. It does not search for causes of event ends because the causal-identifiability theory assumes exponential waiting-time distributions, whereas event durations are modeled with a log-normal distribution.

NiagaraResult.adjacency is the event-level parent-by-child adjacency matrix, labeled by NiagaraResult.feature_names on both axes. NiagaraResult.edges contains the corresponding named (parent, child) pairs. NiagaraResult.mechanisms contains the more detailed start/interval/end mechanisms as CausalMechanism objects. Use result.to_dict() or result.to_json(path) for serialization.

Command line

Given events.csv:

event,start,end
rain,0,2
traffic,1,3
rain,5,7
traffic,6,8

Run:

niagara events.csv --horizon 10 --output result.json --adjacency-output adjacency.csv

Citation

If you use Niagara, please cite:

Lénaïg Cornanguer, Joscha Cüppers, and Jilles Vreeken. Causal Discovery from Interval-Based Event Sequences. In: Proceedings of the AAAI Conference on Artificial Intelligence (AAAI), AAAI, 2026.

Citation metadata is also available in CITATION.cff.

License

Niagara is distributed under the BSD 3-Clause License.

Metadata

Release files for niagara-cd 0.2.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 niagara-cd 0.2.0
File Size Uploaded Provenance Actions
niagara_cd-0.2.0.tar.gz 26.3 kB With provenance Details for niagara_cd-0.2.0.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for niagara-cd 0.2.0
File Interpreter ABI Platform Actions
niagara_cd-0.2.0-py3-none-any.whl Python 3 none any Details for niagara_cd-0.2.0-py3-none-any.whl

Total release size: 57.3 kB

Release files / niagara_cd-0.2.0.tar.gz

Download URL niagara_cd-0.2.0.tar.gz
Size 26.3 kB
Tags Source
SHA-256 checksum
How to use checksums
dd2d17ab76e3e649697a5c400797585f95a90dc3acac904881d2d6e10d0007f3
BLAKE2b-256 checksum
How to use checksums
75f8c31bb5f765e8fdff06973575e228858e290721a4f9acb4d7b5748679afab
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 13, 2026.

Transparency log

Release files / niagara_cd-0.2.0-py3-none-any.whl

Download URL niagara_cd-0.2.0-py3-none-any.whl
Size 31.0 kB
Tags Python 3
SHA-256 checksum
How to use checksums
28276128de26d8790548ba3dd9178a44f1a7d523681fe7aca8e94271aab82ef1
BLAKE2b-256 checksum
How to use checksums
009a62272fe16194547bb6eb21e666fcf8c2c1e216030b2a04640c6c34eadb15
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 13, 2026.

Transparency log

Security for niagara-cd 0.2.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

All 2 files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for niagara_cd-0.2.0.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 13, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Release history Release notifications | RSS feed

This release

0.2.0 This release

2 release files Full provenance

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