Skip to content
Snippets Groups Projects
proxy.hpp 5.52 KiB
#pragma once

#include <any>

#include <arborio/label_parse.hpp>

#include <arbor/morph/label_dict.hpp>

#include "strprintf.hpp"

namespace pyarb {
struct label_dict_proxy {
    using str_map = std::unordered_map<std::string, std::string>;
    arb::label_dict dict;
    str_map cache;
    std::vector<std::string> locsets;
    std::vector<std::string> regions;

    label_dict_proxy() = default;

    label_dict_proxy(const str_map& in) {
        for (auto& i: in) {
            set(i.first, i.second);
        }
    }

    label_dict_proxy& add_swc_tags() {
        set("soma", "(tag 1)");
        set("axon", "(tag 2)");
        set("dend", "(tag 3)");
        set("apic", "(tag 4)");
        return *this;
    }

    label_dict_proxy(const arb::label_dict& label_dict): dict(label_dict) {
        update_cache();
    }

    label_dict_proxy(const label_dict_proxy&) = default;

    std::size_t size() const  {
        return locsets.size() + regions.size();
    }

    void import(const label_dict_proxy& other, std::string prefix = "") {
        dict.import(other.dict, prefix);

        clear_cache();
        update_cache();
    }

    void set(const std::string& name, const std::string& desc) {
        using namespace std::string_literals;
        // The following code takes an input name and a region or locset
        // description, e.g.:
        //      name='reg', desc='(tag 4)'
        //      name='loc', desc='(terminal)'
        //      name='foo', desc='(join (tag 2) (tag 3))'
        // Then it parses the description, and tests whether the description
        // is a region or locset, and updates the label dictionary appropriately.
        // Errors occur when:
        //  * a region is described with a name that matches an existing locset
        //    (and vice versa.)
        //  * the description is not well formed, e.g. it contains a syntax error.
        //  * the description is well-formed, but describes neither a region or locset.
        try {
            // Evaluate the s-expression to build a region/locset.
            auto result = arborio::parse_label_expression(desc);
            if (!result) { // an error parsing / evaluating description.
                throw result.error();