mixle.utils.hvis.distributed module¶
Distributed / out-of-core construction of the direct layout: map-reduce over data shards.
Everything mixle.utils.hvis.direct.model_map() learns from data is ADDITIVE over shards –
posterior masses and overlaps (sum z, sqrt(z)^T sqrt(z), z^T z, triple products for the
nerve), per-(field, component) weighted moments behind the whiteners, and per-component weighted
moments of the fiber coordinates behind the chart PCA. The one order statistic (the occlusion
radius, a 90th percentile) is a cheap gather of one float per dominated point. So the whole layout
is a handful of map-reduce passes with EXACT combines – the same shape as mixle’s
estimator/accumulator machinery (seq_estimate’s Spark path, the multiprocessing/MPI encoded-
data handles), just for the visualization geometry instead of the model parameters:
fiber_stats()per shard, combined with+-> whiteners, vertices, nerve;score_stats()per shard, combined with+-> chart loadings, spreads, scale (quadratic charts whose base dimension exceeds the lift cap need this pass twice: once for the pre-PCA, once for the lifted moments);radius_stats()per shard (only when occlusion must resolve overlaps) -> radii percentile;place()per shard -> coordinates (closed-form, embarrassingly parallel).
distributed_model_map() orchestrates the passes over an in-memory list of shards through any
map-shaped mapper (builtin map, multiprocessing.Pool.map, an MPI executor map, …);
every stage function is a pure picklable callable and every stats object combines with +, so on
Spark the same sequence is rdd.mapPartitions(lambda it: [fiber_stats(model, list(it))]).reduce(
lambda a, b: a + b) per pass with the small plan objects broadcast between passes, and coordinates
come from broadcasting the finished (geometry-only) map and calling .place per partition.
What does NOT distribute: the t-SNE/UMAP refine pass and embedding goals – global sequential
optimizations by construction. At scale, run those on a driver-sized subsample and place the rest
(mixle.utils.hvis.stream is the incremental version of that recipe). Model FITTING is the
already-solved distributed problem (seq_estimate); this module assumes mix_model arrives
fitted and requires it explicitly.
The contract with the single-machine path is equality: distributed_model_map(chunks, model)
reproduces model_map(concat(chunks), model) to floating-point summation order
(hvis_distributed_test pins it), for any chunking.
- class FiberStats(n, mass, sqrt_overlap, co, fields, triple=None)[source]
Bases:
objectPass-1 additive statistics: everything the layout’s GLOBAL geometry needs from data.
- class ScoreStats(sw, su, suu, sf, sff, swc, sfc, sffc)[source]
Bases:
objectPass-2 additive statistics: per-component moments of the whitened fiber coordinates
uand (when computable in the same pass) of the chart features, plus the clamped-weight moments behind the spread normalization.
- distributed_model_map(chunks, mix_model, emb_dim=2, *, spread=0.35, chart='linear', occlusion=True, occlusion_margin=1.05, edge_threshold=0.02, field_weights=None, mapper=None, with_points=True)[source]
model_map()over sharded data (see the module docstring).chunksis a materialized sequence of data shards (each itself a sequence); every pass maps over it once.mapperis anymap-shaped callable – builtinmap(default),multiprocessing.Pool.map, an MPI executor’s map – the stage functions and their broadcast plans are picklable.mix_modelis required: fitting is the estimator machinery’s distributed problem (seq_estimate), not this one.with_points=Falseskips the coordinate pass and returns geometry only (emptycoords/responsibilities) – broadcast the result and call.placeper shard where the data lives.refineand goals are deliberately absent: global sequential optimization does not shard (subsample-and-place instead).
- fiber_stats(mix_model, chunk, *, nerve_triple=False)[source]
Pass 1 over one shard. Combine shard results with
+; order never matters.nerve_triple=Truealso accumulates the (K, K, K) triple-overlap tensor sofuzzy_nerve_from_stats()can report triangles (an extra factor-K of work in this pass).- Parameters:
nerve_triple (bool)
- Return type:
FiberStats
- fuzzy_nerve_from_stats(stats, *, edge_threshold=0.02, triangle_threshold=0.02)[source]
mixle.utils.hvis.topology.fuzzy_nerve()from combined pass-1 statistics – the distributed nerve. Triangles needfiber_stats(..., nerve_triple=True); without the tensor only the 1-skeleton is reported (andnerve_report()would over-count holes, so it raises instead).
- radius_stats(plan, chunk)[source]
Pass 3 over one shard: per component, the scaled score norms of the points it dominates.
- Parameters:
plan (_ScorePlan)
- Return type:
- score_stats(plan, chunk)[source]
Pass 2 over one shard (pure; combine with
+).- Parameters:
plan (_ScorePlan)
- Return type:
ScoreStats