API Reference
Eunoia.EunoiaEunoia.BoundingBoxEunoia.CircleEunoia.ContainerEunoia.EllipseEunoia.EulerFitEunoia.GlyphBoxPlacementsEunoia.GlyphPlacementsEunoia.LabelPlacementEunoia.PointEunoia.RectangleEunoia.RotatedRectangleEunoia.SquareEunoia.VennFitEunoia.eulerEunoia.eunoiaplotEunoia.eunoiaplot!Eunoia.label_boxesEunoia.place_glyph_boxesEunoia.place_glyphsEunoia.place_labelsEunoia.place_set_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. This module loads it and exposes fitting, label placement, glyph placement, and rendering through a typed Julia API.
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.BoundingBox — Type
An axis-aligned rectangle used as a label or glyph keep-out box.
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.GlyphBoxPlacements — Type
GlyphBoxPlacementsResult of place_glyph_boxes. scale is the diagram-wide factor to apply to the reference text size. Each vector in boxes is a prefix aligned with the corresponding input sizes; unplaced reports the omitted suffix.
Eunoia.GlyphPlacements — Type
GlyphPlacementsResult of place_glyphs. radius is shared by every glyph, positions contains glyph centers by region, and unplaced reports any shortfall when a fixed radius could not accommodate every requested glyph.
Eunoia.LabelPlacement — Type
LabelPlacementA resolved label position returned by place_labels or place_set_labels. anchor is the center of the label box. kind is one of :interior, :exterior_raycast, :exterior_force_directed, :exterior_elbow, :exterior_matched, or :exterior_set (: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. Set-label placements carry no leader geometry.
Eunoia.Point — Type
A 2D point.
Eunoia.Rectangle — Type
A fitted axis-aligned rectangle for one input set.
Eunoia.RotatedRectangle — Type
A fitted rotated rectangle for one input set. rotation is the angle (in radians) of the rectangle about its center.
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","rectangle", or"rotated_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","mads","trf","cmaes","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, set_label_placement=false,
glyphs=nothing, members=nothing, figure=(;), axis=(;))
eunoiaplot(gridpos, fit; axis=(;), kwargs...)Render a fitted EulerFit/VennFit as a publication-ready Makie figure (equal aspect, no axis decorations), returning a Makie.FigureAxisPlot.
The second form draws into a layout cell of an existing figure — e.g. eunoiaplot(f[1, 2], fit) — mirroring Makie's plot(fig[i, j], data). It creates a diagram-configured axis (equal aspect, hidden decorations) in that cell and returns a Makie.AxisPlot. Use it to assemble multi-panel figures without configuring each axis by hand. It takes the same styling keywords (pass an axis title and the like through axis = (; title = "…")) but does not add a legend; add a Legend yourself if you want one.
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.set_label_placement:false(default) keeps set names inside their regions;trueplaces them just outside their own shape, and aNamedTuple/Dictadditionally forwardsmargin,angular_steps,obstacles, andprecisiontoplace_set_labels.glyphs: an explicit region-to-integer-count mapping. Circular glyphs are packed withplace_glyphs; useglyph_optionsfor placement knobs andglyph_stylefor Makiescatter!attributes.members: an explicit region-to-ordered-names mapping. Names are measured, packed withplace_glyph_boxes, and scaled uniformly; usemember_optionsandmember_styleto customize them.glyphsandmembersare mutually exclusive.
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, set_label_placement=false,
glyphs=nothing, members=nothing, leader_style=(;), kwargs...)Draw a fitted diagram into an existing Makie axis ax. It accepts the same styling and placement keywords as eunoiaplot, but does not alter the axis aspect or decorations.
Eunoia.label_boxes — Method
label_boxes(placements, sizes; padding=0) -> Vector{BoundingBox}Convert resolved label placements and their measured (width, height) sizes into padded, axis-aligned keep-out boxes. The result can be passed as obstacles to place_set_labels, place_glyphs, or place_glyph_boxes.
Eunoia.place_glyph_boxes — Method
place_glyph_boxes(fit, sizes; arrangement=nothing, scale=nothing,
min_scale=nothing, gap=nothing, seed=nothing,
precision=nothing, max_attempts=nothing,
obstacles=nothing) -> GlyphBoxPlacementsPack ordered, caller-measured member-label boxes inside fitted regions. sizes maps each canonical region combination to a vector of (width, height) pairs. The returned boxes are a prefix aligned with each input vector; render the corresponding text at the reference font size multiplied by scale.
Eunoia.place_glyphs — Method
place_glyphs(fit, counts; arrangement=nothing, radius=nothing, gap=nothing,
seed=nothing, precision=nothing, max_attempts=nothing,
obstacles=nothing) -> GlyphPlacementsPack equally sized circular glyphs inside fitted regions. counts maps canonical region combinations to nonnegative integer counts. Omit radius to choose the largest shared radius that accommodates every requested glyph.
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),"force_directed"(spring/repulsion relaxation for crowded diagrams), or"matched"(noncrossing boundary labels); 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.place_set_labels — Method
place_set_labels(fit, sizes; margin=nothing, angular_steps=nothing,
obstacles=nothing, precision=nothing)Place one measured label per set just outside that set's shape. Labels hug the shape boundary and need no leader line. sizes maps set names to (width, height) pairs in diagram coordinates. Returns a Dict{String,LabelPlacement} keyed by set name.
Eunoia.venn — Method
venn(sets; shape="circle", complement=nothing)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", "rectangle" (n ≤ 3), or "rotated_rectangle" (n ≤ 4).
Pass complement to reserve that area outside every set; the fit then carries a container box (the "universe" frame) drawn behind the diagram, just as for euler.
venn(["A", "B", "C"]; shape="ellipse")
venn(3)
venn(4; shape="rotated_rectangle", complement=2)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.