# Single Experiments This page covers how to run **single behavioral experiments** in Larvaworld using the `Exp` simulation mode. We'll explore two case studies: **Dish Exploration** and **Olfactory Learning**. --- ## Overview The `Exp` mode runs **one simulation** with fixed parameters, making it ideal for: - ✅ Quick testing of configurations - ✅ Video generation for presentations - ✅ Single-condition analysis - ✅ Model demonstrations For more details on simulation modes, see {doc}`../concepts/simulation_modes`. --- ## Case Study 1: Dish Exploration ### Purpose The **Dish Exploration** experiment is the fundamental baseline assay for studying spontaneous larval locomotion in a circular arena without odors or food. ```{mermaid} graph TB subgraph "Setup" Arena[Circular Arena
60-90 mm diameter] Larvae[N larvae
Uniform distribution] Duration[3-10 minutes
Free movement] end subgraph "Metrics" Dispersion[Dispersion Index
Spatial spread over time] Velocity[Velocity Distribution
Speed patterns] Tortuosity[Path Tortuosity
Trajectory straightness] Activity[Activity Patterns
Runs, turns, pauses] end subgraph "Applications" Baseline[Baseline Behavior
Control experiments] Validation[Model Validation
Compare to real data] Phenotype[Phenotype Screening
Behavioral differences] end Arena --> Dispersion Larvae --> Velocity Duration --> Tortuosity Dispersion --> Baseline Velocity --> Validation Tortuosity --> Phenotype Activity --> Phenotype style Arena fill:#2196f3,stroke:#1976d2,stroke-width:2px,color:#fff style Dispersion fill:#f44336,stroke:#d32f2f,stroke-width:2px,color:#fff style Baseline fill:#4caf50,stroke:#388e3c,stroke-width:2px,color:#000 ``` ### Running via CLI ```bash larvaworld Exp dish -N 10 -duration 0.5 # short demo run ``` **Parameters**: - `-N 10`: 10 larvae - `-duration 0.5`: 0.5 minutes simulated time ### Running via Python ```python from larvaworld.lib import reg from larvaworld.lib.sim import ExpRun # Load template exp_params = reg.conf.Exp.getID("dish").get_copy() # Create experiment (headless, short demo duration) run = ExpRun(experiment="dish", parameters=exp_params, duration=0.1, screen_kws={}) # Run simulation run.simulate() # Access dataset dataset = run.datasets[0] print("Endpoint metrics (sample):") print(dataset.e[["length", "cum_dur"]].head()) print("Step-wise sample:") print(dataset.s.head()) ``` ### Key Metrics **Computed automatically** by Larvaworld: | Metric | Description | Unit | | -------------------- | -------------------------- | ------------- | | **Dispersion Index** | Spatial spread over time | cm | | **Linear Velocity** | Forward speed distribution | mm/s | | **Angular Velocity** | Turning rate distribution | rad/s | | **Tortuosity** | Path straightness | dimensionless | | **Activity Index** | Fraction of time active | 0-1 | | **Stride Frequency** | Crawling frequency | Hz | | **Turn Rate** | Reorientation frequency | 1/s | ### Analysis Example ```python # Process dataset dataset.preprocess( drop_collisions=False, interpolate_nans=True, filter_f=3.0 # Low-pass filter at 3 Hz ) dataset.process( proc_keys=["angular", "spatial"], dsp_starts=[0], dsp_stops=[40, 60], tor_durs=[5, 10, 20], ) dataset.annotate( anot_keys=[ "bout_detection", "bout_distribution", "interference", ] ) # Print summary statistics print(dataset.e) # Endpoint metrics ``` --- ## Case Study 2: Olfactory Learning ### Purpose The **Olfactory Learning** experiment demonstrates how larvae associate odors with food rewards through reinforcement learning. ```{mermaid} sequenceDiagram participant L as Larvae participant E as Environment participant M as Memory System Note over L,E: Pre-Test Phase L->>E: Naive odor preference E-->>L: Odor A & B present Note over M: Baseline preference (PI₀) Note over L,E: Training Phase L->>E: Conditioning E-->>L: Odor A + Food (CS+) E-->>L: Odor B alone (CS-) L->>M: Associate A with food (reward signal) Note over M: Q-learning updates gain Note over L,E: Test Phase L->>E: Trained preference E-->>L: Odor A & B present (no food) M->>L: Recall association (high gain for A) L->>E: Prefer Odor A Note over M: Memory expressed (PI > PI₀) Note over L,E: Post-Test L->>E: Extinction or retention Note over M: Memory decay analysis ``` ### Experimental Phases | Phase | Duration | Odor A | Odor B | Food | Purpose | | ------------- | -------- | ------- | ------- | ----------- | ------------------------- | | **Pre-Test** | 3 min | Present | Present | Absent | Baseline preference (PI₀) | | **Training** | 10 min | Present | Present | With A only | Conditioning (CS+/CS-) | | **Test** | 3 min | Present | Present | Absent | Memory expression (PI) | | **Post-Test** | 3 min | Present | Present | Absent | Memory retention | ### Running Training Phase ```bash larvaworld Exp PItrain -N 30 -duration 0.2 # short demo run (use 10.0 for full protocol) ``` ### Running Test Phase ```bash larvaworld Exp PItest_off -N 30 -duration 0.1 # short demo run (use 3.0 for full protocol) ``` ### Complete Protocol (Python) ```python from larvaworld.lib import reg, util from larvaworld.lib.sim import ExpRun screen_kws = {} # headless # 1. Pre-Test (baseline) -- shortened for demo pre_params = reg.conf.Exp.getID("PItest_off").get_copy() pre_params.duration = 0.1 pre = ExpRun( experiment="PItest_off", parameters=pre_params, screen_kws=screen_kws, store_data=False, ) pre.simulate() pre_ds = pre.datasets[0] xs_pre = pre_ds.e["x"].values arena_xdim = pre_ds.c.env_params.arena.dims[0] pi_baseline = util.comp_PI(arena_xdim=arena_xdim, xs=xs_pre) print(f"Baseline PI: {pi_baseline:.3f}") # 2. Training (odor + food conditioning) -- shortened for demo train_params = reg.conf.Exp.getID("PItrain").get_copy() train_params.duration = 0.2 train = ExpRun( experiment="PItrain", parameters=train_params, screen_kws=screen_kws, store_data=False, ) train.simulate() # 3. Test (memory expression) -- shortened for demo test_params = reg.conf.Exp.getID("PItest_off").get_copy() test_params.duration = 0.1 test = ExpRun( experiment="PItest_off", parameters=test_params, screen_kws=screen_kws, store_data=False, ) test.simulate() test_ds = test.datasets[0] xs_test = test_ds.e["x"].values pi_trained = util.comp_PI(arena_xdim=arena_xdim, xs=xs_test) print(f"Trained PI: {pi_trained:.3f}") print(f"Learning effect: {pi_trained - pi_baseline:.3f}") ``` ### Preference Index (PI) **Definition**: `PI = (N_CS+ - N_CS-) / (N_CS+ + N_CS-)` Where: - `N_CS+`: Number of larvae on the CS+ side (e.g. left side) at the timepoint used for PI - `N_CS-`: Number of larvae on the CS- side (e.g. right side) at the timepoint used for PI **Interpretation**: - `PI = 0`: No preference - `PI > 0`: Preference for CS+ (learning) - `PI < 0`: Avoidance of CS+ **Computing PI**: ```python from larvaworld.lib import util xs = dataset.e["x"].values arena_xdim = dataset.c.env_params.arena.dims[0] PI = util.comp_PI(arena_xdim=arena_xdim, xs=xs) print(f"Preference Index: {PI:.3f}") ``` ### Memory Mechanisms Larvaworld implements two learning algorithms: #### 1. Q-Learning (Reinforcement Learning) **Algorithm**: TD-learning with reward-modulated gain adaptation ```python # Memory module updates sensory gain alpha = 0.1 # learning rate (example value) if reward > 0: gain["odor_A"] += alpha * reward # Increase gain for rewarded odor gain["odor_B"] -= alpha * reward # Decrease gain for non-rewarded odor ``` **Code Location**: `src/larvaworld/lib/model/modules/memory.py` (`RLmemory` class) #### 2. Mushroom Body (MB) Model **Algorithm**: Hebbian learning with KC-MBON synaptic plasticity **Code Location**: `src/larvaworld/lib/model/modules/memory.py` (`RemoteBrianModelMemory` class) ### Analysis Example ```python # Load dataset (e.g., from a PI test run) from larvaworld.lib import util dataset = test.datasets[0] # produced by the runs above # Compute preference index xs = dataset.e["x"].values arena_xdim = dataset.c.env_params.arena.dims[0] PI = util.comp_PI(arena_xdim=arena_xdim, xs=xs) # Plot odor navigation and trajectories from larvaworld.lib.plot import traj traj.traj_1group(dataset) # Plot memory gain evolution (RL model) if "gain" in dataset.step_data.columns: import matplotlib.pyplot as plt plt.plot(dataset.step_data["gain"]) plt.xlabel("Time (s)") plt.ylabel("Sensory Gain") plt.title("Memory Gain Evolution") plt.show() ``` --- ## General Workflow ### 1. Select Experiment Choose from 57 preconfigured experiments: ```python from larvaworld.lib import reg # List available experiments exp_ids = reg.conf.Exp.confIDs print(f"Available: {len(exp_ids)} experiments") # Inspect experiment exp_conf = reg.conf.Exp.getID("chemotaxis") print(exp_conf) ``` See {doc}`../concepts/experiment_types` for the full list. ### 2. Customize Parameters Override default parameters: ```python from larvaworld.lib import reg, util from larvaworld.lib.sim import ExpRun # Start from an existing experiment template exp_params = reg.conf.Exp.getID("chemotaxis").get_copy() # Environment customization (override a template Env config) env_params = reg.conf.Env.getID("arena_200mm").get_copy() if env_params.odorscape is None: env_params.odorscape = util.AttrDict() env_params.odorscape.update({"odorscape": "Gaussian", "grid_dims": (51, 51)}) exp_params.env_params = env_params # Agent customization (larva groups are keyed by group_id) exp_params.larva_groups = reg.gen.LarvaGroup(mID="navigator", N=30).entry("navigator") run = ExpRun( experiment="chemotaxis", parameters=exp_params, duration=10.0, screen_kws={"vis_mode": "video", "save_video": True, "video_file": "chemotaxis"}, ) ``` ### 3. Run Simulation ```python run.simulate() ``` ### 4. Access Results ```python # Get dataset dataset = run.datasets[0] # Summary statistics print(dataset.endpoint_data) # Time-series data print(dataset.step_data.keys()) # Configuration print(dataset.config) ``` ### 5. Analyze Data ```python # Preprocessing dataset.preprocess(filter_f=3.0) # Metrics dataset.process(proc_keys=["angular", "spatial"]) # Annotations dataset.annotate( anot_keys=["bout_detection", "bout_distribution", "interference"] ) # See :doc:`../visualization/plotting_api` for plotting examples. ``` ### 6. Save Results ```python # Save to HDF5 run.store() # Location: data/SimGroup/exp_runs/{experiment}/{id}/ print(f"Saved to: {run.dir}") ``` --- ## Video Generation Create videos for presentations or publications: ```python from larvaworld.lib import reg from larvaworld.lib.sim import ExpRun run = ExpRun( experiment="dish", parameters=reg.conf.Exp.getID("dish").get_copy(), duration=0.5, screen_kws={ "vis_mode": "video", "save_video": True, "video_file": "dish_exploration", "fps": 10, } ) run.simulate() ``` For keyboard controls during visualization, see {doc}`../visualization/keyboard_controls`. --- ## Related Documentation - {doc}`../concepts/simulation_modes` - Simulation mode comparison - {doc}`../concepts/experiment_types` - All 57 preconfigured experiments - {doc}`../concepts/experiment_configuration_pipeline` - Configuration system - {doc}`../agents_environments/arenas_and_substrates` - Environment setup - {doc}`../data_pipeline/data_processing` - Data processing pipeline - {doc}`../tutorials/cli` - Step-by-step tutorial