def __init__(self, region_number_to_name_bidict=None, name=None, metadata=None): self.region_number_to_name_bidict = region_number_to_name_bidict self._name = name or ObjectLabeller.get_next_unamed_object_name(MorphologyBase) check_cstyle_varname(self._name) self.metadata = (metadata if metadata else {})
def __init__(self, region_number_to_name_bidict=None, name=None, metadata=None): self.region_number_to_name_bidict = region_number_to_name_bidict self._name = name or ObjectLabeller.get_next_unamed_object_name( MorphologyBase) check_cstyle_varname(self._name) self.metadata = (metadata if metadata else {})
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 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