Rule Registry#
Classes#
RuleRegistry#
- class iguanas.rule_registry.RuleRegistry[source]#
Bases:
objectStore, version, and compare named rule snapshots.
Each snapshot records the rule list, optional metrics, optional metadata, and a UTC timestamp. The registry can be persisted to/from a JSON file for cross-session use, or kept in-memory only.
- Parameters:
path (str | Path | None, default=None) – Path to a JSON file used for persistence. If the file already exists it is loaded on construction. If
None, the registry is in-memory only and snapshots are lost when the object is garbage-collected.
Examples
>>> registry = RuleRegistry("rules.json") >>> registry.save("v1", rules=['(X["age"] > 30)']) >>> registry.list() ['v1'] >>> entry = registry.load("v1") >>> entry["rules"] ['(X["age"] > 30)']
- save(name: str, rules: list[str], metrics: polars.DataFrame | None = None, metadata: dict[str, Any] | None = None) None[source]#
Save a named ruleset snapshot.
Overwrites any existing snapshot with the same name.
- Parameters:
name (str) – Snapshot identifier.
rules (list[str]) – Rule expression strings to store.
metrics (pl.DataFrame | None, default=None) – Optional metrics DataFrame (e.g. from
compute_metrics()). Stored internally as a list of dicts for JSON compatibility.metadata (dict | None, default=None) – Arbitrary key-value metadata (e.g. threshold settings, dataset description, experiment notes).
- load(name: str) dict[str, Any][source]#
Load a saved snapshot by name.
- Parameters:
name (str) – Snapshot name to retrieve.
- Returns:
Dict with keys:
"rules"— list of rule expression strings"metrics"—pl.DataFrameif metrics were saved, elseNone"metadata"— dict of metadata"saved_at"— ISO-8601 UTC timestamp string
- Return type:
dict
- Raises:
KeyError – If no snapshot with the given name exists.
- delete(name: str) None[source]#
Delete a snapshot by name.
- Parameters:
name (str) – Snapshot to remove.
- Raises:
KeyError – If no snapshot with the given name exists.
- compare(name_a: str, name_b: str, metric_cols: list[str] | None = None) polars.DataFrame[source]#
Compare saved metrics of two snapshots side by side.
- Parameters:
name_a (str) – Name of the first snapshot.
name_b (str) – Name of the second snapshot.
metric_cols (list[str] | None, default=None) – Metric columns to include. When
None, all columns present in both snapshots (excluding"rule") are used.
- Returns:
One row per rule found in either snapshot. Metric columns are suffixed with
_{name_a}and_{name_b}. Rules absent from one snapshot produce null values for its columns.- Return type:
pl.DataFrame
- Raises:
ValueError – If either snapshot was saved without a metrics DataFrame.
KeyError – If either snapshot name does not exist.
Functions#
filter_rule_pairs_by_overlap#
- iguanas.rule_registry.filter_rule_pairs_by_overlap(R: polars.DataFrame, min_overlap: float = 0.0, max_overlap: float = 1.0) polars.DataFrame[source]#
Return rule pairs whose Jaccard overlap falls within
[min_overlap, max_overlap].Jaccard similarity is defined as (samples flagged by both) / (samples flagged by either). The two bounds let you slice any region of the overlap spectrum:
Disjoint pairs (never co-fire):
max_overlap=0.0Near-disjoint pairs:
max_overlap=0.1All pairs: defaults
min_overlap=0.0, max_overlap=1.0Redundant pairs (near-identical):
min_overlap=0.9
- Parameters:
R (pl.DataFrame) – Boolean DataFrame of rule predictions (columns = rules, rows = samples).
min_overlap (float, default=0.0) – Lower Jaccard bound (inclusive). Pairs with
jaccard < min_overlapare excluded.max_overlap (float, default=1.0) – Upper Jaccard bound (inclusive). Pairs with
jaccard > max_overlapare excluded.
- Returns:
Matching rule pairs with columns:
rule_a,rule_b,jaccard,flagged_by_both,flagged_by_either. Sorted byjaccardascending. Returns an empty DataFrame with the correct schema when no pairs match.- Return type:
pl.DataFrame
Examples
>>> import polars as pl >>> R = pl.DataFrame({ ... "rule_A": [True, True, False, False], ... "rule_B": [False, False, True, True], # disjoint from rule_A ... "rule_C": [True, False, True, False], ... }) >>> filter_rule_pairs_by_overlap(R, max_overlap=0.0) # only disjoint pairs shape: (1, 5) # rule_A vs rule_B >>> filter_rule_pairs_by_overlap(R, min_overlap=0.3) # only overlapping pairs