diff --git a/nrn/generate_validation_data.sh b/nrn/generate_validation_data.sh new file mode 100755 index 0000000000000000000000000000000000000000..8627a0c56ecd1f2137178a193be99207cb06ef46 --- /dev/null +++ b/nrn/generate_validation_data.sh @@ -0,0 +1,2 @@ +python2.7 soma.py + diff --git a/nrn/soma.py b/nrn/soma.py index f8912c4f7a0ea6bc204695cbef683b01e5172e44..0e73ad624123ec70aed3e9d6dba4747524cd3c17 100644 --- a/nrn/soma.py +++ b/nrn/soma.py @@ -1,7 +1,18 @@ import os.path -from neuron import h, gui from matplotlib import pyplot import numpy as np +import json +import argparse +from neuron import gui, h + +parser = argparse.ArgumentParser(description='generate spike train info for a soma with hh channels') +parser.add_argument('--plot', action='store_true', dest='plot') +args = parser.parse_args() + +if args.plot : + print '-- plotting turned on' +else : + print '-- plotting turned off' soma = h.Section(name='soma') @@ -17,51 +28,43 @@ stim.delay = 10 stim.dur = 100 stim.amp = 0.1 +spike_counter = h.APCount(soma(0.5)) +spike_counter.thresh = 0 + v_vec = h.Vector() # Membrane potential vector t_vec = h.Vector() # Time stamp vector +s_vec = h.Vector() # Time stamp vector v_vec.record(soma(0.5)._ref_v) t_vec.record(h._ref_t) +spike_counter.record(s_vec) + simdur = 120 # initialize plot -pyplot.figure(figsize=(8,4)) # Default figsize is (8,6) - -pyplot.subplot(2,1,1) -pyplot.grid() +if args.plot : + pyplot.figure(figsize=(8,4)) # Default figsize is (8,6) h.tstop = simdur # run neuron with multiple dt - -for dt in [0.02, 0.01, 0.005, 0.002, 0.001]: +results = [] +#for dt in [0.02, 0.01, 0.005, 0.0005, 0.0001]: +for dt in [0.02, 0.0001]: h.dt = dt h.run() - pyplot.plot(t_vec, v_vec, label='neuron ' + str(dt)) - #pyplot.plot(t_vec, v_vec, 'k', label='neuron ' + str(dt)) - -pyplot.xlim([102.5,105]) -pyplot.ylim([0,40]) - -pyplot.legend() -pyplot.subplot(2,1,2) -pyplot.grid() -step = 0 -while os.path.isfile('../tests/v_' + str(step) + '.dat') : - fname = '../tests/v_' + str(step) + '.dat' - print 'loading ' + fname - data = np.loadtxt(fname) - t = data[:,0] - v = data[:,1] - #pyplot.plot(t, v, 'b', label=fname) - pyplot.plot(t, v, label=fname) - step = step + 1 - -pyplot.xlabel('time (ms)') -pyplot.ylabel('mV') - -pyplot.xlim([102.5,105]) -pyplot.ylim([0,40]) - -pyplot.legend() -pyplot.show() + results.append({"dt": dt, "spikes": s_vec.to_python()}) + if args.plot : + pyplot.plot(t_vec, v_vec, label='neuron ' + str(dt)) + +# save the spike info as in json format +fp = open('soma.json', 'w') +json.dump(results, fp, indent=1) + +if args.plot : + pyplot.xlabel('time (ms)') + pyplot.ylabel('mV') + pyplot.xlim([0, 120]) + pyplot.grid() + pyplot.legend() + pyplot.show() diff --git a/src/fvm.hpp b/src/fvm.hpp index 19b27c45268f8be09a4d10e9a79adf2a5d714ac6..833c8cd15953f93d49f9e9ff9c67c2ba43674396 100644 --- a/src/fvm.hpp +++ b/src/fvm.hpp @@ -257,8 +257,6 @@ fvm_cell<T, I>::fvm_cell(nest::mc::cell const& cell) cv_capacitance_[i] /= cv_areas_[i]; } - std::cout << "capacitance " << cv_capacitance_ << "\n"; - ///////////////////////////////////////////// // create mechanisms ///////////////////////////////////////////// diff --git a/tests/util.hpp b/tests/util.hpp index cf10847fbf0de27657be11eb54b545538c3799b5..873bc2055fb6d41f2fda60887223a37a8ec60556 100644 --- a/tests/util.hpp +++ b/tests/util.hpp @@ -3,7 +3,7 @@ #include <string> #include <vector> -static +[[gnu::unused]] static void write_vis_file(const std::string& fname, std::vector<std::vector<double>> values) { auto m = values.size(); @@ -28,3 +28,30 @@ void write_vis_file(const std::string& fname, std::vector<std::vector<double>> v } } +template <typename T> +std::vector<T> find_spikes(std::vector<T> const& v, T threshold, T dt) +{ + if(v.size()<2) { + return {}; + } + bool is_spiking = v[0] >= threshold; + auto it = v.begin() + 1; + + std::vector<T> times; + for(auto i=1u; i<v.size(); ++i) { + if(is_spiking && v[i]<threshold) { + is_spiking = false; + } + else { + if(*it>=threshold) { + is_spiking = true; + auto pos = (threshold-v[i-1]) / (v[i]-v[i-1]); + times.push_back((i-1+pos)*dt); + } + } + } + + + return times; +} + diff --git a/tests/validate_soma.cpp b/tests/validate_soma.cpp index b88c09f40b7426d54b06047cb290c993cb9083d5..70fe80c384e55a9b88c55aff7e020f7c6100bf65 100644 --- a/tests/validate_soma.cpp +++ b/tests/validate_soma.cpp @@ -3,13 +3,16 @@ #include "gtest.h" #include "util.hpp" -#include "../src/cell.hpp" -#include "../src/fvm.hpp" +#include <cell.hpp> +#include <fvm.hpp> + +#include <json/src/json.hpp> // based on hh/Neuron/steps_A.py TEST(soma, resolutions) { using namespace nest::mc; + using namespace nlohmann; nest::mc::cell cell; @@ -22,15 +25,34 @@ TEST(soma, resolutions) 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); - auto i =0; - for(auto dt : {0.02, 0.01, 0.005, 0.002, 0.001}) { - std::vector<std::vector<double>> results(2); + // load data from file + std::string input_name = "../nrn/soma.json"; + json cell_data; + { + auto fid = std::ifstream(input_name); + if(!fid.is_open()) { + std::cerr << "error : unable to open file " << input_name + << " : run the validation generation script first\n"; + return; + } + + try { + fid >> cell_data; + } + catch (...) { + std::cerr << "error : incorrectly formatted json file " << input_name << "\n"; + return; + } + } + + for(auto& run : cell_data) { + std::vector<double> v; + double dt = run["dt"]; // set initial conditions using memory::all; @@ -40,16 +62,16 @@ TEST(soma, resolutions) // run the simulation auto tfinal = 120.; // ms int nt = tfinal/dt; - results[0].push_back(0.); - results[1].push_back(model.voltage()[0]); + v.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]); + v.push_back(model.voltage()[0]); } - write_vis_file("v_" + std::to_string(i) + ".dat", results); - ++i; + + std::cout << v << "\n"; + auto spike_times = find_spikes(v, 0., dt); + std::cout << "dt " << dt << " : spikes " << spike_times << "\n"; } }