def d_lambda(self): freq = 100 d_lambda = 0.1 for dendType in self.dendTypeList: for sec in self.dendTypeList[dendType]: sec.push() if h.n3d() < 2: lambda_f = 1e5 * np.sqrt( sec.diam / (4 * np.pi * freq * sec.Ra * sec.cm)) else: x1 = h.arc3d(0) d1 = h.diam3d(0) lam = 0 for ii in range(1, int(h.n3d())): x2 = h.arc3d(ii) d2 = h.diam3d(ii) lam += (x2 - x1) / np.sqrt(d1 + d2) x1 = x2 d1 = d2 lam *= np.sqrt(2) * 1e-5 * np.sqrt( 4 * np.pi * freq * sec.Ra * sec.cm) lambda_f = sec.L / lam nseg = (int( (sec.L / (d_lambda * lambda_f) + 0.9) / 2) * 2 + 1) / 2 if nseg % 2 == 0: nseg += 1 sec.nseg = nseg h.pop_section()
def morph_per_root(root): morph = [] h.define_shape() for sec in secs_with_root(root): n3d = int(h.n3d(sec=sec)) 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)] d = [h.diam3d(i, sec=sec) for i in xrange(n3d)] arc = [h.arc3d(i, sec=sec) for i in xrange(n3d)] length = sec.L half_dx = 0.5 / sec.nseg for seg in sec: morph.append(get_pts_between(x, y, z, d, arc, (seg.x - half_dx) * length, (seg.x + half_dx) * length)) # add end points for end_pt in [0, 1]: for sec in secs_with_root(root): n3d = int(h.n3d(sec=sec)) pt1 = [h.x3d(0, sec=sec), h.y3d(0, sec=sec), h.z3d(0, sec=sec), h.diam3d(0, sec=sec)] pt2 = [h.x3d(n3d - 1, sec=sec), h.y3d(n3d - 1, sec=sec), h.z3d(n3d - 1, sec=sec), h.diam3d(n3d - 1, sec=sec)] if h.section_orientation(sec=sec) == 0: morph_to_append = [pt1] if end_pt == 0 else [pt2] else: morph_to_append = [pt2] if end_pt == 0 else [pt1] round3(morph_to_append) morph.append(morph_to_append) return morph
def nrngraph(cell): """Convert a NEURON cell model into networkx graph. The nodes are the section names in the cell. Each node has the parent section name in attribute `p`. It is -1 if there is no parent. x, y, z represent the coordinates of the 0 end. orig is SectionRef to the original NEURON section. For display purposes, we add the 1 end of the leaf sections as dummy nodes. They can be identified by the attribute orig=None. """ g = nx.DiGraph() cell.soma.push() # Assume there is a designated soma # This appends all sections accessible from currently # accessed section in root to leaves ordered_tree = h.SectionList() ordered_tree.wholetree() h.pop_section() for comp in ordered_tree: comp.push() cid = comp.name() stype = sectype(cid) g.add_node(cid, x=h.x3d(0), y=h.y3d(0), z=h.z3d(0), r=h.diam3d(0) / 2.0, s=stype, orig=comp) ref = h.SectionRef(sec=comp) if ref.has_parent(): parent = ref.parent g.add_edge(parent.name(), cid, length=parent.L) g.node[cid]['p'] = parent.name() else: g.node[cid]['p'] = -1 # Insert the 1-end of a section as a dummy node if ref.nchild() == 0: leaf_node = '{}_1'.format(cid) g.add_node(leaf_node, x=h.x3d(1), y=h.y3d(1), z=h.z3d(1), r=h.diam3d(1) / 2.0, s=stype, p=comp.name(), orig=None) g.add_edge(cid, leaf_node, length=comp.L) h.pop_section() return g
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 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 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 result(sec): if not isinstance(sec, nrn.Section): sec = sec._sec arc3d = [h.arc3d(i, sec=sec) for i in range(int(h.n3d(sec=sec)))] diam3d = [h.diam3d(i, sec=sec) for i in range(int(h.n3d(sec=sec)))] sas = numpy.zeros(sec.nseg) dx = sec.L / sec.nseg for iseg in range(sec.nseg): # get a list of all pts in the segment, including end points lo = iseg * dx hi = (iseg + 1) * dx pts = [lo] + [x for x in arc3d if lo < x < hi] + [hi] diams = numpy.interp(pts, arc3d, diam3d) # sum the surface areas of the constituent frusta sa = 0 for i in range(len(pts) - 1): diam0, diam1 = diams[i : i + 2] pt0, pt1 = pts[i : i + 2] sa += scale * 0.5 * (diam0 + diam1) * numpy.sqrt(0.25 * (diam0 - diam1) ** 2 + (pt1 - pt0) ** 2) sas[iseg] = sa return sas
def get_coords_and_radii(self): nrn_section = self.nrn_section # Count 3D points point_count = int(h.n3d(sec=nrn_section)) # Let NEURON create them if missing if point_count == 0: h.define_shape(sec=self.nrn_section) point_count = int(h.n3d(sec=self.nrn_section)) # Collect the coordinates coords = [None] * point_count * 3 # 3 for xy and z radii = [None] * point_count for c in range(point_count): ci = c * 3 coords[ci] = h.x3d(c, sec=nrn_section) coords[ci + 1] = h.y3d(c, sec=nrn_section) coords[ci + 2] = h.z3d(c, sec=nrn_section) radii[c] = h.diam3d(c, sec=nrn_section) / 2.0 self.nseg = int(nrn_section.nseg) self.point_count = point_count self.coords = coords self.radii = radii
def volumes1d(self, sec): if not isinstance(sec, nrn.Section): sec = sec._sec arc3d = [h.arc3d(i, sec=sec) for i in xrange(int(h.n3d(sec=sec)))] diam3d = [h.diam3d(i, sec=sec) for i in xrange(int(h.n3d(sec=sec)))] vols = numpy.zeros(sec.nseg) dx = sec.L / sec.nseg for iseg in xrange(sec.nseg): # get a list of all pts in the segment, including end points lo = iseg * dx hi = (iseg + 1) * dx pts = [lo] + [x for x in arc3d if lo < x < hi] + [hi] diams = numpy.interp(pts, arc3d, diam3d) # sum the volume of the constituent frusta, hollowing out by the inside volume = 0 for i in xrange(len(pts) - 1): diam0h, diam1h = self._hi * diams[i:i + 2] diam0l, diam1l = self._lo * diams[i:i + 2] pt0, pt1 = pts[i:i + 2] volume += numpy.pi * (pt1 - pt0) / 12. * ( (diam0h**2 + diam0h * diam1h + diam1h**2) - (diam0l**2 + diam0l * diam1l + diam1l**2)) vols[iseg] = volume return vols
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_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 result(sec): if not isinstance(sec, nrn.Section): sec = sec._sec arc3d = [h.arc3d(i, sec=sec) for i in xrange(int(h.n3d(sec=sec)))] diam3d = [h.diam3d(i, sec=sec) for i in xrange(int(h.n3d(sec=sec)))] sas = numpy.zeros(sec.nseg) dx = sec.L / sec.nseg for iseg in xrange(sec.nseg): # get a list of all pts in the segment, including end points lo = iseg * dx hi = (iseg + 1) * dx pts = [lo] + [x for x in arc3d if lo < x < hi] + [hi] diams = numpy.interp(pts, arc3d, diam3d) # sum the surface areas of the constituent frusta sa = 0 for i in xrange(len(pts) - 1): diam0, diam1 = diams[i:i + 2] pt0, pt1 = pts[i:i + 2] sa += scale * 0.5 * (diam0 + diam1) * numpy.sqrt(0.25 * (diam0 - diam1)**2 + (pt1 - pt0)**2) sas[iseg] = sa return sas
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 lambda_f(section, freq): if h.n3d() < 2: return 1e5*math.sqrt(section.diam/(math.pi*4*freq*section.Ra*section.cm)) else: x1 = h.arc3d(0) d1 = h.diam3d(0) lam = 0 for i in range(int(h.n3d())): x2 = h.arc3d(i) d2 = h.diam3d(i) lam += (x2 - x1)/math.sqrt(d1 + d2) x1 = x2 d1 = d2 lam *= math.sqrt(2) * 1e-5*math.sqrt(4*math.pi*freq*section.Ra*section.cm) return section.L / lam
def _volumes1d(sec): if not isinstance(sec, nrn.Section): sec = sec._sec arc3d = [h.arc3d(i, sec=sec) for i in range(int(h.n3d(sec=sec)))] diam3d = [h.diam3d(i, sec=sec) for i in range(int(h.n3d(sec=sec)))] vols = numpy.zeros(sec.nseg) dx = sec.L / sec.nseg for iseg in range(sec.nseg): # get a list of all pts in the segment, including end points lo = iseg * dx hi = (iseg + 1) * dx pts = [lo] + [x for x in arc3d if lo < x < hi] + [hi] diams = numpy.interp(pts, arc3d, diam3d) # sum the volume of the constituent frusta volume = 0 for i in range(len(pts) - 1): diam0, diam1 = diams[i : i + 2] pt0, pt1 = pts[i : i + 2] volume += numpy.pi * (pt1 - pt0) / 12. * (diam0 ** 2 + diam0 * diam1 + diam1 ** 2) vols[iseg] = volume return vols
def hoc2morph(hoc_file): """ Generate morph sectioning data from NEURON hoc file. """ 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 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 volumes1d(self, sec): if not isinstance(sec, nrn.Section): sec = sec._sec arc3d = [h.arc3d(i, sec=sec) for i in range(int(h.n3d(sec=sec)))] diam3d = [h.diam3d(i, sec=sec) for i in range(int(h.n3d(sec=sec)))] vols = numpy.zeros(sec.nseg) dx = sec.L / sec.nseg for iseg in range(sec.nseg): # get a list of all pts in the segment, including end points lo = iseg * dx hi = (iseg + 1) * dx pts = [lo] + [x for x in arc3d if lo < x < hi] + [hi] diams = numpy.interp(pts, arc3d, diam3d) # sum the volume of the constituent frusta, hollowing out by the inside volume = 0 for i in range(len(pts) - 1): diam0h, diam1h = self._hi * diams[i : i + 2] diam0l, diam1l = self._lo * diams[i : i + 2] pt0, pt1 = pts[i : i + 2] volume += numpy.pi * (pt1 - pt0) / 12. * ((diam0h ** 2 + diam0h * diam1h + diam1h ** 2) - (diam0l ** 2 + diam0l * diam1l + diam1l ** 2)) vols[iseg] = volume return vols
def setup_pcmorphology(kk, x, y, z): print 'i value is:', kk cellpc = Purkinje() h.define_shape() sections = h.SectionList() sections.wholetree(cellpc.soma) cellpc.soma.push() n = h.n3d(sec=cellpc.soma) xs = [h.x3d(i) for i in range(int(n))] ys = [h.y3d(i) for i in range(int(n))] zs = [h.z3d(i) for i in range(int(n))] ds = [h.diam3d(i) for i in range(int(n))] j = 0 #sec.push() for a, b, c, d in zip(xs, ys, zs, ds): #print 'sec here is:', sec h.pt3dchange(j, a + x, b + y, c + z, d) j += 1 h.define_shape() h.pop_section() pulist.append(cellpc) #call another function to locate the local granule neurons cellpc.soma.push() getpurksecs = h.SectionList() getpurksecs.wholetree(cellpc.soma) func_local_grcneurons(kk, getpurksecs)
def _volumes1d(sec): if not isinstance(sec, nrn.Section): sec = sec._sec arc3d = [h.arc3d(i, sec=sec) for i in xrange(int(h.n3d(sec=sec)))] diam3d = [h.diam3d(i, sec=sec) for i in xrange(int(h.n3d(sec=sec)))] vols = numpy.zeros(sec.nseg) dx = sec.L / sec.nseg for iseg in xrange(sec.nseg): # get a list of all pts in the segment, including end points lo = iseg * dx hi = (iseg + 1) * dx pts = [lo] + [x for x in arc3d if lo < x < hi] + [hi] diams = numpy.interp(pts, arc3d, diam3d) # sum the volume of the constituent frusta volume = 0 for i in xrange(len(pts) - 1): diam0, diam1 = diams[i:i + 2] pt0, pt1 = pts[i:i + 2] volume += numpy.pi * (pt1 - pt0) / 12. * (diam0**2 + diam0 * diam1 + diam1**2) vols[iseg] = volume return vols
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 h2morph(h): """ Generate morph sectioning data from NEURON h interface with preloaded morphology. """ 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 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 position(self, x, y, z): 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
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 modify_morphology(section_dict, cellname): for key, sec_list in section_dict.items(): for sec in sec_list: sec.nseg = 11 for sec in section_dict['basal']: for i in xrange(int(nrn.n3d())): nrn.pt3dchange(i, 0.76) for sec in section_dict['oblique_dendrites']: for i in xrange(int(nrn.n3d())): nrn.pt3dchange(i, 0.73) if cellname == 'n120': apic_root_segment = 'apic[9]' elif cellname == 'c12861': apic_root_segment = 'apic[92]' else: raise RuntimeError("Not known cellname!") nrn.distance() apic_tuft_root_diam = None apic_tuft_root_dist = None for sec in section_dict['apic_trunk']: npts = int(nrn.n3d()) cummulative_L = 0 for i in xrange(npts): if not i == 0: delta_x = (nrn.x3d(i) - nrn.x3d(i - 1))**2 delta_y = (nrn.y3d(i) - nrn.y3d(i - 1))**2 delta_z = (nrn.z3d(i) - nrn.z3d(i - 1))**2 cummulative_L += np.sqrt(delta_x + delta_y + delta_z) dist_from_soma = nrn.distance(0) + cummulative_L diam = 3.5 - 4.7e-3 * dist_from_soma # print diam, nrn.diam3d(i) nrn.pt3dchange(i, diam) if sec.name() == apic_root_segment: apic_tuft_root_diam = nrn.diam3d(npts - 1) apic_tuft_root_dist = nrn.distance(1.) longest_tuft_branch = find_longest_tuft_branch(section_dict, apic_tuft_root_dist) tuft_smallest_diam = 0.3 for sec in section_dict['apic_tuft']: npts = int(nrn.n3d()) cummulative_L = 0 start_dist_from_tuft_root = nrn.distance(0.0) - apic_tuft_root_dist for i in xrange(npts): if not i == 0: delta_x = (nrn.x3d(i) - nrn.x3d(i - 1))**2 delta_y = (nrn.y3d(i) - nrn.y3d(i - 1))**2 delta_z = (nrn.z3d(i) - nrn.z3d(i - 1))**2 cummulative_L += np.sqrt(delta_x + delta_y + delta_z) dist_from_root = start_dist_from_tuft_root + cummulative_L diam = apic_tuft_root_diam - dist_from_root/longest_tuft_branch * (apic_tuft_root_diam - tuft_smallest_diam) # print nrn.diam3d(i), diam nrn.pt3dchange(i, diam, sec=sec)
def _neighbor_areas1d(sec): arc3d = [h.arc3d(i, sec=sec._sec) for i in xrange(int(h.n3d(sec=sec._sec)))] diam3d = [h.diam3d(i, sec=sec._sec) for i in xrange(int(h.n3d(sec=sec._sec)))] area_pos = numpy.linspace(0, sec.L, sec.nseg + 1) diams = numpy.interp(area_pos, arc3d, diam3d) return numpy.pi * 0.25 * diams ** 2
def retrieve_coordinates(self, sec): 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 _neighbor_areas1d(sec): if not isinstance(sec, nrn.Section): sec = sec._sec arc3d = [h.arc3d(i, sec=sec) for i in xrange(int(h.n3d(sec=sec)))] diam3d = [h.diam3d(i, sec=sec) for i in xrange(int(h.n3d(sec=sec)))] area_pos = numpy.linspace(0, sec.L, sec.nseg + 1) diams = numpy.interp(area_pos, arc3d, diam3d) return numpy.pi * 0.25 * diams**2
def result(sec): if not isinstance(sec, nrn.Section): sec = sec._sec arc3d = [h.arc3d(i, sec=sec) for i in range(int(h.n3d(sec=sec)))] diam3d = [h.diam3d(i, sec=sec) for i in range(int(h.n3d(sec=sec)))] area_pos = numpy.linspace(0, sec.L, sec.nseg + 1) diams = numpy.interp(area_pos, arc3d, diam3d) return scale * diams
def result(sec): if not isinstance(sec, nrn.Section): sec = sec._sec arc3d = [h.arc3d(i, sec=sec) for i in xrange(int(h.n3d(sec=sec)))] diam3d = [h.diam3d(i, sec=sec) for i in xrange(int(h.n3d(sec=sec)))] area_pos = numpy.linspace(0, sec.L, sec.nseg + 1) diams = numpy.interp(area_pos, arc3d, diam3d) return scale * diams
def neighbor_areas1d(self, sec): arc3d = [h.arc3d(i, sec=sec._sec) for i in xrange(int(h.n3d(sec=sec._sec)))] diam3d = [h.diam3d(i, sec=sec._sec) for i in xrange(int(h.n3d(sec=sec._sec)))] area_pos = numpy.linspace(0, sec.L, sec.nseg + 1) diams = numpy.interp(area_pos, arc3d, diam3d) if self._type == _lo_hi_shell: return numpy.pi * .25 * ((diams * self._hi) ** 2 - (diams * self._lo) ** 2)
def lambda_f(section, freq): if h.n3d() < 2: return 1e5 * math.sqrt(section.diam / (math.pi * 4 * freq * section.Ra * section.cm)) else: x1 = h.arc3d(0) d1 = h.diam3d(0) lam = 0 for i in range(int(h.n3d())): x2 = h.arc3d(i) d2 = h.diam3d(i) lam += (x2 - x1) / math.sqrt(d1 + d2) x1 = x2 d1 = d2 lam *= math.sqrt(2) * 1e-5 * math.sqrt( 4 * math.pi * freq * section.Ra * section.cm) return section.L / lam
def change_cell_location(soma, offset=150): soma.push() for i in range(int(h.n3d())): h.pt3dchange(i, offset + h.x3d(i), offset + h.y3d(i), offset + h.z3d(i), h.diam3d(i))
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 _neighbor_areas1d(sec): if not isinstance(sec, nrn.Section): sec = sec._sec arc3d = [h.arc3d(i, sec=sec) for i in range(int(h.n3d(sec=sec)))] diam3d = [h.diam3d(i, sec=sec) for i in range(int(h.n3d(sec=sec)))] area_pos = numpy.linspace(0, sec.L, sec.nseg + 1) diams = numpy.interp(area_pos, arc3d, diam3d) return numpy.pi * 0.25 * diams ** 2
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 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 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 retreive_coordinates(sec): ''' Only works with cell which have an xtra mechanism ''' # Make sure to run h.setpointers() before running from neuron import h x=sec.sec(.5).x_xtra y=sec.sec(.5).y_xtra z=sec.sec(.5).z_xtra sec.sec.push() diam = h.diam3d(0) h.pop_section() return [x, y, z, diam]
def get_coordinates(sec): sec.push() # make section the currently activated section x, y, z, d = [], [], [], [] # loop through 3d locations in the currently accessed section. for i in range(int(h.n3d())): x.append(h.x3d(i)) y.append(h.y3d(i)) z.append(h.z3d(i)) d.append(h.diam3d(i)) h.pop_section() return (np.array(x), np.array(y), np.array(z), np.array(d))
def rotateZ(self, theta): """ Rotate the cell about the Z axis. """ rot_m = numpy.array([[numpy.sin(theta), numpy.cos(theta)], \ [numpy.cos(theta), -numpy.sin(theta)]]) for sec in self.all: for i in range(int(nrn.n3d())): xy = numpy.dot([nrn.x3d(i), nrn.y3d(i)], rot_m) nrn.pt3dchange(i, float(xy[0]), float(xy[1]), nrn.z3d(i), \ nrn.diam3d(i))
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 set_position(self, x, y, z): """ This method can change the absolute 3D location of the network by translational motion, leaving all relative positons intact. Besides the SimpleCell object, it takes three other argumentseach of which is the change in the respective Cartesian coordinate. """ for section in self.all: for point in range(int(h.n3d(sec=section))): h.pt3dchange(point, x - self.x + h.x3d(point), y - self.y + h.y3d(point), z - self.z + h.z3d(point), h.diam3d(point)) self.x, self.y, self.z = x, y, z
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 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 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 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
h.fadvance() if advance_count % save_every == 0: values.append([seg.v for seg in segs]) advance_count += 1 print h.t # # now fatten everything up (so we can see it) and save the graphics # note: handle the soma differently by scaling in all directions not just diam # scale = 5 import numpy for sec in h.allsec(): if 'soma' not in sec.name(): for i in xrange(int(h.n3d(sec=sec))): d = h.diam3d(i, sec=sec) h.pt3dchange(i, d * scale, sec=sec) elif 'soma' in sec.name(): x, y, z, diam = [], [], [], [] for i in xrange(int(h.n3d(sec=sec))): x.append(h.x3d(i, sec=sec)) y.append(h.y3d(i, sec=sec)) z.append(h.z3d(i, sec=sec)) diam.append(h.diam3d(i, sec=sec)) h.pt3dclear(sec=sec) x, y, z, diam = scale * numpy.array(x), scale * numpy.array(y), scale * numpy.array(z), scale * numpy.array(diam) i = int(len(x) / 2) midptx, midpty, midptz = x[i], y[i], z[i] x -= midptx / 2. y -= midpty / 2. z -= midptz / 2.
def importCell(fileName, cellName, cellArgs = {}): ''' 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) cell = getattr(h, cellName)(**cellArgs) # arguments correspond to zloc, type and id -- remove in future (not used internally) secList = 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 cell = getattr(modulePointer, cellName)(**cellArgs) # create cell and pass type as argument dirCell = dir(cell) if 'all_sec' in dirCell: secList = cell.all_sec elif 'sec' in dirCell: secList = [cell.sec] elif 'allsec' in dir(h): secList = [sec for sec in h.allsec()] elif 'soma' in dirCell: secList = [cell.soma] else: secList = [] 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({cell.__dict__[dirCellName].hname(): dirCellName}) except: pass # create dict with dir(cell) name corresponding to each hname dirCellSecNames = {} for sec in secList: dirCellSecNames.update({hname: name for hname,name in dirCellHnames.iteritems() if hname == sec.hname()}) secDic = {} for sec in secList: # create new section dict with name of section secName = getSecName(sec, dirCellSecNames) if len(secList) == 1: secName = 'soma' # if just one section rename to 'soma' secDic[secName] = {'geom': {}, 'topol': {}, 'mechs': {}, 'syns': {}} # 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 = {} 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 syns = {} pointps = {} for seg in sec: for ipoint,point in enumerate(seg.point_processes()): pptype = point.hname().split('[')[0] varNames = varList['pointps'][pptype] if any([s in pptype.lower() for s in ['syn', 'ampa', 'gaba', 'nmda', 'glu']]): #if 'syn' in pptype.lower(): # if syn in name of point process then assume synapse synName = pptype + '_' + str(len(syns)) syns[synName] = {} syns[synName]['_type'] = pptype syns[synName]['_loc'] = seg.x for varName in varNames: try: syns[synName][varName] = point.__getattribute__(varName) except: print 'Could not read variable %s from synapse %s'%(varName,synName) else: # assume its a non-synapse point process pointpName = pptype + '_'+ str(len(pointps)) pointps[pointpName] = {} pointps[pointpName]['_type'] = pptype 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,synName) if syns: secDic[secName]['syns'] = syns 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() del(cell) # delete cell import gc; gc.collect() return secDic
def constructive_neuronal_geometry(source, n_soma_step, dx): objects = [] source_is_import3d = False # TODO: come up with a better way of checking type if hasattr(source, 'sections'): source_is_import3d = True cell = source # probably an Import3D type num_contours = sum(sec.iscontour_ for sec in cell.sections) if num_contours > 1: raise Exception('more than one contour is not currently supported') if num_contours == 1: # setup the soma # CTNG:soma branches = [] parent_sec_name = [] for sec in cell.sections: if sec.iscontour_: soma_sec = sec.hname() x, y, z = [sec.raw.getrow(i).to_python() for i in xrange(3)] # compute the center of the contour based on uniformly spaced points around the perimeter center_vec = sec.contourcenter(sec.raw.getrow(0), sec.raw.getrow(1), sec.raw.getrow(2)) x0, y0, z0 = [center_vec.x[i] for i in xrange(3)] somax, somay, somaz = x0, y0, z0 xshifted = [xx - x0 for xx in x] yshifted = [yy - y0 for yy in y] # this is a hack to pretend everything is on the same z level zshifted = [0] * len(x) # locate the major and minor axis, adapted from import3d_gui.hoc m = h.Matrix(3, 3) for i, p in enumerate([xshifted, yshifted, zshifted]): for j, q in enumerate([xshifted, yshifted, zshifted]): if j < i: continue v = numpy.dot(p, q) m.setval(i, j, v) m.setval(j, i, v) # CTNG:majoraxis tobj = m.symmeig(m) # major axis is the one with largest eigenvalue major = m.getcol(tobj.max_ind()) # minor is normal and in xy plane minor = m.getcol(3 - tobj.min_ind() - tobj.max_ind()) #minor.x[2] = 0 minor.div(minor.mag()) x1 = x0; y1 = y0 x2 = x1 + major.x[0]; y2 = y1 + major.x[1] xs_loop = x + [x[0]] ys_loop = y + [y[0]] # locate the extrema of the major axis CTNG:somaextrema # this is defined by the furthest points on it that lie on the minor axis pts = [] pts_sources = {} for x3, y3 in zip(x, y): x4, y4 = x3 + minor.x[0], y3 + minor.x[1] pt = seg_line_intersection(x1, y1, x2, y2, x3, y3, x4, y4, clip=False) if pt is not None: pts.append(pt) if pt not in pts_sources: pts_sources[pt] = [] pts_sources[pt].append((x3, y3)) major_p1, major_p2 = extreme_pts(pts) extreme1 = pts_sources[major_p1] extreme2 = pts_sources[major_p2] major_p1, major_p2 = numpy.array(major_p1), numpy.array(major_p2) del pts_sources if len(extreme1) != 1 or len(extreme2) != 1: raise Exception('multiple most extreme points') extreme1 = extreme1[0] extreme2 = extreme2[0] major_length = linalg.norm(major_p1 - major_p2) delta_x, delta_y = major_p2 - major_p1 delta_x /= n_soma_step delta_y /= n_soma_step f_pts = [major_p1] f_diams = [0] # CTNG:slicesoma for i in xrange(1, n_soma_step): x0, y0 = major_p1[0] + i * delta_x, major_p1[1] + i * delta_y # slice in dir of minor axis x1, y1 = x0 + minor.x[0], y0 + minor.x[1] pts = [] for i in xrange(len(x)): pt = seg_line_intersection(xs_loop[i], ys_loop[i], xs_loop[i + 1], ys_loop[i + 1], x0, y0, x1, y1, clip=True) if pt is not None: pts.append(pt) p1, p2 = extreme_pts(pts) p1, p2 = numpy.array(p1), numpy.array(p2) cx, cy = (p1 + p2) / 2. f_pts.append((cx, cy)) f_diams.append(linalg.norm(p1 - p2)) f_pts.append(major_p2) f_diams.append(0) for i in xrange(len(f_pts) - 1): pt1x, pt1y = f_pts[i] pt2x, pt2y = f_pts[i + 1] diam1 = f_diams[i] diam2 = f_diams[i + 1] objects.append(SkewCone(pt1x, pt1y, z0, diam1 * 0.5, pt1x + delta_x, pt1y + delta_y, z0, diam2 * 0.5, pt2x, pt2y, z0)) else: parent_sec_name.append(sec.parentsec.hname()) branches.append(sec) else: h.define_shape() soma_sec = None branches = [] for sec in source: branches.append(sec) # this is ignored in this case, but needs to be same length # so this way no extra memory except the pointer parent_sec_name = branches ##################################################################### # # add the branches # ##################################################################### diam_corrections = {None: None} while diam_corrections: all_cones = [] pts_cones_db = {} diam_db = {} for branch, psec in zip(branches, parent_sec_name): if source_is_import3d: x, y, z = [branch.raw.getrow(i).to_python() for i in xrange(3)] d = branch.d.to_python() else: x = [h.x3d(i, sec=branch) for i in xrange(int(h.n3d(sec=branch)))] y = [h.y3d(i, sec=branch) for i in xrange(int(h.n3d(sec=branch)))] z = [h.z3d(i, sec=branch) for i in xrange(int(h.n3d(sec=branch)))] d = [h.diam3d(i, sec=branch) for i in xrange(int(h.n3d(sec=branch)))] # make sure that all the ones that connect to the soma do in fact connect # do this by connecting to local center axis # CTNG:connectdends if psec == soma_sec: pt = (x[1], y[1], z[1]) cp = closest_pt(pt, f_pts, somaz) # NEURON includes the wire point at the center; we want to connect # to the closest place on the soma's axis instead with full diameter x, y, z, d = [cp[0]] + [X for X in x[1 :]], [cp[1]] + [Y for Y in y[1:]], [somaz] + [Z for Z in z[1:]], [d[1]] + [D for D in d[1 :]] for i in xrange(len(x) - 1): d0, d1 = d[i : i + 2] if (x[i] != x[i + 1] or y[i] != y[i + 1] or z[i] != z[i + 1]): # short section check #if linalg.norm((x[i + 1] - x[i], y[i + 1] - y[i], z[i + 1] - z[i])) < (d1 + d0) * 0.5: # short_segs += 1 axisx, axisy, axisz, deltad = x[i + 1] - x[i], y[i + 1] - y[i], z[i + 1] - z[i], d1 - d0 axislength = (axisx ** 2 + axisy ** 2 + axisz ** 2) ** 0.5 axisx /= axislength; axisy /= axislength; axisz /= axislength; deltad /= axislength x0, y0, z0 = x[i], y[i], z[i] x1, y1, z1 = x[i + 1], y[i + 1], z[i + 1] if (x0, y0, z0) in diam_corrections: d0 = diam_corrections[(x0, y0, z0)] if (x1, y1, z1) in diam_corrections: d1 = diam_corrections[(x1, y1, z1)] if d0 != d1: all_cones.append(Cone(x0, y0, z0, d0 * 0.5, x1, y1, z1, d1 * 0.5)) else: all_cones.append(Cylinder(x0, y0, z0, x1, y1, z1, d1 * 0.5)) register(pts_cones_db, (x0, y0, z0), all_cones[-1]) register(pts_cones_db, (x1, y1, z1), all_cones[-1]) register(diam_db, (x0, y0, z0), d0) register(diam_db, (x1, y1, z1), d1) # at join, should always be the size of the biggest branch # this is different behavior than NEURON, which continues the size of the # first point away from the join to the join diam_corrections = {} for pt in diam_db: vals = diam_db[pt] if max(vals) != min(vals): diam_corrections[pt] = max(vals) cone_clip_db = {cone: [] for cone in all_cones} join_counts = {'2m': 0, '2s': 0, '3m': 0, '3s': 0, '4m': 0, '4s': 0, '0m': 0, '0s': 0, '1m': 0, '1s': 0} for cone in all_cones: x1, y1, z1, r1 = cone._x0, cone._y0, cone._z0, cone._r0 x2, y2, z2, r2 = cone._x1, cone._y1, cone._z1, cone._r1 pt1 = numpy.array([x1, y1, z1]) pt2 = numpy.array([x2, y2, z2]) axis = (pt2 - pt1) / linalg.norm(pt2 - pt1) left_neighbors = list(pts_cones_db[(x1, y1, z1)]) right_neighbors = list(pts_cones_db[(x2, y2, z2)]) left_neighbors.remove(cone) right_neighbors.remove(cone) if not left_neighbors: left_neighbors = [None] if not right_neighbors: right_neighbors = [None] for neighbor_left, neighbor_right in itertools.product(left_neighbors, right_neighbors): clips = [] # process the join on the "left" (end 1) if neighbor_left is not None: # any joins are created on the left pass; the right pass will only do clippings x0, y0, z0, r0 = neighbor_left._x0, neighbor_left._y0, neighbor_left._z0, neighbor_left._r0 if x0 == x1 and y0 == y1 and z0 == z1: x0, y0, z0, r0 = neighbor_left._x1, neighbor_left._y1, neighbor_left._z1, neighbor_left._r1 pt0 = numpy.array([x0, y0, z0]) naxis = (pt1 - pt0) / linalg.norm(pt1 - pt0) # no need to clip if the cones are perfectly aligned if any(axis != naxis): if r0 == r1 == r2: # simplest join: two cylinders (no need for all that nastiness below) sp = Sphere(x1, y1, z1, r1) sp.set_clip([Plane(x0, y0, z0, -naxis[0], -naxis[1], -naxis[2]), Plane(x2, y2, z2, axis[0], axis[1], axis[2])]) objects.append(sp) else: # is the turn sharp or not # CTNG:joinangle sharp_turn = numpy.dot(axis, naxis) < 0 # locate key vectors plane_normal = numpy.cross(axis, naxis) radial_vec = numpy.cross(plane_normal, axis) nradial_vec = numpy.cross(plane_normal, naxis) # normalize all of these radial_vec /= linalg.norm(radial_vec) nradial_vec /= linalg.norm(nradial_vec) # count the corners that are inside the other cone (for both ways) # CTNG:outsidecorners my_corner_count = count_outside(neighbor_left, [pt1 + r1 * radial_vec, pt1 - r1 * radial_vec]) corner_count = my_corner_count + count_outside(cone, [pt1 + r1 * nradial_vec, pt1 - r1 * nradial_vec]) # if corner_count == 0, then probably all nan's from size 0 meeting size 0; ignore # if is 1, probably parallel; no joins # if corner_count not in (1, 2, 3, 4): # print 'corner_count: ', corner_count, [pt1 + r1 * radial_vec, pt1 - r1 * radial_vec] + [pt1 + r1 * nradial_vec, pt1 - r1 * nradial_vec] if corner_count == 2: # CTNG:2outside # add clipped sphere; same rule if sharp or mild turn objects += join_outside(x0, y0, z0, r0, x1, y1, z1, r1, x2, y2, z2, r2, dx) elif corner_count == 3: sp = Sphere(x1, y1, z1, r1) if sharp_turn: # CTNG:3outobtuse if my_corner_count == 1: sp.set_clip([Plane(x1, y1, z1, -naxis[0], -naxis[1], -naxis[2])]) else: sp.set_clip([Plane(x1, y1, z1, axis[0], axis[1], axis[2])]) objects.append(sp) else: # CTNG:3outacute objects += join_outside(x0, y0, z0, r0, x1, y1, z1, r1, x2, y2, z2, r2, dx) if my_corner_count == 1: objects.append(tangent_sphere(neighbor_left, 1)) objects[-1].set_clip([Plane(x2, y2, z2, naxis[0], naxis[1], naxis[2])]) else: objects.append(tangent_sphere(cone, 0)) objects[-1].set_clip([Plane(x0, y0, z0, -axis[0], -axis[1], -axis[2])]) elif corner_count == 4: sp = Sphere(x1, y1, z1, r1) if sharp_turn: # CTNG:4outobtuse # join with the portions of a sphere that are outside at least one of the planes sp.set_clip([Union([ Plane(x1, y1, z1, axis[0], axis[1], axis[2]), Plane(x1, y1, z1, -naxis[0], -naxis[1], -naxis[2])])]) objects.append(sp) else: # CTNG:4outacute (+ 1 more) # join with the portions of a sphere that are outside both planes objects += join_outside(x0, y0, z0, r0, x1, y1, z1, r1, x2, y2, z2, r2, dx) # AND clip the cone to not extend pass the union of the neighbor's plane and the neighbor if r0 == r1: neighbor_copy = Cylinder(x0, y0, z0, x1, y1, z1, r0) else: neighbor_copy = Cone(x0, y0, z0, r0, x1, y1, z1, r1) clips.append(Union([ Plane(x1, y1, z1, -naxis[0], -naxis[1], -naxis[2]), neighbor_copy])) join_type = '%d%s' % (corner_count, 's' if sharp_turn else 'm') join_counts[join_type] += 1 if neighbor_right is not None: # any joins are created on the left pass; the right pass will only do clippings x3, y3, z3, r3 = neighbor_right._x0, neighbor_right._y0, neighbor_right._z0, neighbor_right._r0 if x2 == x3 and y2 == y3 and z2 == z3: x3, y3, z3, r3 = neighbor_right._x1, neighbor_right._y1, neighbor_right._z1, neighbor_right._r1 pt3 = numpy.array([x3, y3, z3]) naxis = (pt3 - pt2) / linalg.norm(pt3 - pt2) # no need to clip if the cones are perfectly aligned if any(axis != naxis): # locate key vectors plane_normal = numpy.cross(axis, naxis) radial_vec = numpy.cross(plane_normal, axis) radial_vec_norm = linalg.norm(radial_vec) # we check again because sometimes there are roundoff errors that this catches if radial_vec_norm: # is the turn sharp or not sharp_turn = numpy.dot(axis, naxis) < 0 nradial_vec = numpy.cross(plane_normal, naxis) # normalize all of these radial_vec /= radial_vec_norm nradial_vec /= linalg.norm(nradial_vec) # count the corners that are inside the other cone (for both ways) my_corner_count = count_outside(neighbor_right, [pt2 + r2 * radial_vec, pt2 - r2 * radial_vec]) corner_count = my_corner_count + count_outside(cone, [pt2 + r2 * nradial_vec, pt2 - r2 * nradial_vec]) if corner_count == 2: # no clipping; already joined pass elif corner_count == 3: pass elif corner_count == 4: # CTNG:4outacute (+ 1 more) # already joined; just clip (only in mild turn case) if not sharp_turn: if r2 == r3: neighbor_copy = Cylinder(x2, y2, z2, x3, y3, z3, r3) else: neighbor_copy = Cone(x2, y2, z2, r2, x3, y3, z3, r3) #print 'cc=4: (%g, %g, %g; %g) (%g, %g, %g; %g) (%g, %g, %g; %g) ' % (x1, y1, z1, r1, x2, y2, z2, r2, x3, y3, z3, r3) clips.append(Union([ Plane(x2, y2, z2, naxis[0], naxis[1], naxis[2]), neighbor_copy])) if clips: cone_clip_db[cone].append(Intersection(clips)) #print 'join_counts:' #print join_counts for cone in all_cones: clip = cone_clip_db[cone] if clip: cone.set_clip([Union(clip)]) ##################################################################### # # add the clipped objects to the list # ##################################################################### objects += all_cones return objects
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 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
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()