API Reference

LifeGrid provides a REST and WebSocket API built with FastAPI for programmatic access, streaming, and collaborative editing.

Starting the Server

uvicorn src.api.app:app --host 0.0.0.0 --port 8000 --reload

The API runs at http://localhost:8000. Interactive docs are available at /docs (Swagger UI) and /redoc.


REST Endpoints

Health Check

GET /health

Response: {"status": "ok"}


Create Session

POST /session

Creates a new simulation session.

Request body:

Field

Type

Default

Description

width

int (4–2048)

64

Grid width

height

int (4–2048)

64

Grid height

mode

string

"Conway's Game of Life"

Automaton mode

birth_rule

string

null

Digit string of birth neighbour counts, e.g. "36" for B36

survival_rule

string

null

Digit string of survival neighbour counts, e.g. "23" for S23

pattern

string

null

Pattern name to load

Response: {"session_id": "<uuid>"}

Example:

curl -X POST http://localhost:8000/session \
  -H "Content-Type: application/json" \
  -d '{"width": 128, "height": 128, "mode": "HighLife"}'

Step Session

POST /session/{session_id}/step

Advance the simulation by one or more generations.

Request body:

Field

Type

Default

Description

steps

int (1–1000)

1

Number of generations to advance

Response: {"generation": <int>}


Get State

GET /session/{session_id}/state

Returns the current grid state.

Response:

{
  "generation": 42,
  "width": 128,
  "height": 128,
  "grid": [[0, 1, 0, ...], ...]
}

Load Pattern

POST /session/{session_id}/pattern

Load a pattern into the session grid.

Request body:

Field

Type

Description

rle

string

RLE-encoded pattern string

pattern_name

string

Named pattern to load

Provide either rle or pattern_name.

Response: {"status": "ok"}


Errors

All endpoints return 404 if the session ID is unknown.


WebSocket Endpoints

Simulation Stream

WS /session/{session_id}/stream

Connects to a simulation session and receives grid state frames automatically at approximately 20 Hz. Each frame is a JSON message with the same schema as the GET /session/{id}/state response.

Example (Python):

import asyncio
import websockets
import json

async def stream():
    async with websockets.connect("ws://localhost:8000/session/<id>/stream") as ws:
        async for message in ws:
            data = json.loads(message)
            print(f"Generation {data['generation']}, grid {data['width']}x{data['height']}")

asyncio.run(stream())

Collaborative Session

WS /collab/{session_id}?width=<int>&height=<int>

Multi-user collaborative editing. Multiple WebSocket clients share the same grid. The grid is created on demand with the specified dimensions (default 64x64).

Actions (client → server):

Action

Payload

Description

draw

{"x": int, "y": int, "value": int}

Set a cell

clear

Clear the grid and reset generation

step

Advance one Conway generation

start

Begin auto-stepping

stop

Stop auto-stepping

set_speed

{"delay": float}

Set seconds between auto-steps (min 0.02)

Message format (client → server):

{"action": "draw", "x": 10, "y": 15, "value": 1}

Broadcasts (server → all clients):

After every mutation the server broadcasts the full grid state to all connected clients:

{
  "type": "state",
  "generation": 5,
  "grid": [[0, 1, ...], ...]
}

Example (Python):

import asyncio
import websockets
import json

async def collab():
    uri = "ws://localhost:8000/collab/my-room?width=32&height=32"
    async with websockets.connect(uri) as ws:
        # Draw a cell
        await ws.send(json.dumps({"action": "draw", "x": 5, "y": 5, "value": 1}))
        # Receive broadcast
        state = json.loads(await ws.recv())
        print(f"Generation: {state['generation']}")

asyncio.run(collab())

Core Python API

Simulator

from src.core.config import SimulatorConfig
from src.core.simulator import Simulator

config = SimulatorConfig(width=100, height=100, automaton_mode="Conway's Game of Life")
sim = Simulator(config)

sim.initialize()
metrics = sim.step(num_steps=10)       # Returns list of {generation, population, density}
grid = sim.get_grid()                   # numpy.ndarray
sim.set_cell(50, 50, 1)
sim.undo()
sim.redo()
summary = sim.get_metrics_summary()     # {generations, current_population, max_population, ...}

Export Manager

from src.export_manager import ExportManager

em = ExportManager(theme="dark")  # themes: "light", "dark", "blue", "warm"

# Single image — grid is the first positional argument
em.export_png(grid, "snapshot.png", cell_size=8)

# Animated GIF — add frames first, then export
for frame in frames:
    em.add_frame(frame)
em.export_gif("animation.gif", cell_size=8, duration=100)

# Video
em.export_video("video.mp4", cell_size=8, fps=10, codec="mp4")

# JSON — filepath first, grid second
em.export_json("state.json", grid, metadata={"generation": 100})

RLE Parser

from src.advanced.rle_format import RLEParser, RLEEncoder

# Parse RLE string — returns (grid: np.ndarray, metadata: dict)
grid, metadata = RLEParser.parse("bo$2bo$3o!")

# Parse from file
grid, metadata = RLEParser.parse_file("pattern.rle")

# Encode grid to RLE string
rle_string = RLEEncoder.encode(grid)

# Encode directly to file
RLEEncoder.encode_to_file(grid, "output.rle")

Statistics

from src.advanced.statistics import StatisticsCollector

coll = StatisticsCollector(track_changes=True, calculate_entropy=False)
stats = coll.collect(step=1, grid=grid)   # returns SimulationStatistics dataclass
print(stats.alive_cells, stats.density, stats.births, stats.deaths)

summary = coll.get_summary()
# {"total_steps": 1, "avg_density": 0.25, "avg_births": ..., ...}

For deeper per-grid metrics use EnhancedStatistics (all static methods):

from src.advanced.enhanced_statistics import EnhancedStatistics

entropy    = EnhancedStatistics.calculate_entropy(grid)
complexity = EnhancedStatistics.calculate_complexity(grid, previous_grid)

Pattern Manager

from src.advanced.pattern_manager import PatternManager, PatternEntry
import numpy as np

pm = PatternManager(data_dir="user_data")

# Add a favourite
entry = PatternEntry.from_grid("my_glider", "conway", grid, description="A glider")
pm.add_favorite(entry)

# Retrieve all favourites
favs = pm.get_favorites()

# Search by tag
conway_patterns = pm.search_by_tag("conway")

# Search by name substring
results = pm.search_by_name("glider")

Cell Age Tracker

from src.advanced.cell_tracker import CellAgeTracker

tracker = CellAgeTracker(width=100, height=100)
tracker.update(grid)        # call once per generation
ages = tracker.get_age_grid()  # numpy array: 0 = dead, n = alive for n generations

AutoSave Manager

from src.autosave_manager import AutoSaveManager

am = AutoSaveManager(save_dir="autosave", interval=300, max_backups=5)
am.set_save_callback(lambda: {"generation": sim.generation, "grid": sim.get_grid().tolist()})
am.start()
# ... simulation runs ...
am.stop()

Plugin System

from src.plugin_system import PluginManager

pm = PluginManager()
count = pm.load_plugins_from_directory("plugins")
print(pm.list_plugins())  # ["Day & Night"]

automaton = pm.create_automaton("Day & Night", 100, 100)