Skip to content

Binder

Parameter exploration with neurolib

In this example, we will draw a bifurcation diagram of a neural mass model that we load using the brain simulation framework neurolib. Please visit the Github repo to learn more about this library or read the gentle introduction to neurolib to learn more about the neuroscience background of neural mass models and whole-brain simulations.

What we will do

We will scan through a 2-dimensional parameter space and record all outputs of the model to a hdf file. We will then load the simulated results from the hdf file and condense the output to a single scalar so we can plot it. Let's get to it!

We'll first start with some unnecessary but useful imports for logging and auto-reloading code. You can skip this block if you don't know what it does.

# change into the root directory of the project
import os
if os.getcwd().split("/")[-1] == "examples":
    os.chdir('..')

%load_ext autoreload
%autoreload 2

import logging
logger = logging.getLogger()
logger.setLevel(logging.INFO)

We have to install matplotlib and neurolib for this example, which we can do using the shell command syntax of jupyter using !pip install matplotlib.

# install matplotlib
!pip install matplotlib
import matplotlib.pyplot as plt
import numpy as np

# a nice color map
plt.rcParams['image.cmap'] = 'plasma'

# install neurolib
!pip install neurolib

from neurolib.models.aln import ALNModel

import mopet

We can now load the ALNModel model from neurolib.

model = ALNModel()
model.params.duration = 1*1000
INFO:root:aln: Model initialized.

Like in other examples, we need to define an evalFunction that mopet can call. The parameters params that are passed to that function are the parameters of the model to run. We load the parameters to the model using a simple dictionary update old_dict.update(new_dict). We then return the output of the model.

def evalFunction(params):
    model.params.update(params)
    model.run()
    return model.outputs

Now we define the parameter ranges to explore (the parameters here are called mue_ext_mean and mui_ext_mean which represent the background input to two neural populations).

# NOTE: These values are low for testing!
explore_params = {"mue_ext_mean" : np.linspace(0, 3, 3),
                  "mui_ext_mean" : np.linspace(0, 3, 3)}
# For a real run, use these values:
# explore_params = {"mue_ext_mean" : np.linspace(0, 3, 31),
#                   "mui_ext_mean" : np.linspace(0, 3, 31)}

# we need this random filename to avoid testing clashes
hdf_filename = f"exploration-{np.random.randint(99999)}.h5"
ex = mopet.Exploration(evalFunction, explore_params, default_params=model.params, hdf_filename=hdf_filename)

Everything is ready and we can now simply run the exploration.

ex.run()
2021-02-15 14:01:44,651   INFO resource_spec.py:212 -- Starting Ray with 3.81 GiB memory available for workers and up to 1.92 GiB for objects. You can adjust these settings with ray.init(memory=<bytes>, object_store_memory=<bytes>).
2021-02-15 14:01:44,913 INFO services.py:1093 -- View the Ray dashboard at localhost:8265
WARNING:root:Could not store dict entry model (type: <class 'str'>)
WARNING:root:Could not store dict entry name (type: <class 'str'>)
WARNING:root:Could not store dict entry description (type: <class 'str'>)
WARNING:root:Could not store dict entry seed (type: <class 'NoneType'>)
INFO:root:Starting 9 jobs.
100%|██████████| 9/9 [00:00<00:00, 41.28it/s]
INFO:root:Runs took 0.2351241111755371 s to submit.
100%|██████████| 9/9 [00:12<00:00,  1.35s/it]
INFO:root:Runs and storage took 12.125471115112305 s to complete.

After the exploration is done, we can load the results into a pandas Dataframe. By adding the argument arrays=True, we also tell mopet to load all simulated output (including arrays!) of the exploration into the Dataframe.

ex.load_results(arrays=True, as_dict=True)
INFO:root:exploration-82611.h5 opened for reading.
INFO:root:Gettings runs of exploration ``exploration_2021_02_15_14H_01M_43S``
100%|██████████| 9/9 [00:00<00:00, 172.57it/s]
INFO:root:Creating new results DataFrame
INFO:root:Aggregating all results ...
100%|██████████| 9/9 [00:00<00:00, 228.06it/s]
INFO:root:exploration-82611.h5 closed.

Because we have used as_dict=True, the outputs of each run are also stored in the results dictionary.

