Long-Form Editions
Overview
A long-form edition series is one algorithm that produces many unique outputs — each driven by a deterministic seed. The same seed always produces the same image. This is the workflow behind Art Blocks, fxhash, and numbered print editions.
Eido provides this pipeline:
- Define a parameter spec — what varies across editions
- Write a scene function — turns parameters into a scene
- Render the range of editions — one deterministic parameter map each
- Analyze trait distribution across the series
Parameter Specs
A parameter spec defines what varies across editions using data-driven distributions:
(def spec
{:hue {:type :uniform :lo 0.0 :hi 360.0}
:density {:type :gaussian :mean 20.0 :sd 5.0}
:palette {:type :choice :options [:sunset :ocean :forest]}
:bold? {:type :boolean :probability 0.3}
:weight {:type :weighted-choice
:options [:light :medium :heavy]
:weights [0.5 0.35 0.15]}})Each edition samples from these distributions using a deterministic seed derived from the master seed + edition number. Distribution types: :uniform, :gaussian, :choice, :weighted-choice, :boolean, :pareto, :triangular, :eased.
Scene Function
The scene function takes sampled parameters and returns a scene map:
(defn make-scene [params]
{:image/size [800 800]
:image/background [:color/hsl (:hue params) 0.1 0.95]
:image/nodes
[(build-artwork params)]})This is where your creative algorithm lives. The parameters control variation; the algorithm defines the visual language.
Batch Rendering
series-range expands a spec into one deterministic parameter map per edition. Render each one in a loop:
(require '[eido.gen.series :as series])
(doseq [[edition params]
(map-indexed vector (series/series-range spec 42 0 50))]
(eido/render (make-scene params)
{:output (str "editions/edition-" edition ".png")}))This writes editions/edition-0.png through edition-49.png. Each edition's parameters come from a seed derived from the master seed (42) and the edition number, so the same pair always reproduces the same image.
Trait Analysis
Traits categorize continuous parameters into named labels. trait-summary counts how many editions fall into each bucket across the series:
(series/trait-summary
spec 42 100
{:density [[15 "sparse"] [25 "medium"] [100 "dense"]]})
;=> {:density {"sparse" 22, "medium" 48, "dense" 30}}Useful for verifying that rare traits are actually rare before releasing a series.
Reproducibility
Reproduction rests on determinism: the same scene map renders to the same bytes, every time. Store the scene as EDN — or the seed and spec that generate it — and you can always re-render it.
When you stumble on a seed worth keeping, bookmark it:
(series/save-seed! "seeds.edn"
{:seed 42 :params params :note "strong diagonal"})
;; Later, read them all back
(series/load-seeds "seeds.edn")
;=> [{:seed 42 :params {,,,} :note "strong diagonal" :timestamp "..."}]save-seed! appends one EDN form per line; load-seeds reads them back in append order.