Interactive Brain Graph Visualization(4): From fMRI to Json file

Interactive Brain Graph Visualization(4): From fMRI to Json file

The code of this visualization is available on my github: https://github.com/astro1860/visualization_project/tree/master/brain_fisheye  and you can see how to generate the json file by running the ipynb file.

Getting data from fMRI

The raw data used for visualization is obtained from fMRI(functional magnetic resonance imaging), using MRI with diffusion tensor imaging and tractography techniques. As the fMRI data can indicate activity of different brain areas, these data can be used to represent the brain and its connections as a graph. In the visualization, each node is a brain region of the Desikan-Killiany Atlas. Each link illustrates the connection between two brain regions. The data is read from .mat file and loaded to python with

D = sp.io.loadmat('/PH0148_allscales_allnodes_with_labels.mat')

The data we interested in are adjacency matrix of brain connections and the labels(names) of the brain areas. The adjacency matrix is the binary matrix, with “1″ representing  connection existed and “0″ meaning no connections. We analyzed only with these two data sets.

adj_mat

Add node and link attributes

1. Add names as node attributes

As the name labels have prefix with “lh”& “rh” as left and right hemisphere information which are unnecessary for visualizations, we deleted the prefix and assign group with different hemisphere with the following code:

Brain1labs={}
Labelsshort={}
group={}
for i in range(len(Brain_adj)):
Brain1labs[i]=Brain1labels[0][i][0]
if Brain1labs[i][0:2]=='lh':
group[i]=1
Labelsshort[i]=Brain1labs[i][3:]
elif Brain1labs[i][0:2]=='rh':
group[i]=2
Labelsshort[i]=Brain1labs[i][3:]
else:
group[i]=0
Labelsshort[i]=Brain1labs[i]

Meanwhile, we would like to the add the names as node attributes in visualization. With networkx, we did this function:

def add_group_attributes(graph):
print "adding groups to the graph..."
g = graph
label_group = group
nx.set_node_attributes(g,'group',label_group)
return g,label_group

2. Add degrees centrality as node attributes

As explained before, the degree of a node is the number of edges it adjacent to and node with more degrees have more connections. While degree centrality is merely one step more than degree, representing the fraction of nodes it is connected to. We added the degree centrality as node attributes with this function:

 def calculate_degree_centrality(graph):
print "Calculating Degree Centrality..."
g = graph
num_nodes = nx.number_of_nodes(g)
dc = nx.degree_centrality(g)
nx.set_node_attributes(g,'degree_cent',dc)
degcent_sorted = sorted(dc.items(), key=itemgetter(1), reverse=True)
for key,value in degcent_sorted[0:num_nodes-1]:
print "Highest degree Centrality:", key, value
return graph, dc

Noted that we also did with this function a ranking of degree centrality from the highest to the lowest, make it convenient in further visualizations.

3. Add eigenvector as node attributes

In blog post “Interactive Brain Visualization(2): simple visualizations with barbell graph“, we have introduced an important concept “eigenvector” and analyzed it mathematically.

We calculate the eigenvector centrality with the following steps:
1. Calculate the eigendecomposition of the pairwise adjacency matrix of the graph.
2. Select the eigenvector associated with largest eigenvalue.
3. Element i in the eigenvector gives the centrality of the i-th node.

The networkx package provides eigenvector_centrality to calculate the values. https://networkx.github.io/documentation/latest/reference/generated/networkx.algorithms.centrality.eigenvector_centrality.html#networkx.algorithms.centrality.eigenvector_centrality We calculated eigenvector centrality and performed a ranking from the highest to lowest with the a

 def calculate_eigenvector_centrality(graph):
print "Calculating Eigenvector Centrality..."
g = graph
ec = nx.eigenvector_centrality(g)
nx.set_node_attributes(g,'eigen_cent',ec)
eigen_sorted = sorted(eigen.items(), key=lambda(k,v):(float(v),k), reverse=True)
for key, val in eigen_sorted[0:num_nodes-1]:
print "highest eigenvector centrality nodes:", key, val
return g, ec

4. add x, y coordinates as node attributes

We extracted position of the brain activity areas with x and y coordinates  and saved them in python dictionaries. With two functions: add_coordinates_x_attributes & add_coordinates_y_attributes, we successfully add the position attributes.

def add_coordinates_x_attributes(graph):
print "adding x to the graph..."
g = graph
nx.set_node_attributes(g,'x',xaxis)
return g,xaxis
 def add_coordinates_y_attributes(graph):
print "adding y to the graph..."
g = graph
nx.set_node_attributes(g,'y',yaxis)
return g,yaxis

Create json file

To add those attributes, we need to call the functions:

g, deg = calculate_degree(g)
g, eigen = calculate_eigenvector_centrality(g)
g, label = add_label_attributes(g)
g, group = add_group_attributes(g)
g,x = add_coordinates_x_attributes(g)
g,y = add_coordinates_y_attributes(g)

At this stage, we have finished adding nodes attributes. Let’s see what are the attributes of random node, saying node[13].

 g.node[20]
{'degree': 13,
'degree_cent': 0.15853658536585366,
'eigen_cent': 0.059968386885244925,
'name': u'cuneus',
'x': 6.50724406627854,
'y': -76.454365427675796}

We saved these information to a position_graph.json file using the following function.

 def save_to_jsonfile(filename, graph):
g = graph
g_json = json_graph.node_link_data(g)
json.dump(g_json, open(filename,'w'))
 import json
save_to_jsonfile("position_graph.json", g)

We will make use of the json file with a powerful tool: d3.js and create a series of interactive graphs.

 

 

 

 

Leave a Reply