def add_network_from_matrix(self, name, matrix, like_network = None, metadata = None, \ directed = False, hierarchical = False, hypergraph = False): """ Add a network to the cfile based on the given connectivity matrix and an already existing other network with node and surface container information. Parameters ---------- name : String Name of the newly added network matrix : NxN array A NxN Numpy array with the values for the edges. N must be the same as len(like_network.graph.nodes()). The first row of the matrix corresponds to the `NetworkX` node with id 'n1' like_network : `INetwork` object, optional Used to copy graph node information and surface containers metadata : Dict, optional A dictionary of metadata directed : bool, optional Is the network directed? hierarchical : bool, optional Is the network hierarchical? (default: '0') Not implemented yet. hypergraph : bool, optional Is the network a hypergraph? (default: '0') Not implemented yet. Returns ------- networkid : int The index in the list of networks in the cfile Note ---- If you use this function only with name and matrix, a spring-force layout algorithm is applied to define the node positions. This may take some time. You can also use the `add_network_from_matrix_pos` and define the node positions by yourself. """ from cviewer.plugins.cff.network import Network create_graph_info = False if like_network is None: create_graph_info = True else: # matrix has N rows and columns which is equal to the number of nodes assert matrix.shape[0] == matrix.shape[1] == len(like_network.graph.nodes()) # add graph import networkx as nx test_G = nx.from_numpy_matrix(matrix) # relabeling function addn = lambda nmod:'n'+str(nmod+1) # relabel graph test_G_corrected = nx.relabel_nodes(test_G, addn) nodes_ids = test_G_corrected.nodes() # create node positions with springlayout if create_graph_info if create_graph_info: npos = nx.spring_layout(test_G_corrected, dim = 3, weighted = True, scale = 100) # add node properties if not create_graph_info: for k, v in like_network.graph.nodes(data=True): if not k in nodes_ids: logger.error('Node id %s is not like_network.graph' % str(k)) # add node properties test_G_corrected.node[k] = v else: for k in test_G_corrected.nodes(): li = str(npos[k].tolist()) li = li.replace('[','') li = li.replace(']','') test_G_corrected.node[k]['dn_position'] = li # create a new network object my_network = Network(name = name, directed = directed, hierarchical = hierarchical, \ hypergraph = hypergraph, graph = test_G_corrected) if not metadata is None: my_network.metadata = metadata # setting the correct parent cfile my_network._parentcfile = self if not create_graph_info: # add surface container from like_network action = ThreadedParsing(self) for surf in like_network.surfaces: if surf.is_atlas: tmp_surfcont = action.process_atlas(surface_node=surf._lxml_node, \ nsprefix=surf._lxml_node_prefix) else: tmp_surfcont = action.process_surface(surface_node=surf._lxml_node, \ nsprefix=surf._lxml_node_prefix) my_network.add_surface_container(tmp_surfcont) # add the created network object to this cfile self.networks.append(my_network) # returns the id of the added network return len(self.networks)-1
def run(self): logger.debug("Start Threaded Parsing of Connectome File ...") import time tic = time.time() # given the full path to meta.xml, create lxml tree and # under the precondition of having a certain file version and generator # one can assume some content of the .cff file # loop over the networks, for each network, the surfaces etc. # in the form of all the attributes (name, srce filename, description etc.) # are given to the created Network instance methods to complete from lxml import etree tree = etree.fromstring(self.metaxmlcontent) nsprefix = "{%s}" % tree.nsmap[None] t = 0 for child in tree.iterchildren(): if child.tag == (nsprefix+'viewer-network'): t = t + 1 if t != self.data.metadata.nr_of_networks: logger.error('The number of networks of networks in meta.xml is not correct!') logger.error('Loading ' + str(t) + ' network(s).') # find all the networks for child in tree.iterchildren(): if child.tag == (nsprefix+'viewer-network'): # load network as string from zip # create temporary StringIO logger.info('-----------------------------------------') logger.info('Now loading ' + child.attrib['src']) logger.info('-----------------------------------------') if child.attrib.has_key('src'): (tmpstring, pickled_graph, local_fname) = self.process_pickle(childnode = child) tmp_network = Network(name = child.attrib['name'], src = tmpstring, pickled_graph = pickled_graph, directed = child.attrib['directed'], hierarchical = child.attrib['hierarchical'], hypergraph = child.attrib['hypergraph']) # store pickled version in connectome file if not tmpstring is None and pickled_graph is None: self.save_pickle_in_cfile(local_fname, networkref = tmp_network) # iterate over children for mchildren in child.iterchildren(): # handling of the metadata # ------------------------- if mchildren.tag == (nsprefix+'network-metadata'): tmp_network.metadata = self.process_metadata(metadata_node = mchildren, nsprefix = nsprefix) # handling of the surfaces # ------------------------ if mchildren.tag == (nsprefix+'network-surface'): # load into surface attr = mchildren.attrib if attr.has_key('src'): # create surface container tmpsurfacecontainer = self.process_surface(surface_node = mchildren, nsprefix = nsprefix) # and add it to the network tmp_network.add_surface_container(tmpsurfacecontainer) # adding a template atlas if stated in the meta.xml if attr.has_key('addatlas'): # create surface container for atlas tmpsurfacecontainer = self.process_atlas(surface_node = mchildren, nsprefix = nsprefix) # and add it to the network tmp_network.add_surface_container(tmpsurfacecontainer) # handling of the volumes # ----------------------- elif mchildren.tag == (nsprefix+'network-volume'): # get the description, is there an easier way with lxml? for desc in mchildren.iterchildren(): if desc.tag == (nsprefix+'description'): mydescr = desc.text attr = mchildren.attrib if attr.has_key('src') and attr.has_key('name'): if not attr.has_key('segmentation'): segm = False else: segm = bool(attr['segmentation']) # create an instance of the Volume class with it tmpvolume = Volume(volumename = attr['name'], \ networkref = tmp_network, \ src = attr['src'], \ description = mydescr, \ segmentation = segm) # add this instance to the list of its network tmp_network.add_volume(tmpvolume) logger.info('Added volume ' + tmpvolume.volumename + \ ' to ' + tmp_network.networkname) # handling of the trackfiles # -------------------------- elif mchildren.tag == (nsprefix+'network-track'): # get the description, is there an easier way with lxml? for desc in mchildren.iterchildren(): if desc.tag == (nsprefix+'description'): mydescr = desc.text attr = mchildren.attrib if attr.has_key('src') and attr.has_key('name'): tmptrack = Trackfile(trkname = attr['name'], tmpfname = attr['src'], \ description = mydescr, networkref = tmp_network) # add this instance to the list of its trackfiles tmp_network.add_trackfile(tmptrack) logger.info('Added trackfile ' + tmptrack.trkname + \ ' to ' + tmp_network.networkname) # setting the correct parent cfile tmp_network._parentcfile = self.data # add the created network object to this cfile self.data.networks.append(tmp_network) toc = time.time() logger.info('Loading Connectome File DONE. (Time: %s)' % str(toc-tic)) logger.info('-----------------------------------------') # setting data loaded flag self.data._data_loaded = True # with do_later, we the change in the statusbar is done in the gui main thread if not self.data._workbenchwin is None: #from enthought.pyface.timer.api import do_later #do_later(self.data._workbenchwin.status_bar_manager.set, message = '') # TEST from enthought.pyface.api import GUI GUI.invoke_later(self.data._workbenchwin.status_bar_manager.set, message = '')
def add_network_from_matrix_with_pos(self, name, matrix, pos, nodeinfo_like_graph = None, \ metadata = None, directed = False, hierarchical = False, hypergraph = False): """ Add a network to the cfil based on the given connectivity matrix and position information. Parameters ---------- name : String Name of the newly added network matrix : NxN array A NxN Numpy array with the values for the edges. N must be the same as len(like_network.graph.nodes()). The first row of the matrix corresponds to the `NetworkX` node with id 'n1' pos : Nx3 array A Nx3 array with the X,Y,Z coordinates for every row (=node) of the matrix nodeinfo_like_graph : `NetworkX` graph Use the node information for the new network metadata : Dict A dictionary of metadata directed : bool Is the network directed? hierarchical : bool Is the network hierarchical? (default: '0') Not implemented yet. hypergraph : bool Is the network a hypergraph? (default: '0') Not implemented yet. Returns ------- networkid : int The index in the list of networks in the cfile """ from cviewer.plugins.cff.network import Network # create a new network object my_network = Network(name = name, directed = directed, hierarchical = hierarchical, \ hypergraph = hypergraph) if not metadata is None: my_network.metadata = metadata # add graph import networkx as nx test_G = nx.from_numpy_matrix(matrix) # relabeling function addn = lambda nmod:'n'+str(nmod+1) # relabel graph test_G_corrected = nx.relabel_nodes(test_G, addn) # update the node position for i in range(matrix.shape[0]): nodeid = addn(i) if not nodeinfo_like_graph is None and nodeinfo_like_graph.has_node(nodeid): test_G_corrected.node[nodeid] = nodeinfo_like_graph.node[nodeid] test_G_corrected.node[nodeid]['dn_position'] = ','.join(list(map(str,pos[i, :]))) my_network.graph = test_G_corrected # setting the correct parent cfile my_network._parentcfile = self # add the created network object to this cfile self.networks.append(my_network) # returns the id of the added network return len(self.networks)-1