API Reference
Eunoia.EunoiaEunoia.CircleEunoia.ContainerEunoia.EllipseEunoia.EulerFitEunoia.LabelPlacementEunoia.PointEunoia.RectangleEunoia.SquareEunoia.VennFitEunoia.eulerEunoia.eunoiaplotEunoia.eunoiaplot!Eunoia.place_labelsEunoia.vennEunoia.version
Eunoia.Eunoia — Module
EunoiaJulia bindings for eunoia, a Rust library for area-proportional Euler and Venn diagrams.
The native code is the eunoia-capi cdylib, which speaks a small JSON-in/ JSON-out C ABI (eunoia_euler, eunoia_venn, eunoia_version, eunoia_free). This module dlopen's it and exposes euler, venn, and version.
Locating the library
At load time the shared library is resolved in this order:
ENV["EUNOIA_CAPI_LIB"]— an explicit path to a locally builtlibeunoia_capi. Set this during development:cargo build -p eunoia-capi --releasethen point attarget/release/libeunoia_capi.{so,dylib}.- The bundled
eunoiaartifact declared inArtifacts.toml(downloaded lazily on first use; populated bygen/generate_artifacts.jlfrom a GitHub release).
If neither is available a descriptive error is raised.
Eunoia.Circle — Type
A fitted circle for one input set.
Eunoia.Container — Type
The fitted universe box drawn around a diagram fit with a complement. The container's area minus the union of the shapes matches the requested complement area.
Eunoia.Ellipse — Type
A fitted ellipse for one input set.
Eunoia.EulerFit — Type
EulerFit{S}Result of fitting an area-proportional Euler diagram with shapes of type S.
Fields:
shapes: fitted shapes, one per input set, in input order.original_values: the requested exclusive area per region (keyed by combination string, e.g."A&B").fitted_values: the fitted exclusive area per region.residuals:original_values − fitted_valuesper region.region_error: per-region error (always in exclusive form).diag_error: eulerAPE-style worst-case region error.stress: venneuler-style stress metric.loss: final value of the optimizer's objective.iterations: optimizer iteration count.container: the fitted universe box when fit with acomplement, elsenothing.
The plot_data field holds the native renderable geometry (region polygons and label anchors); it backs plotting and is not part of the stable public API.
Eunoia.LabelPlacement — Type
LabelPlacementA resolved label position returned by place_labels. anchor is the centre of the label box. kind is one of :interior, :exterior_raycast, :exterior_force_directed, or :exterior_elbow (:unknown for a future native variant). For exterior placements that need a leader line, tether is the inside-region point the leader starts from, leader_end is where it meets the label box, and leader_waypoints are the intermediate polyline vertices (empty for straight leaders, populated for elbow leaders); all three are nothing/ empty for interior placements.
Eunoia.Point — Type
A 2D point.
Eunoia.Rectangle — Type
A fitted axis-aligned rectangle for one input set.
Eunoia.Square — Type
A fitted axis-aligned square for one input set.
Eunoia.VennFit — Type
VennFit{S}Result of laying out a (non-proportional) Venn diagram. Shares EulerFit's structure, but the layout is topological: every set intersection is drawn regardless of area, so the proportional-error metrics are not meaningful (left at zero) and original_values is empty. fitted_values holds the geometric area of each region.
Eunoia.euler — Method
euler(values; shape="circle", input_type="exclusive",
complement=nothing, seed=nothing, loss=nothing, …)Fit an area-proportional Euler diagram. values is one of:
a mapping from combination strings to areas, where a key is a single set (
"A") or an&-joined intersection ("A&B"):euler(Dict("A" => 5, "B" => 3, "A&B" => 1.5))a mapping from set names to membership collections (vector/set/tuple); each element is counted into the canonical region of the sets it belongs to, yielding exclusive per-region counts (so
input_typemust stay"exclusive"):euler(Dict("A" => ["x", "y"], "B" => ["y", "z"]))
Keyword arguments:
shape:"circle"(default),"ellipse","square", or"rectangle".input_type:"exclusive"(default; per-region areas) or"inclusive"(set sizes that include overlaps; the core converts internally and the reportedfitted_values/residualsare reconstructed in the inclusive scale).complement: target "universe" area outside every set (opts into container fitting);nothingto disable.seed: RNG seed for reproducible restarts;nothingfor default.max_sets: raise the set-count ceiling above the core default (32); clamped core-side to the hard cap (63).nothingkeeps the default. Note that a fully-overlappingn-set diagram has2^n - 1regions, so large dense inputs remain intractable regardless.
Fitting knobs (all optional; nothing keeps the core default). Invalid string tokens are rejected by the native core and surface as an error:
loss: objective function. One of"sum_squared"(default),"sum_absolute","sum_absolute_region_error","sum_squared_region_error","max_absolute","max_squared","root_mean_squared","stress","diag_error","log_sum_absolute", or a C¹-smooth surrogate"smooth_sum_absolute","smooth_sum_absolute_region_error","smooth_max_absolute","smooth_max_squared","smooth_diag_error","smooth_log_sum_absolute".loss_eps: smoothing parameter for the sixsmooth_*losses (default1e-3); ignored by the non-smooth losses.n_restarts: number of randomly seeded restarts (default10).optimizer: final-layout solver. One of"levenberg_marquardt","lbfgs","nelder_mead","trf","cmaes_lm", or"cmaes_trf"(default).mds_solver: initial-layout (MDS) solver,"levenberg_marquardt"(default) or"lbfgs".initial_sampler: restart-position sampler,"uniform"(default) or"latin_hypercube".cmaes_fallback_threshold: loss above which thecmaes_*optimizers fire their global escape stage (default1e-3).max_iterations: per-optimizer iteration cap (default200).tolerance: unified convergence tolerance (default1e-3).xtol,ftol,gtol: fine-grained Levenberg-Marquardt tolerances overriding the defaults derived fromtolerance.jobs: thread count for the restart loop; a pure wall-time knob, the chosen layout is identical regardless of value.
Plot-tuning knobs (all optional; nothing keeps the core default). These shape the plot_data geometry used for rendering, not the fit:
n_vertices: vertices per polygonized shape/region outline (default200). Lower values give coarser outlines; higher values, smoother ones.label_precision: pole-of-inaccessibility search precision for label anchors, in coordinate units (default0.01).sliver_threshold: minimum region-piece area, as a fraction of the largest piece, below which a piece is rejected as a polygonization artifact (default1e-3);0.0disables the filter.
Returns an EulerFit carrying the fitted shapes, the original_values/fitted_values/residuals per region, the per-region region_error, the scalar fit metrics, and—if a complement was given—a container.
Eunoia.eunoiaplot — Function
eunoiaplot(fit; colors, fills, edges, labels, quantities, legend, complement,
fontsize=14, label_placement=true, leader_style=(;), figure=(;), axis=(;))Render a fitted EulerFit/VennFit as a publication-ready Makie figure (equal aspect, no axis decorations), returning a Makie.FigureAxisPlot.
This requires a Makie backend to be loaded — the implementation lives in a package extension that activates on using CairoMakie (or GLMakie/WGLMakie). The bare Makie plot(fit)/plot!(ax, fit) recipe forms also work once a backend is loaded.
Styling keywords mirror the eunoia-py plot() API:
colors: per-set colors — a vector (shape order) or aDict(name => color); omitted uses a built-in categorical palette. Region fills blend the member colors perceptually (OKLab).fills:Dict(combo => style)per-region fill overrides.edges: set-outline style — a uniform style, a per-setDict, or a vector.labels:false/true/nothing, a per-setDict, or a uniform style.quantities:false/true,"original"/"fitted","counts"/"percent", or aDict.legend:false/trueor aDictofLegendkeywords.complement: container-box styleDict(drawn only when the fit has one).fontsize: base label font size in points (quantities render smaller).
Collision-aware labels:
label_placement:true(default) places labels collision-aware viaplace_labels: each region's label is measured (Makie text metrics), positioned inside its region when it fits, else pushed outside with a leader line. Set names and quantities are combined into one box per region, so a set name and its region quantity never overlap. The default uses the"raycast"exterior solver with straight leaders; pass aNamedTuple/Dictofplace_labelsstrategy knobs (placement,leader,tether,margin,iterations,precision,leader_gap,min_gap) to change it, e.g.label_placement = (; placement = "force_directed")orlabel_placement = (; leader = "elbow", tether = "boundary"). Passlabel_placement=falseto instead draw labels at their raw anchors.leader_style: collection oflines!keywords styling the leader lines.
Collision-aware placement needs the axis (to convert pixel text metrics to layout units), so it is available through eunoiaplot/eunoiaplot! only; the bare plot(fit) recipe form ignores label_placement.
Eunoia.eunoiaplot! — Function
eunoiaplot!(ax, fit; label_placement=true, leader_style=(;), kwargs...)Draw a fitted diagram into an existing Makie axis ax. Same styling keywords as eunoiaplot (including label_placement/leader_style for collision-aware labels, on by default); does not alter the axis aspect or decorations.
Eunoia.place_labels — Method
place_labels(fit, sizes; placement=nothing, leader=nothing, margin=nothing,
iterations=nothing, precision=nothing, tether=nothing,
leader_gap=nothing, min_gap=nothing)Resolve collision-aware label positions for the regions of a fitted EulerFit/VennFit, given the rendered label box sizes.
The core can't place labels without their on-screen sizes (font metrics it never sees at fit time), so this is a separate call from euler: measure each label, then ask for placements. sizes is a mapping from region/combination strings ("A", "A&B", …) to a (width, height) tuple in the same coordinate units as the fitted shapes. Only regions present in both sizes and the fit's geometry get a placement; degenerate inputs are silently skipped.
Each placement tries to sit inside its region; one that can't fit is pushed outside with a leader line. Returns a Dict{String,LabelPlacement} (see LabelPlacement).
Strategy knobs (all optional; nothing keeps the core default). Invalid string tokens are rejected by the native core and surface as an error:
leader: leader edge type,"straight"(default) or"elbow"(d3-pie style orthogonal leaders with column-based placement).placement: exterior solver for straight leaders,"raycast"(default) or"force_directed"(spring/repulsion relaxation for crowded diagrams); ignored for"elbow".margin: gap between the diagram and exterior labels (both edge types); the per-region proportional default applies when omitted.iterations: iteration cap for"force_directed"(default200); ignored otherwise.precision: pole-of-inaccessibility search precision (default0.01).tether: where an exterior leader attaches to its region,"poi"(default, the pole of inaccessibility) or"boundary"(the region's outer ring).leader_gap: visible gap between the leader tip and the label box (default0.0).min_gap: minimum vertical spacing between stacked"elbow"labels; ignored otherwise.
fit = euler(Dict("A" => 5, "B" => 3, "A&B" => 1.5))
placements = place_labels(fit, Dict("A" => (0.6, 0.3), "B" => (0.6, 0.3));
placement="force_directed")Eunoia.venn — Method
venn(sets; shape="circle")Build a canonical Venn diagram. sets selects the set names, as one of:
- an
Integern—nsets with default names"A","B", …; - a vector of set names, e.g.
["cat", "dog", "fish"]; - a mapping whose keys are set/combination labels (the distinct base set names are extracted; values are ignored, since a Venn layout is non-proportional).
The number of names selects the arrangement; shape is "circle" (n ≤ 3), "ellipse" (n ≤ 5), "square", or "rectangle" (n ≤ 3).
venn(["A", "B", "C"]; shape="ellipse")
venn(3)Returns a VennFit: the same structure as EulerFit, but the layout is topological, so fitted_values holds each region's geometric area and original_values is empty.
Eunoia.version — Method
version() -> StringReturn the version of the underlying eunoia-capi native library.