Yes, it will be much easier to use i_membrane_. With regard to discovering where segment centers are located, the simplest approach is to treat each section's pt3d data as three piecewise linear functions of range, and use the Vector class's interpolate method to find the xyz values that correspond to normalized path lengths that are {(0.5+i)i/nseg for i=0,nseg-1) from the 0 end of each section. It is also useful to use a SectionList that holds all the sections that are of interest, and an NMODL-specified density mechanism to hold the results of interpolation.
Here's an NMODL-specified density mechanism, which is in a file called locus.mod:
Code: Select all
NEURON {
SUFFIX locus
RANGE x, y, z
}
PARAMETER {
x = 0 (1) : spatial coords
y = 0 (1)
z = 0 (1)
}
Here's a procedure that calculates the xyz coordinates of a model cell's internal nodes. It expects that locus has been inserted into all sections of interest, that all sections have been interest have been discretized (i.e. that their nseg values have been asserted), and it expects to be called with an argument that is a SectionList to which all sections of interest have been appended:
Code: Select all
proc interploci() { local ii, nn, xr localobj xx, yy, zz, length, xint, yint, zint, range
// xx, yy, zz, length hold the original, irregularly spaced data
// xint, yint, zint, range hold the interpolated data, and are spaced at regular intervals
forsec $o1 {
// get the data for the section
nn = n3d()
xx = new Vector(nn)
yy = new Vector(nn)
zz = new Vector(nn)
length = new Vector(nn)
for ii = 0,nn-1 {
xx.x[ii] = x3d(ii)
yy.x[ii] = y3d(ii)
zz.x[ii] = z3d(ii)
length.x[ii] = arc3d(ii)
}
// to use Vector class's .interpolate()
// must first scale the independent variable
// i.e. normalize length along centroid
length.div(length.x[nn-1])
// initialize the destination "independent" vector
range = new Vector(nseg)
range.indgen(1/nseg)
range.add(1/(2*nseg))
// length contains the normalized distances of the pt3d points
// along the centroid of the section. These are spaced at irregular intervals.
// range contains the normalized distances of internal nodes
// from the section's 0 end. These are spaced at regular intervals.
// Ready to interpolate.
xint = new Vector(nseg) // hold coords of internal nodes
yint = new Vector(nseg)
zint = new Vector(nseg)
xint.interpolate(range, length, xx)
yint.interpolate(range, length, yy)
zint.interpolate(range, length, zz)
// for each internal node, assign the xyz values to x_locus, y_locus, z_locus
for ii = 0, nseg-1 {
xr = range.x[ii]
x_locus(xr) = xint.x[ii]
y_locus(xr) = yint.x[ii]
z_locus(xr) = zint.x[ii]
}
}
}
After calling interploci with an appropriate argument, each segment's x_locus, y_locus, and z_locus range variables will equal the xyz coordinates of that segment's center.
Here's a test program that you can use to verify its proper operation:
Code: Select all
load_file("nrngui.hoc")
load_file("cell.hoc") // specification of model cell
// whose sections have been appended to a List called "all"
define_shape() // do this before calculating segment centers!
forall insert locus
load_file("interploci.hoc")
interploci(all)
forsec all {
print secname()
for (x,0) print x, x_locus(x), y_locus(x), z_locus(x)
}
Be sure to read about define_shape in the Programmer's Reference! (also about any other features of hoc that you may not already know, e.g. Vector class's interpolate method).
You might try this with a toy model cell that has two or three sections of known length and orientation.