Skip to content
Snippets Groups Projects
Unverified Commit bf842fdc authored by Thorsten Hater's avatar Thorsten Hater Committed by GitHub
Browse files

Allow multiple schedules per source_cell. (#1963)

Spike source cells can now generate events based on the interleaving of arbitrarily many schedules.
This should simplify the required connectivity.
parent 93f13310
No related branches found
No related tags found
No related merge requests found
......@@ -11,10 +11,12 @@ namespace arb {
struct ARB_SYMBOL_VISIBLE spike_source_cell {
cell_tag_type source; // Label of source.
schedule seq;
std::vector<schedule> seqs;
spike_source_cell() = delete;
spike_source_cell(cell_tag_type source, schedule seq): source(std::move(source)), seq(std::move(seq)) {};
template<typename... Seqs>
spike_source_cell(cell_tag_type source, Seqs&&... seqs): source(std::move(source)), seqs{std::forward<Seqs>(seqs)...} {}
spike_source_cell(cell_tag_type source, std::vector<schedule> seqs): source(std::move(source)), seqs(std::move(seqs)) {}
};
} // namespace arb
......@@ -26,13 +26,13 @@ spike_source_cell_group::spike_source_cell_group(
}
}
time_sequences_.reserve(gids_.size());
time_sequences_.reserve(gids.size());
for (auto gid: gids_) {
cg_sources.add_cell();
cg_targets.add_cell();
try {
auto cell = util::any_cast<spike_source_cell>(rec.get_cell_description(gid));
time_sequences_.push_back(std::move(cell.seq));
time_sequences_.emplace_back(cell.seqs);
cg_sources.add_label(cell.source, {0, 1});
}
catch (std::bad_any_cast& e) {
......@@ -51,8 +51,10 @@ void spike_source_cell_group::advance(epoch ep, time_type dt, const event_lane_s
for (auto i: util::count_along(gids_)) {
const auto gid = gids_[i];
for (auto t: util::make_range(time_sequences_[i].events(ep.t0, ep.t1))) {
spikes_.push_back({{gid, 0u}, t});
for (auto& ts: time_sequences_[i]) {
for (auto &t: util::make_range(ts.events(ep.t0, ep.t1))) {
spikes_.push_back({{gid, 0u}, t});
}
}
}
......@@ -60,8 +62,10 @@ void spike_source_cell_group::advance(epoch ep, time_type dt, const event_lane_s
};
void spike_source_cell_group::reset() {
for (auto& s: time_sequences_) {
s.reset();
for (auto& ss: time_sequences_) {
for(auto& s: ss) {
s.reset();
}
}
clear_spikes();
}
......
......@@ -40,7 +40,7 @@ public:
private:
std::vector<spike> spikes_;
std::vector<cell_gid_type> gids_;
std::vector<schedule> time_sequences_;
std::vector<std::vector<schedule>> time_sequences_;
};
} // namespace arb
......
......@@ -115,3 +115,43 @@ TEST(spike_source, exhaust)
test_seq(regular_schedule(0, 1, 5));
test_seq(explicit_schedule({0.3, 2.3, 4.7}));
}
TEST(spike_source, multiple)
{
// This test assumes that seq will exhaust itself before t=10 ms.
auto test_seq = [](auto&&... seqs) {
std::vector<schedule> schedules{seqs...};
ss_recipe rec(1u, spike_source_cell("src", static_cast<decltype(seqs)&&>(seqs)...));
cell_label_range srcs, tgts;
spike_source_cell_group group({0}, rec, srcs, tgts);
// epoch ending at 10ms
epoch ep(0, 0., 10.);
group.advance(ep, 1, {});
auto expected = spike_times(group.spikes());
std::sort(expected.begin(), expected.end());
auto actual = std::vector<time_type>{};
for (auto& schedule: schedules) {
auto ts = as_vector(schedule.events(0, 10));
actual.insert(actual.end(),
ts.begin(), ts.end());
}
std::sort(actual.begin(), actual.end());
EXPECT_EQ(expected, actual);
// Check that the last spike was before the end of the epoch.
EXPECT_LT(group.spikes().back().time, time_type(10));
};
auto seqs = std::vector<schedule>{regular_schedule(0, 1, 5),
explicit_schedule({0.3, 2.3, 4.7})};
test_seq(seqs);
test_seq(std::vector<schedule>{regular_schedule(0, 1, 5),
explicit_schedule({0.3, 2.3, 4.7})});
test_seq(regular_schedule(0, 1, 5),
explicit_schedule({0.3, 2.3, 4.7}));
auto reg_sched = regular_schedule(0, 1, 5);
test_seq(reg_sched, explicit_schedule({0.3, 2.3, 4.7}));
}
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment