diff --git a/example/dryrun/dryrun.cpp b/example/dryrun/dryrun.cpp index 0ef5193d1aa5038ace8653cc9ee2177a3ee4fdb3..54757996001288c742fce0bf2c1dca343f078ad2 100644 --- a/example/dryrun/dryrun.cpp +++ b/example/dryrun/dryrun.cpp @@ -18,6 +18,7 @@ #include <arbor/morph/primitives.hpp> #include <arbor/profile/meter_manager.hpp> #include <arbor/profile/profiler.hpp> +#include <arbor/simple_sampler.hpp> #include <arbor/simulation.hpp> #include <arbor/symmetric_recipe.hpp> #include <arbor/recipe.hpp> @@ -44,6 +45,7 @@ struct run_params { cell_parameters cell; }; +void write_trace_json(const arb::trace_data<double>& trace); run_params read_options(int argc, char** argv); using arb::cell_gid_type; @@ -115,7 +117,7 @@ public: std::vector<arb::event_generator> event_generators(cell_gid_type gid) const override { std::vector<arb::event_generator> gens; if (gid%20 == 0) { - gens.push_back(arb::explicit_generator(arb::pse_vector{{{gid, 0}, 0.1, 1.0}})); + gens.push_back(arb::explicit_generator(arb::pse_vector{{{gid, 0}, 1.0, event_weight_}})); } return gens; } @@ -130,7 +132,7 @@ private: cell_size_type num_tiles_; cell_parameters cell_params_; double min_delay_; - float event_weight_ = 0.01; + float event_weight_ = 0.05; }; int main(int argc, char** argv) { @@ -186,6 +188,15 @@ int main(int argc, char** argv) { // Construct the model. arb::simulation sim(recipe, decomp, ctx); + // The id of the only probe on the cell: the cell_member type points to (cell 0, probe 0) + auto probe_id = cell_member_type{0, 0}; + // The schedule for sampling is 10 samples every 1 ms. + auto sched = arb::regular_schedule(1); + // This is where the voltage samples will be stored as (time, value) pairs + arb::trace_vector<double> voltage; + // Now attach the sampler at probe_id, with sampling schedule sched, writing to voltage + sim.add_sampler(arb::one_probe(probe_id), sched, arb::make_simple_sampler(voltage)); + // Set up recording of spikes to a vector on the root process. std::vector<arb::spike> recorded_spikes; if (root) { @@ -221,6 +232,8 @@ int main(int argc, char** argv) { fid.write(linebuf, n); } } + // Write the samples to a json file. + write_trace_json(voltage.at(0)); } auto profile = arb::profile::profiler_summary(); @@ -237,6 +250,27 @@ int main(int argc, char** argv) { return 0; } +void write_trace_json(const arb::trace_data<double>& trace) { + std::string path = "./voltages.json"; + + nlohmann::json json; + json["name"] = "ring demo"; + json["units"] = "mV"; + json["cell"] = "0.0"; + json["probe"] = "0"; + + auto& jt = json["data"]["time"]; + auto& jy = json["data"]["voltage"]; + + for (const auto& sample: trace) { + jt.push_back(sample.t); + jy.push_back(sample.v); + } + + std::ofstream file(path); + file << std::setw(1) << json << "\n"; +} + run_params read_options(int argc, char** argv) { using sup::param_from_json; diff --git a/python/example/ring.py b/python/example/ring.py index 8ddaaf54e31d0efcc2d48f76bb43aee6f31c8d8c..17d01f1033abc998ccfdd6a8de5cda230c357077 100644 --- a/python/example/ring.py +++ b/python/example/ring.py @@ -33,12 +33,12 @@ def make_cable_cell(gid): cell = b.build() # Put hh dynamics on soma, and passive properties on the dendrites. - cell.paint('soma', 'hh') - cell.paint('dend', 'pas') + cell.paint('"soma"', 'hh') + cell.paint('"dend"', 'pas') # Attach a single synapse. - cell.place('synapse_site', 'expsyn') + cell.place('"synapse_site"', 'expsyn') # Attach a spike detector with threshold of -10 mV. - cell.place('root', arbor.spike_detector(-10)) + cell.place('"root"', arbor.spike_detector(-10)) return cell @@ -84,13 +84,9 @@ class ring_recipe (arbor.recipe): return [arbor.event_generator(arbor.cell_member(0,0), 0.1, sched)] return [] - # Define one probe (for measuring voltage at the soma) on each cell. - def num_probes(self, gid): - return 1 - - def get_probe(self, id): + def get_probes(self, gid): loc = arbor.location(0, 0) # at the soma - return arbor.cable_probe('voltage', id, loc) + return [arbor.cable_probe('voltage', loc)] context = arbor.context(threads=12, gpu_id=None) print(context) diff --git a/python/example/single_cell_builder.py b/python/example/single_cell_builder.py index 58e7054cacfa12343c85f0f390a00400cedb36bd..98ce339b22737f725fc2cd0ee0f82f2e6f9f54f6 100644 --- a/python/example/single_cell_builder.py +++ b/python/example/single_cell_builder.py @@ -64,7 +64,7 @@ cell.place('"stim_site"', arbor.iclamp( 10, 2, 0.8)) cell.place('"stim_site"', arbor.iclamp( 50, 2, 0.8)) cell.place('"stim_site"', arbor.iclamp( 80, 2, 0.8)) # Add a spike detector with threshold of -10 mV. -cell.place('root', arbor.spike_detector(-10)) +cell.place('"root"', arbor.spike_detector(-10)) # Make single cell model. m = arbor.single_cell_model(cell) diff --git a/python/example/single_cell_swc.py b/python/example/single_cell_swc.py index 957dc8bfa978cd745d4047cdf687102d3ecc09c3..f50768bb6e7c384d345e4b833595ef3d6e8aab9d 100644 --- a/python/example/single_cell_swc.py +++ b/python/example/single_cell_swc.py @@ -14,9 +14,7 @@ from arbor import location as loc import matplotlib.pyplot as plt # Load a cell morphology from an swc file. -# The model has 31 branches, including soma, dendrites and axon. -#tree = arbor.load_swc('../../test/unit/swc/example.swc') -tree = arbor.load_swc('example.swc') +tree = arbor.load_swc('../../test/unit/swc/pyramidal.swc') # Define the regions and locsets in the model. defs = {'soma': '(tag 1)', # soma has tag 1 in swc files. @@ -30,7 +28,7 @@ labels = arbor.label_dict(defs) # Combine morphology with region and locset definitions to make a cable cell. cell = arbor.cable_cell(tree, labels) -print(cell.locations('axon_end')) +print(cell.locations('"axon_end"')) # Set initial membrane potential to -55 mV cell.set_properties(Vm=-55) @@ -44,8 +42,8 @@ cell.paint('"dend"', 'pas') # Increase resistivity on dendrites. cell.paint('"dend"', rL=500) # Attach stimuli that inject 0.8 nA currents for 1 ms, starting at 3 and 8 ms. -cell.place('"stim_site"', arbor.iclamp(3, 1, current=0.5)) -cell.place('"stim_site"', arbor.iclamp(8, 1, current=1)) +cell.place('"stim_site"', arbor.iclamp(3, 1, current=2)) +cell.place('"stim_site"', arbor.iclamp(8, 1, current=4)) # Detect spikes at the soma with a voltage threshold of -10 mV. cell.place('"root"', arbor.spike_detector(-10)) @@ -56,10 +54,10 @@ cell.compartments_on_segments() m = arbor.single_cell_model(cell) # Attach voltage probes that sample at 50 kHz. -m.probe('voltage', where='root', frequency=50000) +m.probe('voltage', where='"root"', frequency=50000) m.probe('voltage', where=loc(2,1), frequency=50000) -m.probe('voltage', where='stim_site', frequency=50000) -m.probe('voltage', where='axon_end', frequency=50000) +m.probe('voltage', where='"stim_site"', frequency=50000) +m.probe('voltage', where='"axon_end"', frequency=50000) # Simulate the cell for 15 ms. tfinal=15 diff --git a/python/recipe.cpp b/python/recipe.cpp index 45c5cfa3b2bf34a2dfca9e9da58dba816d0ad306..922f47e550c9d4b75ebd2e989013dccff2370297 100644 --- a/python/recipe.cpp +++ b/python/recipe.cpp @@ -29,7 +29,7 @@ arb::util::unique_any py_recipe_shim::get_cell_description(arb::cell_gid_type gi "Python error already thrown"); } -arb::probe_info cable_loc_probe(std::string kind, arb::cell_member_type id, arb::mlocation loc) { +arb::probe_info cable_loc_probe(std::string kind, arb::mlocation loc) { if (kind == "voltage") { return arb::cable_probe_membrane_voltage{loc}; } @@ -170,9 +170,9 @@ void register_recipe(pybind11::module& m) { // Probes m.def("cable_probe", &cable_loc_probe, - "Description of a probe at a location on a cable cell with id available for monitoring data of kind "\ + "Description of a probe at a location available for monitoring data of kind "\ "where kind is one of 'voltage' or 'ionic current density'.", - "kind"_a, "id"_a, "location"_a); + "kind"_a, "location"_a); pybind11::class_<arb::probe_info> probe(m, "probe"); probe