# Information Architecture¶

The neet.information provides a collection of functions which compute various information measures over the dynamics of discrete-state network models. Each measure computes a time series of a desired length from each initial state of the network and uses the time series to populate probability distributions over the state transitions of each node. From there any number of information or entropy measures may be applied. All of this is bookkeeping is taken care of by the function; all you have to do is provide a network and any necessary parameters for the calculation

Example (Active Information for Fission Yeast)

>>> active_information(s_pombe, k=5, timesteps=20)
array([0.        , 0.4083436 , 0.62956679, 0.62956679, 0.37915718,
0.40046165, 0.67019615, 0.67019615, 0.39189127])


The core information-theoretic computations are supported by the PyInform package.

## API Documentation¶

The neet.information module is broken into two parts: Information Measures and the Architecture Class.

The Information Measures are a collection of module-level functions which independently compute a variety of information measures over a network of interest:

However, since they do not share any data between them, if you plan to compute many different measures, it is much more efficient to cache the computed time series. This is done by the Architecture class which provides all of the same measures, only computes the time series once.

### Information Measures¶

neet.information.active_information(net, k, timesteps, size=None, local=False)[source]

Compute the active information storage for each node in a network.

>>> active_information(s_pombe, k=5, timesteps=20)
array([0.        , 0.4083436 , 0.62956679, 0.62956679, 0.37915718,
0.40046165, 0.67019615, 0.67019615, 0.39189127])
>>> lais = active_information(s_pombe, k=5, timesteps=20, local=True)
>>> lais[1]
array([[0.13079175, 0.13079175, 0.13079175, ..., 0.13079175, 0.13079175,
0.13079175],
[0.13079175, 0.13079175, 0.13079175, ..., 0.13079175, 0.13079175,
0.13079175],
[0.13079175, 0.13079175, 0.13079175, ..., 0.13079175, 0.13079175,
0.13079175],
...,
[0.13079175, 0.13079175, 0.13079175, ..., 0.13079175, 0.13079175,
0.13079175],
[0.13079175, 0.13079175, 0.13079175, ..., 0.13079175, 0.13079175,
0.13079175],
[0.13079175, 0.13079175, 0.13079175, ..., 0.13079175, 0.13079175,
0.13079175]])
>>> np.mean(lais[1])
0.4083435963963132

Parameters: net – a NEET network k – the history length timesteps – the number of timesteps to evaluate the network size – the size of variable-sized network (or None) local – whether or not to compute the local active information a numpy array of active information values
neet.information.entropy_rate(net, k, timesteps, size=None, local=False)[source]

Compute the entropy rate for each node in a network.

>>> entropy_rate(s_pombe, k=5, timesteps=20)
array([0.        , 0.01691208, 0.07280268, 0.07280268, 0.05841994,
0.02479402, 0.03217332, 0.03217332, 0.08966941])
>>> ler = entropy_rate(s_pombe, k=5, timesteps=20, local=True)
>>> ler[4]
array([[0.        , 0.        , 0.        , ..., 0.00507099, 0.00507099,
0.00507099],
[0.        , 0.        , 0.        , ..., 0.00507099, 0.00507099,
0.00507099],
[0.        , 0.        , 0.        , ..., 0.00507099, 0.00507099,
0.00507099],
...,
[0.        , 0.29604946, 0.00507099, ..., 0.00507099, 0.00507099,
0.00507099],
[0.        , 0.29604946, 0.00507099, ..., 0.00507099, 0.00507099,
0.00507099],
[0.        , 0.29604946, 0.00507099, ..., 0.00507099, 0.00507099,
0.00507099]])
>>> np.mean(ler[4])
0.0584199434476326

Parameters: net – a NEET network k – the history length timesteps – the number of timesteps to evaluate the network size – the size of variable-sized network (or None) local – whether or not to compute the local entropy rate a numpy array of entropy rate values
neet.information.transfer_entropy(net, k, timesteps, size=None, local=False)[source]

