Skip to content

Commit

Permalink
Merge branch 'master' into 1uc/fix-cmake-install
Browse files Browse the repository at this point in the history
  • Loading branch information
mgeplf committed Jan 3, 2024
2 parents 672a4b2 + c4e6d48 commit 3afe928
Show file tree
Hide file tree
Showing 4 changed files with 200 additions and 42 deletions.
45 changes: 30 additions & 15 deletions include/bbp/sonata/config.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@

#pragma once

#include <memory> // std::unique_ptr
#include <set>
#include <string>
#include <unordered_map>
Expand Down Expand Up @@ -266,27 +265,34 @@ class SONATA_API SimulationConfig
struct Run {
enum class IntegrationMethod { invalid = -1, euler, nicholson, nicholson_ion };

static constexpr int DEFAULT_spikeThreshold = -30;
static constexpr IntegrationMethod DEFAULT_IntegrationMethod = IntegrationMethod::euler;
static constexpr int DEFAULT_stimulusSeed = 0;
static constexpr int DEFAULT_ionchannelSeed = 0;
static constexpr int DEFAULT_minisSeed = 0;
static constexpr int DEFAULT_synapseSeed = 0;

/// Biological simulation end time in milliseconds
double tstop{};
/// Integration step duration in milliseconds
double dt{};
/// Random seed
int randomSeed{};
/// The spike detection threshold. Default is -30mV
int spikeThreshold;
int spikeThreshold = DEFAULT_spikeThreshold;
/// Selects the NEURON/CoreNEURON integration method. This parameter sets the NEURON
/// global variable h.secondorder. Default 0 ('euler')
IntegrationMethod integrationMethod;
IntegrationMethod integrationMethod = DEFAULT_IntegrationMethod;
/// A non-negative integer used for seeding noise stimuli and any other future stochastic
/// stimuli, default is 0.
int stimulusSeed;
int stimulusSeed = DEFAULT_stimulusSeed;
/// A non-negative integer used for seeding stochastic ion channels, default is 0.
int ionchannelSeed;
int ionchannelSeed = DEFAULT_ionchannelSeed;
/// A non-negative integer used for seeding the Poisson processes that drives the minis,
/// default is 0.
int minisSeed;
int minisSeed = DEFAULT_minisSeed;
/// A non-negative integer used for seeding stochastic synapses, default is 0.
int synapseSeed;
int synapseSeed = DEFAULT_synapseSeed;
/// Filename that contains the weights for the LFP calculation.
std::string electrodesFile;
};
Expand All @@ -296,14 +302,19 @@ class SONATA_API SimulationConfig
struct Output {
enum class SpikesSortOrder { invalid = -1, none, by_id, by_time };

static constexpr char DEFAULT_outputDir[] = "output";
static constexpr char DEFAULT_logFile[] = "";
static constexpr char DEFAULT_spikesFile[] = "out.h5";
static constexpr SpikesSortOrder DEFAULT_sortOrder = SpikesSortOrder::by_time;

/// Spike report file output directory. Default is "output"
std::string outputDir;
std::string outputDir = DEFAULT_outputDir;
/// Filename where console output is written. Default is STDOUT.
std::string logFile;
std::string logFile = DEFAULT_logFile;
/// Spike report file name. Default is "out.h5"
std::string spikesFile;
std::string spikesFile = DEFAULT_spikesFile;
/// The sorting order of the spike report. Default is "by_time"
SpikesSortOrder sortOrder;
SpikesSortOrder sortOrder = DEFAULT_sortOrder;
};

struct ModificationBase {
Expand Down Expand Up @@ -333,19 +344,23 @@ class SONATA_API SimulationConfig
*/
struct Conditions {
enum class SpikeLocation { invalid = -1, soma, AIS };
static constexpr double DEFAULT_celsius = 34.0;
static constexpr double DEFAULT_vInit = -80.0;
static constexpr SpikeLocation DEFAULT_spikeLocation = SpikeLocation::soma;
static constexpr bool DEFAULT_randomizeGabaRiseTime = false;

/// Temperature of experiment. Default is 34.0
double celsius;
double celsius = DEFAULT_celsius;
/// Initial membrane voltage in mV. Default is -80
double vInit;
double vInit = DEFAULT_vInit;
/// The spike detection location. Can be either ‘soma’ or 'AIS'. Default is 'soma'
SpikeLocation spikeLocation;
SpikeLocation spikeLocation = DEFAULT_spikeLocation;
/// Extracellular calcium concentration, being applied to the synapse uHill parameter in
/// order to scale the U parameter of synapses. Default is None.
nonstd::optional<double> extracellularCalcium{nonstd::nullopt};
/// Enable legacy behavior to randomize the GABA_A rise time in the helper functions.
/// Default is false
bool randomizeGabaRiseTime;
bool randomizeGabaRiseTime = DEFAULT_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.
Expand Down
125 changes: 115 additions & 10 deletions python/generated/docstrings.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,8 @@ static const char *__doc_bbp_sonata_CircuitConfig_Components_vasculatureMesh = R
static const char *__doc_bbp_sonata_CircuitConfig_ConfigStatus = R"doc()doc";

static const char *__doc_bbp_sonata_CircuitConfig_ConfigStatus_complete =
R"doc(all mandatory properties exist, and the the config should return
correct values in all possible cases)doc";
R"doc(all mandatory properties exist, and the config should return correct
values in all possible cases)doc";

