hnn-core
hnn-core copied to clipboard
separating the geometry of cells/networks from the Neuron code
This has come up a few times in different contexts, most notably for the Network
class. The reason one would want to separate the geometry from the actual Neuron code are:
- it allows easy pickling of the class, necessary in the context of parallelization
- it prevents weird bugs due to the way Neuron works. Neuron holds everything in global workspace. It's better to hold the state of objects in Python as much as possible and not in HOC.
- it will allow HNN-core to be easily extensible to new kinds of neuron morphologies and networks
- it is also more future proof. If there are updates to Neuron code, we can look in specific designated spots and update the code there. If there is another differential solver engine that we want to use for running our code, it will be straightforward to switch back and forth between Neuron and the others
This came up during our discussion with @blakecaldwell and @rythorpe
I tried to come up with a prototype here. This is literally from 3 hours of hacking, so nothing is final but gives an idea what we can aspire for. I would propose a Section
, Cell
and Network
class, each with its own plot
method and create
or build_in_neuron
method.
This 200 line script demos how one could load an arbitrary cell morphology downloaded from the internet and incorporate it in HNN workflow.
I propose we start from cell.py
first since network.py
is still undergoing a few changes.
I think this is pretty much done after #322 . One thing that remains is we could write readers for different types of morphology files:
def load_morphology(fname):
from neuron import h
h.xopen(fname)
p_secs = dict()
for sec in h.allsec():
sec_name = sec.name()
p_secs[sec_name] = dict()
p_secs[sec_name]['diam'] = getattr(sec, 'diam', None)
p_secs[sec_name]['L'] = getattr(sec, 'L', None)
p_secs[sec_name]['Ra'] = getattr(sec, 'Ra', None)
p_secs[sec_name]['cm'] = getattr(sec, 'cm', None)
pts = list()
for idx in range(sec.n3d()):
pts.append([sec.x3d(idx), sec.y3d(idx), sec.z3d(idx)])
p_secs[sec_name]['pts'] = pts
cell = Cell(pos=(0., 0., 0.))
cell.p_secs = p_secs
return cell
Then the API would be so that you can do something like this:
import os.path as op
from hnn_core import load_morphology
url = 'http://cns.iaf.cnrs-gif.fr/files/CELLS/pyramidal264L.geo'
fname = 'pyramidal264L.geo'
if not op.exists(fname):
urlretrieve(url, fname)
custom_cell = load_morphology(fname)
# inside network builder
cell.build()
I think it should be fairly straightforward to read the following formats with this machinery: asc
, swc
, xml
, and hoc
/geo
:
h.Import3d_Neurolucida3()
h.Import3d_SWC_read()
h.Import3d_MorphML()
Closed by #661 and #481