diff --git a/include/bbp/sonata/config.h b/include/bbp/sonata/config.h index 9925f7a3..62a22e67 100644 --- a/include/bbp/sonata/config.h +++ b/include/bbp/sonata/config.h @@ -549,8 +549,6 @@ class SONATA_API SimulationConfig double reversal{}; /// Timestep of generated signal in ms. Default is 0.25 ms double dt{}; - /// The coefficient of variation (sd/mean) of gamma-distributed amplitudes - double ampCv{}; /// Signal mean as percentage of a cell’s threshold current (current_clamp) or inverse input /// resistance (conductance) double meanPercent{}; @@ -559,6 +557,10 @@ class SONATA_API SimulationConfig double sdPercent{}; /// Whether this input represents a physical electrode. Default is false bool representsPhysicalElectrode = false; + /// Signal skewness as a fraction in [0, 1] representing a value between the minimum and + /// maximum skewness values compatible with the given signal mean and std dev. Default is + /// 0.5. + double relativeSkew{}; }; struct InputAbsoluteShotNoise: public InputBase { @@ -572,14 +574,16 @@ class SONATA_API SimulationConfig double reversal{}; /// Timestep of generated signal in ms. Default is 0.25 ms double dt{}; - /// The coefficient of variation (sd/mean) of gamma-distributed amplitudes - double ampCv{}; /// Signal mean in nA (current_clamp) or uS (conductance). double mean{}; /// signal std dev in nA (current_clamp) or uS (conductance). double sigma{}; /// Whether this input represents a physical electrode. Default is false bool representsPhysicalElectrode = false; + /// Signal skewness as a fraction in [0, 1] representing a value between the minimum and + /// maximum skewness values compatible with the given signal mean and std dev. Default is + /// 0.5. + double relativeSkew{}; }; struct InputOrnsteinUhlenbeck: public InputBase { diff --git a/python/bindings.cpp b/python/bindings.cpp index 7a2b628f..bf800e84 100644 --- a/python/bindings.cpp +++ b/python/bindings.cpp @@ -695,7 +695,9 @@ PYBIND11_MODULE(_libsonata, m) { .def_readonly("mechanisms", &SimulationConfig::Conditions::mechanisms, DOC_SIMULATIONCONFIG(Conditions, mechanisms)) - .def("modifications", &SimulationConfig::Conditions::getModifications); + .def("modifications", + &SimulationConfig::Conditions::getModifications, + DOC_SIMULATIONCONFIG(Conditions, getModifications)); py::enum_(conditions, "SpikeLocation") @@ -703,7 +705,10 @@ PYBIND11_MODULE(_libsonata, m) { .value("AIS", SimulationConfig::Conditions::SpikeLocation::AIS); py::class_ modificationBase(simConf, "ModificationBase"); - modificationBase.def_readonly("name", &SimulationConfig::ModificationBase::name) + modificationBase + .def_readonly("name", + &SimulationConfig::ModificationBase::name, + DOC_SIMULATIONCONFIG(ModificationBase, name)) .def_readonly("node_set", &SimulationConfig::ModificationBase::nodeSet, DOC_SIMULATIONCONFIG(ModificationBase, nodeSet)) @@ -937,9 +942,6 @@ PYBIND11_MODULE(_libsonata, m) { .def_readonly("dt", &SimulationConfig::InputRelativeShotNoise::dt, DOC_SIMULATIONCONFIG(InputRelativeShotNoise, dt)) - .def_readonly("amp_cv", - &SimulationConfig::InputRelativeShotNoise::ampCv, - DOC_SIMULATIONCONFIG(InputRelativeShotNoise, ampCv)) .def_readonly("sd_percent", &SimulationConfig::InputRelativeShotNoise::sdPercent, DOC_SIMULATIONCONFIG(InputRelativeShotNoise, sdPercent)) @@ -948,7 +950,10 @@ PYBIND11_MODULE(_libsonata, m) { DOC_SIMULATIONCONFIG(InputRelativeShotNoise, meanPercent)) .def_readonly("represents_physical_electrode", &SimulationConfig::InputRelativeShotNoise::representsPhysicalElectrode, - DOC_SIMULATIONCONFIG(InputRelativeShotNoise, representsPhysicalElectrode)); + DOC_SIMULATIONCONFIG(InputRelativeShotNoise, representsPhysicalElectrode)) + .def_readonly("relative_skew", + &SimulationConfig::InputRelativeShotNoise::relativeSkew, + DOC_SIMULATIONCONFIG(InputRelativeShotNoise, relativeSkew)); py::class_( simConf, "AbsoluteShotNoise") @@ -967,9 +972,6 @@ PYBIND11_MODULE(_libsonata, m) { .def_readonly("dt", &SimulationConfig::InputAbsoluteShotNoise::dt, DOC_SIMULATIONCONFIG(InputAbsoluteShotNoise, dt)) - .def_readonly("amp_cv", - &SimulationConfig::InputAbsoluteShotNoise::ampCv, - DOC_SIMULATIONCONFIG(InputAbsoluteShotNoise, ampCv)) .def_readonly("mean", &SimulationConfig::InputAbsoluteShotNoise::mean, DOC_SIMULATIONCONFIG(InputAbsoluteShotNoise, mean)) @@ -978,7 +980,11 @@ PYBIND11_MODULE(_libsonata, m) { DOC_SIMULATIONCONFIG(InputAbsoluteShotNoise, sigma)) .def_readonly("represents_physical_electrode", &SimulationConfig::InputAbsoluteShotNoise::representsPhysicalElectrode, - DOC_SIMULATIONCONFIG(InputAbsoluteShotNoise, representsPhysicalElectrode)); + DOC_SIMULATIONCONFIG(InputAbsoluteShotNoise, representsPhysicalElectrode)) + .def_readonly("relative_skew", + &SimulationConfig::InputAbsoluteShotNoise::relativeSkew, + DOC_SIMULATIONCONFIG(InputAbsoluteShotNoise, relativeSkew)); + ; py::class_( simConf, "OrnsteinUhlenbeck") diff --git a/python/generated/docstrings.h b/python/generated/docstrings.h index 02a92e21..db259a47 100644 --- a/python/generated/docstrings.h +++ b/python/generated/docstrings.h @@ -778,8 +778,6 @@ static const char *__doc_bbp_sonata_SimulationConfig_ConnectionOverride_weight = static const char *__doc_bbp_sonata_SimulationConfig_InputAbsoluteShotNoise = R"doc()doc"; -static const char *__doc_bbp_sonata_SimulationConfig_InputAbsoluteShotNoise_ampCv = R"doc(The coefficient of variation (sd/mean) of gamma-distributed amplitudes)doc"; - static const char *__doc_bbp_sonata_SimulationConfig_InputAbsoluteShotNoise_decayTime = R"doc(The decay time of the bi-exponential shots (ms))doc"; static const char *__doc_bbp_sonata_SimulationConfig_InputAbsoluteShotNoise_dt = R"doc(Timestep of generated signal in ms. Default is 0.25 ms)doc"; @@ -790,6 +788,11 @@ static const char *__doc_bbp_sonata_SimulationConfig_InputAbsoluteShotNoise_rand R"doc(Override the random seed to introduce correlations between cells, default = None)doc"; +static const char *__doc_bbp_sonata_SimulationConfig_InputAbsoluteShotNoise_relativeSkew = +R"doc(Signal skewness as a fraction in [0, 1] representing a value between +the minimum and maximum skewness values compatible with the given +signal mean and std dev. Default is 0.5.)doc"; + static const char *__doc_bbp_sonata_SimulationConfig_InputAbsoluteShotNoise_representsPhysicalElectrode = R"doc(Whether this input represents a physical electrode. Default is false)doc"; static const char *__doc_bbp_sonata_SimulationConfig_InputAbsoluteShotNoise_reversal = R"doc(Reversal potential for conductance injection in mV. Default is 0)doc"; @@ -940,8 +943,6 @@ static const char *__doc_bbp_sonata_SimulationConfig_InputRelativeOrnsteinUhlenb static const char *__doc_bbp_sonata_SimulationConfig_InputRelativeShotNoise = R"doc()doc"; -static const char *__doc_bbp_sonata_SimulationConfig_InputRelativeShotNoise_ampCv = R"doc(The coefficient of variation (sd/mean) of gamma-distributed amplitudes)doc"; - static const char *__doc_bbp_sonata_SimulationConfig_InputRelativeShotNoise_decayTime = R"doc(The decay time of the bi-exponential shots (ms))doc"; static const char *__doc_bbp_sonata_SimulationConfig_InputRelativeShotNoise_dt = R"doc(Timestep of generated signal in ms. Default is 0.25 ms)doc"; @@ -954,6 +955,11 @@ static const char *__doc_bbp_sonata_SimulationConfig_InputRelativeShotNoise_rand R"doc(Override the random seed to introduce correlations between cells, default = None)doc"; +static const char *__doc_bbp_sonata_SimulationConfig_InputRelativeShotNoise_relativeSkew = +R"doc(Signal skewness as a fraction in [0, 1] representing a value between +the minimum and maximum skewness values compatible with the given +signal mean and std dev. Default is 0.5.)doc"; + static const char *__doc_bbp_sonata_SimulationConfig_InputRelativeShotNoise_representsPhysicalElectrode = R"doc(Whether this input represents a physical electrode. Default is false)doc"; static const char *__doc_bbp_sonata_SimulationConfig_InputRelativeShotNoise_reversal = R"doc(Reversal potential for conductance injection in mV. Default is 0)doc"; diff --git a/python/tests/test_config.py b/python/tests/test_config.py index 77577334..31822814 100644 --- a/python/tests/test_config.py +++ b/python/tests/test_config.py @@ -547,6 +547,7 @@ def test_basic(self): self.assertEqual(self.config.input('ex_rel_shotnoise').random_seed, 230522) self.assertEqual(self.config.input('ex_rel_shotnoise').dt, 0.25) self.assertEqual(self.config.input('ex_rel_shotnoise').reversal, 0) + self.assertEqual(self.config.input('ex_rel_shotnoise').relative_skew, 0.5) self.assertEqual(self.config.input('ex_replay').input_type.name, 'spikes') self.assertEqual(self.config.input('ex_replay').module.name, 'synapse_replay') @@ -558,12 +559,12 @@ def test_basic(self): self.assertEqual(self.config.input('ex_extracellular_stimulation').node_set, 'Column') self.assertEqual(self.config.input('ex_abs_shotnoise').input_type.name, "conductance") - self.assertEqual(self.config.input('ex_abs_shotnoise').amp_cv, 0.63) self.assertEqual(self.config.input('ex_abs_shotnoise').mean, 50) self.assertEqual(self.config.input('ex_abs_shotnoise').sigma, 5) self.assertEqual(self.config.input('ex_abs_shotnoise').reversal, 10) self.assertEqual(self.config.input('ex_abs_shotnoise').random_seed, None) self.assertEqual(self.config.input('ex_abs_shotnoise').represents_physical_electrode, True) + self.assertEqual(self.config.input('ex_abs_shotnoise').relative_skew, 0.1) self.assertEqual(self.config.input('ex_OU').module.name, "ornstein_uhlenbeck") self.assertEqual(self.config.input('ex_OU').input_type.name, "conductance") diff --git a/src/config.cpp b/src/config.cpp index 9e347615..1bed987d 100644 --- a/src/config.cpp +++ b/src/config.cpp @@ -506,9 +506,9 @@ SimulationConfig::Input parseInputModule(const nlohmann::json& valueIt, "represents_physical_electrode", ret.representsPhysicalElectrode, {false}); - parseMandatory(valueIt, "amp_cv", debugStr, ret.ampCv); parseMandatory(valueIt, "mean_percent", debugStr, ret.meanPercent); parseMandatory(valueIt, "sd_percent", debugStr, ret.sdPercent); + parseOptional(valueIt, "relative_skew", ret.relativeSkew, {0.5}); return ret; } case Module::absolute_shot_noise: { @@ -524,9 +524,9 @@ SimulationConfig::Input parseInputModule(const nlohmann::json& valueIt, "represents_physical_electrode", ret.representsPhysicalElectrode, {false}); - parseMandatory(valueIt, "amp_cv", debugStr, ret.ampCv); parseMandatory(valueIt, "mean", debugStr, ret.mean); parseMandatory(valueIt, "sigma", debugStr, ret.sigma); + parseOptional(valueIt, "relative_skew", ret.relativeSkew, {0.5}); return ret; } case Module::hyperpolarizing: { diff --git a/tests/data/config/simulation_config.json b/tests/data/config/simulation_config.json index f83d745b..ecd2bf93 100644 --- a/tests/data/config/simulation_config.json +++ b/tests/data/config/simulation_config.json @@ -153,7 +153,6 @@ "duration": 1000, "decay_time": 4, "rise_time": 0.4, - "amp_cv": 0.63, "mean_percent": 70, "sd_percent": 40, "node_set": "L5E", @@ -167,7 +166,7 @@ "decay_time": 4, "reversal": 10, "rise_time": 0.4, - "amp_cv": 0.63, + "relative_skew": 0.1, "mean": 50, "sigma": 5, "represents_physical_electrode": true, diff --git a/tests/test_config.cpp b/tests/test_config.cpp index 7c1848d5..2ef9e3b0 100644 --- a/tests/test_config.cpp +++ b/tests/test_config.cpp @@ -482,13 +482,13 @@ TEST_CASE("SimulationConfig") { CHECK(input.delay == 0); CHECK(input.duration == 1000); CHECK(input.nodeSet == "L5E"); - CHECK(input.ampCv == 0.63); CHECK(input.meanPercent == 70); CHECK(input.sdPercent == 40); CHECK(input.randomSeed == 230522); CHECK(input.riseTime == 0.4); CHECK(input.decayTime == 4); CHECK(input.reversal == 0); + CHECK(input.relativeSkew == 0.5); } { const auto input = nonstd::get(config.getInput("ex_hyperpolarizing")); @@ -522,12 +522,12 @@ TEST_CASE("SimulationConfig") { config.getInput("ex_abs_shotnoise")); CHECK(input.inputType == InputType::conductance); CHECK(input.module == Module::absolute_shot_noise); - CHECK(input.ampCv == 0.63); CHECK(input.mean == 50); CHECK(input.sigma == 5); CHECK(input.reversal == 10); CHECK(input.randomSeed == nonstd::nullopt); CHECK(input.representsPhysicalElectrode == true); + CHECK(input.relativeSkew == 0.1); } { const auto input = nonstd::get(