static const char *__doc_bbp_sonata_CircuitConfig_ConfigStatus_invalid = R"doc(needed for parsing json contents that are null / not an enum value)doc";

Expand Down Expand Up @@ -95,6 +95,8 @@ given population, and the edge network it belongs to.
SonataError if the given population does not exist in any edge
network.)doc";

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

static const char *__doc_bbp_sonata_CircuitConfig_getEdgePopulationProperties =
R"doc(Return a structure containing edge population specific properties,
falling back to network properties if there are no population-specific
Expand All @@ -116,6 +118,8 @@ given population, and the node network it belongs to.
SonataError if the given population does not exist in any node
network.)doc";

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

static const char *__doc_bbp_sonata_CircuitConfig_getNodePopulationProperties =
R"doc(Return a structure containing node population specific properties,
falling back to network properties if there are no population-specific
Expand All @@ -139,7 +143,7 @@ static const char *__doc_bbp_sonata_CircuitConfig_nodePopulationProperties = R"d

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

static const char *__doc_bbp_sonata_CircuitConfig_status = R"doc(How strict we are checking the circuit config)doc";
static const char *__doc_bbp_sonata_CircuitConfig_status = R"doc()doc";

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

Expand Down Expand Up @@ -179,6 +183,8 @@ static const char *__doc_bbp_sonata_EdgePopulationProperties_spatialSynapseIndex

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

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

static const char *__doc_bbp_sonata_EdgePopulation_afferentEdges = R"doc(Return inbound edges for given node IDs.)doc";

static const char *__doc_bbp_sonata_EdgePopulation_connectingEdges = R"doc(Return edges connecting two given nodes.)doc";
Expand All @@ -195,6 +201,97 @@ static const char *__doc_bbp_sonata_EdgePopulation_targetNodeIDs = R"doc(Return

static const char *__doc_bbp_sonata_EdgePopulation_writeIndices = R"doc(Write bidirectional node->edge indices to EdgePopulation HDF5.)doc";

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

static const char *__doc_bbp_sonata_Hdf5PluginRead1DInterface = R"doc(Interface for implementing `readSelection<T>(dset, selection)`.)doc";

static const char *__doc_bbp_sonata_Hdf5PluginRead1DInterface_readSelection =
R"doc(Read the selected subset of the one-dimensional array.
The selection is canonical, i.e. sorted and non-overlapping. The
dataset is obtained from a `HighFive::File` opened via
`this->openFile`.)doc";

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

static const char *__doc_bbp_sonata_Hdf5PluginRead2DInterface_readSelection =
R"doc(Read the Cartesian product of the two selections.
Both selections are canonical, i.e. sorted and non-overlapping. The
dataset is obtained from a `HighFive::File` opened via
`this->openFile`.)doc";

static const char *__doc_bbp_sonata_Hdf5Reader =
R"doc(Abstraction for reading HDF5 datasets.
The Hdf5Reader provides an interface for reading canonical selections
from datasets. Selections are canonical if they are sorted and don't
overlap. This allows implementing different optimization strategies,
such as minimizing bytes read, aggregating nearby reads or using MPI
collective I/O.
The design uses virtual inheritance, which enables users to inject
their own reader if needed. This class is the interface used within
libsonata. It simply delegates to a "plugin", that satisfies the
interface `Hdf5PluginInterface`.
To enable MPI collective I/O, `libsonata` must call all methods in an
MPI-collective manner. This implies that the number of times any
function in `libsonata` calls any of the `Hdf5Reader` methods must not
depend on the arguments to the function.
Examples:
void wrong(Selection selection) { // Wrong because some MPI ranks
might return without // calling `readSelection`. if(selection.empty())
{ return; } hdf5_reader.readSelection(dset, selection); }
void also_wrong(Selection selection) { // Wrong because `hdf5_reader`
is called `selection.ranges().size()` // number of times. Which could
be different on each MPI rank. for(auto range : selection.ranges()) {
hdf5_reader.readSelection(dset, Selection(std::vector{range})); } }
void subtle(Selection selection, bool flag) { // If the flag can
differ between MPI ranks, this is wrong because // `readSelection` is
called with different `dset`s. If the `flag` must // be the same on
all MPI ranks, this is correct. If this happens in // the libsonata
API, then passing the same `flag` on all MPI ranks becomes // a
requirement for the users, when using a collective reader. Example: //
pop.get_attribute(attr_name, selection) if(flag) {
hdf5_reader.readSelection(dset1, selection); } else {
hdf5_reader.readSelection(dset2, selection); } }
void correct(Selection selection) { // Correct because no matter which
branch is taken // `hdf5_reader.readSelection` is called exactly once.
if(selection.size % 2 == 0) { hdf5_reader.readSelection(dset,
selection); } else { hdf5_reader.readSelection(dset, {}); } })doc";

