Arenas and Substrates
This page covers environment configuration: arena geometry, food sources, odorscapes, and obstacles.
Arena Types
Circular Arena (Petri Dish)
Default: dish (100 mm diameter)
from larvaworld.lib import reg
# Preconfigured circular arena (dims are in meters)
env_params = reg.conf.Env.getID("dish").get_copy()
print(env_params.arena.geometry, env_params.arena.dims) # circular (0.1, 0.1)
Rectangular Arena
from larvaworld.lib import reg
# Preconfigured rectangular arena (200 mm x 200 mm)
env_params = reg.conf.Env.getID("arena_200mm").get_copy()
print(env_params.arena.geometry, env_params.arena.dims) # rectangular (0.2, 0.2)
Preconfigured Arenas
from larvaworld.lib import reg
# List available arenas
env_ids = reg.conf.Env.confIDs
print(env_ids)
# Load arena
env_conf = reg.conf.Env.getID("arena_200mm").get_copy()
Food Sources
Larvaworld supports three types of food distributions:
1. Discrete Patches
Purpose: Localized food sources
from larvaworld.lib import reg
env_params = reg.conf.Env.getID("arena_200mm").get_copy()
# Create 3 food patches (group generator creates N individual sources)
env_params.food_params.source_groups = {
"patches": {
"N": 3, # number of patches
"mode": "uniform",
"shape": "rect",
"loc": (0.0, 0.0),
"scale": (0.07, 0.07),
"radius": 0.005, # 5 mm
"amount": 3.0,
"substrate": {"type": "standard", "quality": 1.0},
"color": "green",
}
}
2. Food Grid
Purpose: Regular grid of patches
from larvaworld.lib import reg
env_params = reg.conf.Env.getID("arena_200mm").get_copy()
# Place food patches on a regular grid
env_params.food_params.source_groups = {
"grid": {
"N": 16, # total patches (e.g., 4x4)
"mode": "grid",
"shape": "rect",
"loc": (0.0, 0.0),
"scale": (0.2, 0.2),
"radius": 0.003,
"amount": 3.0,
"substrate": {"type": "standard", "quality": 1.0},
"color": "green",
}
}
3. Uniform Substrate
Purpose: Continuous nutritious substrate
from larvaworld.lib import reg
env_params = reg.conf.Env.getID("arena_200mm").get_copy()
env_params.food_params.source_groups = {}
env_params.food_params.source_units = {}
env_params.food_params.food_grid = {
"grid_dims": (51, 51),
"initial_value": 1e-6,
"substrate": {"type": "standard", "quality": 1.0},
}
Nutritious Substrates
Larvaworld implements real experimental substrates.
The following table reproduces the compound densities reported in the Larvaworld paper (see Citing larvaworld).
Substrate |
Glucose (μg/ml) |
Yeast (μg/ml) |
Agar (μg/ml) |
Source |
|---|---|---|---|---|
standard-medium |
100 |
50 |
16 |
Kaun et al. (2007) |
PED-tracker |
10* |
187.5 |
5000 |
Schumann et al. (2020) |
cornmeal |
70.3** |
14.1 |
6.6 |
Wosniack et al. (2021) |
sucrose |
17.1 |
0 |
4 |
Wosniack et al. (2021) |
*Saccharose instead of glucose **Dextrose instead of glucose
In Larvaworld configuration, these correspond to Substrate.type values:
standard-medium→standardPED-tracker→PED_trackercornmeal→cornmealsucrose→sucrose
Usage:
from larvaworld.lib import reg
env_params = reg.conf.Env.getID("arena_200mm").get_copy()
env_params.food_params.food_grid = {
"grid_dims": (51, 51),
"initial_value": 1e-6,
"substrate": {"type": "standard", "quality": 1.0},
}
Odorscapes
Odor layers are created from sources (food patches) that have an odor.id.
To enable odor diffusion, set env_params.odorscape to "Gaussian" or "Diffusion".
from larvaworld.lib import reg
env_params = reg.conf.Env.getID("arena_200mm").get_copy()
env_params.odorscape = {"odorscape": "Gaussian", "grid_dims": (51, 51)}
# One odorized food patch produces an odor layer with id="apple"
env_params.food_params.source_units = {
"apple_patch": {
"pos": (0.02, 0.0),
"radius": 0.005,
"amount": 3.0,
"odor": {"id": "apple", "intensity": 1.0, "spread": 0.02},
"substrate": {"type": "standard", "quality": 1.0},
"color": "green",
"regeneration": False,
}
}
Obstacles and Borders
Arena Borders
from larvaworld.lib import reg
env_params = reg.conf.Env.getID("arena_200mm").get_copy()
# Borders are configured via env_params.border_list.
# Vertices are interpreted as pairs of points (p0,p1), (p1,p2), ... (p3,p0):
p0, p1, p2, p3 = (-0.1, -0.1), (0.1, -0.1), (0.1, 0.1), (-0.1, 0.1)
env_params.border_list = {
"wall0": {
"vertices": [p0, p1, p1, p2, p2, p3, p3, p0],
"width": 0.001,
}
}
Larva Initial Placement
Control where larvae start:
larva_groups = {
"explorers": {
"model": "explorer",
"distribution": {
"N": 20,
"mode": "uniform", # Distribution mode
"loc": (0.0, 0.0), # center (meters)
"scale": (0.01, 0.01), # spread (meters)
"shape": "circle",
},
}
}
Distribution Modes
Mode |
Description |
|---|---|
|
Uniform random within shape |
|
Ring around center |
|
Linear arrangement |
|
Regular grid |
See Table 4 for details.
Complete Example
from larvaworld.lib import reg
from larvaworld.lib.sim import ExpRun
from larvaworld.lib.util import AttrDict
# Start from a built-in experiment template and override env/larvae
exp_params = reg.conf.Exp.getID("dish").get_copy()
env_params = reg.conf.Env.getID("arena_200mm").get_copy()
env_params.odorscape = {"odorscape": "Gaussian", "grid_dims": (51, 51)}
env_params.food_params.source_units = {
"food_patch": {
"pos": (0.02, 0.0),
"radius": 0.008,
"amount": 3.0,
"odor": {"id": "food_odor", "intensity": 1.0, "spread": 0.03},
"substrate": {"type": "standard", "quality": 1.0},
"color": "green",
}
}
exp_params.env_params = env_params
exp_params.larva_groups = AttrDict(
{
"foragers": AttrDict(
{
"model": "forager",
"distribution": {
"N": 5,
"mode": "periphery",
"shape": "circle",
"loc": (0.0, 0.0),
"scale": (0.08, 0.08),
},
}
)
}
)
run = ExpRun(experiment="dish", parameters=exp_params, duration=0.2, screen_kws={})
run.simulate()