cella_gui 1.0.0

A GUI for the Cella cellular automata library
cella_gui-1.0.0 is not a library.

Cella

Cella GUI screenshot

Cella is a Rust toolkit for cellular automata (CA): grids of cells that change step by step according to simple local rules, like Conway's Game of Life. It has four layers, each usable on its own:

  • An engine for 1D and 2D rule-based CAs, with multi-threaded stepping and JSON configs you can save, share and resume.
  • A plugin seam (ExternalModel) for replacing the built-in rules with your own transition code. A wildfire spread model ships as the worked example.
  • An Explore module that runs any rule or model many times (ensembles), searches for good settings (evolution) and maps the range of behaviors a rule family can produce (MAP-Elites).
  • A GUI workbench (egui) and a small CLI demo menu on top of all of it.

It is for people who want to play with CA rules, build a model on a fast grid engine, or study how a stochastic (random-element) model behaves across many runs.

Wildfire disclaimer. The wildfire model and the scoring tools in validation/ are a personal-interest project. They must not be used to model or predict real fires.


Features

  • 1D Wolfram-style rules (any code, any radius) and 2D neighborhood-count rules (Moore, Von Neumann, Langton, StraightLine, Knight), with multi-state cells and optional per-rule randomness.
  • Deterministic results: the same config and seed give the same run, on any thread count.
  • JSON configs: load, save, and resume a run part-way through.
  • Plugin models: implement ExternalModel in your own crate and tag it with typetag. Configs then load it by name, and the engine and Explore drive it with no changes to Cella. To use it in the GUI, link your crate into the cella binary.
  • Explore: Monte Carlo ensembles (probability maps), genetic-algorithm evolution, novelty search and MAP-Elites, for any rule or model.
  • GUI: live rule editor, paint/stamp tools, zoom and pan, population charts, per-type colors, GIF export, and an Explore tab.
  • Wildfire example model with a validation pipeline that scores it against observed fires, including null baselines (see validation/).

Quick start

Prerequisites

  • Rust. Install via rustup. The GUI crates (eframe/egui 0.35) require Rust 1.92 or newer. cella_lib alone uses the 2024 edition, so it needs at least 1.85. The project is developed on recent stable.
  • Linux desktop libraries for the GUI. eframe needs the usual X11 or Wayland and OpenGL development packages. rfd, which draws the file open/save dialogs, needs xdg-desktop-portal or zenity. On Debian or Ubuntu, sudo apt install zenity covers the dialogs.
  • WSL users: without a desktop session the "Load Config JSON..." button silently does nothing. Install zenity, or skip the dialog by passing a config on the command line (next section). Details are in docs/app.md, "Troubleshooting".
  • Python 3 is only needed for the data-conversion scripts in validation/. It is not needed to build or run Cella.

Build and run

# Build the binary (first build downloads and compiles dependencies)
cargo build --release

# Launch the GUI
cargo run --release -- --gui

# Launch the GUI with a config already open (also the WSL workaround)
cargo run --release -- --gui --config configs/life.json

# Launch the CLI demo menu
cargo run --release

The Cargo package is named cella_gui (the name cella is taken on crates.io), but the program it builds is still called cella, so the release build ends up at target/release/cella. Use --package cella_gui if a Cargo command asks which package you mean.

Window size is optional:

cargo run --release -- --gui --size=1280x720
cargo run --release -- --gui --width=1920 --height=1080

If only --width or --height is given, the other is computed for a 16:9 window.

CLI demo menu

Without --gui, the binary shows a numbered menu and prints results to the terminal:

Cella demos (CLI):
1) 2D Game of Life (approx)
2) 1D Wolfram Rule 30 (n=1)
3) 1D Wolfram n=2 demo
4) 1D Custom (Wolfram code + n)
5) Load from configuration file (JSON)
6) Langton's ant (placeholder)
7) 1D three-state cycle demo
8) 2D three-state cycle demo
9) 2D StraightLine neighborhood demo
0) Exit

Option 6 is a placeholder: it only prints a "not yet implemented" message, because Langton's ant needs a moving agent and the engine has none.

To run a config file, pick option 5:

Select an option: 5
Enter path to JSON config: configs/life.json
Enter number of steps to run [10]: 20

Ready-made configs are in configs/: Life, Rule 30, multi-state cycles, other neighborhoods, wildfire demos, and Explore setups.


Documentation map

Document Contents
Application guide CLI, GUI workbench tour, editing, Explore tab, config guide, troubleshooting
Library README Using cella_lib in your own crate: install, code samples, bundled examples
Library guide Architecture, module reference, rule system, external models, serialization, threading
Explore guide Ensembles, evolution and MAP-Elites for any rule or model; how to read results honestly
Primer: Monte Carlo Plain-language: why run a simulation many times, probability maps, particle filters, seeds
Primer: Genetic Algorithms Plain-language: populations, selection, mutation, novelty search, MAP-Elites
Validation README Scoring the wildfire model against real fires; start with ANALYSIS.md
Performance review Developer notes: engine internals, optimizations, known issues
Roadmap Developer notes: GUI and plugin-UI work plan, with status per phase

Rust API docs: run cd cella_lib && cargo doc --open for the library. (make doc documents only the cella_gui package, because cella_lib is a separate build root; see "Building and testing".)


