Closed edovanveen closed 1 year ago
There is now a allsec-mac-nrn8
folder in https://github.com/mcdougallab/neuron-c-api-demos that demonstrates looping over NEURON's global section_list
variable, which basically defines a circularly linked list of all the sections.
The key part here is:
for (auto list_ptr = (*section_list)->next; list_ptr != *section_list; list_ptr=list_ptr->next) {
Section* sec = list_ptr->element.sec;
// check to make sure the section has properties
// missing properties means that the section has been invalidated
// but not removed
if (sec->prop) {
// we've found a real section, now let's do something
cout << " sec = " << secname(sec) << endl;
} else {
// invalidated section; we can remove it from the section_list and unref it
// it would be mostly harmless to skip this, but NEURON does not routinely
// search for and remove sections
hoc_l_delete(list_ptr);
section_unref(sec);
}
}
Here I'm simply calling cout
to print the name of the Section* sec
but we could do whatever we want once we have the Section. (Note: checking that sec->prop
is non-null is essential to make sure the section is still active, but strictly speaking we could just ignore null values.)
I believe that SectionList
objects also store their data in the same structure and the iteration should work, but I haven't tried to figure out how to get the underlying pointer to a SectionList
object's circularly linked list from C++ yet.
The plotshape-linux-nrn8
folder on neuron-c-api-demos builds two PlotShape
objects (one with no specified sections hence covering all, and one with a specified SectionList
). It then queries the PlotShape
to get the SectionList
(if specified), variables, and bounds back... loops through either the SectionList
or all sections, and displays all the info that would be needed to generate a PlotShape
3d graph.
Relative to the previous example, if sl
is an Object*
referring to a SectionList
, then instead of using the global section_list
, you'd use my_section_list = (hoc_Item**) &sl->u.this_pointer;
instead for looping over the SectionList.
I made a first version of allsec
, but it cannot yet handle invalidated sections. How do i make an invalidated section, just so I can test allsec
behaviour?
If you create a bunch of sections, then loop over allsec you should get all of them.
Suppose then that you delete a section, which you can probably do by setting it to be the currently accessed section and then calling delete_section
.
Now loop over everything. The section should not appear. If it does and isn't invalidated, check its ref count.
Then repeat the same test (of deleting a section) with a SectionList
that contains the section.
Sounds great!
Here's a comment for you: in Python, h.allsec()
is a generator; it returns sections as needed instead of returning a list of everything. I see pros (it's nice to be able to grab the ith item and you can reuse a list) and cons (have to store a MATLAB alias to everything in memory), just wanted to point out the difference and see if anyone has any opinions about which is better in the MATLAB context.
Just to point this out: the PlotShape
C++ example also loops over segments. Segments are essential for cleanly specifying e.g. membrane potential, but there's also potential for a rabbit hole of making functions work with segments. (There's a quick and dirty hack that works most of the time, which would be to replace and argument that's a segment with the x
value from a segment and push the corresponding section to the section stack... it obviously wouldn't let you do anything that takes two segments in one command -- but neither does HOC, only Python... the weirder thing would be that segments could then be misused for values between 0 and 1... but I think that may be the only real downside.)
As far as I know, iterators/generators aren't really a thing in MATLAB, although it is probably possible to make a generator-like class ourselves.
I will work on segments next.
I implemented the 'quick hack' for Segments, see example_netcon.m
in branch https://github.com/mcdougallab/matlabneuroninterface/tree/48-iterating-over-sections-and-segments. We can now do n.ExpSyn(soma(0.5))
, for example.
Implement MATLAB equivalents for: