From e0cdaf707feae298d432a11742d2620721a1ae10 Mon Sep 17 00:00:00 2001 From: WeinaJi Date: Tue, 12 Jul 2022 09:02:53 +0200 Subject: [PATCH] Parse synapse mod variables in conditions/mechanisms section (#217) --- include/bbp/sonata/config.h | 7 ++++ python/bindings.cpp | 5 ++- python/generated/docstrings.h | 49 ++++++++++++++++++++---- python/tests/test.py | 4 ++ src/config.cpp | 36 ++++++++++++++++- tests/data/config/simulation_config.json | 14 ++++++- tests/test_config.cpp | 8 ++++ 7 files changed, 111 insertions(+), 12 deletions(-) diff --git a/include/bbp/sonata/config.h b/include/bbp/sonata/config.h index b938565a..177221ec 100644 --- a/include/bbp/sonata/config.h +++ b/include/bbp/sonata/config.h @@ -29,6 +29,8 @@ namespace bbp { namespace sonata { +using variantValueType = nonstd::variant; + /** * Stores population-specific network information. */ @@ -241,6 +243,11 @@ class SONATA_API SimulationConfig /// Enable legacy behavior to randomize the GABA_A rise time in the helper functions. /// Default is false bool randomizeGabaRiseTime; + /// Properties to assign values to variables in synapse MOD files. + /// The format is a dictionary with keys being the SUFFIX names and values being + /// dictionaries of variables' names and values. + std::unordered_map> + mechanisms; }; /** * List of report parameters collected during the simulation diff --git a/python/bindings.cpp b/python/bindings.cpp index 999f3e97..dc784ce4 100644 --- a/python/bindings.cpp +++ b/python/bindings.cpp @@ -597,7 +597,10 @@ PYBIND11_MODULE(_libsonata, m) { DOC_SIMULATIONCONFIG(Conditions, minisSingleVesicle)) .def_readonly("randomize_gaba_rise_time", &SimulationConfig::Conditions::randomizeGabaRiseTime, - DOC_SIMULATIONCONFIG(Conditions, randomizeGabaRiseTime)); + DOC_SIMULATIONCONFIG(Conditions, randomizeGabaRiseTime)) + .def_readonly("mechanisms", + &SimulationConfig::Conditions::mechanisms, + DOC_SIMULATIONCONFIG(Conditions, mechanisms)); py::class_ report(m, "Report", "Parameters of a report"); report diff --git a/python/generated/docstrings.h b/python/generated/docstrings.h index 5b0e9844..5549d5fd 100644 --- a/python/generated/docstrings.h +++ b/python/generated/docstrings.h @@ -545,6 +545,11 @@ R"doc(Extracellular calcium concentration, being applied to the synapse uHill parameter in order to scale the U parameter of synapses. Default is None.)doc"; +static const char *__doc_bbp_sonata_SimulationConfig_Conditions_mechanisms = +R"doc(Properties to assign values to variables in synapse MOD files. The +format is a dictionary with keys being the SUFFIX names and values +being dictionaries of variables' names and values.)doc"; + static const char *__doc_bbp_sonata_SimulationConfig_Conditions_minisSingleVesicle = R"doc(Limit spontaneous release to single vesicle when true. Default is false)doc"; @@ -875,19 +880,43 @@ static const char *__doc_bbp_sonata_SimulationConfig_Report_variableName = R"doc static const char *__doc_bbp_sonata_SimulationConfig_Run = R"doc(Parameters defining global simulation settings for spike reports)doc"; +static const char *__doc_bbp_sonata_SimulationConfig_Run_IntegrationMethod = R"doc()doc"; + +static const char *__doc_bbp_sonata_SimulationConfig_Run_IntegrationMethod_euler = R"doc()doc"; + +static const char *__doc_bbp_sonata_SimulationConfig_Run_IntegrationMethod_invalid = R"doc()doc"; + +static const char *__doc_bbp_sonata_SimulationConfig_Run_IntegrationMethod_nicholson = R"doc()doc"; + +static const char *__doc_bbp_sonata_SimulationConfig_Run_IntegrationMethod_nicholson_ion = R"doc()doc"; + +static const char *__doc_bbp_sonata_SimulationConfig_Run_SpikeLocation = R"doc()doc"; + +static const char *__doc_bbp_sonata_SimulationConfig_Run_SpikeLocation_AIS = R"doc()doc"; + +static const char *__doc_bbp_sonata_SimulationConfig_Run_SpikeLocation_invalid = R"doc()doc"; + +static const char *__doc_bbp_sonata_SimulationConfig_Run_SpikeLocation_soma = R"doc()doc"; + static const char *__doc_bbp_sonata_SimulationConfig_Run_dt = R"doc(Integration step duration in milliseconds)doc"; -static const char *__doc_bbp_sonata_SimulationConfig_Run_randomSeed = R"doc(Random seed)doc"; +static const char *__doc_bbp_sonata_SimulationConfig_Run_forwardSkip = +R"doc(Run without Stimulus or Reports for given duration prior to t=0 using +a timestep computed as dt=0.1*forward_skip. Default = None)doc"; -static const char *__doc_bbp_sonata_SimulationConfig_Run_tstop = R"doc(Biological simulation end time in milliseconds)doc"; +static const char *__doc_bbp_sonata_SimulationConfig_Run_integrationMethod = +R"doc(Selects the NEURON/CoreNEURON integration method. This parameter sets +the NEURON global variable h.secondorder. Default 0 ('euler'))doc"; -static const char *__doc_bbp_sonata_SimulationConfig_Run_spikeThreshold = R"doc(The spike detection threshold. Default is -30mV)doc"; +static const char *__doc_bbp_sonata_SimulationConfig_Run_randomSeed = R"doc(Random seed)doc"; -static const char *__doc_bbp_sonata_SimulationConfig_Run_spikeLocation = R"doc(The spike detection location. Can be either ‘soma’ or 'AIS'. Default is 'soma')doc"; +static const char *__doc_bbp_sonata_SimulationConfig_Run_spikeLocation = +R"doc(The spike detection location. Can be either ‘soma’ or 'AIS'. Default +is 'soma')doc"; -static const char *__doc_bbp_sonata_SimulationConfig_Run_integrationMethod = R"doc(Selects the NEURON/CoreNEURON integration method. This parameter sets the NEURON global variable h.secondorder. Default 0 ('euler'))doc"; +static const char *__doc_bbp_sonata_SimulationConfig_Run_spikeThreshold = R"doc(The spike detection threshold. Default is -30mV)doc"; -static const char *__doc_bbp_sonata_SimulationConfig_Run_forwardSkip = R"doc(Run without Stimulus or Reports for given duration prior to t=0 using a timestep computed as dt=0.1*forward_skip. Default = None)doc"; +static const char *__doc_bbp_sonata_SimulationConfig_Run_tstop = R"doc(Biological simulation end time in milliseconds)doc"; static const char *__doc_bbp_sonata_SimulationConfig_SimulationConfig = R"doc(Parses a SONATA JSON simulation configuration file. @@ -910,6 +939,8 @@ static const char *__doc_bbp_sonata_SimulationConfig_conditions = R"doc()doc"; static const char *__doc_bbp_sonata_SimulationConfig_connections = R"doc()doc"; +static const char *__doc_bbp_sonata_SimulationConfig_expandedJSON = R"doc()doc"; + static const char *__doc_bbp_sonata_SimulationConfig_fromFile = R"doc(Loads a SONATA JSON simulation config file from disk and returns a CircuitConfig object which parses it. @@ -930,6 +961,10 @@ R"doc(Returns the given connection parameters SonataError if the given connection name does not correspond with any existing connection.)doc"; +static const char *__doc_bbp_sonata_SimulationConfig_getExpandedJSON = +R"doc(Returns the configuration file JSON whose variables have been expanded +by the manifest entries.)doc"; + static const char *__doc_bbp_sonata_SimulationConfig_getInput = R"doc(Returns the given input parameters. @@ -967,8 +1002,6 @@ R"doc(Returns the name of simulator, default = NEURON static const char *__doc_bbp_sonata_SimulationConfig_inputs = R"doc()doc"; -static const char *__doc_bbp_sonata_SimulationConfig_jsonContent = R"doc()doc"; - static const char *__doc_bbp_sonata_SimulationConfig_listConnectionOverrideNames = R"doc(Returns the names of the connection_overrides)doc"; static const char *__doc_bbp_sonata_SimulationConfig_listInputNames = R"doc(Returns the names of the reports)doc"; diff --git a/python/tests/test.py b/python/tests/test.py index 729b6cbe..d4318e0c 100644 --- a/python/tests/test.py +++ b/python/tests/test.py @@ -716,6 +716,10 @@ def test_basic(self): self.assertEqual(self.config.conditions.extracellular_calcium, None) self.assertEqual(self.config.conditions.minis_single_vesicle, False) self.assertEqual(self.config.conditions.randomize_gaba_rise_time, False) + self.assertEqual(self.config.conditions.mechanisms, {'ProbAMPANMDA_EMS': {'property2': -1, + 'property1': False}, + 'GluSynapse': {'property4': 'test', + 'property3': 0.025}}) self.assertEqual(self.config.list_report_names, { "axonal_comp_centers", "cell_imembrane", "compartment", "soma" }) diff --git a/src/config.cpp b/src/config.cpp index ffdd5d9b..114d5e27 100644 --- a/src/config.cpp +++ b/src/config.cpp @@ -421,6 +421,40 @@ SimulationConfig::Input parseInputModule(const nlohmann::json& valueIt, } } +void parseConditionsMechanisms( + const nlohmann::json& it, + std::unordered_map>& buf) { + const auto mechIt = it.find("mechanisms"); + if (mechIt == it.end()) { + return; + } + for (auto& scopeIt : mechIt->items()) { + std::unordered_map map_vars; + for (auto& varIt : scopeIt.value().items()) { + variantValueType res_val; + switch (varIt.value().type()) { + case nlohmann::json::value_t::boolean: + res_val = varIt.value().get(); + break; + case nlohmann::json::value_t::string: + res_val = varIt.value().get(); + break; + case nlohmann::json::value_t::number_float: + res_val = varIt.value().get(); + break; + case nlohmann::json::value_t::number_integer: + case nlohmann::json::value_t::number_unsigned: + res_val = varIt.value().get(); + break; + default: + throw SonataError("Value type not supported"); + } + map_vars.insert({varIt.key(), res_val}); + } + buf.insert({scopeIt.key(), map_vars}); + } +} + } // namespace class CircuitConfig::Parser @@ -845,7 +879,7 @@ class SimulationConfig::Parser "randomize_gaba_rise_time", result.randomizeGabaRiseTime, {false}); - + parseConditionsMechanisms(*conditionsIt, result.mechanisms); return result; } diff --git a/tests/data/config/simulation_config.json b/tests/data/config/simulation_config.json index 3760a8a0..4d03afb8 100644 --- a/tests/data/config/simulation_config.json +++ b/tests/data/config/simulation_config.json @@ -18,8 +18,18 @@ "spikes_sort_order": "by_id" }, "conditions": { - "celsius": 35.0, - "synapses_init_deleted": false + "celsius": 35.0, + "synapses_init_depleted": false, + "mechanisms": { + "ProbAMPANMDA_EMS": { + "property1": false, + "property2": -1 + }, + "GluSynapse" : { + "property3": 0.025, + "property4": "test" + } + } }, "inputs": { "ex_linear": { diff --git a/tests/test_config.cpp b/tests/test_config.cpp index c96ce886..d773d320 100644 --- a/tests/test_config.cpp +++ b/tests/test_config.cpp @@ -327,6 +327,14 @@ TEST_CASE("SimulationConfig") { CHECK(config.getConditions().extracellularCalcium == nonstd::nullopt); CHECK(config.getConditions().minisSingleVesicle == false); CHECK(config.getConditions().randomizeGabaRiseTime == false); + CHECK(config.getConditions().mechanisms.size() == 2); + auto itr = config.getConditions().mechanisms.find("ProbAMPANMDA_EMS"); + CHECK(itr != config.getConditions().mechanisms.end()); + CHECK(nonstd::get(itr->second.find("property1")->second) == false); + CHECK(nonstd::get(itr->second.find("property2")->second) == -1); + itr = config.getConditions().mechanisms.find("GluSynapse"); + CHECK(nonstd::get(itr->second.find("property3")->second) == 0.025); + CHECK(nonstd::get(itr->second.find("property4")->second) == "test"); CHECK_THROWS_AS(config.getReport("DoesNotExist"), SonataError);