Getting Started¶
First steps¶
The scaffold provides a simple command line interface (CLI) to compile network architectures and run simulations.
To start, let’s create ourselves a project directory and a template configuration:
mkdir my_brain
cd my_brain
bsb make-config
See Command Line Interface for a full list of CLI commands.
The make-config
command makes a template configuration file:
{
"name": "Empty template",
"network_architecture": {
"simulation_volume_x": 400.0,
"simulation_volume_z": 400.0
},
"output": {
"format": "bsb.output.HDF5Formatter"
},
"layers": {
"base_layer": {
"thickness": 100
}
},
"cell_types": {
"base_type": {
"placement": {
"class": "bsb.placement.ParticlePlacement",
"layer": "base_layer",
"soma_radius": 2.5,
"density": 3.9e-4
},
"morphology": {
"class": "bsb.morphologies.NoGeometry"
},
"plotting": {
"display_label": "Template cell",
"color": "#E62314",
"opacity": 0.5
}
}
},
"after_placement": {
},
"connection_types": {
},
"after_connectivity": {
},
"simulations": {
}
}
The configuration is laid out to be as self explanatory as possible. For a full walkthrough of all parts see the Configuration reference.
To convert the abstract description in the configuration file into a concrete
network file with cell positions and connections run the compile
command:
bsb -c network_configuration.json compile -p
Note
You can leave off the -c
(or --config
) flag in this case as
network_configuration.json
is the default config that bsb compile
will
look for. The -p
(or --plot
) flag will plot your network afterwards
First script¶
The BSB is also a library that can be imported into Python scripts. You can load configurations and adapt the loaded object before constructing a network with it to programmatically alter the network structure.
Let’s go over an example first script that creates 5 networks with different
densities of base_type
.
To use the scaffold in your script you should import the bsb.core.Scaffold
and construct a new instance by passing it a bsb.config.ScaffoldConfig
.
The only provided configuration is the bsb.config.JSONConfig
.
To load a configuration file, construct a JSONConfig object providing the file
keyword argument with a path to the configuration file:
from bsb.core import Scaffold
from bsb.config import JSONConfig
from bsb.reporting import set_verbosity
config = JSONConfig(file="network_configuration.json")
set_verbosity(3) # This way we can follow what's going on.
scaffold = Scaffold(config)
Note
The verbosity is 1 by default, which only displays errors. You could also add a
verbosity
attribute to the root node of the network_configuration.json
file to
set the verbosity.
Let’s find the base_type
cell configuration:
base_type = scaffold.get_cell_type("base_type")
The next step is to adapt the base_type
cell density each iteration. The location
of the attributes on the Python objects mostly corresponds to their location in
the configuration file. This means that:
"base_type": {
"placement": {
"density": 3.9e-4,
...
},
...
}
will be stored in the Python CellType
object under
base_type.placement.density
:
max_density = base_type.placement.density
for i in range(5):
base_type.placement.density = i * 20 / 100 * max_density
scaffold.compile_network()
scaffold.plot_network_cache()
scaffold.reset_network_cache()
Warning
If you don’t use reset_network_cache()
between compile_network()
calls,
the new cells will just be appended to the previous ones. This might lead to
confusing results.
Full code example¶
from bsb.core import Scaffold
from bsb.config import JSONConfig
from bsb.reporting import set_verbosity
config = JSONConfig(file="network_configuration.json")
set_verbosity(3) # This way we can follow what's going on.
scaffold = Scaffold(config)
base_type = scaffold.get_cell_type("base_type_cell")
max_density = base_type.placement.density
for i in range(5):
base_type.placement.density = i * 20 / 100 * max_density
scaffold.compile_network()
scaffold.plot_network_cache()
scaffold.reset_network_cache()
Network compilation¶
compilation
is the process of creating an output containing the constructed
network with cells placed according to the specified placement strategies and
connected to each other according to the specified connection strategies:
from bsb.core import Scaffold
from bsb.config import JSONConfig
import os
config = JSONConfig(file="network_configuration.json")
# The configuration provided in the file can be overwritten here.
# For example:
config.cell_types["some_cell"].placement.some_parameter = 50
config.cell_types["some_cell"].plotting.color = os.getenv("ENV_PLOTTING_COLOR", "black")
scaffold = Scaffold(config)
scaffold.compile_network()
The configuration object can be freely modified before compilation, although values that depend on eachother - i.e. layers in a stack - will not update each other.
Network simulation¶
Simulations can be executed from configuration in a managed way using:
scaffold.run_simulation(name)
This will load the simulation configuration associated with name
and create
an adapter for the simulator. An adapter translates the scaffold configuration
into commands for the simulator. In this way scaffold adapters are able to
prepare simulations in external simulators such as NEST or NEURON for you. After
the simulator is prepared the simulation is ran.
For more control over the interface with the simulator, or finer control of the configuration, the process can be split into parts. The adapter to the interface of the simulator can be ejected and its configuration can be modified:
adapter = scaffold.create_adapter(name)
adapter.devices["input_stimulation"].parameters["rate"] = 40
You can then use this adapter to prepare the simulator for the configured simulation:
simulator = adapter.prepare()
After preparation the simulator is primed, but can still be modified directly accessing the interface of the simulator itself. For example to create 5 extra cells in a NEST simulation on top of the prepared configuration one could:
cells = simulator.Create("iaf_cond_alpha", 5)
print(cells)
You’ll notice that the IDs of those cells won’t start at 1 as would be the case
for an empty simulation, because the prepare
statement has already created
cells in the simulator.
After custom interfacing with the simulator, the adapter can be used to run the simulation:
adapter.simulate()
Full code example¶
adapter = scaffold.create_adapter(name)
adapter.devices["input_stimulation"].parameters["rate"] = 40
simulator = adapter.prepare()
cells = simulator.Create("iaf_cond_alpha", 5)
print(cells)
adapter.simulate()
Using Cell Types¶
Cell types are obtained by name using bsb.get_cell_type(name). And the associated cells either currently in the network cache or in persistent storage can be fetched with bsb.get_cells_by_type(name). The columns of such a set are the scaffold id of the cell, followed by the type id and the xyz position.
A collection of all cell types can be retrieved with bsb.get_cell_types():
for cell_type in scaffold.get_cell_types():
cells = scaffold.get_cells_by_type(cell_type.name)
for cell in cells:
print("Cell id {} of type {} at position {}.".format(cell[0], cell[1], cell[2:5]))