Select Git revision
akuesters
authored and
Ben Cumming
committed
Add docs for Python wrapper to ReadTheDocs: - Overview, Common Types, Hardware Management, Recipes, Domain Decomposition, Simulations, Metering - Installing Arbor: Optional Requirements (Python), Buidling and Installing (Python Frontend), and Installation (Python Module) Missing (, since not implemented yet): - probes - arbor-sup - hint maps in domain_decomposition - reset, events, empty schedule in event_generator Also does not cover unit testing (since doc is user-centric). Makes also defaults and units in wrapper consistent. Fixes #766
spikes.cpp 3.08 KiB
#include <memory>
#include <vector>
#include <pybind11/pybind11.h>
#include <pybind11/stl.h>
#include <arbor/spike.hpp>
#include <arbor/simulation.hpp>
#include "strprintf.hpp"
namespace pyarb {
// A functor that models arb::spike_export_function.
// Holds a shared pointer to the spike_vec used to store the spikes, so that if
// the spike_vec in spike_recorder is garbage collected in Python, stores will
// not seg fault.
struct spike_callback {
using spike_vec = std::vector<arb::spike>;
std::shared_ptr<spike_vec> spike_store;
spike_callback(const std::shared_ptr<spike_vec>& state):
spike_store(state)
{}
void operator() (const spike_vec& spikes) {
spike_store->insert(spike_store->end(), spikes.begin(), spikes.end());
};
};
// Helper type for recording spikes from a simulation.
// This type is wrapped in Python, to expose spike_recorder::spike_store.
struct spike_recorder {
using spike_vec = std::vector<arb::spike>;
std::shared_ptr<spike_vec> spike_store;
spike_callback callback() {
// initialize the spike_store
spike_store = std::make_shared<spike_vec>();
// The callback holds a copy of spike_store, i.e. the shared
// pointer is held by both the spike_recorder and the callback, so if
// the spike_recorder is destructed in the calling Python code, attempts
// to write to spike_store inside the callback will not seg fault.
return spike_callback(spike_store);
}
const spike_vec& spikes() const {
return *spike_store;
}
};
std::shared_ptr<spike_recorder> attach_spike_recorder(arb::simulation& sim) {
auto r = std::make_shared<spike_recorder>();
sim.set_global_spike_callback(r->callback());
return r;
}
std::string spike_str(const arb::spike& s) {
return util::pprintf(
"<arbor.spike: source ({},{}), time {} ms>",
s.source.gid, s.source.index, s.time);
}
void register_spike_handling(pybind11::module& m) {
using namespace pybind11::literals;
pybind11::class_<arb::spike> spike(m, "spike");
spike .def(pybind11::init<>())
.def_readwrite("source", &arb::spike::source, "The spike source (type: cell_member).")
.def_readwrite("time", &arb::spike::time, "The spike time [ms].")
.def("__str__", &spike_str)
.def("__repr__", &spike_str);
// Use shared_ptr for spike_recorder, so that all copies of a recorder will
// see the spikes from the simulation with which the recorder's callback has been
// registered.
pybind11::class_<spike_recorder, std::shared_ptr<spike_recorder>> sprec(m, "spike_recorder");
sprec
.def(pybind11::init<>())
.def_property_readonly("spikes", &spike_recorder::spikes, "A list of the recorded spikes.");
m.def("attach_spike_recorder", &attach_spike_recorder,
"sim"_a,
"Attach a spike recorder to an arbor simulation.\n"
"The recorder that is returned will record all spikes generated after it has been\n"
"attached (spikes generated before attaching are not recorded).");
}
} // namespace pyarb