Compute the transfer entropy matrix for a network.

>>> transfer_entropy(s_pombe, k=5, timesteps=20)
array([[ 0.00000000e+00,  0.00000000e+00, -1.11022302e-16,
-1.11022302e-16,  0.00000000e+00,  0.00000000e+00,
-1.11022302e-16,  0.00000000e+00,  0.00000000e+00],
[-4.44089210e-16, -4.44089210e-16, -4.44089210e-16,
-4.44089210e-16,  1.69120759e-02, -4.44089210e-16,
-4.44089210e-16, -4.44089210e-16, -4.44089210e-16],
[ 4.44089210e-16,  5.13704599e-02,  4.44089210e-16,
1.22248438e-02,  1.99473023e-02,  5.13704599e-02,
6.03879253e-03,  6.03879253e-03,  7.28026801e-02],
[ 4.44089210e-16,  5.13704599e-02,  1.22248438e-02,
4.44089210e-16,  1.99473023e-02,  5.13704599e-02,
6.03879253e-03,  6.03879253e-03,  7.28026801e-02],
[ 0.00000000e+00,  5.84199434e-02,  4.76020591e-02,
4.76020591e-02,  0.00000000e+00,  5.84199434e-02,
4.76020591e-02,  4.76020591e-02,  0.00000000e+00],
[ 2.22044605e-16,  2.22044605e-16,  2.47940243e-02,
2.47940243e-02,  2.22044605e-16,  2.22044605e-16,
2.47940243e-02,  2.47940243e-02,  2.22044605e-16],
[-4.44089210e-16,  1.66898258e-02,  4.52634832e-03,
4.52634832e-03,  1.19161772e-02,  1.66898258e-02,
-4.44089210e-16,  2.98276692e-03,  3.21733224e-02],
[-4.44089210e-16,  1.66898258e-02,  4.52634832e-03,
4.52634832e-03,  1.19161772e-02,  1.66898258e-02,
2.98276692e-03, -4.44089210e-16,  3.21733224e-02],
[-4.44089210e-16,  6.03036989e-02,  4.82889077e-02,
4.82889077e-02,  8.96694146e-02,  6.03036989e-02,
4.89270931e-02,  4.89270931e-02, -4.44089210e-16]])

>>> lte = transfer_entropy(s_pombe, k=5, timesteps=20, local=True)
>>> lte[4,3]
array([[0.        , 0.        , 0.        , ..., 0.00507099, 0.00507099,
0.00507099],
[0.        , 0.        , 0.        , ..., 0.00507099, 0.00507099,
0.00507099],
[0.        , 0.        , 0.        , ..., 0.00507099, 0.00507099,
0.00507099],
...,
[0.        , 0.29604946, 0.00507099, ..., 0.00507099, 0.00507099,
0.00507099],
[0.        , 0.29604946, 0.00507099, ..., 0.00507099, 0.00507099,
0.00507099],
[0.        , 0.29604946, 0.00507099, ..., 0.00507099, 0.00507099,
0.00507099]])
>>> np.mean(lte[4,3])
0.047602059103704124

Parameters: net – a NEET network k – the history length timesteps – the number of timesteps to evaluate the network size – the size of variable-sized network (or None) local – whether or not to compute the local transfer entropy a numpy matrix of transfer entropy values
neet.information.mutual_information(net, timesteps, size=None, local=False)[source]

Compute the mutual information matrix for a network.

