I have two adjacent matrices that represent two brain structures (cerebellum and cortex):
Dataset:
import networkx as nx
from astropy.io import fits
# Cerebellum
with fits.open('matrix_CEREBELLUM_large.fits') as data:
matrix_cerebellum = pd.DataFrame(data[0].data.byteswap().newbyteorder())
# 1858 rows × 1858 columns
# Cortex
with fits.open('matrix_CORTEX_large.fits') as data:
matrix_cortex = pd.DataFrame(data[0].data.byteswap().newbyteorder())
#1464 rows × 1464 columns
Note: datasets can be downloaded here: brain datasets
Adjacent matrices here are not weighted, and have the usual binary representation, with 1 value for connected nodes and 0 otherwise, like so:
0 1 0 1 0 0 0 0 0 0 0 ...
0 0 0 1 0 0 0 0 0 0 0 ...
0 0 0 0 0 0 0 0 0 0 1 ...
I'm using the library Networkx
to look for community detection in the networks. I could try to do that for each network, individually.
Let's say I need to simulate the real world networks, where a fraction of cortex nodes ( say, 0.01%) projects edges into cerebellum.
I'm wondering how I could implement this simulation considering my community detection goal.
I initially though about creating a bipartite network, but decided instead to use a multilayer network (2 layers, actually) approach.
In this approach, cortex would be network layer 1, cerebellum would be network layer 2, each one with intra-connections already represented in each adjacent matrix.
Now I would add the cortex projections as inter-connections between the two layers.
How do I create these projections and represent the new matrix, knowing that I need to:
Here's a way to do what you want:
nx.convert_matrix.from_pandas_adjacency
nx.disjoint_union
. The nodes of both graphs are basically concatenated onto a single graph (see more here).adj_matrix_full=nx.linalg.graphmatrix.adjacency_matrix(full_g,weight=None)
See full code below for more details:
import networkx as nx
from astropy.io import fits
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
fig=plt.figure(figsize=(20,20))
# Cerebellum
with fits.open('matrix_CEREBELLUM_large.fits') as data:
matrix_cerebellum = pd.DataFrame(data[0].data.byteswap().newbyteorder())
# 1858 rows × 1858 columns
# Cortex
with fits.open('matrix_CORTEX_large.fits') as data:
matrix_cortex = pd.DataFrame(data[0].data.byteswap().newbyteorder())
#1464 rows × 1464 columns
cerebellum_g=nx.convert_matrix.from_pandas_adjacency(matrix_cerebellum) #convert cerebellum adj matrix to nx graph
N_nodes_cer=cerebellum_g.number_of_nodes()
cortex_g=nx.convert_matrix.from_pandas_adjacency(matrix_cortex) #convert matrix adj matrix to nx graph
N_nodes_cort=cortex_g.number_of_nodes()
full_g=nx.algorithms.operators.binary.disjoint_union(cortex_g,cerebellum_g) #concatenate the two graphs
#choose randomly 0.01 cortex nodes to project to cerebellum
p=0.01
N_projs=int(cortex_g.number_of_nodes()*p)
cortex_proj_nodes=np.random.choice(cortex_g.number_of_nodes(), size=N_projs,replace=False)
cerebellum_recipient=np.random.choice(cerebellum_g.number_of_nodes(), size=N_projs,replace=False)
#Add edges
for i in range(N_projs):
full_g.add_edge(list(full_g.nodes)[cortex_proj_nodes[i]],list(full_g.nodes)[N_nodes_cort+cerebellum_recipient[i]])
#Color the nodes based on brain region
color_map = []
for node in full_g:
if node < N_nodes_cort:
color_map.append('tab:blue')
else:
color_map.append('tab:orange')
adj_matrix_full=nx.linalg.graphmatrix.adjacency_matrix(full_g,weight=None) #Compute adj matrix for full graph
pos = nx.circular_layout(full_g)
#Setting up a legend
plt.plot([],[],color='tab:blue',label='Cortex')
plt.plot([],[],color='tab:orange',label='Cerebellum')
#plotting graph
nx.draw(full_g,pos=pos,node_color=color_map)
plt.legend()