From 13131745410a16982d21a641cc9e13dff18ed96b Mon Sep 17 00:00:00 2001 From: thorstenhater <24411438+thorstenhater@users.noreply.github.com> Date: Mon, 2 Nov 2020 13:03:01 +0100 Subject: [PATCH] Interface/merge cat names (#1208) * Add interface for querying names. * Add derived mechanisms to list, clean-up. * Add unit tests. * Add python bindings and docs. --- arbor/include/arbor/mechcat.hpp | 3 +++ arbor/mechcat.cpp | 13 ++++++++++ doc/python/mechanisms.rst | 6 +++++ python/mechanism.cpp | 4 +++- test/unit/test_mechcat.cpp | 42 +++++++++++++++++++++++++++++++++ 5 files changed, 67 insertions(+), 1 deletion(-) diff --git a/arbor/include/arbor/mechcat.hpp b/arbor/include/arbor/mechcat.hpp index 0fc0a23f..436edbc2 100644 --- a/arbor/include/arbor/mechcat.hpp +++ b/arbor/include/arbor/mechcat.hpp @@ -110,6 +110,9 @@ public: ~mechanism_catalogue(); + // Grab a collection of all mechanism names in the catalogue. + std::vector<std::string> mechanism_names() const; + private: std::unique_ptr<catalogue_state> state_; diff --git a/arbor/mechcat.cpp b/arbor/mechcat.cpp index 3fac9e80..001ab95e 100644 --- a/arbor/mechcat.cpp +++ b/arbor/mechcat.cpp @@ -8,6 +8,7 @@ #include <arbor/mechcat.hpp> #include <arbor/util/expected.hpp> +#include "util/rangeutil.hpp" #include "util/maputil.hpp" /* Notes on implementation: @@ -479,6 +480,14 @@ struct catalogue_state { return over; } + // Collect all mechanism names present in this catalogue + std::vector<std::string> mechanism_names() const { + std::vector<std::string> result; + util::assign(result, util::keys(info_map_)); + util::append(result, util::keys(derived_map_)); + return result; + } + // Schemata for (un-derived) mechanisms. string_map<mechanism_info_ptr> info_map_; @@ -495,6 +504,10 @@ mechanism_catalogue::mechanism_catalogue(): state_(new catalogue_state) {} +std::vector<std::string> mechanism_catalogue::mechanism_names() const { + return state_->mechanism_names(); +} + mechanism_catalogue::mechanism_catalogue(mechanism_catalogue&& other) = default; mechanism_catalogue& mechanism_catalogue::operator=(mechanism_catalogue&& other) = default; diff --git a/doc/python/mechanisms.rst b/doc/python/mechanisms.rst index e31f137a..b55aa460 100644 --- a/doc/python/mechanisms.rst +++ b/doc/python/mechanisms.rst @@ -280,6 +280,12 @@ Mechanism catalogues :return: mechanism metadata :rtype: :class:`mechanism_info` + .. py:method:: names() + + Return a list names of all the mechanisms in the catalogue. + + :return: list + .. py:method:: derive(name, parent, globals={}, ions={}) Derive a new mechanism with *name* from the mechanism *parent*. diff --git a/python/mechanism.cpp b/python/mechanism.cpp index 9c65cc2d..e0fc9846 100644 --- a/python/mechanism.cpp +++ b/python/mechanism.cpp @@ -107,7 +107,9 @@ void register_mechanisms(pybind11::module& m) { cat .def(pybind11::init<const arb::mechanism_catalogue&>()) .def("has", &arb::mechanism_catalogue::has, - "name"_a, "Is 'name' in the catalogue?") + "name"_a, "Is 'name' in the catalogue?") + .def("keys", &arb::mechanism_catalogue::mechanism_names, + "Return a list of all mechanisms in this catalogues.") .def("is_derived", &arb::mechanism_catalogue::is_derived, "name"_a, "Is 'name' a derived mechanism or can it be implicitly derived?") .def("__getitem__", diff --git a/test/unit/test_mechcat.cpp b/test/unit/test_mechcat.cpp index 31526aa2..ffd6b265 100644 --- a/test/unit/test_mechcat.cpp +++ b/test/unit/test_mechcat.cpp @@ -244,6 +244,48 @@ TEST(mechcat, fingerprint) { arb::fingerprint_mismatch); } +TEST(mechcat, names) { + // All names are caught; covers `add' and `derive' + { + auto cat = build_fake_catalogue(); + auto names = cat.mechanism_names(); + auto expect = std::vector<std::string>{"bleeble", "burble", "fleeb", "fleeb1", "fleeb2", "fleeb3", "special_fleeb"}; + std::sort(names.begin(), names.end()); + EXPECT_EQ(names, expect); + } + + // Deriving names does not add to catalogue + { + auto cat = build_fake_catalogue(); + auto info = cat["burble/quux=3,xyzzy=4"]; + auto names = cat.mechanism_names(); + auto expect = std::vector<std::string>{"bleeble", "burble", "fleeb", "fleeb1", "fleeb2", "fleeb3", "special_fleeb"}; + std::sort(names.begin(), names.end()); + EXPECT_EQ(names, expect); + } + + // Deleting a mechanism removes it and all derived from it. + { + auto cat = build_fake_catalogue(); + cat.remove("fleeb"); + auto names = cat.mechanism_names(); + auto expect = std::vector<std::string>{"bleeble", "burble"}; + std::sort(names.begin(), names.end()); + EXPECT_EQ(names, expect); + } + + // Empty means empty. + { + auto cat = build_fake_catalogue(); + cat.remove("fleeb"); + cat.remove("burble"); + auto names = cat.mechanism_names(); + auto expect = std::vector<std::string>{}; + std::sort(names.begin(), names.end()); + EXPECT_EQ(names, expect); + } +} + TEST(mechcat, derived_info) { auto cat = build_fake_catalogue(); -- GitLab