Skip to content

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.

import pandas as pd
import mbnet as mn
import networkx as nx
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')
Network does not contain negative loops

This network is also strongly connected making it a balanced network.

nx.is_strongly_connected(G)
True

Conversion to positive network

Define the transformation: $$\alpha = (TGF\beta, \neg miR200, SNAI1, \neg OVOL2, ZEB1, \neg miR34a) $$

alpha = ['miR200', 'OVOL2', 'miR34']

Applying the transformation $\alpha$, changes the sign of edges where the sources and targets are these nodes. This gives a positive network.

adj.loc[alpha,:] = -adj.loc[alpha,:]
adj.loc[:, alpha] = -adj.loc[:, alpha]
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

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.

counts = mn.tl.n_mbm(adj)
counts
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]
param_set = mn.tl.UL_mbm(adj)
param_set
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