{ "cells": [ { "cell_type": "markdown", "id": "cb39a316", "metadata": { "pycharm": { "name": "#%% md\n" } }, "source": [ "# *(Brette & Guigon, 2003)*: Reliability of spike timing\n", "\n", "[![Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/brainpy/examples/blob/main/others/Brette_Guigon_2003_spike_timing_reliability.ipynb)\n", "[![Open in Kaggle](https://kaggle.com/static/images/open-in-kaggle.svg)](https://kaggle.com/kernels/welcome?src=https://github.com/brainpy/examples/blob/main/others/Brette_Guigon_2003_spike_timing_reliability.ipynb)" ] }, { "cell_type": "markdown", "id": "b6c57b77", "metadata": { "pycharm": { "name": "#%% md\n" } }, "source": [ "Implementation of the paper:\n", "\n", "- Brette R and E Guigon (2003). Reliability of Spike Timing Is a General Property of Spiking Model Neurons. Neural Computation 15, 279-308." ] }, { "cell_type": "code", "execution_count": 1, "id": "39d2e037", "metadata": { "ExecuteTime": { "end_time": "2023-07-22T04:13:54.345731100Z", "start_time": "2023-07-22T04:13:53.459794700Z" }, "pycharm": { "name": "#%%\n" } }, "outputs": [], "source": [ "import brainpy as bp\n", "import brainpy.math as bm\n", "import matplotlib.pyplot as plt" ] }, { "cell_type": "code", "execution_count": 2, "id": "6705807941846b7b", "metadata": { "ExecuteTime": { "end_time": "2023-07-22T04:13:54.354492400Z", "start_time": "2023-07-22T04:13:54.338483800Z" }, "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "'2.4.3'" ] }, "execution_count": 2, "metadata": {}, "output_type": "execute_result" } ], "source": [ "bp.__version__" ] }, { "cell_type": "code", "execution_count": 3, "id": "88e9fdd9", "metadata": { "ExecuteTime": { "end_time": "2023-07-22T04:13:54.408768Z", "start_time": "2023-07-22T04:13:54.354492400Z" }, "pycharm": { "name": "#%%\n" } }, "outputs": [], "source": [ "class ExternalInput(bp.DynamicalSystem):\n", " def __init__(self, num):\n", " super(ExternalInput, self).__init__()\n", "\n", " # parameters\n", " self.num = num\n", "\n", " # variables\n", " self.I = bm.Variable(bm.zeros(num))" ] }, { "cell_type": "code", "execution_count": 4, "id": "7b5df88b", "metadata": { "ExecuteTime": { "end_time": "2023-07-22T04:13:54.408768Z", "start_time": "2023-07-22T04:13:54.370156800Z" }, "pycharm": { "name": "#%%\n" } }, "outputs": [], "source": [ "class LinearLeakyModel(bp.dyn.NeuDyn):\n", " r\"\"\"A nonlinear leaky model.\n", "\n", " .. math::\n", "\n", " \\tau \\frac{d V}{d t}=-V+R I(t)\n", "\n", " \"\"\"\n", "\n", " def __init__(self, size, inputs):\n", " super().__init__(size)\n", " # parameters\n", " self.tau = 33 # ms\n", " self.R = 200 / 1e3 # Ω\n", " self.Vt = 15 # mV\n", " self.Vr = -5 # mV\n", " self.sigma = 1.\n", " self.inputs = inputs\n", "\n", " # variables\n", " self.V = bm.Variable(bm.random.uniform(self.Vr, self.Vt, self.num))\n", " self.spike = bm.Variable(bm.zeros(self.num, dtype=bool))\n", "\n", " # functions\n", " f = lambda V, t: (-V + self.R * self.inputs.I) / self.tau\n", " g = lambda V, t: self.sigma * bm.sqrt(2. / self.tau)\n", " self.integral = bp.sdeint(f=f, g=g)\n", "\n", " def update(self):\n", " self.inputs()\n", " self.V.value = self.integral(self.V, bp.share['t'], bp.share['dt'])\n", " self.spike.value = self.V >= self.Vt\n", " self.V.value = bm.where(self.spike, self.Vr, self.V)" ] }, { "cell_type": "code", "execution_count": 5, "id": "93782788", "metadata": { "ExecuteTime": { "end_time": "2023-07-22T04:13:54.408768Z", "start_time": "2023-07-22T04:13:54.390898900Z" }, "pycharm": { "name": "#%%\n" } }, "outputs": [], "source": [ "class NonlinearLeakyModel(bp.dyn.NeuDyn):\n", " r\"\"\"A nonlinear leaky model.\n", " \n", " .. math::\n", " \n", " \\tau \\frac{d V}{d t}=-a V^{3}+R I(t)\n", " \n", " \"\"\"\n", "\n", " def __init__(self, size, inputs):\n", " super().__init__(size)\n", " # parameters\n", " self.tau = 33 # ms\n", " self.R = 200 / 1e3 # MΩ\n", " self.Vt = 15 # mV\n", " self.Vr = -5 # mV\n", " self.a = 4444 / 1e6 # V^(-2)\n", " self.sigma = 1.\n", " self.inputs = inputs\n", "\n", " # variables\n", " self.V = bm.Variable(bm.zeros(self.num))\n", " self.spike = bm.Variable(bm.zeros(self.num, dtype=bool))\n", "\n", " # functions\n", " f = lambda V, t: (-self.a * V ** 3 + self.R * self.inputs.I) / self.tau\n", " g = lambda V, t: self.sigma * bm.sqrt(2. / self.tau)\n", " self.integral = bp.sdeint(f=f, g=g)\n", "\n", " def update(self):\n", " self.inputs()\n", " self.V.value = self.integral(self.V, bp.share['t'], bp.share['dt'])\n", " self.spike.value = self.V >= self.Vt\n", " self.V.value = bm.where(self.spike, self.Vr, self.V)" ] }, { "cell_type": "code", "execution_count": 6, "id": "2155c27d", "metadata": { "ExecuteTime": { "end_time": "2023-07-22T04:13:54.424216100Z", "start_time": "2023-07-22T04:13:54.408768Z" }, "pycharm": { "name": "#%%\n" } }, "outputs": [], "source": [ "class NonLeakyModel(bp.dyn.NeuDyn):\n", " r\"\"\"A non-leaky model.\n", "\n", " .. math::\n", "\n", " \\tau \\frac{d V}{d t}=V I(t)+k\n", "\n", " \"\"\"\n", "\n", " def __init__(self, size, inputs):\n", " super().__init__(size)\n", "\n", " # parameters\n", " self.Vt = 1\n", " self.Vr = 0\n", " self.tau = 33 # ms\n", " self.k = 1\n", " self.sigma = 0.02\n", " self.inputs = inputs\n", "\n", " # variables\n", " self.V = bm.Variable(bm.random.uniform(self.Vr, self.Vt, self.num))\n", " self.spike = bm.Variable(bm.zeros(self.num, dtype=bool))\n", "\n", " # functions\n", " f = lambda V, t: (V * self.inputs.I + self.k) / self.tau\n", " g = lambda V, t: self.sigma * (2 / self.tau) ** .5\n", " self.integral = bp.sdeint(f, g, method='euler')\n", "\n", " def update(self):\n", " self.inputs()\n", " self.V.value = self.integral(self.V, bp.share['t'], bp.share['dt'])\n", " self.spike.value = self.V >= self.Vt\n", " self.V.value = bm.where(self.spike, self.Vr, self.V)" ] }, { "cell_type": "code", "execution_count": 7, "id": "ed364942", "metadata": { "ExecuteTime": { "end_time": "2023-07-22T04:13:54.439872700Z", "start_time": "2023-07-22T04:13:54.424216100Z" }, "pycharm": { "name": "#%%\n" } }, "outputs": [], "source": [ "class PerfectIntegrator(bp.dyn.NeuDyn):\n", " r\"\"\"Integrate inputs.\n", "\n", " .. math::\n", "\n", " \\tau \\frac{d V}{d t}=f(t)\n", "\n", " where :math:`f(t)` is an input function.\n", "\n", " \"\"\"\n", "\n", " def __init__(self, size, inputs):\n", " super().__init__(size)\n", "\n", " # parameters\n", " self.tau = 12.5 # ms\n", " self.Vt = 1\n", " self.Vr = 0\n", " self.sigma = 0.27\n", " self.inputs = inputs\n", "\n", " # variables\n", " self.V = bm.Variable(bm.random.uniform(self.Vr, self.Vt, self.num))\n", " self.spike = bm.Variable(bm.zeros(self.num, dtype=bool))\n", "\n", " # functions\n", " f = lambda V, t: self.inputs.I / self.tau\n", " g = lambda V, t: self.sigma * (2 / self.tau) ** .5\n", " self.integral = bp.sdeint(f, g, method='euler')\n", "\n", " def update(self):\n", " self.inputs()\n", " self.V.value = self.integral(self.V, bp.share['t'], bp.share['dt'])\n", " self.spike.value = self.V >= self.Vt\n", " self.V.value = bm.where(self.spike, self.Vr, self.V)" ] }, { "cell_type": "code", "execution_count": 8, "id": "ceab0946", "metadata": { "ExecuteTime": { "end_time": "2023-07-22T04:13:54.455502Z", "start_time": "2023-07-22T04:13:54.439872700Z" }, "pycharm": { "name": "#%%\n" } }, "outputs": [], "source": [ "def figure6(sigma=0.):\n", " class Noise(ExternalInput):\n", " def __init__(self, num):\n", " super(Noise, self).__init__(num)\n", " # parameters\n", " self.p = bm.linspace(0., 1., num)\n", " # variables\n", " self.B = bm.Variable(bm.zeros(1))\n", "\n", " def update(self):\n", " self.B[:] = 30 * bm.sin(40 * bm.pi * bp.share['t'] / 1000) # (1,)\n", " self.I.value = 85 + 40 * (1 - self.p) + self.p * self.B # (num,)\n", "\n", " num = 500\n", " model = LinearLeakyModel(num, inputs=Noise(num))\n", " model.sigma = sigma\n", "\n", " runner = bp.DSRunner(model, monitors=['inputs.B', 'spike'])\n", " runner.run(2000.)\n", "\n", " fig, gs = bp.visualize.get_figure(2, 1, 4, 12)\n", " fig.add_subplot(gs[0, 0])\n", " bp.visualize.line_plot(runner.mon.ts, runner.mon['inputs.B'], title='shared inputs')\n", " fig.add_subplot(gs[1, 0])\n", " bp.visualize.raster_plot(runner.mon.ts, runner.mon['spike'], ylabel='p')\n", " plt.yticks(bm.linspace(0, num, 5).numpy(), bm.linspace(0., 1., 5).numpy())\n", " plt.show()" ] }, { "cell_type": "code", "execution_count": 9, "id": "ee5dcaf3", "metadata": { "ExecuteTime": { "end_time": "2023-07-22T04:13:55.389105400Z", "start_time": "2023-07-22T04:13:54.455502Z" }, "pycharm": { "name": "#%%\n" } }, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "No GPU/TPU found, falling back to CPU. (Set TF_CPP_MIN_LOG_LEVEL=0 and rerun for more info.)\n" ] }, { "data": { "application/vnd.jupyter.widget-view+json": { "model_id": "e73878db9bd14b519e715e331e88ca16", "version_major": 2, "version_minor": 0 }, "text/plain": [ " 0%| | 0/20000 [00:00" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "figure6(0.)" ] }, { "cell_type": "code", "execution_count": 10, "id": "a49f13a5", "metadata": { "ExecuteTime": { "end_time": "2023-07-22T04:13:56.022987900Z", "start_time": "2023-07-22T04:13:55.389105400Z" }, "pycharm": { "name": "#%%\n" } }, "outputs": [ { "data": { "application/vnd.jupyter.widget-view+json": { "model_id": "f367d1d9c07d4c0887a263fbb24e763d", "version_major": 2, "version_minor": 0 }, "text/plain": [ " 0%| | 0/20000 [00:00" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "figure6(1.)" ] }, { "cell_type": "code", "execution_count": 11, "id": "44295d5d", "metadata": { "ExecuteTime": { "end_time": "2023-07-22T04:13:56.132378700Z", "start_time": "2023-07-22T04:13:56.022987900Z" }, "pycharm": { "name": "#%%\n" } }, "outputs": [], "source": [ "def figure7(sigma):\n", " class Noise(ExternalInput):\n", " def __init__(self, num):\n", " super(Noise, self).__init__(num)\n", " # parameters\n", " self.p = bm.linspace(0., 1., num)\n", " # variables\n", " self.B = bm.Variable(bm.zeros(1))\n", "\n", " def update(self):\n", " self.B[:] = 150 * bm.sin(40 * bm.pi * bp.share['t'] / 1000) # (1,)\n", " self.I.value = 150 + self.p * self.B # (num,)\n", "\n", " num = 500\n", " model = NonlinearLeakyModel(num, inputs=Noise(num))\n", " model.sigma = sigma\n", "\n", " runner = bp.DSRunner(model, monitors=['inputs.B', 'spike'])\n", " runner.run(1000.)\n", "\n", " fig, gs = bp.visualize.get_figure(2, 1, 4, 8)\n", " fig.add_subplot(gs[0, 0])\n", " bp.visualize.line_plot(runner.mon.ts, runner.mon['inputs.B'], title='shared inputs')\n", " fig.add_subplot(gs[1, 0])\n", " bp.visualize.raster_plot(runner.mon.ts, runner.mon['spike'], ylabel='p')\n", " plt.yticks(bm.linspace(0, num, 5).numpy(), bm.linspace(0., 1., 5).numpy())\n", " plt.show()" ] }, { "cell_type": "code", "execution_count": 12, "id": "be05804c", "metadata": { "ExecuteTime": { "end_time": "2023-07-22T04:13:56.542643600Z", "start_time": "2023-07-22T04:13:56.038622100Z" }, "pycharm": { "name": "#%%\n" } }, "outputs": [ { "data": { "application/vnd.jupyter.widget-view+json": { "model_id": "7af1f871e3224977963007953f11bbaf", "version_major": 2, "version_minor": 0 }, "text/plain": [ " 0%| | 0/10000 [00:00" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "figure7(1.5)" ] }, { "cell_type": "code", "execution_count": 13, "id": "cc0554f0", "metadata": { "ExecuteTime": { "end_time": "2023-07-22T04:13:56.620841300Z", "start_time": "2023-07-22T04:13:56.542643600Z" }, "pycharm": { "name": "#%%\n" } }, "outputs": [], "source": [ "def figure8(sigma):\n", " class Noise(ExternalInput):\n", " def __init__(self, num):\n", " super(Noise, self).__init__(num)\n", " # parameters\n", " self.p = bm.linspace(0., 1., num)\n", " # variables\n", " self.B = bm.Variable(bm.zeros(1))\n", "\n", " def update(self):\n", " self.B[:] = 150 * bm.sin(40 * bm.pi * bp.share['t'] / 1000) # (1,)\n", " self.I.value = 150 + self.p * self.B # (num,)\n", "\n", " num = 500\n", " model = NonlinearLeakyModel(num, inputs=Noise(num))\n", " model.V.value = bm.random.uniform(model.Vr, model.Vt, model.num)\n", " model.sigma = sigma\n", "\n", " runner = bp.DSRunner(model, monitors=['inputs.B', 'spike'])\n", " runner.run(1000.)\n", "\n", " fig, gs = bp.visualize.get_figure(2, 1, 4, 8)\n", " fig.add_subplot(gs[0, 0])\n", " bp.visualize.line_plot(runner.mon.ts, runner.mon['inputs.B'], title='shared inputs')\n", " fig.add_subplot(gs[1, 0])\n", " bp.visualize.raster_plot(runner.mon.ts, runner.mon['spike'], ylabel='p')\n", " plt.yticks(bm.linspace(0, num, 5).numpy(), bm.linspace(0., 1., 5).numpy())\n", " plt.show()" ] }, { "cell_type": "code", "execution_count": 14, "id": "d07c2506", "metadata": { "ExecuteTime": { "end_time": "2023-07-22T04:13:57.063460200Z", "start_time": "2023-07-22T04:13:56.558335300Z" }, "pycharm": { "name": "#%%\n" } }, "outputs": [ { "data": { "application/vnd.jupyter.widget-view+json": { "model_id": "29b0315b865748f7a0ab5a347244a65c", "version_major": 2, "version_minor": 0 }, "text/plain": [ " 0%| | 0/10000 [00:00" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "figure8(1.5)" ] }, { "cell_type": "code", "execution_count": 15, "id": "759a434e", "metadata": { "ExecuteTime": { "end_time": "2023-07-22T04:13:57.142886500Z", "start_time": "2023-07-22T04:13:57.063460200Z" }, "pycharm": { "name": "#%%\n" } }, "outputs": [], "source": [ "def figure9(sigma):\n", " class Noise(ExternalInput):\n", " def __init__(self, num):\n", " super(Noise, self).__init__(num)\n", " # parameters\n", " self.p = bm.linspace(0., 1., num)\n", " # variables\n", " self.B = bm.Variable(bm.zeros(1))\n", "\n", " def update(self):\n", " self.B[:] = bm.sin(40 * bm.pi * bp.share['t'] / 1000) # (1,)\n", " self.I.value = 112.5 + (75 + 37.5 * self.p) * self.B + 37.5 * self.p # (num,)\n", "\n", " num = 500\n", " # B should be a triangular wave taking values between -1 and 1, with\n", " # rising and falling time drawn uniformly between 10 ms and 50 ms.\n", " # While we use sin wave instead.\n", " model = LinearLeakyModel(num, inputs=Noise(num))\n", " model.sigma = sigma\n", "\n", " runner = bp.DSRunner(model, monitors=['inputs.B', 'spike'])\n", " runner.run(2000.)\n", "\n", " fig, gs = bp.visualize.get_figure(2, 1, 4, 12)\n", " fig.add_subplot(gs[0, 0])\n", " bp.visualize.line_plot(runner.mon.ts, runner.mon['inputs.B'], title='shared inputs')\n", " fig.add_subplot(gs[1, 0])\n", " bp.visualize.raster_plot(runner.mon.ts, runner.mon['spike'], ylabel='p')\n", " plt.yticks(bm.linspace(0, num, 5).numpy(), bm.linspace(0., 1., 5).numpy())\n", " plt.show()" ] }, { "cell_type": "code", "execution_count": 16, "id": "f4f4ba5b", "metadata": { "ExecuteTime": { "end_time": "2023-07-22T04:13:57.708103400Z", "start_time": "2023-07-22T04:13:57.083310300Z" }, "pycharm": { "name": "#%%\n" } }, "outputs": [ { "data": { "application/vnd.jupyter.widget-view+json": { "model_id": "a62e6d81d945440e8fb492893d8c0c03", "version_major": 2, "version_minor": 0 }, "text/plain": [ " 0%| | 0/20000 [00:00" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "figure9(0.5)" ] }, { "cell_type": "code", "execution_count": 17, "id": "88c82316", "metadata": { "ExecuteTime": { "end_time": "2023-07-22T04:13:57.725263Z", "start_time": "2023-07-22T04:13:57.708103400Z" }, "pycharm": { "name": "#%%\n" } }, "outputs": [], "source": [ "def figure10():\n", " class Noise(ExternalInput):\n", " def __init__(self, num):\n", " super(Noise, self).__init__(num)\n", " # parameters\n", " self.tau = 10 # ms\n", " self.p = bm.linspace(0., 1., num)\n", " # variables\n", " self.x = bm.Variable(bm.zeros(1))\n", " self.B = bm.Variable(bm.zeros(1))\n", " # functions\n", " f = lambda x, t: -x / self.tau\n", " g = lambda x, t: bm.sqrt(2. / self.tau)\n", " self.integral = bp.sdeint(f=f, g=g)\n", "\n", " def update(self):\n", " self.x.value = self.integral(self.x, bp.share['t'], bp.share['dt']) # (1,)\n", " self.B.value = 2. / (1 + bm.exp(-2 * self.x)) - 1 # (1,)\n", " self.I.value = 0.5 + 3 * self.p * self.B # (num,)\n", "\n", " num = 500\n", " model = NonLeakyModel(num, inputs=Noise(num))\n", "\n", " runner = bp.DSRunner(model, monitors=['inputs.B', 'spike'])\n", " runner.run(1000.)\n", "\n", " fig, gs = bp.visualize.get_figure(2, 1, 4, 8)\n", " fig.add_subplot(gs[0, 0])\n", " bp.visualize.line_plot(runner.mon.ts, runner.mon['inputs.B'], title='shared inputs')\n", " fig.add_subplot(gs[1, 0])\n", " bp.visualize.raster_plot(runner.mon.ts, runner.mon['spike'], ylabel='p')\n", " plt.yticks(bm.linspace(0, num, 5).numpy(), bm.linspace(0., 1., 5).numpy())\n", " plt.show()" ] }, { "cell_type": "code", "execution_count": 18, "id": "48969095", "metadata": { "ExecuteTime": { "end_time": "2023-07-22T04:13:57.832395200Z", "start_time": "2023-07-22T04:13:57.728184600Z" }, "pycharm": { "name": "#%%\n" } }, "outputs": [], "source": [ "def figure11(sigma):\n", " class Noise(ExternalInput):\n", " def __init__(self, num):\n", " super(Noise, self).__init__(num)\n", " # parameters\n", " self.tau = 10 # ms\n", " self.p = bm.linspace(0., 1., num)\n", " # variables\n", " self.x = bm.Variable(bm.zeros(1))\n", " self.B = bm.Variable(bm.zeros(1))\n", " # functions\n", " f = lambda x, t: -x / self.tau\n", " g = lambda x, t: bm.sqrt(2. / self.tau)\n", " self.integral = bp.sdeint(f=f, g=g)\n", "\n", " def update(self):\n", " self.x.value = self.integral(self.x, bp.share['t'], bp.share['dt']) # (1,)\n", " self.B.value = 2. / (1 + bm.exp(-2 * self.x)) - 1 # (1,)\n", " self.I.value = 0.5 + self.p * self.B # (num,)\n", "\n", " num = 500\n", " model = PerfectIntegrator(num, inputs=Noise(num))\n", " model.sigma = sigma\n", "\n", " runner = bp.DSRunner(model, monitors=['inputs.B', 'spike'])\n", " runner.run(1000.)\n", "\n", " fig, gs = bp.visualize.get_figure(2, 1, 4, 8)\n", " fig.add_subplot(gs[0, 0])\n", " bp.visualize.line_plot(runner.mon.ts, runner.mon['inputs.B'], title='shared inputs')\n", " fig.add_subplot(gs[1, 0])\n", " bp.visualize.raster_plot(runner.mon.ts, runner.mon['spike'], ylabel='p')\n", " plt.yticks(bm.linspace(0, num, 5).numpy(), bm.linspace(0., 1., 5).numpy())\n", " plt.show()" ] }, { "cell_type": "code", "execution_count": 19, "id": "d74117b6", "metadata": { "ExecuteTime": { "end_time": "2023-07-22T04:13:58.346039400Z", "start_time": "2023-07-22T04:13:57.738116Z" }, "pycharm": { "name": "#%%\n" } }, "outputs": [ { "data": { "application/vnd.jupyter.widget-view+json": { "model_id": "b703c7dfe19b44cd876ceeae94b48d41", "version_major": 2, "version_minor": 0 }, "text/plain": [ " 0%| | 0/10000 [00:00" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "figure11(0.)" ] }, { "cell_type": "code", "execution_count": 20, "id": "d6dec8fc", "metadata": { "ExecuteTime": { "end_time": "2023-07-22T04:13:59.006754800Z", "start_time": "2023-07-22T04:13:58.346039400Z" }, "pycharm": { "name": "#%%\n" } }, "outputs": [ { "data": { "application/vnd.jupyter.widget-view+json": { "model_id": "0e83bd20f0234c099edba2751383401e", "version_major": 2, "version_minor": 0 }, "text/plain": [ " 0%| | 0/10000 [00:00" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "figure11(0.27)" ] } ], "metadata": { "jupytext": { "cell_metadata_filter": "-all", "encoding": "# -*- coding: utf-8 -*-", "formats": "auto:light,ipynb", "notebook_metadata_filter": "-all" }, "kernelspec": { "display_name": "brainpy", "language": "python", "name": "brainpy" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.9.12" }, "latex_envs": { "LaTeX_envs_menu_present": true, "autoclose": false, "autocomplete": true, "bibliofile": "biblio.bib", "cite_by": "apalike", "current_citInitial": 1, "eqLabelWithNumbers": true, "eqNumInitial": 1, "hotkeys": { "equation": "Ctrl-E", "itemize": "Ctrl-I" }, "labels_anchors": false, "latex_user_defs": false, "report_style_numbering": false, "user_envs_cfg": false }, "toc": { "base_numbering": 1, "nav_menu": {}, "number_sections": true, "sideBar": true, "skip_h1_title": false, "title_cell": "Table of Contents", "title_sidebar": "Contents", "toc_cell": false, "toc_position": {}, "toc_section_display": true, "toc_window_display": false } }, "nbformat": 4, "nbformat_minor": 5 }