diff --git a/.github/workflows/publish-sdist-wheels.yml b/.github/workflows/publish-sdist-wheels.yml index 4e086abc..8f4e1a06 100644 --- a/.github/workflows/publish-sdist-wheels.yml +++ b/.github/workflows/publish-sdist-wheels.yml @@ -45,7 +45,6 @@ jobs: path: src-cache/ key: ${{ runner.os }}-build-${{ env.cache-name }} - - name: Build wheels on Linux if: runner.os == 'Linux' env: @@ -60,7 +59,7 @@ jobs: run: | # used by setup.py to decide if to set `FindHDF5` to use static hdf5 libraries export STATIC_HDF5=True - export CMAKE_PREFIX_PATH=/opt/hdf5-static/install-/install/ + export CMAKE_PREFIX_PATH=/opt/hdf5-static/install-x86_64/install/ CIBW_MANYLINUX_X86_64_IMAGE=manylinux2014 python -m cibuildwheel --output-dir dist CIBW_MANYLINUX_X86_64_IMAGE=manylinux_2_28 python -m cibuildwheel --output-dir dist diff --git a/.github/workflows/run-tests.yml b/.github/workflows/run-tests.yml index 1971924d..17585ff0 100644 --- a/.github/workflows/run-tests.yml +++ b/.github/workflows/run-tests.yml @@ -97,10 +97,7 @@ jobs: name: Run tests on macos runs-on: macos-latest env: - CIBW_ARCHS_MACOS: "x86_64" - CMAKE_OSX_ARCHITECTURES: "x86_64" UNIXY_HDF5_VERSION: 1.14.3 - MACOSX_DEPLOYMENT_TARGET: "11.0" steps: - name: Checkout repository @@ -124,10 +121,18 @@ jobs: ln -s $PWD/src-cache /Users/runner/work/src-cache bash ci/hdf5-build.sh /Users/runner/work/src-cache - - name: Build and run unittests + - name: Build and run unittests C++ tests run: | + : "${CIBW_ARCHS_MACOS:=$(uname -m)}" export CMAKE_PREFIX_PATH=/Users/runner/work/src-cache/install-$CIBW_ARCHS_MACOS/install export STATIC_HDF5=True ./ci/cpp_test.sh + + - name: Build and run unittests python tests + run: | + : "${CIBW_ARCHS_MACOS:=$(uname -m)}" + export CMAKE_PREFIX_PATH=/Users/runner/work/src-cache/install-$CIBW_ARCHS_MACOS/install + export STATIC_HDF5=True + ./ci/python_test.sh diff --git a/ci/hdf5-build.sh b/ci/hdf5-build.sh index f82d3887..4e1a3fd4 100755 --- a/ci/hdf5-build.sh +++ b/ci/hdf5-build.sh @@ -1,11 +1,12 @@ #!/bin/bash set -e -x +: "${UNIXY_HDF5_VERSION:=1.14.3}" +: "${CIBW_ARCHS_MACOS:=$(uname -m)}" export INPUT=$(cd $(dirname "$1") && pwd -P)/$(basename "$1") export OUTPUT="$INPUT/install-$CIBW_ARCHS_MACOS" -: "${UNIXY_HDF5_VERSION:=1.14.3}" function download_unpack_hdf5 { pushd "$INPUT" diff --git a/ci/python_test.sh b/ci/python_test.sh index 5a0258d1..543da86e 100755 --- a/ci/python_test.sh +++ b/ci/python_test.sh @@ -15,8 +15,13 @@ source $BIN/activate set -u $BIN/pip -v install --upgrade pip setuptools wheel + +which python +which pip +pip debug + $BIN/pip -v install --force . pushd python/tests -$BIN/python -m unittest -v +$BIN/python -m unittest -v popd diff --git a/include/bbp/sonata/config.h b/include/bbp/sonata/config.h index 9b4a4596..9ffeff98 100644 --- a/include/bbp/sonata/config.h +++ b/include/bbp/sonata/config.h @@ -460,6 +460,8 @@ class SONATA_API SimulationConfig double ampStart{}; /// The final current when a stimulus concludes (nA) double ampEnd{}; + /// Whether this input represents a physical electrode. Default is false + bool representsPhysicalElectrode = false; }; struct InputRelativeLinear: public InputBase { @@ -467,6 +469,8 @@ class SONATA_API SimulationConfig double percentStart{}; /// The percentage of a cell's threshold current to inject at the end double percentEnd{}; + /// Whether this input represents a physical electrode. Default is false + bool representsPhysicalElectrode = false; }; struct InputPulse: public InputBase { @@ -478,14 +482,21 @@ class SONATA_API SimulationConfig double width{}; /// The frequency of pulse trains (Hz) double frequency{}; + /// Whether this input represents a physical electrode. Default is false + bool representsPhysicalElectrode = false; }; struct InputSubthreshold: public InputBase { /// A percentage adjusted from 100 of a cell's threshold current double percentLess{}; + /// Whether this input represents a physical electrode. Default is false + bool representsPhysicalElectrode = false; }; - struct InputHyperpolarizing: public InputBase {}; + struct InputHyperpolarizing: public InputBase { + /// Whether this input represents a physical electrode. Default is false + bool representsPhysicalElectrode = false; + }; struct InputSynapseReplay: public InputBase { /// The location of the file with the spike info for injection, file extension must be .h5 @@ -507,6 +518,8 @@ class SONATA_API SimulationConfig /// State var to track whether the value of injected noise current is mean or /// mean_percent double variance{}; + /// Whether this input represents a physical electrode. Default is false + bool representsPhysicalElectrode = false; }; struct InputShotNoise: public InputBase { @@ -527,6 +540,8 @@ class SONATA_API SimulationConfig /// The variance of gamma-distributed amplitudes in nA^2 (current_clamp) or uS^2 /// (conductance) double ampVar{}; + /// Whether this input represents a physical electrode. Default is false + bool representsPhysicalElectrode = false; }; struct InputRelativeShotNoise: public InputBase { @@ -548,6 +563,8 @@ class SONATA_API SimulationConfig /// signal std dev as percentage of a cell’s threshold current (current_clamp) or inverse /// input resistance (conductance). double sdPercent{}; + /// Whether this input represents a physical electrode. Default is false + bool representsPhysicalElectrode = false; }; struct InputAbsoluteShotNoise: public InputBase { @@ -567,6 +584,8 @@ class SONATA_API SimulationConfig 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; }; struct InputOrnsteinUhlenbeck: public InputBase { @@ -582,6 +601,8 @@ class SONATA_API SimulationConfig 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; }; struct InputRelativeOrnsteinUhlenbeck: public InputBase { @@ -599,6 +620,8 @@ class SONATA_API SimulationConfig /// Signal std dev as percentage of a cell’s threshold current (current_clamp) or inverse /// input resistance (conductance) double sdPercent{}; + /// Whether this input represents a physical electrode. Default is false + bool representsPhysicalElectrode = false; }; using Input = nonstd::variant(simConf, "RelativeLinear") @@ -832,7 +835,10 @@ PYBIND11_MODULE(_libsonata, m) { DOC_SIMULATIONCONFIG(InputRelativeLinear, percentStart)) .def_readonly("percent_end", &SimulationConfig::InputRelativeLinear::percentEnd, - DOC_SIMULATIONCONFIG(InputRelativeLinear, percentEnd)); + DOC_SIMULATIONCONFIG(InputRelativeLinear, percentEnd)) + .def_readonly("represents_physical_electrode", + &SimulationConfig::InputRelativeLinear::representsPhysicalElectrode, + DOC_SIMULATIONCONFIG(InputRelativeLinear, representsPhysicalElectrode)); py::class_(simConf, "Pulse") .def_readonly("amp_start", @@ -846,16 +852,25 @@ PYBIND11_MODULE(_libsonata, m) { DOC_SIMULATIONCONFIG(InputPulse, width)) .def_readonly("frequency", &SimulationConfig::InputPulse::frequency, - DOC_SIMULATIONCONFIG(InputPulse, frequency)); + DOC_SIMULATIONCONFIG(InputPulse, frequency)) + .def_readonly("represents_physical_electrode", + &SimulationConfig::InputPulse::representsPhysicalElectrode, + DOC_SIMULATIONCONFIG(InputPulse, representsPhysicalElectrode)); py::class_(simConf, "Subthreshold") .def_readonly("percent_less", &SimulationConfig::InputSubthreshold::percentLess, - DOC_SIMULATIONCONFIG(InputSubthreshold, percentLess)); + DOC_SIMULATIONCONFIG(InputSubthreshold, percentLess)) + .def_readonly("represents_physical_electrode", + &SimulationConfig::InputSubthreshold::representsPhysicalElectrode, + DOC_SIMULATIONCONFIG(InputSubthreshold, representsPhysicalElectrode)); py::class_( - simConf, "Hyperpolarizing"); + simConf, "Hyperpolarizing") + .def_readonly("represents_physical_electrode", + &SimulationConfig::InputHyperpolarizing::representsPhysicalElectrode, + DOC_SIMULATIONCONFIG(InputHyperpolarizing, representsPhysicalElectrode)); py::class_(simConf, "SynapseReplay") @@ -880,7 +895,10 @@ PYBIND11_MODULE(_libsonata, m) { DOC_SIMULATIONCONFIG(InputNoise, meanPercent)) .def_readonly("variance", &SimulationConfig::InputNoise::variance, - DOC_SIMULATIONCONFIG(InputNoise, variance)); + DOC_SIMULATIONCONFIG(InputNoise, variance)) + .def_readonly("represents_physical_electrode", + &SimulationConfig::InputNoise::representsPhysicalElectrode, + DOC_SIMULATIONCONFIG(InputNoise, representsPhysicalElectrode)); py::class_(simConf, "ShotNoise") .def_readonly("rise_time", @@ -906,7 +924,10 @@ PYBIND11_MODULE(_libsonata, m) { DOC_SIMULATIONCONFIG(InputShotNoise, ampMean)) .def_readonly("amp_var", &SimulationConfig::InputShotNoise::ampVar, - DOC_SIMULATIONCONFIG(InputShotNoise, ampVar)); + DOC_SIMULATIONCONFIG(InputShotNoise, ampVar)) + .def_readonly("represents_physical_electrode", + &SimulationConfig::InputShotNoise::representsPhysicalElectrode, + DOC_SIMULATIONCONFIG(InputShotNoise, representsPhysicalElectrode)); py::class_( simConf, "RelativeShotNoise") @@ -933,7 +954,10 @@ PYBIND11_MODULE(_libsonata, m) { DOC_SIMULATIONCONFIG(InputRelativeShotNoise, sdPercent)) .def_readonly("mean_percent", &SimulationConfig::InputRelativeShotNoise::meanPercent, - DOC_SIMULATIONCONFIG(InputRelativeShotNoise, meanPercent)); + DOC_SIMULATIONCONFIG(InputRelativeShotNoise, meanPercent)) + .def_readonly("represents_physical_electrode", + &SimulationConfig::InputRelativeShotNoise::representsPhysicalElectrode, + DOC_SIMULATIONCONFIG(InputRelativeShotNoise, representsPhysicalElectrode)); py::class_( simConf, "AbsoluteShotNoise") @@ -960,7 +984,10 @@ PYBIND11_MODULE(_libsonata, m) { DOC_SIMULATIONCONFIG(InputAbsoluteShotNoise, mean)) .def_readonly("sigma", &SimulationConfig::InputAbsoluteShotNoise::sigma, - DOC_SIMULATIONCONFIG(InputAbsoluteShotNoise, sigma)); + DOC_SIMULATIONCONFIG(InputAbsoluteShotNoise, sigma)) + .def_readonly("represents_physical_electrode", + &SimulationConfig::InputAbsoluteShotNoise::representsPhysicalElectrode, + DOC_SIMULATIONCONFIG(InputAbsoluteShotNoise, representsPhysicalElectrode)); py::class_( simConf, "OrnsteinUhlenbeck") @@ -981,7 +1008,10 @@ PYBIND11_MODULE(_libsonata, m) { DOC_SIMULATIONCONFIG(InputOrnsteinUhlenbeck, mean)) .def_readonly("sigma", &SimulationConfig::InputOrnsteinUhlenbeck::sigma, - DOC_SIMULATIONCONFIG(InputOrnsteinUhlenbeck, sigma)); + DOC_SIMULATIONCONFIG(InputOrnsteinUhlenbeck, sigma)) + .def_readonly("represents_physical_electrode", + &SimulationConfig::InputOrnsteinUhlenbeck::representsPhysicalElectrode, + DOC_SIMULATIONCONFIG(InputOrnsteinUhlenbeck, representsPhysicalElectrode)); py::class_( simConf, "RelativeOrnsteinUhlenbeck") @@ -1002,7 +1032,11 @@ PYBIND11_MODULE(_libsonata, m) { DOC_SIMULATIONCONFIG(InputRelativeOrnsteinUhlenbeck, meanPercent)) .def_readonly("sd_percent", &SimulationConfig::InputRelativeOrnsteinUhlenbeck::sdPercent, - DOC_SIMULATIONCONFIG(InputRelativeOrnsteinUhlenbeck, sdPercent)); + DOC_SIMULATIONCONFIG(InputRelativeOrnsteinUhlenbeck, sdPercent)) + .def_readonly( + "represents_physical_electrode", + &SimulationConfig::InputRelativeOrnsteinUhlenbeck::representsPhysicalElectrode, + DOC_SIMULATIONCONFIG(InputRelativeOrnsteinUhlenbeck, representsPhysicalElectrode)); py::enum_(inputBase, "Module") .value("linear", SimulationConfig::InputBase::Module::linear) diff --git a/python/generated/docstrings.h b/python/generated/docstrings.h index 3d0951d2..c7711ce3 100644 --- a/python/generated/docstrings.h +++ b/python/generated/docstrings.h @@ -800,6 +800,8 @@ static const char *__doc_bbp_sonata_SimulationConfig_InputAbsoluteShotNoise_rise static const char *__doc_bbp_sonata_SimulationConfig_InputAbsoluteShotNoise_sigma = R"doc(signal std dev in nA (current_clamp) or uS (conductance).)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_InputBase = R"doc()doc"; static const char *__doc_bbp_sonata_SimulationConfig_InputBase_InputType = R"doc()doc"; @@ -858,12 +860,16 @@ static const char *__doc_bbp_sonata_SimulationConfig_InputBase_nodeSet = R"doc(N static const char *__doc_bbp_sonata_SimulationConfig_InputHyperpolarizing = R"doc()doc"; +static const char *__doc_bbp_sonata_SimulationConfig_InputHyperpolarizing_representsPhysicalElectrode = R"doc(Whether this input represents a physical electrode. Default is false)doc"; + static const char *__doc_bbp_sonata_SimulationConfig_InputLinear = R"doc()doc"; static const char *__doc_bbp_sonata_SimulationConfig_InputLinear_ampEnd = R"doc(The final current when a stimulus concludes (nA))doc"; static const char *__doc_bbp_sonata_SimulationConfig_InputLinear_ampStart = R"doc(The amount of current initially injected (nA))doc"; +static const char *__doc_bbp_sonata_SimulationConfig_InputLinear_representsPhysicalElectrode = R"doc(Whether this input represents a physical electrode. Default is false)doc"; + static const char *__doc_bbp_sonata_SimulationConfig_InputNoise = R"doc()doc"; static const char *__doc_bbp_sonata_SimulationConfig_InputNoise_mean = R"doc(The mean value of current to inject (nA), default = None)doc"; @@ -876,6 +882,8 @@ static const char *__doc_bbp_sonata_SimulationConfig_InputNoise_variance = R"doc(State var to track whether the value of injected noise current is mean or mean_percent)doc"; +static const char *__doc_bbp_sonata_SimulationConfig_InputNoise_representsPhysicalElectrode = R"doc(Whether this input represents a physical electrode. Default is false)doc"; + static const char *__doc_bbp_sonata_SimulationConfig_InputOrnsteinUhlenbeck = R"doc()doc"; static const char *__doc_bbp_sonata_SimulationConfig_InputOrnsteinUhlenbeck_dt = R"doc(Timestep of generated signal in ms. Default is 0.25 ms)doc"; @@ -892,6 +900,8 @@ static const char *__doc_bbp_sonata_SimulationConfig_InputOrnsteinUhlenbeck_sigm static const char *__doc_bbp_sonata_SimulationConfig_InputOrnsteinUhlenbeck_tau = R"doc(Relaxation time constant in ms)doc"; +static const char *__doc_bbp_sonata_SimulationConfig_InputOrnsteinUhlenbeck_representsPhysicalElectrode = R"doc(Whether this input represents a physical electrode. Default is false)doc"; + static const char *__doc_bbp_sonata_SimulationConfig_InputPulse = R"doc()doc"; static const char *__doc_bbp_sonata_SimulationConfig_InputPulse_ampEnd = R"doc(The final current when a stimulus concludes (nA))doc"; @@ -902,12 +912,16 @@ static const char *__doc_bbp_sonata_SimulationConfig_InputPulse_frequency = R"do static const char *__doc_bbp_sonata_SimulationConfig_InputPulse_width = R"doc(The length of time each pulse lasts (ms))doc"; +static const char *__doc_bbp_sonata_SimulationConfig_InputPulse_representsPhysicalElectrode = R"doc(Whether this input represents a physical electrode. Default is false)doc"; + static const char *__doc_bbp_sonata_SimulationConfig_InputRelativeLinear = R"doc()doc"; static const char *__doc_bbp_sonata_SimulationConfig_InputRelativeLinear_percentEnd = R"doc(The percentage of a cell's threshold current to inject at the end)doc"; static const char *__doc_bbp_sonata_SimulationConfig_InputRelativeLinear_percentStart = R"doc(The percentage of a cell's threshold current to inject)doc"; +static const char *__doc_bbp_sonata_SimulationConfig_InputRelativeLinear_representsPhysicalElectrode = R"doc(Whether this input represents a physical electrode. Default is false)doc"; + static const char *__doc_bbp_sonata_SimulationConfig_InputRelativeOrnsteinUhlenbeck = R"doc()doc"; static const char *__doc_bbp_sonata_SimulationConfig_InputRelativeOrnsteinUhlenbeck_dt = R"doc(Timestep of generated signal in ms. Default is 0.25 ms)doc"; @@ -928,6 +942,8 @@ R"doc(Signal std dev as percentage of a cell’s threshold current static const char *__doc_bbp_sonata_SimulationConfig_InputRelativeOrnsteinUhlenbeck_tau = R"doc(Relaxation time constant in ms)doc"; +static const char *__doc_bbp_sonata_SimulationConfig_InputRelativeOrnsteinUhlenbeck_representsPhysicalElectrode = R"doc(Whether this input represents a physical electrode. Default is false)doc"; + 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"; @@ -952,6 +968,8 @@ static const char *__doc_bbp_sonata_SimulationConfig_InputRelativeShotNoise_sdPe R"doc(signal std dev as percentage of a cell’s threshold current (current_clamp) or inverse input resistance (conductance).)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_InputSeclamp = R"doc()doc"; static const char *__doc_bbp_sonata_SimulationConfig_InputSeclamp_seriesResistance = R"doc(The series resistance (Mohm), default is 0.01 Mohm)doc"; @@ -982,10 +1000,14 @@ static const char *__doc_bbp_sonata_SimulationConfig_InputShotNoise_reversal = R static const char *__doc_bbp_sonata_SimulationConfig_InputShotNoise_riseTime = R"doc(The rise time of the bi-exponential shots (ms))doc"; +static const char *__doc_bbp_sonata_SimulationConfig_InputShotNoise_representsPhysicalElectrode = R"doc(Whether this input represents a physical electrode. Default is false)doc"; + static const char *__doc_bbp_sonata_SimulationConfig_InputSubthreshold = R"doc()doc"; static const char *__doc_bbp_sonata_SimulationConfig_InputSubthreshold_percentLess = R"doc(A percentage adjusted from 100 of a cell's threshold current)doc"; +static const char *__doc_bbp_sonata_SimulationConfig_InputSubthreshold_representsPhysicalElectrode = R"doc(Whether this input represents a physical electrode. Default is false)doc"; + static const char *__doc_bbp_sonata_SimulationConfig_InputSynapseReplay = R"doc()doc"; static const char *__doc_bbp_sonata_SimulationConfig_InputSynapseReplay_spikeFile = diff --git a/python/tests/test_config.py b/python/tests/test_config.py index 3ab4dc26..52a2e082 100644 --- a/python/tests/test_config.py +++ b/python/tests/test_config.py @@ -565,6 +565,7 @@ def test_basic(self): 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_OU').module.name, "ornstein_uhlenbeck") self.assertEqual(self.config.input('ex_OU').input_type.name, "conductance") @@ -573,6 +574,7 @@ def test_basic(self): self.assertEqual(self.config.input('ex_OU').mean, 50) self.assertEqual(self.config.input('ex_OU').sigma, 5) self.assertEqual(self.config.input('ex_OU').random_seed, None) + self.assertEqual(self.config.input('ex_OU').represents_physical_electrode, False) self.assertEqual(self.config.input('ex_rel_OU').input_type.name, "current_clamp") self.assertEqual(self.config.input('ex_rel_OU').tau, 2.8) diff --git a/src/config.cpp b/src/config.cpp index d846cfa9..31f0e095 100644 --- a/src/config.cpp +++ b/src/config.cpp @@ -409,6 +409,10 @@ SimulationConfig::Input parseInputModule(const nlohmann::json& valueIt, parseCommon(ret); parseMandatory(valueIt, "amp_start", debugStr, ret.ampStart); parseOptional(valueIt, "amp_end", ret.ampEnd, {ret.ampStart}); + parseOptional(valueIt, + "represents_physical_electrode", + ret.representsPhysicalElectrode, + {false}); return ret; } case Module::relative_linear: { @@ -416,6 +420,10 @@ SimulationConfig::Input parseInputModule(const nlohmann::json& valueIt, parseCommon(ret); parseMandatory(valueIt, "percent_start", debugStr, ret.percentStart); parseOptional(valueIt, "percent_end", ret.percentEnd, {ret.percentStart}); + parseOptional(valueIt, + "represents_physical_electrode", + ret.representsPhysicalElectrode, + {false}); return ret; } case Module::pulse: { @@ -425,12 +433,20 @@ SimulationConfig::Input parseInputModule(const nlohmann::json& valueIt, parseMandatory(valueIt, "width", debugStr, ret.width); parseMandatory(valueIt, "frequency", debugStr, ret.frequency); parseOptional(valueIt, "amp_end", ret.ampEnd, {ret.ampStart}); + parseOptional(valueIt, + "represents_physical_electrode", + ret.representsPhysicalElectrode, + {false}); return ret; } case Module::subthreshold: { SimulationConfig::InputSubthreshold ret; parseCommon(ret); parseMandatory(valueIt, "percent_less", debugStr, ret.percentLess); + parseOptional(valueIt, + "represents_physical_electrode", + ret.representsPhysicalElectrode, + {false}); return ret; } case Module::noise: { @@ -455,6 +471,10 @@ SimulationConfig::Input parseInputModule(const nlohmann::json& valueIt, } parseOptional(valueIt, "variance", ret.variance); + parseOptional(valueIt, + "represents_physical_electrode", + ret.representsPhysicalElectrode, + {false}); return ret; } case Module::shot_noise: { @@ -465,6 +485,10 @@ SimulationConfig::Input parseInputModule(const nlohmann::json& valueIt, parseOptional(valueIt, "random_seed", ret.randomSeed); parseOptional(valueIt, "reversal", ret.reversal, {0.0}); parseOptional(valueIt, "dt", ret.dt, {0.25}); + parseOptional(valueIt, + "represents_physical_electrode", + ret.representsPhysicalElectrode, + {false}); parseMandatory(valueIt, "rate", debugStr, ret.rate); parseMandatory(valueIt, "amp_mean", debugStr, ret.ampMean); parseMandatory(valueIt, "amp_var", debugStr, ret.ampVar); @@ -479,6 +503,10 @@ SimulationConfig::Input parseInputModule(const nlohmann::json& valueIt, parseOptional(valueIt, "random_seed", ret.randomSeed); parseOptional(valueIt, "reversal", ret.reversal, {0.0}); parseOptional(valueIt, "dt", ret.dt, {0.25}); + parseOptional(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); @@ -493,6 +521,10 @@ SimulationConfig::Input parseInputModule(const nlohmann::json& valueIt, parseOptional(valueIt, "random_seed", ret.randomSeed); parseOptional(valueIt, "reversal", ret.reversal, {0.0}); parseOptional(valueIt, "dt", ret.dt, {0.25}); + parseOptional(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); @@ -501,6 +533,10 @@ SimulationConfig::Input parseInputModule(const nlohmann::json& valueIt, case Module::hyperpolarizing: { SimulationConfig::InputHyperpolarizing ret; parseCommon(ret); + parseOptional(valueIt, + "represents_physical_electrode", + ret.representsPhysicalElectrode, + {false}); return ret; } case Module::synapse_replay: { @@ -528,6 +564,10 @@ SimulationConfig::Input parseInputModule(const nlohmann::json& valueIt, parseOptional(valueIt, "reversal", ret.reversal, {0.0}); parseOptional(valueIt, "random_seed", ret.randomSeed); parseOptional(valueIt, "dt", ret.dt, {0.25}); + parseOptional(valueIt, + "represents_physical_electrode", + ret.representsPhysicalElectrode, + {false}); parseMandatory(valueIt, "mean", debugStr, ret.mean); parseMandatory(valueIt, "sigma", debugStr, ret.sigma); @@ -540,6 +580,10 @@ SimulationConfig::Input parseInputModule(const nlohmann::json& valueIt, parseOptional(valueIt, "reversal", ret.reversal, {0.0}); parseOptional(valueIt, "random_seed", ret.randomSeed); parseOptional(valueIt, "dt", ret.dt, {0.25}); + parseOptional(valueIt, + "represents_physical_electrode", + ret.representsPhysicalElectrode, + {false}); parseMandatory(valueIt, "mean_percent", debugStr, ret.meanPercent); parseMandatory(valueIt, "sd_percent", debugStr, ret.sdPercent); diff --git a/tests/data/config/simulation_config.json b/tests/data/config/simulation_config.json index d7f00419..f718cbd7 100644 --- a/tests/data/config/simulation_config.json +++ b/tests/data/config/simulation_config.json @@ -168,6 +168,7 @@ "amp_cv": 0.63, "mean": 50, "sigma": 5, + "represents_physical_electrode": true, "node_set": "L5E" }, "ex_replay": { diff --git a/tests/test_config.cpp b/tests/test_config.cpp index caae6a6b..bcb6aa11 100644 --- a/tests/test_config.cpp +++ b/tests/test_config.cpp @@ -528,6 +528,7 @@ TEST_CASE("SimulationConfig") { CHECK(input.sigma == 5); CHECK(input.reversal == 10); CHECK(input.randomSeed == nonstd::nullopt); + CHECK(input.representsPhysicalElectrode == true); } { const auto input = nonstd::get( @@ -539,6 +540,7 @@ TEST_CASE("SimulationConfig") { CHECK(input.mean == 50); CHECK(input.sigma == 5); CHECK(input.randomSeed == nonstd::nullopt); + CHECK(input.representsPhysicalElectrode == false); } { const auto input = nonstd::get(