def get_nseg( mysec ): """ return the number of segments necesary to sample the smallest distance between 2 consequtive 3D coordinates in a segment according to the Nysquid criterum (in our case 2 times smaller than the smallest distance). """ ncoord = int( h.n3d( sec = mysec) ) # calculate distance between 0 and 1 coordinate x = h.x3d(0, sec = mysec) - h.x3d(1, sec = mysec) y = h.y3d(0, sec = mysec) - h.y3d(1, sec = mysec) z = h.z3d(0, sec = mysec) - h.z3d(1, sec = mysec) dist = sqrt(x*x + y*y + z*z) for i in range(1, ncoord-1): x = h.x3d(i, sec = mysec) - h.x3d(i+1, sec = mysec) y = h.y3d(i, sec = mysec) - h.y3d(i+1, sec = mysec) z = h.z3d(i, sec = mysec) - h.z3d(i+1, sec = mysec) value = sqrt(x*x + y*y + z*z) dist = value if value < dist else dist nseg = int((mysec.L/dist)*2.0) + 1 # odd number return( nseg )
def _indices_from_sec_x(self, sec, position): # TODO: the assert is here because the diameter is not computed correctly # unless it coincides with a 3d point, which we only know to exist at the # endpoints and because the section does not proceed linearly between # the endpoints (in general)... which affects the computation of the # normal vector as well assert(position in (0, 1)) # NOTE: some care is necessary in constructing normal vector... must be # based on end frusta, not on vector between end points if position == 0: x = h.x3d(0, sec=sec) y = h.y3d(0, sec=sec) z = h.z3d(0, sec=sec) nx = h.x3d(1, sec=sec) - x ny = h.y3d(1, sec=sec) - y nz = h.z3d(1, sec=sec) - z elif position == 1: n = int(h.n3d(sec=sec)) x = h.x3d(n - 1, sec=sec) y = h.y3d(n - 1, sec=sec) z = h.z3d(n - 1, sec=sec) # NOTE: sign of the normal is irrelevant nx = x - h.x3d(n - 2, sec=sec) ny = y - h.y3d(n - 2, sec=sec) nz = z - h.z3d(n - 2, sec=sec) else: raise RxDException('should never get here') # x, y, z = x * x1 + (1 - x) * x0, x * y1 + (1 - x) * y0, x * z1 + (1 - x) * z1 r = sec(position).diam * 0.5 plane_of_disc = geometry3d.graphicsPrimitives.Plane(x, y, z, nx, ny, nz) potential_coordinates = [] mesh = self._mesh xs, ys, zs = mesh._xs, mesh._ys, mesh._zs xlo, ylo, zlo = xs[0], ys[0], zs[0] # locate the indices of the cube containing the sphere containing the disc # TODO: write this more efficiently i_indices = [i for i, a in enumerate(xs) if abs(a - x) < r] j_indices = [i for i, a in enumerate(ys) if abs(a - y) < r] k_indices = [i for i, a in enumerate(zs) if abs(a - z) < r] sphere_indices = [(i, j, k) for i, j, k in itertools.product(i_indices, j_indices, k_indices) if (xs[i] - x) ** 2 + (ys[j] - y) ** 2 + (zs[k] - z) ** 2 < r ** 2] dx2 = self.dx * 0.5 dx = self.dx disc_indices = [] for i, j, k in sphere_indices: # a, b, c = xs[i], ys[j], zs[k] # TODO: no need to compute all; can stop when some True and some False # on_side1 = [plane_of_disc.distance(x, y, z) >= 0 for x, y, z in itertools.product([a - dx2, a + dx2], [b - dx2, b + dx2], [c - dx2, c + dx2])] # NOTE: the expression is structured this way to make sure it tests the exact same corner coordinates for corners shared by multiple voxels and that there are no round-off issues (an earlier attempt had round-off issues that resulted in double-thick discs when the frustum ended exactly on a grid plane) on_side1 = [plane_of_disc.distance(x, y, z) >= 0 for x, y, z in itertools.product([(xlo + (i - 1) * dx) + dx2, (xlo + i * dx) + dx2], [(ylo + (j - 1) * dx) + dx2, (ylo + j * dx) + dx2], [(zlo + (k - 1) * dx) + dx2, (zlo + k * dx) + dx2])] # need both sides to have at least one corner if any(on_side1) and not all(on_side1): # if we're here, then we've found a point on the disc. disc_indices.append((i, j, k)) return disc_indices
def retrieve_coordinate(sec): sec.push() x, y, z, d = [],[],[],[] area = 0 tot_points = 0 connect_next = False for i in range(int(h.n3d())): present = False x_i = h.x3d(i) y_i = h.y3d(i) z_i = h.z3d(i) d_i = h.diam3d(i) a_i = h.area(0.5) if x_i in x: ind = len(x) - 1 - x[::-1].index(x_i) # Getting the index of last value if y_i == y[ind]: if z_i == z[ind]: present = True if not present: k =(x_i, y_i, z_i) x.append(x_i) y.append(y_i) z.append(z_i) d.append(d_i) area += np.sum(a_i) h.pop_section() #adding num 3d points per section n3dpoints[sec.name()] = [np.array(x),np.array(y),np.array(z),np.array(d)] return (np.array(x),np.array(y),np.array(z),np.array(d),area)
def coarse(hoc_filename,cube_length,save_filename): # INPUT: NEURON .hoc filename to import (str), voxel cube side length (fl/str for gcd), name of file to create for mesh output (str) # >> cube_length: 'gcd' (gcd of box dims) OR floating-point (must be common factor of all box dims) # This function reads in NEURON data and passes their info to # coarse_gen(), then associates the tets of the STEPS Tetmesh object returned # to the NEURON sections which exist inside of them. # Returns a tet_hoc dictionary -- tet_hoc[tet_index] = [encapsulated hoc section references] -- as well as the Tetmesh object ## GET HOC SECTION INFO ## h.load_file(hoc_filename) allp = [[],[],[]] for s in h.allsec(): for j in range(int(h.n3d())): allp[0].append(h.x3d(j)) allp[1].append(h.y3d(j)) allp[2].append(h.z3d(j)) maxl = [max(allp[0]),max(allp[1]),max(allp[2])] minl = [min(allp[0]),min(allp[1]),min(allp[2])] bdim = [ maxl[0] - minl[0], maxl[1] - minl[1], maxl[2] - minl[2] ] print "dims: ", bdim print "mins: ", minl ## CREATE COARSE MESH ## if (cube_length == 'gcd'): gcd = fractions.gcd(fractions.gcd(bdim[0],bdim[1]),fractions.gcd(bdim[2],bdim[1])) print "GCD: ", gcd cube_length = gcd sm = coarse_gen(cube_length,bdim,minl,save_filename) ## ASSOCIATE HOC SECTIONS WITH THEIR TETS ## tet_hoc = tet_associate(sm[0]) return tet_hoc, sm[0]
def morphology_to_dict(sections, outfile=None): section_map = {sec: i for i, sec in enumerate(sections)} result = [] h.define_shape() for sec in sections: my_parent = parent(sec) my_parent_loc = -1 if my_parent is None else parent_loc(sec, my_parent) my_parent = -1 if my_parent is None else section_map[my_parent] n3d = int(h.n3d(sec=sec)) result.append({ 'section_orientation': h.section_orientation(sec=sec), 'parent': my_parent, 'parent_loc': my_parent_loc, 'x': [h.x3d(i, sec=sec) for i in xrange(n3d)], 'y': [h.y3d(i, sec=sec) for i in xrange(n3d)], 'z': [h.z3d(i, sec=sec) for i in xrange(n3d)], 'diam': [h.diam3d(i, sec=sec) for i in xrange(n3d)], 'name': sec.hname() }) if outfile is not None: with open(outfile, 'w') as f: json.dump(result, f) return result
def get_section_path(h,sec): n3d = int(h.n3d(sec=sec)) xyz = [] for i in range(0,n3d): xyz.append([h.x3d(i,sec=sec),h.y3d(i,sec=sec),h.z3d(i,sec=sec)]) xyz = np.array(xyz) return xyz
def rotateZ(self, theta): """Rotate the cell about the Z axis.""" rot_m = numpy.array([[sin(theta), cos(theta)], [cos(theta), -sin(theta)]]) for sec in self.all: for i in range(int(h.n3d())): xy = numpy.dot([h.x3d(i), h.y3d(i)], rot_m) h.pt3dchange(i, xy[0], xy[1], h.z3d(i), h.diam3d(i))
def mkmitral(gid): nrn = getmitral(gid) m = h.Mitral() m.createsec(len(nrn.dend), len(nrn.tuft)) m.subsets() m.topol(0) # need to connect secondary dendrites explicitly for i, d in enumerate(nrn.dend): # <<< check my changed if if(d.parent == nrn.soma): # <<< changed name m.secden[i].connect(m.soma(.5)) else: m.secden[i].connect(m.secden[d.parent.index](1)) # <<< changed name m.geometry() m.segments() # depends on geometry m.geometry() # again to get the hillock stylized shape fillall(nrn, m) m.segments() # again to get the proper number of segments for tuft and secden m.soma.push() m.x = h.x3d(0) m.y = h.y3d(0) m.z = h.z3d(0) h.pop_section() m.memb() return m
def get_pos_data_short(): """ Get positions of all segments currently loaded in Neuron in a simple matrix. Section position information is not available. :returns: Matrix (3 x nSegments) With x,y,z positions. :rtype: :class:`~numpy.ndarray` Example: .. code-block:: python data = get_pos_data_short() """ n = 0 for sec in h.allsec(): n += int(h.n3d()) data = np.zeros([4, n]) cnt = 0 for sec in h.allsec(): for i in xrange(int(h.n3d())): data[0, cnt] = h.x3d(i) data[1, cnt] = h.y3d(i) data[2, cnt] = h.z3d(i) data[3, cnt] = h.diam3d(i) cnt += 1 return data
def get_pos_data(): """ Get positions x, y, z for all segments and their diameter. :returns: 4 lists: x,y,z,d. One element per section where each element is a :class:`~numpy.ndarray`. Example: .. code-block:: python x,y,z,d = get_pos_data() for sec in xrange(len(x)): for seg in xrange(len(x[sec]): print x[sec][seg], y[sec][seg], z[sec][seg] """ x = [] y = [] z = [] d = [] for sec in h.allsec(): n3d = int(h.n3d()) x_i, y_i, z_i = np.zeros(n3d), np.zeros(n3d), np.zeros(n3d), d_i = np.zeros(n3d) for i in xrange(n3d): x_i[i] = h.x3d(i) y_i[i] = h.y3d(i) z_i[i] = h.z3d(i) d_i[i] = h.diam3d(i) x.append(x_i) y.append(y_i) z.append(z_i) d.append(d_i) return x, y, z, d
def retrieve_coordinate(self, sec): """Retrieve the coordinates of the section avoiding duplicates""" sec.push() x, y, z, d = [],[],[],[] tot_points = 0 connect_next = False for i in range(int(h.n3d())): present = False x_i = h.x3d(i) y_i = h.y3d(i) z_i = h.z3d(i) d_i = h.diam3d(i) # Avoiding duplicates in the sec if x_i in x: ind = len(x) - 1 - x[::-1].index(x_i) # Getting the index of last value if y_i == y[ind]: if z_i == z[ind]: present = True if not present: k =(x_i, y_i, z_i) x.append(x_i) y.append(y_i) z.append(z_i) d.append(d_i) h.pop_section() #adding num 3d points per section self.n3dpoints_per_sec[sec.name()] = len(d) return (np.array(x),np.array(y),np.array(z),np.array(d))
def rotateZ(self, theta): """Rotate the cell about the Z axis.""" for sec in self.all: for i in range(2): x = h.x3d(i) * sin(theta) + h.y3d(i) * cos(theta) y = h.x3d(i) * cos(theta) + h.y3d(i) * -sin(theta) h.pt3dchange(i, x, y, h.z3d(i), h.diam3d(i))
def retrieve_coordinates(self, sec): xyzds = [] sec.push() for ii in xrange(int(nrn.n3d())): xyzds.append([nrn.x3d(ii), nrn.y3d(ii), nrn.z3d(ii), nrn.diam3d(ii)]) nrn.pop_section() return xyzds
def build_tree(self): print "-"*100 def append_data(sec, xyzdv, parent_id, connections): """ Append data to xyzdv """ if self.var is 'v': v = sec.v else: raise AttributeError('Variable %s not implemented' % self.var) sec.push() for ii in xrange(1, int(nrn.n3d())): x = nrn.x3d(ii) y = nrn.y3d(ii) z = nrn.z3d(ii) d = nrn.diam3d(ii) xyzdv.append([x,y,z,d,v]) child_id = len(xyzdv)-1 if len(xyzdv)>1: connections.append([child_id, parent_id]) parent_id = child_id nrn.pop_section() return xyzdv, connections def append_children_data(parent, parent_id, xyzdv, connections): parent.push() sref = nrn.SectionRef() nrn.pop_section() if sref.child: for child in sref.child: xyzdv, connections = append_data(child, xyzdv, parent_id, connections) xyzdv, connections = append_children_data(parent = child, parent_id = len(xyzdv)-1, xyzdv = xyzdv, connections = connections) return xyzdv, connections # Find data and connections root_section = self.root_section() root_section.push() xyzdv = [[nrn.x3d(0), nrn.y3d(0), nrn.z3d(0), nrn.diam3d(0), root_section.v]] nrn.pop_section() xyzdv, connections = append_data(root_section, xyzdv, 0, []) xyzdv, connections = append_children_data(root_section, len(xyzdv)-1, xyzdv, connections) self.xyzdv = array(xyzdv) self.connections = array(connections)
def set_position(self, x, y, z): """ Set the base location in 3D and move all other parts of the cell relative to that location. """ for sec in self.all: for i in range(int(h.n3d())): h.pt3dchange(i, x - self.x + h.x3d(i), y - self.y + h.y3d(i), z - self.z + h.z3d(i), h.diam3d(i)) self.x, self.y, self.z = x, y, z
def computeCenter(seg): """Compute the distance from soma Assuming soma is at (0,0,0) """ # n3d returns the number of 3d points in a segment. xpoints = ypoints = zpoints = np.zeros(h.n3d(seg)) for i in range(len(xpoints)): xpoints[i] = h.x3d(i, seg) ypoints[i] = h.y3d(i, seg) zpoints[i] = h.z3d(i, seg) center = np.array([xpoints.mean(), ypoints.mean(), zpoints.mean()]) r = np.sqrt(np.mean(center)) return r, center
def make_sec_dict(self, dendTypeList): d = {} for dendType in dendTypeList: d[dendType] = {} dend = dendTypeList[dendType] for ii in range(len(dend)): dend[ii].push() idx = h.n3d() - 1 dist = np.sum( (np.array([h.x3d(idx), h.y3d(idx), h.z3d(idx)]) - self.center)**2)**0.5 d[dendType][dist] = dend[ii] h.pop_section() return d
def getMaxExtent(self, dendTypeList): maxExtent = {} for dendType in dendTypeList: dend = dendTypeList[dendType] values = [] for i in range(len(dend)): dend[i].push() for j in range(int(h.n3d())): swc = np.array([h.x3d(j), h.y3d(j), h.z3d(j)]) distance = abs(np.dot(self.new_axis, swc - self.center)) values.append(distance) h.pop_section() maxExtent[dendType] = max(values) return maxExtent
def get_soma_pos(self): n3dsoma = 0 r3dsoma = np.zeros(3) for sec in self.hobj.soma: n3d = int(h.n3d(sec=sec)) # get number of n3d points in each section r3d = np.zeros((3, n3d)) # to hold locations of 3D morphology for the current section n3dsoma += n3d for i in range(n3d): r3dsoma[0] += h.x3d(i, sec=sec) r3dsoma[1] += h.y3d(i, sec=sec) r3dsoma[2] += h.z3d(i, sec=sec) r3dsoma /= n3dsoma return r3dsoma
def find_middle_coordinates(self) : cell_list = [] self.m_coordinates = [] for n in range(self.num_neurons) : cell = [] print "Neuron ", n for i in range(self.NSize[n]): exec "cell.append(h.neuron"+str(n)+"_tree["+str(i)+"])"; cell[i].push() middle = int(h.n3d()/2)# It has to be integer!! self.m_coordinates.append((h.x3d(middle),h.y3d(middle),h.z3d(middle))) #print "Yo(", i, ") Middle is ", middle, Coordinates[i] h.pop_section() cell_list.append(cell) self.m_coordinates
def set_position(self, x, y, z): """ Set the base location in 3D and move all other parts of the cell relative to that location. """ for sec in self.all: for i in range(int(nrn.n3d())): nrn.pt3dchange(i, \ x-self.x+nrn.x3d(i), \ y-self.y+nrn.y3d(i), \ z-self.z+nrn.z3d(i), \ nrn.diam3d(i)) self.x = x self.y = y self.z = z
def CalcDistance(cmpt1, cmpt2): #cmpt means compartment cmpt1.push() sr1 = h.SectionRef(sec=cmpt1) x1 = h.x3d(0.5) y1 = h.y3d(0.5) z1 = h.z3d(0.5) h.pop_section() cmpt2.push() sr2 = h.SectionRef(sec=cmpt2) x2 = h.x3d(0.5) y2 = h.y3d(0.5) z2 = h.z3d(0.5) h.pop_section() dx = x1 - x2 dy = y1 - y2 dz = z1 - z2 distance = dx * dx + dy * dy + dz * dz #if(distance < 100.0): # print "pos %f %f %f %f %f %f dist %f"%(x1, y1, z1, x2, y2, z2,distance) return distance
def retrieve_coordinates(self, sec): """ Returns the 3D coordinates of all points in the currently accessed section. Does not calculate the center of each section (see 'center_3Dcoords' above) " """ xyzds = [] for ii in xrange(int(h.n3d(sec=sec))): xyzds.append([ h.x3d(ii, sec=sec), h.y3d(ii, sec=sec), h.z3d(ii, sec=sec), h.diam3d(ii, sec=sec) ]) return xyzds
def set_position(self, x, y, z): """ Set the base location in 3D and move all other parts of the cell relative to that location. """ for sec in self.all: # note: iterating like this changes the context for all NEURON # functions that depend on a section, so no need to specify sec= for i in range(int(h.n3d())): h.pt3dchange(i, x - self.x + h.x3d(i), y - self.y + h.y3d(i), z - self.z + h.z3d(i), h.diam3d(i)) self.x, self.y, self.z = x, y, z
def CalcDistance(cmpt1, cmpt2): #cmpt means compartment cmpt1.push() sr1 = h.SectionRef(sec=cmpt1) x1 = h.x3d(0.5) y1 = h.y3d(0.5) z1 = h.z3d(0.5) h.pop_section() cmpt2.push() sr2 = h.SectionRef(sec=cmpt2) x2 = h.x3d(0.5) y2 = h.y3d(0.5) z2 = h.z3d(0.5) h.pop_section() dx = x1 - x2 dy = y1 - y2 dz = z1 - z2 distance = dx*dx + dy*dy + dz*dz #if(distance < 100.0): # print "pos %f %f %f %f %f %f dist %f"%(x1, y1, z1, x2, y2, z2,distance) return distance
def find_middle_coordinates(self): cell_list = [] self.m_coordinates = [] for n in range(self.num_neurons): cell = [] print "Neuron ", n for i in range(self.NSize[n]): exec "cell.append(h.neuron" + str(n) + "_tree[" + str(i) + "])" cell[i].push() middle = int(h.n3d() / 2) # It has to be integer!! self.m_coordinates.append( (h.x3d(middle), h.y3d(middle), h.z3d(middle))) #print "Yo(", i, ") Middle is ", middle, Coordinates[i] h.pop_section() cell_list.append(cell) self.m_coordinates
def rotateZ(self, theta): """Rotate the cell about the Z axis.""" for sec in self.all: for i in range(int(h.n3d(sec=sec))): x = h.x3d(i, sec=sec) y = h.y3d(i, sec=sec) c = cos(theta) s = sin(theta) xprime = x * c - y * s yprime = x * s + y * c h.pt3dchange(i, xprime, yprime, h.z3d(i, sec=sec), h.diam3d(i, sec=sec), sec=sec)
def objects_by_segment(sec): """ given a section, returns a dictionary whose entries are lists of objects that should be used for distance calculations, keyed by section .. warning:: Does not currently support non-frustum based sections (i.e. no support for new 3d styles, like soma outlines) .. warning:: This assumes a 3d style exists. The safest way to call this is to call h.define_shape() first """ # TODO: fix the issue described in the warning # (when this was written, these objects were only under development) n3d = int(h.n3d(sec=sec)) length = sec.L arc3d = [h.arc3d(i, sec=sec) for i in xrange(n3d)] x3d = numpy.array([h.x3d(i, sec=sec) for i in xrange(n3d)]) y3d = numpy.array([h.y3d(i, sec=sec) for i in xrange(n3d)]) z3d = numpy.array([h.z3d(i, sec=sec) for i in xrange(n3d)]) diam3d = numpy.array([h.diam3d(i, sec=sec) for i in xrange(n3d)]) dx = length / sec.nseg objs = {} for i in xrange(sec.nseg): x_lo = i * dx x_hi = (i + 1) * dx pts = [x_lo] + _values_strictly_between(x_lo, x_hi, arc3d) + [x_hi] local_x3d = numpy.interp(pts, arc3d, x3d) local_y3d = numpy.interp(pts, arc3d, y3d) local_z3d = numpy.interp(pts, arc3d, z3d) local_diam3d = numpy.interp(pts, arc3d, diam3d) local_objs = [] for j in xrange(len(pts) - 1): x0, y0, z0, r0 = local_x3d[j], local_y3d[j], local_z3d[j], local_diam3d[j] / 2. x1, y1, z1, r1 = local_x3d[j + 1], local_y3d[j + 1], local_z3d[j + 1], local_diam3d[j + 1] / 2. if r0 == r1: local_objs.append(Cylinder(x0, y0, z0, x1, y1, z1, r0)) else: local_objs.append(Cone(x0, y0, z0, r0, x1, y1, z1, r1)) objs[sec((i + 0.5) / sec.nseg)] = local_objs return objs
def centroids_by_segment(sec): """ given a section, returns a dictionary whose entries are lists of cylinders of radius 0 that should be used for distance calculations, keyed by section .. warning:: Does not currently support non-frustum based sections (i.e. no support for new 3d styles, like soma outlines) .. warning:: This assumes a 3d style exists. The safest way to call this is to call h.define_shape() first """ # TODO: fix the issue described in the warning # (when this was written, these objects were only under development) n3d = int(h.n3d(sec=sec)) length = sec.L arc3d = [h.arc3d(i, sec=sec) for i in xrange(n3d)] x3d = numpy.array([h.x3d(i, sec=sec) for i in xrange(n3d)]) y3d = numpy.array([h.y3d(i, sec=sec) for i in xrange(n3d)]) z3d = numpy.array([h.z3d(i, sec=sec) for i in xrange(n3d)]) diam3d = numpy.array([h.diam3d(i, sec=sec) for i in xrange(n3d)]) dx = length / sec.nseg objs = {} for i in xrange(sec.nseg): x_lo = i * dx x_hi = (i + 1) * dx pts = [x_lo] + _values_strictly_between(x_lo, x_hi, arc3d) + [x_hi] local_x3d = numpy.interp(pts, arc3d, x3d) local_y3d = numpy.interp(pts, arc3d, y3d) local_z3d = numpy.interp(pts, arc3d, z3d) local_diam3d = numpy.interp(pts, arc3d, diam3d) local_objs = [] for j in xrange(len(pts) - 1): x0, y0, z0, r0 = local_x3d[j], local_y3d[j], local_z3d[ j], local_diam3d[j] / 2. x1, y1, z1, r1 = local_x3d[j + 1], local_y3d[j + 1], local_z3d[ j + 1], local_diam3d[j + 1] / 2. if x0 != x1 or y0 != y1 or z0 != z1: local_objs.append(Cylinder(x0, y0, z0, x1, y1, z1, 0)) objs[sec((i + 0.5) / sec.nseg)] = local_objs return objs
def move(self, xyz, move_mlab=False): """ Move visualization and cell """ from neuron import h if move_mlab: if self.mlab_cell: self.mlab_cell.mlab_source.x = self.mlab_cell.mlab_source.x + xyz[0] self.mlab_cell.mlab_source.y = self.mlab_cell.mlab_source.y + xyz[1] self.mlab_cell.mlab_source.z = self.mlab_cell.mlab_source.z + xyz[2] tree = h.SectionList() tree.wholetree(sec=self.root) for sec in tree: for ii in xrange(h.n3d(sec=sec).__int__()): x=h.x3d(ii,sec=sec) y=h.y3d(ii,sec=sec) z=h.z3d(ii,sec=sec) d=h.diam3d(ii,sec=sec) h.pt3dchange(ii,x+float(xyz[0]),y+float(xyz[1]),z+float(xyz[2]),d)
def set_position(self, x, y, z): """ Set the base location in 3D and move all other parts of the cell relative to that location. """ for sec in self.all: sec.push() #print('secname = %s, h.n3d = %d' % (h.secname(), h.n3d())) for i in range(int(h.n3d())): h.pt3dchange(i, x - self.x + h.x3d(i), y - self.y + h.y3d(i), z - self.z + h.z3d(i), h.diam3d(i), sec=sec) h.pop_section() #h.define_shape() self.x, self.y, self.z = x, y, z
def tet_associate(sm): # INPUT: Tetmesh object # This function associates .hoc sections to the tets which contain them, and returns the association dictionary. # It's packaged separately from the coarse() function so it can be used independently in scripts which load a Tetmesh from file # and don't need any Tetmesh to be generated from a .hoc file. tet_hoc = {} for s in h.allsec(): for j in range(int(h.n3d())): containing_tet = sm.findTetByPoint((h.x3d(j),h.y3d(j),h.z3d(j))) if (containing_tet) not in tet_hoc.keys(): tet_hoc[containing_tet] = [s] elif (containing_tet) in tet_hoc.keys(): if (s) not in tet_hoc[containing_tet]: tet_hoc[containing_tet].append(s) return tet_hoc
def z_rotation(self, theta): """ This method rotates the SimpleCell object in 3D space around the z-axis by a user-specified number of degrees. """ theta *= (pylab.pi / 180) for section in self.all: for point in range(int(h.n3d(sec=section))): xold = h.x3d(point, sec=section) yold = h.y3d(point, sec=section) xnew = xold * pylab.cos(theta) - yold * pylab.sin(theta) ynew = xold * pylab.sin(theta) + yold * pylab.cos(theta) h.pt3dchange(point, xnew, ynew, h.z3d(point, sec=section), h.diam3d(point, sec=section), sec=section)
def cell_to_morph3d(cell): """Convert a neuron cell to a morphological tree. Here we create nodes by recovering the 3d point coordinates in the section. Returns: g, root where g is a digraph rooted at soma, root is the node label for the root node ({soma.name()}_0). This will need a cleanup for nrn7.5. """ g = nx.DiGraph() stack = [cell.soma] while len(stack) > 0: sec = stack.pop() # This is roundabout way is required because nrn7.4 does not # provide explicit equivalent of `access {section}`. In nrn7.5 # the 3d functions are available as Section methods. h('access {}'.format(sec.name())) stype = nu.sectype(sec.name()) pt3d = int(h.n3d()) # pt3d = int(sec.n3d()): # only nrn >= 7.5 for ii in range(pt3d): name = '{}_{}'.format(sec.name(), ii) x = h.x3d(ii) y = h.y3d(ii) z = h.z3d(ii) d = h.diam3d(ii) g.add_node(name, x=x, y=y, z=z, r=d / 2.0, s=stype, orig=sec) for ii in range(1, pt3d): n1 = '{}_{}'.format(sec.name(), ii - 1) n2 = '{}_{}'.format(sec.name(), ii) length = ng.eucd(g, n1, n2) g.add_edge(n1, n2, length=length) current = h.SectionRef(sec=sec) if current.has_parent(): h('access {}'.format(current.parent.name())) n1 = '{}_{}'.format(current.parent.name(), int(h.n3d() - 1)) g.add_edge(n1, '{}_0'.format(sec.name()), length=0) for child in current.child: # print('Adding', child.name()) stack.append(child) return g, '{}_0'.format(cell.soma.name())
def get_alen_pos3d(sec): """Get the arclength and 3D position of the poinst in section sec. Inspired by http://www.neuron.yale.edu/ftp/ted/neuron/extracellular_stim_and_rec.zip: interpxyz.hoc Returns: length, pos where length is the list of arc3d lengths and pos the list of 3D positions (x, y, z), of the 3D points in section `sec`. """ npts = int(h.n3d(sec=sec)) pos = [] length = [] for ii in range(npts): pos.append((h.x3d(ii, sec=sec), h.y3d(ii, sec=sec), h.z3d(ii, sec=sec))) length.append(h.arc3d(ii, sec=sec)) return length, pos
def swc2morph(swc_file): """ Generate morph sectioning data from swc file. """ from neuron import h h.load_file('stdlib.hoc') h.load_file('import3d.hoc') cell = h.Import3d_SWC_read() cell.input(swc_file) i3d = h.Import3d_GUI(cell, 0) i3d.instantiate(None) sections = {} for sec in h.allsec(): sections[sec.name()] = {} sections[sec.name()]["name"] = sec.name() sr = h.SectionRef(sec=sec) if sr.has_parent(): parent = sr.parent.name() else: parent = None sections[sec.name()]["parent"] = parent children = [] for child in sr.child: children.append(child.name()) sections[sec.name()]["children"] = children x = [] y = [] z = [] d = [] n3d = int(h.n3d()) sections[sec.name()]["points"] = [] for i in range(n3d): sections[sec.name()]["points"].append( [h.x3d(i), h.y3d(i), h.z3d(i), h.diam3d(i)]) return sections
def append_data(sec, xyzdv, parent_id, connections,func,segfunc): """ Append data to xyzdv """ if not segfunc: v=func(sec) n = int(h.n3d(sec=sec)) for ii in xrange(1, n): x = h.x3d(ii,sec=sec) y = h.y3d(ii,sec=sec) z = h.z3d(ii,sec=sec) d = h.diam3d(ii,sec=sec) if segfunc: if n==1:v=func(sec(0.5)) else:v = func(sec(ii/float(n-1))) xyzdv.append([x,y,z,d,v]) child_id = len(xyzdv)-1 if len(xyzdv)>1: connections.append([child_id, parent_id]) parent_id = child_id return xyzdv, connections
def retrieve_coordinate(sec): sec.push() x, y, z = [], [], [] connect_next = False for i in range(int(h.n3d())): present = False x_i = h.x3d(i) y_i = h.y3d(i) z_i = h.z3d(i) if x_i in x: ind = len(x) - 1 - x[::-1].index(x_i) if y_i == y[ind]: if z_i == z[ind]: present = True if not present: x.append(x_i) y.append(y_i) z.append(z_i) h.pop_section() return (np.array(x),np.array(y),np.array(z))
def rotate(self, theta): """ Rotate neuron coordinates. theta = [thetax,thetay,thetaz] """ from neuron import h from mytools.rotate_xyz import rotate_xyz tree = h.SectionList() tree.wholetree(sec=self.root) for sec in tree: for ii in xrange(h.n3d(sec=sec).__int__()): x = h.x3d(ii, sec=sec) y = h.y3d(ii, sec=sec) z = h.z3d(ii, sec=sec) d = h.diam3d(ii, sec=sec) xyz_out = rotate_xyz(theta, [x, y, z]) h.pt3dchange(ii, float(xyz_out[0]), float(xyz_out[1]), float(xyz_out[2]), d)
def printSegmentTree(rootSection, indentLevel=0): from neuron import h coordCount = int(h.n3d(sec=rootSection)) coords = [] for c in range(coordCount): coords.append({ "x": h.x3d(c, sec=rootSection), "y": h.y3d(c, sec=rootSection), "z": h.z3d(c, sec=rootSection), "d": h.diam3d(c, sec=rootSection) }) sectionInfo = { "name": rootSection.name(), "L": '{:.3f}'.format(rootSection.L), "Diam": '{:.3f}'.format(rootSection.diam), "Ra": '{:.3f}'.format(rootSection.Ra), "Branch": '{:.3f}'.format(rootSection.rallbranch), "Orientation": '{:.3f}'.format(rootSection.orientation()), "segs": rootSection.nseg, "locOnParent": '{:.3f}'.format(rootSection.parentseg().x) if rootSection.parentseg() is not None else None } print(" " * indentLevel + str(sectionInfo)) print("") # for coord in coords: # print(" " * indentLevel + str(coord)) children = rootSection.children() children.sort(key=lambda sec: sec.name()) for child in children: printSegmentTree(child, indentLevel + 1)
def _walk_path(sec_ref, path): rec_pos = np.zeros([len(path), 3]) v_vec_list = [] i_vec_list = [] t_vec = h.Vector() t_vec.record(h._ref_t) for cnt, idx in enumerate(path): v_vec = h.Vector() i_vec = h.Vector() sec = sec_ref.child[idx] sec_pos = 0.5 # Find closest segment index to sec_pos. idx_seg = int((h.n3d(sec=sec) - 1) * sec_pos) rec_pos[cnt, 0] = h.x3d(idx_seg, sec=sec) rec_pos[cnt, 1] = h.y3d(idx_seg, sec=sec) rec_pos[cnt, 2] = h.z3d(idx_seg, sec=sec) v_vec.record(sec(sec_pos)._ref_v) i_vec.record(sec(sec_pos)._ref_i_membrane) v_vec_list.append(v_vec) i_vec_list.append(i_vec) sec_ref = h.SectionRef(sec=sec) return v_vec_list, i_vec_list, t_vec, rec_pos
def append_data(sec, xyzdv, parent_id, connections): """ Append data to xyzdv """ if self.var is 'v': v = sec.v else: raise AttributeError('Variable %s not implemented' % self.var) sec.push() for ii in xrange(1, int(nrn.n3d())): x = nrn.x3d(ii) y = nrn.y3d(ii) z = nrn.z3d(ii) d = nrn.diam3d(ii) xyzdv.append([x,y,z,d,v]) child_id = len(xyzdv)-1 if len(xyzdv)>1: connections.append([child_id, parent_id]) parent_id = child_id nrn.pop_section() return xyzdv, connections
def hoc2morph(hoc_file): """ Generate morph sectioning data from NEURON hoc file. """ import sys from neuron import h sections = {} h.load_file(hoc_file) for sec in h.allsec(): sections[sec.name()] = {} sections[sec.name()]["name"] = sec.name() sr = h.SectionRef(sec=sec) if sr.has_parent(): parent = sr.parent.name() else: parent = None sections[sec.name()]["parent"] = parent children = [] for child in sr.child: children.append(child.name()) sections[sec.name()]["children"] = children x = [] y = [] z = [] d = [] n3d = int(h.n3d()) sections[sec.name()]["points"] = [] for i in range(n3d): sections[sec.name()]["points"].append( [h.x3d(i), h.y3d(i), h.z3d(i), h.diam3d(i)]) return sections
def get_dict(self, geom_type): """ Create a dictionary representation of this section. :param geom_type: 'stylized': dict with L and diam, '3d': list of [x, y, z, diam] :type geom_type: str :return: Dictionary containing all parameters of a section. :rtype: dict """ # geometry if geom_type == 'stylized': geom = {'L': self.L, 'diam': self.diam} elif geom_type == '3d': geom = [[h.x3d(seg.x, sec=self), h.y3d(seg.x, sec=self), h.z3d(seg.x, sec=self), seg.diam] for seg in self] else: raise ValueError("Invalid geometry type! Should be 'stylized' or '3d'.") # mechanisms mechanism_names = [mechanism_name for mechanism_name in vars(self(.5)) if isinstance(getattr(self(.5), mechanism_name), nrn.Mechanism)] mechanisms = {name: dict() for name in mechanism_names} # saved according to name, then pos for mechanism_name in mechanism_names: for seg in self: mechanisms[mechanism_name][str(seg.x)] = \ {p: getattr(seg, p) for p in vars(getattr(seg, mechanism_name))} # parent if h.SectionRef(sec=self).has_parent(): parent = [h.SectionRef(sec=self).parent.name, h.SectionRef(sec=self).parent.index] else: parent = None return {'nseg': self.nseg, 'Ra': self.Ra, 'cm': self.cm, 'geom': geom, 'mechanisms': mechanisms, 'parent': parent, 'connection_point': self.connection_point}
def _indices_from_sec_x(self, sec, position): # TODO: the assert is here because the diameter is not computed correctly # unless it coincides with a 3d point, which we only know to exist at the # endpoints and because the section does not proceed linearly between # the endpoints (in general)... which affects the computation of the # normal vector as well assert (position in (0, 1)) # NOTE: some care is necessary in constructing normal vector... must be # based on end frusta, not on vector between end points if position == 0: x = h.x3d(0, sec=sec) y = h.y3d(0, sec=sec) z = h.z3d(0, sec=sec) nx = h.x3d(1, sec=sec) - x ny = h.y3d(1, sec=sec) - y nz = h.z3d(1, sec=sec) - z elif position == 1: n = int(h.n3d(sec=sec)) x = h.x3d(n - 1, sec=sec) y = h.y3d(n - 1, sec=sec) z = h.z3d(n - 1, sec=sec) # NOTE: sign of the normal is irrelevant nx = x - h.x3d(n - 2, sec=sec) ny = y - h.y3d(n - 2, sec=sec) nz = z - h.z3d(n - 2, sec=sec) else: raise RxDException('should never get here') # x, y, z = x * x1 + (1 - x) * x0, x * y1 + (1 - x) * y0, x * z1 + (1 - x) * z1 r = sec(position).diam * 0.5 plane_of_disc = geometry3d.graphicsPrimitives.Plane( x, y, z, nx, ny, nz) potential_coordinates = [] mesh = self._mesh xs, ys, zs = mesh._xs, mesh._ys, mesh._zs xlo, ylo, zlo = xs[0], ys[0], zs[0] # locate the indices of the cube containing the sphere containing the disc # TODO: write this more efficiently i_indices = [i for i, a in enumerate(xs) if abs(a - x) < r] j_indices = [i for i, a in enumerate(ys) if abs(a - y) < r] k_indices = [i for i, a in enumerate(zs) if abs(a - z) < r] sphere_indices = [ (i, j, k) for i, j, k in itertools.product(i_indices, j_indices, k_indices) if (xs[i] - x)**2 + (ys[j] - y)**2 + (zs[k] - z)**2 < r**2 ] dx2 = self.dx * 0.5 dx = self.dx disc_indices = [] for i, j, k in sphere_indices: # a, b, c = xs[i], ys[j], zs[k] # TODO: no need to compute all; can stop when some True and some False # on_side1 = [plane_of_disc.distance(x, y, z) >= 0 for x, y, z in itertools.product([a - dx2, a + dx2], [b - dx2, b + dx2], [c - dx2, c + dx2])] # NOTE: the expression is structured this way to make sure it tests the exact same corner coordinates for corners shared by multiple voxels and that there are no round-off issues (an earlier attempt had round-off issues that resulted in double-thick discs when the frustum ended exactly on a grid plane) on_side1 = [ plane_of_disc.distance(x, y, z) >= 0 for x, y, z in itertools.product( [(xlo + (i - 1) * dx) + dx2, (xlo + i * dx) + dx2], [(ylo + (j - 1) * dx) + dx2, (ylo + j * dx) + dx2], [(zlo + (k - 1) * dx) + dx2, (zlo + k * dx) + dx2]) ] # need both sides to have at least one corner if any(on_side1) and not all(on_side1): # if we're here, then we've found a point on the disc. disc_indices.append((i, j, k)) return disc_indices
def position(self, x, y, z): self.soma.push() for i in range(h.n3d()): h.pt3dchange(i, x-self.x+h.x3d(i), y-self.y+h.y3d(i), z-self.z+h.z3d(i), h.diam3d(i)) self.x = x; self.y = y; self.z = z h.pop_section()
def getCellParams(cell): dirCell = dir(cell) if 'all_sec' in dirCell: secs = cell.all_sec elif 'sec' in dirCell: secs = [cell.sec] elif 'allsec' in dir(h): secs = [sec for sec in h.allsec()] elif 'soma' in dirCell: secs = [cell.soma] else: secs = [] # create dict with hname of each element in dir(cell) dirCellHnames = {} for dirCellName in dirCell: try: dirCellHnames.update( {getattr(cell, dirCellName).hname(): dirCellName}) except: pass # create dict with dir(cell) name corresponding to each hname dirCellSecNames = {} for sec in secs: dirCellSecNames.update({ hname: name for hname, name in dirCellHnames.iteritems() if hname == sec.hname() }) secDic = {} synMechs = [] for sec in secs: # create new section dict with name of section secName = getSecName(sec, dirCellSecNames) if len(secs) == 1: secName = 'soma' # if just one section rename to 'soma' secDic[secName] = { 'geom': {}, 'topol': {}, 'mechs': {} } # create dictionary to store sec info # store geometry properties standardGeomParams = ['L', 'nseg', 'diam', 'Ra', 'cm'] secDir = dir(sec) for geomParam in standardGeomParams: #if geomParam in secDir: try: secDic[secName]['geom'][geomParam] = sec.__getattribute__( geomParam) except: pass # store 3d geometry sec.push() # access current section so ismembrane() works numPoints = int(h.n3d()) if numPoints: points = [] for ipoint in range(numPoints): x = h.x3d(ipoint) y = h.y3d(ipoint) z = h.z3d(ipoint) diam = h.diam3d(ipoint) points.append((x, y, z, diam)) secDic[secName]['geom']['pt3d'] = points # store mechanisms varList = mechVarList( ) # list of properties for all density mechanisms and point processes ignoreMechs = ['dist'] # dist only used during cell creation ignoreVars = [] # mechDic = {} ionDic = {} for mech in dir(sec(0.5)): if h.ismembrane( mech ) and mech not in ignoreMechs: # check if membrane mechanism if not mech.endswith('_ion'): # exclude ions mechDic[mech] = {} # create dic for mechanism properties varNames = [ varName.replace('_' + mech, '') for varName in varList['mechs'][mech] ] varVals = [] for varName in varNames: if varName not in ignoreVars: try: varVals = [ seg.__getattribute__( mech).__getattribute__(varName) for seg in sec ] if len(set(varVals)) == 1: varVals = varVals[0] mechDic[mech][varName] = varVals except: pass #print 'Could not read variable %s from mechanism %s'%(varName,mech) # store ions elif mech.endswith('_ion'): ionName = mech.split('_ion')[0] varNames = [ varName.replace('_' + mech, '').replace(ionName, '') for varName in varList['mechs'][mech] ] varNames.append('e') varVals = [] ionDic[ionName] = {} # create dic for mechanism properties for varName in varNames: varNameSplit = varName if varName not in ignoreVars: try: varVals = [ seg.__getattribute__(varNameSplit + ionName) for seg in sec ] if len(set(varVals)) == 1: varVals = varVals[0] ionDic[ionName][varNameSplit] = varVals except: pass #print 'Could not read variable %s from mechanism %s'%(varName,mech) secDic[secName]['mechs'] = mechDic if len(ionDic) > 0: secDic[secName]['ions'] = ionDic # add synapses and point neurons # for now read fixed params, but need to find way to read only synapse params pointps = {} for seg in sec: for ipoint, point in enumerate(seg.point_processes()): pointpMod = point.hname().split('[')[0] varNames = varList['pointps'][pointpMod] if any([ s in pointpMod.lower() for s in ['syn', 'ampa', 'gaba', 'nmda', 'glu'] ]): #if 'synMech' in pptype.lower(): # if syn in name of point process then assume synapse synMech = {} synMech['label'] = pointpMod + '_' + str(len(synMechs)) synMech['mod'] = pointpMod #synMech['loc'] = seg.x for varName in varNames: try: synMech[varName] = point.__getattribute__(varName) except: print 'Could not read variable %s from synapse %s' % ( varName, synMech['label']) if not [ _equal_dicts( synMech, synMech2, ignore_keys=['label']) for synMech2 in synMechs ]: synMechs.append(synMech) else: # assume its a non-synapse point process pointpName = pointpMod + '_' + str(len(pointps)) pointps[pointpName] = {} pointps[pointpName]['mod'] = pointpMod pointps[pointpName]['loc'] = seg.x for varName in varNames: try: pointps[pointpName][ varName] = point.__getattribute__(varName) # special condition for Izhi model, to set vinit=vr # if varName == 'vr': secDic[secName]['vinit'] = point.__getattribute__(varName) except: print 'Could not read %s variable from point process %s' % ( varName, pointpName) if pointps: secDic[secName]['pointps'] = pointps # store topology (keep at the end since h.SectionRef messes remaining loop) secRef = h.SectionRef(sec=sec) if secRef.has_parent(): secDic[secName]['topol']['parentSec'] = getSecName( secRef.parent().sec, dirCellSecNames) secDic[secName]['topol']['parentX'] = h.parent_connection() secDic[secName]['topol']['childX'] = h.section_orientation() h.pop_section() # to prevent section stack overflow # store section lists secLists = h.List('SectionList') if int(secLists.count()): secListDic = {} for i in xrange(int(secLists.count())): # loop over section lists hname = secLists.o(i).hname() if hname in dirCellHnames: # use python variable name secListName = dirCellHnames[hname] else: secListName = hname secListDic[secListName] = [ getSecName(sec, dirCellSecNames) for sec in secLists.o(i) ] else: secListDic = {} # celsius warning if hasattr(h, 'celsius'): if h.celsius != 6.3: # if not default value print "Warning: h.celsius=%.4g in imported file -- you can set this value in simConfig['hParams']['celsius']" % ( h.celsius) # clean h.initnrn() del (cell) # delete cell import gc gc.collect() return secDic, secListDic, synMechs
def importCell (fileName, cellName, cellArgs = None): h.initnrn() if cellArgs is None: cellArgs = [] # Define as empty list if not otherwise defined ''' Import cell from HOC template or python file into framework format (dict of sections, with geom, topol, mechs, syns)''' if fileName.endswith('.hoc'): h.load_file(fileName) if isinstance(cellArgs, dict): cell = getattr(h, cellName)(**cellArgs) # create cell using template, passing dict with args else: cell = getattr(h, cellName)(*cellArgs) # create cell using template, passing list with args secs = list(cell.allsec()) dirCell = dir(cell) elif fileName.endswith('.py'): filePath,fileNameOnly = os.path.split(fileName) # split path from filename if filePath not in sys.path: # add to path if not there (need to import module) sys.path.insert(0, filePath) moduleName = fileNameOnly.split('.py')[0] # remove .py to obtain module name exec('import ' + moduleName + ' as tempModule') in globals(), locals() # import module dynamically modulePointer = tempModule if isinstance(cellArgs, dict): cell = getattr(modulePointer, cellName)(**cellArgs) # create cell using template, passing dict with args else: cell = getattr(modulePointer, cellName)(*cellArgs) # create cell using template, passing list with args dirCell = dir(cell) if 'all_sec' in dirCell: secs = cell.all_sec elif 'sec' in dirCell: secs = [cell.sec] elif 'allsec' in dir(h): secs = [sec for sec in h.allsec()] elif 'soma' in dirCell: secs = [cell.soma] else: secs = [] sys.path.remove(filePath) else: print "File name should be either .hoc or .py file" return # create dict with hname of each element in dir(cell) dirCellHnames = {} for dirCellName in dirCell: try: dirCellHnames.update({getattr(cell, dirCellName).hname(): dirCellName}) except: pass # create dict with dir(cell) name corresponding to each hname dirCellSecNames = {} for sec in secs: dirCellSecNames.update({hname: name for hname,name in dirCellHnames.iteritems() if hname == sec.hname()}) secDic = {} synMechs = [] for sec in secs: # create new section dict with name of section secName = getSecName(sec, dirCellSecNames) if len(secs) == 1: secName = 'soma' # if just one section rename to 'soma' secDic[secName] = {'geom': {}, 'topol': {}, 'mechs': {}} # create dictionary to store sec info # store geometry properties standardGeomParams = ['L', 'nseg', 'diam', 'Ra', 'cm'] secDir = dir(sec) for geomParam in standardGeomParams: #if geomParam in secDir: try: secDic[secName]['geom'][geomParam] = sec.__getattribute__(geomParam) except: pass # store 3d geometry numPoints = int(h.n3d()) if numPoints: points = [] for ipoint in range(numPoints): x = h.x3d(ipoint) y = h.y3d(ipoint) z = h.z3d(ipoint) diam = h.diam3d(ipoint) points.append((x, y, z, diam)) secDic[secName]['geom']['pt3d'] = points # store mechanisms varList = mechVarList() # list of properties for all density mechanisms and point processes ignoreMechs = ['dist'] # dist only used during cell creation mechDic = {} sec.push() # access current section so ismembrane() works for mech in dir(sec(0.5)): if h.ismembrane(mech) and mech not in ignoreMechs: # check if membrane mechanism mechDic[mech] = {} # create dic for mechanism properties varNames = [varName.replace('_'+mech, '') for varName in varList['mechs'][mech]] varVals = [] for varName in varNames: try: varVals = [seg.__getattribute__(mech).__getattribute__(varName) for seg in sec] if len(set(varVals)) == 1: varVals = varVals[0] mechDic[mech][varName] = varVals except: pass #print 'Could not read variable %s from mechanism %s'%(varName,mech) secDic[secName]['mechs'] = mechDic # add synapses and point neurons # for now read fixed params, but need to find way to read only synapse params pointps = {} for seg in sec: for ipoint,point in enumerate(seg.point_processes()): pointpMod = point.hname().split('[')[0] varNames = varList['pointps'][pointpMod] if any([s in pointpMod.lower() for s in ['syn', 'ampa', 'gaba', 'nmda', 'glu']]): #if 'synMech' in pptype.lower(): # if syn in name of point process then assume synapse synMech = {} synMech['label'] = pointpMod + '_' + str(len(synMechs)) synMech['mod'] = pointpMod #synMech['loc'] = seg.x for varName in varNames: try: synMech[varName] = point.__getattribute__(varName) except: print 'Could not read variable %s from synapse %s'%(varName,synMech['label']) if not [_equal_dicts(synMech, synMech2, ignore_keys=['label']) for synMech2 in synMechs]: synMechs.append(synMech) else: # assume its a non-synapse point process pointpName = pointpMod + '_'+ str(len(pointps)) pointps[pointpName] = {} pointps[pointpName]['mod'] = pointpMod pointps[pointpName]['loc'] = seg.x for varName in varNames: try: pointps[pointpName][varName] = point.__getattribute__(varName) # special condition for Izhi model, to set vinit=vr # if varName == 'vr': secDic[secName]['vinit'] = point.__getattribute__(varName) except: print 'Could not read %s variable from point process %s'%(varName,pointpName) if pointps: secDic[secName]['pointps'] = pointps # store topology (keep at the end since h.SectionRef messes remaining loop) secRef = h.SectionRef(sec=sec) if secRef.has_parent(): secDic[secName]['topol']['parentSec'] = getSecName(secRef.parent().sec, dirCellSecNames) secDic[secName]['topol']['parentX'] = h.parent_connection() secDic[secName]['topol']['childX'] = h.section_orientation() h.pop_section() # to prevent section stack overflow # # store synMechs in input argument # if synMechs: # for synMech in synMechs: synMechParams.append(synMech) # store section lists secLists = h.List('SectionList') if int(secLists.count()): secListDic = {} for i in xrange(int(secLists.count())): # loop over section lists hname = secLists.o(i).hname() if hname in dirCellHnames: # use python variable name secListName = dirCellHnames[hname] else: secListName = hname secListDic[secListName] = [getSecName(sec, dirCellSecNames) for sec in secLists.o(i)] else: secListDic = {} # celsius warning if hasattr(h, 'celsius'): if h.celsius != 6.3: # if not default value print "Warning: h.celsius=%.4g in imported file %s -- you can set this value in simConfig['hParams']['celsius']"%(h.celsius, fileName) # clean h.initnrn() del(cell) # delete cell import gc; gc.collect() return secDic, secListDic, synMechs
maincelldct=[] dictcnt=0 for ij in range(len(pcpositions)): #exec('sectdict_%d={}'%ij) sectiondct={} for sec in pcsecall: segstr=str(sec) sec.push() listgrX=[] listgrY=[] listgrZ=[] for i in range(int(h.n3d())): listgrX.append(h.x3d(i)) listgrY.append(h.y3d(i)) listgrZ.append(h.z3d(i)) if str(sec)=="axonAIS" or str(sec)=="axonmyelin" or str(sec)=="axonmyelin4" or str(sec)=="axonNOR3" or str(sec)=="axoncoll2" or str(sec)=="axonmyelin3" or str(sec)=="axoncoll" or str(sec)=="axonNOR2" or str(sec)=="axonmyelin2" or str(sec)=="axonNOR" or str(sec)=="axonAISK" or str(sec)=="axonAIS": segstr=str(sec) buf=segstr else: segstr=segstr.split('.') segstr=segstr[2].split('[') if segstr[0]=='soma': buf=segstr[0] else: secname=segstr[0] segstr=segstr[1].split(']') secid=segstr[0] buf=secname+"_"+secid #print 'buf contains:', buf
def getCenter(soma): soma.push() center = np.array((h.x3d(0), h.y3d(0), h.z3d(0))) h.pop_section() return center
def calcRelativeSegCoords(self): """Calculate segment coordinates from 3d point coordinates Used for LFP calc (one per population cell; assumes same morphology)""" from .. import sim localPopGids = list( set(sim.net.gid2lid.keys()).intersection(set(self.cellGids))) if localPopGids: cell = sim.net.cells[sim.net.gid2lid[localPopGids[0]]] else: return -1 ix = 0 # segment index p3dsoma = cell.getSomaPos() nseg = sum([sec['hObj'].nseg for sec in list(cell.secs.values())]) p0 = np.zeros( (3, nseg)) # hold the coordinates of segment starting points p1 = np.zeros((3, nseg)) # hold the coordinates of segment end points d0 = np.zeros(nseg) d1 = np.zeros(nseg) for sec in list(cell.secs.values()): hSec = sec['hObj'] hSec.push() n3d = int(h.n3d()) # get number of n3d points in each section p3d = np.zeros( (3, n3d) ) # to hold locations of 3D morphology for the current section l3d = np.zeros( n3d ) # to hold locations of 3D morphology for the current section diam3d = np.zeros(n3d) # to diameters for i in range(n3d): p3d[0, i] = h.x3d(i) - p3dsoma[0] p3d[1, i] = h.y3d(i) - p3dsoma[ 1] # shift coordinates such to place soma at the origin. p3d[2, i] = h.z3d(i) - p3dsoma[2] diam3d[i] = h.diam3d(i) l3d[i] = h.arc3d(i) l3d /= hSec.L # normalize nseg = hSec.nseg l0 = np.zeros(nseg) # keep range of segment starting point l1 = np.zeros(nseg) # keep range of segment ending point for iseg, seg in enumerate(hSec): l0[iseg] = seg.x - 0.5 * 1 / nseg # x (normalized distance along the section) for the beginning of the segment l1[iseg] = seg.x + 0.5 * 1 / nseg # x for the end of the segment p0[0, ix:ix + nseg] = np.interp(l0, l3d, p3d[0, :]) p0[1, ix:ix + nseg] = np.interp(l0, l3d, p3d[1, :]) p0[2, ix:ix + nseg] = np.interp(l0, l3d, p3d[2, :]) d0[ix:ix + nseg] = np.interp(l0, l3d, diam3d[:]) p1[0, ix:ix + nseg] = np.interp(l1, l3d, p3d[0, :]) p1[1, ix:ix + nseg] = np.interp(l1, l3d, p3d[1, :]) p1[2, ix:ix + nseg] = np.interp(l1, l3d, p3d[2, :]) d1[ix:ix + nseg] = np.interp(l1, l3d, diam3d[:]) ix += nseg h.pop_section() self._morphSegCoords = {} self._morphSegCoords['p0'] = p0 self._morphSegCoords['p1'] = p1 self._morphSegCoords['d0'] = d0 self._morphSegCoords['d1'] = d1 return self._morphSegCoords
def build_tree(self, func, segfunc=False): """ func must act on a neuron section """ from numpy import array print("-" * 100) def append_data(sec, xyzdv, parent_id, connections, func, segfunc): """ Append data to xyzdv """ if not segfunc: v = func(sec) n = int(h.n3d(sec=sec)) for ii in xrange(1, n): x = h.x3d(ii, sec=sec) y = h.y3d(ii, sec=sec) z = h.z3d(ii, sec=sec) d = h.diam3d(ii, sec=sec) if 'node' in sec.name() or 'MYSA' in sec.name(): v = 1.0 else: pass if segfunc: if n == 1: v = func(sec(0.5)) else: v = func(sec(ii / float(n - 1))) xyzdv.append([x, y, z, d, v]) child_id = len(xyzdv) - 1 if len(xyzdv) > 1: connections.append([child_id, parent_id]) parent_id = child_id return xyzdv, connections def append_children_data(parent, parent_id, xyzdv, connections, func, segfunc): sref = h.SectionRef(sec=parent) if sref.child: for child in sref.child: xyzdv, connections = append_data(child, xyzdv, parent_id, connections, func, segfunc) xyzdv, connections = append_children_data( parent=child, parent_id=len(xyzdv) - 1, xyzdv=xyzdv, connections=connections, func=func, segfunc=segfunc) return xyzdv, connections # Find data and connections root_section = self.root_section() if segfunc: if root_section.nseg == 1: v = func(root_section(0.5)) else: v = func(root_section(0.0)) else: v = func(root_section) xyzdv = [[ h.x3d(0, sec=root_section), h.y3d(0, sec=root_section), h.z3d(0, sec=root_section), h.diam3d(0, sec=root_section), v ]] xyzdv, connections = append_data(root_section, xyzdv, 0, [], func, segfunc) xyzdv, connections = append_children_data(root_section, len(xyzdv) - 1, xyzdv, connections, func, segfunc) self.xyzdv = array(xyzdv) self.connections = array(connections)
def position(self, x, y, z): soma.push() for i in range(h.n3d()): h.pt3dchange(i, x-self.x+h.x3d(i), y-self.y+h.y3d(i), z-self.z+h.z3d(i), h.diam3d(i)) self.x = x; self.y = y; self.z = z h.pop_section()
def getCellParams(cell): dirCell = dir(cell) if 'all_sec' in dirCell: secs = cell.all_sec elif 'sec' in dirCell: secs = [cell.sec] elif 'allsec' in dir(h): secs = [sec for sec in h.allsec()] elif 'soma' in dirCell: secs = [cell.soma] else: secs = [] # create dict with hname of each element in dir(cell) dirCellHnames = {} for dirCellName in dirCell: try: dirCellHnames.update({getattr(cell, dirCellName).hname(): dirCellName}) except: pass # create dict with dir(cell) name corresponding to each hname dirCellSecNames = {} for sec in secs: dirCellSecNames.update({hname: name for hname,name in dirCellHnames.iteritems() if hname == sec.hname()}) secDic = {} synMechs = [] for sec in secs: # create new section dict with name of section secName = getSecName(sec, dirCellSecNames) if len(secs) == 1: secName = 'soma' # if just one section rename to 'soma' secDic[secName] = {'geom': {}, 'topol': {}, 'mechs': {}} # create dictionary to store sec info # store geometry properties standardGeomParams = ['L', 'nseg', 'diam', 'Ra', 'cm'] secDir = dir(sec) for geomParam in standardGeomParams: #if geomParam in secDir: try: secDic[secName]['geom'][geomParam] = sec.__getattribute__(geomParam) except: pass # store 3d geometry sec.push() # access current section so ismembrane() works numPoints = int(h.n3d()) if numPoints: points = [] for ipoint in range(numPoints): x = h.x3d(ipoint) y = h.y3d(ipoint) z = h.z3d(ipoint) diam = h.diam3d(ipoint) points.append((x, y, z, diam)) secDic[secName]['geom']['pt3d'] = points # store mechanisms varList = mechVarList() # list of properties for all density mechanisms and point processes ignoreMechs = ['dist'] # dist only used during cell creation ignoreVars = [] # mechDic = {} ionDic = {} for mech in dir(sec(0.5)): if h.ismembrane(mech) and mech not in ignoreMechs: # check if membrane mechanism if not mech.endswith('_ion'): # exclude ions mechDic[mech] = {} # create dic for mechanism properties varNames = [varName.replace('_'+mech, '') for varName in varList['mechs'][mech]] varVals = [] for varName in varNames: if varName not in ignoreVars: try: varVals = [seg.__getattribute__(mech).__getattribute__(varName) for seg in sec] if len(set(varVals)) == 1: varVals = varVals[0] mechDic[mech][varName] = varVals except: pass #print 'Could not read variable %s from mechanism %s'%(varName,mech) # store ions elif mech.endswith('_ion'): ionName = mech.split('_ion')[0] varNames = [varName.replace('_'+mech, '').replace(ionName,'') for varName in varList['mechs'][mech]] varNames.append('e') varVals = [] ionDic[ionName] = {} # create dic for mechanism properties for varName in varNames: varNameSplit = varName if varName not in ignoreVars: try: varVals = [seg.__getattribute__(varNameSplit+ionName) for seg in sec] if len(set(varVals)) == 1: varVals = varVals[0] ionDic[ionName][varNameSplit] = varVals except: pass #print 'Could not read variable %s from mechanism %s'%(varName,mech) secDic[secName]['mechs'] = mechDic if len(ionDic)>0: secDic[secName]['ions'] = ionDic # add synapses and point neurons # for now read fixed params, but need to find way to read only synapse params pointps = {} for seg in sec: for ipoint,point in enumerate(seg.point_processes()): pointpMod = point.hname().split('[')[0] varNames = varList['pointps'][pointpMod] if any([s in pointpMod.lower() for s in ['syn', 'ampa', 'gaba', 'nmda', 'glu']]): #if 'synMech' in pptype.lower(): # if syn in name of point process then assume synapse synMech = {} synMech['label'] = pointpMod + '_' + str(len(synMechs)) synMech['mod'] = pointpMod #synMech['loc'] = seg.x for varName in varNames: try: synMech[varName] = point.__getattribute__(varName) except: print 'Could not read variable %s from synapse %s'%(varName,synMech['label']) if not [_equal_dicts(synMech, synMech2, ignore_keys=['label']) for synMech2 in synMechs]: synMechs.append(synMech) else: # assume its a non-synapse point process pointpName = pointpMod + '_'+ str(len(pointps)) pointps[pointpName] = {} pointps[pointpName]['mod'] = pointpMod pointps[pointpName]['loc'] = seg.x for varName in varNames: try: pointps[pointpName][varName] = point.__getattribute__(varName) # special condition for Izhi model, to set vinit=vr # if varName == 'vr': secDic[secName]['vinit'] = point.__getattribute__(varName) except: print 'Could not read %s variable from point process %s'%(varName,pointpName) if pointps: secDic[secName]['pointps'] = pointps # store topology (keep at the end since h.SectionRef messes remaining loop) secRef = h.SectionRef(sec=sec) if secRef.has_parent(): secDic[secName]['topol']['parentSec'] = getSecName(secRef.parent().sec, dirCellSecNames) secDic[secName]['topol']['parentX'] = h.parent_connection() secDic[secName]['topol']['childX'] = h.section_orientation() h.pop_section() # to prevent section stack overflow # store section lists secLists = h.List('SectionList') if int(secLists.count()): secListDic = {} for i in xrange(int(secLists.count())): # loop over section lists hname = secLists.o(i).hname() if hname in dirCellHnames: # use python variable name secListName = dirCellHnames[hname] else: secListName = hname secListDic[secListName] = [getSecName(sec, dirCellSecNames) for sec in secLists.o(i)] else: secListDic = {} # celsius warning if hasattr(h, 'celsius'): if h.celsius != 6.3: # if not default value print "Warning: h.celsius=%.4g in imported file -- you can set this value in simConfig['hParams']['celsius']"%(h.celsius) # clean h.initnrn() del(cell) # delete cell import gc; gc.collect() return secDic, secListDic, synMechs
def calc_seg_coords(self): """Calculate segment coordinates from 3d point coordinates""" ix = 0 # segment index p3dsoma = self.get_soma_pos() self.psoma = p3dsoma p0 = np.zeros( (3, self.nseg)) # hold the coordinates of segment starting points p1 = np.zeros( (3, self.nseg)) # hold the coordinates of segment end points d0 = np.zeros(self.nseg) d1 = np.zeros(self.nseg) for sec in self.hobj.all: n3d = int(h.n3d()) # get number of n3d points in each section p3d = np.zeros( (3, n3d) ) # to hold locations of 3D morphology for the current section l3d = np.zeros( n3d ) # to hold locations of 3D morphology for the current section diam3d = np.zeros(n3d) # to diameters for i in range(n3d): p3d[0, i] = h.x3d(i) - p3dsoma[0] p3d[1, i] = h.y3d(i) - p3dsoma[ 1] # shift coordinates such to place soma at the origin. p3d[2, i] = h.z3d(i) - p3dsoma[2] diam3d[i] = h.diam3d(i) l3d[i] = h.arc3d(i) l3d /= sec.L # normalize nseg = sec.nseg l0 = np.zeros(nseg) # keep range of segment starting point l1 = np.zeros(nseg) # keep range of segment ending point for iseg, seg in enumerate(sec): l0[iseg] = seg.x - 0.5 * 1 / nseg # x (normalized distance along the section) for the beginning of the segment l1[iseg] = seg.x + 0.5 * 1 / nseg # x for the end of the segment p0[0, ix:ix + nseg] = np.interp(l0, l3d, p3d[0, :]) p0[1, ix:ix + nseg] = np.interp(l0, l3d, p3d[1, :]) p0[2, ix:ix + nseg] = np.interp(l0, l3d, p3d[2, :]) d0[ix:ix + nseg] = np.interp(l0, l3d, diam3d[:]) p1[0, ix:ix + nseg] = np.interp(l1, l3d, p3d[0, :]) p1[1, ix:ix + nseg] = np.interp(l1, l3d, p3d[1, :]) p1[2, ix:ix + nseg] = np.interp(l1, l3d, p3d[2, :]) d1[ix:ix + nseg] = np.interp(l1, l3d, diam3d[:]) ix += nseg self.seg_coords = {} self.seg_coords['p0'] = p0 self.seg_coords['p1'] = p1 self.seg_coords['d0'] = d0 self.seg_coords['d1'] = d1 return self.seg_coords
def writeNeuronToJson(filename='neuron', directory='neuron'): """ Create a JSON file of the morphology of the currently loaded neuron. The position of each compartment are stored along with the diameter at each of those positions. Each section is seperated with a row of zeros. :param str filename: Filename. :param str directory: Relative or full directory address. """ if not os.path.exists(directory): os.makedirs(directory) filename, ext = os.path.splitext(filename) filename = filename + '.js' filename = directory + '/' + filename x = [] y = [] z = [] diam = [] arrayLength = 0 for sec in h.allsec(): arrayLength += int(h.n3d()) # Create a gap in the array to seperate sections. arrayLength += 1 x = np.zeros(arrayLength) y = np.zeros(arrayLength) z = np.zeros(arrayLength) diam = np.zeros(arrayLength) indx = 0 for sec in h.allsec(): for i in xrange(int(h.n3d())): x[indx] = h.x3d(i) y[indx] = h.y3d(i) z[indx] = h.z3d(i) diam[indx] = h.diam3d(i) indx += 1 indx += 1 x = np.zeros(arrayLength) y = np.zeros(arrayLength) z = np.zeros(arrayLength) diam = np.zeros(arrayLength) indx = 0 for sec in h.allsec(): for i in xrange(int(h.n3d())): x[indx] = h.x3d(i) y[indx] = h.y3d(i) z[indx] = h.z3d(i) diam[indx] = h.diam3d(i) indx += 1 indx += 1 if len(diam) == 0: print "No sections found." return data = { \ 'x': x.tolist(), \ 'y': y.tolist(), \ 'z': z.tolist(), \ 'diam': diam.tolist(), \ } dataString = json.dumps(data) f = open(filename, 'w') f.write(dataString) f.close()
def __set_3Dshape(self): # set 3D shape of soma by calling shape_soma from class Cell # print "WARNING: You are setting 3d shape geom. You better be doing" # print "gui analysis and not numerical analysis!!" self.shape_soma() # soma proximal coords x_prox = 0 y_prox = 0 # soma distal coords x_distal = 0 y_distal = self.soma.L # dend 0-3 are major axis, dend 4 is branch # deal with distal first along major cable axis # the way this is assigning variables is ugly/lazy right now for i in range(0, 4): h.pt3dclear(sec=self.list_dend[i]) # x_distal and y_distal are the starting points for each segment # these are updated at the end of the loop sec=self.list_dend[i] h.pt3dadd(0, y_distal, 0, sec.diam, sec=sec) # update x_distal and y_distal after setting them # x_distal += dend_dx[i] y_distal += sec.L # add next point h.pt3dadd(0, y_distal, 0, sec.diam, sec=sec) # now deal with dend 4 # dend 4 will ALWAYS be positioned at the end of dend[0] h.pt3dclear(sec=self.list_dend[4]) # activate this section with 'sec=self.list_dend[i]' notation x_start = h.x3d(1, sec=self.list_dend[0]) y_start = h.y3d(1, sec=self.list_dend[0]) sec=self.list_dend[4] h.pt3dadd(x_start, y_start, 0, sec.diam, sec=sec) # self.dend_L[4] is subtracted because lengths always positive, # and this goes to negative x h.pt3dadd(x_start-sec.L, y_start, 0, sec.diam, sec=sec) # now deal with proximal dends for i in range(5, 8): h.pt3dclear(sec=self.list_dend[i]) # deal with dend 5, ugly. sorry. sec=self.list_dend[5] h.pt3dadd(x_prox, y_prox, 0, sec.diam, sec=sec) y_prox += -sec.L h.pt3dadd(x_prox, y_prox, 0, sec.diam,sec=sec) # x_prox, y_prox are now the starting points for BOTH of last 2 sections # dend 6 # Calculate x-coordinate for end of dend sec=self.list_dend[6] dend6_x = -sec.L * np.sqrt(2) / 2. h.pt3dadd(x_prox, y_prox, 0, sec.diam, sec=sec) h.pt3dadd(dend6_x, y_prox-sec.L * np.sqrt(2) / 2., 0, sec.diam, sec=sec) # dend 7 # Calculate x-coordinate for end of dend sec=self.list_dend[7] dend7_x = sec.L * np.sqrt(2) / 2. h.pt3dadd(x_prox, y_prox, 0, sec.diam, sec=sec) h.pt3dadd(dend7_x, y_prox-sec.L * np.sqrt(2) / 2., 0, sec.diam, sec=sec) # set 3D position # z grid position used as y coordinate in h.pt3dchange() to satisfy # gui convention that y is height and z is depth. In h.pt3dchange() # x and z components are scaled by 100 for visualization clarity self.soma.push() for i in range(0, int(h.n3d())): h.pt3dchange(i, self.pos[0]*100 + h.x3d(i), -self.pos[2] + h.y3d(i), self.pos[1] * 100 + h.z3d(i), h.diam3d(i)) h.pop_section()
def graph(self): #Function: graph #Input: self #Process: create dendrite branch network #Output: neuron self.dendsegs = numpy.array([self.coordinates[:,0], self.coordinates[:,2], self.coordinates[:,3],self.coordinates[:,4],self.coordinates[:,5],self.coordinates[:,6]]) self.seglist = numpy.array(self.coordinates[:,0]-1,dtype=int) self.segmap = numpy.array(self.coordinates[:,6]-1,dtype=int) if self.seglist[0] == 1: self.seglist = numpy.array(self.seglist-1,dtype=int) self.segmap = numpy.array(self.segmap-1,dtype=int) #----------------------------------------------------------------------------------------------------------------------------------------------- self.compartmentdict = {} segvals = [] Gcompartment = [] #----------------------------------------------------------------------------------------------------------------------------------------------- for c in range(len(self.seglist)): #----------------------------------------------------------------------------------------------------------------------------------------------- if self.segmap[c] < self.seglist[c] - 1: if len(segvals) == 0: continue i = c self.compartmentdict[i] = [Gcompartment,h.Section(name='compartment',cell=self),segvals] Gcompartment = [] segvals = [] #----------------------------------------------------------------------------------------------------------------------------------------------- if c == len(self.seglist) - 1: if len(segvals) == 0: break i = c self.compartmentdict[i] = [Gcompartment,h.Section(name='compartment',cell=self),segvals] Gcompartment = [] segvals = [] #----------------------------------------------------------------------------------------------------------------------------------------------- else: segvals.append([self.dendsegs[1,c]*1/125.0,self.dendsegs[2,c]*1/125.0,self.dendsegs[3,c]*1/125.0,self.dendsegs[4,c]*1/125.0]) Gcompartment.append(self.seglist[c]) #----------------------------------------------------------------------------------------------------------------------------------------------- for key in self.compartmentdict.keys(): if len(self.compartmentdict[key][2]) > 0: s = self.compartmentdict[key][2][0] e = self.compartmentdict[key][2][-1] if distance.euclidean(s[0:2],e[0:2]) == 0: h.pt3dadd(s[0],s[1],s[2],s[3],sec=self.compartmentdict[key][1]) h.pt3dadd(e[0] + 1e-5,e[1] + 1e-5,e[2] + 1e-5,e[3],sec=self.compartmentdict[key][1]) else: h.pt3dadd(s[0],s[1],s[2],s[3],sec=self.compartmentdict[key][1]) h.pt3dadd(e[0],e[1],e[2],e[3],sec=self.compartmentdict[key][1]) #----------------------------------------------------------------------------------------------------------------------------------------------- for key in self.compartmentdict.keys(): for part in self.compartmentdict.keys(): if key in self.compartmentdict[part][0]: self.compartmentdict[key][1].connect(self.compartmentdict[part][1]) #----------------------------------------------------------------------------------------------------------------------------------------------- for dendID in self.compartmentdict.keys(): n3dID = int(h.n3d(sec=self.compartmentdict[dendID][1])) for n in range(n3dID): self.dendgraph[dendID] = numpy.array([float(h.x3d(n,sec=self.compartmentdict[dendID][1])),float(h.y3d(n,sec=self.compartmentdict[dendID][1])),float(h.z3d(n,sec=self.compartmentdict[dendID][1]))])