Skip to content

Commit

Permalink
Make documentation available for Python API
Browse files Browse the repository at this point in the history
* CircuitConfig, NodeSets, and SimulationConfig didn't have a top level
  docstring and thus sphinx `automodule` wasn't displaying them

* Many of the SimulationConfig were rooted in _libsonata, when they
  should be in SimulationConfig; this was refactored, however it has
  implications in the following projects:

* BlueCelluLab was update to work around the change
    BlueBrain/BlueCelluLab#123

* SNAP tests have been updated to handle the different locations of
  SimulationConfig classes:
    BlueBrain/snap#254
  • Loading branch information
mgeplf committed Feb 2, 2024
1 parent 21a31c4 commit 958f546
Show file tree
Hide file tree
Showing 4 changed files with 64 additions and 34 deletions.
1 change: 0 additions & 1 deletion docs/source/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@

# -- Project information -----------------------------------------------------

import os
from pathlib import Path
import pkg_resources
import re
Expand Down
57 changes: 30 additions & 27 deletions python/bindings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -527,7 +527,7 @@ PYBIND11_MODULE(_libsonata, m) {

bindStorageClass<NodeStorage>(m, "NodeStorage", "NodePopulation");

py::class_<NodeSets>(m, "NodeSets", "")
py::class_<NodeSets>(m, "NodeSets", "NodeSets")
.def(py::init<const std::string&>())
.def_static("from_file", [](py::object path) { return NodeSets::fromFile(py::str(path)); })
.def_property_readonly("names", &NodeSets::names, DOC_NODESETS(names))
Expand Down Expand Up @@ -589,11 +589,11 @@ PYBIND11_MODULE(_libsonata, m) {
.value("complete", CircuitConfig::ConfigStatus::complete)
.value("partial", CircuitConfig::ConfigStatus::partial);

py::class_<CircuitConfig>(m, "CircuitConfig", "")
py::class_<CircuitConfig>(m, "CircuitConfig", "Circuit Configuration")
.def(py::init<const std::string&, const std::string&>())
.def_static("from_file",
[](py::object path) { return CircuitConfig::fromFile(py::str(path)); })
.def_property_readonly("config_status", &CircuitConfig::getCircuitConfigStatus)
.def_property_readonly("config_status", &CircuitConfig::getCircuitConfigStatus, "ibid")
.def_property_readonly("node_sets_path", &CircuitConfig::getNodeSetsPath)
.def_property_readonly("node_populations", &CircuitConfig::listNodePopulations)
.def("node_population",
Expand All @@ -613,7 +613,8 @@ PYBIND11_MODULE(_libsonata, m) {
.def("edge_population_properties", &CircuitConfig::getEdgePopulationProperties, "name"_a)
.def_property_readonly("expanded_json", &CircuitConfig::getExpandedJSON);

py::class_<SimulationConfig::Run> run(m,
py::class_<SimulationConfig> simConf(m, "SimulationConfig", "Simulation Configuration");
py::class_<SimulationConfig::Run> run(simConf,
"Run",
"Stores parameters defining global simulation settings");
run.def_readonly("tstop", &SimulationConfig::Run::tstop, DOC_SIMULATIONCONFIG(Run, tstop))
Expand Down Expand Up @@ -648,7 +649,9 @@ PYBIND11_MODULE(_libsonata, m) {
.value("nicholson", SimulationConfig::Run::IntegrationMethod::nicholson)
.value("nicholson_ion", SimulationConfig::Run::IntegrationMethod::nicholson_ion);

py::class_<SimulationConfig::Output> output(m, "Output", "Parameters of simulation output");
py::class_<SimulationConfig::Output> output(simConf,
"Output",
"Parameters of simulation output");
output
.def_readonly("output_dir",
&SimulationConfig::Output::outputDir,
Expand All @@ -672,7 +675,7 @@ PYBIND11_MODULE(_libsonata, m) {
.value("by_time", SimulationConfig::Output::SpikesSortOrder::by_time);

py::class_<SimulationConfig::Conditions> conditions(
m, "Conditions", "Parameters defining global experimental conditions");
simConf, "Conditions", "Parameters defining global experimental conditions");
conditions
.def_readonly("celsius",
&SimulationConfig::Conditions::celsius,
Expand Down Expand Up @@ -705,7 +708,7 @@ PYBIND11_MODULE(_libsonata, m) {
.value("soma", SimulationConfig::Conditions::SpikeLocation::soma)
.value("AIS", SimulationConfig::Conditions::SpikeLocation::AIS);

py::class_<SimulationConfig::ModificationBase> modificationBase(m, "ModificationBase");
py::class_<SimulationConfig::ModificationBase> modificationBase(simConf, "ModificationBase");
modificationBase
.def_readonly("node_set",
&SimulationConfig::ModificationBase::nodeSet,
Expand All @@ -715,10 +718,10 @@ PYBIND11_MODULE(_libsonata, m) {
DOC_SIMULATIONCONFIG(ModificationBase, type));

py::class_<SimulationConfig::ModificationTTX, SimulationConfig::ModificationBase>(
m, "ModificationTTX");
simConf, "ModificationTTX");

py::class_<SimulationConfig::ModificationConfigureAllSections,
SimulationConfig::ModificationBase>(m, "ModificationConfigureAllSections")
SimulationConfig::ModificationBase>(simConf, "ModificationConfigureAllSections")
.def_readonly("section_configure",
&SimulationConfig::ModificationConfigureAllSections::sectionConfigure,
DOC_SIMULATIONCONFIG(ModificationConfigureAllSections, sectionConfigure));
Expand All @@ -732,7 +735,7 @@ PYBIND11_MODULE(_libsonata, m) {
SimulationConfig::ModificationBase::ModificationType::ConfigureAllSections,
DOC_SIMULATIONCONFIG(ModificationBase, ModificationType, ConfigureAllSections));

py::class_<SimulationConfig::Report> report(m, "Report", "Parameters of a report");
py::class_<SimulationConfig::Report> report(simConf, "Report", "Parameters of a report");
report
.def_readonly("cells",
&SimulationConfig::Report::cells,
Expand Down Expand Up @@ -796,7 +799,7 @@ PYBIND11_MODULE(_libsonata, m) {
.value("center", SimulationConfig::Report::Compartments::center)
.value("all", SimulationConfig::Report::Compartments::all);

py::class_<SimulationConfig::InputBase> inputBase(m, "InputBase");
py::class_<SimulationConfig::InputBase> inputBase(simConf, "InputBase");
inputBase
.def_readonly("module",
&SimulationConfig::InputBase::module,
Expand All @@ -814,15 +817,15 @@ PYBIND11_MODULE(_libsonata, m) {
&SimulationConfig::InputBase::nodeSet,
DOC_SIMULATIONCONFIG(InputBase, nodeSet));

py::class_<SimulationConfig::InputLinear, SimulationConfig::InputBase>(m, "Linear")
py::class_<SimulationConfig::InputLinear, SimulationConfig::InputBase>(simConf, "Linear")
.def_readonly("amp_start",
&SimulationConfig::InputLinear::ampStart,
DOC_SIMULATIONCONFIG(InputLinear, ampStart))
.def_readonly("amp_end",
&SimulationConfig::InputLinear::ampEnd,
DOC_SIMULATIONCONFIG(InputLinear, ampEnd));

py::class_<SimulationConfig::InputRelativeLinear, SimulationConfig::InputBase>(m,
py::class_<SimulationConfig::InputRelativeLinear, SimulationConfig::InputBase>(simConf,
"RelativeLinear")
.def_readonly("percent_start",
&SimulationConfig::InputRelativeLinear::percentStart,
Expand All @@ -831,7 +834,7 @@ PYBIND11_MODULE(_libsonata, m) {
&SimulationConfig::InputRelativeLinear::percentEnd,
DOC_SIMULATIONCONFIG(InputRelativeLinear, percentEnd));

py::class_<SimulationConfig::InputPulse, SimulationConfig::InputBase>(m, "Pulse")
py::class_<SimulationConfig::InputPulse, SimulationConfig::InputBase>(simConf, "Pulse")
.def_readonly("amp_start",
&SimulationConfig::InputPulse::ampStart,
DOC_SIMULATIONCONFIG(InputPulse, ampStart))
Expand All @@ -845,15 +848,16 @@ PYBIND11_MODULE(_libsonata, m) {
&SimulationConfig::InputPulse::frequency,
DOC_SIMULATIONCONFIG(InputPulse, frequency));

py::class_<SimulationConfig::InputSubthreshold, SimulationConfig::InputBase>(m, "Subthreshold")
py::class_<SimulationConfig::InputSubthreshold, SimulationConfig::InputBase>(simConf,
"Subthreshold")
.def_readonly("percent_less",
&SimulationConfig::InputSubthreshold::percentLess,
DOC_SIMULATIONCONFIG(InputSubthreshold, percentLess));

py::class_<SimulationConfig::InputHyperpolarizing, SimulationConfig::InputBase>(
m, "Hyperpolarizing");
simConf, "Hyperpolarizing");

py::class_<SimulationConfig::InputSynapseReplay, SimulationConfig::InputBase>(m,
py::class_<SimulationConfig::InputSynapseReplay, SimulationConfig::InputBase>(simConf,
"SynapseReplay")
.def_readonly("spike_file",
&SimulationConfig::InputSynapseReplay::spikeFile,
Expand All @@ -862,15 +866,15 @@ PYBIND11_MODULE(_libsonata, m) {
&SimulationConfig::InputSynapseReplay::source,
DOC_SIMULATIONCONFIG(InputSynapseReplay, source));

py::class_<SimulationConfig::InputSeclamp, SimulationConfig::InputBase>(m, "Seclamp")
py::class_<SimulationConfig::InputSeclamp, SimulationConfig::InputBase>(simConf, "Seclamp")
.def_readonly("voltage",
&SimulationConfig::InputSeclamp::voltage,
DOC_SIMULATIONCONFIG(InputSeclamp, voltage))
.def_readonly("series_resistance",
&SimulationConfig::InputSeclamp::seriesResistance,
DOC_SIMULATIONCONFIG(InputSeclamp, seriesResistance));

py::class_<SimulationConfig::InputNoise, SimulationConfig::InputBase>(m, "Noise")
py::class_<SimulationConfig::InputNoise, SimulationConfig::InputBase>(simConf, "Noise")
.def_readonly("mean",
&SimulationConfig::InputNoise::mean,
DOC_SIMULATIONCONFIG(InputNoise, mean))
Expand All @@ -881,7 +885,7 @@ PYBIND11_MODULE(_libsonata, m) {
&SimulationConfig::InputNoise::variance,
DOC_SIMULATIONCONFIG(InputNoise, variance));

py::class_<SimulationConfig::InputShotNoise, SimulationConfig::InputBase>(m, "ShotNoise")
py::class_<SimulationConfig::InputShotNoise, SimulationConfig::InputBase>(simConf, "ShotNoise")
.def_readonly("rise_time",
&SimulationConfig::InputShotNoise::riseTime,
DOC_SIMULATIONCONFIG(InputShotNoise, riseTime))
Expand All @@ -908,7 +912,7 @@ PYBIND11_MODULE(_libsonata, m) {
DOC_SIMULATIONCONFIG(InputShotNoise, ampVar));

py::class_<SimulationConfig::InputRelativeShotNoise, SimulationConfig::InputBase>(
m, "RelativeShotNoise")
simConf, "RelativeShotNoise")
.def_readonly("rise_time",
&SimulationConfig::InputRelativeShotNoise::riseTime,
DOC_SIMULATIONCONFIG(InputRelativeShotNoise, riseTime))
Expand All @@ -935,7 +939,7 @@ PYBIND11_MODULE(_libsonata, m) {
DOC_SIMULATIONCONFIG(InputRelativeShotNoise, meanPercent));

py::class_<SimulationConfig::InputAbsoluteShotNoise, SimulationConfig::InputBase>(
m, "AbsoluteShotNoise")
simConf, "AbsoluteShotNoise")
.def_readonly("rise_time",
&SimulationConfig::InputAbsoluteShotNoise::riseTime,
DOC_SIMULATIONCONFIG(InputAbsoluteShotNoise, riseTime))
Expand All @@ -962,7 +966,7 @@ PYBIND11_MODULE(_libsonata, m) {
DOC_SIMULATIONCONFIG(InputAbsoluteShotNoise, sigma));

py::class_<SimulationConfig::InputOrnsteinUhlenbeck, SimulationConfig::InputBase>(
m, "OrnsteinUhlenbeck")
simConf, "OrnsteinUhlenbeck")
.def_readonly("tau",
&SimulationConfig::InputOrnsteinUhlenbeck::tau,
DOC_SIMULATIONCONFIG(InputOrnsteinUhlenbeck, tau))
Expand All @@ -983,7 +987,7 @@ PYBIND11_MODULE(_libsonata, m) {
DOC_SIMULATIONCONFIG(InputOrnsteinUhlenbeck, sigma));

py::class_<SimulationConfig::InputRelativeOrnsteinUhlenbeck, SimulationConfig::InputBase>(
m, "RelativeOrnsteinUhlenbeck")
simConf, "RelativeOrnsteinUhlenbeck")
.def_readonly("tau",
&SimulationConfig::InputRelativeOrnsteinUhlenbeck::tau,
DOC_SIMULATIONCONFIG(InputRelativeOrnsteinUhlenbeck, tau))
Expand Down Expand Up @@ -1027,7 +1031,7 @@ PYBIND11_MODULE(_libsonata, m) {
.value("voltage_clamp", SimulationConfig::InputBase::InputType::voltage_clamp)
.value("conductance", SimulationConfig::InputBase::InputType::conductance);

py::class_<SimulationConfig::ConnectionOverride>(m,
py::class_<SimulationConfig::ConnectionOverride>(simConf,
"ConnectionOverride",
"List of parameters of a connection")
.def_readonly("name",
Expand Down Expand Up @@ -1064,7 +1068,6 @@ PYBIND11_MODULE(_libsonata, m) {
&SimulationConfig::ConnectionOverride::neuromodulationStrength,
DOC_SIMULATIONCONFIG(ConnectionOverride, neuromodulationStrength));

py::class_<SimulationConfig> simConf(m, "SimulationConfig", "");
simConf.def(py::init<const std::string&, const std::string&>())
.def_static(
"from_file",
Expand Down Expand Up @@ -1113,7 +1116,7 @@ PYBIND11_MODULE(_libsonata, m) {
&SimulationConfig::getBetaFeatures,
DOC_SIMULATIONCONFIG(getBetaFeatures));

py::enum_<SimulationConfig::SimulatorType>(simConf, "SimulatorType")
py::enum_<SimulationConfig::SimulatorType>(simConf, "SimulatorType", "SimulatorType Enum")
.value("NEURON", SimulationConfig::SimulatorType::NEURON)
.value("CORENEURON", SimulationConfig::SimulatorType::CORENEURON);

Expand Down
27 changes: 27 additions & 0 deletions python/libsonata/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,33 @@
Hdf5Reader,
)

#import libsonata._libsonata
#for module in (
# 'Output',
# 'Conditions', # BlueBrain/BlueCelluLab/bluecellulab/circuit/config/sections.py
## 'ModificationTTX',
## 'ModificationConfigureAllSections',
## 'Report',
##
## 'InputBase',
## 'Linear',
## 'RelativeLinear',
## 'Pulse',
## 'Subthreshold',
## 'Hyperpolarizing',
## 'SynapseReplay',
## 'Seclamp',
## 'Noise',
## 'ShotNoise',
## 'RelativeShotNoise',
## 'AbsoluteShotNoise',
## 'OrnsteinUhlenbeck',
## 'RelativeOrnsteinUhlenbeck',
## 'ConnectionOverride',
# ):
# setattr(libsonata._libsonata, module, getattr(SimulationConfig, module))


__all__ = [
"CircuitConfig",
"CircuitConfigStatus",
Expand Down
13 changes: 7 additions & 6 deletions python/tests/test_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,6 @@
)


from libsonata._libsonata import Report, Output, Run, Conditions


PATH = os.path.join(os.path.dirname(os.path.realpath(__file__)),
'../../tests/data')

Expand Down Expand Up @@ -411,7 +408,8 @@ def test_basic(self):
self.assertEqual(self.config.run.dt, 0.025)
self.assertEqual(self.config.run.random_seed, 201506)
self.assertEqual(self.config.run.spike_threshold, -35.5)
self.assertEqual(self.config.run.integration_method, Run.IntegrationMethod.nicholson_ion)
self.assertEqual(self.config.run.integration_method,
SimulationConfig.Run.IntegrationMethod.nicholson_ion)
self.assertEqual(self.config.run.stimulus_seed, 111)
self.assertEqual(self.config.run.ionchannel_seed, 222)
self.assertEqual(self.config.run.minis_seed, 333)
Expand All @@ -423,11 +421,13 @@ def test_basic(self):
os.path.abspath(os.path.join(PATH, 'config/some/path/output')))
self.assertEqual(self.config.output.spikes_file, 'out.h5')
self.assertEqual(self.config.output.log_file, '')
self.assertEqual(self.config.output.spikes_sort_order, Output.SpikesSortOrder.by_id)
self.assertEqual(self.config.output.spikes_sort_order,
SimulationConfig.Output.SpikesSortOrder.by_id)

self.assertEqual(self.config.conditions.celsius, 35.0)
self.assertEqual(self.config.conditions.v_init, -80)
self.assertEqual(self.config.conditions.spike_location, Conditions.SpikeLocation.AIS)
self.assertEqual(self.config.conditions.spike_location,
SimulationConfig.Conditions.SpikeLocation.AIS)
self.assertEqual(self.config.conditions.extracellular_calcium, None)
self.assertEqual(self.config.conditions.randomize_gaba_rise_time, False)
self.assertEqual(self.config.conditions.mechanisms, {'ProbAMPANMDA_EMS': {'property2': -1,
Expand All @@ -446,6 +446,7 @@ def test_basic(self):
self.assertEqual(self.config.list_report_names,
{ "axonal_comp_centers", "cell_imembrane", "compartment", "soma", "lfp" })

Report = SimulationConfig.Report
self.assertEqual(self.config.report('soma').cells, 'Column')
self.assertEqual(self.config.report('soma').type, Report.Type.compartment)
self.assertEqual(self.config.report('soma').compartments, Report.Compartments.center)
Expand Down

0 comments on commit 958f546

Please sign in to comment.