neuronsimulator / nrn

NEURON Simulator
http://nrn.readthedocs.io
Other
381 stars 114 forks source link

Wrong logical connection points for cell imported from neurolucida file #2973

Open TorgeW opened 1 month ago

TorgeW commented 1 month ago

Context

Its common that define_shape needs to be called when working with and editing cells imported from an neurolucida file. define_shape will also be called before the visualization in NEURON.

Overview of the issue

When importing a cell from a neurolucida file (.asc) that contains a some described by a contour, the center of this contour will be used as the logical connection point for the connected processes (connected at 0.5). When calling define_shape after importing, the processes will be moved since the soma section center is at a different location then the contour center. I fixed this for myself by changing the logical connection points after importing to the center of the soma section.

Expected result/behavior

After importing a cell from a neurolucida file, define_shape should not change the cell in any way.

NEURON setup

Minimal working example - MWE

class Cell: pass

cell = Cell() h.load_file("stdrun.hoc") h.load_file("import3d.hoc") nl = h.Import3d_Neurolucida3() nl.quiet = 1 nl.input('test.asc') import_neuron = h.Import3d_GUI(nl, 0) import_neuron.instantiate(cell)

for s in cell.axon: for i in range(s.n3d()): print(i, s, s.x3d(i), s.y3d(i), s.z3d(i))

h.define_shape() print('------------------') for s in cell.axon: for i in range(s.n3d()): print(i, s, s.x3d(i), s.y3d(i), s.z3d(i))

* asc file:

("CellBody" (Color Red) (CellBody) (3.80077 3.41923 0 0) ; 1, 1 (3.81077 1.71923 0 0) ; 1, 2 (6.30077 -1.15077 0 0) ; 1, 3 (5.79077 -3.76077 0 0) ; 1, 4 (2.48077 -6.86077 0 0) ; 1, 5 (-0.849229 -8.24077 0 0) ; 1, 6 (-4.37923 -7.22077 0 0) ; 1, 7 (-5.62923 -4.94077 0 0) ; 1, 8 (-5.19923 -0.95077 0 0) ; 1, 9 (-3.06923 4.74923 0 0) ; 1, 10 (-1.70923 6.51923 0 0) ; 1, 11 (-2.10923 7.95923 0 0) ; 1, 12 (0.760771 8.75923 0 0) ; 1, 13 );

( (Color Blue) (Axon) (-1.10012 -6.51191 1.75185 1.33) (-1.39509 -8.25791 2.22157 1.33) (-2.03149 -16.6016 2.41259 0.66) );

* script output:

0 <main.Cell object at 0x7ff4c6e7ef10>.axon[0] -1.100119948387146 -6.5119099617004395 1.7518500089645386 1 <main.Cell object at 0x7ff4c6e7ef10>.axon[0] -1.3950899839401245 -8.257909774780273 2.2215700149536133 2 <main.Cell object at 0x7ff4c6e7ef10>.axon[0] -2.0314900875091553 -16.601600646972656 2.4125900268554688

0 <main.Cell object at 0x7ff4c6e7ef10>.axon[0] -1.2292762994766235 -5.1274309158325195 1.7518500089645386 1 <main.Cell object at 0x7ff4c6e7ef10>.axon[0] -1.524246335029602 -6.8734307289123535 2.2215700149536133 2 <main.Cell object at 0x7ff4c6e7ef10>.axon[0] -2.160646438598633 -15.217121124267578 2.4125900268554688

nrnhines commented 1 month ago

No fix yet, but it seems worthwhile to document some of my diagnostic results so far which more closely isolate the underlying puzzle to me. I.e. why does the logical connection point change (with define_shape) when the soma 3d points do not change. Note that the logical connection point should always track the location of the parent connection (3-d location of center of parent segment). The distance between logical connection point and first 3-d point of a section should be invariant. Thus, when one moves the root section (usually soma) that moves the rest of the tree a corresponding amount (and updates the logical connection point to keep the invariant).

Anyway, what I observe is that the soma 3d points are exactly the same before and after define_shape. Also, of course, that means the average and center of the soma points are the same. However the logical connection point starts out wrong and after define_shape gets updated to be the same as the soma center point.

The observations are: before diam_shape

average  [-0.5143091442684332, 0.224248896752085, 0.0, 7.583558775129772]
center  [-0.5143091678619385, 0.22424888610839844, 0.0, 2.4370133876800537]
logcon  (1.0, [-0.3851528465747833, -1.1602301597595215, 0.0])

after diam_shape

average  [-0.5143091442684332, 0.224248896752085, 0.0, 7.583558775129772]
center  [-0.5143091678619385, 0.22424888610839844, 0.0, 2.4370133876800537]
logcon  (1.0, [-0.5143091678619385, 0.22424888610839844, 0.0])

Note that the code for those calculations is

def logcon(s):
    lcf = tuple([h.ref(0.) for _ in range(3)])
    lc = h.pt3dstyle(1, *lcf, sec=s)
    return lc, [ref[0] for ref in lcf]

printed by print("logcon ", logcon(cell.axon[0])) and

def vec3d(s):
    vecs =[[] for _ in range(4)] # x, y ,z, d
    for i, f in enumerate([h.x3d, h.y3d, h.z3d, h.diam3d]):
        for j in range(s.n3d()):
            vecs[i].append(f(j))
    return vecs

def paverage():
    soma3d = vec3d(cell.soma[0])
    print("average ", [sum(vec)/len(vec) for vec in soma3d])
    print("center ", [(vec[0] + vec[-1])/2.0 for vec in soma3d])
nrnhines commented 1 month ago

The problem is that the center of the original soma neurolucida contour is not the same as the center of the processed contour that ends up becoming the linear chain of 3d soma points. The former is

-0.385153   -1.16023    0

and looks like (Note the tip of the green line) image

and the latter is (see the green dot on the screenshot)

-0.5143091678619385, 0.22424888610839844, 0.0

image

nrnhines commented 1 month ago

I'm wondering if the least disruptive fix is to construct the processed soma (defined by the h.soma[0] 3-d points) so that the processed soma has the same center as the original neurolucida contour.

TorgeW commented 1 month ago

What would be the issue with updating the style (logical connection points) after the soma section (points) is created from the counter with the real section center?

Setting the processed soma center to the same center as the original neurolucida contour would not work. You would need to translate the full cell then, which would be especially bad because the coordinates from the file wouldnt match the loaded point coordinates anymore, which isnt a problem inn itself but would throw people off for sure.

If you are talking about changing the way the contour is turned into the section, to more closely match the contour shape, that would work I guess if one finds a way to preserve the center in that process, although it would change the soma shape, which is a change that would effect anyone using neurolucida files. While correcting the logical connection points is only noticed when using define shape in combination with neurolucida files.

nrnhines commented 1 month ago

Let me know if you agree with the fix embodied in #2981

TorgeW commented 1 month ago

Looks good to me as far as I understand it.