Somas not being positioned properly

Using the graphical user interface to build and exercise models. Includes customizing the GUI by writing a little bit of hoc or Python
Post Reply
opdalex
Posts: 9
Joined: Tue Sep 26, 2023 9:16 am

Somas not being positioned properly

Post by opdalex »

Hi!

I am attempting to place a grid of cells, all duplicates from one neurolucida morphology, in a shapeplot in NEURON. My issue is that the somas do not move in synchronization with their dendritic trees when I use the "_set_position" function from the Ball-and-stick tutorial (link: https://neuron.yale.edu/neuron/docs/bal ... del-part-3). When in shapeplot, it appears to me as if the somas move exactly half of the grid distance given compared to their dendritic trees. I have attempted to solve this by altering the "_set_position" function, but have been unsuccessful.

Here are some images of my issue. The first is what happens when using the original "_set_position" function, the others are the result of an alternative function I tested. Image link: https://universityofbergen-my.sharepoin ... w?e=TjZ9Vi

This is the code I use to create a grid:

Code: Select all

from neuron import h, gui
from neuron.units import ms, mV
from AII_class_v2 import AmacrineAII as AII
import sys
h.load_file('stdrun.hoc')
h.load_file("stdlib.hoc")

morphology = sys.argv[1]
x, y = 2, 2 #matrix 
distance = 300
cells = []

counter = 0
for row in range(x):
    for col in range(y):
        counter += 1
        new_cell = AII(morphology, counter)
        new_cell.set_position(row * distance, 0, col * distance)
        cells.append(new_cell)
        
ps = h.PlotShape(True)
ps.variable('v')
ps.scale(-80, 60)
ps.show(0)
ps.exec_menu('Shape Plot')
h.fast_flush_list.append(ps)
This is the original "_set_position":

Code: Select all

def _set_position(self, x, y, z):
        for sec in self.all:
            for i in range(sec.n3d()):
                sec.pt3dchange(i,
                               x - self.x + sec.x3d(i),
                               y - self.y + sec.y3d(i),
                               z - self.z + sec.z3d(i),
                              sec.diam3d(i))
        self.x, self.y, self.z = x, y, z
This is one of the alternative ways I tested:

Code: Select all

def _set_position(self, x, y, z):
        for sec in self.soma:
            for i in range(sec.n3d()):
                sec.pt3dchange(i,
                               2 * (x - self.x) + sec.x3d(i),
                               2 * (y - self.y) + sec.y3d(i),
                               2 * (z - self.z) + sec.z3d(i),
                              sec.diam3d(i))
                
        for sec in self.dend:
            for i in range(sec.n3d()):
                sec.pt3dchange(i,
                               x - self.x + sec.x3d(i),
                               y - self.y + sec.y3d(i),
                               z - self.z + sec.z3d(i),
                              sec.diam3d(i))
        
        self.x, self.y, self.z = x, y, z
Hope to hear from you soon!
ted
Site Admin
Posts: 6314
Joined: Wed May 18, 2005 4:50 pm
Location: Yale University School of Medicine
Contact:

Re: Somas not being positioned properly

Post by ted »

First, something unrelated:
h.load_file('stdrun.hoc')
h.load_file("stdlib.hoc")
is unnecessary if you have already imported gui from neuron

Now something related, although not necessarily the cause of the symptom you report: why iterate over x and y

Code: Select all

for row in range(x):
    for col in range(y):
if you're then going to specify x and z coordinates?

Code: Select all

       new_cell.set_position(row * distance, 0, col * distance)
opdalex
Posts: 9
Joined: Tue Sep 26, 2023 9:16 am

Re: Somas not being positioned properly

Post by opdalex »

I have to state that this mapping is as intended, and of little functional importance.

Since the question came up, however, some things are needed to explain this unintuitive x, y -> x, z mapping. First of all, the cell morphology I am using is positioned such that the soma is above the dendritic tree in an upright position on the GUI y axis. My intention was to generate a shape plot that first revealed one row of cells, standing upright, then to rotate in the GUI manually to see the grid in the GUI x, z axis with the somas pointing towards the user. I can see that the mapping is confusing, I merely thought of the abstract grid in x, y form, though it is really x, z in the GUI.
ted
Site Admin
Posts: 6314
Joined: Wed May 18, 2005 4:50 pm
Location: Yale University School of Medicine
Contact:

Re: Somas not being positioned properly

Post by ted »

I have to state that this mapping is as intended, and of little functional importance.
Yes, it is of no functional imporance to the computer, but it will be a potential source of confusion to those who may read or reuse your code in the future. It's never a good idea to deliberately embed confusing stuff in code. If you want cells to be distributed over the xz plane, write code that iterates over x and z, and maybe also include a comment that says why you want the cells to be distributed over the xz plane.
opdalex
Posts: 9
Joined: Tue Sep 26, 2023 9:16 am

Re: Somas not being positioned properly

Post by opdalex »

You are right, of course, this piece of code is not written in the best manner. Sorry if it was a source of confusion.

Possibly related to the issue, I am using Windows 11, python 3.9.16 and NEURON 8.2.0. I saw a similar set of circumstances in this post: viewtopic.php?t=4449, and as I get the same error

Code: Select all

OSError: exception: access violation reading 0x0000000000000010
when attempting to combine shape plot and pyplot, I thought the setup might be relevant here as well.

I will test my code on a linux machine as soon as I can, hopefully the issue disappears.
ted
Site Admin
Posts: 6314
Joined: Wed May 18, 2005 4:50 pm
Location: Yale University School of Medicine
Contact:

Re: Somas not being positioned properly

Post by ted »

Interesting. There has been a lot of development since those versions; is there a reason you can't use NEURON 8.2.2?


Marginally related thoughts:

IMO _set_position is more code than necessary to do the job. For any cell instance, it should be sufficient to pt3dchange just the 3d points that belong to its root section, then execute h.define_shape().

"What about the caveat that 'This may not work right when a branch is connected to the interior of a parent section'?"

With one exception, nobody should be writing code that attaches a child section to an internal node of its parent (because changing nseg could move the location to which the child is attached). That exception is when the child belongs to a spine, and there's an easy workaround: don't attach spines until you have moved your cell to the desired location. And there's a way to prevent nseg changes from moving the child's attachment site: increase nseg by an odd multiple, e.g. 3, because that will merely add new nodes between existing internal nodes, while leaving the locations of existing nodes unchanged.

So instead of _set_postion, here's what I'd do instead:

Code: Select all

create each cell instance and append it to the list of cells

for each cell in the list of cells:
  translate each 3d point of the root section by the desired amount

h.define_shape() # after all root sections have been translated
I just did that with a model cell and it worked fine.

So, given a model cell, how do you discover its root section? You could read the code that defines the topology of the cell--but there's an easier way. If you know that the model cell has a section called foo, then
foo.wholetree() returns a list whose first element is the root section. Example: you have a model cell called pyr that is an instance of some class, and you know that pyr contains a section called dend. Then
pyr.dend.wholetree()
is a list whose first element is the section whose 3d points you need to translate.

BTW, define_shape executes at the speed of compiled code, whereas using Python to iterate over all 3d points etc. executes at the speed of the Python interpreter.
opdalex
Posts: 9
Joined: Tue Sep 26, 2023 9:16 am

Re: Somas not being positioned properly

Post by opdalex »

The alternative method you described worked well, the cells are positioned as I intended without any off-set somas.

I replaced _set_position with this function:

Code: Select all

def set_position(self, x, y, z):
        soma = self.soma[0]
        root = soma.wholetree()[0]
        for i in range(root.n3d()):
            root.pt3dchange(i,
                           (x - self.x) + root.x3d(i),
                           (y - self.y) + root.y3d(i),
                           (z - self.z) + root.z3d(i),
                          root.diam3d(i))
            
        self.x, self.y, self.z = x, y, z    
        h.define_shape() # after all root sections have been translated
Also, there is no particular reason for not using the latest NEURON edition, so I will update.

Thank you so much for helping!
ted
Site Admin
Posts: 6314
Joined: Wed May 18, 2005 4:50 pm
Location: Yale University School of Medicine
Contact:

Re: Somas not being positioned properly

Post by ted »

You're quite welcome. Thank you for using NEURON in your research!
Post Reply