static const char *__doc_bbp_sonata_Hdf5Reader_Hdf5Reader = R"doc(Create a valid Hdf5Reader with the default plugin.)doc";

static const char *__doc_bbp_sonata_Hdf5Reader_Hdf5Reader_2 = R"doc(Create an Hdf5Reader with a user supplied plugin.)doc";

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

static const char *__doc_bbp_sonata_Hdf5Reader_openFile =
R"doc(Open the HDF5.
The dataset passed to `readSelection` must be obtained from a file
open via this method.)doc";

static const char *__doc_bbp_sonata_Hdf5Reader_readSelection =
R"doc(Read the selected subset of the one-dimensional array.
Both selections are canonical, i.e. sorted and non-overlapping. The
dataset is obtained from a `HighFive::File` opened via
`this->openFile`.)doc";

static const char *__doc_bbp_sonata_Hdf5Reader_readSelection_2 =
R"doc(Read the Cartesian product of the two selections.
Both selections are canonical, i.e. sorted and non-overlapping. The
dataset is obtained from a `HighFive::File` opened via
`this->openFile`.)doc";

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

static const char *__doc_bbp_sonata_NodePopulationProperties = R"doc(Node population-specific network information.)doc";
Expand All @@ -217,6 +314,8 @@ Only for vasculature node populations where it is mandatory.)doc";

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

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

static const char *__doc_bbp_sonata_NodePopulation_matchAttributeValues =
R"doc(Return selection of where attribute values match value
Expand Down Expand Up @@ -274,18 +373,18 @@ Parameter ``name``:
is the name of the node_set rule to be evaluated
Parameter ``population``:
is the population overwhich the returned selection will be valid)doc";
is the population for which the returned selection will be valid)doc";

static const char *__doc_bbp_sonata_NodeSets_names = R"doc(Names of the node sets available)doc";

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

static const char *__doc_bbp_sonata_NodeSets_toJSON = R"doc(Return string version of node sets)doc";
static const char *__doc_bbp_sonata_NodeSets_toJSON = R"doc(Return the nodesets as a JSON string.)doc";

static const char *__doc_bbp_sonata_NodeSets_update =
R"doc(Update this NodeSets to include the `other` nodeset
R"doc(Update `this` to include all nodesets from `this` and `other`.
Duplicate names are overriden with the values from `other`
Duplicate names are overridden with the values from `other`.
The duplicate names are returned.)doc";

Expand All @@ -301,6 +400,12 @@ static const char *__doc_bbp_sonata_PopulationStorage_PopulationStorage_2 = R"do

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

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

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

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

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

static const char *__doc_bbp_sonata_PopulationStorage_openPopulation =
Expand Down Expand Up @@ -575,8 +680,6 @@ static const char *__doc_bbp_sonata_Selection = R"doc()doc";

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

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

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

static const char *__doc_bbp_sonata_Selection_flatSize = R"doc(Total number of elements constituting Selection)doc";
Expand Down Expand Up @@ -989,7 +1092,9 @@ R"doc(For compartment type, select compartments to report. Default value:

static const char *__doc_bbp_sonata_SimulationConfig_Report_dt = R"doc(Interval between reporting steps in milliseconds)doc";

static const char *__doc_bbp_sonata_SimulationConfig_Report_enabled = R"doc(Allows for supressing a report so that is not created. Default is true)doc";
static const char *__doc_bbp_sonata_SimulationConfig_Report_enabled =
R"doc(Allows for suppressing a report so that is not created. Default is
true)doc";

static const char *__doc_bbp_sonata_SimulationConfig_Report_endTime = R"doc(Time to stop reporting in milliseconds)doc";

Expand Down
13 changes: 13 additions & 0 deletions python/tests/test_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -625,6 +625,19 @@ def test_empty_connection_overrides(self):
conf = SimulationConfig(contents, "./")
self.assertEqual(conf.connection_overrides(), [])

def test_empty_conditions(self):
contents = """
{
"manifest": { "$CIRCUIT_DIR": "./circuit" },
"network": "$CIRCUIT_DIR/circuit_config.json",
"run": { "random_seed": 12345, "dt": 0.05, "tstop": 1000 },
"connection_overrides": []
}
"""
conf = SimulationConfig(contents, "./")
self.assertEqual(conf.conditions.celsius, 34.0)
self.assertEqual(conf.conditions.v_init, -80)

def test_run(self):
contents = """
{
Expand Down

0 comments on commit 3afe928

Please sign in to comment.