Skip to content

Commit

Permalink
Add support for sinusoidal inputs in sonata configs (#367)
Browse files Browse the repository at this point in the history
* Add support for sinusoidal inputs in sonata configs
  • Loading branch information
jorblancoa authored Aug 2, 2024
1 parent c631788 commit 5b1c2c8
Show file tree
Hide file tree
Showing 7 changed files with 120 additions and 0 deletions.
13 changes: 13 additions & 0 deletions include/bbp/sonata/config.h
Original file line number Diff line number Diff line change
Expand Up @@ -418,6 +418,7 @@ class SONATA_API SimulationConfig
linear,
relative_linear,
pulse,
sinusoidal,
subthreshold,
hyperpolarizing,
synapse_replay,
Expand Down Expand Up @@ -480,6 +481,17 @@ class SONATA_API SimulationConfig
bool representsPhysicalElectrode = false;
};

struct InputSinusoidal: public InputBase {
/// The peak amplitude of the sinusoid. Given in nA.
double ampStart{};
/// The frequency of the sinusoidal waveform. Given in Hz.
double frequency{};
/// Timestep of generated signal in ms. Default is 0.025 ms
double dt{};
/// Whether this input represents a physical electrode. Default is false
bool representsPhysicalElectrode = false;
};

struct InputSubthreshold: public InputBase {
/// A percentage adjusted from 100 of a cell's threshold current
double percentLess{};
Expand Down Expand Up @@ -625,6 +637,7 @@ class SONATA_API SimulationConfig
using Input = nonstd::variant<InputLinear,
InputRelativeLinear,
InputPulse,
InputSinusoidal,
InputSubthreshold,
InputHyperpolarizing,
InputSynapseReplay,
Expand Down
16 changes: 16 additions & 0 deletions python/bindings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -853,6 +853,21 @@ PYBIND11_MODULE(_libsonata, m) {
&SimulationConfig::InputPulse::representsPhysicalElectrode,
DOC_SIMULATIONCONFIG(InputPulse, representsPhysicalElectrode));

py::class_<SimulationConfig::InputSinusoidal, SimulationConfig::InputBase>(simConf,
"Sinusoidal")
.def_readonly("amp_start",
&SimulationConfig::InputSinusoidal::ampStart,
DOC_SIMULATIONCONFIG(InputSinusoidal, ampStart))
.def_readonly("frequency",
&SimulationConfig::InputSinusoidal::frequency,
DOC_SIMULATIONCONFIG(InputSinusoidal, frequency))
.def_readonly("dt",
&SimulationConfig::InputSinusoidal::dt,
DOC_SIMULATIONCONFIG(InputSinusoidal, dt))
.def_readonly("represents_physical_electrode",
&SimulationConfig::InputSinusoidal::representsPhysicalElectrode,
DOC_SIMULATIONCONFIG(InputSinusoidal, representsPhysicalElectrode));

py::class_<SimulationConfig::InputSubthreshold, SimulationConfig::InputBase>(simConf,
"Subthreshold")
.def_readonly("percent_less",
Expand Down Expand Up @@ -1039,6 +1054,7 @@ PYBIND11_MODULE(_libsonata, m) {
.value("linear", SimulationConfig::InputBase::Module::linear)
.value("relative_linear", SimulationConfig::InputBase::Module::relative_linear)
.value("pulse", SimulationConfig::InputBase::Module::pulse)
.value("sinusoidal", SimulationConfig::InputBase::Module::sinusoidal)
.value("subthreshold", SimulationConfig::InputBase::Module::subthreshold)
.value("hyperpolarizing", SimulationConfig::InputBase::Module::hyperpolarizing)
.value("synapse_replay", SimulationConfig::InputBase::Module::synapse_replay)
Expand Down
12 changes: 12 additions & 0 deletions python/generated/docstrings.h
Original file line number Diff line number Diff line change
Expand Up @@ -833,6 +833,8 @@ static const char *__doc_bbp_sonata_SimulationConfig_InputBase_Module_ornstein_u

static const char *__doc_bbp_sonata_SimulationConfig_InputBase_Module_pulse = R"doc()doc";

static const char *__doc_bbp_sonata_SimulationConfig_InputBase_Module_sinusoidal = R"doc()doc";

static const char *__doc_bbp_sonata_SimulationConfig_InputBase_Module_relative_linear = R"doc()doc";

static const char *__doc_bbp_sonata_SimulationConfig_InputBase_Module_relative_ornstein_uhlenbeck = R"doc()doc";
Expand Down Expand Up @@ -911,6 +913,16 @@ static const char *__doc_bbp_sonata_SimulationConfig_InputPulse_representsPhysic

static const char *__doc_bbp_sonata_SimulationConfig_InputPulse_width = R"doc(The length of time each pulse lasts (ms))doc";

static const char *__doc_bbp_sonata_SimulationConfig_InputSinusoidal = R"doc()doc";

static const char *__doc_bbp_sonata_SimulationConfig_InputSinusoidal_ampStart = R"doc(The amount of current initially injected (nA))doc";

static const char *__doc_bbp_sonata_SimulationConfig_InputSinusoidal_frequency = R"doc(The frequency of the waveform (Hz))doc";

static const char *__doc_bbp_sonata_SimulationConfig_InputSinusoidal_dt = R"doc(Timestep of generated signal in ms. Default is 0.025 ms)doc";

static const char *__doc_bbp_sonata_SimulationConfig_InputSinusoidal_representsPhysicalElectrode = R"doc(Whether this input represents a physical electrode. Default is false)doc";

static const char *__doc_bbp_sonata_SimulationConfig_InputRelativeLinear = R"doc()doc";

static const char *__doc_bbp_sonata_SimulationConfig_InputRelativeLinear_percentEnd = R"doc(The percentage of a cell's threshold current to inject at the end)doc";
Expand Down
20 changes: 20 additions & 0 deletions python/tests/test_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -487,6 +487,8 @@ def test_basic(self):
"ex_replay",
"ex_seclamp",
"ex_shotnoise",
"ex_sinusoidal",
"ex_sinusoidal_default_dt",
"ex_subthreshold"
})

Expand Down Expand Up @@ -514,6 +516,24 @@ def test_basic(self):
self.assertEqual(self.config.input('ex_pulse').width, 1)
self.assertEqual(self.config.input('ex_pulse').frequency, 80)

self.assertEqual(self.config.input('ex_sinusoidal').input_type.name, 'current_clamp')
self.assertEqual(self.config.input('ex_sinusoidal').module.name, 'sinusoidal')
self.assertEqual(self.config.input('ex_sinusoidal').delay, 10)
self.assertEqual(self.config.input('ex_sinusoidal').duration, 80)
self.assertEqual(self.config.input('ex_sinusoidal').node_set, "Mosaic")
self.assertEqual(self.config.input('ex_sinusoidal').frequency, 8)
self.assertEqual(self.config.input('ex_sinusoidal').amp_start, 0.2)
self.assertEqual(self.config.input('ex_sinusoidal').dt, 0.5)

self.assertEqual(self.config.input('ex_sinusoidal_default_dt').input_type.name, 'current_clamp')
self.assertEqual(self.config.input('ex_sinusoidal_default_dt').module.name, 'sinusoidal')
self.assertEqual(self.config.input('ex_sinusoidal_default_dt').delay, 10)
self.assertEqual(self.config.input('ex_sinusoidal_default_dt').duration, 80)
self.assertEqual(self.config.input('ex_sinusoidal_default_dt').node_set, "Mosaic")
self.assertEqual(self.config.input('ex_sinusoidal_default_dt').frequency, 80)
self.assertEqual(self.config.input('ex_sinusoidal_default_dt').amp_start, 2)
self.assertEqual(self.config.input('ex_sinusoidal_default_dt').dt, 0.025)

self.assertEqual(self.config.input('ex_noise_meanpercent').input_type.name, 'current_clamp')
self.assertEqual(self.config.input('ex_noise_meanpercent').module.name, 'noise')
self.assertEqual(self.config.input('ex_noise_meanpercent').delay, 0)
Expand Down
14 changes: 14 additions & 0 deletions src/config.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ NLOHMANN_JSON_SERIALIZE_ENUM(
{SimulationConfig::InputBase::Module::linear, "linear"},
{SimulationConfig::InputBase::Module::relative_linear, "relative_linear"},
{SimulationConfig::InputBase::Module::pulse, "pulse"},
{SimulationConfig::InputBase::Module::sinusoidal, "sinusoidal"},
{SimulationConfig::InputBase::Module::subthreshold, "subthreshold"},
{SimulationConfig::InputBase::Module::hyperpolarizing, "hyperpolarizing"},
{SimulationConfig::InputBase::Module::synapse_replay, "synapse_replay"},
Expand Down Expand Up @@ -438,6 +439,18 @@ SimulationConfig::Input parseInputModule(const nlohmann::json& valueIt,
{false});
return ret;
}
case Module::sinusoidal: {
SimulationConfig::InputSinusoidal ret;
parseCommon(ret);
parseMandatory(valueIt, "amp_start", debugStr, ret.ampStart);
parseMandatory(valueIt, "frequency", debugStr, ret.frequency);
parseOptional(valueIt, "dt", ret.dt, {0.025});
parseOptional(valueIt,
"represents_physical_electrode",
ret.representsPhysicalElectrode,
{false});
return ret;
}
case Module::subthreshold: {
SimulationConfig::InputSubthreshold ret;
parseCommon(ret);
Expand Down Expand Up @@ -1234,6 +1247,7 @@ class SimulationConfig::Parser
if (!(nonstd::holds_alternative<SimulationConfig::InputLinear>(input) ||
nonstd::holds_alternative<SimulationConfig::InputRelativeLinear>(input) ||
nonstd::holds_alternative<SimulationConfig::InputPulse>(input) ||
nonstd::holds_alternative<SimulationConfig::InputSinusoidal>(input) ||
nonstd::holds_alternative<SimulationConfig::InputSubthreshold>(input) ||
nonstd::holds_alternative<SimulationConfig::InputNoise>(input) ||
nonstd::holds_alternative<SimulationConfig::InputShotNoise>(input) ||
Expand Down
19 changes: 19 additions & 0 deletions tests/data/config/simulation_config.json
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,25 @@
"duration": 80,
"node_set": "Mosaic"
},
"ex_sinusoidal": {
"input_type": "current_clamp",
"module": "sinusoidal",
"frequency": 8,
"amp_start": 0.2,
"dt": 0.5,
"delay": 10,
"duration": 80,
"node_set": "Mosaic"
},
"ex_sinusoidal_default_dt": {
"input_type": "current_clamp",
"module": "sinusoidal",
"frequency": 80,
"amp_start": 2,
"delay": 10,
"duration": 80,
"node_set": "Mosaic"
},
"ex_subthreshold": {
"input_type": "current_clamp",
"module": "subthreshold",
Expand Down
26 changes: 26 additions & 0 deletions tests/test_config.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -431,6 +431,30 @@ TEST_CASE("SimulationConfig") {
CHECK(input.ampStart == 2);
CHECK(input.width == 1);
}
{
const auto input = nonstd::get<SimulationConfig::InputSinusoidal>(config.getInput("ex_sinusoidal"));
CHECK(input.inputType == InputType::current_clamp);
CHECK(input.module == Module::sinusoidal);
CHECK(input.delay == 10);
CHECK(input.duration == 80);
CHECK(input.nodeSet == "Mosaic");

CHECK(input.frequency == 8);
CHECK(input.ampStart == 0.2);
CHECK(input.dt == 0.5);
}
{
const auto input = nonstd::get<SimulationConfig::InputSinusoidal>(config.getInput("ex_sinusoidal_default_dt"));
CHECK(input.inputType == InputType::current_clamp);
CHECK(input.module == Module::sinusoidal);
CHECK(input.delay == 10);
CHECK(input.duration == 80);
CHECK(input.nodeSet == "Mosaic");

CHECK(input.frequency == 80);
CHECK(input.ampStart == 2);
CHECK(input.dt == 0.025);
}
{
const auto input = nonstd::get<SimulationConfig::InputSubthreshold>(config.getInput("ex_subthreshold"));
CHECK(input.inputType == InputType::current_clamp);
Expand Down Expand Up @@ -567,6 +591,8 @@ TEST_CASE("SimulationConfig") {
"ex_replay",
"ex_seclamp",
"ex_shotnoise",
"ex_sinusoidal",
"ex_sinusoidal_default_dt",
"ex_subthreshold"});

auto overrides = config.getConnectionOverrides();
Expand Down

0 comments on commit 5b1c2c8

Please sign in to comment.