BlueBrain / BluePyOpt

Blue Brain Python Optimisation Library
https://bluepyopt.readthedocs.io/en/latest/
Other
198 stars 96 forks source link

How to override the `Morphology.instantiate` method #488

Closed Helveg closed 6 months ago

Helveg commented 6 months ago

Hi,

I do not wish to use NEURON's Import3D, as it comes with several limitations, so I'd like to implement the instantiate method of the ephys.morphologies.Morphology class myself.

Because of the strange setup with HOC templates, garbage collection refs and the like, I seem to be fighting an uphill battle against an undocumented interface. Any help would be appreciated 😄

What I have:

The problem is to get the sections transferred correctly to the damned icell HOC template (btw: NEURON makes me cry, without fail, every time). I would wish it was as simple as: setattr(icell, sectionlist_name, sections) but alas.

Here's some code to give you an idea what I'm trying:

class ArbitraryMorphology(ephys.morphologies.Morphology):
    def __init__(self, schematic: "Schematic"):
        super().__init__()
        self._schematic = schematic

    def instantiate(self, sim, icell):
        arbitrary_cell = neuron_build(self._schematic)
        for label in self._schematic.get_cable_types().keys():
            icell.__dict__[label] = arbitrary_cell.filter_sections([label])

But it keeps complaining in one way or another about:

NEURON: section in the object was deleted
 near line 0

                ^

but there's no stacktrace other than the external DEAP part, nothing of the presumably invoked process.

No amount of manipulation of the icell's attributes etc is getting me anywhere.

Helveg commented 6 months ago

It seems for now that by using CellModel(..., secarray_names=[], sectionlist_names=["tomato", "cherry", "apple"]) and then using h.SectionList.append to append all the sections created by my own factory function to the correct section lists, that the immediate problem is resolved, giving the following pseudo-code as an example for future adventurers:

class ArbitraryMorphology(ephys.morphologies.Morphology):
    def __init__(self, schematic):
        super().__init__()
        self._schematic = schematic

    def instantiate(self, sim, icell):
        # The `neuron_build` function creates the sections that I need
        arbitrary_cell = neuron_build(self._schematic)
        # My "cable types" are equivalent to the sectionlists, basically
        for label in self._schematic.get_cable_types().keys():
            section_list = getattr(icell, label)
            for section in arbitrary_cell.filter_sections([label]):
              section_list.append(section)

mechs = []
params = []
morph = ArbitraryMorphology(schematic)
model = ephys.models.CellModel(
    "banana", morph, mechs, params, secarray_names=[], seclist_names=["tomato", "cherry", "apple"]
)