Skip to content

Commit

Permalink
New parameters in SimulationConfig (#192)
Browse files Browse the repository at this point in the history
- Parse floating point with type "double" to align with specification report output
- Parse variables in "manifest" section and apply them to the configuration file
- Parse "network" parameter for the path of circuit_config file
  • Loading branch information
WeinaJi authored Apr 8, 2022
1 parent 663a21b commit 3ca8afc
Show file tree
Hide file tree
Showing 6 changed files with 63 additions and 19 deletions.
14 changes: 9 additions & 5 deletions include/bbp/sonata/config.h
Original file line number Diff line number Diff line change
Expand Up @@ -186,9 +186,9 @@ class SONATA_API SimulationConfig
*/
struct Run {
/// Biological simulation end time in milliseconds
float tstop{};
double tstop{};
/// Integration step duration in milliseconds
float dt{};
double dt{};
};
/**
* Parameters to override simulator output for spike reports
Expand All @@ -208,11 +208,11 @@ class SONATA_API SimulationConfig
/// Report type. Possible values: "compartment", "summation", "synapse"
std::string type;
/// Interval between reporting steps in milliseconds
float dt{};
double dt{};
/// Time to step reporting in milliseconds
float startTime{};
double startTime{};
/// Time to stop reporting in milliseconds
float endTime{};
double endTime{};
/// Report filename. Default is "<report name>_SONATA.h5"
std::string fileName;
};
Expand Down Expand Up @@ -265,6 +265,8 @@ class SONATA_API SimulationConfig
*/
const Report& getReport(const std::string& name) const;

const std::string& getNetwork() const noexcept;

private:
// JSON string
const std::string _jsonContent;
Expand All @@ -277,6 +279,8 @@ class SONATA_API SimulationConfig
Output _output;
// List of reports
std::unordered_map<std::string, Report> _reports;
// Path of circuit config file for the simulation
std::string _network;

class Parser;
friend class Parser;
Expand Down
1 change: 1 addition & 0 deletions python/bindings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -561,6 +561,7 @@ PYBIND11_MODULE(_libsonata, m) {
.def_property_readonly("json", &SimulationConfig::getJSON)
.def_property_readonly("run", &SimulationConfig::getRun)
.def_property_readonly("output", &SimulationConfig::getOutput)
.def_property_readonly("network", &SimulationConfig::getNetwork)
.def("report", &SimulationConfig::getReport, "name"_a);

bindPopulationClass<EdgePopulation>(
Expand Down
7 changes: 5 additions & 2 deletions python/tests/test.py
Original file line number Diff line number Diff line change
Expand Up @@ -585,20 +585,23 @@ def test_basic(self):
self.assertEqual(self.config.base_path, os.path.abspath(os.path.join(PATH, 'config')))

self.assertEqual(self.config.run.tstop, 1000)
self.assertTrue(abs(self.config.run.dt - 0.025) < 0.01)
self.assertEqual(self.config.run.dt, 0.025)

self.assertEqual(self.config.output.output_dir,
os.path.abspath(os.path.join(PATH, 'config/output')))
self.assertEqual(self.config.output.spikes_file, 'out.h5')

self.assertEqual(self.config.report('soma').cells, 'Mosaic')
self.assertEqual(self.config.report('soma').type, 'compartment')
self.assertTrue(abs(self.config.report('compartment').dt - 0.1) < 0.01)
self.assertEqual(self.config.report('compartment').dt, 0.1)
self.assertEqual(self.config.report('axonal_comp_centers').start_time, 0)
self.assertEqual(self.config.report('axonal_comp_centers').file_name,
os.path.abspath(os.path.join(PATH, 'config/axon_centers.h5')))
self.assertEqual(self.config.report('cell_imembrane').end_time, 500)

self.assertEqual(self.config.network,
os.path.abspath(os.path.join(PATH, 'config/circuit_config.json')))

def test_json(self):
temp_config = json.loads(self.config.json)
self.assertEqual(temp_config['run']['tstop'], 1000)
Expand Down
22 changes: 18 additions & 4 deletions src/config.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ using Variables = std::map<std::string, std::string>;
Variables readVariables(const nlohmann::json& json) {
Variables variables;

if (json.find("networks") == json.end() || json.find("manifest") == json.end()) {
if (json.find("manifest") == json.end()) {
return variables;
}

Expand Down Expand Up @@ -482,8 +482,12 @@ class SimulationConfig::Parser
{
public:
Parser(const std::string& content, const std::string& basePath)
: _basePath(fs::absolute(fs::path(basePath)).lexically_normal())
, _json(nlohmann::json::parse(content)) {}
: _basePath(fs::absolute(fs::path(basePath)).lexically_normal()) {
// Parse manifest section and expand JSON string
const auto rawJson = nlohmann::json::parse(content);
const auto vars = replaceVariables(readVariables(rawJson));
_json = expandVariables(rawJson, vars);
}

template <typename Iterator, typename Type, typename SectionName>
void parseMandatory(const Iterator& it,
Expand Down Expand Up @@ -560,9 +564,14 @@ class SimulationConfig::Parser
return result;
}

const std::string parseNetwork() const {
auto val = _json.find("network") != _json.end() ? _json["network"] : "circuit_config.json";
return toAbsolute(_basePath, val);
}

private:
const fs::path _basePath;
const nlohmann::json _json;
nlohmann::json _json;
};

SimulationConfig::SimulationConfig(const std::string& content, const std::string& basePath)
Expand All @@ -572,6 +581,7 @@ SimulationConfig::SimulationConfig(const std::string& content, const std::string
_run = parser.parseRun();
_output = parser.parseOutput();
_reports = parser.parseReports();
_network = parser.parseNetwork();
}

SimulationConfig SimulationConfig::fromFile(const std::string& path) {
Expand All @@ -594,6 +604,10 @@ const SimulationConfig::Output& SimulationConfig::getOutput() const noexcept {
return _output;
}

const std::string& SimulationConfig::getNetwork() const noexcept {
return _network;
}

const SimulationConfig::Report& SimulationConfig::getReport(const std::string& name) const {
const auto it = _reports.find(name);
if (it == _reports.end())
Expand Down
7 changes: 5 additions & 2 deletions tests/data/config/simulation_config.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
{
"run": {
"manifest": {
"$OUTPUT_DIR": "."
},
"run": {
"tstop": 1000,
"dt": 0.025,
"random_seed": 201506,
Expand All @@ -8,7 +11,7 @@
"forward_skip": 500
},
"output": {
"output_dir": "output",
"output_dir": "$OUTPUT_DIR/output",
"spikes_file": "out.h5"
},
"reports": {
Expand Down
31 changes: 25 additions & 6 deletions tests/test_config.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -296,8 +296,8 @@ TEST_CASE("SimulationConfig") {
const auto config = SimulationConfig::fromFile("./data/config/simulation_config.json");
CHECK_NOTHROW(config.getRun());
using Catch::Matchers::WithinULP;
REQUIRE_THAT(config.getRun().tstop, WithinULP(1000.f, 1));
REQUIRE_THAT(config.getRun().dt, WithinULP(0.025f, 1));
CHECK(config.getRun().tstop == 1000);
CHECK(config.getRun().dt == 0.025);

namespace fs = ghc::filesystem;
const auto basePath = fs::absolute(
Expand All @@ -312,17 +312,36 @@ TEST_CASE("SimulationConfig") {

CHECK(config.getReport("soma").cells == "Mosaic");
CHECK(config.getReport("soma").type == "compartment");
CHECK(config.getReport("compartment").dt == 0.1f);
CHECK(config.getReport("axonal_comp_centers").startTime == 0.f);
CHECK(config.getReport("compartment").dt == 0.1);
CHECK(config.getReport("axonal_comp_centers").startTime == 0.);
const auto axonalFilePath = fs::absolute(basePath / fs::path("axon_centers.h5"));
CHECK(config.getReport("axonal_comp_centers").fileName ==
axonalFilePath.lexically_normal());
CHECK(config.getReport("cell_imembrane").endTime == 500.f);
CHECK(config.getReport("cell_imembrane").endTime == 500.);

CHECK_NOTHROW(nlohmann::json::parse(config.getJSON()));
CHECK(config.getBasePath() == basePath.lexically_normal());
}

const auto network = fs::absolute(basePath / fs::path("circuit_config.json"));
CHECK(config.getNetwork() == network.lexically_normal());
}
SECTION("manifest_network") {
auto contents = R"({
"manifest": {
"$CIRCUIT_DIR": "./circuit"
},
"network": "$CIRCUIT_DIR/circuit_config.json",
"run": {
"dt": 0.05,
"tstop": 1000
}
})";
namespace fs = ghc::filesystem;
const auto basePath = fs::absolute(fs::path("./").parent_path());
const auto config = SimulationConfig(contents, basePath);
const auto network = fs::absolute(basePath / "circuit" / fs::path("circuit_config.json"));
CHECK(config.getNetwork() == network.lexically_normal());
}
SECTION("Exception") {
{ // No run section
auto contents = R"({})";
Expand Down

0 comments on commit 3ca8afc

Please sign in to comment.