>>> mutual_information(s_pombe, timesteps=20)
array([[0.16232618, 0.01374672, 0.00428548, 0.00428548, 0.01340937,
0.01586238, 0.00516987, 0.00516987, 0.01102766],
[0.01374672, 0.56660996, 0.00745714, 0.00745714, 0.00639113,
0.32790848, 0.0067609 , 0.0067609 , 0.00468342],
[0.00428548, 0.00745714, 0.83837294, 0.475582  , 0.21157695,
0.00432855, 0.4590254 , 0.4590254 , 0.12755745],
[0.00428548, 0.00745714, 0.475582  , 0.83837294, 0.21157695,
0.00432855, 0.4590254 , 0.4590254 , 0.12755745],
[0.01340937, 0.00639113, 0.21157695, 0.21157695, 0.57459066,
0.00703145, 0.17560769, 0.17560769, 0.01233356],
[0.01586238, 0.32790848, 0.00432855, 0.00432855, 0.00703145,
0.51905053, 0.00621124, 0.00621124, 0.00260667],
[0.00516987, 0.0067609 , 0.4590254 , 0.4590254 , 0.17560769,
0.00621124, 0.80831657, 0.49349527, 0.10390475],
[0.00516987, 0.0067609 , 0.4590254 , 0.4590254 , 0.17560769,
0.00621124, 0.49349527, 0.80831657, 0.10390475],
[0.01102766, 0.00468342, 0.12755745, 0.12755745, 0.01233356,
0.00260667, 0.10390475, 0.10390475, 0.63423835]])
>>> lmi = mutual_information(s_pombe, timesteps=20, local=True)
>>> lmi[4,3]
array([[-0.67489772, -0.67489772, -0.67489772, ...,  0.18484073,
0.18484073,  0.18484073],
[-0.67489772, -0.67489772, -0.67489772, ...,  0.18484073,
0.18484073,  0.18484073],
[-0.67489772, -0.67489772, -0.67489772, ...,  0.18484073,
0.18484073,  0.18484073],
...,
[-2.89794147,  1.7513014 ,  0.18484073, ...,  0.18484073,
0.18484073,  0.18484073],
[-2.89794147,  1.7513014 ,  0.18484073, ...,  0.18484073,
0.18484073,  0.18484073],
[-2.89794147,  1.7513014 ,  0.18484073, ...,  0.18484073,
0.18484073,  0.18484073]])
>>> np.mean(lmi[4,3])
0.21157695279993294

Parameters: net – a NEET network k – the history length timesteps – the number of timesteps to evaluate the network size – the size of variable-sized network (or None) local – whether or not to compute the local mutual information a numpy matrix of mutual information values

### Architecture Class¶

class neet.information.Architecture(net, k, timesteps, size=None)[source]

A class to represent the k-history informational architecture of a network.

Note

The class:Architecture computes the average information measures a bit differently than the associated module-level functions. Specifically, it first computes the local measures and then averages them; this leads different numerical results on account of the subtlties of floating-point mathematics. However, they will always be “close”. In particular

>>> arch = Architecture(s_pombe, k=5, timesteps=20)
>>> function = transfer_entropy(s_pombe, k=5, timesteps=20)
>>> method = arch.transfer_entropy()
>>> np.testing.assert_almost_equal(method, function)

__init__(net, k, timesteps, size=None)[source]

Initialize the architecture given a network and enough information to compute a time series.

During initialization the following measures are computed and cached: * Local and Average Active Information Storage * Local and Average Entropy Rate * Local and Average Transfer Entropy * Local and Average Mutual Information

>>> arch = Architecture(s_pombe, k=5, timesteps=20)
>>> arch.active_information()
array([0.        , 0.4083436 , 0.62956679, 0.62956679, 0.37915718,
0.40046165, 0.67019615, 0.67019615, 0.39189127])

Parameters: net – a NEET network k – the history length timesteps – the number of timesteps to evaluate the network size – the size of variable-sized network (or None)
active_information(local=False)[source]

Get the local or average active information

