From 75cdf2f22283e7dc8a39b11e81dd26ee62265d4c Mon Sep 17 00:00:00 2001 From: bcumming <bcumming@cscs.ch> Date: Tue, 24 May 2016 11:06:09 +0200 Subject: [PATCH] refactor unit tests --- src/cell.cpp | 4 +- src/cell.hpp | 2 +- tests/CMakeLists.txt | 3 +- tests/test_fvm.cpp | 105 +++++++++++++++ tests/test_parameters.cpp | 42 ++++++ tests/test_run.cpp | 265 -------------------------------------- 6 files changed, 152 insertions(+), 269 deletions(-) create mode 100644 tests/test_parameters.cpp delete mode 100644 tests/test_run.cpp diff --git a/src/cell.cpp b/src/cell.cpp index 72bad02a..a6986f06 100644 --- a/src/cell.cpp +++ b/src/cell.cpp @@ -155,9 +155,9 @@ std::vector<int> cell::compartment_counts() const return comp_count; } -int cell::num_compartments() const +size_t cell::num_compartments() const { - auto n = 0; + auto n = 0u; for(auto &s : segments_) { n += s->num_compartments(); } diff --git a/src/cell.hpp b/src/cell.hpp index 6e5d95f9..ba5f9b6b 100644 --- a/src/cell.hpp +++ b/src/cell.hpp @@ -86,7 +86,7 @@ class cell { value_type area() const; /// the total number of compartments over all segments - int num_compartments() const; + size_t num_compartments() const; std::vector<segment_ptr> const& segments() const; diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 11b88107..cb33af4d 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -16,10 +16,11 @@ set(TEST_SOURCES test_algorithms.cpp test_cell.cpp test_compartments.cpp + test_fvm.cpp test_matrix.cpp test_mechanisms.cpp + test_parameters.cpp test_point.cpp - test_run.cpp test_segment.cpp test_stimulus.cpp test_swcio.cpp diff --git a/tests/test_fvm.cpp b/tests/test_fvm.cpp index e69de29b..85a25f35 100644 --- a/tests/test_fvm.cpp +++ b/tests/test_fvm.cpp @@ -0,0 +1,105 @@ +#include <fstream> + +#include "gtest.h" +#include "util.hpp" + +#include "../src/cell.hpp" +#include "../src/fvm.hpp" + +TEST(fvm, cable) +{ + using namespace nest::mc; + + nest::mc::cell cell; + + // setup global state for the mechanisms + nest::mc::mechanisms::setup_mechanism_helpers(); + + cell.add_soma(6e-4); // 6um in cm + + // 1um radius and 4mm long, all in cm + cell.add_cable(0, segmentKind::dendrite, 1e-4, 1e-4, 4e-1); + cell.add_cable(0, segmentKind::dendrite, 1e-4, 1e-4, 4e-1); + + //std::cout << cell.segment(1)->area() << " is the area\n"; + EXPECT_EQ(cell.model().tree.num_segments(), 3u); + + // add passive to all 3 segments in the cell + for(auto& seg :cell.segments()) { + seg->add_mechanism(pas_parameters()); + } + + cell.soma()->add_mechanism(hh_parameters()); + cell.segment(2)->add_mechanism(hh_parameters()); + + auto& soma_hh = cell.soma()->mechanism("hh"); + + soma_hh.set("gnabar", 0.12); + soma_hh.set("gkbar", 0.036); + soma_hh.set("gl", 0.0003); + soma_hh.set("el", -54.387); + + cell.segment(1)->set_compartments(4); + cell.segment(2)->set_compartments(4); + + using fvm_cell = fvm::fvm_cell<double, int>; + fvm_cell fvcell(cell); + auto& J = fvcell.jacobian(); + + EXPECT_EQ(cell.num_compartments(), 9u); + + // assert that the matrix has one row for each compartment + EXPECT_EQ(J.size(), cell.num_compartments()); + + fvcell.setup_matrix(0.02); + + // assert that the number of cv areas is the same as the matrix size + // i.e. both should equal the number of compartments + EXPECT_EQ(fvcell.cv_areas().size(), J.size()); +} + +TEST(fvm, init) +{ + using namespace nest::mc; + + nest::mc::cell cell; + + // setup global state for the mechanisms + nest::mc::mechanisms::setup_mechanism_helpers(); + + cell.add_soma(12.6157/2.0); + //auto& props = cell.soma()->properties; + + cell.add_cable(0, segmentKind::dendrite, 0.5, 0.5, 200); + + const auto m = cell.model(); + EXPECT_EQ(m.tree.num_segments(), 2u); + + // in this context (i.e. attached to a segment on a high-level cell) + // a mechanism is essentially a set of parameters + // - the only "state" is that used to define parameters + cell.soma()->add_mechanism(hh_parameters()); + + auto& soma_hh = cell.soma()->mechanism("hh"); + + soma_hh.set("gnabar", 0.12); + soma_hh.set("gkbar", 0.036); + soma_hh.set("gl", 0.0003); + soma_hh.set("el", -54.3); + + // check that parameter values were set correctly + EXPECT_EQ(cell.soma()->mechanism("hh").get("gnabar").value, 0.12); + EXPECT_EQ(cell.soma()->mechanism("hh").get("gkbar").value, 0.036); + EXPECT_EQ(cell.soma()->mechanism("hh").get("gl").value, 0.0003); + EXPECT_EQ(cell.soma()->mechanism("hh").get("el").value, -54.3); + + cell.segment(1)->set_compartments(10); + + using fvm_cell = fvm::fvm_cell<double, int>; + fvm_cell fvcell(cell); + auto& J = fvcell.jacobian(); + EXPECT_EQ(J.size(), 11u); + + fvcell.setup_matrix(0.01); +} + diff --git a/tests/test_parameters.cpp b/tests/test_parameters.cpp new file mode 100644 index 00000000..0dce58b0 --- /dev/null +++ b/tests/test_parameters.cpp @@ -0,0 +1,42 @@ + +#include <fstream> + +#include "gtest.h" +#include "util.hpp" + +#include <parameter_list.hpp> + +// test out the parameter infrastructure +TEST(parameters, setting) +{ + nest::mc::parameter_list list("test"); + EXPECT_EQ(list.name(), "test"); + EXPECT_EQ(list.num_parameters(), 0); + + nest::mc::parameter p("a", 0.12, {0, 10}); + + // add_parameter() returns a bool that indicates whether + // it was able to successfull add the parameter + EXPECT_TRUE(list.add_parameter(std::move(p))); + EXPECT_EQ(list.num_parameters(), 1); + + // test in place construction of a parameter + EXPECT_TRUE(list.add_parameter({"b", -3.0})); + EXPECT_EQ(list.num_parameters(), 2); + + // check that adding a parameter that already exists returns false + // and does not increase the number of parameters + EXPECT_FALSE(list.add_parameter({"b", -3.0})); + EXPECT_EQ(list.num_parameters(), 2); + + auto &parms = list.parameters(); + EXPECT_EQ(parms[0].name, "a"); + EXPECT_EQ(parms[0].value, 0.12); + EXPECT_EQ(parms[0].range.min, 0); + EXPECT_EQ(parms[0].range.max, 10); + + EXPECT_EQ(parms[1].name, "b"); + EXPECT_EQ(parms[1].value, -3); + EXPECT_FALSE(parms[1].range.has_lower_bound()); + EXPECT_FALSE(parms[1].range.has_upper_bound()); +} diff --git a/tests/test_run.cpp b/tests/test_run.cpp deleted file mode 100644 index aa4d9bba..00000000 --- a/tests/test_run.cpp +++ /dev/null @@ -1,265 +0,0 @@ -#include <fstream> - -#include "gtest.h" -#include "util.hpp" - -#include "../src/cell.hpp" -#include "../src/fvm.hpp" - -// based on hh/Neuron/steps_A.py -TEST(run, single_compartment) -{ - using namespace nest::mc; - - std::vector<std::vector<double>> results(2); - - nest::mc::cell cell; - - // setup global state for the mechanisms - nest::mc::mechanisms::setup_mechanism_helpers(); - - // Soma with diameter 18.8um and HH channel - auto soma = cell.add_soma(18.8/2.0); - soma->mechanism("membrane").set("r_L", 123); // no effect for single compartment cell - soma->add_mechanism(hh_parameters()); - - // add stimulus to the soma - //cell.add_stimulus({0,0}, {5., 3., 0.1}); - cell.add_stimulus({0,0.5}, {10., 100., 0.1}); - - // make the lowered finite volume cell - fvm::fvm_cell<double, int> model(cell); - - // set initial conditions - using memory::all; - model.voltage()(all) = -65.; - model.initialize(); // have to do this _after_ initial conditions are set - - // run the simulation - auto dt = 0.0005; // ms - auto tfinal = 120.; // ms - int nt = tfinal/dt; - results[0].push_back(0.); - results[1].push_back(model.voltage()[0]); - for(auto i=0; i<nt; ++i) { - model.advance(dt); - // save voltage at soma - results[0].push_back((i+1)*dt); - results[1].push_back(model.voltage()[0]); - } - - testing::write_vis_file("v.dat", results); -} - -TEST(run, ball_and_stick) -{ - using namespace nest::mc; - - std::vector<std::vector<double>> results(3); - - nest::mc::cell cell; - - // setup global state for the mechanisms - nest::mc::mechanisms::setup_mechanism_helpers(); - - // Soma with diameter 12.6157 um and HH channel - auto soma = cell.add_soma(12.6157/2.0); - soma->add_mechanism(hh_parameters()); - - // add dendrite of length 200 um and diameter 1 um with passive channel - auto dendrite = cell.add_cable(0, segmentKind::dendrite, 0.5, 0.5, 200); - dendrite->set_compartments(10); - dendrite->add_mechanism(pas_parameters()); - - dendrite->mechanism("membrane").set("r_L", 100); // no effect for single compartment cell - - // add stimulus - //cell.add_stimulus({0,0}, {5., 1., 0.1}); // soma - cell.add_stimulus({1,1}, {5., 1., 0.5}); - - // make the lowered finite volume cell - fvm::fvm_cell<double, int> model(cell); - - std::cout << "CV areas " << model.cv_areas() << "\n"; - - // set initial conditions - using memory::all; - model.voltage()(all) = -65.; - model.initialize(); // have to do this _after_ initial conditions are set - - // run the simulation - auto pos = model.size()-1; - auto dt = 0.001; // ms - auto tfinal = 25.; // ms - int nt = tfinal/dt; - results[0].push_back(0.); - results[1].push_back(model.voltage()[0]); - results[2].push_back(model.voltage()[pos]); - for(auto i=0; i<nt; ++i) { - model.advance(dt); - results[0].push_back((i+1)*dt); - results[1].push_back(model.voltage()[0]); - results[2].push_back(model.voltage()[pos]); - } - - testing::write_vis_file("v.dat", results); -} - -TEST(run, cable) -{ - using namespace nest::mc; - - nest::mc::cell cell; - - // setup global state for the mechanisms - nest::mc::mechanisms::setup_mechanism_helpers(); - - cell.add_soma(6e-4); // 6um in cm - - // 1um radius and 4mm long, all in cm - cell.add_cable(0, segmentKind::dendrite, 1e-4, 1e-4, 4e-1); - cell.add_cable(0, segmentKind::dendrite, 1e-4, 1e-4, 4e-1); - - //std::cout << cell.segment(1)->area() << " is the area\n"; - EXPECT_EQ(cell.model().tree.num_segments(), 3u); - - // add passive to all 3 segments in the cell - for(auto& seg :cell.segments()) { - seg->add_mechanism(pas_parameters()); - } - - cell.soma()->add_mechanism(hh_parameters()); - cell.segment(2)->add_mechanism(hh_parameters()); - - auto& soma_hh = cell.soma()->mechanism("hh"); - - soma_hh.set("gnabar", 0.12); - soma_hh.set("gkbar", 0.036); - soma_hh.set("gl", 0.0003); - soma_hh.set("el", -54.387); - - cell.segment(1)->set_compartments(4); - cell.segment(2)->set_compartments(4); - - using fvm_cell = fvm::fvm_cell<double, int>; - fvm_cell fvcell(cell); - auto& J = fvcell.jacobian(); - EXPECT_EQ(J.size(), 9u); - - fvcell.setup_matrix(0.02); - EXPECT_EQ(fvcell.cv_areas().size(), J.size()); - - // inspect ion channels - /* - std::cout << "ion na index : " << fvcell.ion_na().node_index() << "\n"; - std::cout << "ion ca index : " << fvcell.ion_ca().node_index() << "\n"; - std::cout << "ion k index : " << fvcell.ion_k().node_index() << "\n"; - - std::cout << "ion na E : " << fvcell.ion_na().reversal_potential() << "\n"; - std::cout << "ion ca E : " << fvcell.ion_ca().reversal_potential() << "\n"; - std::cout << "ion k E : " << fvcell.ion_k().reversal_potential() << "\n"; - */ - - //auto& cable_parms = cell.segment(1)->mechanism("membrane"); - //std::cout << soma_hh << std::endl; - //std::cout << cable_parms << std::endl; - - //std::cout << "l " << J.l() << "\n"; - //std::cout << "d " << J.d() << "\n"; - //std::cout << "u " << J.u() << "\n"; - //std::cout << "p " << J.p() << "\n"; - - J.rhs()(memory::all) = 1.; - J.rhs()[0] = 10.; - - J.solve(); -} - -TEST(run, init) -{ - using namespace nest::mc; - - nest::mc::cell cell; - - // setup global state for the mechanisms - nest::mc::mechanisms::setup_mechanism_helpers(); - - cell.add_soma(12.6157/2.0); - //auto& props = cell.soma()->properties; - - cell.add_cable(0, segmentKind::dendrite, 0.5, 0.5, 200); - - const auto m = cell.model(); - EXPECT_EQ(m.tree.num_segments(), 2u); - - // in this context (i.e. attached to a segment on a high-level cell) - // a mechanism is essentially a set of parameters - // - the only "state" is that used to define parameters - cell.soma()->add_mechanism(hh_parameters()); - - auto& soma_hh = cell.soma()->mechanism("hh"); - - soma_hh.set("gnabar", 0.12); - soma_hh.set("gkbar", 0.036); - soma_hh.set("gl", 0.0003); - soma_hh.set("el", -54.3); - - // check that parameter values were set correctly - EXPECT_EQ(cell.soma()->mechanism("hh").get("gnabar").value, 0.12); - EXPECT_EQ(cell.soma()->mechanism("hh").get("gkbar").value, 0.036); - EXPECT_EQ(cell.soma()->mechanism("hh").get("gl").value, 0.0003); - EXPECT_EQ(cell.soma()->mechanism("hh").get("el").value, -54.3); - - cell.segment(1)->set_compartments(10); - - using fvm_cell = fvm::fvm_cell<double, int>; - fvm_cell fvcell(cell); - auto& J = fvcell.jacobian(); - EXPECT_EQ(J.size(), 11u); - - fvcell.setup_matrix(0.01); - //std::cout << "areas " << fvcell.cv_areas() << "\n"; - - J.rhs()(memory::all) = 1.; - J.rhs()[0] = 10.; - - J.solve(); - - //std::cout << "x" << J.rhs() << "\n"; -} - -// test out the parameter infrastructure -TEST(run, parameters) -{ - nest::mc::parameter_list list("test"); - EXPECT_EQ(list.name(), "test"); - EXPECT_EQ(list.num_parameters(), 0); - - nest::mc::parameter p("a", 0.12, {0, 10}); - - // add_parameter() returns a bool that indicates whether - // it was able to successfull add the parameter - EXPECT_EQ(list.add_parameter(std::move(p)), true); - EXPECT_EQ(list.num_parameters(), 1); - - // test in place construction of a parameter - EXPECT_EQ(list.add_parameter({"b", -3.0}), true); - EXPECT_EQ(list.num_parameters(), 2); - - // check that adding a parameter that already exists returns false - // and does not increase the number of parameters - EXPECT_EQ(list.add_parameter({"b", -3.0}), false); - EXPECT_EQ(list.num_parameters(), 2); - - auto &parms = list.parameters(); - EXPECT_EQ(parms[0].name, "a"); - EXPECT_EQ(parms[0].value, 0.12); - EXPECT_EQ(parms[0].range.min, 0); - EXPECT_EQ(parms[0].range.max, 10); - - EXPECT_EQ(parms[1].name, "b"); - EXPECT_EQ(parms[1].value, -3); - EXPECT_EQ(parms[1].range.has_lower_bound(), false); - EXPECT_EQ(parms[1].range.has_upper_bound(), false); -} - -- GitLab