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 getParentDendrites(sec, parentsecList): if h.SectionRef(sec=sec).parent and h.SectionRef( sec=sec).parent.name().find('soma') == -1: parentSec = h.SectionRef(sec=sec).parent #print (" parentSec " + str(parentSec.name())) parentsecList.append([parentSec, parentSec.L]) return getParentDendrites(parentSec, parentsecList) else: return parentsecList
def parent_loc(sec, trueparent): """Return the position on the (true) parent where sec is connected Note that h.section_orientation(sec=sec) is which end of the section is connected. """ # TODO: would I ever have a parent but not a trueparent (or vice versa) sref = h.SectionRef(sec=sec) parent = sref.parent().sec while parent != trueparent: sec, parent = parent, h.SectionRef(sec=sec).parent().sec return h.parent_connection(sec=sec)
def add_spines(num_of_synapses,trees,secs,Xs): secs_sref_list = h.List() Xs_vec = h.Vector() for ix in range(num_of_synapses): #create Neuron's list of section refs if trees[ix] == 'apic': sref = h.SectionRef(sec = HCell.apic[secs[ix]]) else: sref = h.SectionRef(sec = HCell.dend[secs[ix]]) secs_sref_list.append(sref) Xs_vec.append(Xs[ix]) HCell.add_few_spines(secs_sref_list,Xs_vec,0.25,1.35,2.8,HCell.soma[0].Ra)
def branch_order(h, section, path=[]): """ Returns the branch order of a section """ path.append(section) sref = h.SectionRef(sec=section) # has_parent returns a float... cast to bool if sref.has_parent() < 0.9: return 0 # section is a root else: nchild = len(list(h.SectionRef(sec=sref.parent).child)) if nchild <= 1.1: return branch_order(h, sref.parent, path) else: return 1 + branch_order(h, sref.parent, path)
def parent(sec): """Return the parent of sec or None if sec is a root""" sref = h.SectionRef(sec=sec) if sref.has_trueparent(): return sref.trueparent().sec elif sref.has_parent(): temp = sref.parent().sec # check if temp owns the connection point if h.SectionRef(sec=temp).has_parent() and h.parent_connection( sec=temp) == h.section_orientation(sec=temp): # connection point belongs to temp's ancestor return parent(temp) return temp else: return None
def add_spines_on_segments(list_of_segments, seg_to_num_of_syn): HCell.delete_spine() total_synapses = 0 Xs_vec = h.Vector() secs_sref_list = h.List() for seg in list_of_segments: sec = seg.sec num_of_synapses = seg_to_num_of_syn[seg] assert num_of_synapses != 0, "segment on %s has 0 synapses" % sec.hname( ) Lsec = sec.L sref = h.SectionRef(sec=sec) if Lsec > CLUSTER_LENGTH: # distributes the spines on CLUSTER_LENGTH um on the section min_x = (Lsec - CLUSTER_LENGTH) / float(seg.x) else: # in cases where the section is shorter than CLUSTER_LENGTH mix_x = 0 for ix in range(num_of_synapses): secs_sref_list.append(sref) x_syn = min_x + ix * CLUSTER_LENGTH / float(num_of_synapses - 1) Xs_vec.append(min(x_syn / float(Lsec), 1)) total_synapses += num_of_synapses HCell.add_few_spines(secs_sref_list, Xs_vec, 0.25, 1.35, 2.8, HCell.soma[0].Ra) HCell.soma[0].push() return total_synapses
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 select_random_terminal_segments_by_sid(g, sid, count, by_length=True, replace=True): """Select segments from sections with specified sid. If by_length is True, select with probability proportional to the length of the segment. """ good_secs = [] for n in g.nodes(): sec = g.node[n]['orig'] if sec is not None and (g.node[n]['s'] == sid): ref = h.SectionRef(sec=sec) if len(ref.child) == 0: good_secs.append(sec) seg_list = [] seg_lengths = [] for sec in good_secs: for seg in sec: seg_list.append(seg) seg_lengths.append(sec.L / sec.nseg) seg_lengths = np.array(seg_lengths) probability = None if by_length: probability = seg_lengths / np.sum(seg_lengths) segs = np.random.choice(seg_list, size=count, p=probability, replace=replace) # Don't keep the segments around beyond this function, x and sec # will suffice to retrieve them return [(seg.sec, seg.x) for seg in segs]
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 find_parent_seg(join, sdict, objects): if not join: return None elif join[0] not in objects: pseg = sdict[( join[0]._x0, join[0]._y0, join[0]._z0, join[0]._x1, join[0]._y1, join[0]._z1, )] # better be all in same cell; so just set root once h.distance(0, h.SectionRef(sec=pseg.sec).root(0)) closest = h.distance(pseg) # any other possible instance? for item in join: if item not in objects: s = sdict[(item._x0, item._y0, item._z0, item._x1, item._y1, item._z1)] d = h.distance(s) if d < closest: pseg = s closest = d return pseg
def gen_primary_paths(model): """Generate all the possible primary path from the soma""" # Initialise with all the child from the soma pps = [[i.name()] for i in h.SectionRef(sec=model.sections["soma"]).child] for sec_name in pps: # Obtain all the child for the first section in the path child = h.SectionRef(sec=model.sections[sec_name[0]]).child child_names = [sec.name() for sec in child] sec_name += child_names i = 1 # Go through the all the section in the path while i < len(sec_name): child = h.SectionRef(sec=model.sections[sec_name[i]]).child child_names = [sec.name() for sec in child] sec_name += child_names i += 1 return pps
def save_degrees(cell): degrees = {} calculate_degree(h.SectionRef(sec=cell.hobj.soma[0]), degrees, 0) df_dict = {} df_dict["SectionName"] = list(degrees.keys()) df_dict["Degrees"] = list(degrees.values()) df = pd.DataFrame(df_dict) df.to_csv("SectionDegrees.csv", index=False)
def root_sections(h): """ Returns a list of all sections that have no parent. """ roots = [] for section in h.allsec(): sref = h.SectionRef(sec=section) # has_parent returns a float... cast to bool if sref.has_parent() < 0.9: roots.append(section) return roots
def __get_parent(self, sec, tree): """Recursive function used to create the tree list of section""" sec.push() secRef = h.SectionRef() if secRef.has_parent(): parentSeg = secRef.parent() parentSec = parentSeg.sec tree.append(parentSec) tree = self.__get_parent(parentSec, tree) h.pop_section() return tree
def leaf_sections(h): """ Returns a list of all sections that have no children. """ leaves = [] for section in h.allsec(): sref = h.SectionRef(sec=section) # nchild returns a float... cast to bool if sref.nchild() < 0.9: leaves.append(section) return leaves
def root_indices(sec_list): """ Returns the index of all sections without a parent. """ roots = [] for i, section in enumerate(sec_list): sref = h.SectionRef(sec=section) # has_parent returns a float... cast to bool if sref.has_parent() < 0.9: roots.append(i) return roots
def test(): sec = h.Section(name='dend') for sec in h.allsec(): h.disconnect(sec=sec) sref = h.SectionRef(sec=sec) #defeated the guards against deleting the Section pointed to by # a PythonSection sref.rename('delete') h.disconnect(sec=sec) #used to be allowed only for hoc sections (create ...) h.delete_section(sec=sec)
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
def add_Spines(num_of_spines, syn_trees, syn_secs, syn_segs): hocL = h.List() for i in range(num_of_spines): if syn_trees[i] == APIC: cell.apic[syn_secs[i]].push() else: cell.dend[syn_secs[i]].push() hocL.append(h.SectionRef()) h.pop_section() hocVxs = h.Vector(syn_segs) cell.add_few_spines(hocL, hocVxs, SPINE_NECK_DIAM, SPINE_NECK_L, SPINE_HEAD_AREA, SPINE_NECK_RA)
def add_spines_on_segments(HCell, list_of_segments): Xs_vec = h.Vector() secs_sref_list = h.List() for seg in list_of_segments: sec = seg.sec sref = h.SectionRef(sec=sec) secs_sref_list.append(sref) Xs_vec.append(min(seg.x, 1)) HCell.add_few_spines(secs_sref_list, Xs_vec, 0.25, 1.35, 2.8, HCell.soma[0].Ra)
def dist_to_mark(h, section, secdict, path=[]): path.append(section) sref = h.SectionRef(sec=section) # print 'current : '+str(section) # print 'parent : '+str(sref.parent) if secdict[sref.parent] is None: # print '-> go to parent' s = section.L + dist_to_mark(h, sref.parent, secdict, path) # print 'summing, '+str(s) return s else: # print 'end <- start summing: '+str(section.L) return section.L # parent is marked
def neuron_instance(neuron_import): """Sets/Resets the rxd test environment. Provides 'data', a dictionary used to store voltages and rxd node values for comparisons with the 'correct_data'. """ h, rxd = neuron_import data = {'record_count': 0, 'data': []} h.load_file('stdrun.hoc') cvode = h.CVode() cvode.active(False) cvode.atol(1e-3) h.dt = 0.025 h.stoprun = False def gather(): return collect_data(h, rxd, data) cvode.extra_scatter_gather(0, gather) yield (h, rxd, data) rxd.region._all_regions = [] rxd.region._region_count = 0 rxd.region._c_region_lookup = None for r in rxd.rxd._all_reactions[:]: if r(): rxd.rxd._unregister_reaction(r) for s in rxd.species._all_species: if s(): s().__del__() rxd.species._species_counts = 0 rxd.section1d._rxd_sec_lookup = {} rxd.section1d._purge_cptrs() rxd.initializer.has_initialized = False rxd.rxd.free_conc_ptrs() rxd.rxd.free_curr_ptrs() rxd.rxd.rxd_include_node_flux1D(0, None, None, None) for sec in h.allsec(): h.disconnect(sec=sec) sref = h.SectionRef(sec=sec) sref.rename('delete') h.delete_section(sec=sec) rxd.species._has_1d = False rxd.species._has_3d = False rxd.rxd._memb_cur_ptrs = [] rxd.rxd._rxd_induced_currents = None rxd.rxd._curr_indices = None rxd.rxd._zero_volume_indices = numpy.ndarray(0, dtype=numpy.int_) rxd.set_solve_type(dimension=1) cvode.extra_scatter_gather_remove(gather)
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 reduce_subtree(subtree_root, frequency): '''Reduces the subtree from the original_cell into one single section (cable). The reduction is done by finding the length and diameter of the cable (a single solution) that preserves the subtree's input impedance at the somatic end, and the transfer impedance in the subtree from the distal end to the proximal somatic end (between the new cable's two tips). ''' subtree_root_ref = h.SectionRef(sec=subtree_root) cm, rm, ra, e_pas, q = _get_subtree_biophysical_properties( subtree_root_ref, frequency) # finds the subtree's input impedance (at the somatic-proximal end of the # subtree root section) and the lowest transfer impedance in the subtree in # relation to the somatic-proximal end (see more in Readme on NeuroReduce) imp_obj, root_input_impedance = measure_input_impedance_of_subtree( subtree_root, frequency) # in Ohms (a complex number) curr_lowest_subtree_imp = find_lowest_subtree_impedance( subtree_root_ref, imp_obj) # reducing the whole subtree into one section: # L = 1/q * arcosh(ZtreeIn(f)/min(ZtreeX,0(f)), # d = ( (2/pi * (sqrt(Rm*Ra)/q*ZtreeIn(f)) * coth(qL) )^(2/3) - from Gal Eliraz's thesis 1999 new_cable_electrotonic_length = find_subtree_new_electrotonic_length( root_input_impedance, curr_lowest_subtree_imp, q) cable_electrotonic_length_as_complex = complex( new_cable_electrotonic_length, 0) new_cable_diameter_in_cm = _find_subtree_new_diam_in_cm( root_input_impedance, cable_electrotonic_length_as_complex, rm, ra, q) new_cable_diameter = new_cable_diameter_in_cm * 10000 # in microns # calculating the space constant, in order to find the cylinder's length: # space_const = sqrt(rm/(ri+r0)) curr_space_const_in_cm = find_space_const_in_cm(new_cable_diameter_in_cm, rm, ra) curr_space_const_in_micron = 10000 * curr_space_const_in_cm new_cable_length = curr_space_const_in_micron * new_cable_electrotonic_length # in microns return CableParams(length=new_cable_length, diam=new_cable_diameter, space_const=curr_space_const_in_micron, cm=cm, rm=rm, ra=ra, e_pas=e_pas, electrotonic_length=new_cable_electrotonic_length)
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 add_pre(h, sec_list, section, order_list=None, branch_order=None): """ A helper function that traverses a neuron's morphology (or a sub-tree) of the morphology in pre-order. This is usually not necessary for the user to import. """ sec_list.append(section) sref = h.SectionRef(sec=section) if branch_order is not None: order_list.append(branch_order) if len(sref.child) > 1: branch_order += 1 for next_node in sref.child: add_pre(h, sec_list, next_node, order_list, branch_order)
def PutSpines(section_type, sec_obj, spine_locs, neck_diam=0, neck_len=0, head_radius=0, Ra=0, cm=None, e_pas=None, g_pas=None): """ section type must be 'whole_cell', 'cable' or 'single_branch' (names of template files are '%s_template.hoc'%section_type). - Currently only adapted for 'cable' type because spine heads and necks are accessed from h.allsec() (doesn't distinguish spines on different branches) - Currently only adapted for new cable or data from Neurolucida because new hoc template is uploaded and spines added there """ dend_ref = h.SectionRef(sec_obj) spine_heads, spine_necks = [], [] for i in range(len(spine_locs)): # temp_neck = h.Section(name='spine_neck[%i]'%i) # I don't use h.Section() because then h.delete_section() doesn't work h('create spine_neck_%i' % i) exec('h.spine_neck_' + str(i) + '.diam = neck_diam') exec('h.spine_neck_' + str(i) + '.L = neck_len') exec('h.spine_neck_' + str(i) + '.insert(\'pas\')') exec('h.spine_neck_' + str(i) + '.connect(sec_obj(spine_locs[%i]), 0)' % i) # temp_head = h.Section(name='spine_head[%i]'%i) h('create spine_head_%i' % i) exec('h.spine_head_' + str(i) + '.diam = 2 * head_radius') exec('h.spine_head_' + str(i) + '.L = 2 * head_radius') exec('h.spine_head_' + str(i) + '.insert(\'pas\')') exec('h.spine_head_' + str(i) + '.connect(h.spine_neck_%i(1), 0)' % i) exec('spine_necks.append(h.spine_neck_' + str(i) + ')') exec('spine_heads.append(h.spine_head_' + str(i) + ')') for param in ['cm', 'e_pas', 'Ra', 'g_pas']: for spine in spine_heads + spine_necks: setattr(spine, param, eval(param)) h.define_shape() return spine_heads, spine_necks
def all_branch_orders(h): """ Produces a list branch orders for each section (following pre-order tree traversal) """ #Iterate over all sections, find roots roots = [] for section in h.allsec(): sref = h.SectionRef(sec=section) # has_parent returns a float... cast to bool if sref.has_parent() < 0.9: roots.append(section) # Build list of all sections order_list = [] for r in roots: add_pre(h, [], r, order_list, 0) return order_list
def add_spines_on_seg(num_of_synapses,sec,x): Lsec = sec.L sref = h.SectionRef(sec=sec) xL = float(x)*Lsec maxX = xL+CLUSTER_LENGTH/2.0 if xL+10>Lsec: maxX = Lsec minX = xL-10 if xL-10<0: minX = 0 local_vec_x = h.Vector() list_sref = h.List() for ix in range(num_of_synapses): list_sref.append(sref) local_vec_x.append(np.random.uniform(minX/Lsec,maxX/Lsec)) HCell.add_few_spines(list_sref,local_vec_x,0.25,1.35,2.8,HCell.soma[0].Ra)