>>> arch = Architecture(s_pombe, k=5, timesteps=20)
>>> arch.active_information()
array([0.        , 0.4083436 , 0.62956679, 0.62956679, 0.37915718,
0.40046165, 0.67019615, 0.67019615, 0.39189127])
>>> lais = arch.active_information(local=True)
>>> lais[1]
array([[0.13079175, 0.13079175, 0.13079175, ..., 0.13079175, 0.13079175,
0.13079175],
[0.13079175, 0.13079175, 0.13079175, ..., 0.13079175, 0.13079175,
0.13079175],
[0.13079175, 0.13079175, 0.13079175, ..., 0.13079175, 0.13079175,
0.13079175],
...,
[0.13079175, 0.13079175, 0.13079175, ..., 0.13079175, 0.13079175,
0.13079175],
[0.13079175, 0.13079175, 0.13079175, ..., 0.13079175, 0.13079175,
0.13079175],
[0.13079175, 0.13079175, 0.13079175, ..., 0.13079175, 0.13079175,
0.13079175]])
>>> np.mean(lais[1])
0.4083435963963132

Parameters: local (bool) – whether to return local (True) or global active information a numpy array containing the (local) active information
entropy_rate(local=False)[source]

Get the local or average entropy rate

>>> arch = Architecture(s_pombe, k=5, timesteps=20)
>>> arch.entropy_rate()
array([0.        , 0.01691208, 0.07280268, 0.07280268, 0.05841994,
0.02479402, 0.03217332, 0.03217332, 0.08966941])
>>> ler = arch.entropy_rate(local=True)
>>> ler[4]
array([[0.        , 0.        , 0.        , ..., 0.00507099, 0.00507099,
0.00507099],
[0.        , 0.        , 0.        , ..., 0.00507099, 0.00507099,
0.00507099],
[0.        , 0.        , 0.        , ..., 0.00507099, 0.00507099,
0.00507099],
...,
[0.        , 0.29604946, 0.00507099, ..., 0.00507099, 0.00507099,
0.00507099],
[0.        , 0.29604946, 0.00507099, ..., 0.00507099, 0.00507099,
0.00507099],
[0.        , 0.29604946, 0.00507099, ..., 0.00507099, 0.00507099,
0.00507099]])

Parameters: local (bool) – whether to return local (True) or global entropy rate a numpy array containing the (local) entropy rate
mutual_information(local=False)[source]

Get the local or average mutual information

>>> arch = Architecture(s_pombe, k=5, timesteps=20)
>>> arch.mutual_information()
array([[0.16232618, 0.01374672, 0.00428548, 0.00428548, 0.01340937,
0.01586238, 0.00516987, 0.00516987, 0.01102766],
[0.01374672, 0.56660996, 0.00745714, 0.00745714, 0.00639113,
0.32790848, 0.0067609 , 0.0067609 , 0.00468342],
[0.00428548, 0.00745714, 0.83837294, 0.475582  , 0.21157695,
0.00432855, 0.4590254 , 0.4590254 , 0.12755745],
[0.00428548, 0.00745714, 0.475582  , 0.83837294, 0.21157695,
0.00432855, 0.4590254 , 0.4590254 , 0.12755745],
[0.01340937, 0.00639113, 0.21157695, 0.21157695, 0.57459066,
0.00703145, 0.17560769, 0.17560769, 0.01233356],
[0.01586238, 0.32790848, 0.00432855, 0.00432855, 0.00703145,
0.51905053, 0.00621124, 0.00621124, 0.00260667],
[0.00516987, 0.0067609 , 0.4590254 , 0.4590254 , 0.17560769,
0.00621124, 0.80831657, 0.49349527, 0.10390475],
[0.00516987, 0.0067609 , 0.4590254 , 0.4590254 , 0.17560769,
0.00621124, 0.49349527, 0.80831657, 0.10390475],
[0.01102766, 0.00468342, 0.12755745, 0.12755745, 0.01233356,
0.00260667, 0.10390475, 0.10390475, 0.63423835]])
>>> lmi = arch.mutual_information(local=True)
>>> lmi[4,3]
array([[-0.67489772, -0.67489772, -0.67489772, ...,  0.18484073,
0.18484073,  0.18484073],
[-0.67489772, -0.67489772, -0.67489772, ...,  0.18484073,
0.18484073,  0.18484073],
[-0.67489772, -0.67489772, -0.67489772, ...,  0.18484073,
0.18484073,  0.18484073],
...,
[-2.89794147,  1.7513014 ,  0.18484073, ...,  0.18484073,
0.18484073,  0.18484073],
[-2.89794147,  1.7513014 ,  0.18484073, ...,  0.18484073,
0.18484073,  0.18484073],
[-2.89794147,  1.7513014 ,  0.18484073, ...,  0.18484073,
0.18484073,  0.18484073]])

