pyfracval.event_log#

Structured, append-only event log for aggregate generation.

Existing telemetry answers “did this run succeed”. A paper needs something else: where generation fails, why, and how badly - pooled over thousands of runs and sliceable by the physics (Df, kf, sigma_p,geo, N). Free-text log lines cannot be aggregated, and the in-memory diagnostics dict run_simulation accepts is per-call and never persisted.

This module writes one JSONL file carrying three record kinds, each stamped with the same run context so they can be sliced or joined together:

merge

One CCA merge attempt: which round, which cluster pair, the contact distance attempted, how much of the search was consumed, the outcome, and - when a census ran - how many particles ended up overlapping and by how much.

pca_failure

A PCA subcluster that could not be built: at which particle index, with how many candidate partners available, after how many search/swap attempts. Without this, “where does it fail” cannot distinguish a PCA failure from a CCA one with any detail, even though both occur.

run

One completed or abandoned aggregate: outcome, failure stage and reason, attempts consumed, wall time, and the final geometry’s measured quality.

Enable with OrchestratorAlgorithmConfig.event_log_path. Nothing is written and no file is opened when it is unset.

Concurrency: records are written as single write() calls of one line each in append mode, which is atomic enough on POSIX for several Dask workers to share one path. Every record carries run_id and pid so interleaved lines can always be separated again.

Module Contents#

class pyfracval.event_log.MergeEvent[source]#

One CCA merge attempt between two clusters.

round_index[source]#

Which CCA round (1-based). Round 1 merges the initial PCA subclusters - the round essentially every hard-regime failure occurs in (docs/source/pairing_frustration.md).

Type:

int

pool_size[source]#

Number of clusters in the pool at the start of this round.

Type:

int

cluster_idx1, cluster_idx2

Indices of the two clusters within the round’s pool.

Type:

int

n1, n2

Particle counts of the two clusters.

Type:

int

gamma_pc[source]#

Scaling-law contact distance the merge was attempted at.

Type:

float

gamma_real[source]#

Whether the Gamma equation had a real solution at all.

Type:

bool

sum_rmax[source]#

r_max1 + r_max2; the cheap feasibility gate compares this against gamma_pc.

Type:

float

outcome[source]#

One of stuck, stuck_relaxed_tol, failed_no_candidates, failed_overlap, rescued_soft_relaxation, rescued_drop, failed_gamma_not_real, skipped_bv_filter.

Type:

str

candidates_tried[source]#

Number of candidate (s1, s2) monomer pairs attempted.

Type:

int

n_feasible_pairs[source]#

Size of the candidate matrix - the search space available.

Type:

int

rotations_used[source]#

Rotation steps consumed on the final candidate attempted.

Type:

int

min_overlap[source]#

Best (smallest) max-overlap reached, normalized by r_i + r_j so it is directly comparable to tol_ov.

Type:

float

n_offending_particles[source]#

Distinct particles involved in a residual overlap at give-up.

Type:

int | None

n_pairs_overlapping[source]#

Overlapping pairs at give-up.

Type:

int | None

max_overlap_of_rsum[source]#

Worst residual overlap at give-up, normalized by r_i + r_j and therefore comparable to tol_ov.

Type:

float | None

max_overlap_of_rmin[source]#

The same overlap normalized by min(r_i, r_j). Recorded separately because the two denominators differ by a large factor for wide size distributions and must never be conflated.

Type:

float | None

n_particles_dropped[source]#

Particles removed by drop-rescue, when that fallback succeeded.

Type:

int

attempt_index[source]#

0-based index of this partner attempt for cluster_idx1 within the round; non-zero only under backtracking pairing, and what distinguishes “first choice worked” from “third choice worked”.

Type:

int

class pyfracval.event_log.PcaFailureEvent[source]#

A PCA subcluster that could not be completed.

PCA failure is a distinct mechanism from CCA sticking failure: it happens while growing a single subcluster particle by particle, and the usual cause is that no already-placed particle sits at a workable distance for the next monomer’s Gamma. Recording it separately is what lets a failure taxonomy attribute blame correctly instead of lumping everything under “the run failed”.

class pyfracval.event_log.RunEvent[source]#

One aggregate generation attempt, start to finish.

class pyfracval.event_log.EventLog(path, context=None, run_id=None)[source]#

Append-only JSONL sink for generation events.

set_context(**kwargs)[source]#

Merge additional fields into the per-record context.

record(event)[source]#

Append one event. Never raises: logging is diagnostic, and a full disk or bad path must not abort an aggregate mid-build.