Skip to content
This repository was archived by the owner on Feb 26, 2025. It is now read-only.

SimulationConfig: modifications as a list to preserve the order #359

Merged
merged 4 commits into from
Jul 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 6 additions & 10 deletions include/bbp/sonata/config.h
Original file line number Diff line number Diff line change
Expand Up @@ -324,6 +324,8 @@ class SONATA_API SimulationConfig
std::string nodeSet;
/// Name of the manipulation. Supported values are “TTX” and “ConfigureAllSections”.
ModificationType type;
/// Name of the modification setting.
std::string name;
};

struct ModificationTTX: public ModificationBase {};
Expand All @@ -337,8 +339,6 @@ class SONATA_API SimulationConfig

using Modification = nonstd::variant<ModificationTTX, ModificationConfigureAllSections>;

using ModificationMap = std::unordered_map<std::string, Modification>;

/**
* Parameters defining global experimental conditions.
*/
Expand Down Expand Up @@ -366,14 +366,10 @@ class SONATA_API SimulationConfig
/// dictionaries of variables' names and values.
std::unordered_map<std::string, std::unordered_map<std::string, variantValueType>>
mechanisms;
/// Collection of dictionaries with each member decribing a modification that mimics
/// experimental manipulations to the circuit.
ModificationMap modifications;
/// Returns the names of the modifications
std::set<std::string> listModificationNames() const;
/// Returns the given modification parameters
/// \throws SonataError if the given modification name does not exist
const Modification& getModification(const std::string& name) const;
/// List of modifications that mimics experimental manipulations to the circuit.
std::vector<Modification> modifications;
/// Method to return the full list of modifications in the Conditions section.
const std::vector<Modification>& getModifications() const noexcept;
};
/**
* List of report parameters collected during the simulation
Expand Down
10 changes: 2 additions & 8 deletions python/bindings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -695,21 +695,15 @@ PYBIND11_MODULE(_libsonata, m) {
.def_readonly("mechanisms",
&SimulationConfig::Conditions::mechanisms,
DOC_SIMULATIONCONFIG(Conditions, mechanisms))
.def_property_readonly("list_modification_names",
&SimulationConfig::Conditions::listModificationNames,
DOC_SIMULATIONCONFIG(Conditions, listModificationNames))
.def("modification",
&SimulationConfig::Conditions::getModification,
"name"_a,
DOC_SIMULATIONCONFIG(Conditions, getModification));
.def("modifications", &SimulationConfig::Conditions::getModifications);


py::enum_<SimulationConfig::Conditions::SpikeLocation>(conditions, "SpikeLocation")
.value("soma", SimulationConfig::Conditions::SpikeLocation::soma)
.value("AIS", SimulationConfig::Conditions::SpikeLocation::AIS);

py::class_<SimulationConfig::ModificationBase> modificationBase(simConf, "ModificationBase");
modificationBase
modificationBase.def_readonly("name", &SimulationConfig::ModificationBase::name)
.def_readonly("node_set",
&SimulationConfig::ModificationBase::nodeSet,
DOC_SIMULATIONCONFIG(ModificationBase, nodeSet))
Expand Down
16 changes: 7 additions & 9 deletions python/generated/docstrings.h
Original file line number Diff line number Diff line change
Expand Up @@ -713,22 +713,18 @@ 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_getModification =
R"doc(Returns the given modification parameters

Throws:
SonataError if the given modification name does not exist)doc";

static const char *__doc_bbp_sonata_SimulationConfig_Conditions_listModificationNames = R"doc(Returns the names of the modifications)doc";
static const char *__doc_bbp_sonata_SimulationConfig_Conditions_getModifications =
R"doc(Method to return the full list of modifications in the Conditions
section.)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_modifications =
R"doc(Collection of dictionaries with each member decribing a modification
that mimics experimental manipulations to the circuit.)doc";
R"doc(List of modifications that mimics experimental manipulations to the
circuit.)doc";

static const char *__doc_bbp_sonata_SimulationConfig_Conditions_randomizeGabaRiseTime =
R"doc(Enable legacy behavior to randomize the GABA_A rise time in the helper
Expand Down Expand Up @@ -1022,6 +1018,8 @@ static const char *__doc_bbp_sonata_SimulationConfig_ModificationBase_Modificati

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

static const char *__doc_bbp_sonata_SimulationConfig_ModificationBase_name = R"doc(Name of the modification setting.)doc";

static const char *__doc_bbp_sonata_SimulationConfig_ModificationBase_nodeSet = R"doc(Node set which receives the manipulation)doc";

static const char *__doc_bbp_sonata_SimulationConfig_ModificationBase_type =
Expand Down
14 changes: 6 additions & 8 deletions python/tests/test_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -434,14 +434,12 @@ def test_basic(self):
'property1': False},
'GluSynapse': {'property4': 'test',
'property3': 0.025}})
self.assertEqual(self.config.conditions.list_modification_names, {"applyTTX", "no_SK_E2"})
self.assertEqual(self.config.conditions.modification("applyTTX").type.name, "TTX")
self.assertEqual(self.config.conditions.modification("applyTTX").node_set, "single")
self.assertEqual(self.config.conditions.modification("no_SK_E2").type.name,
"ConfigureAllSections")
self.assertEqual(self.config.conditions.modification("no_SK_E2").node_set, "single")
self.assertEqual(self.config.conditions.modification("no_SK_E2").section_configure,
"%s.gSK_E2bar_SK_E2 = 0")
modifications = {o.name: o for o in self.config.conditions.modifications()}
self.assertEqual(modifications["applyTTX"].type.name, "TTX")
self.assertEqual(modifications["applyTTX"].node_set, "single")
self.assertEqual(modifications["no_SK_E2"].type.name, "ConfigureAllSections")
self.assertEqual(modifications["no_SK_E2"].node_set, "single")
self.assertEqual(modifications["no_SK_E2"].section_configure, "%s.gSK_E2bar_SK_E2 = 0")

self.assertEqual(self.config.list_report_names,
{ "axonal_comp_centers", "cell_imembrane", "compartment", "soma", "lfp" })
Expand Down
35 changes: 16 additions & 19 deletions src/config.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -612,11 +612,16 @@ void parseConditionsMechanisms(
}

void parseConditionsModifications(const nlohmann::json& it,
SimulationConfig::ModificationMap& buf) {
std::vector<SimulationConfig::Modification>& buf) {
const auto sectionIt = it.find("modifications");
if (sectionIt == it.end()) {
if (sectionIt == it.end() || sectionIt->is_null()) {
return;
}
if (!sectionIt->is_array()) {
throw SonataError("`modifications` must be an array");
}
buf.reserve(sectionIt->size());

for (auto& mIt : sectionIt->items()) {
const auto valueIt = mIt.value();
const auto debugStr = fmt::format("modification {}", mIt.key());
Expand All @@ -628,16 +633,18 @@ void parseConditionsModifications(const nlohmann::json& it,
case SimulationConfig::ModificationBase::ModificationType::TTX: {
SimulationConfig::ModificationTTX result;
result.type = type;
parseMandatory(valueIt, "name", debugStr, result.name);
parseMandatory(valueIt, "node_set", debugStr, result.nodeSet);
buf[mIt.key()] = result;
buf.push_back(std::move(result));
break;
}
case SimulationConfig::ModificationBase::ModificationType::ConfigureAllSections: {
SimulationConfig::ModificationConfigureAllSections result;
result.type = type;
parseMandatory(valueIt, "name", debugStr, result.name);
parseMandatory(valueIt, "node_set", debugStr, result.nodeSet);
parseMandatory(valueIt, "section_configure", debugStr, result.sectionConfigure);
buf[mIt.key()] = result;
buf.push_back(std::move(result));
break;
}
default:
Expand Down Expand Up @@ -1383,6 +1390,11 @@ const SimulationConfig::Conditions& SimulationConfig::getConditions() const noex
return _conditions;
}

const std::vector<SimulationConfig::Modification>& SimulationConfig::Conditions::getModifications()
const noexcept {
return modifications;
}

const std::string& SimulationConfig::getNetwork() const noexcept {
return _network;
}
Expand Down Expand Up @@ -1445,20 +1457,5 @@ const std::string& SimulationConfig::getExpandedJSON() const {
return _expandedJSON;
}

std::set<std::string> SimulationConfig::Conditions::listModificationNames() const {
return getMapKeys(modifications);
}

const SimulationConfig::Modification& SimulationConfig::Conditions::getModification(
const std::string& name) const {
const auto it = modifications.find(name);
if (it == modifications.end()) {
throw SonataError(
fmt::format("The modification '{}' is not present in the simulation config file",
name));
}
return it->second;
}

} // namespace sonata
} // namespace bbp
14 changes: 8 additions & 6 deletions tests/data/config/simulation_config.json
Original file line number Diff line number Diff line change
Expand Up @@ -48,17 +48,19 @@
"property4": "test"
}
},
"modifications": {
"applyTTX": {
"modifications": [
{
"node_set": "single",
"type": "TTX"
"type": "TTX",
"name": "applyTTX"
},
"no_SK_E2": {
{
"node_set": "single",
"type": "ConfigureAllSections",
"section_configure": "%s.gSK_E2bar_SK_E2 = 0"
"section_configure": "%s.gSK_E2bar_SK_E2 = 0",
"name": "no_SK_E2"
}
}
]
},
"inputs": {
"ex_linear": {
Expand Down
13 changes: 6 additions & 7 deletions tests/test_config.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -345,15 +345,14 @@ TEST_CASE("SimulationConfig") {
itr = config.getConditions().mechanisms.find("GluSynapse");
CHECK(nonstd::get<double>(itr->second.find("property3")->second) == 0.025);
CHECK(nonstd::get<std::string>(itr->second.find("property4")->second) == "test");
CHECK(config.getConditions().listModificationNames() ==
std::set<std::string>{"applyTTX", "no_SK_E2"});
const auto TTX = nonstd::get<SimulationConfig::ModificationTTX>(
config.getConditions().getModification("applyTTX"));
const auto configAllSects = nonstd::get<SimulationConfig::ModificationConfigureAllSections>(
config.getConditions().getModification("no_SK_E2"));
CHECK_THROWS_AS(config.getConditions().getModification("DoesNotExist"), SonataError);
const auto modifications = config.getConditions().getModifications();
CHECK(modifications.size() == 2);
const auto TTX = nonstd::get<SimulationConfig::ModificationTTX>(modifications[0]);
CHECK(TTX.name == "applyTTX");
CHECK(TTX.type == SimulationConfig::ModificationBase::ModificationType::TTX);
CHECK(TTX.nodeSet == "single");
const auto configAllSects = nonstd::get<SimulationConfig::ModificationConfigureAllSections>(modifications[1]);
CHECK(configAllSects.name == "no_SK_E2");
CHECK(configAllSects.type ==
SimulationConfig::ModificationBase::ModificationType::ConfigureAllSections);
CHECK(configAllSects.sectionConfigure == "%s.gSK_E2bar_SK_E2 = 0");
Expand Down
Loading