I want to plot a directed graph for a group of genes. Let's say some genes are oncogenes, and some are driver genes. Further, the gene-gene interactions are weighted and represented using specific shapes and colours. I am using the following code to draw the directed graph:
import networkx as nx
import matplotlib.pyplot as plt
import numpy as np
# Your weighted adjacency matrix (replace this with your actual matrix)
adjacency_matrix = np.array([
[0, 0.2, 0, 0, 0.4],
[0.0, 0, 0, 0, 0.1],
[0.1, 0, 0, 0.1, 0],
[0, 0, 0.3, 0, 0],
[0.0, 0.0, 0, 0, 0]
])
# Your Katz centrality scores (replace this with your actual scores)
katz_centrality_scores = [0.95, 0.03, 0.65, 0.12, 0.06]
# Relative scaling to range [1,10]
katz_centrality_scores = [9*(i-min(katz_centrality_scores))/(max(katz_centrality_scores) - min(katz_centrality_scores)) + 1 for i in katz_centrality_scores]
# Gene labels (replace with your gene labels)
gene_labels = ["Gene1", "Gene2", "Gene3", "Gene4", "Gene5"]
# Gene types (1 for oncogene, 2 for driver gene)
gene_types = [1, 2, 1, 2, 2]
# Create a graph
G = nx.DiGraph()
# Add nodes with attributes
for i in range(len(gene_labels)):
node_color = 'red' if gene_types[i] == 1 else 'green'
node_shape = 'v' if gene_types[i] == 1 else 's'
node_size = katz_centrality_scores[i]*80 # Adjust the scaling factor as needed
G.add_node(gene_labels[i], color=node_color, shape=node_shape, size=node_size)
node_colors = [v['color'] for v in dict(G.nodes(data=True)).values()]
# Add edges from the adjacency matrix
for i in range(len(gene_labels)):
for j in range(len(gene_labels)):
if adjacency_matrix[i][j] > 0:
G.add_edge(gene_labels[i], gene_labels[j], weight=katz_centrality_scores[i], color=node_colors[i])
# Extract node attributes
node_colors = [G.nodes[n]['color'] for n in G.nodes()]
node_shapes = [G.nodes[n]['shape'] for n in G.nodes()]
node_sizes = [G.nodes[n]['size'] for n in G.nodes()]
edge_colors = [G[u][v]['color'] for u, v in G.edges()]
# Extract edge weights
edge_weights = [G[u][v]['weight'] for u, v in G.edges()]
# Draw the graph
pos = nx.spring_layout(G, seed=42) # You can use other layout algorithms
curved_edges = [edge for edge in G.edges() if reversed(edge) in G.edges()]
straight_edges = [edge for edge in G.edges() if not reversed(edge) in G.edges()]
nx.draw(G,
pos,
node_color=node_colors,
node_size=node_sizes,
edge_color=edge_colors,
# node_shape=node_shapes,
width=edge_weights,
with_labels=True,
edgelist=straight_edges,
arrowsize=25,
arrowstyle='->')
nx.draw(G,
pos,
node_color=node_colors,
node_size=node_sizes,
edge_color=edge_colors,
# node_shape=node_shapes,
width=edge_weights,
with_labels=True,
edgelist=curved_edges,
connectionstyle='arc3, rad = 0.25',
arrowsize=25,
arrowstyle='->')
# Create a legend
red_patch = plt.Line2D([0], [0], marker='v', color='red', label='Oncogene', markersize=10, linestyle='None')
green_patch = plt.Line2D([0], [0], marker='s', color='green', label='Driver Gene', markersize=10, linestyle='None')
plt.legend(handles=[red_patch, green_patch], loc='upper right')
# Show the plot
plt.title('Gene Network')
plt.axis('off') # Turn off axis labels and ticks
plt.show()
After running the above code, the graph edge attribute is as follows:
list(G.edges(data=True))
[('Gene1', 'Gene2', {'weight': 10.0, 'color': 'red'}),
('Gene1', 'Gene5', {'weight': 10.0, 'color': 'red'}),
('Gene2', 'Gene5', {'weight': 1.0, 'color': 'green'}),
('Gene3', 'Gene1', {'weight': 7.065217391304349, 'color': 'red'}),
('Gene3', 'Gene4', {'weight': 7.065217391304349, 'color': 'red'}),
('Gene4', 'Gene3', {'weight': 1.8804347826086958, 'color': 'green'})]
`
The above code is generating the following graph (which is not correct):
Please note that the image is not according to the node and edge criteria mentioned in the code. For example,
The edge colour and weight for an edge for node pair (Gene3, Gene4) and (Gene4, Gene3) are (red,7.06) and (green,1.88). But in the generated graph, the edge between (Gene4, Gene3) the colour is shown as red (not green), and the edge thickness is the same as (Gene3, Gene4) (which is wrong).
When I uncomment the
node_shapeargument innx.draw, I get the following error:ValueError: Unrecognized marker style ['v', 's', 'v', 's', 's']. I am not able to figure out how to give the node shape for each gene category (e.g., triangle for oncogene and square for driver gene)
Can anyone suggest to me what I am missing in the above code?
Thanks.

You have two different lists here and call draw twice, once for each. However on each call you pass the same list of colors
You need two lists of colors, one for straight edges and one for curved edges so that the draw method will get the correct color for each edge.