Parameters: local (bool) – whether to return local (True) or global mutual information a numpy array containing the (local) mutual information
transfer_entropy(local=False)[source]

Get the local or average transfer entropy

>>> arch = Architecture(s_pombe, k=5, timesteps=20)
>>> arch.transfer_entropy()
array([[ 0.00000000e+00,  3.37457926e-18, -2.18195687e-18,
-2.18195687e-18, -5.39390581e-18,  3.37457926e-18,
5.10930274e-18,  5.10930274e-18,  1.80248611e-18],
[-3.25260652e-18, -3.25260652e-18, -3.05745013e-17,
-3.05745013e-17,  1.69120759e-02, -3.25260652e-18,
-3.25260652e-18, -3.25260652e-18, -3.25260652e-18],
[-4.20670443e-17,  5.13704599e-02, -4.20670443e-17,
1.22248438e-02,  1.99473023e-02,  5.13704599e-02,
6.03879253e-03,  6.03879253e-03,  7.28026801e-02],
[-4.20670443e-17,  5.13704599e-02,  1.22248438e-02,
-4.20670443e-17,  1.99473023e-02,  5.13704599e-02,
6.03879253e-03,  6.03879253e-03,  7.28026801e-02],
[-1.09531524e-16,  5.84199434e-02,  4.76020591e-02,
4.76020591e-02, -1.09531524e-16,  5.84199434e-02,
4.76020591e-02,  4.76020591e-02, -1.09531524e-16],
[-5.20417043e-18, -5.20417043e-18,  2.47940243e-02,
2.47940243e-02, -5.20417043e-18, -5.20417043e-18,
2.47940243e-02,  2.47940243e-02, -5.20417043e-18],
[ 3.08997619e-17,  1.66898258e-02,  4.52634832e-03,
4.52634832e-03,  1.19161772e-02,  1.66898258e-02,
3.08997619e-17,  2.98276692e-03,  3.21733224e-02],
[ 3.08997619e-17,  1.66898258e-02,  4.52634832e-03,
4.52634832e-03,  1.19161772e-02,  1.66898258e-02,
2.98276692e-03,  3.08997619e-17,  3.21733224e-02],
[ 1.37693676e-17,  6.03036989e-02,  4.82889077e-02,
4.82889077e-02,  8.96694146e-02,  6.03036989e-02,
4.89270931e-02,  4.89270931e-02,  1.37693676e-17]])

>>> lte = arch.transfer_entropy(local=True)
>>> lte[4,3]
array([[0.        , 0.        , 0.        , ..., 0.00507099, 0.00507099,
0.00507099],
[0.        , 0.        , 0.        , ..., 0.00507099, 0.00507099,
0.00507099],
[0.        , 0.        , 0.        , ..., 0.00507099, 0.00507099,
0.00507099],
...,
[0.        , 0.29604946, 0.00507099, ..., 0.00507099, 0.00507099,
0.00507099],
[0.        , 0.29604946, 0.00507099, ..., 0.00507099, 0.00507099,
0.00507099],
[0.        , 0.29604946, 0.00507099, ..., 0.00507099, 0.00507099,
0.00507099]])

Parameters: local (bool) – whether to return local (True) or global transfer entropy a numpy array containing the (local) transfer entropy