def get_cell(self, cellname=None): """ Either return a cell by name if there is more than one cell, otherwise the single cell """ if cellname: return SeqUtils.filter_expect_single(self.cells, lambda s: s.name == cellname) else: return SeqUtils.expect_single(self.cells)
def getitem(self, *args, **kwargs): assert len(kwargs) == 1 k = kwargs.keys()[0] v = kwargs[k] assert len(args) == 0 if isinstance(k, collections.Callable): return SeqUtils.expect_single([k(o) for o in self.data]) elif isinstance(k, basestring): return SeqUtils.expect_single([o for o in self.data if getattr(o, k) == v]) else: print "Unexpected Type of %s - %s" % (k, type(k)) assert False
def get_evset(self, obj): # Get the results by string: if isinstance(obj, basestring): return SeqUtils.filter_expect_single( self.evsets, lambda s: s.name == obj) else: assert False
def getitem(self, *args, **kwargs): assert len(kwargs) == 1 k = kwargs.keys()[0] v = kwargs[k] assert len(args) == 0 if isinstance(k, collections.Callable): return SeqUtils.expect_single([k(o) for o in self.data]) elif isinstance(k, basestring): return SeqUtils.expect_single( [o for o in self.data if getattr(o, k) == v]) else: print 'Unexpected Type of %s - %s' % (k, type(k)) assert False
def get_trace(self, obj): # Get the results by string: if isinstance(obj, basestring): return SeqUtils.filter_expect_single( self.traces, lambda s: s.name == obj) # Get the results by Recordable object: else: return self.get_trace(obj.name)
def get_trace(self, obj): # Get the results by string: if isinstance(obj, basestring): return SeqUtils.filter_expect_single(self.traces, lambda s: s.name == obj) # Get the results by Recordable object: else: return self.get_trace(obj.name)
def record_from_mechanism(sim, mechanism_name, cell_location, what, on_error_skip=False, user_tags = None, **kwargs): user_tags = user_tags or [] assert on_error_skip == False mechs = cell_location.cell.get_biophysics().get_all_mechanisms_applied_to_cell() chl = SeqUtils.filter_expect_single(seq=mechs, filter_func=lambda m:m.name==mechanism_name) r = sim.record(chl, what=what, cell_location=cell_location, user_tags = user_tags + [chl.name], **kwargs) return r
def load_cell(cls, cellNode, regions=None): cableIDToRegionName, segmentListInfo = cls.load_cell_dictionaries(cellNode, regions=regions) # Make all the regions: regionNames = list(set(Filter(cableIDToRegionName.values(), lambda e: e is not None))) print "RegionNames:", regionNames regionNamesClean = [_clean_name(str(region_name)) for region_name in regionNames] rgns = [Region(name=region_name) for region_name in regionNamesClean] region_nameToRegionDict = dict([(rgn.name, rgn) for rgn in rgns]) cableIDToRegionDict = dict( [ (cableId, region_nameToRegionDict[_clean_name(region_name)]) if region_name is not None else (cableId, None) for cableId, region_name in cableIDToRegionName.iteritems() ] ) # Find the node without a parent: rN = SeqUtils.filter_expect_single(segmentListInfo.values(), lambda s: not s[3]) # Recursively Construct by finding what should be attached to current structure: # (id, name, cable, parent, (px, py, pz, pDiam), (dx, dy, dz, dDiam)) # rDummy = Section(region=cableIDToRegionDict[rN[2]], x=rN[4][0], y=rN[4][1], z=rN[4][2], r=rN[4][3] / 2.0) rDummy = Section(region=None, x=rN[4][0], y=rN[4][1], z=rN[4][2], r=rN[4][3] / 2.0) rActual = rDummy.create_distal_section( region=cableIDToRegionDict[rN[2]], x=rN[5][0], y=rN[5][1], z=rN[5][2], r=rN[5][3] / 2.0, idtag=rN[1] ) idToSectionMap = {rN[0]: rActual} recentlyAdded = [rN[0]] while recentlyAdded != []: curNode = recentlyAdded[0][0] curSect = idToSectionMap[curNode] recentlyAdded = recentlyAdded[1:] childNodes = Filter(segmentListInfo.values(), lambda s: s[3] == curNode) for c in childNodes: # print c newSect = curSect.create_distal_section( region=cableIDToRegionDict[c[2]], x=c[5][0], y=c[5][1], z=c[5][2], r=c[5][3] / 2.0, idtag=c[1] ) idToSectionMap[c[0]] = newSect recentlyAdded.append(c) return MorphologyTree(name="FromNeuroML", dummysection=rDummy, metadata={})
def load(cls, neuroMLFileObj, regions=None): """regions is a dictionary, which maps cable-groups to a Region name; this handles the case when there are multiple group tags in a MorphML document, since morphforge does not allow multiple regions' """ doc = XML.parse(neuroMLFileObj).documentElement assert doc.tagName in ('morphml', 'neuroml') # Do the action: cellsNode = SeqUtils.filter_expect_single( doc.childNodes, filter_func=isElementWithTag("cells")) morphs = [] for cellNode in Filter(cellsNode.childNodes, isElementWithTag("cell")): morph = cls.load_cell(cellNode, regions=regions) morphs.append(morph) assert len(morphs) == 1 return morphs[0]
def load(cls, src, regions=None): """regions is a dictionary, which maps cable-groups to a Region name; this handles the case when there are multiple group tags in a MorphML document, since morphforge does not allow multiple regions' """ doc = XML.parse(src).documentElement assert doc.tagName in ("morphml", "neuroml") # Do the action: cellsNode = SeqUtils.filter_expect_single(doc.childNodes, filter_func=isElementWithTag("cells")) morphs = [] for cellNode in Filter(cellsNode.childNodes, isElementWithTag("cell")): morph = cls.load_cell(cellNode, regions=regions) morphs.append(morph) assert len(morphs) == 1 return morphs[0]
def buildPaneFromExistingChannelInfTau1State(existing_channel_functor, sim_config, chlname): # Setup the channel, so we can look at inf_tau: chl = existing_channel_functor(NEURONEnvironment()) state_name = SeqUtils.expect_single(chl.statevars.keys()) state=buildStatePane(chl, state_name) general=HHGeneralPanel( gbar=float(chl.conductance.rescale('mS/cm2').magnitude), vrev=float(chl.reversalpotential.rescale("mV").magnitude) ) return HHChannelPaneInfTau1(sim_config=sim_config, general_pane=general, state_pane=state, eqn = chl.eqn, state_var_name = state_name, chlname = chlname )
def record_from_mechanism(sim, mechanism_name, cell_location, what, on_error_skip=False, user_tags=None, **kwargs): user_tags = user_tags or [] assert on_error_skip == False mechs = cell_location.cell.get_biophysics( ).get_all_mechanisms_applied_to_cell() chl = SeqUtils.filter_expect_single( seq=mechs, filter_func=lambda m: m.name == mechanism_name) r = sim.record(chl, what=what, cell_location=cell_location, user_tags=user_tags + [chl.name], **kwargs) return r
def load_cell_dictionaries(self, cellNode, regions=None): l1 = Level1NeuroMLRepresentation(cellNode) print "CellName:", cellNode.getAttribute("name") # We are not too worried about cables, but we do need the region name out of them: cableIDToRegionName = {} cablesNode = SeqUtils.filter_expect_single(cellNode.childNodes, isElementWithTag("cables")) for cableNode in Filter(cablesNode.childNodes, isElementWithTag("cable")): id = cableNode.getAttribute("id") name = cableNode.getAttribute("name") group_nodes = Filter(cableNode.childNodes, isElementWithTag("group")) if group_nodes: if regions: # for n in group_nodes: # print get_text(n) metaGroupNode = SeqUtils.filter_expect_single(group_nodes, lambda e: get_text(e) in regions) region_name = regions[get_text(metaGroupNode)] else: metaGroupNode = SeqUtils.expect_single(group_nodes) region_name = get_text(metaGroupNode) assert not id in cableIDToRegionName cableIDToRegionName[id] = region_name else: cableIDToRegionName[id] = None pass print "Loaded Cable: ", id, name # Load the segments: segmentListInfo = {} # id -> (id, name, cable, parent, (px, py, pz, pDiam), (dx, dy, dz, dDiam)) segmentsNode = SeqUtils.filter_expect_single(cellNode.childNodes, isElementWithTag("segments")) for segNode in Filter(segmentsNode.childNodes, isElementWithTag("segment")): print "Segment" id = segNode.getAttribute("id") name = segNode.getAttribute("name") cable = segNode.getAttribute("cable") parent = segNode.getAttribute("parent") # Every point should have a distal End: dNode = SeqUtils.filter_expect_single(segNode.childNodes, isElementWithTag("distal")) d_x, d_y, d_z = dNode.getAttribute("x"), dNode.getAttribute("y"), dNode.getAttribute("z") d_diam = dNode.getAttribute("diameter") if not parent: pass pNode = SeqUtils.filter_expect_single(segNode.childNodes, isElementWithTag("proximal")) p_x, p_y, p_z = pNode.getAttribute("x"), pNode.getAttribute("y"), pNode.getAttribute("z") p_diam = pNode.getAttribute("diameter") else: # Not every point need have a proximal end, we look at the parent in case it has # both and check the locations agree parent_Dist_Loc = segmentListInfo[parent][5] pNode = Filter(segNode.childNodes, isElementWithTag("proximal")) if len(pNode) == 0: p_x, p_y, p_z, p_diam = parent_Dist_Loc elif len(pNode) == 1: p_xR, p_yR, p_zR = ( pNode[0].getAttribute("x"), pNode[0].getAttribute("y"), pNode[0].getAttribute("z"), ) p_diamR = pNode[0].getAttribute("diameter") # I do not understand MorphML to understand why these checks do not fail.... # print (p_xR, p_yR, p_zR) # print (parent_Dist_Loc[0], parent_Dist_Loc[1], parent_Dist_Loc[2]) # assert (p_xR, p_yR, p_zR) == (parent_Dist_Loc[0], parent_Dist_Loc[1], parent_Dist_Loc[2]) # In this case, use the diameter just read: p_x, p_y, p_z = p_xR, p_yR, p_zR p_diam = p_diamR else: assert False print id, name, cable, parent, (p_x, p_y, p_z, p_diam), (d_x, d_y, d_z, d_diam) infTuple = ( id, name, cable, parent, (float(p_x), float(p_y), float(p_z), float(p_diam)), (float(d_x), float(d_y), float(d_z), float(d_diam)), ) assert not id in segmentListInfo segmentListInfo[id] = infTuple # Now we have read the file and created the dictionaries: return (cableIDToRegionName, segmentListInfo)
def load(cls, morph_dict, name=None, metadata=None): """ Load a morphology from a recursive dictionary such as: {'root': {'length': 20, 'diam': 20, 'sections': [ {'absangle': 120, 'length': 40, 'diam': 5, 'region': 'dendrite'}, {'absangle': 240, 'length': 40, 'diam': 5, 'sections': [ {'region': 'dendrite', 'diam': 5, 'relangle': 240, 'length': 40} ], 'region': 'dendrite'}, {'absangle': 5, 'length': 500, 'diam': 0.29999999999999999, 'region': 'axon'}], 'region': 'soma'}} If addRootSection is true, then we make the root section, by adding in a fake section: """ if not morph_dict or not morph_dict.has_key('root'): raise ValueError() valid_keywords = [ 'length', 'diam', 'id', 'sections', 'region', 'regions', 'relangle', 'absangle', 'xyz', ] required_keywords = ['diam'] # Does the root has a length variable? if it does, then lets add an intermediate node and remove it. root_node = morph_dict['root'] if root_node.has_key('length'): # Lets assume it extends backwards on the X-axis. This isn't great, but will work, although # visualisations are likely to look a bit screwy: assert not root_node.has_key('xyz') new_root_node = { 'region': 'soma', 'diam': root_node['diam'], 'xyz': (0.0, 0.0, 0.0), 'sections': [root_node], } root_node = new_root_node #First flatten the recursion, by copy #the dictionary and adding a parent tag: yaml_section_dict = {} # id to paramDict def recursively_add_section_to_list(sectionNode, sectionNodeParentID, sectionDictInt): for key in sectionNode.keys(): if not key in valid_keywords: raise ValueError('Invalid Keyword: ' + key) for req_kw in required_keywords: if not req_kw in sectionNode.keys(): raise ValueError('Required Key: %s not found.' % req_kw) children = sectionNode.get('sections', []) if sectionNode.has_key('sections'): del sectionNode['sections'] section_id = len(sectionDictInt) sectionDictInt[section_id] = merge_dictionaries([{ "parent": sectionNodeParentID }, sectionNode]) for child in children: recursively_add_section_to_list(child, section_id, sectionDictInt) #root_node = morph_dict["root"] recursively_add_section_to_list(root_node, None, yaml_section_dict) #We now have a dictionary similar to: # """ 0 {'length': 20, 'diam': 20, 'region': 'soma', 'parent': None} # 1 {'absangle': 120, 'length': 40, 'diam': 5, 'region': 'dendrite', 'parent': 0} # 2 {'absangle': 240, 'length': 40, 'diam': 5, 'region': 'dendrite', 'parent': 0} # 3 {'length': 40, 'region': 'dendrite', 'diam': 5, 'relangle': 240, 'parent': 2} # 4 {'absangle': 5, 'length': 500, 'diam': 0.29999999999999999, 'region': 'axon', 'parent': 0} # """ #Map a lack of region to region:"NoRegionGiven" for yml in yaml_section_dict.values(): if not ('region' in yml or 'regions' in yml): yml['region'] = 'NoRegionGiven' region_names1 = [ yml["region"] for yml in yaml_section_dict.values() if yml.has_key("region") ] region_names2 = SeqUtils.flatten([ yml["regions"] for yml in yaml_section_dict.values() if yml.has_key("regions") ]) region_names = list(set(region_names1 + region_names2)) region_dict = dict([(region_name, Region(region_name)) for region_name in region_names]) section_angles_dict = {} section_id_tags = [] # We create a 'dummy' root node, and then the real root node. # This will be at index '0' # Do we need to create a dummy node explicity? This depends on whether the root node has a length: section_dict = {} root_yaml_sect = yaml_section_dict[0] if 'length' in root_yaml_sect.keys(): assert False xyz = root_yaml_sect['xyz'] section_dict[0] = Section( x=xyz[0], y=xyz[1], z=xyz[2], r=root_yaml_sect['diam'] / 2.0, region=None, parent=None, ) # Add the remaining nodes: for (yaml_id, yaml_sect) in yaml_section_dict.iteritems(): if yaml_sect['parent'] == None: continue # print yaml_id, yaml_sect parent_section = section_dict[yaml_sect['parent']] #Region: rg_names1 = [yaml_sect["region"] ] if yaml_sect.has_key("region") else [] rg_names2 = yaml_sect["regions"] if yaml_sect.has_key( "regions") else [] rgs = [region_dict[rgName] for rgName in rg_names1 + rg_names2] # Since December 2010 each section is only allowed to have one # region. assert len(rgs) <= 1 #Diameter & length: if not yaml_sect.has_key("diam"): raise ValueError("Not radius given") diam = yaml_sect["diam"] if not (diam > 0): raise ValueError("indvalid radius: %s" % diam) rad = diam / 2.0 # End Point: def get_yaml_length(yaml_sect): if not yaml_sect.has_key("length"): raise ValueError("No Length given") length = yaml_sect["length"] if not length > 0: raise ValueError("Invalid Length") return length #We only specify end points by using angles or by xyz cooridinates: if int(yaml_sect.has_key("absangle")) + int( yaml_sect.has_key("relangle")) + int( yaml_sect.has_key("xyz")) >= 2: raise ValueError("Too many ways for specifying endpoint") if yaml_sect.has_key('xyz'): if not parent_section: angle = 0 xyz = yaml_sect['xyz'] elif yaml_sect.has_key("absangle"): length = get_yaml_length(yaml_sect) angle = yaml_sect['absangle'] xyz = (parent_section.d_x + length * math.cos(math.radians(angle)), parent_section.d_y + length * math.sin(math.radians(angle)), 0.0) elif yaml_sect.has_key('relangle'): length = get_yaml_length(yaml_sect) angle = section_angles_dict[parent_section] + yaml_sect[ "relangle"] xyz = (parent_section.d_x + length * math.cos(math.radians(angle)), parent_section.d_y + length * math.sin(math.radians(angle)), 0.0) else: # Default to 'abs'-angle to 0 length = get_yaml_length(yaml_sect) angle = 0 xyz = (parent_section.d_x + length * math.cos(math.radians(angle)), parent_section.d_y + length * math.sin(math.radians(angle)), 0.0) # Possible ID's: section_id_tag = (yaml_sect['id'] if yaml_sect.has_key('id') else None) if section_id_tag: check_cstyle_varname(section_id_tag) if section_id_tag in section_id_tags: raise ValueError('Duplicate Section ID: %s' % section_id_tag) if section_id_tag: section_id_tags.append(section_id_tag) # Create the new section: if parent_section: new_section = parent_section.create_distal_section( x=xyz[0], y=xyz[1], z=xyz[2], r=rad, region=rgs[0], idtag=section_id_tag) else: new_section = Section(x=xyz[0], y=xyz[1], z=xyz[2], r=rad, region=None, idtag=section_id_tag) section_dict[None] = new_section # Calculate the angle of the current section: if parent_section: joining_vec = new_section.get_distal_npa3( ) - parent_section.get_distal_npa3() angle = math.radians(math.atan2(joining_vec[1], joining_vec[0])) section_angles_dict[new_section] = angle #Save the section: section_dict[yaml_id] = new_section # # TODO: THIS IS A HACK! Ensure the dummy node has no attached regions: # section_dict[None].regions = [] assert section_dict[0].region == None if section_dict[0].children == []: raise ValueError("No segments found") morphs = MorphologyTree(name=name, dummysection=section_dict[0], metadata=metadata) if len(morphs) < 1: raise ValueError return morphs
def FilterExpectSingleChildrenByTag(node, tag): return SeqUtils.filter_expect_single(node.childNodes, isElementWithTag(tag))
def load_cell_dictionaries(self, cellNode, regions=None): l1 = Level1NeuroMLRepresentation(cellNode) print 'CellName:', cellNode.getAttribute('name') # We are not too worried about cables, but we do need the region name out of them: cableIDToRegionName = {} cablesNode = SeqUtils.filter_expect_single(cellNode.childNodes, isElementWithTag("cables")) for cableNode in Filter(cablesNode.childNodes, isElementWithTag("cable")): id = cableNode.getAttribute("id") name = cableNode.getAttribute("name") group_nodes = Filter(cableNode.childNodes, isElementWithTag("group")) if group_nodes: if regions: metaGroupNode = SeqUtils.filter_expect_single( group_nodes, lambda e: get_text(e) in regions) region_name = regions[get_text(metaGroupNode)] else: metaGroupNode = SeqUtils.expect_single(group_nodes) region_name = get_text(metaGroupNode) assert not id in cableIDToRegionName cableIDToRegionName[id] = region_name else: cableIDToRegionName[id] = None pass print 'Loaded Cable: ', id, name # Load the segments: segmentListInfo = { } # id -> (id, name, cable, parent, (px, py, pz, pDiam), (dx, dy, dz, dDiam)) segmentsNode = SeqUtils.filter_expect_single( cellNode.childNodes, isElementWithTag("segments")) for segNode in Filter(segmentsNode.childNodes, isElementWithTag("segment")): print "Segment" id = segNode.getAttribute("id") name = segNode.getAttribute("name") cable = segNode.getAttribute("cable") parent = segNode.getAttribute("parent") # Every point should have a distal End: dNode = SeqUtils.filter_expect_single(segNode.childNodes, isElementWithTag("distal")) d_x, d_y, d_z = dNode.getAttribute("x"), dNode.getAttribute( "y"), dNode.getAttribute("z") d_diam = dNode.getAttribute("diameter") if not parent: pass pNode = SeqUtils.filter_expect_single( segNode.childNodes, isElementWithTag("proximal")) p_x, p_y, p_z = pNode.getAttribute("x"), pNode.getAttribute( "y"), pNode.getAttribute("z") p_diam = pNode.getAttribute("diameter") else: # Not every point need have a proximal end, we look at the parent in case it has # both and check the locations agree parent_Dist_Loc = segmentListInfo[parent][5] pNode = Filter(segNode.childNodes, isElementWithTag("proximal")) if len(pNode) == 0: p_x, p_y, p_z, p_diam = parent_Dist_Loc elif len(pNode) == 1: p_xR, p_yR, p_zR = pNode[0].getAttribute("x"), pNode[ 0].getAttribute("y"), pNode[0].getAttribute("z") p_diamR = pNode[0].getAttribute("diameter") # I do not understand MorphML to understand why these checks do not fail.... #print (p_xR, p_yR, p_zR) #print (parent_Dist_Loc[0], parent_Dist_Loc[1], parent_Dist_Loc[2]) #assert (p_xR, p_yR, p_zR) == (parent_Dist_Loc[0], parent_Dist_Loc[1], parent_Dist_Loc[2]) # In this case, use the diameter just read: p_x, p_y, p_z = p_xR, p_yR, p_zR p_diam = p_diamR else: assert False print id, name, cable, parent, (p_x, p_y, p_z, p_diam), (d_x, d_y, d_z, d_diam) infTuple = (id, name, cable, parent, (float(p_x), float(p_y), float(p_z), float(p_diam)), (float(d_x), float(d_y), float(d_z), float(d_diam))) assert not id in segmentListInfo segmentListInfo[id] = infTuple # Now we have read the file and created the dictionaries: return (cableIDToRegionName, segmentListInfo)
def load_cell(cls, cellNode, regions=None): cableIDToRegionName, segmentListInfo = cls.load_cell_dictionaries( cellNode, regions=regions) # Make all the regions: regionNames = list( set(Filter(cableIDToRegionName.values(), lambda e: e is not None))) print 'RegionNames:', regionNames regionNamesClean = [ _clean_name(str(region_name)) for region_name in regionNames ] rgns = [Region(name=region_name) for region_name in regionNamesClean] region_nameToRegionDict = dict([(rgn.name, rgn) for rgn in rgns]) cableIDToRegionDict = dict([ (cableId, region_nameToRegionDict[_clean_name(region_name)]) if region_name is not None else (cableId, None) for cableId, region_name in cableIDToRegionName.iteritems() ]) # Find the node without a parent: rN = SeqUtils.filter_expect_single(segmentListInfo.values(), lambda s: not s[3]) #Recursively Construct by finding what should be attached to current structure: #(id, name, cable, parent, (px, py, pz, pDiam), (dx, dy, dz, dDiam)) #rDummy = Section(region=cableIDToRegionDict[rN[2]], x=rN[4][0], y=rN[4][1], z=rN[4][2], r=rN[4][3] / 2.0) rDummy = Section(region=None, x=rN[4][0], y=rN[4][1], z=rN[4][2], r=rN[4][3] / 2.0) rActual = rDummy.create_distal_section( region=cableIDToRegionDict[rN[2]], x=rN[5][0], y=rN[5][1], z=rN[5][2], r=rN[5][3] / 2.0, idtag=rN[1]) idToSectionMap = {rN[0]: rActual} recentlyAdded = [rN[0]] while recentlyAdded != []: curNode = recentlyAdded[0][0] curSect = idToSectionMap[curNode] recentlyAdded = recentlyAdded[1:] childNodes = Filter(segmentListInfo.values(), lambda s: s[3] == curNode) for c in childNodes: #print c newSect = curSect.create_distal_section( region=cableIDToRegionDict[c[2]], x=c[5][0], y=c[5][1], z=c[5][2], r=c[5][3] / 2.0, idtag=c[1]) idToSectionMap[c[0]] = newSect recentlyAdded.append(c) return MorphologyTree(name='FromNeuroML', dummysection=rDummy, metadata={})
def __init__(self, cellNode): self.cables = SearchableSet() self.cablegroups = SearchableSet() self.segments = SearchableSet() # Read the XML: # Start with the declared Cables: cablesNode = FilterExpectSingleChildrenByTag(cellNode, 'cables') # Load the individual cable objects for cableNode in FilterChildrenByTag(cablesNode, "cable"): if cableNode.getAttribute('id') in self.cables.keys('cable_id'): continue cable = NeuroMLCable(cable_id=cableNode.getAttribute('id'), name=cablesNode.getAttribute('name')) self.cables.add(cable) # Does the cable belong to any groups? for group_node in Filter(cableNode.childNodes, isElementWithTag("group")): cablegroupname = get_text(group_node) if not cablegroupname in self.cablegroups.keys('name'): self.cablegroups.add( NeuroMLCableGroup(name=cablegroupname)) self.cablegroups.getitem(name=cablegroupname).add_cable(cable) # Load the CableGroup Objects: for cableGroupNode in Filter(cablesNode.childNodes, isElementWithTag("cablegroup")): # Get, or create, the cable node: cablegroupname = cableGroupNode.getAttribute('name') if not cablegroupname in self.cablegroups.keys('name'): self.cablegroups.add(NeuroMLCableGroup(name=cablegroupname)) grp = self.cablegroups.getitem(name=cablegroupname) # Add the cable segments: for cableNode in Filter(cableGroupNode.childNodes, isElementWithTag("cable")): cableNodeID = cableNode.getAttribute('id') if not cableNodeID in self.cables.keys('cable_id'): assert False cable = self.cables.getitem(cable_id=cableNodeID) grp.add_cable(cable) # Load the Segments Objects: segmentsNode = SeqUtils.filter_expect_single( cellNode.childNodes, isElementWithTag("segments")) for segmentNode in Filter(segmentsNode.childNodes, isElementWithTag("segment")): #Attributes: segment_id = segmentNode.getAttribute('id') parent_id = segmentNode.getAttribute('parent') cable_id = segmentNode.getAttribute('cable') cable = self.cables.getitem( cable_id=cable_id) if cable_id else None # Distal Information: distalNode = FilterExpectSingleChildrenByTag(segmentNode, 'distal') d_X, d_Y, d_Z, d_d = float(distalNode.getAttribute('x')), float( distalNode.getAttribute('y')), float( distalNode.getAttribute('z')), float( distalNode.getAttribute('diameter')) dInfo = (d_X, d_Y, d_Z, d_d) proximalNode = FilterChildrenByTag(segmentNode, 'proximal') # Root node: if not parent_id: assert proximalNode proximalNode = SeqUtils.expect_single(proximalNode) p_X, p_Y, p_Z, p_d = float( proximalNode.getAttribute('x')), float( proximalNode.getAttribute('y')), float( proximalNode.getAttribute('z')), float( proximalNode.getAttribute('diameter')) pInfo = (p_X, p_Y, p_Z, p_d) segment = NeuroMLSegment(segment_id=segment_id, distInfo=dInfo, proxInfo=pInfo, parent=None, cable=cable) #Child Node: else: # Not the root node, but a proximal node is provided: if proximalNode: pInfo = (p_X, p_Y, p_Z, p_d) # Proximal node and NOT the root: if parent_id: parentNode = self.segments.getitem( segment_id=parent_id) parentDistalInfo = parentNode.distInfo eps = 0.01 # assert fabs(parentDistalInfo[0] - pInfo[0]) < eps # assert fabs(parentDistalInfo[1] - pInfo[1]) < eps # assert fabs(parentDistalInfo[2] - pInfo[2]) < eps # assert fabs(parentDistalInfo[3] - pInfo[3]) < eps # Add the child node: segment = NeuroMLSegment(segment_id=segment_id, distInfo=dInfo, proxInfo=pInfo, parent=None, cable=cable) # Add the segment to groups? self.segments.add(segment)
def load(cls, morph_dict, name=None, metadata=None): """ Load a morphology from a recursive dictionary such as: {'root': {'length': 20, 'diam': 20, 'sections': [ {'absangle': 120, 'length': 40, 'diam': 5, 'region': 'dendrite'}, {'absangle': 240, 'length': 40, 'diam': 5, 'sections': [ {'region': 'dendrite', 'diam': 5, 'relangle': 240, 'length': 40} ], 'region': 'dendrite'}, {'absangle': 5, 'length': 500, 'diam': 0.29999999999999999, 'region': 'axon'}], 'region': 'soma'}} """ if not morph_dict or not morph_dict.has_key('root'): raise ValueError() valid_keywords = [ 'length', 'diam', 'id', 'sections', 'region', 'regions', 'relangle', 'absangle', 'xyz', ] required_keywords = ['diam'] # Does the root has a length variable? if it does, then lets add an intermediate node and remove it. root_node = morph_dict['root'] if root_node.has_key('length'): # Lets assume it extends backwards on the X-axis. This isn't great, but will work, although # visualisations are likely to look a bit screwy: assert not root_node.has_key('xyz') new_root_node = { 'region': 'soma', 'diam': root_node['diam'], 'xyz': (0.0, 0.0, 0.0), 'sections': [root_node], } root_node = new_root_node #First flatten the recursion, by copy #the dictionary and adding a parent tag: yaml_section_dict = {} # id to paramDict def recursively_add_section_to_list(sectionNode, sectionNodeParentID, sectionDictInt): for key in sectionNode.keys(): if not key in valid_keywords: raise ValueError('Invalid Keyword: ' + key) for req_kw in required_keywords: if not req_kw in sectionNode.keys(): raise ValueError('Required Key: %s not found.' % req_kw) children = sectionNode.get('sections', []) if sectionNode.has_key('sections'): del sectionNode['sections'] section_id = len(sectionDictInt) sectionDictInt[section_id] = merge_dictionaries([{"parent": sectionNodeParentID}, sectionNode]) for child in children: recursively_add_section_to_list(child, section_id, sectionDictInt) #root_node = morph_dict["root"] recursively_add_section_to_list(root_node, None, yaml_section_dict) #We now have a dictionary similar to: # """ 0 {'length': 20, 'diam': 20, 'region': 'soma', 'parent': None} # 1 {'absangle': 120, 'length': 40, 'diam': 5, 'region': 'dendrite', 'parent': 0} # 2 {'absangle': 240, 'length': 40, 'diam': 5, 'region': 'dendrite', 'parent': 0} # 3 {'length': 40, 'region': 'dendrite', 'diam': 5, 'relangle': 240, 'parent': 2} # 4 {'absangle': 5, 'length': 500, 'diam': 0.29999999999999999, 'region': 'axon', 'parent': 0} # """ #Map a lack of region to region:"NoRegionGiven" for yml in yaml_section_dict.values(): if not ('region' in yml or 'regions' in yml): yml['region'] = 'NoRegionGiven' region_names1 = [yml["region"] for yml in yaml_section_dict.values() if yml.has_key("region")] region_names2 = SeqUtils.flatten([yml["regions"] for yml in yaml_section_dict.values() if yml.has_key("regions")]) region_names = list(set(region_names1 + region_names2)) region_dict = dict([(region_name, Region(region_name)) for region_name in region_names]) section_angles_dict = {} section_id_tags = [] # We create a 'dummy' root node, and then the real root node. # This will be at index '0' # Do we need to create a dummy node explicity? This depends on whether the root node has a length: section_dict = {} root_yaml_sect = yaml_section_dict[0] if 'length' in root_yaml_sect.keys(): assert False xyz = root_yaml_sect['xyz'] section_dict[0] = Section( x=xyz[0], y=xyz[1], z=xyz[2], r=root_yaml_sect['diam'] / 2.0, region=None, parent=None, ) # Add the remaining nodes: for (yaml_id, yaml_sect) in yaml_section_dict.iteritems(): if yaml_sect['parent'] == None: continue # print yaml_id, yaml_sect parent_section = section_dict[yaml_sect['parent']] #Region: rg_names1 = [yaml_sect["region"]] if yaml_sect.has_key("region") else [] rg_names2 = yaml_sect["regions"] if yaml_sect.has_key("regions") else [] rgs = [region_dict[rgName] for rgName in rg_names1 + rg_names2 ] # Since December 2010 each section is only allowed to have one # region. assert len(rgs) <= 1 #Diameter & length: if not yaml_sect.has_key("diam"): raise ValueError("Not radius given") diam = yaml_sect["diam"] if not (diam > 0): raise ValueError("indvalid radius: %s" % diam ) rad = diam / 2.0 # End Point: def get_yaml_length(yaml_sect): if not yaml_sect.has_key("length"): raise ValueError("No Length given") length = yaml_sect["length"] if not length > 0: raise ValueError("Invalid Length") return length #We only specify end points by using angles or by xyz cooridinates: if int(yaml_sect.has_key("absangle")) + int(yaml_sect.has_key("relangle")) + int(yaml_sect.has_key("xyz")) >= 2: raise ValueError("Too many ways for specifying endpoint") if yaml_sect.has_key('xyz'): if not parent_section: angle = 0 xyz = yaml_sect['xyz'] elif yaml_sect.has_key("absangle"): length = get_yaml_length(yaml_sect) angle = yaml_sect['absangle'] xyz = (parent_section.d_x + length * math.cos(math.radians(angle)), parent_section.d_y + length * math.sin(math.radians(angle)), 0.0) elif yaml_sect.has_key('relangle'): length = get_yaml_length(yaml_sect) angle = section_angles_dict[parent_section] + yaml_sect["relangle"] xyz = (parent_section.d_x + length * math.cos(math.radians(angle)), parent_section.d_y + length * math.sin(math.radians(angle)), 0.0) else: # Default to 'abs'-angle to 0 length = get_yaml_length(yaml_sect) angle = 0 xyz = (parent_section.d_x + length * math.cos(math.radians(angle)), parent_section.d_y + length * math.sin(math.radians(angle)), 0.0) # Possible ID's: section_id_tag = (yaml_sect['id'] if yaml_sect.has_key('id') else None) if section_id_tag: check_cstyle_varname(section_id_tag) if section_id_tag in section_id_tags: raise ValueError('Duplicate Section ID: %s' % section_id_tag) if section_id_tag: section_id_tags.append(section_id_tag) # Create the new section: if parent_section: new_section = parent_section.create_distal_section(x=xyz[0], y=xyz[1], z=xyz[2], r=rad, region=rgs[0], idtag=section_id_tag) else: new_section = Section(x=xyz[0], y=xyz[1], z=xyz[2], r=rad, region=None, idtag=section_id_tag) section_dict[None] = new_section # Calculate the angle of the current section: if parent_section: joining_vec = new_section.get_distal_npa3() - parent_section.get_distal_npa3() angle = math.radians(math.atan2(joining_vec[1], joining_vec[0])) section_angles_dict[new_section] = angle #Save the section: section_dict[yaml_id] = new_section # # TODO: THIS IS A HACK! Ensure the dummy node has no attached regions: # section_dict[None].regions = [] assert section_dict[0].region == None if section_dict[0].children == []: raise ValueError("No segments found") morphs = MorphologyTree(name=name, dummysection=section_dict[0], metadata=metadata) if len(morphs) < 1: raise ValueError return morphs
def __init__(self, cellNode): self.cables = SearchableSet() self.cablegroups = SearchableSet() self.segments = SearchableSet() # Read the XML: # Start with the declared Cables: cablesNode = FilterExpectSingleChildrenByTag(cellNode, "cables") # Load the individual cable objects for cableNode in FilterChildrenByTag(cablesNode, "cable"): if cableNode.getAttribute("id") in self.cables.keys("cable_id"): continue cable = NeuroMLCable(cable_id=cableNode.getAttribute("id"), name=cablesNode.getAttribute("name")) self.cables.add(cable) # Does the cable belong to any groups? for group_node in Filter(cableNode.childNodes, isElementWithTag("group")): cablegroupname = get_text(group_node) if not cablegroupname in self.cablegroups.keys("name"): self.cablegroups.add(NeuroMLCableGroup(name=cablegroupname)) self.cablegroups.getitem(name=cablegroupname).add_cable(cable) # Load the CableGroup Objects: for cableGroupNode in Filter(cablesNode.childNodes, isElementWithTag("cablegroup")): # Get, or create, the cable node: cablegroupname = cableGroupNode.getAttribute("name") if not cablegroupname in self.cablegroups.keys("name"): self.cablegroups.add(NeuroMLCableGroup(name=cablegroupname)) grp = self.cablegroups.getitem(name=cablegroupname) # Add the cable segments: for cableNode in Filter(cableGroupNode.childNodes, isElementWithTag("cable")): cableNodeID = cableNode.getAttribute("id") if not cableNodeID in self.cables.keys("cable_id"): assert False cable = self.cables.getitem(cable_id=cableNodeID) grp.add_cable(cable) # Load the Segments Objects: segmentsNode = SeqUtils.filter_expect_single(cellNode.childNodes, isElementWithTag("segments")) for segmentNode in Filter(segmentsNode.childNodes, isElementWithTag("segment")): # Attributes: segment_id = segmentNode.getAttribute("id") parent_id = segmentNode.getAttribute("parent") cable_id = segmentNode.getAttribute("cable") cable = self.cables.getitem(cable_id=cable_id) if cable_id else None # Distal Information: distalNode = FilterExpectSingleChildrenByTag(segmentNode, "distal") d_X, d_Y, d_Z, d_d = ( float(distalNode.getAttribute("x")), float(distalNode.getAttribute("y")), float(distalNode.getAttribute("z")), float(distalNode.getAttribute("diameter")), ) dInfo = (d_X, d_Y, d_Z, d_d) proximalNode = FilterChildrenByTag(segmentNode, "proximal") # Root node: if not parent_id: assert proximalNode proximalNode = SeqUtils.expect_single(proximalNode) p_X, p_Y, p_Z, p_d = ( float(proximalNode.getAttribute("x")), float(proximalNode.getAttribute("y")), float(proximalNode.getAttribute("z")), float(proximalNode.getAttribute("diameter")), ) pInfo = (p_X, p_Y, p_Z, p_d) segment = NeuroMLSegment( segment_id=segment_id, distInfo=dInfo, proxInfo=pInfo, parent=None, cable=cable ) # Child Node: else: # Not the root node, but a proximal node is provided: if proximalNode: pInfo = (p_X, p_Y, p_Z, p_d) # Proximal node and NOT the root: if parent_id: parentNode = self.segments.getitem(segment_id=parent_id) parentDistalInfo = parentNode.distInfo eps = 0.01 # assert fabs(parentDistalInfo[0] - pInfo[0]) < eps # assert fabs(parentDistalInfo[1] - pInfo[1]) < eps # assert fabs(parentDistalInfo[2] - pInfo[2]) < eps # assert fabs(parentDistalInfo[3] - pInfo[3]) < eps # Add the child node: segment = NeuroMLSegment( segment_id=segment_id, distInfo=dInfo, proxInfo=pInfo, parent=None, cable=cable ) # Add the segment to groups? self.segments.add(segment)
def get_trace_by_tagselection(self, ts): import morphforge selector = morphforge.stdimports.TagSelector.from_string(ts) return SeqUtils.filter_expect_single(self.traces, selector)