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

Different behaviours from loading an ascii morphology file in hoc and in python #2602

Closed
WeinaJi opened this issue Nov 7, 2023 · 2 comments · Fixed by #2605 or #2609
Closed

Different behaviours from loading an ascii morphology file in hoc and in python #2602

WeinaJi opened this issue Nov 7, 2023 · 2 comments · Fixed by #2605 or #2609
Assignees
Labels

Comments

@WeinaJi
Copy link
Collaborator

WeinaJi commented Nov 7, 2023

Context

Issue 1

In Blue Brain, we read an ascii morphology file (old_morph.asc in Archive.zip) using a HOC script

{load_file("import3d.hoc")}

begintemplate GEN_etype
public init
objref this
public soma
create soma[1]
public all, somatic
objref all, somatic

proc init() { localobj morph, i3d
    all = new SectionList()
    somatic = new SectionList()

    morph = new Import3d_Neurolucida3()
    morph.input($s1)
    i3d = new Import3d_GUI(morph, 0)
    i3d.instantiate(this)
}
endtemplate GEN_etype

objref cellref
cellref=new GEN_etype("old_morph.asc")

which returns the error

nrniv: undefined variable nan
 in morph_test.hoc near line 2
 }
  ^
        Import3d_GUI[0].execute("soma { pt3...", GEN_etype[0])
      Import3d_GUI[0].instantiate(GEN_etype[0])
    GEN_etype[0].init("old_morph.asc")
hoc_run1: caught exception: hoc_execerror: undefined variable nan

What does the error mean?

On the other hand, loading the same file in Python works without any issue.

from neuron import h

h.load_file("import3d.hoc")

class GEN_etype:
    def __init__(self, morph_file):
        morph = h.Import3d_Neurolucida3()
        morph.input(morph_file)
        i3d = h.Import3d_GUI(morph, 0)
        i3d.instantiate(self)

cell = GEN_etype("old_morph.asc")

Expected result/behavior

I would expect that Python also returns an error in this case. And is it possible to improve the error msg? It is hard for us to investigate our input morphology file.

Issue 2 or question

When running the above HOC and Python scripts to load a different version of the same morphology (new_morph.asc in Archive.zip), both loading are successful. The diff between the two versions of the morphology is

$ diff new_morph.asc old_morph.asc
4,9c4,6
<   (-20.539806366 -20.539806366 0.000000000 0.000000000)
<   (0.000000000 -20.539806366 0.000000000 0.000000000)
<   (20.539806366 -20.539806366 0.000000000 0.000000000)
<   (20.539806366 20.539806366 0.000000000 0.000000000)
<   (0.000000000 20.539806366 0.000000000 0.000000000)
<   (-20.539806366 20.539806366 0.000000000 0.000000000)
---
>   (-20.539806366 0.000000000 0.000000000 41.079612732)
>   (0.000000000 0.000000000 0.000000000 41.079612732)
>   (20.539806366 0.000000000 0.000000000 41.079612732)

It seems that NEURON expects a contour for the ascii format. Can someone explain why?

NEURON setup

  • Version: 3bbdd8d
  • Installation method: cmake build
  • OS + Version: Ubuntu
@WeinaJi WeinaJi added the bug label Nov 7, 2023
@nrnhines nrnhines self-assigned this Nov 7, 2023
@nrnhines
Copy link
Member

nrnhines commented Nov 7, 2023

It seems that NEURON expects a contour for the ascii format.

That is correct. When a top level object begins with ("CellBody" or ("Cell Body" or ("soma" the object points are interpreted as a contour. In this case, since the three points are in a straight line, the internal arithmetic generates a nan (not a number) floating point error. Apparently that is ignored by Python but can be seen by adding a second line to the python file of

h.nrn_feenableexcept(1)

With that, one can use gdb to find the location of the floating point exception. e.g.

$ gdb nrniv
...
(gdb) run -python test.py
...
9 lines read

Thread 1 "nrniv" received signal SIGFPE, Arithmetic exception.
0x00007ffff7588048 in operator() (__closure=0x7fffffffc4cf, d=@0x5555581fd900: 0) at /home/hines/neuron/nrn/src/ivoc/ivocvect.cpp:2372
2372	        std::for_each(x->begin(), x->end(), [](double& d) { d /= *getarg(1); });
(gdb) bt
#0  0x00007ffff7588048 in operator() (__closure=0x7fffffffc4cf, 
    d=@0x5555581fd900: 0) at /home/hines/neuron/nrn/src/ivoc/ivocvect.cpp:2372
#1  0x00007ffff758dbcb in std::for_each<__gnu_cxx::__normal_iterator<double*, std::vector<double> >, v_div(void*)::<lambda(double&)> >(__gnu_cxx::__normal_iterator<double*, std::vector<double, std::allocator<double> > >, __gnu_cxx::__normal_iterator<double*, std::vector<double, std::allocator<double> > >, struct {...}) (__first=0, __last=1.6304166312761136e-322, __f=...)
    at /usr/include/c++/11/bits/stl_algo.h:3820
#2  0x00007ffff75880b0 in v_div (v1=0x5555581fb830)
    at /home/hines/neuron/nrn/src/ivoc/ivocvect.cpp:2372

Frame 2 happens to be

#2  0x00007ffff75880b0 in v_div (v1=0x5555581fb830)
    at /home/hines/neuron/nrn/src/ivoc/ivocvect.cpp:2372
2372	        std::for_each(x->begin(), x->end(), [](double& d) { d /= *getarg(1); });
(gdb) p *getarg(1)
No symbol "getarg" in current context.
(gdb) p *hoc_getarg(1)
$1 = 0

There are only three calls to Vector.div in the import3d code

import3d$ grep -r -w div
import3d_sec.hoc:	x.index(x, i1).div(norm)
import3d_sec.hoc:	y.index(y, i1).div(norm)
import3d_gui.hoc:	minor.div(minor.mag)

clearly div should raise an error if its arg is 0. That would give a python and hoc backtrace.

@WeinaJi WeinaJi linked a pull request Nov 8, 2023 that will close this issue
@WeinaJi
Copy link
Collaborator Author

WeinaJi commented Nov 8, 2023

Thank @nrnhines for the clear answer!
I open PR #2605 to raise an error in v_div so that it throws in both hoc and python by default.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
2 participants