Using cella_lib as a library

The engine is its own crate, cella_lib, which you can use in your own programs without the GUI. Its README covers installation, code samples (Game of Life from a config, Rule 30 in the terminal), plugging in your own model, and the bundled example programs: cella_lib/README.md.

Thread count

The engine steps grids in parallel. To set the worker count, create a cella.properties file in the directory you run from (the repo root has one already):

# Number of worker threads for grid stepping. 1 disables parallelism.
threads=4

Without the file, the engine uses std::thread::available_parallelism(), usually the number of logical CPUs.


Config format

A config is a JSON file with a "dim" field ("1d" or "2d"), a size, an initial list of cell types, and a rule made of subrules. A subrule says "a cell of type A, seeing at least N neighbors of type B, becomes type C".

{
  "dim": "2d",
  "width": 10,
  "height": 10,
  "history_limit": 5,
  "initial": ["Inactive","Inactive","...","Alive","Alive","Alive","..."],
  "rule": {
    "subrules": [
      { "current_type":"Alive", "criteria_type":"Alive", "count":4,
        "op":"gt", "range":1, "neighborhood":"Moore",
        "randomness":null, "output_type":"Inactive" },
      { "current_type":"Alive", "criteria_type":"Alive", "count":2,
        "op":"gt", "range":1, "neighborhood":"Moore",
        "randomness":null, "output_type":"Alive" },
      { "current_type":"Inactive", "criteria_type":"Alive", "count":3,
        "op":"eq", "range":1, "neighborhood":"Moore",
        "randomness":null, "output_type":"Alive" }
    ]
  }
}
{
  "dim": "1d",
  "width": 257,
  "history_limit": 4,
  "initial": ["Inactive","...","X","...","Inactive"],
  "rule": {
    "subrules": [
      { "current_type":"X", "criteria_type":"X",
        "wolfram_code":"30", "n":1,
        "randomness":null, "output_type":"X" },
      { "current_type":"Inactive", "criteria_type":"X",
        "wolfram_code":"30", "n":1,
        "randomness":null, "output_type":"X" }
    ]
  }
}

(The "..." entries stand in for the full list in the real files. In JSON wolfram_code is a string; in the Rust API it is a number.)

2D subrule notes: op ("lt"/"gt"/"eq") is inclusive for gt and lt ("at least" / "at most"). neighborhood is one of "Moore", "VonNeumann", "Langton", "StraightLine", "Knight". An optional "limit" turns gt/lt into an inclusive between-range (for example "count":2, "op":"gt", "limit":3 means "survive with 2 to 3 neighbors"). "randomness" and "limit" may be omitted.

The full field guide, plus the optional model, colors, snapshot, ensemble and evolve blocks, is in docs/app.md, "Config file guide" and docs/lib.md.


Building and testing

The Makefile wraps the common commands (each target has a one-line comment above it):

Command What it does
make build / make build-release Build the cella binary
make run / make run-gui Run the CLI menu / the GUI at 1024x768
make clippy Lint everything with warnings as errors (the lint gate)
make fmt / make fmt-check Format / check formatting
make test Fast tests: non-ignored cella_lib tests plus the wildfire_smc example tests
make test-all Also runs the slow #[ignore]d tests
make coverage Line coverage for cella_lib (needs cargo install cargo-llvm-cov)

cella_lib is its own Cargo build root. The root Cargo.toml depends on it by path but does not list it as a workspace member. In practice:

  • A bare cargo test at the repo root tests only the cella binary, not the library. The library tests run with cd cella_lib && cargo test, which is what make test does for you.
  • cella_lib has its own target/ directory and its own copy of the release profile, so it builds separately from the root.
  • Its examples (cella_lib/examples/) are built and run from inside cella_lib/, for example cd cella_lib && cargo run --release --example explore.

Before sending a change, run make clippy and make test. More on test environment variables, snapshots and benchmarks is in docs/lib.md, "Building and testing".


Project layout

cella/
├── Cargo.toml          # `cella_gui` package (builds the `cella` app)
├── Makefile            # build / lint / test shortcuts
├── cella.properties    # Thread count
├── configs/            # Ready-made JSON scenarios
├── docs/               # Guides (see the documentation map above)
├── src/                # Binary crate
│   ├── main.rs         #   Entry point: CLI menu or --gui
│   ├── demos/          #   CLI demos
│   └── gui/            #   egui workbench (app, panels, explore, export, ...)
├── cella_lib/          # Library crate (its own Cargo build root)
│   ├── src/
│   │   ├── grid1d.rs, grid2d.rs, rules.rs   # Grids and rule system
│   │   ├── config.rs, state.rs              # JSON configs, save/resume
│   │   ├── external.rs                      # ExternalModel plugin seam
│   │   ├── explore/                         # Ensembles, evolution, MAP-Elites
│   │   └── wildfire/                        # Worked-example model (not engine code)
│   ├── examples/       #   explore, wildfire_validate, wildfire_smc, ...
│   └── tests/          #   Integration and snapshot tests
└── validation/         # Scoring the wildfire model against real fires

The full module map for the library is in docs/lib.md; for the GUI, in docs/app.md.


License

MIT — see LICENSE.