Reproducing Table 2
The counts for EMT6N can be directly computed using the state_count script. This can be done for any network, irrespective of whether it is balanced or not.
To follow the steps as closely as the manuscript, follow this tutorial.
Loading the topology
The topo file for the 6 node EMT network is provided in Inputs. To maintain consistency with the manuscript, the order has been set manually.
topo = '../../Inputs/Topo/EMT6N.topo'
adj = mn.utils.topo_to_adj(topo)
# Arrange by order
order = ['TGFbeta', 'miR200', 'SNAI1', 'OVOL2', 'ZEB1', 'miR34']
adj = adj.loc[order,order]
G = nx.from_pandas_adjacency(adj, create_using=nx.DiGraph)
adj
TGFbeta miR200 SNAI1 OVOL2 ZEB1 miR34
TGFbeta 0 0 1 0 0 0
miR200 -1 0 0 0 -1 0
SNAI1 0 -1 0 0 1 -1
OVOL2 -1 0 0 0 -1 0
ZEB1 0 -1 0 -1 0 -1
miR34 0 0 -1 0 0 0
Checking if the network is balanced
The presence of any negative loops in the network can be checked.
for cycle in nx.simple_cycles(G):
weight = 1
for i in range(len(cycle)):
u = cycle[i]
v = cycle[(i + 1) % len(cycle)]
weight *= G[u][v]['weight']
if weight < 0:
print('Network contains a negative loop')
break
else:
print('Network does not contain negative loops')
This network is also strongly connected making it a balanced network.
Conversion to positive network
Define the transformation: $$\alpha = (TGF\beta, \neg miR200, SNAI1, \neg OVOL2, ZEB1, \neg miR34a) $$
Applying the transformation $\alpha$, changes the sign of edges where the sources and targets are these nodes. This gives a positive network.
TGFbeta miR200 SNAI1 OVOL2 ZEB1 miR34
TGFbeta 0 0 1 0 0 0
miR200 1 0 0 0 1 0
SNAI1 0 1 0 0 1 1
OVOL2 1 0 0 0 1 0
ZEB1 0 1 0 1 0 1
miR34 0 0 1 0 0 0
Enumeration for positive network
The functions defined in the Python library can give the counts of MBMs, as well as the lattice representation (in terms of Us and Ls) for the positive network.
TGFbeta miR200 SNAI1 OVOL2 ZEB1 miR34 Total
000000 5 5 5 2 19 5 23750
010000 3 1 5 2 14 5 2100
100000 1 5 3 2 19 5 2850
110000 3 1 3 2 14 5 1260
001000 5 3 1 2 14 3 1260
... ... ... ... ... ... ... ...
110111 5 3 1 2 14 3 1260
001111 3 1 3 2 14 5 1260
011111 1 5 3 2 19 5 2850
101111 3 1 5 2 14 5 2100
111111 5 5 5 2 19 5 23750
[64 rows x 7 columns]
TGFbeta miR200 SNAI1 OVOL2 ZEB1 miR34
000000 L(00) L(00) L(00) L(0) L(000) L(00)
010000 L(10) U(00) L(00) L(0) L(100) L(00)
100000 U(00) L(00) L(10) L(0) L(000) L(00)
110000 U(10) U(00) L(10) L(0) L(100) L(00)
001000 L(00) L(10) U(00) L(0) L(010) L(10)
... ... ... ... ... ... ...
110111 U(11) U(01) L(11) U(1) U(101) U(01)
001111 L(01) L(11) U(01) U(1) U(011) U(11)
011111 L(11) U(11) U(01) U(1) U(111) U(11)
101111 U(01) L(11) U(11) U(1) U(011) U(11)
111111 U(11) U(11) U(11) U(1) U(111) U(11)
[64 rows x 6 columns]
Top 12 states table
The exact Table 2 as given in the manuscript, can be obtained by subsetting the the top 12 from the merged list.
df = pd.merge(param_set, counts['Total'], left_index=True, right_index=True)
state = df.index.map(tuple).to_frame(index=False,name=order).astype(int)
state.index = df.index
state.loc[:, alpha] = 1 - state.loc[:, alpha]
df['EMT state'] = state.astype(str).sum(axis=1)
df.sort_values('Total',ascending=False)[:12]
TGFbeta miR200 SNAI1 OVOL2 ZEB1 miR34 Total EMT state
000000 L(00) L(00) L(00) L(0) L(000) L(00) 23750 010101
111111 U(11) U(11) U(11) U(1) U(111) U(11) 23750 101010
111011 U(10) U(11) U(11) L(1) U(110) U(11) 5250 101110
000100 L(01) L(00) L(00) U(0) L(001) L(00) 5250 010001
110110 U(11) U(01) L(10) U(1) U(101) L(01) 3780 100011
001001 L(00) L(10) U(01) L(0) L(010) U(10) 3780 011100
011011 L(10) U(11) U(01) L(1) U(110) U(11) 3150 001110
100100 U(01) L(00) L(10) U(0) L(001) L(00) 3150 110001
100000 U(00) L(00) L(10) L(0) L(000) L(00) 2850 110101
011111 L(11) U(11) U(01) U(1) U(111) U(11) 2850 001010
111110 U(11) U(11) U(10) U(1) U(111) L(11) 2850 101011
000001 L(00) L(00) L(01) L(0) L(000) U(00) 2850 010100