From db0041a59507d26ae6fe8bafe9a9b63c2806a826 Mon Sep 17 00:00:00 2001 From: Nora Abi Akar <nora.abiakar@gmail.com> Date: Mon, 29 Mar 2021 17:23:41 +0200 Subject: [PATCH] Remove `gid` attribute of target of a connection, and local gap-junction site of a gap-junction connection (#1467) * Change the type of the target of a `connection` from `cell_member_type` to `cell_lid_type`. The target cell's gid is always known in both the recipe and simulation. * Change the type of the local site of a `gap_junction_connection` from `cell_member_type` to `cell_lid_type`, and make it such that the first argument of the connection is the peer site, and the second the local site. The local cell's gid is always known in both the recipe and simulation. * Change the type of the target of an `event_generator` from `cell_member_type` to `cell_lid_type`. The target cell's gid is always known in both the recipe and simulation. * New `cell_spike_events` and `cse_vector` for `simulation::inject_events`. * Simplify recipe sanity checks and remove associated exception types. * Fix unit tests, examples, docs --- arbor/arbexcept.cpp | 17 --- arbor/communication/communicator.cpp | 7 +- arbor/connection.hpp | 6 +- arbor/fvm_lowered_cell_impl.hpp | 27 ++-- arbor/include/arbor/arbexcept.hpp | 15 --- arbor/include/arbor/event_generator.hpp | 22 +-- arbor/include/arbor/recipe.hpp | 13 +- arbor/include/arbor/simulation.hpp | 2 +- arbor/include/arbor/spike_event.hpp | 9 +- arbor/mc_cell_group.cpp | 2 +- arbor/merge_events.cpp | 2 +- arbor/partition_load_balance.cpp | 11 +- arbor/simulation.cpp | 29 ++-- arbor/symmetric_recipe.cpp | 1 - doc/concepts/interconnectivity.rst | 5 +- doc/cpp/interconnectivity.rst | 34 +++-- doc/cpp/recipe.rst | 9 +- doc/python/cell.rst | 2 +- doc/python/interconnectivity.rst | 46 +++++-- doc/python/recipe.rst | 49 ++++--- doc/tutorial/network_ring.rst | 4 +- example/bench/bench.cpp | 2 +- example/brunel/brunel.cpp | 6 +- example/dryrun/dryrun.cpp | 4 +- example/gap_junctions/gap_junctions.cpp | 6 +- example/generators/generators.cpp | 12 +- example/lfp/lfp.cpp | 2 +- example/ring/ring.cpp | 4 +- example/single/single.cpp | 5 +- python/event_generator.cpp | 2 +- python/event_generator.hpp | 6 +- python/example/brunel.py | 7 +- python/example/network_ring.py | 4 +- python/example/single_cell_stdp.py | 6 +- python/recipe.cpp | 14 +- test/unit-distributed/test_communicator.cpp | 8 +- .../test_domain_decomposition.cpp | 20 +-- test/unit/test_domain_decomposition.cpp | 38 +++--- test/unit/test_event_delivery.cpp | 7 +- test/unit/test_event_generators.cpp | 30 ++--- test/unit/test_event_queue.cpp | 15 +-- test/unit/test_fvm_lowered.cpp | 62 ++++----- test/unit/test_lif_cell_group.cpp | 14 +- test/unit/test_merge_events.cpp | 124 ++++++++--------- test/unit/test_probe.cpp | 6 +- test/unit/test_recipe.cpp | 125 ++++++------------ test/unit/test_simulation.cpp | 4 +- 47 files changed, 394 insertions(+), 451 deletions(-) diff --git a/arbor/arbexcept.cpp b/arbor/arbexcept.cpp index e27f04fa..2a384b51 100644 --- a/arbor/arbexcept.cpp +++ b/arbor/arbexcept.cpp @@ -43,22 +43,12 @@ bad_connection_source_lid::bad_connection_source_lid(cell_gid_type gid, cell_lid gid(gid), src_lid(src_lid), num_sources(num_sources) {} -bad_connection_target_gid::bad_connection_target_gid(cell_gid_type gid, cell_gid_type tgt_gid): - arbor_exception(pprintf("Model building error on cell {}: connection target gid {} has to match cell gid {}].", gid, tgt_gid, gid)), - gid(gid), tgt_gid(tgt_gid) -{} - bad_connection_target_lid::bad_connection_target_lid(cell_gid_type gid, cell_lid_type tgt_lid, cell_size_type num_targets): arbor_exception(pprintf("Model building error on cell {}: connection target index {} is out of range. Cell {} has {} targets", gid, tgt_lid, gid, num_targets) + (num_targets ? pprintf(", in the range [{}:{}].", 0, num_targets-1) : ".")), gid(gid), tgt_lid(tgt_lid), num_targets(num_targets) {} -bad_event_generator_target_gid::bad_event_generator_target_gid(cell_gid_type gid, cell_gid_type tgt_gid): - arbor_exception(pprintf("Model building error on cell {}: event_generator target gid {} has to match cell gid {}].", gid, tgt_gid, gid)), - gid(gid), tgt_gid(tgt_gid) -{} - bad_event_generator_target_lid::bad_event_generator_target_lid(cell_gid_type gid, cell_lid_type tgt_lid, cell_size_type num_targets): arbor_exception(pprintf("Model building error on cell {}: event_generator target index {} is out of range. Cell {} has {} targets", gid, tgt_lid, gid, num_targets) + (num_targets ? pprintf(", in the range [{}:{}].", 0, num_targets-1) : ".")), @@ -81,13 +71,6 @@ gj_unsupported_domain_decomposition::gj_unsupported_domain_decomposition(cell_gi gid_1(gid_1) {} -bad_gj_connection_gid::bad_gj_connection_gid(cell_gid_type gid, cell_gid_type site_0, cell_gid_type site_1): - arbor_exception(pprintf("Model building error on cell {}: recipe::gap_junctions_on(gid={}) -> cell {} <-> cell{}: one of the sites must be on the cell with gid = {})", gid, gid, site_0, site_1, gid)), - gid(gid), - site_0(site_0), - site_1(site_1) -{} - bad_gj_connection_lid::bad_gj_connection_lid(cell_gid_type gid, cell_member_type site): arbor_exception(pprintf("Model building error on cell {}: gap junction index {} on cell {} does not exist)", gid, site.gid, site.index)), gid(gid), diff --git a/arbor/communication/communicator.cpp b/arbor/communication/communicator.cpp index 032f09c4..b93638f8 100644 --- a/arbor/communication/communicator.cpp +++ b/arbor/communication/communicator.cpp @@ -87,11 +87,8 @@ communicator::communicator(const recipe& rec, if (c.source.index >= num_sources) { throw arb::bad_connection_source_lid(cell.gid, c.source.index, num_sources); } - if (c.dest.gid != cell.gid) { - throw arb::bad_connection_target_gid(cell.gid, c.dest.gid); - } - if (c.dest.index >= num_targets) { - throw arb::bad_connection_target_lid(cell.gid, c.dest.index, num_targets); + if (c.dest >= num_targets) { + throw arb::bad_connection_target_lid(cell.gid, c.dest, num_targets); } const auto src = dom_dec.gid_domain(c.source.gid); src_domains.push_back(src); diff --git a/arbor/connection.hpp b/arbor/connection.hpp index 4a9fe0fc..05be9556 100644 --- a/arbor/connection.hpp +++ b/arbor/connection.hpp @@ -11,7 +11,7 @@ class connection { public: connection() = default; connection( cell_member_type src, - cell_member_type dest, + cell_lid_type dest, float w, float d, cell_gid_type didx=cell_gid_type(-1)): @@ -26,7 +26,7 @@ public: time_type delay() const { return delay_; } cell_member_type source() const { return source_; } - cell_member_type destination() const { return destination_; } + cell_lid_type destination() const { return destination_; } cell_size_type index_on_domain() const { return index_on_domain_; } spike_event make_event(const spike& s) { @@ -35,7 +35,7 @@ public: private: cell_member_type source_; - cell_member_type destination_; + cell_lid_type destination_; float weight_; float delay_; cell_size_type index_on_domain_; diff --git a/arbor/fvm_lowered_cell_impl.hpp b/arbor/fvm_lowered_cell_impl.hpp index 6086383f..8bdc287d 100644 --- a/arbor/fvm_lowered_cell_impl.hpp +++ b/arbor/fvm_lowered_cell_impl.hpp @@ -644,20 +644,14 @@ std::vector<fvm_gap_junction> fvm_lowered_cell_impl<Backend>::fvm_gap_junctions( for (auto gid: gids) { auto gj_list = rec.gap_junctions_on(gid); for (auto g: gj_list) { - if (gid != g.local.gid && gid != g.peer.gid) { - throw arb::bad_gj_connection_gid(gid, g.local.gid, g.peer.gid); - } - if (g.local.index >= gid_to_cvs[g.local.gid].size()) { - throw arb::bad_gj_connection_lid(gid, g.local); + if (g.local >= gid_to_cvs[gid].size()) { + throw arb::bad_gj_connection_lid(gid, {gid, g.local}); } if (g.peer.index >= gid_to_cvs[g.peer.gid].size()) { throw arb::bad_gj_connection_lid(gid, g.peer); } - auto cv0 = gid_to_cvs[g.local.gid][g.local.index]; + auto cv0 = gid_to_cvs[gid][g.local]; auto cv1 = gid_to_cvs[g.peer.gid][g.peer.index]; - if (gid != g.local.gid) { - std::swap(cv0, cv1); - } v.push_back(fvm_gap_junction(std::make_pair(cv0, cv1), g.ggap * 1e3 / D.cv_area[cv0])); } } @@ -694,18 +688,13 @@ fvm_size_type fvm_lowered_cell_impl<Backend>::fvm_intdom( cell_to_intdom[gid_to_loc[g]] = intdom_id; for (auto gj: rec.gap_junctions_on(g)) { - cell_gid_type peer = - gj.local.gid==g? gj.peer.gid: - gj.peer.gid==g? gj.local.gid: - throw bad_cell_description(cell_kind::cable, g); - - if (!gid_to_loc.count(peer)) { - throw gj_unsupported_domain_decomposition(g, peer); + if (!gid_to_loc.count(gj.peer.gid)) { + throw gj_unsupported_domain_decomposition(g, gj.peer.gid); } - if (!visited.count(peer)) { - visited.insert(peer); - intdomq.push(peer); + if (!visited.count(gj.peer.gid)) { + visited.insert(gj.peer.gid); + intdomq.push(gj.peer.gid); } } } diff --git a/arbor/include/arbor/arbexcept.hpp b/arbor/include/arbor/arbexcept.hpp index 814c628f..2cc0c5ed 100644 --- a/arbor/include/arbor/arbexcept.hpp +++ b/arbor/include/arbor/arbexcept.hpp @@ -67,11 +67,6 @@ struct bad_connection_source_lid: arbor_exception { cell_size_type num_sources; }; -struct bad_connection_target_gid: arbor_exception { - bad_connection_target_gid(cell_gid_type gid, cell_gid_type tgt_gid); - cell_gid_type gid, tgt_gid; -}; - struct bad_connection_target_lid: arbor_exception { bad_connection_target_lid(cell_gid_type gid, cell_lid_type tgt_lid, cell_size_type num_targets); cell_gid_type gid; @@ -79,11 +74,6 @@ struct bad_connection_target_lid: arbor_exception { cell_size_type num_targets; }; -struct bad_event_generator_target_gid: arbor_exception { - bad_event_generator_target_gid(cell_gid_type gid, cell_gid_type tgt_gid); - cell_gid_type gid, tgt_gid; -}; - struct bad_event_generator_target_lid: arbor_exception { bad_event_generator_target_lid(cell_gid_type gid, cell_lid_type tgt_lid, cell_size_type num_targets); cell_gid_type gid; @@ -106,11 +96,6 @@ struct gj_kind_mismatch: arbor_exception { cell_gid_type gid_0, gid_1; }; -struct bad_gj_connection_gid: arbor_exception { - bad_gj_connection_gid(cell_gid_type gid, cell_gid_type site_0, cell_gid_type site_1); - cell_gid_type gid, site_0, site_1; -}; - struct bad_gj_connection_lid: arbor_exception { bad_gj_connection_lid(cell_gid_type gid, cell_member_type site); cell_gid_type gid; diff --git a/arbor/include/arbor/event_generator.hpp b/arbor/include/arbor/event_generator.hpp index 4e526b58..95a52452 100644 --- a/arbor/include/arbor/event_generator.hpp +++ b/arbor/include/arbor/event_generator.hpp @@ -68,7 +68,7 @@ struct empty_generator { event_seq events(time_type, time_type) { return {nullptr, nullptr}; } - std::vector<cell_member_type> targets() { + std::vector<cell_lid_type> targets() { return {}; }; }; @@ -102,7 +102,7 @@ public: return impl_->events(t0, t1); } - std::vector<cell_member_type> targets() const { + std::vector<cell_lid_type> targets() const { return impl_->targets(); } @@ -110,7 +110,7 @@ private: struct interface { virtual void reset() = 0; virtual event_seq events(time_type, time_type) = 0; - virtual std::vector<cell_member_type> targets() = 0; + virtual std::vector<cell_lid_type> targets() = 0; virtual std::unique_ptr<interface> clone() = 0; virtual ~interface() {} }; @@ -126,7 +126,7 @@ private: return wrapped.events(t0, t1); } - std::vector<cell_member_type> targets() override { + std::vector<cell_lid_type> targets() override { return wrapped.targets(); } @@ -148,7 +148,7 @@ private: // a provided time schedule. struct schedule_generator { - schedule_generator(cell_member_type target, float weight, schedule sched): + schedule_generator(cell_lid_type target, float weight, schedule sched): target_(target), weight_(weight), sched_(std::move(sched)) {} @@ -169,13 +169,13 @@ struct schedule_generator { return {events_.data(), events_.data()+events_.size()}; } - std::vector<cell_member_type> targets() { + std::vector<cell_lid_type> targets() { return {target_}; } private: pse_vector events_; - cell_member_type target_; + cell_lid_type target_; float weight_; schedule sched_; }; @@ -183,7 +183,7 @@ private: // Generate events at integer multiples of dt that lie between tstart and tstop. inline event_generator regular_generator( - cell_member_type target, + cell_lid_type target, float weight, time_type tstart, time_type dt, @@ -194,7 +194,7 @@ inline event_generator regular_generator( template <typename RNG> inline event_generator poisson_generator( - cell_member_type target, + cell_lid_type target, float weight, time_type tstart, time_type rate_kHz, @@ -237,8 +237,8 @@ struct explicit_generator { return {lb, ub}; } - std::vector<cell_member_type> targets() { - std::vector<cell_member_type> tgts; + std::vector<cell_lid_type> targets() { + std::vector<cell_lid_type> tgts; std::transform(events_.begin(), events_.end(), std::back_inserter(tgts), [](auto&& e){ return e.target;}); return tgts; } diff --git a/arbor/include/arbor/recipe.hpp b/arbor/include/arbor/recipe.hpp index 3e8d834f..63fe1a21 100644 --- a/arbor/include/arbor/recipe.hpp +++ b/arbor/include/arbor/recipe.hpp @@ -40,26 +40,25 @@ struct probe_info { struct cell_connection { // Connection end-points are represented by pairs // (cell index, source/target index on cell). - using cell_connection_endpoint = cell_member_type; - cell_connection_endpoint source; - cell_connection_endpoint dest; + cell_member_type source; + cell_lid_type dest; float weight; float delay; - cell_connection(cell_connection_endpoint src, cell_connection_endpoint dst, float w, float d): + cell_connection(cell_member_type src, cell_lid_type dst, float w, float d): source(src), dest(dst), weight(w), delay(d) {} }; struct gap_junction_connection { - cell_member_type local; cell_member_type peer; + cell_lid_type local; double ggap; - gap_junction_connection(cell_member_type local, cell_member_type peer, double g): - local(local), peer(peer), ggap(g) {} + gap_junction_connection(cell_member_type peer, cell_lid_type local, double g): + peer(peer), local(local), ggap(g) {} }; class recipe { diff --git a/arbor/include/arbor/simulation.hpp b/arbor/include/arbor/simulation.hpp index c26d0225..1f4afc69 100644 --- a/arbor/include/arbor/simulation.hpp +++ b/arbor/include/arbor/simulation.hpp @@ -59,7 +59,7 @@ public: // 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 pse_vector& events); + void inject_events(const cse_vector& events); ~simulation(); diff --git a/arbor/include/arbor/spike_event.hpp b/arbor/include/arbor/spike_event.hpp index 2b72314c..102f3c42 100644 --- a/arbor/include/arbor/spike_event.hpp +++ b/arbor/include/arbor/spike_event.hpp @@ -11,7 +11,7 @@ namespace arb { // Events delivered to targets on cells with a cell group. struct spike_event { - cell_member_type target; + cell_lid_type target; time_type time; float weight; @@ -26,6 +26,13 @@ struct spike_event { 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>; + std::ostream& operator<<(std::ostream&, const spike_event&); } // namespace arb diff --git a/arbor/mc_cell_group.cpp b/arbor/mc_cell_group.cpp index 395f426e..3a0a27ed 100644 --- a/arbor/mc_cell_group.cpp +++ b/arbor/mc_cell_group.cpp @@ -400,7 +400,7 @@ void mc_cell_group::advance(epoch ep, time_type dt, const event_lane_subrange& e for (auto e: lane) { if (e.time>=ep.t1) break; e.time = binners_[lid].bin(e.time, tstart); - auto h = target_handles_[target_handle_divisions_[lid]+e.target.index]; + auto h = target_handles_[target_handle_divisions_[lid]+e.target]; auto ev = deliverable_event(e.time, h, e.weight); staged_events_.push_back(ev); count_staged++; diff --git a/arbor/merge_events.cpp b/arbor/merge_events.cpp index 53dd901f..90241cad 100644 --- a/arbor/merge_events.cpp +++ b/arbor/merge_events.cpp @@ -17,7 +17,7 @@ namespace impl { // A postsynaptic spike event that has delivery time set to // terminal_time, used as a sentinel in `tourney_tree`. -static constexpr spike_event terminal_pse{cell_member_type{0,0}, terminal_time, 0}; +static constexpr spike_event terminal_pse{0, terminal_time, 0}; // The tournament tree data structure is used to merge k sorted lists of events. diff --git a/arbor/partition_load_balance.cpp b/arbor/partition_load_balance.cpp index e8fd4135..f1f064b7 100644 --- a/arbor/partition_load_balance.cpp +++ b/arbor/partition_load_balance.cpp @@ -92,14 +92,9 @@ domain_decomposition partition_load_balance( // Adjacency list auto conns = rec.gap_junctions_on(element); for (auto c: conns) { - if (element != c.local.gid && element != c.peer.gid) { - throw bad_gj_connection_gid(element, c.local.gid, c.peer.gid); - } - cell_member_type other = c.local.gid == element ? c.peer : c.local; - - if (!visited.count(other.gid)) { - visited.insert(other.gid); - q.push(other.gid); + if (!visited.count(c.peer.gid)) { + visited.insert(c.peer.gid); + q.push(c.peer.gid); } } } diff --git a/arbor/simulation.cpp b/arbor/simulation.cpp index 3ed22957..231c7d9a 100644 --- a/arbor/simulation.cpp +++ b/arbor/simulation.cpp @@ -110,7 +110,7 @@ public: void set_binning_policy(binning_kind policy, time_type bin_interval); - void inject_events(const pse_vector& events); + void inject_events(const cse_vector& events); spike_export_function global_export_callback_; spike_export_function local_export_callback_; @@ -208,11 +208,8 @@ simulation_state::simulation_state( auto num_targets = rec.num_targets(gid); for (const auto& g: event_gens) { for (const auto& t: g.targets()) { - if (t.gid != gid) { - throw arb::bad_event_generator_target_gid(gid, t.gid); - } - if (t.index >= num_targets) { - throw arb::bad_event_generator_target_lid(gid, t.index, num_targets); + if (t >= num_targets) { + throw arb::bad_event_generator_target_lid(gid, t, num_targets); } } } @@ -468,16 +465,18 @@ void simulation_state::set_binning_policy(binning_kind policy, time_type bin_int [&](cell_group_ptr& group) { group->set_binning_policy(policy, bin_interval); }); } -void simulation_state::inject_events(const pse_vector& events) { +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& e: events) { - 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_, e.target.gid)) { - pending_events_[lidx->cell_index].push_back(e); + 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); + } } } } @@ -537,7 +536,7 @@ void simulation::set_local_spike_callback(spike_export_function export_callback) impl_->local_export_callback_ = std::move(export_callback); } -void simulation::inject_events(const pse_vector& events) { +void simulation::inject_events(const cse_vector& events) { impl_->inject_events(events); } diff --git a/arbor/symmetric_recipe.cpp b/arbor/symmetric_recipe.cpp index 66b846f8..ccf9dec5 100644 --- a/arbor/symmetric_recipe.cpp +++ b/arbor/symmetric_recipe.cpp @@ -39,7 +39,6 @@ std::vector<cell_connection> symmetric_recipe::connections_on(cell_gid_type i) c for (unsigned j = 0; j < conns.size(); j++) { conns[j].source.gid = (conns[j].source.gid + offset) % n_global; - conns[j].dest.gid = (conns[j].dest.gid + offset) % n_global; } return conns; } diff --git a/doc/concepts/interconnectivity.rst b/doc/concepts/interconnectivity.rst index 11caa96a..73f9ca9c 100644 --- a/doc/concepts/interconnectivity.rst +++ b/doc/concepts/interconnectivity.rst @@ -53,8 +53,9 @@ A recipe lets you define which sites are connected to which. 1. Create a **gap junction site** on two separate cells as part of their :ref:`cell descriptions <modelcelldesc>` in the :ref:`recipe <modelrecipe>`. - 2. Declare the Gap Junction in the recipe: with two **gap junction sites** identified using :gen:`cell_member` - and a conductance in μS. + 2. Declare the Gap Junction connections in the recipe: between a peer and local **gap junction site** + identified using :gen:`cell_member` and a conductance in μS. Two of these connections are needed, + on each of the peer and local cells. .. Note:: Only cable cells support gap junctions as of now. diff --git a/doc/cpp/interconnectivity.rst b/doc/cpp/interconnectivity.rst index 266708a7..3ac0dc43 100644 --- a/doc/cpp/interconnectivity.rst +++ b/doc/cpp/interconnectivity.rst @@ -9,18 +9,17 @@ Interconnectivity post-synaptic destination. The source is typically a threshold detector on a cell or a spike source. The destination is a synapse on the post-synaptic cell. - .. cpp:type:: cell_connection_endpoint = cell_member_type + The :cpp:member:`dest` does not include the gid of a cell, this is because a + :cpp:class:`cell_connection` is bound to the destination cell which means that the gid + is implicitly known. - Connection end-points are represented by pairs - (cell index, source/target index on cell). + .. cpp:member:: cell_member_type source - .. cpp:member:: cell_connection_endpoint source + Source end point, represented by the pair (cell gid, source index on the cell) - Source end point. + .. cpp:member:: cell_lid_type dest - .. cpp:member:: cell_connection_endpoint dest - - Destination end point. + Destination target index on the cell, target cell's gid is implicitly known. .. cpp:member:: float weight @@ -36,16 +35,25 @@ Interconnectivity .. cpp:class:: gap_junction_connection - Describes a gap junction between two gap junction sites. - Gap junction sites are represented by :cpp:type:cell_member_type. + Describes a gap junction between two gap junction sites. The :cpp:member:`local` site does not include + the gid of a cell, this is because a :cpp:class:`gap_junction_connection` is bound to the local + cell which means that the gid is implicitly known. - .. cpp:member:: cell_member_type local + .. note:: - gap junction site: one half of the gap junction connection. + A bidirectional gap-junction between two cells ``c0`` and ``c1`` requires two + :cpp:class:`gap_junction_connection` objects to be constructed: one where ``c0`` is the + :cpp:member:`local` site, and ``c1`` is the :cpp:member:`peer` site; and another where ``c1`` is the + :cpp:member:`local` site, and ``c0`` is the :cpp:member:`peer` site. If :cpp:member:`ggap` is equal + in both connections, a symmetric gap-junction is formed, other wise the gap-junction is asymmetric. .. cpp:member:: cell_member_type peer - gap junction site: other half of the gap junction connection. + Peer gap junction site, represented by the pair (cell gid, gap junction site index on the cell) + + .. cpp:member:: cell_lid_type local + + Local gap junction site index on the cell, the gid of the local site's cell is implicitly known. .. cpp:member:: float ggap diff --git a/doc/cpp/recipe.rst b/doc/cpp/recipe.rst index a71c290f..5660894e 100644 --- a/doc/cpp/recipe.rst +++ b/doc/cpp/recipe.rst @@ -74,8 +74,8 @@ Recipe .. cpp:function:: virtual std::vector<cell_connection> connections_on(cell_gid_type gid) const Returns a list of all the **incoming** connections for `gid` . - Each connection ``con`` should have post-synaptic target ``con.dest.gid`` that matches - the argument :cpp:any:`gid`, and a valid synapse id ``con.dest.index`` on `gid`. + Each connection ``con`` should have a valid synapse id ``con.dest`` on the post-synaptic target `gid`, + and a valid source id ``con.source.index`` on the pre-synaptic source ``con.source.gid``. See :cpp:type:`cell_connection`. By default returns an empty list. @@ -83,9 +83,8 @@ Recipe .. cpp:function:: virtual std::vector<gap_junction_connection> gap_junctions_on(cell_gid_type gid) const Returns a list of all the gap junctions connected to `gid`. - Each gap junction ``gj`` should have one of the two gap junction sites ``gj.local.gid`` or - ``gj.peer.gid`` matching the argument :cpp:any:`gid`, and the corresponding synapse id - ``gj.local.index`` or ``gj.peer.index`` should be valid on `gid`. + Each gap junction ``gj`` should have a valid gap junction site id ``gj.local`` on ``gid``, + and a valid gap junction site id ``gj.peer.index`` on ``gj.peer.gid``. See :cpp:type:`gap_junction_connection`. By default returns an empty list. diff --git a/doc/python/cell.rst b/doc/python/cell.rst index ca1d1df1..e89d472f 100644 --- a/doc/python/cell.rst +++ b/doc/python/cell.rst @@ -23,7 +23,7 @@ The types defined below are used as identifiers for cells and members of cell-lo An example is uniquely identifying a synapse in the model. Each synapse has a post-synaptic cell (with :attr:`gid`), and an :attr:`index` into the set of synapses on the post-synaptic cell. - Lexographically ordered by :attr:`gid`, then :attr:`index`. + Lexicographically ordered by :attr:`gid`, then :attr:`index`. .. attribute:: gid diff --git a/doc/python/interconnectivity.rst b/doc/python/interconnectivity.rst index 430496f2..944825a2 100644 --- a/doc/python/interconnectivity.rst +++ b/doc/python/interconnectivity.rst @@ -10,6 +10,9 @@ Interconnectivity Describes a connection between two cells, defined by source and destination end points (that is pre-synaptic and post-synaptic respectively), a connection weight and a delay time. + The :attr:`dest` does not include the gid of a cell, this is because a :class:`arbor.connection` is bound to the destination cell which means that the gid + is implicitly known. + .. function:: connection(source, destination, weight, delay) Construct a connection between the :attr:`source` and the :attr:`dest` with a :attr:`weight` and :attr:`delay`. @@ -20,7 +23,8 @@ Interconnectivity .. attribute:: dest - The destination end point of the connection (type: :class:`arbor.cell_member`, which can be initialized with a (gid, index) tuple). + The destination end point of the connection (type: :class:`arbor.cell_member.index` representing the index of the destination on the cell). + The gid of the cell is implicitly known. .. attribute:: weight @@ -40,29 +44,43 @@ Interconnectivity import arbor - # construct a connection between cells (0,0) and (1,0) with weight 0.01 and delay of 10 ms. - src = arbor.cell_member(0,0) - dest = arbor.cell_member(1,0) - w = 0.01 - d = 10 - con = arbor.connection(src, dest, w, d) + def connections_on(gid): + # construct a connection from the 0th source index of cell 2 (2,0) + # to the 1st target index of cell gid (gid,1) with weight 0.01 and delay of 10 ms. + src = arbor.cell_member(2,0) + dest = 1 # gid of the destination is is determined by the argument to `connections_on` + w = 0.01 + d = 10 + return [arbor.connection(src, dest, w, d)] .. class:: gap_junction_connection - Describes a gap junction between two gap junction sites. - Gap junction sites are represented by :class:`arbor.cell_member`. + Describes a gap junction between two gap junction sites. Gap junction sites are identified by :class:`arbor.cell_member`. - .. function::gap_junction_connection(local, peer, ggap) + The :attr:`local` site does not include the gid of a cell, this is because a :class:`arbor.gap_junction_connection` is bound to + the destination cell which means that the gid is implicitly known. - Construct a gap junction connection between :attr:`local` and :attr:`peer` with conductance :attr:`ggap`. + .. note:: - .. attribute:: local + A bidirectional gap-junction between two cells ``c0`` and ``c1`` requires two + :class:`gap_junction_connection` objects to be constructed: one where ``c0`` is the + :attr:`local` site, and ``c1`` is the :attr:`peer` site; and another where ``c1`` is the + :attr:`local` site, and ``c0`` is the :attr:`peer` site. If :attr:`ggap` is equal + in both connections, a symmetric gap-junction is formed, other wise the gap-junction is asymmetric. + + .. function::gap_junction_connection(peer, local, ggap) - The gap junction site: one half of the gap junction connection. + Construct a gap junction connection between :attr:`peer` and :attr:`local` with conductance :attr:`ggap`. .. attribute:: peer - The gap junction site: other half of the gap junction connection. + The gap junction site: the remote half of the gap junction connection (type: :class:`arbor.cell_member`, + which can be initialized with a (gid, index) tuple). + + .. attribute:: local + + The gap junction site: the local half of the gap junction connection (type: :class:`arbor.cell_member.index`, representing + the index of the local site on the cell). The gid of the cell is implicitly known. .. attribute:: ggap diff --git a/doc/python/recipe.rst b/doc/python/recipe.rst index 0a945d5f..ecdea890 100644 --- a/doc/python/recipe.rst +++ b/doc/python/recipe.rst @@ -33,11 +33,11 @@ Recipe .. function:: cell_kind(gid) - The cell kind of the cell with global identifier :attr:`arbor.cell_member.gid` (return type: :class:`arbor.cell_kind`). + The cell kind of the cell with global identifier ``gid`` (return type: :class:`arbor.cell_kind`). .. function:: cell_description(gid) - A high level description of the cell with global identifier :attr:`arbor.cell_member.gid`, + A high level description of the cell with global identifier ``gid``, for example the morphology, synapses and ion channels required to build a multi-compartment neuron. The type used to describe a cell depends on the kind of the cell. The interface for querying the kind and description of a cell are separate @@ -48,45 +48,43 @@ Recipe .. function:: connections_on(gid) - Returns a list of all the **incoming** connections to :attr:`arbor.cell_member.gid`. - Each connection should have post-synaptic target ``connection.dest.gid`` - that matches the argument :attr:`arbor.cell_member.gid`, - and a valid synapse id ``connection.dest.index`` on :attr:`arbor.cell_member.gid`. + Returns a list of all the **incoming** connections to ``gid``. + Each connection should have a valid synapse id ``connection.dest`` on the post-synaptic target ``gid``, + and a valid source id ``connection.source.index`` on the pre-synaptic source ``connection.source.gid``. See :class:`connection`. By default returns an empty list. .. function:: gap_junctions_on(gid) - Returns a list of all the gap junctions connected to :attr:`arbor.cell_member.gid`. - Each gap junction ``gj`` should have one of the two gap junction sites ``gj.local.gid`` - or ``gj.peer.gid`` matching the argument :attr:`arbor.cell_member.gid`, - and the corresponding synapse id ``gj.local.index`` or ``gj.peer.index`` should be valid on :attr:`arbor.cell_member.gid`. + Returns a list of all the gap junctions connected to ``gid``. + Each gap junction ``gj`` should have a valid gap junction site id ``gj.local`` on ``gid``, + and a valid gap junction site id ``gj.peer.index`` on ``gj.peer.gid``. See :class:`gap_junction_connection`. By default returns an empty list. .. function:: event_generators(gid) - A list of all the :class:`event_generator` s that are attached to :attr:`arbor.cell_member.gid`. + A list of all the :class:`event_generator` s that are attached to ``gid``. By default returns an empty list. .. function:: num_sources(gid) - The number of spike sources on :attr:`arbor.cell_member.gid`. + The number of spike sources on ``gid``. By default returns 0. .. function:: num_targets(gid) - The number of post-synaptic sites on :attr:`arbor.cell_member.gid`, which corresponds to the number of synapses. + The number of post-synaptic sites on ``gid``, which corresponds to the number of synapses. By default returns 0. .. function:: num_gap_junction_sites(gid) - Returns the number of gap junction sites on :attr:`arbor.cell_member.gid`. + Returns the number of gap junction sites on ``gid``. By default returns 0. @@ -132,7 +130,7 @@ Event generator and schedules .. attribute:: target - The target synapse of type :class:`arbor.cell_member`. + The target synapse of type :class:`arbor.cell_member.index`. .. attribute:: weight @@ -222,15 +220,16 @@ An example of an event generator reads as follows: # define a Poisson schedule with start time 1 ms, expected frequency of 5 Hz, # and the target cell's gid as seed - target = arbor.cell_member(0,0) - seed = target.gid - tstart = 1 - freq = 0.005 - sched = arbor.poisson_schedule(tstart, freq, seed) + def event_generators(gid): + target = 0 # index of the synapse on target cell gid + seed = gid + tstart = 1 + freq = 0.005 + sched = arbor.poisson_schedule(tstart, freq, seed) - # construct an event generator with this schedule on target cell and weight 0.1 - w = 0.1 - gen = arbor.event_generator(target, w, sched) + # construct an event generator with this schedule on target cell and weight 0.1 + w = 0.1 + return [arbor.event_generator(target, w, sched)] Example ------- @@ -280,13 +279,13 @@ helpers in cell_parameters and make_cable_cell for building cells are used. src = (gid-1)%self.ncells w = 0.01 d = 10 - return [arbor.connection(arbor.cell_member(src,0), arbor.cell_member(gid,0), w, d)] + return [arbor.connection(arbor.cell_member(src,0), 0, w, d)] # Attach a generator to the first cell in the ring. def event_generators(self, gid): if gid==0: sched = arbor.explicit_schedule([1]) - return [arbor.event_generator(arbor.cell_member(0,0), 0.1, sched)] + return [arbor.event_generator(0, 0.1, sched)] return [] def get_probes(self, id): diff --git a/doc/tutorial/network_ring.rst b/doc/tutorial/network_ring.rst index a7cbe4be..d0db20cf 100644 --- a/doc/tutorial/network_ring.rst +++ b/doc/tutorial/network_ring.rst @@ -102,7 +102,9 @@ to :py:class:`arbor.connection` are the **source** and **target** of the connect cell index ``gid`` and the source or target index. (:term:`Remember <connection>` that sources and targets are separately indexed.) -The two endpoints are of type :class:`arbor.cell_member`, and can be initialized with a ``(gid,index)`` tuple. +The source endpoint has type :class:`arbor.cell_member`, and can be initialized with a ``(gid,index)`` tuple. +The gid of the target end-point is implicitly known from the argument of :py:func:`arbor.recipe.connections_on`, +Therefore, we only need to identify the index of the target on the cell using the :class:`arbor.cell_member.index` type. The cells have one synapse (step **3**), so the target endpoint has the 0th index. The cell has one spike generator (step **4**), so its source index is also 0. diff --git a/example/bench/bench.cpp b/example/bench/bench.cpp index ab5912e7..43df04e0 100644 --- a/example/bench/bench.cpp +++ b/example/bench/bench.cpp @@ -134,7 +134,7 @@ public: arb::cell_gid_type src = dist(rng); if (src>=gid) ++src; // Note: target is {gid, 0}, i.e. the first (and only) target on the cell. - arb::cell_connection con({src, 0}, {gid, 0}, 1.f, params_.network.min_delay); + arb::cell_connection con({src, 0}, 0, 1.f, params_.network.min_delay); cons.push_back(con); } diff --git a/example/brunel/brunel.cpp b/example/brunel/brunel.cpp index 7f208844..8084baaa 100644 --- a/example/brunel/brunel.cpp +++ b/example/brunel/brunel.cpp @@ -119,12 +119,12 @@ public: std::vector<cell_connection> connections; // Add incoming excitatory connections. for (auto i: sample_subset(gid, 0, ncells_exc_, in_degree_exc_)) { - connections.push_back({{cell_gid_type(i), 0}, {gid, 0}, weight_exc_, delay_}); + connections.push_back({{cell_gid_type(i), 0}, 0, weight_exc_, delay_}); } // Add incoming inhibitory connections. for (auto i: sample_subset(gid, ncells_exc_, ncells_exc_ + ncells_inh_, in_degree_inh_)) { - connections.push_back({{cell_gid_type(i), 0}, {gid, 0}, weight_inh_, delay_}); + connections.push_back({{cell_gid_type(i), 0}, 0, weight_inh_, delay_}); } return connections; } @@ -145,7 +145,7 @@ public: std::mt19937_64 G; G.seed(gid + seed_); time_type t0 = 0; - return {poisson_generator({gid, 0}, weight_ext_, t0, lambda_, G)}; + return {poisson_generator(0, weight_ext_, t0, lambda_, G)}; } cell_size_type num_sources(cell_gid_type) const override { diff --git a/example/dryrun/dryrun.cpp b/example/dryrun/dryrun.cpp index 458938e7..a743ac75 100644 --- a/example/dryrun/dryrun.cpp +++ b/example/dryrun/dryrun.cpp @@ -108,7 +108,7 @@ public: auto src = source_distribution(src_gen); if (src>=gid) ++src; - return {arb::cell_connection({src, 0}, {gid, 0}, event_weight_, min_delay_)}; + return {arb::cell_connection({src, 0}, 0, event_weight_, min_delay_)}; } // Return an event generator on every 20th gid. This function needs to generate events @@ -117,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}, 1.0, event_weight_}})); + gens.push_back(arb::explicit_generator(arb::pse_vector{{0, 1.0, event_weight_}})); } return gens; } diff --git a/example/gap_junctions/gap_junctions.cpp b/example/gap_junctions/gap_junctions.cpp index 323d7667..4c16d2bc 100644 --- a/example/gap_junctions/gap_junctions.cpp +++ b/example/gap_junctions/gap_junctions.cpp @@ -91,7 +91,7 @@ public: if(gid % params_.n_cells_per_cable || (int)gid - 1 < 0) { return{}; } - return {arb::cell_connection({gid - 1, 0}, {gid, 0}, params_.event_weight, params_.event_min_delay)}; + return {arb::cell_connection({gid - 1, 0}, 0, params_.event_weight, params_.event_min_delay)}; } std::vector<arb::probe_info> get_probes(cell_gid_type gid) const override { @@ -121,10 +121,10 @@ public: // Gap junction conductance in μS if (next_cell < cable_end) { - conns.push_back(arb::gap_junction_connection({(cell_gid_type)next_cell, 0}, {gid, 1}, 0.015)); + conns.push_back(arb::gap_junction_connection({(cell_gid_type)next_cell, 0}, 1, 0.015)); } if (prev_cell >= cable_begin) { - conns.push_back(arb::gap_junction_connection({(cell_gid_type)prev_cell, 1}, {gid, 0}, 0.015)); + conns.push_back(arb::gap_junction_connection({(cell_gid_type)prev_cell, 1}, 0, 0.015)); } return conns; diff --git a/example/generators/generators.cpp b/example/generators/generators.cpp index 5b62c95f..a2747ea3 100644 --- a/example/generators/generators.cpp +++ b/example/generators/generators.cpp @@ -103,15 +103,15 @@ public: // Add excitatory generator gens.push_back( - poisson_generator(cell_member_type{0,0}, // Target synapse (gid, local_id). - w_e, // Weight of events to deliver - t0, // Events start being delivered from this time - lambda_e, // Expected frequency (kHz) - RNG(29562872))); // Random number generator to use + arb::poisson_generator(0, // Target synapse index on cell `gid` + w_e, // Weight of events to deliver + t0, // Events start being delivered from this time + lambda_e, // Expected frequency (kHz) + RNG(29562872))); // Random number generator to use // Add inhibitory generator gens.emplace_back( - poisson_generator(cell_member_type{0,0}, w_i, t0, lambda_i, RNG(86543891))); + arb::poisson_generator(0, w_i, t0, lambda_i, RNG(86543891))); return gens; } diff --git a/example/lfp/lfp.cpp b/example/lfp/lfp.cpp index 29a557d8..10c463ad 100644 --- a/example/lfp/lfp.cpp +++ b/example/lfp/lfp.cpp @@ -187,7 +187,7 @@ int main(int argc, char** argv) { auto context = arb::make_context(); // Weight 0.005 μS, onset at t = 0 ms, mean frequency 0.1 kHz. - auto events = arb::poisson_generator({0, 0}, .005, 0., 0.1, std::minstd_rand{}); + auto events = arb::poisson_generator(0, .005, 0., 0.1, std::minstd_rand{}); lfp_demo_recipe R(events); const double t_stop = 100; // [ms] diff --git a/example/ring/ring.cpp b/example/ring/ring.cpp index a6bfbd1e..c3091d5a 100644 --- a/example/ring/ring.cpp +++ b/example/ring/ring.cpp @@ -97,7 +97,7 @@ public: // Each cell has one incoming connection, from cell with gid-1. std::vector<arb::cell_connection> connections_on(cell_gid_type gid) const override { cell_gid_type src = gid? gid-1: num_cells_-1; - return {arb::cell_connection({src, 0}, {gid, 0}, event_weight_, min_delay_)}; + return {arb::cell_connection({src, 0}, 0, event_weight_, min_delay_)}; } // Return one event generator on gid 0. This generates a single event that will @@ -105,7 +105,7 @@ public: std::vector<arb::event_generator> event_generators(cell_gid_type gid) const override { std::vector<arb::event_generator> gens; if (!gid) { - gens.push_back(arb::explicit_generator(arb::pse_vector{{{0, 0}, 1.0, event_weight_}})); + gens.push_back(arb::explicit_generator(arb::pse_vector{{0, 1.0, event_weight_}})); } return gens; } diff --git a/example/single/single.cpp b/example/single/single.cpp index b3be1a02..bbe7fcbe 100644 --- a/example/single/single.cpp +++ b/example/single/single.cpp @@ -97,8 +97,9 @@ int main(int argc, char** argv) { // Trigger the single synapse (target is gid 0, index 0) at t = 1 ms with // the given weight. - arb::spike_event spike = {{0, 0}, 1., opt.syn_weight}; - sim.inject_events({spike}); + 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, opt.dt); diff --git a/python/event_generator.cpp b/python/event_generator.cpp index f89df17c..ad7d0bbd 100644 --- a/python/event_generator.cpp +++ b/python/event_generator.cpp @@ -17,7 +17,7 @@ void register_event_generators(pybind11::module& m) { event_generator .def(pybind11::init<>( - [](arb::cell_member_type target, double weight, const schedule_shim_base& sched) { + [](arb::cell_lid_type target, double weight, const schedule_shim_base& sched) { return event_generator_shim(target, weight, sched.schedule()); }), "target"_a, "weight"_a, "sched"_a, "Construct an event generator with arguments:\n" diff --git a/python/event_generator.hpp b/python/event_generator.hpp index d58d8d4d..1d0d61c3 100644 --- a/python/event_generator.hpp +++ b/python/event_generator.hpp @@ -6,12 +6,12 @@ namespace pyarb { struct event_generator_shim { - arb::cell_member_type target; + arb::cell_lid_type target; double weight; arb::schedule time_sched; - event_generator_shim(arb::cell_member_type gid, double event_weight, arb::schedule sched): - target(gid), + event_generator_shim(arb::cell_lid_type event_target, double event_weight, arb::schedule sched): + target(event_target), weight(event_weight), time_sched(std::move(sched)) {} diff --git a/python/example/brunel.py b/python/example/brunel.py index d1081fc3..3bd0af9e 100755 --- a/python/example/brunel.py +++ b/python/example/brunel.py @@ -64,10 +64,10 @@ class brunel_recipe (arbor.recipe): connections=[] # Add incoming excitatory connections. for i in sample_subset(gid, 0, self.ncells_exc_, self.in_degree_exc_): - connections.append(arbor.connection((i,0), (gid,0), self.weight_exc_, self.delay_)) + connections.append(arbor.connection((i,0), 0, self.weight_exc_, self.delay_)) # Add incoming inhibitory connections. for i in sample_subset(gid, self.ncells_exc_, self.ncells_exc_ + self.ncells_inh_, self.in_degree_inh_): - connections.append(arbor.connection((i,0), (gid,0), self.weight_inh_, self.delay_)) + connections.append(arbor.connection((i,0), 0, self.weight_inh_, self.delay_)) return connections def cell_description(self, gid): @@ -83,8 +83,9 @@ class brunel_recipe (arbor.recipe): def event_generators(self, gid): t0 = 0 + idx = 0 sched = arbor.poisson_schedule(t0, self.lambda_, gid + self.seed_) - return [arbor.event_generator(arbor.cell_member(gid,0), self.weight_ext_, sched)] + return [arbor.event_generator(idx, self.weight_ext_, sched)] def num_targets(self, gid): return 1 diff --git a/python/example/network_ring.py b/python/example/network_ring.py index 14671b3b..23657065 100755 --- a/python/example/network_ring.py +++ b/python/example/network_ring.py @@ -88,7 +88,7 @@ class ring_recipe (arbor.recipe): src = (gid-1)%self.ncells w = 0.01 d = 5 - return [arbor.connection((src,0), (gid,0), w, d)] + return [arbor.connection((src,0), 0, w, d)] def num_targets(self, gid): return 1 @@ -100,7 +100,7 @@ class ring_recipe (arbor.recipe): def event_generators(self, gid): if gid==0: sched = arbor.explicit_schedule([1]) - return [arbor.event_generator((0,0), 0.1, sched)] + return [arbor.event_generator(0, 0.1, sched)] return [] # (10) Place a probe at the root of each cell. diff --git a/python/example/single_cell_stdp.py b/python/example/single_cell_stdp.py index 84fa6550..2c783520 100755 --- a/python/example/single_cell_stdp.py +++ b/python/example/single_cell_stdp.py @@ -59,12 +59,10 @@ class single_recipe(arbor.recipe): stimulus_times = numpy.linspace(50, 500, self.n_pairs) # strong enough stimulus - spike = arbor.event_generator(arbor.cell_member( - 0, 0), 1., arbor.explicit_schedule(stimulus_times)) + spike = arbor.event_generator(0, 1., arbor.explicit_schedule(stimulus_times)) # zero weight -> just modify synaptic weight via stdp - stdp = arbor.event_generator(arbor.cell_member( - 0, 1), 0., arbor.explicit_schedule(stimulus_times - self.dT)) + stdp = arbor.event_generator(1, 0., arbor.explicit_schedule(stimulus_times - self.dT)) return [spike, stdp] diff --git a/python/recipe.cpp b/python/recipe.cpp index 21b9a7ec..9456dd3d 100644 --- a/python/recipe.cpp +++ b/python/recipe.cpp @@ -103,7 +103,7 @@ static std::vector<arb::event_generator> convert_gen(std::vector<pybind11::objec auto& p = cast<const pyarb::event_generator_shim&>(g); // convert the event_generator to an arb::event_generator - gens.push_back(arb::schedule_generator({gid, p.target.index}, p.weight, std::move(p.time_sched))); + gens.push_back(arb::schedule_generator(p.target, p.weight, std::move(p.time_sched))); } return gens; @@ -118,13 +118,13 @@ std::vector<arb::event_generator> py_recipe_shim::event_generators(arb::cell_gid } std::string con_to_string(const arb::cell_connection& c) { - return util::pprintf("<arbor.connection: source ({},{}), destination ({},{}), delay {}, weight {}>", - c.source.gid, c.source.index, c.dest.gid, c.dest.index, c.delay, c.weight); + return util::pprintf("<arbor.connection: source ({},{}), destination {}, delay {}, weight {}>", + c.source.gid, c.source.index, c.dest, c.delay, c.weight); } std::string gj_to_string(const arb::gap_junction_connection& gc) { - return util::pprintf("<arbor.gap_junction_connection: local ({},{}), peer ({},{}), ggap {}>", - gc.local.gid, gc.local.index, gc.peer.gid, gc.peer.index, gc.ggap); + return util::pprintf("<arbor.gap_junction_connection: peer ({},{}), local {}, ggap {}>", + gc.peer.gid, gc.peer.index, gc.local, gc.ggap); } void register_recipe(pybind11::module& m) { @@ -135,7 +135,7 @@ void register_recipe(pybind11::module& m) { "Describes a connection between two cells:\n" " Defined by source and destination end points (that is pre-synaptic and post-synaptic respectively), a connection weight and a delay time."); cell_connection - .def(pybind11::init<arb::cell_member_type, arb::cell_member_type, float, float>(), + .def(pybind11::init<arb::cell_member_type, arb::cell_lid_type, float, float>(), "source"_a, "dest"_a, "weight"_a, "delay"_a, "Construct a connection with arguments:\n" " source: The source end point of the connection.\n" @@ -157,7 +157,7 @@ void register_recipe(pybind11::module& m) { pybind11::class_<arb::gap_junction_connection> gap_junction_connection(m, "gap_junction_connection", "Describes a gap junction between two gap junction sites."); gap_junction_connection - .def(pybind11::init<arb::cell_member_type, arb::cell_member_type, double>(), + .def(pybind11::init<arb::cell_member_type, arb::cell_lid_type, double>(), "local"_a, "peer"_a, "ggap"_a, "Construct a gap junction connection with arguments:\n" " local: One half of the gap junction connection.\n" diff --git a/test/unit-distributed/test_communicator.cpp b/test/unit-distributed/test_communicator.cpp index 16c3527d..5c1f904a 100644 --- a/test/unit-distributed/test_communicator.cpp +++ b/test/unit-distributed/test_communicator.cpp @@ -209,7 +209,7 @@ namespace { // weight is the destination gid // delay is 1 cell_member_type src = {gid==0? size_-1: gid-1, 0}; - cell_member_type dst = {gid, 0}; + cell_lid_type dst = 0; return {cell_connection( src, dst, // end points float(gid), // weight @@ -233,7 +233,7 @@ namespace { spike_event expected_event_ring(cell_gid_type gid, cell_size_type num_cells) { auto sid = source_of(gid, num_cells); return { - {gid, 0u}, // source + 0u, // source sid+1.0f, // time (all conns have delay 1 ms) float(gid)};// weight } @@ -272,7 +272,7 @@ namespace { for (auto sid: util::make_span(0, size_)) { cell_connection con( {sid, 0}, // source - {gid, sid}, // destination + sid, // destination float(gid+sid), // weight 1.0f); // delay cons.push_back(con); @@ -287,7 +287,7 @@ namespace { spike_event expected_event_all2all(cell_gid_type gid, cell_gid_type sid) { return { - {gid, sid}, // target, event from sid goes to synapse with index sid + sid, // target, event from sid goes to synapse with index sid sid+1.0f, // time (all conns have delay 1 ms) float(gid+sid)}; // weight } diff --git a/test/unit-distributed/test_domain_decomposition.cpp b/test/unit-distributed/test_domain_decomposition.cpp index 3b5c336c..e905f564 100644 --- a/test/unit-distributed/test_domain_decomposition.cpp +++ b/test/unit-distributed/test_domain_decomposition.cpp @@ -85,20 +85,20 @@ namespace { std::vector<gap_junction_connection> gap_junctions_on(cell_gid_type gid) const override { unsigned shift = (gid/size_)*size_; switch (gid % size_) { - case 1 : return { gap_junction_connection({7 + shift, 0}, {gid, 0}, 0.1)}; + case 1 : return { gap_junction_connection({7 + shift, 0}, 0, 0.1)}; case 2 : return { - gap_junction_connection({6 + shift, 0}, {gid, 0}, 0.1), - gap_junction_connection({9 + shift, 0}, {gid, 0}, 0.1) + gap_junction_connection({6 + shift, 0}, 0, 0.1), + gap_junction_connection({9 + shift, 0}, 0, 0.1) }; case 6 : return { - gap_junction_connection({2 + shift, 0}, {gid, 0}, 0.1), - gap_junction_connection({7 + shift, 0}, {gid, 0}, 0.1) + gap_junction_connection({2 + shift, 0}, 0, 0.1), + gap_junction_connection({7 + shift, 0}, 0, 0.1) }; case 7 : return { - gap_junction_connection({6 + shift, 0}, {gid, 0}, 0.1), - gap_junction_connection({1 + shift, 0}, {gid, 0}, 0.1) + gap_junction_connection({6 + shift, 0}, 0, 0.1), + gap_junction_connection({1 + shift, 0}, 0, 0.1) }; - case 9 : return { gap_junction_connection({2 + shift, 0}, {gid, 0}, 0.1)}; + case 9 : return { gap_junction_connection({2 + shift, 0}, 0, 0.1)}; default : return {}; } } @@ -127,10 +127,10 @@ namespace { unsigned group = gid/groups_; unsigned id = gid%size_; if (id == group && group != (groups_ - 1)) { - return {gap_junction_connection({gid + size_, 0}, {gid, 0}, 0.1)}; + return {gap_junction_connection({gid + size_, 0}, 0, 0.1)}; } else if (id == group - 1) { - return {gap_junction_connection({gid - size_, 0}, {gid, 0}, 0.1)}; + return {gap_junction_connection({gid - size_, 0}, 0, 0.1)}; } else { return {}; diff --git a/test/unit/test_domain_decomposition.cpp b/test/unit/test_domain_decomposition.cpp index 8d7e9750..2db33679 100644 --- a/test/unit/test_domain_decomposition.cpp +++ b/test/unit/test_domain_decomposition.cpp @@ -77,34 +77,40 @@ namespace { } std::vector<gap_junction_connection> gap_junctions_on(cell_gid_type gid) const override { switch (gid) { - case 0 : return {gap_junction_connection({13, 0}, {0, 0}, 0.1)}; + case 0 : return { + gap_junction_connection({13, 0}, 0, 0.1) + }; case 2 : return { - gap_junction_connection({7, 0}, {2, 0}, 0.1), - gap_junction_connection({11, 0}, {2, 0}, 0.1) + gap_junction_connection({7, 0}, 0, 0.1), + gap_junction_connection({11, 0}, 0, 0.1) }; case 3 : return { - gap_junction_connection({4, 0}, {3, 0}, 0.1), - gap_junction_connection({8, 0}, {3, 0}, 0.1) + gap_junction_connection({4, 0}, 0, 0.1), + gap_junction_connection({8, 0}, 0, 0.1) }; case 4 : return { - gap_junction_connection({3, 0}, {4, 0}, 0.1), - gap_junction_connection({8, 0}, {4, 0}, 0.1), - gap_junction_connection({9, 0}, {4, 0}, 0.1) + gap_junction_connection({3, 0}, 0, 0.1), + gap_junction_connection({8, 0}, 0, 0.1), + gap_junction_connection({9, 0}, 0, 0.1) }; case 7 : return { - gap_junction_connection({2, 0}, {7, 0}, 0.1), - gap_junction_connection({11, 0}, {7, 0}, 0.1) + gap_junction_connection({2, 0}, 0, 0.1), + gap_junction_connection({11, 0}, 0, 0.1) };; case 8 : return { - gap_junction_connection({3, 0}, {8, 0}, 0.1), - gap_junction_connection({4, 0}, {8, 0}, 0.1) + gap_junction_connection({3, 0}, 0, 0.1), + gap_junction_connection({4, 0}, 0, 0.1) };; - case 9 : return {gap_junction_connection({4, 0}, {9, 0}, 0.1)}; + case 9 : return { + gap_junction_connection({4, 0}, 0, 0.1) + }; case 11 : return { - gap_junction_connection({2, 0}, {11, 0}, 0.1), - gap_junction_connection({7, 0}, {11, 0}, 0.1) + gap_junction_connection({2, 0}, 0, 0.1), + gap_junction_connection({7, 0}, 0, 0.1) + }; + case 13 : return { + gap_junction_connection({0, 0}, 0, 0.1) }; - case 13 : return {gap_junction_connection({0, 0}, {13, 0}, 0.1)}; default : return {}; } } diff --git a/test/unit/test_event_delivery.cpp b/test/unit/test_event_delivery.cpp index f8fa888e..1d4f9cd9 100644 --- a/test/unit/test_event_delivery.cpp +++ b/test/unit/test_event_delivery.cpp @@ -75,9 +75,9 @@ std::vector<cell_gid_type> run_test_sim(const recipe& R, const group_gids_type& constexpr time_type ev_delta_t = 0.2; - pse_vector cell_events; + cse_vector cell_events; for (unsigned i = 0; i<n; ++i) { - cell_events.push_back({{i, 0u}, i*ev_delta_t, 1.f}); + cell_events.push_back({i, {{0u, i*ev_delta_t, 1.f}}}); } sim.inject_events(cell_events); @@ -112,7 +112,8 @@ struct test_recipe_gj: public test_recipe { std::vector<gap_junction_connection> gap_junctions_on(cell_gid_type i) const override { std::vector<gap_junction_connection> gjs; for (auto p: gj_pairs_) { - if (p.first == i || p.second == i) gjs.push_back({{p.first, 0u}, {p.second, 0u}, 0.}); + if (p.first == i) gjs.push_back({{p.second, 0u}, 0u, 0.}); + if (p.second == i) gjs.push_back({{p.first, 0u}, 0u, 0.}); } return gjs; } diff --git a/test/unit/test_event_generators.cpp b/test/unit/test_event_generators.cpp index 032abda3..0f17feb4 100644 --- a/test/unit/test_event_generators.cpp +++ b/test/unit/test_event_generators.cpp @@ -18,8 +18,8 @@ namespace{ } TEST(event_generators, assign_and_copy) { - event_generator gen = regular_generator({1, 2}, 5., 0.5, 0.75); - spike_event expected{{1, 2}, 0.75, 5.}; + event_generator gen = regular_generator(2, 5., 0.5, 0.75); + spike_event expected{2, 0.75, 5.}; auto first = [](const event_seq& seq) { if (seq.first==seq.second) throw std::runtime_error("no events"); @@ -54,7 +54,7 @@ TEST(event_generators, regular) { // events regularly spaced 0.5 ms apart. time_type t0 = 2.0; time_type dt = 0.5; - cell_member_type target = {42, 3}; + cell_lid_type target = 3; float weight = 3.14; event_generator gen = regular_generator(target, weight, t0, dt); @@ -81,13 +81,13 @@ TEST(event_generators, regular) { TEST(event_generators, seq) { pse_vector in = { - {{0, 0}, 0.1, 1.0}, - {{0, 0}, 1.0, 2.0}, - {{0, 0}, 1.0, 3.0}, - {{0, 0}, 1.5, 4.0}, - {{0, 0}, 2.3, 5.0}, - {{0, 0}, 3.0, 6.0}, - {{0, 0}, 3.5, 7.0}, + {0, 0.1, 1.0}, + {0, 1.0, 2.0}, + {0, 1.0, 3.0}, + {0, 1.5, 4.0}, + {0, 2.3, 5.0}, + {0, 3.0, 6.0}, + {0, 3.5, 7.0}, }; auto events = [&in] (int b, int e) { @@ -102,10 +102,10 @@ TEST(event_generators, seq) { // Check reported sub-intervals against a smaller set of events. in = { - {{0, 0}, 1.5, 4.0}, - {{0, 0}, 2.3, 5.0}, - {{0, 0}, 3.0, 6.0}, - {{0, 0}, 3.5, 7.0}, + {0, 1.5, 4.0}, + {0, 2.3, 5.0}, + {0, 3.0, 6.0}, + {0, 3.5, 7.0}, }; gen = explicit_generator(in); @@ -143,7 +143,7 @@ TEST(event_generators, poisson) { time_type t0 = 0; time_type t1 = 10; time_type lambda = 10; // expect 10 events per ms - cell_member_type target{4, 2}; + cell_lid_type target = 2; float weight = 42; event_generator gen = poisson_generator(target, weight, t0, lambda, G); diff --git a/test/unit/test_event_queue.cpp b/test/unit/test_event_queue.cpp index 3ce72e0b..b47a3ed3 100644 --- a/test/unit/test_event_queue.cpp +++ b/test/unit/test_event_queue.cpp @@ -14,10 +14,10 @@ TEST(event_queue, push) { ps_event_queue q; - q.push({{1u, 0u}, 2.f, 2.f}); - q.push({{4u, 1u}, 1.f, 2.f}); - q.push({{8u, 2u}, 20.f, 2.f}); - q.push({{2u, 3u}, 8.f, 2.f}); + q.push({0u, 2.f, 2.f}); + q.push({1u, 1.f, 2.f}); + q.push({2u, 20.f, 2.f}); + q.push({3u, 8.f, 2.f}); EXPECT_EQ(4u, q.size()); @@ -33,12 +33,7 @@ TEST(event_queue, push) { TEST(event_queue, pop_if_before) { using ps_event_queue = event_queue<spike_event>; - cell_member_type target[4] = { - {1u, 0u}, - {4u, 1u}, - {8u, 2u}, - {2u, 3u} - }; + cell_lid_type target[4] = {0u, 1u, 2u, 3u}; spike_event events[] = { {target[0], 1.f, 2.f}, diff --git a/test/unit/test_fvm_lowered.cpp b/test/unit/test_fvm_lowered.cpp index 5d11cff3..a35e8393 100644 --- a/test/unit/test_fvm_lowered.cpp +++ b/test/unit/test_fvm_lowered.cpp @@ -107,21 +107,21 @@ public: std::vector<gap_junction_connection> gap_junctions_on(cell_gid_type gid) const override { switch (gid) { case 0 : - return {gap_junction_connection({5, 0}, {0, 0}, 0.1)}; + return {gap_junction_connection({5, 0}, 0, 0.1)}; case 2 : return { - gap_junction_connection({3, 0}, {2, 0}, 0.1), + gap_junction_connection({3, 0}, 0, 0.1), }; case 3 : return { - gap_junction_connection({7, 0}, {3, 0}, 0.1), - gap_junction_connection({3, 0}, {2, 0}, 0.1) + gap_junction_connection({7, 0}, 0, 0.1), + gap_junction_connection({2, 0}, 0, 0.1) }; case 5 : - return {gap_junction_connection({5, 0}, {0, 0}, 0.1)}; + return {gap_junction_connection({0, 0}, 0, 0.1)}; case 7 : return { - gap_junction_connection({3, 0}, {7, 0}, 0.1), + gap_junction_connection({3, 0}, 0, 0.1), }; default : return {}; @@ -173,27 +173,27 @@ public: switch (gid) { case 0 : return { - gap_junction_connection({2, 0}, {0, 0}, 0.1), - gap_junction_connection({3, 0}, {0, 0}, 0.1), - gap_junction_connection({5, 0}, {0, 0}, 0.1) + gap_junction_connection({2, 0}, 0, 0.1), + gap_junction_connection({3, 0}, 0, 0.1), + gap_junction_connection({5, 0}, 0, 0.1) }; case 2 : return { - gap_junction_connection({0, 0}, {2, 0}, 0.1), - gap_junction_connection({3, 0}, {2, 0}, 0.1), - gap_junction_connection({5, 0}, {2, 0}, 0.1) + gap_junction_connection({0, 0}, 0, 0.1), + gap_junction_connection({3, 0}, 0, 0.1), + gap_junction_connection({5, 0}, 0, 0.1) }; case 3 : return { - gap_junction_connection({0, 0}, {3, 0}, 0.1), - gap_junction_connection({2, 0}, {3, 0}, 0.1), - gap_junction_connection({5, 0}, {3, 0}, 0.1) + gap_junction_connection({0, 0}, 0, 0.1), + gap_junction_connection({2, 0}, 0, 0.1), + gap_junction_connection({5, 0}, 0, 0.1) }; case 5 : return { - gap_junction_connection({2, 0}, {5, 0}, 0.1), - gap_junction_connection({3, 0}, {5, 0}, 0.1), - gap_junction_connection({0, 0}, {5, 0}, 0.1) + gap_junction_connection({2, 0}, 0, 0.1), + gap_junction_connection({3, 0}, 0, 0.1), + gap_junction_connection({0, 0}, 0, 0.1) }; default : return {}; @@ -939,7 +939,7 @@ TEST(fvm_lowered, gj_coords_simple) { } std::vector<arb::gap_junction_connection> gap_junctions_on(cell_gid_type gid) const override{ std::vector<gap_junction_connection> conns; - conns.push_back(gap_junction_connection({(gid+1)%2, 0}, {gid, 0}, 0.5)); + conns.push_back(gap_junction_connection({(gid+1)%2, 0}, 0, 0.5)); return conns; } @@ -1007,22 +1007,22 @@ TEST(fvm_lowered, gj_coords_complex) { switch (gid) { case 0: return { - gap_junction_connection({2, 0}, {0, 1}, 0.01), - gap_junction_connection({1, 0}, {0, 0}, 0.03), - gap_junction_connection({1, 1}, {0, 0}, 0.04) + gap_junction_connection({2, 0}, 1, 0.01), + gap_junction_connection({1, 0}, 0, 0.03), + gap_junction_connection({1, 1}, 0, 0.04) }; case 1: return { - gap_junction_connection({0, 0}, {1, 0}, 0.03), - gap_junction_connection({0, 0}, {1, 1}, 0.04), - gap_junction_connection({2, 1}, {1, 2}, 0.02), - gap_junction_connection({2, 2}, {1, 3}, 0.01) + gap_junction_connection({0, 0}, 0, 0.03), + gap_junction_connection({0, 0}, 1, 0.04), + gap_junction_connection({2, 1}, 2, 0.02), + gap_junction_connection({2, 2}, 3, 0.01) }; case 2: return { - gap_junction_connection({0, 1}, {2, 0}, 0.01), - gap_junction_connection({1, 2}, {2, 1}, 0.02), - gap_junction_connection({1, 3}, {2, 2}, 0.01) + gap_junction_connection({0, 1}, 0, 0.01), + gap_junction_connection({1, 2}, 1, 0.02), + gap_junction_connection({1, 3}, 2, 0.01) }; default : return {}; } @@ -1152,8 +1152,8 @@ TEST(fvm_lowered, cell_group_gj) { // connect 5 of the first 10 cells in a ring; connect 5 of the second 10 cells in a ring auto next_cell = gid == 8 ? 0 : (gid == 18 ? 10 : gid + 2); auto prev_cell = gid == 0 ? 8 : (gid == 10 ? 18 : gid - 2); - conns.push_back(gap_junction_connection({next_cell, 0}, {gid, 0}, 0.03)); - conns.push_back(gap_junction_connection({prev_cell, 0}, {gid, 0}, 0.03)); + conns.push_back(gap_junction_connection({next_cell, 0}, 0, 0.03)); + conns.push_back(gap_junction_connection({prev_cell, 0}, 0, 0.03)); } return conns; } diff --git a/test/unit/test_lif_cell_group.cpp b/test/unit/test_lif_cell_group.cpp index 664f7d88..272245a1 100644 --- a/test/unit/test_lif_cell_group.cpp +++ b/test/unit/test_lif_cell_group.cpp @@ -42,7 +42,7 @@ public: std::vector<cell_connection> connections; // gid-1 >= 0 since gid != 0 cell_member_type source{(gid - 1) % n_lif_cells_, 0}; - cell_member_type target{gid, 0}; + cell_lid_type target{0}; cell_connection conn(source, target, weight_, delay_); connections.push_back(conn); @@ -50,7 +50,7 @@ public: // the connection from the last LIF cell as well if (gid == 1) { cell_member_type source{n_lif_cells_, 0}; - cell_member_type target{gid, 0}; + cell_lid_type target{0}; cell_connection conn(source, target, weight_, delay_); connections.push_back(conn); } @@ -101,7 +101,7 @@ public: } std::vector<cell_connection> connections; cell_member_type source{gid - 1, 0}; - cell_member_type target{gid, 0}; + cell_lid_type target{0}; cell_connection conn(source, target, weight_, delay_); connections.push_back(conn); @@ -177,18 +177,18 @@ TEST(lif_cell_group, spikes) { auto decomp = partition_load_balance(recipe, context); simulation sim(recipe, decomp, context); - std::vector<spike_event> events; + cse_vector events; // First event to trigger the spike (first neuron). - events.push_back({{0, 0}, 1, 1000}); + 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}); + 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}); + events.push_back({0, {{0, 50, 1000}}}); sim.inject_events(events); diff --git a/test/unit/test_merge_events.cpp b/test/unit/test_merge_events.cpp index d1756f4e..d61363f4 100644 --- a/test/unit/test_merge_events.cpp +++ b/test/unit/test_merge_events.cpp @@ -54,9 +54,9 @@ TEST(merge_events, empty) TEST(merge_events, no_overlap) { pse_vector lc = { - {{0, 0}, 1, 1}, - {{0, 0}, 2, 1}, - {{0, 0}, 3, 3}, + {0, 1, 1}, + {0, 2, 1}, + {0, 3, 3}, }; // Check that the inputs satisfy the precondition that lc is sorted. EXPECT_TRUE(std::is_sorted(lc.begin(), lc.end())); @@ -64,25 +64,25 @@ TEST(merge_events, no_overlap) // These events should be removed from lf by merge_events, and replaced // with events to be delivered after t=10 pse_vector lf = { - {{0, 0}, 1, 1}, - {{0, 0}, 2, 1}, - {{0, 0}, 3, 3}, + {0, 1, 1}, + {0, 2, 1}, + {0, 3, 3}, }; pse_vector events = { - {{0, 0}, 12, 1}, - {{0, 0}, 11, 2}, - {{8, 0}, 10, 4}, - {{0, 0}, 11, 1}, + {0, 12, 1}, + {0, 11, 2}, + {0, 10, 4}, + {0, 11, 1}, }; merge_events(10, terminal_time, lc, events, empty_gens, lf); pse_vector expected = { - {{8, 0}, 10, 4}, - {{0, 0}, 11, 1}, - {{0, 0}, 11, 2}, - {{0, 0}, 12, 1}, + {0, 10, 4}, + {0, 11, 1}, + {0, 11, 2}, + {0, 12, 1}, }; EXPECT_TRUE(std::is_sorted(lf.begin(), lf.end())); @@ -95,11 +95,11 @@ TEST(merge_events, no_overlap) TEST(merge_events, overlap) { pse_vector lc = { - {{0, 0}, 1, 1}, - {{0, 0}, 2, 1}, + {0, 1, 1}, + {0, 2, 1}, // The current epoch ends at t=10, so all events from here down are expected in lf. - {{8, 0}, 10, 2}, - {{0, 0}, 11, 3}, + {0, 10, 2}, + {0, 11, 3}, }; EXPECT_TRUE(std::is_sorted(lc.begin(), lc.end())); @@ -107,23 +107,23 @@ TEST(merge_events, overlap) pse_vector events = { // events are in reverse order: they should be sorted in the output of merge_events. - {{0, 0}, 12, 1}, - {{0, 0}, 11, 2}, - {{0, 0}, 11, 1}, - {{8, 0}, 10, 3}, - {{7, 0}, 10, 8}, + {0, 12, 1}, + {0, 11, 2}, + {0, 11, 1}, + {1, 10, 3}, + {0, 10, 8}, }; merge_events(10, terminal_time, lc, events, empty_gens, lf); pse_vector expected = { - {{7, 0}, 10, 8}, // from events - {{8, 0}, 10, 2}, // from lc - {{8, 0}, 10, 3}, // from events - {{0, 0}, 11, 1}, // from events - {{0, 0}, 11, 2}, // from events - {{0, 0}, 11, 3}, // from lc - {{0, 0}, 12, 1}, // from events + {0, 10, 2}, // from lc + {0, 10, 8}, // from events + {1, 10, 3}, // from events + {0, 11, 1}, // from events + {0, 11, 2}, // from events + {0, 11, 3}, // from lc + {0, 12, 1}, // from events }; EXPECT_TRUE(std::is_sorted(lf.begin(), lf.end())); @@ -137,42 +137,42 @@ TEST(merge_events, X) const time_type t1 = 20; pse_vector lc = { - {{0, 0}, 1, 1}, - {{0, 0}, 5, 1}, + {0, 1, 1}, + {0, 5, 1}, // The current epoch ends at t=10, so all events from here down are expected in lf. - {{8, 0}, 10, 2}, - {{0, 0}, 11, 3}, - {{8, 0}, 20, 2}, - {{0, 0}, 21, 3}, + {0, 10, 2}, + {0, 11, 3}, + {0, 20, 2}, + {0, 21, 3}, }; EXPECT_TRUE(std::is_sorted(lc.begin(), lc.end())); pse_vector lf; pse_vector events = { - {{0, 0}, 12, 1}, - {{1, 0}, 15, 2}, - {{2, 0}, 22, 3}, - {{3, 0}, 26, 4}, + {0, 12, 1}, + {0, 15, 2}, + {0, 22, 3}, + {0, 26, 4}, }; std::vector<event_generator> generators = { - regular_generator(cell_member_type{4,2}, 42.f, t0, 5) + regular_generator(2, 42.f, t0, 5) }; merge_events(t0, t1, lc, events, generators, lf); pse_vector expected = { - {{4, 2}, 10, 42}, // from generator - {{8, 0}, 10, 2}, // from lc - {{0, 0}, 11, 3}, // from lc - {{0, 0}, 12, 1}, // from events - {{1, 0}, 15, 2}, // from events - {{4, 2}, 15, 42}, // from generator - {{8, 0}, 20, 2}, // from lc - {{0, 0}, 21, 3}, // from lc - {{2, 0}, 22, 3}, // from events - {{3, 0}, 26, 4}, // from events + {0, 10, 2}, // from lc + {2, 10, 42}, // from generator + {0, 11, 3}, // from lc + {0, 12, 1}, // from events + {0, 15, 2}, // from events + {2, 15, 42}, // from generator + {0, 20, 2}, // from lc + {0, 21, 3}, // from lc + {0, 22, 3}, // from events + {0, 26, 4}, // from events }; EXPECT_TRUE(std::is_sorted(lf.begin(), lf.end())); @@ -183,19 +183,19 @@ TEST(merge_events, X) TEST(merge_events, tourney_seq) { pse_vector evs1 = { - {{0, 0}, 1, 1}, - {{0, 0}, 2, 2}, - {{0, 0}, 3, 3}, - {{0, 0}, 4, 4}, - {{0, 0}, 5, 5}, + {0, 1, 1}, + {0, 2, 2}, + {0, 3, 3}, + {0, 4, 4}, + {0, 5, 5}, }; pse_vector evs2 = { - {{0, 0}, 1.5, 1}, - {{0, 0}, 2.5, 2}, - {{0, 0}, 3.5, 3}, - {{0, 0}, 4.5, 4}, - {{0, 0}, 5.5, 5}, + {0, 1.5, 1}, + {0, 2.5, 2}, + {0, 3.5, 3}, + {0, 4.5, 4}, + {0, 5.5, 5}, }; event_generator g1 = explicit_generator(evs1); @@ -234,7 +234,7 @@ TEST(merge_events, tourney_poisson) std::vector<event_generator> generators; for (auto i=0u; i<ngen; ++i) { - cell_member_type tgt{0, i}; + cell_lid_type tgt = i; float weight = i; // the first and last generators have the same seed to test that sorting // of events with the same time but different weights works properly. diff --git a/test/unit/test_probe.cpp b/test/unit/test_probe.cpp index f08a4cf0..7e705019 100644 --- a/test/unit/test_probe.cpp +++ b/test/unit/test_probe.cpp @@ -1249,9 +1249,9 @@ void run_exact_sampling_probe_test(const context& ctx) { std::vector<gap_junction_connection> gap_junctions_on(cell_gid_type gid) const override { switch (gid) { case 1: - return {gap_junction_connection({gid, 0}, {3, 0}, 1.)}; + return {gap_junction_connection({3, 0}, 0, 1.)}; case 3: - return {gap_junction_connection({gid, 0}, {1, 0}, 1.)}; + return {gap_junction_connection({1, 0}, 0, 1.)}; default: return {}; } @@ -1259,7 +1259,7 @@ void run_exact_sampling_probe_test(const context& ctx) { std::vector<event_generator> event_generators(cell_gid_type gid) const override { // Send a single event to cell i at 0.1*i milliseconds. - pse_vector spikes = {spike_event{{gid, 0}, 0.1*gid, 1.f}}; + pse_vector spikes = {spike_event{0, 0.1*gid, 1.f}}; return {explicit_generator(spikes)}; } diff --git a/test/unit/test_recipe.cpp b/test/unit/test_recipe.cpp index 0d2a6489..b1b0c04e 100644 --- a/test/unit/test_recipe.cpp +++ b/test/unit/test_recipe.cpp @@ -171,36 +171,34 @@ TEST(recipe, gap_junctions) auto cell_1 = custom_cell(0, 0, 3); { - std::vector<arb::gap_junction_connection> gjs_0 = {{{0, 0}, {1, 1}, 0.1}, - {{0, 1}, {1, 2}, 0.1}, - {{0, 2}, {1, 0}, 0.1}}; + std::vector<arb::gap_junction_connection> gjs_0 = {{{1, 1}, 0, 0.1}, + {{1, 2}, 1, 0.1}, + {{1, 0}, 2, 0.1}}; - auto recipe_0 = custom_recipe({cell_0, cell_1}, {0, 0}, {0, 0}, {{}, {}}, {gjs_0, gjs_0}, {{}, {}}); + std::vector<arb::gap_junction_connection> gjs_1 = {{{0, 0}, 1, 0.1}, + {{0, 1}, 2, 0.1}, + {{0, 2}, 0, 0.1}}; + + auto recipe_0 = custom_recipe({cell_0, cell_1}, {0, 0}, {0, 0}, {{}, {}}, {gjs_0, gjs_1}, {{}, {}}); auto decomp_0 = partition_load_balance(recipe_0, context); EXPECT_NO_THROW(simulation(recipe_0, decomp_0, context)); } { - std::vector<arb::gap_junction_connection> gjs_1 = {{{0, 0}, {1, 1}, 0.1}, - {{0, 1}, {1, 2}, 0.1}, - {{0, 2}, {1, 5}, 0.1}}; + std::vector<arb::gap_junction_connection> gjs_0 = {{{1, 1}, 0, 0.1}, + {{1, 2}, 1, 0.1}, + {{1, 5}, 2, 0.1}}; + + std::vector<arb::gap_junction_connection> gjs_1 = {{{0, 0}, 1, 0.1}, + {{0, 1}, 2, 0.1}, + {{0, 2}, 5, 0.1}}; - auto recipe_1 = custom_recipe({cell_0, cell_1}, {0, 0}, {0, 0}, {{}, {}}, {gjs_1, gjs_1}, {{}, {}}); + auto recipe_1 = custom_recipe({cell_0, cell_1}, {0, 0}, {0, 0}, {{}, {}}, {gjs_0, gjs_1}, {{}, {}}); auto decomp_1 = partition_load_balance(recipe_1, context); EXPECT_THROW(simulation(recipe_1, decomp_1, context), arb::bad_gj_connection_lid); } - { - std::vector<arb::gap_junction_connection> gjs_2 = {{{0, 0}, {1, 1}, 0.1}, - {{0, 1}, {1, 2}, 0.1}, - {{0, 2}, {3, 0}, 0.1}}; - - auto recipe_2 = custom_recipe({cell_0, cell_1}, {0, 0}, {0, 0}, {{}, {}}, {gjs_2, gjs_2}, {{}, {}}); - auto context = make_context(resources); - - EXPECT_THROW(partition_load_balance(recipe_2, context), arb::bad_gj_connection_gid); - } } TEST(recipe, connections) @@ -218,13 +216,13 @@ TEST(recipe, connections) auto cell_1 = custom_cell(2, 1, 0); std::vector<arb::cell_connection> conns_0, conns_1; { - conns_0 = {{{1, 0}, {0, 0}, 0.1, 0.1}, - {{1, 1}, {0, 0}, 0.1, 0.1}, - {{1, 0}, {0, 1}, 0.2, 0.4}}; + conns_0 = {{{1, 0}, 0, 0.1, 0.1}, + {{1, 1}, 0, 0.1, 0.1}, + {{1, 0}, 1, 0.2, 0.4}}; - conns_1 = {{{0, 0}, {1, 0}, 0.1, 0.2}, - {{0, 0}, {1, 0}, 0.3, 0.1}, - {{0, 0}, {1, 0}, 0.1, 0.8}}; + conns_1 = {{{0, 0}, 0, 0.1, 0.2}, + {{0, 0}, 0, 0.3, 0.1}, + {{0, 0}, 0, 0.1, 0.8}}; auto recipe_0 = custom_recipe({cell_0, cell_1}, {1, 2}, {2, 1}, {conns_0, conns_1}, {{}, {}}, {{}, {}}); auto decomp_0 = partition_load_balance(recipe_0, context); @@ -232,13 +230,13 @@ TEST(recipe, connections) EXPECT_NO_THROW(simulation(recipe_0, decomp_0, context)); } { - conns_0 = {{{1, 0}, {0, 0}, 0.1, 0.1}, - {{2, 1}, {0, 0}, 0.1, 0.1}, - {{1, 0}, {0, 1}, 0.2, 0.4}}; + conns_0 = {{{1, 0}, 0, 0.1, 0.1}, + {{2, 1}, 0, 0.1, 0.1}, + {{1, 0}, 1, 0.2, 0.4}}; - conns_1 = {{{0, 0}, {1, 0}, 0.1, 0.2}, - {{0, 0}, {1, 0}, 0.3, 0.1}, - {{0, 0}, {1, 0}, 0.1, 0.8}}; + conns_1 = {{{0, 0}, 0, 0.1, 0.2}, + {{0, 0}, 0, 0.3, 0.1}, + {{0, 0}, 0, 0.1, 0.8}}; auto recipe_1 = custom_recipe({cell_0, cell_1}, {1, 2}, {2, 1}, {conns_0, conns_1}, {{}, {}}, {{}, {}}); auto decomp_1 = partition_load_balance(recipe_1, context); @@ -246,13 +244,13 @@ TEST(recipe, connections) EXPECT_THROW(simulation(recipe_1, decomp_1, context), arb::bad_connection_source_gid); } { - conns_0 = {{{1, 0}, {0, 0}, 0.1, 0.1}, - {{1, 1}, {0, 0}, 0.1, 0.1}, - {{1, 3}, {0, 1}, 0.2, 0.4}}; + conns_0 = {{{1, 0}, 0, 0.1, 0.1}, + {{1, 1}, 0, 0.1, 0.1}, + {{1, 3}, 1, 0.2, 0.4}}; - conns_1 = {{{0, 0}, {1, 0}, 0.1, 0.2}, - {{0, 0}, {1, 0}, 0.3, 0.1}, - {{0, 0}, {1, 0}, 0.1, 0.8}}; + conns_1 = {{{0, 0}, 0, 0.1, 0.2}, + {{0, 0}, 0, 0.3, 0.1}, + {{0, 0}, 0, 0.1, 0.8}}; auto recipe_2 = custom_recipe({cell_0, cell_1}, {1, 2}, {2, 1}, {conns_0, conns_1}, {{}, {}}, {{}, {}}); auto decomp_2 = partition_load_balance(recipe_2, context); @@ -260,41 +258,13 @@ TEST(recipe, connections) EXPECT_THROW(simulation(recipe_2, decomp_2, context), arb::bad_connection_source_lid); } { - conns_0 = {{{1, 0}, {0, 0}, 0.1, 0.1}, - {{1, 1}, {0, 0}, 0.1, 0.1}, - {{1, 0}, {0, 1}, 0.2, 0.4}}; - - conns_1 = {{{0, 0}, {1, 0}, 0.1, 0.2}, - {{0, 0}, {7, 0}, 0.3, 0.1}, - {{0, 0}, {1, 0}, 0.1, 0.8}}; - - auto recipe_3 = custom_recipe({cell_0, cell_1}, {1, 2}, {2, 1}, {conns_0, conns_1}, {{}, {}}, {{}, {}}); - auto decomp_3 = partition_load_balance(recipe_3, context); - - EXPECT_THROW(simulation(recipe_3, decomp_3, context), arb::bad_connection_target_gid); - } - { - conns_0 = {{{1, 0}, {0, 0}, 0.1, 0.1}, - {{1, 1}, {0, 0}, 0.1, 0.1}, - {{1, 0}, {0, 1}, 0.2, 0.4}}; + conns_0 = {{{1, 0}, 0, 0.1, 0.1}, + {{1, 1}, 0, 0.1, 0.1}, + {{1, 0}, 1, 0.2, 0.4}}; - conns_1 = {{{0, 0}, {1, 0}, 0.1, 0.2}, - {{0, 0}, {0, 0}, 0.3, 0.1}, - {{0, 0}, {1, 0}, 0.1, 0.8}}; - - auto recipe_5 = custom_recipe({cell_0, cell_1}, {1, 2}, {2, 1}, {conns_0, conns_1}, {{}, {}}, {{}, {}}); - auto decomp_5 = partition_load_balance(recipe_5, context); - - EXPECT_THROW(simulation(recipe_5, decomp_5, context), arb::bad_connection_target_gid); - } - { - conns_0 = {{{1, 0}, {0, 0}, 0.1, 0.1}, - {{1, 1}, {0, 0}, 0.1, 0.1}, - {{1, 0}, {0, 1}, 0.2, 0.4}}; - - conns_1 = {{{0, 0}, {1, 0}, 0.1, 0.2}, - {{0, 0}, {1, 9}, 0.3, 0.1}, - {{0, 0}, {1, 0}, 0.1, 0.8}}; + conns_1 = {{{0, 0}, 0, 0.1, 0.2}, + {{0, 0}, 9, 0.3, 0.1}, + {{0, 0}, 0, 0.1, 0.8}}; auto recipe_4 = custom_recipe({cell_0, cell_1}, {1, 2}, {2, 1}, {conns_0, conns_1}, {{}, {}}, {{}, {}}); auto decomp_4 = partition_load_balance(recipe_4, context); @@ -317,9 +287,9 @@ TEST(recipe, event_generators) { auto cell_1 = custom_cell(2, 1, 0); std::vector<arb::event_generator> gens_0, gens_1; { - gens_0 = {arb::explicit_generator(arb::pse_vector{{{0, 0}, 1.0, 0.1}, {{0, 1}, 2.0, 0.1}})}; + gens_0 = {arb::explicit_generator(arb::pse_vector{{0, 1.0, 0.1}, {1, 2.0, 0.1}})}; - gens_1 = {arb::explicit_generator(arb::pse_vector{{{1, 0}, 1.0, 0.1}})}; + gens_1 = {arb::explicit_generator(arb::pse_vector{{0, 1.0, 0.1}})}; auto recipe_0 = custom_recipe({cell_0, cell_1}, {1, 2}, {2, 1}, {{}, {}}, {{}, {}}, {gens_0, gens_1}); auto decomp_0 = partition_load_balance(recipe_0, context); @@ -327,16 +297,7 @@ TEST(recipe, event_generators) { EXPECT_NO_THROW(simulation(recipe_0, decomp_0, context)); } { - gens_0.clear(); - gens_1 = {arb::explicit_generator(arb::pse_vector{{{0, 0}, 1.0, 0.1}})}; - - auto recipe_0 = custom_recipe({cell_0, cell_1}, {1, 2}, {2, 1}, {{}, {}}, {{}, {}}, {gens_0, gens_1}); - auto decomp_0 = partition_load_balance(recipe_0, context); - - EXPECT_THROW(simulation(recipe_0, decomp_0, context), arb::bad_event_generator_target_gid); - } - { - gens_0 = {arb::explicit_generator(arb::pse_vector{{{0, 0}, 1.0, 0.1}, {{0, 3}, 2.0, 0.1}})}; + gens_0 = {arb::explicit_generator(arb::pse_vector{{0, 1.0, 0.1}, {3, 2.0, 0.1}})}; gens_1.clear(); auto recipe_0 = custom_recipe({cell_0, cell_1}, {1, 2}, {2, 1}, {{}, {}}, {{}, {}}, {gens_0, gens_1}); diff --git a/test/unit/test_simulation.cpp b/test/unit/test_simulation.cpp index dda5be17..88d39b72 100644 --- a/test/unit/test_simulation.cpp +++ b/test/unit/test_simulation.cpp @@ -94,7 +94,7 @@ struct lif_chain: public recipe { std::vector<cell_connection> connections_on(cell_gid_type target) const { if (target) { - return {cell_connection({target-1, 0}, {target, 0}, weight_, delay_)}; + return {cell_connection({target-1, 0}, 0, weight_, delay_)}; } else { return {}; @@ -106,7 +106,7 @@ struct lif_chain: public recipe { return {}; } else { - return {schedule_generator({target, 0}, weight_, triggers_)}; + return {schedule_generator(0, weight_, triggers_)}; } } -- GitLab