Skip to content

Commit

Permalink
Remove simulation::inject_events (#2265)
Browse files Browse the repository at this point in the history
This removes `simulation::inject_events` which is made obsolete by
`recipe::event_generators`.
The method exposed internals by giving access to the `lid` of synapses
(over labels) and broke
abstractions (`gid` must be present on this MPI rank and all events must
be deliverable during
the current time (as per documentation)). It was used only in a few
tests and examples and these
uses were replaced by `event_generator`s.
  • Loading branch information
thorstenhater authored Apr 3, 2024
1 parent 08a157f commit 9f20e83
Show file tree
Hide file tree
Showing 9 changed files with 40 additions and 85 deletions.
5 changes: 0 additions & 5 deletions arbor/include/arbor/simulation.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -85,11 +85,6 @@ class ARB_ARBOR_API simulation {
// start of the simulation.
void set_epoch_callback(epoch_function = epoch_function{});

// Add events directly to targets.
// Must be called before calling simulation::run, and must contain events that
// are to be delivered at or after the current simulation time.
void inject_events(const cse_vector& events);

// If remote connections are present, export only the spikes for which this
// predicate returns true.
void set_remote_spike_filter(const spike_predicate&);
Expand Down
7 changes: 0 additions & 7 deletions arbor/include/arbor/spike_event.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,6 @@ ARB_DEFINE_LEXICOGRAPHIC_ORDERING(spike_event,(a.time,a.target,a.weight),(b.time

using pse_vector = std::vector<spike_event>;

struct cell_spike_events {
cell_gid_type target;
pse_vector events;
};

using cse_vector = std::vector<cell_spike_events>;

ARB_ARBOR_API std::ostream& operator<<(std::ostream&, const spike_event&);

} // namespace arb
22 changes: 0 additions & 22 deletions arbor/simulation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -108,8 +108,6 @@ class simulation_state {

void set_remote_spike_filter(const spike_predicate& p) { return communicator_.set_remote_spike_filter(p); }

void inject_events(const cse_vector& events);

time_type min_delay() { return communicator_.min_delay(); }

spike_export_function global_export_callback_;
Expand Down Expand Up @@ -560,22 +558,6 @@ std::vector<probe_metadata> simulation_state::get_probe_metadata(const cell_addr
}
}

void simulation_state::inject_events(const cse_vector& events) {
// Push all events that are to be delivered to local cells into the
// pending event list for the event's target cell.
for (auto& [gid, pse_vector]: events) {
for (auto& e: pse_vector) {
if (e.time < epoch_.t1) {
throw bad_event_time(e.time, epoch_.t1);
}
// gid_to_local_ maps gid to index in local cells and of corresponding cell group.
if (auto lidx = util::value_by_key(gid_to_local_, gid)) {
pending_events_[lidx->cell_index].push_back(e);
}
}
}
}

// Simulation class implementations forward to implementation class.

simulation_builder simulation::create(recipe const & rec) { return {rec}; };
Expand Down Expand Up @@ -639,10 +621,6 @@ void simulation::set_epoch_callback(epoch_function epoch_callback) {
impl_->epoch_callback_ = std::move(epoch_callback);
}

void simulation::inject_events(const cse_vector& events) {
impl_->inject_events(events);
}

simulation::simulation(simulation&&) = default;

simulation::~simulation() = default;
Expand Down
8 changes: 0 additions & 8 deletions doc/cpp/simulation.rst
Original file line number Diff line number Diff line change
Expand Up @@ -100,14 +100,6 @@ Class documentation
Returns a builder object to which the constructor arguments can be passed selectively (see
also example above).

**Experimental inputs:**

.. cpp:function:: void inject_events(const pse_vector& events)

Add events directly to targets.
Must be called before calling :cpp:func:`run`, and must contain events that
are to be delivered at or after the current simulation time.

**Updating Model State:**

.. cpp:function:: void reset()
Expand Down
20 changes: 11 additions & 9 deletions example/single/single.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,10 @@ options parse_options(int argc, char** argv);
arborio::loaded_morphology default_morphology();

struct single_recipe: public arb::recipe {
explicit single_recipe(arborio::loaded_morphology m, arb::cv_policy pol):
morpho(std::move(m.morphology)) {
explicit single_recipe(arborio::loaded_morphology m, arb::cv_policy pol, float w):
morpho(std::move(m.morphology)),
syn_weight{w}
{
gprop.default_parameters = arb::neuron_parameter_defaults;
gprop.default_parameters.discretization = pol;
}
Expand Down Expand Up @@ -74,15 +76,21 @@ struct single_recipe: public arb::recipe {
return arb::cable_cell(morpho, decor, dict);
}

std::vector<arb::event_generator> event_generators(arb::cell_gid_type) const override {
return {arb::explicit_generator_from_milliseconds({"synapse"}, syn_weight, std::vector{1.0})};
}

arb::morphology morpho;
arb::cable_cell_global_properties gprop;
float syn_weight;
};

int main(int argc, char** argv) {
try {
options opt = parse_options(argc, argv);
single_recipe R(opt.swc_file.empty() ? default_morphology() : arborio::load_swc_arbor(opt.swc_file),
opt.policy);
opt.policy,
opt.syn_weight);

arb::simulation sim(R);

Expand All @@ -92,12 +100,6 @@ int main(int argc, char** argv) {
arb::regular_schedule(0.1*arb::units::ms),
arb::make_simple_sampler(traces));

// Trigger the single synapse (target is gid 0, index 0) at t = 1 ms
// with the given weight.
arb::spike_event spike = {0, 1., opt.syn_weight};
arb::cell_spike_events cell_spikes = {0, {spike}};
sim.inject_events({cell_spikes});

sim.run(opt.t_end*arb::units::ms, opt.dt*arb::units::ms);

for (auto entry: traces.at(0)) {
Expand Down
23 changes: 12 additions & 11 deletions example/v_clamp/v-clamp.cpp
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
#include <any>
#include <fstream>
#include <iostream>
#include <stdexcept>
#include <string>
#include <vector>

Expand Down Expand Up @@ -33,7 +31,10 @@ options parse_options(int argc, char** argv);
arborio::loaded_morphology default_morphology();

struct single_recipe: public arb::recipe {
explicit single_recipe(arborio::loaded_morphology m, arb::cv_policy pol): morpho(std::move(m.morphology)) {
explicit single_recipe(arborio::loaded_morphology m, arb::cv_policy pol, float w):
morpho(std::move(m.morphology)),
syn_weight(w)
{
gprop.default_parameters = arb::neuron_parameter_defaults;
gprop.default_parameters.discretization = pol;
}
Expand Down Expand Up @@ -75,15 +76,22 @@ struct single_recipe: public arb::recipe {
return arb::cable_cell(morpho, decor, dict);
}

std::vector<arb::event_generator> event_generators(arb::cell_gid_type) const override {
return {arb::explicit_generator_from_milliseconds({"synapse"}, syn_weight, std::vector{1.0})};
}

std::optional<double> voltage_clamp;
arb::morphology morpho;
arb::cable_cell_global_properties gprop;
float syn_weight;
};

int main(int argc, char** argv) {
try {
options opt = parse_options(argc, argv);
single_recipe R(opt.swc_file.empty()? default_morphology(): arborio::load_swc_arbor(opt.swc_file), opt.policy);
single_recipe R(opt.swc_file.empty()? default_morphology(): arborio::load_swc_arbor(opt.swc_file),
opt.policy,
opt.syn_weight);
R.voltage_clamp = opt.voltage;
arb::simulation sim(R);

Expand All @@ -92,13 +100,6 @@ int main(int argc, char** argv) {
arb::trace_vector<double> traces;
sim.add_sampler(arb::all_probes, arb::regular_schedule(0.1*arb::units::ms), arb::make_simple_sampler(traces));

// Trigger the single synapse (target is gid 0, index 0) at t = 1 ms with
// the given weight.

arb::spike_event spike = {0, 1., opt.syn_weight};
arb::cell_spike_events cell_spikes = {0, {spike}};
sim.inject_events({cell_spikes});

sim.run(opt.t_end*arb::units::ms, opt.dt*arb::units::ms);

for (auto entry: traces.at(0)) {
Expand Down
2 changes: 1 addition & 1 deletion python/example/single_cell_bluepyopt_l5pc.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ def __init__(self, cell, probes):
def num_cells(self):
return 1

# (6.3) Override the num_targets method
# (6.3) Override the cell_kind method
def cell_kind(self, gid):
return arbor.cell_kind.cable

Expand Down
14 changes: 6 additions & 8 deletions test/unit/test_event_delivery.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ using namespace arb;

using n_cable_cell_recipe = homogeneous_recipe<cell_kind::cable, cable_cell>;

constexpr time_type ev_delta_t = 0.2;

struct test_recipe: public n_cable_cell_recipe {
explicit test_recipe(int n): n_cable_cell_recipe(n, test_cell()) {}

Expand All @@ -43,6 +45,10 @@ struct test_recipe: public n_cable_cell_recipe {

return c;
}

std::vector<arb::event_generator> event_generators(arb::cell_gid_type gid) const override {
return {arb::explicit_generator_from_milliseconds({"synapse"}, 1.0f, std::vector{gid*ev_delta_t})};
}
};

using gid_vector = std::vector<cell_gid_type>;
Expand All @@ -66,14 +72,6 @@ std::vector<cell_gid_type> run_test_sim(const recipe& R, const group_gids_type&
spikes.insert(spikes.end(), ss.begin(), ss.end());
});

constexpr time_type ev_delta_t = 0.2;

cse_vector cell_events;
for (unsigned i = 0; i<n; ++i) {
cell_events.push_back({i, {{0u, i*ev_delta_t, 1.f}}});
}

sim.inject_events(cell_events);
sim.run((n+1)*ev_delta_t*arb::units::ms, 0.01*arb::units::ms);

std::vector<cell_gid_type> spike_gids;
Expand Down
24 changes: 10 additions & 14 deletions test/unit/test_lif_cell_group.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,16 @@ class path_recipe: public arb::recipe {
return cell;
}

std::vector<arb::event_generator> event_generators(arb::cell_gid_type gid) const override {
if (gid != 0) return {};
return {arb::explicit_generator_from_milliseconds({"tgt"},
1000.0, // use a large weight to trigger spikes
std::vector{ 1.0, // First event to trigger the spike
1.1, // inside refractory period; should be ignored
50.0 // long after previous event; should trigger new spike
})};
}

private:
cell_size_type ncells_;
float weight_, delay_;
Expand Down Expand Up @@ -177,20 +187,6 @@ TEST(lif_cell_group, spikes) {
auto decomp = partition_load_balance(recipe, context);
simulation sim(recipe, context, decomp);

cse_vector events;

// First event to trigger the spike (first neuron).
events.push_back({0, {{0, 1, 1000}}});

// This event happens inside the refractory period of the previous
// event, thus, should be ignored (first neuron)
events.push_back({0, {{0, 1.1, 1000}}});

// This event happens long after the refractory period of the previous
// event, should thus trigger new spike (first neuron).
events.push_back({0, {{0, 50, 1000}}});

sim.inject_events(events);
sim.run(100*U::ms, 0.01*U::ms);

// we expect 4 spikes: 2 by both neurons
Expand Down

0 comments on commit 9f20e83

Please sign in to comment.