Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

pt3dstyle logical connection should be at center of soma section (instead of center of contour). #2981

Open
wants to merge 10 commits into
base: master
Choose a base branch
from
36 changes: 27 additions & 9 deletions share/lib/hoc/import3d/import3d_gui.hoc
Original file line number Diff line number Diff line change
Expand Up @@ -1041,7 +1041,7 @@ func set_nameindex() {local i, min localobj sec
* @param $2 (optional) If set to 1, will keep a public reference to a list of strings that were executed by this method (commands).
*/

proc instantiate() {local i, j, min, haspy, ispycontext, keepCommands localobj sec, xx, yy, zz, dd, pyobj, allpyobjs
proc instantiate() {local i, j, min, haspy, ispycontext, keepCommands localobj sec, psec, xx, yy, zz, dd, pyobj, allpyobjs
commands = new List()
chk_valid()
haspy = nrnpython("import neuron")
Expand Down Expand Up @@ -1077,6 +1077,7 @@ proc instantiate() {local i, j, min, haspy, ispycontext, keepCommands localobj
// connect
for i = 0, swc.sections.count-1 {
sec = swc.sections.object(i)
psec = sec.parentsec
if (sec.is_subsidiary) { continue }
name(sec, tstr)
if (i == 0 && !ispycontext) {
Expand All @@ -1086,25 +1087,33 @@ proc instantiate() {local i, j, min, haspy, ispycontext, keepCommands localobj
execute(tstr1, $o1)
}
}
if (sec.parentsec != nil) {
name(sec.parentsec, tstr1)
if (psec != nil) {
name(psec, tstr1)
if (!ispycontext) {
sprint(tstr1, "%s connect %s(0), %g\n", tstr1, tstr, sec.parentx)
commands.append(new String(tstr1))
execute(tstr1, $o1)
} else {
pyobj.neuron._connect_sections_in_obj($o1, tstr, 0, tstr1, sec.parentx)
}
} else {
pyobj.neuron._connect_sections_in_obj($o1, tstr, 0, tstr1, sec.parentx)
}
}
// 3-d point info
if (sec.first == 1) {
// if psec is contour, update logical connection
if (psec != nil) {
if (psec.iscontour_) {
for j = 0, 2 {
sec.raw.x[j][0] = psec.processed_contour_center.x[j]
}
}
}
nrnhines marked this conversation as resolved.
Show resolved Hide resolved
if (ispycontext) {
pyobj.neuron._pt3dstyle_in_obj($o1, tstr, sec.raw.x[0][0], sec.raw.x[1][0], sec.raw.x[2][0])
} else {
sprint(tstr1, "%s { pt3dstyle(1, %.8g, %.8g, %.8g) }\n", tstr, sec.raw.x[0][0], sec.raw.x[1][0], sec.raw.x[2][0])
commands.append(new String(tstr1))
execute(tstr1, $o1)
}
}
}
j = sec.first
xx = sec.raw.getrow(0).c(j)
Expand Down Expand Up @@ -1199,12 +1208,13 @@ proc mksubset() {
execute(tstr1, $o1)
}

proc contour2centroid() {local i, j, imax, imin, ok localobj mean, pts, d, max, min, tobj, rad, rad2, side2, pt, major, m, minor
proc contour2centroid() {local i, j, imax, imin, ok localobj sec, mean, pts, d, max, min, tobj, rad, rad2, side2, pt, major, m, minor
if (object_id($o5.contour_list)) {
contourstack2centroid($o1, $o2, $o3, $o4, $o5)
return
}
mean = swc.sections.object(0).contourcenter($o1, $o2, $o3)
sec = swc.sections.object(0)
mean = sec.contourcenter($o1, $o2, $o3)
if (g != nil) {
g.beginline(6,1)
for i=0, $o1.size-1 {
Expand Down Expand Up @@ -1307,6 +1317,14 @@ if (g != nil) g.line(tobj.x[0], tobj.x[1]) g.flush
for i=1,3 { $oi = pts.getrow(i-1) }
// print d d.printf print rad rad.printf
// print side2 side2.printf print rad2 rad2.printf

// store the center of the processed contour for later
// updating of child logical connection to center of section
j = $o1.size-1
for i = 1, 3 {
mean.x[i-1] = ($oi.x[0] + $oi.x[j])/2
}
sec.processed_contour_center = mean.c()
nrnhines marked this conversation as resolved.
Show resolved Hide resolved
}

proc contourstack2centroid() {local i, j, area, d localobj c
Expand Down
6 changes: 5 additions & 1 deletion share/lib/hoc/import3d/import3d_sec.hoc
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,11 @@ public stk_triang_vec, stk_triang_area, is_subsidiary
public volatile2, contourcenter, ztrans, approximate_contour_by_circle
public pl_point, insrt, set_pt, stk_center, accurate_triangle_area
objref raw, xyz, d, g, parentsec, contour_list, this, stk_triang_vec
// processed_contour_center vector introduced because it may differ
// from the raw contour center
public processed_contour_center
objref processed_contour_center

proc init() {
is_subsidiary = 0
ztrans = 0
Expand Down Expand Up @@ -184,7 +189,6 @@ proc rotate() {
}
}


// a utility function
obfunc contourcenter() {local i localobj mean, pts, perim, d
// convert contour defined by $o1, $o2, $o3 vectors to
Expand Down
7 changes: 4 additions & 3 deletions src/nrnpython/nrnpy_hoc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2864,9 +2864,10 @@ extern "C" NRN_EXPORT PyObject* get_plotshape_data(PyObject* sp) {
void* that = pho->ho_->u.this_pointer;
#if HAVE_IV
IFGUI
spi = ((ShapePlot*) that);
} else {
spi = ((ShapePlotData*) that);
spi = ((ShapePlot*) that);
}
else {
spi = ((ShapePlotData*) that);
nrnhines marked this conversation as resolved.
Show resolved Hide resolved
ENDGUI
#else
spi = ((ShapePlotData*) that);
Expand Down
3 changes: 2 additions & 1 deletion test/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -313,7 +313,8 @@ if(NRN_ENABLE_PYTHON)
GROUP hoctests
NAME ${name}_${ext} ${${ext}_preload} # PRELOAD_SANITIZER for Python
COMMAND ${${ext}_exe} "${hoc_script}"
SCRIPT_PATTERNS "${hoc_script}" "tests/${name}.json" ${${ext}test_utils})
SCRIPT_PATTERNS "${hoc_script}" "tests/${name}.json" "tests/${name}.asc"
${${ext}test_utils})
endforeach()
endforeach()

Expand Down
24 changes: 24 additions & 0 deletions test/hoctests/tests/test_pt3dstyle.asc
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
("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)
);
55 changes: 55 additions & 0 deletions test/hoctests/tests/test_pt3dstyle.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
from neuron import h
from math import isclose
import os


class Cell:
def __init__(self, id):
self.id = id

def __str__(self):
return "Cell_%d" % self.id


cell = Cell(0)
h.load_file("stdrun.hoc")
h.load_file("import3d.hoc")
nl = h.Import3d_Neurolucida3()
nl.quiet = 1
dir_path = os.path.dirname(os.path.realpath(__file__))
fname = os.path.join(dir_path, "test_pt3dstyle.asc")
nl.input(fname)
import_neuron = h.Import3d_GUI(nl, 0)
import_neuron.instantiate(cell)


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


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 allpts():
return [vec3d(s) for s in h.allsec()]


stdpts = allpts()
stdlogcon = logcon(cell.axon[0])

h.define_shape()

assert stdpts == allpts()
# The logical connection is only accurate to float32 resolution
print(stdlogcon)
print(logcon(cell.axon[0]))
nrnhines marked this conversation as resolved.
Show resolved Hide resolved
# assert stdlogcon == logcon(cell.axon[0])
for i, val in enumerate(logcon(cell.axon[0])[1]):
assert isclose(stdlogcon[1][i], val, rel_tol=1e-7)
Loading