Domain Packs
Pre-built BioModules for specific scientific domains.
Neuroscience Pack
bsim.packs.neuro - Computational neuroscience modules for spiking neural networks.
Installation
from bsim.packs.neuro import (
# Inputs
PoissonInput,
StepCurrent,
# Populations
IzhikevichPopulation,
# Synapses
ExpSynapseCurrent,
# Monitors
SpikeMonitor,
RateMonitor,
StateMonitor,
NeuroMetrics
)Input Modules
PoissonInput
Generate Poisson-distributed spike trains:
input = PoissonInput(
rate_hz=100.0, # Firing rate (Hz)
n=10 # Number of spike trains
)Outputs:
spikes- Spike times array
StepCurrent
Inject current into neurons:
# Constant current
current = StepCurrent(I=10.0) # 10 pA
# Scheduled current (start_t, end_t, I_value)
current = StepCurrent(
I=10.0,
schedule=[(0.1, 0.5, 15.0)]
)Outputs:
current- Current value
Neuron Populations
IzhikevichPopulation
Spiking neuron population with various presets:
# Regular spiking (default cortical neurons)
pop = IzhikevichPopulation(n=100, preset="RS")
# Fast spiking (interneurons)
pop = IzhikevichPopulation(n=50, preset="FS")
# Intrinsically bursting
pop = IzhikevichPopulation(n=25, preset="Bursting")Presets:
| Preset | a | b | c | d | Behavior |
|---|---|---|---|---|---|
RS | 0.02 | 0.2 | -65 | 8 | Regular spiking |
FS | 0.1 | 0.2 | -65 | 2 | Fast spiking |
Bursting | 0.02 | 0.2 | -55 | 4 | Intrinsically bursting |
Chattering | 0.02 | 0.2 | -50 | 2 | Chattering |
LTS | 0.02 | 0.25 | -65 | 2 | Low-threshold spiking |
Custom parameters:
pop = IzhikevichPopulation(
n=100,
a=0.02, b=0.2, c=-65, d=8, # Izhikevich parameters
v_init=-70.0, # Initial membrane potential
u_init=-14.0 # Initial recovery variable
)Inputs:
current- External current injection
Outputs:
spikes- Output spike timesstate- Sampled membrane state traces
Synapses
ExpSynapseCurrent
Exponentially decaying synaptic current:
synapse = ExpSynapseCurrent(
n_pre=100, # Pre-synaptic population size
n_post=100, # Post-synaptic population size
p_connect=0.1,# Connection probability
weight=1.0, # Synaptic weight
tau=0.01, # Decay time constant (s)
delay_steps=0 # Step delay
)Inputs:
spikes- Presynaptic spike times
Outputs:
current- Postsynaptic current
Monitors
SpikeMonitor
Record and visualize spike rasters:
monitor = SpikeMonitor(
width=800, # Raster plot width
height=400 # Raster plot height
)Inputs:
spikes- Spike times to record
Visualization:
- Raster plot image
RateMonitor
Population firing rate over time:
monitor = RateMonitor(
window_size=0.05, # Window in seconds
n_neurons=100 # Population size
)Visualization:
- Firing rate timeseries
StateMonitor
Record membrane voltage traces:
monitor = StateMonitor(
max_points=5000
)Visualization:
- Voltage traces timeseries
NeuroMetrics
Summary statistics:
metrics = NeuroMetrics()Visualization:
- Table with spike counts, mean rates, CV ISI, etc.
Complete Example
import bsim
from bsim.packs.neuro import (
PoissonInput, IzhikevichPopulation,
ExpSynapseCurrent, SpikeMonitor, RateMonitor
)
world = bsim.BioWorld(solver=bsim.FixedStepSolver())
wb = bsim.WiringBuilder(world)
# Input spikes
wb.add("input", PoissonInput(n=100, rate_hz=50.0))
wb.add("input_syn", ExpSynapseCurrent(n_pre=100, n_post=800, weight=0.5, tau=0.01))
# Excitatory population
wb.add("exc", IzhikevichPopulation(n=800, preset="RS"))
# Inhibitory population
wb.add("inh", IzhikevichPopulation(n=200, preset="FS"))
# Synapses
wb.add("e2i_syn", ExpSynapseCurrent(n_pre=800, n_post=200, weight=0.5, tau=0.01))
wb.add("i2e_syn", ExpSynapseCurrent(n_pre=200, n_post=800, weight=-1.0, tau=0.01))
# Monitors
wb.add("spike_mon", SpikeMonitor())
wb.add("rate_mon", RateMonitor(window_size=0.05, n_neurons=1000))
# Wiring
wb.connect("input.out.spikes", ["input_syn.in.spikes"])
wb.connect("input_syn.out.current", ["exc.in.current"])
wb.connect("exc.out.spikes", ["e2i_syn.in.spikes", "spike_mon.in.spikes", "rate_mon.in.spikes"])
wb.connect("e2i_syn.out.current", ["inh.in.current"])
wb.connect("inh.out.spikes", ["i2e_syn.in.spikes"])
wb.connect("i2e_syn.out.current", ["exc.in.current"])
wb.apply()
# Simulate 1 second
result = world.simulate(steps=10000, dt=0.001)Ecology Pack
bsim.packs.ecology - Population dynamics and ecosystem simulations.
Installation
from bsim.packs.ecology import (
# Environment
Environment,
# Populations
OrganismPopulation,
Prey,
Predator,
# Interactions
PredatorPreyInteraction,
CompetitionInteraction,
MutualismInteraction,
# Monitors
PopulationMonitor,
EcologyMetrics,
PhaseSpaceMonitor,
# Presets
PRESET_RABBIT, PRESET_FOX,
PRESET_DEER, PRESET_WOLF,
PRESET_BACTERIA
)Environment
Broadcast environmental conditions:
env = Environment(
temperature=25.0, # Celsius
water=100.0, # Arbitrary units
food_availability=1.0, # 0-2 scale
sunlight=1.0
)Outputs:
conditions- Combined environmental state
Populations
OrganismPopulation
Generic population with birth/death dynamics:
pop = OrganismPopulation(
name="Species",
initial_count=100, # Initial population
birth_rate=0.1, # Per-capita birth rate
death_rate=0.02, # Per-capita death rate
carrying_capacity=1000 # Optional K
)Using presets:
rabbits = OrganismPopulation(name="Rabbits", initial_count=100, preset="rabbit")
foxes = OrganismPopulation(name="Foxes", initial_count=10, preset="fox")Presets:
| Preset | birth_rate | death_rate | Notes |
|---|---|---|---|
PRESET_RABBIT | 0.2 | 0.05 | Fast reproduction |
PRESET_FOX | 0.05 | 0.08 | Predator-leaning |
PRESET_DEER | 0.1 | 0.04 | Moderate |
PRESET_WOLF | 0.04 | 0.06 | Slow, apex predator |
PRESET_BACTERIA | 0.8 | 0.7 | Very fast |
Inputs:
conditions- Environment conditions payloadpredation- Predation events (kills)competition- Competition pressurefood_gained- Food from predation
Outputs:
population_state- Current population state payload
Interactions
PredatorPreyInteraction
Lotka-Volterra style predation:
interaction = PredatorPreyInteraction(
predation_rate=0.01, # Attack rate
conversion_efficiency=0.1 # Prey -> Predator conversion
)Inputs:
prey_state- Prey population statepredator_state- Predator population state
Outputs:
predation- Predation events sent to preyfood_gained- Food gain sent to predators
CompetitionInteraction
Resource competition between species:
competition = CompetitionInteraction(
competition_coefficient=0.5,
resource_type="food"
)MutualismInteraction
Beneficial relationships:
mutualism = MutualismInteraction(
benefit_rate=0.05,
benefit_type="food"
)Monitors
PopulationMonitor
Track populations over time:
monitor = PopulationMonitor()Inputs:
population_state- Population state signals
Visualization:
- Dual timeseries plot
EcologyMetrics
Summary statistics:
metrics = EcologyMetrics()Visualization:
- Table with diversity indices, extinction events, etc.
PhaseSpaceMonitor
2D phase space trajectory:
monitor = PhaseSpaceMonitor(
x_species="Prey",
y_species="Predator"
)Visualization:
- Phase space plot
Complete Example
import bsim
from bsim.packs.ecology import (
Environment, OrganismPopulation,
PredatorPreyInteraction, PopulationMonitor, PhaseSpaceMonitor
)
world = bsim.BioWorld(solver=bsim.FixedStepSolver())
wb = bsim.WiringBuilder(world)
# Environment
wb.add("env", Environment(temperature=20.0))
# Populations
wb.add("rabbits", OrganismPopulation(name="Rabbits", initial_count=100, preset="rabbit"))
wb.add("foxes", OrganismPopulation(name="Foxes", initial_count=10, preset="fox"))
# Interaction
wb.add("predation", PredatorPreyInteraction(
predation_rate=0.01,
conversion_efficiency=0.1
))
# Monitors
pop_mon = PopulationMonitor()
phase_mon = PhaseSpaceMonitor(x_species="Rabbits", y_species="Foxes")
wb.add("pop_mon", pop_mon)
wb.add("phase_mon", phase_mon)
# Wiring
wb.connect("env.out.conditions", ["rabbits.in.conditions", "foxes.in.conditions"])
wb.connect("rabbits.out.population_state", [
"predation.in.prey_state",
"pop_mon.in.population_state",
"phase_mon.in.population_state"
])
wb.connect("foxes.out.population_state", [
"predation.in.predator_state",
"pop_mon.in.population_state",
"phase_mon.in.population_state"
])
wb.connect("predation.out.predation", ["rabbits.in.predation"])
wb.connect("predation.out.food_gained", ["foxes.in.food_gained"])
wb.apply()
# Simulate 100 time units
result = world.simulate(steps=10000, dt=0.01)
# Get visualizations
pop_vis = pop_mon.visualize()
phase_vis = phase_mon.visualize()Creating Custom Packs
Structure a new domain pack:
bsim/packs/mypack/
├── __init__.py # Export all modules
├── inputs.py # Input modules
├── populations.py # Core entities
├── interactions.py # Interactions between entities
├── monitors.py # Visualization modules
└── presets.py # Parameter presetsExample module:
# mypack/populations.py
from bsim import BioModule
class CellPopulation(BioModule):
def __init__(self, n: int, division_rate: float):
super().__init__()
self.n = n
self.division_rate = division_rate
def inputs(self):
return {"nutrients", "signals"}
def outputs(self):
return {"population", "waste"}
# ... implement on_event, on_signal, visualize, reset