ex.results
{0: {'IA': array([[159.05706529, 158.97753676, 158.89804799, ...,   1.07198599,
            1.07145   ,   1.07091428]]),
  'rates_exc': array([[1.02403238e-07, 1.09923893e-07, 1.16356391e-07, ...,
          3.45083953e-02, 3.45104976e-02, 3.45125989e-02]]),
  'rates_inh': array([[26.40960076, 26.72866115, 26.94340331, ...,  0.03753811,
           0.03753869,  0.03753928]]),
  't': array([1.000e-01, 2.000e-01, 3.000e-01, ..., 9.998e+02, 9.999e+02,
         1.000e+03])},
 1: {'IA': array([[159.05706529, 158.97753676, 158.89804799, ...,   1.07198599,
            1.07145   ,   1.07091428]]),
  'rates_exc': array([[1.02403238e-07, 1.09923893e-07, 1.16356391e-07, ...,
          2.59036677e-10, 2.59036677e-10, 2.59036677e-10]]),
  'rates_inh': array([[26.40960076, 26.72866115, 26.99308004, ...,  5.42581999,
           5.42581999,  5.42581999]]),
  't': array([1.000e-01, 2.000e-01, 3.000e-01, ..., 9.998e+02, 9.999e+02,
         1.000e+03])},
 2: {'IA': array([[159.05706529, 158.97753676, 158.89804799, ...,   1.07198599,
            1.07145   ,   1.07091428]]),
  'rates_exc': array([[1.02403238e-07, 1.09923893e-07, 1.16356391e-07, ...,
          5.75384038e-13, 5.75384038e-13, 5.75384038e-13]]),
  'rates_inh': array([[26.40960076, 26.72866115, 27.04275677, ..., 41.91810664,
          41.91810664, 41.91810664]]),
  't': array([1.000e-01, 2.000e-01, 3.000e-01, ..., 9.998e+02, 9.999e+02,
         1.000e+03])},
 3: {'IA': array([[159.05706529, 158.97753676, 158.89804799, ...,   1.07198599,
            1.07145   ,   1.07091428]]),
  'rates_exc': array([[1.02403238e-07, 1.09923893e-07, 1.16754766e-07, ...,
          3.10924479e+01, 3.10925428e+01, 3.10926376e+01]]),
  'rates_inh': array([[26.40960076, 26.72866115, 26.94340331, ..., 17.85135676,
          17.85138409, 17.8514114 ]]),
  't': array([1.000e-01, 2.000e-01, 3.000e-01, ..., 9.998e+02, 9.999e+02,
         1.000e+03])},
 4: {'IA': array([[159.05706529, 158.97753676, 158.89804799, ...,   1.07198599,
            1.07145   ,   1.07091428]]),
  'rates_exc': array([[1.02403238e-07, 1.09923893e-07, 1.16754766e-07, ...,
          9.87365039e-02, 9.87387537e-02, 9.87410024e-02]]),
  'rates_inh': array([[26.40960076, 26.72866115, 26.99308004, ...,  5.88861088,
           5.88862208,  5.88863328]]),
  't': array([1.000e-01, 2.000e-01, 3.000e-01, ..., 9.998e+02, 9.999e+02,
         1.000e+03])},
 5: {'IA': array([[159.05706529, 158.97753676, 158.89804799, ...,   1.07198599,
            1.07145   ,   1.07091428]]),
  'rates_exc': array([[1.02403238e-07, 1.09923893e-07, 1.16754766e-07, ...,
          5.75384038e-13, 5.75384038e-13, 5.75384038e-13]]),
  'rates_inh': array([[26.40960076, 26.72866115, 27.04275677, ..., 41.91810664,
          41.91810664, 41.91810664]]),
  't': array([1.000e-01, 2.000e-01, 3.000e-01, ..., 9.998e+02, 9.999e+02,
         1.000e+03])},
 6: {'IA': array([[159.05706529, 158.97753676, 158.89804799, ...,   1.07198599,
            1.07145   ,   1.07091428]]),
  'rates_exc': array([[1.02403238e-07, 1.09923893e-07, 1.17153140e-07, ...,
          8.01355471e+01, 8.01356258e+01, 8.01357044e+01]]),
  'rates_inh': array([[26.40960076, 26.72866115, 26.94340331, ..., 24.14426514,
          24.14426982, 24.14427451]]),
  't': array([1.000e-01, 2.000e-01, 3.000e-01, ..., 9.998e+02, 9.999e+02,
         1.000e+03])},
 7: {'IA': array([[159.05706529, 158.97753676, 158.89804799, ...,   1.07198599,
            1.07145   ,   1.07091428]]),
  'rates_exc': array([[1.02403238e-07, 1.09923893e-07, 1.17153140e-07, ...,
          6.66892386e+01, 6.66893269e+01, 6.66894151e+01]]),
  'rates_inh': array([[26.40960076, 26.72866115, 26.99308004, ..., 69.74336334,
          69.74337057, 69.74337779]]),
  't': array([1.000e-01, 2.000e-01, 3.000e-01, ..., 9.998e+02, 9.999e+02,
         1.000e+03])},
 8: {'IA': array([[159.05706529, 158.97753676, 158.89804799, ...,   1.07198599,
            1.07145   ,   1.07091428]]),
  'rates_exc': array([[1.02403238e-07, 1.09923893e-07, 1.17153140e-07, ...,
          6.33525384e+01, 6.33526295e+01, 6.33527206e+01]]),
  'rates_inh': array([[ 26.40960076,  26.72866115,  27.04275677, ..., 110.44781739,
          110.44782441, 110.44783143]]),
  't': array([1.000e-01, 2.000e-01, 3.000e-01, ..., 9.998e+02, 9.999e+02,
         1.000e+03])}}

