Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Check that mechanisms have the right kind #1633

Merged
merged 4 commits into from
Aug 27, 2021
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 25 additions & 4 deletions arbor/fvm_layout.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -838,6 +838,16 @@ fvm_mechanism_data fvm_build_mechanism_data(const cable_cell_global_properties&
}
};

// Mechanism kind as string, for error messages.
auto mech_kind_to_string = [](arb_mechanism_kind t) {
switch (t) {
case arb_mechanism_kind_density: return "density mechanism kind";
case arb_mechanism_kind_point: return "point mechanism kind";
case arb_mechanism_kind_reversal_potential: return "reversal potential mechanism kind";
default: return "unknown mechanism kind";
}
};

// Track ion usage of mechanisms so that ions are only instantiated where required.
std::unordered_map<std::string, std::vector<index_type>> ion_support;
auto update_ion_support = [&ion_support](const mechanism_info& info, const std::vector<index_type>& cvs) {
Expand All @@ -858,14 +868,17 @@ fvm_mechanism_data fvm_build_mechanism_data(const cable_cell_global_properties&
const std::string& name = entry.first;
mechanism_info info = catalogue[name];

std::vector<double> param_dflt;
fvm_mechanism_config config;
config.kind = arb_mechanism_kind_density;
if (info.kind != arb_mechanism_kind_density) {
throw cable_cell_error("expected density mechanism, got " +name +" which has " +mech_kind_to_string(info.kind));
}
config.kind = info.kind;

std::vector<std::string> param_names;
assign(param_names, util::keys(info.parameters));
sort(param_names);

std::vector<double> param_dflt;
std::size_t n_param = param_names.size();
param_dflt.reserve(n_param);
config.param_values.reserve(n_param);
Expand Down Expand Up @@ -963,6 +976,10 @@ fvm_mechanism_data fvm_build_mechanism_data(const cable_cell_global_properties&
const std::string& name = entry.first;
mechanism_info info = catalogue[name];

if (info.kind != arb_mechanism_kind_point) {
throw cable_cell_error("expected point mechanism, got " +name +" which has " +mech_kind_to_string(info.kind));
}

post_events |= info.post_events;
std::size_t n_param = info.parameters.size();
std::size_t n_inst = entry.second.size();
Expand Down Expand Up @@ -1044,7 +1061,7 @@ fvm_mechanism_data fvm_build_mechanism_data(const cable_cell_global_properties&
bool coalesce = catalogue[name].linear && gprop.coalesce_synapses;

fvm_mechanism_config config;
config.kind = arb_mechanism_kind_point;
config.kind = info.kind;
for (auto& kv: info.parameters) {
config.param_values.emplace_back(kv.first, std::vector<value_type>{});
if (!coalesce) {
Expand Down Expand Up @@ -1210,6 +1227,10 @@ fvm_mechanism_data fvm_build_mechanism_data(const cable_cell_global_properties&
{
const mechanism_desc& revpot = *maybe_revpot;
mechanism_info info = catalogue[revpot.name()];
if (info.kind != arb_mechanism_kind_reversal_potential) {
throw cable_cell_error("expected reversal potential mechanism for ion " +ion +", got "+ revpot.name() +" which has " +mech_kind_to_string(info.kind));
}

verify_mechanism(info, revpot);
revpot_specified.insert(ion);

Expand Down Expand Up @@ -1248,7 +1269,7 @@ fvm_mechanism_data fvm_build_mechanism_data(const cable_cell_global_properties&
}
else {
fvm_mechanism_config config;
config.kind = arb_mechanism_kind_reversal_potential;
config.kind = info.kind;
config.cv = M.ions[ion].cv;
config.norm_area.assign(config.cv.size(), 1.);

Expand Down
3 changes: 3 additions & 0 deletions arbor/include/arbor/mechinfo.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,9 @@ struct mechanism_info {
mechanism_info(const arb_mechanism_type&);
mechanism_info() = default;

// Mechanism kind
arb_mechanism_kind kind;

// Global fields have one value common to an instance of a mechanism, are
// constant in time and set at instantiation.
std::unordered_map<std::string, mechanism_field_spec> globals;
Expand Down
1 change: 1 addition & 0 deletions arbor/mechinfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

namespace arb {
mechanism_info::mechanism_info(const arb_mechanism_type& m) {
kind = m.kind;
post_events = m.has_post_events;
linear = m.is_linear;
fingerprint = m.fingerprint;
Expand Down
10 changes: 10 additions & 0 deletions doc/python/mechanisms.rst
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,11 @@ mechanism that is to be painted or placed on the cable cell.
print(mech.parameters['tau'].default)
# 2.0

.. py:attribute:: kind
:type: string

String representation of the kind of the mechanism: density, point or reversal potential.

.. py:attribute:: globals
:type: dict[str, mechanism_field]

Expand All @@ -163,6 +168,11 @@ mechanism that is to be painted or placed on the cable cell.

True if a synapse mechanism has linear current contributions so that multiple instances on the same :term:`control volume` can be coalesced.

.. py:attribute:: post_events
:type: bool

True if a synapse mechanism has a `POST_EVENT` procedure defined.


.. py:class:: ion_dependency

Expand Down
11 changes: 11 additions & 0 deletions python/mechanism.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,17 @@ void register_mechanisms(pybind11::module& m) {
"Ion dependencies.")
.def_readonly("linear", &arb::mechanism_info::linear,
"True if a synapse mechanism has linear current contributions so that multiple instances on the same compartment can be coalesced.")
.def_readonly("post_events", &arb::mechanism_info::post_events,
"True if a synapse mechanism has a `POST_EVENT` procedure defined.")
.def_property_readonly("kind",
[](const arb::mechanism_info& info) {
switch (info.kind) {
case arb_mechanism_kind_density: return "Density mechanism";
case arb_mechanism_kind_point: return "Point mechanism";
case arb_mechanism_kind_reversal_potential: return "Reversal potential mechanism";
default: return "Unknown mechanism kind";
};
}, "String representation of the kind of the mechanism.")
.def("__repr__",
[](const arb::mechanism_info& inf) {
return util::pprintf("(arbor.mechanism_info)"); })
Expand Down
54 changes: 54 additions & 0 deletions test/unit/test_fvm_layout.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,60 @@ namespace {
}
} // namespace

TEST(fvm_layout, compatible_mechanisms) {
cable_cell_global_properties gprop;
gprop.default_parameters = neuron_parameter_defaults;

{
auto system = two_cell_system();

// place a density mechanism instead of a point mechanism
system.descriptions[0].decorations.place(system.builders[0].location({1, 0.4}), "hh", "syn0");

auto cells = system.cells();
check_two_cell_system(cells);
fvm_cv_discretization D = fvm_cv_discretize(cells, gprop.default_parameters);

EXPECT_THROW(fvm_build_mechanism_data(gprop, cells, D), arb::cable_cell_error);
}
{
auto system = two_cell_system();

// paint a point mechanism instead of a density mechanism
system.descriptions[1].decorations.paint(system.builders[1].cable(mcable{0}), "expsyn");

auto cells = system.cells();
check_two_cell_system(cells);
fvm_cv_discretization D = fvm_cv_discretize(cells, gprop.default_parameters);

EXPECT_THROW(fvm_build_mechanism_data(gprop, cells, D), arb::cable_cell_error);
}
{
auto system = two_cell_system();

// Set a density mechanism instead of a reversal potential mechanism
system.descriptions[1].decorations.set_default(ion_reversal_potential_method{"na", "expsyn"});

auto cells = system.cells();
check_two_cell_system(cells);
fvm_cv_discretization D = fvm_cv_discretize(cells, gprop.default_parameters);

EXPECT_THROW(fvm_build_mechanism_data(gprop, cells, D), arb::cable_cell_error);
}
{
auto system = two_cell_system();

// Set a density mechanism instead of a reversal potential mechanism
gprop.default_parameters.reversal_potential_method["na"] = "pas";

auto cells = system.cells();
check_two_cell_system(cells);
fvm_cv_discretization D = fvm_cv_discretize(cells, gprop.default_parameters);

EXPECT_THROW(fvm_build_mechanism_data(gprop, cells, D), arb::cable_cell_error);
}
}

TEST(fvm_layout, mech_index) {
auto system = two_cell_system();
auto& descriptions = system.descriptions;
Expand Down