Reducing the results

As you can see, the results above are time series. For each simulation, we've got multiple arrays. We would like to visualize the results somehow. However, it can be quite challenging to plot many time series in a single figure and still understand what's happening. Therefore, to reduce the dimensionality of the data to a single scalar number per simulation, we will loop through the entire results Dataframe, grab the time series called rates_exc and simply compute its maximum after a transient time of t>500 time steps. We then store this number in the Dataframe and simply call the new column result.

ex.df["result"] = None
for r in ex.df.index:
    t = ex.results[r]['t']    
    rates_exc = ex.results[r]['rates_exc']
    ex.df.loc[r, "result"] = np.max(rates_exc[:, t>500])

We can now inspect the updated dataframe using the attribute .df.

ex.df
mue_ext_mean mui_ext_mean IA rates_exc rates_inh t result
0 0 0 [[159.0570652914145, 158.9775367587688, 158.89... [[1.0240323754967869e-07, 1.0992389289172249e-... [[26.409600760054225, 26.728661152752267, 26.9... [0.1, 0.2, 0.30000000000000004, 0.4, 0.5, 0.60... 0.0345126
1 0 1.5 [[159.0570652914145, 158.9775367587688, 158.89... [[1.0240323754967869e-07, 1.0992389289172249e-... [[26.409600760054225, 26.728661152752267, 26.9... [0.1, 0.2, 0.30000000000000004, 0.4, 0.5, 0.60... 2.59037e-10
2 0 3 [[159.0570652914145, 158.9775367587688, 158.89... [[1.0240323754967869e-07, 1.0992389289172249e-... [[26.409600760054225, 26.728661152752267, 27.0... [0.1, 0.2, 0.30000000000000004, 0.4, 0.5, 0.60... 5.75384e-13
3 1.5 0 [[159.0570652914145, 158.9775367587688, 158.89... [[1.0240323754967869e-07, 1.0992389289172249e-... [[26.409600760054225, 26.728661152752267, 26.9... [0.1, 0.2, 0.30000000000000004, 0.4, 0.5, 0.60... 31.0926
4 1.5 1.5 [[159.0570652914145, 158.9775367587688, 158.89... [[1.0240323754967869e-07, 1.0992389289172249e-... [[26.409600760054225, 26.728661152752267, 26.9... [0.1, 0.2, 0.30000000000000004, 0.4, 0.5, 0.60... 0.098741
5 1.5 3 [[159.0570652914145, 158.9775367587688, 158.89... [[1.0240323754967869e-07, 1.0992389289172249e-... [[26.409600760054225, 26.728661152752267, 27.0... [0.1, 0.2, 0.30000000000000004, 0.4, 0.5, 0.60... 5.75384e-13
6 3 0 [[159.0570652914145, 158.9775367587688, 158.89... [[1.0240323754967869e-07, 1.0992389289172249e-... [[26.409600760054225, 26.728661152752267, 26.9... [0.1, 0.2, 0.30000000000000004, 0.4, 0.5, 0.60... 80.1357
7 3 1.5 [[159.0570652914145, 158.9775367587688, 158.89... [[1.0240323754967869e-07, 1.0992389289172249e-... [[26.409600760054225, 26.728661152752267, 26.9... [0.1, 0.2, 0.30000000000000004, 0.4, 0.5, 0.60... 66.6894
8 3 3 [[159.0570652914145, 158.9775367587688, 158.89... [[1.0240323754967869e-07, 1.0992389289172249e-... [[26.409600760054225, 26.728661152752267, 27.0... [0.1, 0.2, 0.30000000000000004, 0.4, 0.5, 0.60... 63.3527

As you can see, the column result only has a single number for each run. Perfect for plotting! In order to plot this long-format Dataframe, we need to pivot it to create a new Dataframe pivoted which has the correct x and y coordinates for plotting the results value.

pivoted = ex.df.pivot_table(values='result', index = 'mui_ext_mean', columns='mue_ext_mean', aggfunc='first')

Let's have a look at the new Dataframe that we're about to plot.

pivoted
mue_ext_mean 0.0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 ... 2.1 2.2 2.3 2.4 2.5 2.6 2.7 2.8 2.9 3.0
mui_ext_mean
0.0 3.566714e-02 5.038073e+00 2.025389e+01 3.674348e+01 5.033596e+01 6.057443e+01 6.792469e+01 7.205380e+01 7.212920e+01 6.390489e+01 ... 5.204773e+01 5.536249e+01 5.862604e+01 61.839978 65.006270 68.125977 71.201859 74.234977 77.226649 80.178835
0.1 2.309179e-02 1.893093e-01 6.573055e+00 1.973052e+01 3.464734e+01 4.793192e+01 5.856197e+01 6.619381e+01 6.966394e+01 6.840042e+01 ... 4.956086e+01 5.297202e+01 5.632147e+01 59.612008 62.847173 66.029777 69.162763 72.248066 75.288125 78.285311
0.2 1.139727e-02 6.566545e-02 5.777425e-01 6.942009e+00 1.867513e+01 3.216752e+01 4.505146e+01 5.590772e+01 6.364450e+01 6.642131e+01 ... 4.733510e+01 5.084602e+01 5.428230e+01 57.648712 60.951266 64.194099 67.380941 70.515759 73.601047 76.639324
0.3 4.980980e-03 2.668306e-02 1.389261e-01 7.672331e-01 6.834751e+00 1.729525e+01 2.995169e+01 4.232013e+01 5.307061e+01 6.054178e+01 ... 4.534479e+01 4.895815e+01 5.248024e+01 55.920889 59.288067 62.587445 65.825477 69.005410 72.132165 75.208225
0.4 1.774000e-03 9.545725e-03 4.632592e-02 2.257016e-01 8.299970e-01 6.339486e+00 1.589181e+01 2.803041e+01 3.995661e+01 5.030109e+01 ... 4.356350e+01 4.727974e+01 5.088630e+01 54.398174 57.826662 61.179190 64.464000 67.686022 70.850201 73.960529
0.5 5.518867e-04 3.117537e-03 1.578428e-02 7.044940e-02 2.879694e-01 8.278262e-01 5.770501e+00 1.441105e+01 2.621844e+01 3.785076e+01 ... 4.196489e+01 4.578350e+01 4.947261e+01 53.052735 56.538380 59.940886 63.268404 66.529015 69.727161 72.868326
0.6 1.410664e-04 8.584281e-04 4.675732e-03 2.175138e-02 8.921891e-02 3.212336e-01 7.906348e-01 5.012672e+00 1.280725e+01 2.432060e+01 ... 4.052428e+01 4.444487e+01 4.821441e+01 51.859508 55.398690 58.846881 62.214551 65.509289 68.738692 71.907518
0.7 2.666909e-05 1.844340e-04 1.102892e-03 5.771147e-03 2.571231e-02 1.005409e-01 3.231891e-01 7.281859e-01 4.219999e+00 1.112888e+01 ... 3.922140e+01 4.324317e+01 4.708968e+01 50.795865 54.385822 57.876537 61.280031 64.606649 67.864156 71.057823
0.8 4.009508e-06 3.179702e-05 2.147151e-04 1.239125e-03 6.370432e-03 2.781132e-02 1.034079e-01 3.051518e-01 6.506604e-01 3.399014e+00 ... 3.803692e+01 4.215889e+01 4.607996e+01 49.844377 53.481517 57.011032 60.447884 63.803446 67.086149 70.302511
0.9 5.211367e-07 4.494865e-06 3.316653e-05 2.228548e-04 1.271082e-03 6.256895e-03 2.696717e-02 9.658404e-02 2.709520e-01 5.666516e-01 ... 3.695606e+01 4.117694e+01 4.516972e+01 48.989173 52.670173 56.235696 59.703132 63.085022 66.390763 69.627552
1.0 4.497921e-08 4.382856e-07 3.753760e-06 2.883101e-05 1.885120e-04 1.088116e-03 5.454615e-03 2.317611e-02 8.175859e-02 2.286241e-01 ... 3.596407e+01 4.028364e+01 4.434546e+01 48.216899 51.938838 55.537941 59.033403 62.439296 65.766181 69.021414
1.1 2.454856e-09 2.828892e-08 2.784138e-07 2.543065e-06 1.970298e-05 1.325695e-04 7.964396e-04 4.057528e-03 1.764448e-02 6.394733e-02 ... 3.505049e+01 3.946759e+01 4.359590e+01 47.516540 51.276760 54.907187 58.428464 61.856296 65.202224 68.474600
1.2 8.617726e-10 1.033598e-09 1.270822e-08 1.330508e-07 1.292857e-06 1.063115e-05 7.562577e-05 4.808429e-04 2.583567e-03 1.184341e-02 ... 3.420550e+01 3.871909e+01 4.291163e+01 46.878913 50.674992 54.334154 57.879714 61.327758 64.690995 67.979021
1.3 4.749090e-10 4.749090e-10 4.749090e-10 3.809268e-09 4.591911e-08 4.808315e-07 4.470947e-06 3.483011e-05 2.382303e-04 1.402141e-03 ... 3.342083e+01 3.803007e+01 4.228475e+01 46.296340 50.126070 53.811955 57.379414 60.846529 64.225870 67.527775
1.4 3.779369e-10 3.779369e-10 3.779369e-10 3.779369e-10 1.251640e-09 1.668310e-08 1.860033e-07 1.767367e-06 1.520766e-05 1.095455e-04 ... 3.268948e+01 3.739377e+01 4.170865e+01 45.762305 49.623654 53.334517 56.922280 60.406374 63.800751 67.115838
1.5 2.590367e-10 2.590367e-10 2.590367e-10 2.590367e-10 2.590367e-10 3.288077e-10 4.536740e-09 5.344076e-08 5.769909e-07 5.198401e-06 ... 3.200543e+01 3.680447e+01 4.117684e+01 45.270179 49.161303 52.895689 56.502829 60.003073 63.410852 66.737814
1.6 1.251886e-10 1.251886e-10 1.251886e-10 1.251886e-10 1.251886e-10 1.251886e-10 1.251886e-10 7.907271e-10 1.108750e-08 1.310678e-07 ... 1.772481e+00 3.625664e+01 4.068472e+01 44.816402 48.735648 52.491775 56.116466 59.631386 63.052248 66.390267
1.7 4.542324e-11 4.542324e-11 4.542324e-11 4.542324e-11 4.542324e-11 4.542324e-11 4.542324e-11 4.542324e-11 9.924273e-11 1.688537e-09 ... 8.180056e-01 1.792342e+00 4.022864e+01 44.396018 48.341665 52.118400 55.759885 59.288792 62.721043 66.069255
1.8 2.971878e-11 2.971878e-11 2.971878e-11 2.971878e-11 2.971878e-11 2.971878e-11 2.971878e-11 2.971878e-11 2.971878e-11 2.971878e-11 ... 3.593108e-01 7.246393e-01 3.980337e+01 44.005865 47.976716 51.772671 55.429416 58.971013 62.414508 65.772525
1.9 1.504514e-11 1.504514e-11 1.504514e-11 1.504514e-11 1.504514e-11 1.504514e-11 1.504514e-11 1.504514e-11 1.504514e-11 1.504514e-11 ... 1.058719e-01 2.819929e-01 6.712352e-01 43.642547 47.636960 51.451138 55.122567 58.676420 62.130072 65.496564
2.0 4.047458e-12 4.047458e-12 4.047458e-12 4.047458e-12 4.047458e-12 4.047458e-12 4.047458e-12 4.047458e-12 4.047458e-12 4.047458e-12 ... 1.755791e-02 7.188787e-02 2.278265e-01 0.710385 47.320899 51.152163 54.837136 58.401912 61.865056 65.240070
2.1 3.170746e-12 3.170746e-12 3.170746e-12 3.170746e-12 3.170746e-12 3.170746e-12 3.170746e-12 3.170746e-12 3.170746e-12 3.170746e-12 ... 2.157163e-03 1.212794e-02 5.480229e-02 0.203206 47.024924 50.872384 54.570262 58.145799 61.618114 65.000810
2.2 2.474273e-12 2.474273e-12 2.474273e-12 2.474273e-12 2.474273e-12 2.474273e-12 2.474273e-12 2.474273e-12 2.474273e-12 2.474273e-12 ... 2.521486e-04 1.721699e-03 1.013798e-02 0.049366 0.216226 50.610903 54.320970 57.906609 61.387091 64.776849
2.3 1.940476e-12 1.940476e-12 1.940476e-12 1.940476e-12 1.940476e-12 1.940476e-12 1.940476e-12 1.940476e-12 1.940476e-12 1.940476e-12 ... 3.130066e-05 2.555109e-04 1.817075e-03 0.010711 0.054714 0.316819 54.087366 57.682068 61.170426 64.567209
2.4 1.540749e-12 1.540749e-12 1.540749e-12 1.540749e-12 1.540749e-12 1.540749e-12 1.540749e-12 1.540749e-12 1.540749e-12 1.540749e-12 ... 4.385798e-06 4.346083e-05 3.511440e-04 0.002435 0.014367 0.077998 53.867577 57.471239 60.967217 64.370566
2.5 1.244689e-12 1.244689e-12 1.244689e-12 1.244689e-12 1.244689e-12 1.244689e-12 1.244689e-12 1.244689e-12 1.244689e-12 1.244689e-12 ... 7.471609e-07 8.428183e-06 7.756259e-05 0.000619 0.004133 0.023924 53.660989 57.273101 60.776234 64.185135
2.6 1.025698e-12 1.025698e-12 1.025698e-12 1.025698e-12 1.025698e-12 1.025698e-12 1.025698e-12 1.025698e-12 1.025698e-12 1.025698e-12 ... 1.537594e-07 1.855367e-06 2.024127e-05 0.000178 0.001317 0.008475 0.050404 57.086449 60.595775 64.010538
2.7 8.627628e-13 8.627628e-13 8.627628e-13 8.627628e-13 8.627628e-13 8.627628e-13 8.627628e-13 8.627628e-13 8.627628e-13 8.627628e-13 ... 3.749910e-08 5.039620e-07 5.941546e-06 0.000059 0.000472 0.003333 0.020206 56.909811 60.425557 63.845853
2.8 7.403169e-13 7.403169e-13 7.403169e-13 7.403169e-13 7.403169e-13 7.403169e-13 7.403169e-13 7.403169e-13 7.403169e-13 7.403169e-13 ... 1.059124e-08 1.534140e-07 2.023165e-06 0.000021 0.000190 0.001452 0.009229 56.742925 60.264750 63.690263
2.9 6.471729e-13 6.471729e-13 6.471729e-13 6.471729e-13 6.471729e-13 6.471729e-13 6.471729e-13 6.471729e-13 6.471729e-13 6.471729e-13 ... 3.370684e-09 5.643513e-08 7.581333e-07 0.000009 0.000085 0.000679 0.004705 56.585028 60.112586 63.542675
3.0 5.753840e-13 5.753840e-13 5.753840e-13 5.753840e-13 5.753840e-13 5.753840e-13 5.753840e-13 5.753840e-13 5.753840e-13 5.753840e-13 ... 1.282160e-09 2.152856e-08 3.257588e-07 0.000004 0.000041 0.000354 0.002523 56.435399 59.968116 63.402682

31 rows × 31 columns

Perfect, that's exactly what we need. We have two indices, which are both equal to the paramters that we have explored before. The only entry of the Dataframe is the results value that we've put in before. Now, let's plot this Dataframe using matplotlib.imshow().

plt.imshow(pivoted, \
           extent = [min(ex.df.mue_ext_mean), max(ex.df.mue_ext_mean),
                     min(ex.df.mui_ext_mean), max(ex.df.mui_ext_mean)], origin='lower')
plt.colorbar(label='Maximum firing rate')
plt.xlabel("Input to E")
plt.ylabel("Input to I")
Text(0, 0.5, 'Input to I')