├── LICENSE ├── LICENSE.CC-BY-4.0 ├── LICENSE.MIT ├── README.md ├── environment.yml ├── example_1_pyloric_net_plot.py ├── example_1_pyloric_network.ipynb ├── example_1_pyloric_network_complex.ipynb ├── example_2_eye_movements.ipynb ├── example_2_eye_movements_interactive.ipynb ├── example_2_eye_movements_interactive_matplotlib.ipynb ├── example_3_bisection.ipynb ├── example_4_microphone.ipynb ├── example_appendix_multicompartment_model.ipynb ├── example_appendix_parameter_exploration.ipynb ├── index.ipynb ├── scale_flute.wav ├── sound_from_file.cpp ├── sound_from_mic.cpp ├── sound_input.h └── tc200.CNG.swc /LICENSE: -------------------------------------------------------------------------------- 1 | ## License 2 | 3 | This work is dual-licensed under the Creative Commons Attribution 4.0 International and the MIT license. 4 | You can choose between them if you use this work. 5 | 6 | `SPDX-License-Identifier: CC-BY-4.0 OR MIT` 7 | 8 | -------------------------------------------------------------------------------- /LICENSE.CC-BY-4.0: -------------------------------------------------------------------------------- 1 | Creative Commons Attribution 4.0 International Public License 2 | 3 | By exercising the Licensed Rights (defined below), You accept and agree to be bound by the terms and conditions of this Creative Commons Attribution 4.0 International Public License ("Public License"). To the extent this Public License may be interpreted as a contract, You are granted the Licensed Rights in consideration of Your acceptance of these terms and conditions, and the Licensor grants You such rights in consideration of benefits the Licensor receives from making the Licensed Material available under these terms and conditions. 4 | 5 | Section 1 – Definitions. 6 | 7 | a. Adapted Material means material subject to Copyright and Similar Rights that is derived from or based upon the Licensed Material and in which the Licensed Material is translated, altered, arranged, transformed, or otherwise modified in a manner requiring permission under the Copyright and Similar Rights held by the Licensor. For purposes of this Public License, where the Licensed Material is a musical work, performance, or sound recording, Adapted Material is always produced where the Licensed Material is synched in timed relation with a moving image. 8 | b. Adapter's License means the license You apply to Your Copyright and Similar Rights in Your contributions to Adapted Material in accordance with the terms and conditions of this Public License. 9 | c. Copyright and Similar Rights means copyright and/or similar rights closely related to copyright including, without limitation, performance, broadcast, sound recording, and Sui Generis Database Rights, without regard to how the rights are labeled or categorized. For purposes of this Public License, the rights specified in Section 2(b)(1)-(2) are not Copyright and Similar Rights. 10 | d. Effective Technological Measures means those measures that, in the absence of proper authority, may not be circumvented under laws fulfilling obligations under Article 11 of the WIPO Copyright Treaty adopted on December 20, 1996, and/or similar international agreements. 11 | e. Exceptions and Limitations means fair use, fair dealing, and/or any other exception or limitation to Copyright and Similar Rights that applies to Your use of the Licensed Material. 12 | f. Licensed Material means the artistic or literary work, database, or other material to which the Licensor applied this Public License. 13 | g. Licensed Rights means the rights granted to You subject to the terms and conditions of this Public License, which are limited to all Copyright and Similar Rights that apply to Your use of the Licensed Material and that the Licensor has authority to license. 14 | h. Licensor means the individual(s) or entity(ies) granting rights under this Public License. 15 | i. Share means to provide material to the public by any means or process that requires permission under the Licensed Rights, such as reproduction, public display, public performance, distribution, dissemination, communication, or importation, and to make material available to the public including in ways that members of the public may access the material from a place and at a time individually chosen by them. 16 | j. Sui Generis Database Rights means rights other than copyright resulting from Directive 96/9/EC of the European Parliament and of the Council of 11 March 1996 on the legal protection of databases, as amended and/or succeeded, as well as other essentially equivalent rights anywhere in the world. 17 | k. You means the individual or entity exercising the Licensed Rights under this Public License. Your has a corresponding meaning. 18 | 19 | Section 2 – Scope. 20 | 21 | a. License grant. 22 | 1. Subject to the terms and conditions of this Public License, the Licensor hereby grants You a worldwide, royalty-free, non-sublicensable, non-exclusive, irrevocable license to exercise the Licensed Rights in the Licensed Material to: 23 | A. reproduce and Share the Licensed Material, in whole or in part; and 24 | B. produce, reproduce, and Share Adapted Material. 25 | 2. Exceptions and Limitations. For the avoidance of doubt, where Exceptions and Limitations apply to Your use, this Public License does not apply, and You do not need to comply with its terms and conditions. 26 | 3. Term. The term of this Public License is specified in Section 6(a). 27 | 4. Media and formats; technical modifications allowed. The Licensor authorizes You to exercise the Licensed Rights in all media and formats whether now known or hereafter created, and to make technical modifications necessary to do so. The Licensor waives and/or agrees not to assert any right or authority to forbid You from making technical modifications necessary to exercise the Licensed Rights, including technical modifications necessary to circumvent Effective Technological Measures. For purposes of this Public License, simply making modifications authorized by this Section 2(a)(4) never produces Adapted Material. 28 | 5. Downstream recipients. 29 | A. Offer from the Licensor – Licensed Material. Every recipient of the Licensed Material automatically receives an offer from the Licensor to exercise the Licensed Rights under the terms and conditions of this Public License. 30 | B. No downstream restrictions. You may not offer or impose any additional or different terms or conditions on, or apply any Effective Technological Measures to, the Licensed Material if doing so restricts exercise of the Licensed Rights by any recipient of the Licensed Material. 31 | 6. No endorsement. Nothing in this Public License constitutes or may be construed as permission to assert or imply that You are, or that Your use of the Licensed Material is, connected with, or sponsored, endorsed, or granted official status by, the Licensor or others designated to receive attribution as provided in Section 3(a)(1)(A)(i). 32 | b. Other rights. 33 | 1. Moral rights, such as the right of integrity, are not licensed under this Public License, nor are publicity, privacy, and/or other similar personality rights; however, to the extent possible, the Licensor waives and/or agrees not to assert any such rights held by the Licensor to the limited extent necessary to allow You to exercise the Licensed Rights, but not otherwise. 34 | 2. Patent and trademark rights are not licensed under this Public License. 35 | 3. To the extent possible, the Licensor waives any right to collect royalties from You for the exercise of the Licensed Rights, whether directly or through a collecting society under any voluntary or waivable statutory or compulsory licensing scheme. In all other cases the Licensor expressly reserves any right to collect such royalties. 36 | 37 | Section 3 – License Conditions. 38 | 39 | Your exercise of the Licensed Rights is expressly made subject to the following conditions. 40 | 41 | a. Attribution. 42 | 1. If You Share the Licensed Material (including in modified form), You must: 43 | A. retain the following if it is supplied by the Licensor with the Licensed Material: 44 | i. identification of the creator(s) of the Licensed Material and any others designated to receive attribution, in any reasonable manner requested by the Licensor (including by pseudonym if designated); 45 | ii. a copyright notice; 46 | iii. a notice that refers to this Public License; 47 | iv. a notice that refers to the disclaimer of warranties; 48 | v. a URI or hyperlink to the Licensed Material to the extent reasonably practicable; 49 | B. indicate if You modified the Licensed Material and retain an indication of any previous modifications; and 50 | C. indicate the Licensed Material is licensed under this Public License, and include the text of, or the URI or hyperlink to, this Public License. 51 | 2. You may satisfy the conditions in Section 3(a)(1) in any reasonable manner based on the medium, means, and context in which You Share the Licensed Material. For example, it may be reasonable to satisfy the conditions by providing a URI or hyperlink to a resource that includes the required information. 52 | 3. If requested by the Licensor, You must remove any of the information required by Section 3(a)(1)(A) to the extent reasonably practicable. 53 | 4. If You Share Adapted Material You produce, the Adapter's License You apply must not prevent recipients of the Adapted Material from complying with this Public License. 54 | 55 | Section 4 – Sui Generis Database Rights. 56 | 57 | Where the Licensed Rights include Sui Generis Database Rights that apply to Your use of the Licensed Material: 58 | 59 | a. for the avoidance of doubt, Section 2(a)(1) grants You the right to extract, reuse, reproduce, and Share all or a substantial portion of the contents of the database; 60 | b. if You include all or a substantial portion of the database contents in a database in which You have Sui Generis Database Rights, then the database in which You have Sui Generis Database Rights (but not its individual contents) is Adapted Material; and 61 | c. You must comply with the conditions in Section 3(a) if You Share all or a substantial portion of the contents of the database. 62 | 63 | For the avoidance of doubt, this Section 4 supplements and does not replace Your obligations under this Public License where the Licensed Rights include other Copyright and Similar Rights. 64 | 65 | Section 5 – Disclaimer of Warranties and Limitation of Liability. 66 | 67 | a. Unless otherwise separately undertaken by the Licensor, to the extent possible, the Licensor offers the Licensed Material as-is and as-available, and makes no representations or warranties of any kind concerning the Licensed Material, whether express, implied, statutory, or other. This includes, without limitation, warranties of title, merchantability, fitness for a particular purpose, non-infringement, absence of latent or other defects, accuracy, or the presence or absence of errors, whether or not known or discoverable. Where disclaimers of warranties are not allowed in full or in part, this disclaimer may not apply to You. 68 | b. To the extent possible, in no event will the Licensor be liable to You on any legal theory (including, without limitation, negligence) or otherwise for any direct, special, indirect, incidental, consequential, punitive, exemplary, or other losses, costs, expenses, or damages arising out of this Public License or use of the Licensed Material, even if the Licensor has been advised of the possibility of such losses, costs, expenses, or damages. Where a limitation of liability is not allowed in full or in part, this limitation may not apply to You. 69 | c. The disclaimer of warranties and limitation of liability provided above shall be interpreted in a manner that, to the extent possible, most closely approximates an absolute disclaimer and waiver of all liability. 70 | 71 | Section 6 – Term and Termination. 72 | 73 | a. This Public License applies for the term of the Copyright and Similar Rights licensed here. However, if You fail to comply with this Public License, then Your rights under this Public License terminate automatically. 74 | b. Where Your right to use the Licensed Material has terminated under Section 6(a), it reinstates: 75 | 1. automatically as of the date the violation is cured, provided it is cured within 30 days of Your discovery of the violation; or 76 | 2. upon express reinstatement by the Licensor. 77 | c. For the avoidance of doubt, this Section 6(b) does not affect any right the Licensor may have to seek remedies for Your violations of this Public License. 78 | d. For the avoidance of doubt, the Licensor may also offer the Licensed Material under separate terms or conditions or stop distributing the Licensed Material at any time; however, doing so will not terminate this Public License. 79 | e. Sections 1, 5, 6, 7, and 8 survive termination of this Public License. 80 | 81 | Section 7 – Other Terms and Conditions. 82 | 83 | a. The Licensor shall not be bound by any additional or different terms or conditions communicated by You unless expressly agreed. 84 | b. Any arrangements, understandings, or agreements regarding the Licensed Material not stated herein are separate from and independent of the terms and conditions of this Public License. 85 | 86 | Section 8 – Interpretation. 87 | 88 | a. For the avoidance of doubt, this Public License does not, and shall not be interpreted to, reduce, limit, restrict, or impose conditions on any use of the Licensed Material that could lawfully be made without permission under this Public License. 89 | b. To the extent possible, if any provision of this Public License is deemed unenforceable, it shall be automatically reformed to the minimum extent necessary to make it enforceable. If the provision cannot be reformed, it shall be severed from this Public License without affecting the enforceability of the remaining terms and conditions. 90 | c. No term or condition of this Public License will be waived and no failure to comply consented to unless expressly agreed to by the Licensor. 91 | d. Nothing in this Public License constitutes or may be interpreted as a limitation upon, or waiver of, any privileges and immunities that apply to the Licensor or You, including from the legal processes of any jurisdiction or authority. 92 | -------------------------------------------------------------------------------- /LICENSE.MIT: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Marcel Stimberg, Romain Brette, and Dan F.M. Goodman 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 6 | 7 | The above copyright notice and this permission notice (including the next paragraph) shall be included in all copies or substantial portions of the Software. 8 | 9 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 10 | 11 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Examples for Brian 2 paper 2 | -------------------------- 3 | 4 | This repository contains interactive examples in the form of [Jupyter notebooks]() that demonstrate 5 | the use of the [Brian simulator](http://briansimulator.org) for neural modeling. 6 | 7 | Running these examples needs an installation of Brian 2 (see documentation at 8 | [brian2.readthedocs.io](https://brian2.readthedocs.io)), together with libraries 9 | for plotting of the results ([plotly](https://plot.ly/) and [matplotlib](https://matplotlib.org/)). 10 | 11 | You can install all necessary dependencies by creating a [conda](https://conda.io) environment from the provided environment file: 12 | 13 | ```shell 14 | $ conda env create -f environment.yml 15 | ``` 16 | 17 | To run the notebooks in the [binder](https://mybinder.org/) environment, without requiring any installation on your local computer, use the following link: 18 | [![Binder](https://mybinder.org/badge_logo.svg)](https://mybinder.org/v2/gh/brian-team/brian2_paper_examples/master?filepath=index.ipynb) 19 | 20 | The code and data in this repository are dual-licensed under the [Creative Commons Attribution 4.0 International Public License](LICENSE.CC-BY-4.0) and the 21 | [MIT license](LICENSE.MIT), you can chose between them if you use this work. 22 | -------------------------------------------------------------------------------- /environment.yml: -------------------------------------------------------------------------------- 1 | name: brian2-paper-examples 2 | channels: 3 | - conda-forge 4 | dependencies: 5 | - python=3.6 6 | - cython=0.29* 7 | - nose=1.3* 8 | - ipywidgets=7.4* 9 | - notebook=5.7* 10 | - widgetsnbextension=3.4* 11 | - plotly=3.6* 12 | - sympy=1.3* 13 | - scipy=1.2* 14 | - matplotlib=2.1* 15 | - ipympl=0.2* 16 | - brian2=2.2.2.1 17 | - pip=19.* 18 | - pip: 19 | - brian2tools 20 | 21 | -------------------------------------------------------------------------------- /example_1_pyloric_net_plot.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | 3 | from plotly import tools 4 | from plotly.offline import iplot, init_notebook_mode 5 | import plotly.graph_objs as go 6 | 7 | from brian2.units import second, mV 8 | 9 | init_notebook_mode(connected=True) 10 | 11 | def do_pyloric_net_plot(spike_trains, times, membrane_potential, varname, 12 | init_time, observe_time, adapt_time): 13 | fig = tools.make_subplots(rows=7, cols=2, shared_xaxes=True, shared_yaxes=True, 14 | start_cell='bottom-left', subplot_titles=['initial', 'adapted', 15 | '', '', '', '', '', ''], 16 | specs=[[{}, {}], 17 | [{'rowspan': 2}, {'rowspan': 2}], 18 | [None, None], 19 | [{'rowspan': 2}, {'rowspan': 2}], 20 | [None, None], 21 | [{'rowspan': 2}, {'rowspan': 2}], 22 | [None, None]], 23 | print_grid=False) 24 | 25 | traces = [] 26 | before_adaptation = (times>=init_time) & (times < (init_time + observe_time)) 27 | after_adapt_time = init_time + observe_time + adapt_time 28 | after_adaptation = (times>=after_adapt_time) 29 | for idx, (label, color) in enumerate(zip(['AB/PD', 'LP', 'PY'], 30 | ['#1f77b4', '#ff7f03', '#2ca02c'])): 31 | 32 | trace = go.Scattergl(x=(times[before_adaptation] - init_time) / second, 33 | y=membrane_potential[idx][before_adaptation] / mV, 34 | marker={'color': color}, 35 | showlegend=False, name=label) 36 | fig.append_trace(trace, 2+idx*2, 1) 37 | if spike_trains is not None: 38 | spike_times = spike_trains[idx] 39 | spike_times = spike_times[(spike_times >= init_time) & (spike_times < (init_time + observe_time))] 40 | spike_trace = go.Scattergl(x=(spike_times - init_time) / second, 41 | y=np.ones(len(spike_times))*(3-idx), 42 | marker={'symbol': 'line-ns', "line": {"width": 2, 'color': color}}, 43 | mode='markers', showlegend=False, name=label) 44 | fig.append_trace(spike_trace, 1, 1) 45 | trace = go.Scattergl(x=(times[after_adaptation] - after_adapt_time) / second, 46 | y=membrane_potential[idx][after_adaptation] / mV, 47 | marker={'color': color}, 48 | name=label) 49 | fig.append_trace(trace, 2+idx*2, 2) 50 | if spike_trains is not None: 51 | spike_times = spike_trains[idx] 52 | spike_times = spike_times[spike_times >= after_adapt_time] 53 | spike_trace = go.Scattergl(x=(spike_times - after_adapt_time) / second, 54 | y=np.ones(len(spike_times))*(3-idx), 55 | marker={'symbol': 'line-ns', "line": {"width": 2, 'color': color}}, 56 | mode='markers', showlegend=False, name=label) 57 | fig.append_trace(spike_trace, 1, 2) 58 | fig['layout'].update(xaxis1={'range': (0, observe_time/second), 59 | 'title': 'time (in s)', 60 | 'zeroline': False}, 61 | xaxis2={'range': (0, observe_time/second), 62 | 'title': 'time (in s)', 63 | 'zeroline': False}, 64 | yaxis3={'title': 'v (in mV)'}, 65 | yaxis1={'showline': False, 66 | 'showticklabels': False}) 67 | iplot(fig) 68 | -------------------------------------------------------------------------------- /example_1_pyloric_network.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "### Quickstart\n", 8 | "To run the code below:\n", 9 | "\n", 10 | "1. Click on the cell to select it.\n", 11 | "2. Press `SHIFT+ENTER` on your keyboard or press the play button\n", 12 | " () in the toolbar above.\n", 13 | "\n", 14 | "Feel free to create new cells using the plus button\n", 15 | "(), or pressing `SHIFT+ENTER` while this cell\n", 16 | "is selected." 17 | ] 18 | }, 19 | { 20 | "cell_type": "markdown", 21 | "metadata": {}, 22 | "source": [ 23 | "# Example 1 (Pyloric network of the crustacean stomatogastric ganglion)\n", 24 | "\n", 25 | "This example demonstrates a highly simplified model of the pyloric circuit of the crustacean stomatogastric ganglion. This circuit generates a tri-phasic rhythmic pattern with alternating bursts of action potentials in different types of motor neurons. Here, we follow previous work (e.g. Golowasch et al., 1999) by modeling the circuit as consisting of three populations: AB/PD (anterior buster and pyloaric dilator neurons), LP (lateral pyloric neurons), and PY (pyloric neurons). This model has a number of non-standard properties that will be described in the following annotated version of the code.\n", 26 | "\n", 27 | "Golowasch, J., Casey, M., Abbott, L. F., & Marder, E. (1999).
\n", 28 | "Network Stability from Activity-Dependent Regulation of Neuronal Conductances.
\n", 29 | "Neural Computation, 11(5), 1079-1096.
\n", 30 | "https://doi.org/10.1162/089976699300016359" 31 | ] 32 | }, 33 | { 34 | "cell_type": "markdown", 35 | "metadata": {}, 36 | "source": [ 37 | "Before describing a model, we set up the Brian simulator:" 38 | ] 39 | }, 40 | { 41 | "cell_type": "code", 42 | "execution_count": null, 43 | "metadata": {}, 44 | "outputs": [], 45 | "source": [ 46 | "# Import names from the the Brian library\n", 47 | "from brian2.only import *" 48 | ] 49 | }, 50 | { 51 | "cell_type": "markdown", 52 | "metadata": {}, 53 | "source": [ 54 | "We now enable the high-performance \"standalone-mode\". By default, the first run statement the code encounters will trigger the automatic compilcation and execution. We disable this feature here (`build_on_run=False`) because our model consists of a sequence of runs. Only after all runs have been defined, we ask Brian to build and execute the simulation code" 55 | ] 56 | }, 57 | { 58 | "cell_type": "code", 59 | "execution_count": null, 60 | "metadata": {}, 61 | "outputs": [], 62 | "source": [ 63 | "set_device('cpp_standalone', build_on_run=False)" 64 | ] 65 | }, 66 | { 67 | "cell_type": "markdown", 68 | "metadata": {}, 69 | "source": [ 70 | "To make simulation runs reproducible, we set the seed of the random number generator." 71 | ] 72 | }, 73 | { 74 | "cell_type": "code", 75 | "execution_count": null, 76 | "metadata": {}, 77 | "outputs": [], 78 | "source": [ 79 | "seed(123456)" 80 | ] 81 | }, 82 | { 83 | "cell_type": "markdown", 84 | "metadata": {}, 85 | "source": [ 86 | "All operations in Brian take place on \"clocks\" that step forward with given time steps. If not defined otherwise (as in this script), operations use the \"default clock\". We set its time step to 0.01ms:" 87 | ] 88 | }, 89 | { 90 | "cell_type": "code", 91 | "execution_count": null, 92 | "metadata": {}, 93 | "outputs": [], 94 | "source": [ 95 | "defaultclock.dt = 0.01*ms" 96 | ] 97 | }, 98 | { 99 | "cell_type": "markdown", 100 | "metadata": {}, 101 | "source": [ 102 | "The neuron's membrane potential in the pyloric network shows slow oscillations with burst of action potentials at its peak. Here, we use a variant of the Hindmarsh-Rose model, reformulated to use physical dimensions instead of unitless variables. This model defines the dynamics of the membrane potential $v$, and of the adaptation variables $w$ and $x$ as follows:\n", 103 | "$$\n", 104 | "\\frac{\\mathrm{d}v}{\\mathrm{d}t} = \\left(\\Delta_Tg\\left(-a\\left(v - v_T\\right)^3 + b\\left(v - v_T\\right)^2\\right) + w - x - I_\\mathrm{fast} - I_\\mathrm{slow}\\right)\\frac{1}{C} \\\\\n", 105 | "\\frac{\\mathrm{d}w}{\\mathrm{d}t} = \\left(c - d\\left(v - v_T\\right)^2 - w\\right)\\frac{1}{\\tau} \\\\\n", 106 | "\\frac{\\mathrm{d}x}{\\mathrm{d}t} = \\left(s\\left(v - v_r\\right) - x\\right)\\frac{1}{\\tau_x}\n", 107 | "$$\n", 108 | "\n", 109 | "In Brian, such equations can be specified as a string, following mathematic notation as closely as possible. The physical dimensions of the variable defined in the respective line has to be specified after a colon; this allows Brian to check for the consistency of the dimensions and therefore avoid the use of incorrect equations:" 110 | ] 111 | }, 112 | { 113 | "cell_type": "code", 114 | "execution_count": null, 115 | "metadata": {}, 116 | "outputs": [], 117 | "source": [ 118 | "eqs = '''\n", 119 | "dv/dt = (Delta_T*g*(-a*(v - v_T)**3 + b*(v - v_T)**2) + w - x - I_fast - I_slow)/C : volt\n", 120 | "dw/dt = (c - d*(v - v_T)**2 - w)/tau : amp\n", 121 | "dx/dt = (s*(v - v_r) - x)/tau_x : amp\n", 122 | "'''" 123 | ] 124 | }, 125 | { 126 | "cell_type": "markdown", 127 | "metadata": {}, 128 | "source": [ 129 | "One particular feature of the pyloric network model in Golowasch et al. (1999) is that not all intrinsic conductances are constant, but some are activity-dependent via the Calcium current. Here, we simplify this dependency by having a Calcium signal that exponentially decays in the absence of spikes (it increases with each spike, see definition later in the script):\n", 130 | "$$\n", 131 | "\\frac{\\mathrm{d}Ca}{\\mathrm{d}t} = -\\frac{Ca}{\\tau_{Ca}}\n", 132 | "$$" 133 | ] 134 | }, 135 | { 136 | "cell_type": "code", 137 | "execution_count": null, 138 | "metadata": {}, 139 | "outputs": [], 140 | "source": [ 141 | "eqs += '''\n", 142 | "dCa/dt = -Ca/tau_Ca : 1\n", 143 | "'''" 144 | ] 145 | }, 146 | { 147 | "cell_type": "markdown", 148 | "metadata": {}, 149 | "source": [ 150 | "Note that this Calcium signal is normalized and therefore dimensionless. We now follow the model of Golowasch et al. (1999) to describe the dependency of two conductances, $s$ and $g$ in our case, on the difference of this Calcium current to a target current via the dynamic variable $z$:\n", 151 | "$$\n", 152 | "\\frac{\\mathrm{d}z}{\\mathrm{d}t} = \\tanh\\left(Ca - Ca_\\mathrm{target}\\right)\\frac{1}{\\tau_z}\\\\\n", 153 | "s = S\\left(1 - \\tanh(z)\\right)\\\\\n", 154 | "g = G\\left(1 + \\tanh(z)\\right)\n", 155 | "$$" 156 | ] 157 | }, 158 | { 159 | "cell_type": "code", 160 | "execution_count": null, 161 | "metadata": {}, 162 | "outputs": [], 163 | "source": [ 164 | "eqs += '''\n", 165 | "s = S*(1 - tanh(z)) : siemens\n", 166 | "g = G*(1 + tanh(z)) : siemens\n", 167 | "dz/dt = tanh(Ca - Ca_target)/tau_z : 1\n", 168 | "'''" 169 | ] 170 | }, 171 | { 172 | "cell_type": "markdown", 173 | "metadata": {}, 174 | "source": [ 175 | "Finally, we note that $I_\\mathrm{fast}$ and $I_\\mathrm{slow}$ are neuron-specific state variables (set by the Synapses later), and that $Ca_\\mathrm{target}$ is a neuron-specific constant. We also add a special integer constant called `label` that will be used to label AB/PD, LP, and PY neurons." 176 | ] 177 | }, 178 | { 179 | "cell_type": "code", 180 | "execution_count": null, 181 | "metadata": {}, 182 | "outputs": [], 183 | "source": [ 184 | "eqs += '''\n", 185 | "I_fast : amp\n", 186 | "I_slow : amp\n", 187 | "Ca_target : 1 (constant)\n", 188 | "label : integer (constant)\n", 189 | "'''" 190 | ] 191 | }, 192 | { 193 | "cell_type": "markdown", 194 | "metadata": {}, 195 | "source": [ 196 | "Our equations refer to a number of constants that are shared across all neurons, we define them as standard Python variables. " 197 | ] 198 | }, 199 | { 200 | "cell_type": "code", 201 | "execution_count": null, 202 | "metadata": {}, 203 | "outputs": [], 204 | "source": [ 205 | "init_time = 2.5*second\n", 206 | "observe_time = 4*second\n", 207 | "adapt_time = 49 * second\n", 208 | "Delta_T = 17.5*mV\n", 209 | "v_T = -40*mV\n", 210 | "tau = 2*ms\n", 211 | "tau_adapt = .02*second\n", 212 | "tau_Ca = 150*ms\n", 213 | "tau_x = 2*second\n", 214 | "v_r = -68*mV\n", 215 | "a = 1/Delta_T**3\n", 216 | "b = 3/Delta_T**2\n", 217 | "d = 2.5*nA/Delta_T**2\n", 218 | "C = 60*pF\n", 219 | "S = 2*nA/Delta_T\n", 220 | "G = 28.5*nS\n", 221 | "tau_z = 5*second\n", 222 | "c = 1.2*nA\n", 223 | "ABPD, LP, PY = 0, 1, 2 # Arbitrary numbers" 224 | ] 225 | }, 226 | { 227 | "cell_type": "markdown", 228 | "metadata": {}, 229 | "source": [ 230 | "Now, we create the neurons that follow the previously defined model, and additionally define what should count as a threshold crossing (`threshold`) and what should happen when it is crossed (`reset`). Note that this model describes the trajectory of the membrane potential during an action potential as part of its equations, it therefore does not reset the membrane potential after a spike as an integrate-and-fire model would. To prevent repeatedly triggering \"spikes\" due to the fact that the membrane potential is above the threshold all the time during the action potential, we state that while the neuron is still above the threshold, it should be considered not able to elicit any more spikes (`refractory`). Finally, we define the numerical integration method to use (`method`), here, a 2nd order Runge-Kutta method." 231 | ] 232 | }, 233 | { 234 | "cell_type": "code", 235 | "execution_count": null, 236 | "metadata": {}, 237 | "outputs": [], 238 | "source": [ 239 | "circuit = NeuronGroup(3, eqs, threshold='v>-20*mV', refractory='v>-20*mV', method='rk2',\n", 240 | " reset='Ca += 0.1')" 241 | ] 242 | }, 243 | { 244 | "cell_type": "markdown", 245 | "metadata": {}, 246 | "source": [ 247 | "We've defined a group of three neurons, each one being of a different type. We set the neurons' label accordingly and set the initial conditions for the variables $v$, $w$, and $z$, as well as the neuron-type dependent values for the constant $Ca_\\mathrm{target}$:" 248 | ] 249 | }, 250 | { 251 | "cell_type": "code", 252 | "execution_count": null, 253 | "metadata": {}, 254 | "outputs": [], 255 | "source": [ 256 | "circuit.label = [ABPD, LP, PY]\n", 257 | "circuit.v = v_r\n", 258 | "circuit.w = '-5*nA*rand()'\n", 259 | "circuit.z = 'rand()*0.2 - 0.1'\n", 260 | "circuit.Ca_target = [0.048, 0.0384, 0.06]" 261 | ] 262 | }, 263 | { 264 | "cell_type": "markdown", 265 | "metadata": {}, 266 | "source": [ 267 | "The predefined `rand()` function returns random number from a uniform distribution between 0 and 1, i.e. $w$ is initialized to be between 0nA and -5nA, and $z$ between -0.1 and 0.1.\n", 268 | "\n", 269 | "For this model, we want to describe two classes of synapses, \"fast\" and \"slow\". Both synaptic currents are graded functions of the presynaptic membrane potential. For the fast synapses, the current is an instantaneous function of both the pre-synaptic and the post-synaptic membrane potential:" 270 | ] 271 | }, 272 | { 273 | "cell_type": "code", 274 | "execution_count": null, 275 | "metadata": {}, 276 | "outputs": [], 277 | "source": [ 278 | "# Synapses\n", 279 | "eqs_fast = '''\n", 280 | "g_fast : siemens (constant)\n", 281 | "I_fast_post = g_fast*(v_post - E_syn)/(1+exp(s_fast*(V_fast-v_pre))) : amp (summed)\n", 282 | "'''\n", 283 | "fast_synapses = Synapses(circuit, circuit, model=eqs_fast)" 284 | ] 285 | }, 286 | { 287 | "cell_type": "markdown", 288 | "metadata": {}, 289 | "source": [ 290 | "The `(summed)` here means that the post-synaptic current will be summed over all currents from synapses targetting the same post-synaptic target. As for neurons, we then define general constants as Python variables:" 291 | ] 292 | }, 293 | { 294 | "cell_type": "code", 295 | "execution_count": null, 296 | "metadata": {}, 297 | "outputs": [], 298 | "source": [ 299 | "s_fast = 0.2/mV\n", 300 | "V_fast = -50*mV\n", 301 | "s_slow = 1/mV\n", 302 | "V_slow = -55*mV\n", 303 | "E_syn = -75*mV\n", 304 | "k_1 = 1/ms" 305 | ] 306 | }, 307 | { 308 | "cell_type": "markdown", 309 | "metadata": {}, 310 | "source": [ 311 | "To establish synapses between the neurons, we can provide a logical condition detailing whether a connection should be created for a specific pair of neurons. This condition can refer to arbitrary pre- and post-synaptic variables or constants. In the following, we make use of the `label` constant that defines the type of each neuron. Given that our simple model only includes one neuron of each type, we could have used the neuron indices instead. However, using a label has the advantage of clearly showing the intent behind the connection pattern and would automatically generalize to a network with multiple neurons per type. Here, we want to establish connections with fast synapses for all pairs of neurons with different type (i.e., don't connect neurons of the same type to each other), but not from PY to AB/PD neurons: " 312 | ] 313 | }, 314 | { 315 | "cell_type": "code", 316 | "execution_count": null, 317 | "metadata": {}, 318 | "outputs": [], 319 | "source": [ 320 | "fast_synapses.connect('label_pre != label_post and not (label_pre == PY and label_post == ABPD)')" 321 | ] 322 | }, 323 | { 324 | "cell_type": "markdown", 325 | "metadata": {}, 326 | "source": [ 327 | "The maximum conductance of each synapse depends on the pre- and post-synaptic neuron types, we assign them accordingly:" 328 | ] 329 | }, 330 | { 331 | "cell_type": "code", 332 | "execution_count": null, 333 | "metadata": {}, 334 | "outputs": [], 335 | "source": [ 336 | "fast_synapses.g_fast['label_pre == ABPD and label_post == LP'] = 0.015*uS\n", 337 | "fast_synapses.g_fast['label_pre == ABPD and label_post == PY'] = 0.005*uS\n", 338 | "fast_synapses.g_fast['label_pre == LP and label_post == ABPD'] = 0.01*uS\n", 339 | "fast_synapses.g_fast['label_pre == LP and label_post == PY'] = 0.02*uS\n", 340 | "fast_synapses.g_fast['label_pre == PY and label_post == LP'] = 0.005*uS" 341 | ] 342 | }, 343 | { 344 | "cell_type": "markdown", 345 | "metadata": {}, 346 | "source": [ 347 | "For the slow synapses, the post-synaptic current depends on the pre-synaptic membrane potential indirectly via the variable $m_\\mathrm{slow}$ (its differential equation is solved via its analytical solution, requested by chosing `method='exact'`):" 348 | ] 349 | }, 350 | { 351 | "cell_type": "code", 352 | "execution_count": null, 353 | "metadata": {}, 354 | "outputs": [], 355 | "source": [ 356 | "eqs_slow = '''\n", 357 | "k_2 : 1/second (constant)\n", 358 | "g_slow : siemens (constant)\n", 359 | "I_slow_post = g_slow*m_slow*(v_post-E_syn) : amp (summed)\n", 360 | "dm_slow/dt = k_1*(1-m_slow)/(1+exp(s_slow*(V_slow-v_pre))) - k_2*m_slow : 1 (clock-driven)\n", 361 | "'''\n", 362 | "slow_synapses = Synapses(circuit, circuit, model=eqs_slow, method='exact')" 363 | ] 364 | }, 365 | { 366 | "cell_type": "markdown", 367 | "metadata": {}, 368 | "source": [ 369 | "Slow synapses are only arising from AB/PD units, and target neurons of all other types:" 370 | ] 371 | }, 372 | { 373 | "cell_type": "code", 374 | "execution_count": null, 375 | "metadata": {}, 376 | "outputs": [], 377 | "source": [ 378 | "slow_synapses.connect('label_pre == ABPD and label_post != ABPD')" 379 | ] 380 | }, 381 | { 382 | "cell_type": "markdown", 383 | "metadata": {}, 384 | "source": [ 385 | "Their maximum conductance depends on the type of the target cell:" 386 | ] 387 | }, 388 | { 389 | "cell_type": "code", 390 | "execution_count": null, 391 | "metadata": {}, 392 | "outputs": [], 393 | "source": [ 394 | "slow_synapses.g_slow['label_post == LP'] = 0.025*uS\n", 395 | "slow_synapses.k_2['label_post == LP'] = 0.03/ms\n", 396 | "slow_synapses.g_slow['label_post == PY'] = 0.015*uS\n", 397 | "slow_synapses.k_2['label_post == PY'] = 0.008/ms" 398 | ] 399 | }, 400 | { 401 | "cell_type": "markdown", 402 | "metadata": {}, 403 | "source": [ 404 | "Before we start the simulation, we state what data we want to record during the simulation. In addition to the spiking activity, we record the membrane potential $v$ for all cells (`record=True`). By default, this monitor would use the same time resolution as the rest of the simulation (0.01 ms), but we reduce the resolution to 0.1ms:" 405 | ] 406 | }, 407 | { 408 | "cell_type": "code", 409 | "execution_count": null, 410 | "metadata": {}, 411 | "outputs": [], 412 | "source": [ 413 | "M = StateMonitor(circuit, ['v'], record=True, dt=.1*ms)\n", 414 | "spikes = SpikeMonitor(circuit)" 415 | ] 416 | }, 417 | { 418 | "cell_type": "markdown", 419 | "metadata": {}, 420 | "source": [ 421 | "To make analysis and plotting easier, we run the simulations in separate parts with the recording initally switched off (`M.active = false`). After a short period (`init_time`) we record the activity for a fixed period (`observe_time`). We then let the network adapt its conductances for a long time (`adapt_time`), without recording its activity. Finally, we record the activity in the adaptated network." 422 | ] 423 | }, 424 | { 425 | "cell_type": "code", 426 | "execution_count": null, 427 | "metadata": {}, 428 | "outputs": [], 429 | "source": [ 430 | "M.active = False\n", 431 | "run(init_time, report='text')\n", 432 | "M.active = True\n", 433 | "run(observe_time, report='text')\n", 434 | "M.active = False\n", 435 | "run(adapt_time, report='text')\n", 436 | "M.active = True\n", 437 | "run(observe_time, report='text')" 438 | ] 439 | }, 440 | { 441 | "cell_type": "markdown", 442 | "metadata": {}, 443 | "source": [ 444 | "In the computationally efficient \"standalone mode\", the above statements describe the simulation protocol without actually launching the compilation and execution process. We do this now:" 445 | ] 446 | }, 447 | { 448 | "cell_type": "code", 449 | "execution_count": null, 450 | "metadata": {}, 451 | "outputs": [], 452 | "source": [ 453 | "device.build(directory='example_1')" 454 | ] 455 | }, 456 | { 457 | "cell_type": "markdown", 458 | "metadata": {}, 459 | "source": [ 460 | "After the simulation finished, we extract the spike trains from the monitor (spiking activity for each neuron) and call a general plotting procedure that we share with the more complex biophysical model." 461 | ] 462 | }, 463 | { 464 | "cell_type": "code", 465 | "execution_count": null, 466 | "metadata": {}, 467 | "outputs": [], 468 | "source": [ 469 | "spike_trains = spikes.spike_trains()" 470 | ] 471 | }, 472 | { 473 | "cell_type": "code", 474 | "execution_count": null, 475 | "metadata": {}, 476 | "outputs": [], 477 | "source": [ 478 | "from example_1_pyloric_net_plot import do_pyloric_net_plot\n", 479 | "do_pyloric_net_plot(spike_trains, M.t, M.v, 'v',\n", 480 | " init_time, observe_time, adapt_time);" 481 | ] 482 | }, 483 | { 484 | "cell_type": "markdown", 485 | "metadata": {}, 486 | "source": [ 487 | "Note that you can zoom and pan the above figure." 488 | ] 489 | } 490 | ], 491 | "metadata": { 492 | "kernelspec": { 493 | "display_name": "Python 3", 494 | "language": "python", 495 | "name": "python3" 496 | }, 497 | "language_info": { 498 | "codemirror_mode": { 499 | "name": "ipython", 500 | "version": 3 501 | }, 502 | "file_extension": ".py", 503 | "mimetype": "text/x-python", 504 | "name": "python", 505 | "nbconvert_exporter": "python", 506 | "pygments_lexer": "ipython3", 507 | "version": "3.6.7" 508 | } 509 | }, 510 | "nbformat": 4, 511 | "nbformat_minor": 2 512 | } 513 | -------------------------------------------------------------------------------- /example_1_pyloric_network_complex.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "### Quickstart\n", 8 | "To run the code below:\n", 9 | "\n", 10 | "1. Click on the cell to select it.\n", 11 | "2. Press `SHIFT+ENTER` on your keyboard or press the play button\n", 12 | " () in the toolbar above.\n", 13 | "\n", 14 | "Feel free to create new cells using the plus button\n", 15 | "(), or pressing `SHIFT+ENTER` while this cell\n", 16 | "is selected." 17 | ] 18 | }, 19 | { 20 | "cell_type": "markdown", 21 | "metadata": {}, 22 | "source": [ 23 | "# Example 1 (Pyloric network of the crustacean stomatogastric ganglion) – biophysically detailed model\n", 24 | "\n", 25 | "This example is equivalent to the [simplified model](example_1_pyloric_network.ipynb), but uses a more biophysically detailed neuron model. For a detailed explanation of the modelling approach and the conversion of equations into Brian syntax, see the comments in that file.\n", 26 | "\n", 27 | "For details about the neuron model, see:\n", 28 | "\n", 29 | "Golowasch, J., Casey, M., Abbott, L. F., & Marder, E. (1999). \n", 30 | "Network Stability from Activity-Dependent Regulation of Neuronal Conductances. \n", 31 | "Neural Computation, 11(5), 1079-1096. \n", 32 | "https://doi.org/10.1162/089976699300016359" 33 | ] 34 | }, 35 | { 36 | "cell_type": "code", 37 | "execution_count": null, 38 | "metadata": {}, 39 | "outputs": [], 40 | "source": [ 41 | "from brian2.only import *\n", 42 | "import numpy as np\n", 43 | "\n", 44 | "set_device('cpp_standalone', build_on_run=False)\n", 45 | "\n", 46 | "defaultclock.dt = 0.01*ms\n", 47 | "\n", 48 | "init_time = 0.5*second\n", 49 | "observe_time = 3*second\n", 50 | "adapt_time = 24 * second\n", 51 | "\n", 52 | "### Class-independent constants\n", 53 | "# Reversal potentials\n", 54 | "E_L = -68*mV\n", 55 | "E_Na = 20*mV\n", 56 | "E_K = -80*mV\n", 57 | "E_Ca = 120*mV\n", 58 | "E_proc = -10*mV\n", 59 | "\n", 60 | "# Capacitance\n", 61 | "C_s = 0.2*nF\n", 62 | "C_a = 0.02*nF\n", 63 | "\n", 64 | "# maximal conductances\n", 65 | "g_E = 10*nS\n", 66 | "g_La = 7.5*nS\n", 67 | "g_Na = 300*nS\n", 68 | "g_Kd = 4*uS\n", 69 | "G_Ca = 0.2*uS\n", 70 | "G_K = 16*uS\n", 71 | "\n", 72 | "# time constants (independent of V)\n", 73 | "tau_h_Ca = 150*ms\n", 74 | "tau_m_A = 0.1*ms\n", 75 | "tau_h_A = 50*ms\n", 76 | "tau_m_proc = 6*ms\n", 77 | "tau_m_Na = 0.025*ms\n", 78 | "tau_z = 5*second\n", 79 | "\n", 80 | "# Synapses\n", 81 | "s_fast = 0.2/mV\n", 82 | "V_fast = -50*mV\n", 83 | "s_slow = 1/mV\n", 84 | "V_slow = -55*mV\n", 85 | "E_syn = -75*mV\n", 86 | "k_1 = 1/ms\n", 87 | "\n", 88 | "### Neuronal equations\n", 89 | "eqs = '''\n", 90 | "# somatic compartment\n", 91 | "dV_s/dt = (-I_syn - I_L - I_Ca - I_K - I_A - I_proc - g_E*(V_s - V_a))/C_s : volt\n", 92 | "\n", 93 | "I_L = g_Ls*(V_s - E_L) : amp\n", 94 | "I_K = g_K*m_K**4*(V_s - E_K) : amp\n", 95 | "I_A = g_A*m_A**3*h_A*(V_s - E_K) : amp\n", 96 | "I_proc = g_proc*m_proc*(V_s - E_proc) : amp\n", 97 | "\n", 98 | "I_syn = I_fast + I_slow: amp\n", 99 | "I_fast : amp\n", 100 | "I_slow : amp\n", 101 | "\n", 102 | "I_Ca = g_Ca*m_Ca**3*h_Ca*(V_s - E_Ca) : amp\n", 103 | "dm_Ca/dt = (m_Ca_inf - m_Ca)/tau_m_Ca : 1\n", 104 | "m_Ca_inf = 1/(1 + exp(0.205/mV*(-61.2*mV - V_s))): 1\n", 105 | "tau_m_Ca = 30*ms -5*ms/(1 + exp(0.2/mV*(-65*mV - V_s))) : second\n", 106 | "dh_Ca/dt = (h_Ca_inf - h_Ca)/tau_h_Ca : 1\n", 107 | "h_Ca_inf = 1/(1 + exp(-0.15/mV*(-75*mV - V_s))) : 1\n", 108 | "\n", 109 | "dm_K/dt = (m_K_inf - m_K)/tau_m_K : 1\n", 110 | "m_K_inf = 1/(1 + exp(0.1/mV*(-35*mV - V_s))) : 1\n", 111 | "tau_m_K = 2*ms + 55*ms/(1 + exp(-0.125/mV*(-54*mV - V_s))) : second\n", 112 | "\n", 113 | "dm_A/dt = (m_A_inf - m_A)/tau_m_A : 1\n", 114 | "m_A_inf = 1/(1 + exp(0.2/mV*(-60*mV - V_s))) : 1\n", 115 | "dh_A/dt = (h_A_inf - h_A)/tau_h_A : 1\n", 116 | "h_A_inf = 1/(1 + exp(-0.18/mV*(-68*mV - V_s))) : 1\n", 117 | "\n", 118 | "dm_proc/dt = (m_proc_inf - m_proc)/tau_m_proc : 1\n", 119 | "m_proc_inf = 1/(1 + exp(0.2/mV*(-55*mV - V_s))) : 1\n", 120 | "\n", 121 | "# axonal compartment\n", 122 | "dV_a/dt = (-g_La*(V_a - E_L) - g_Na*m_Na**3*h_Na*(V_a - E_Na)\n", 123 | " -g_Kd*m_Kd**4*(V_a - E_K) - g_E*(V_a - V_s))/C_a : volt\n", 124 | "\n", 125 | "dm_Na/dt = (m_Na_inf - m_Na)/tau_m_Na : 1\n", 126 | "m_Na_inf = 1/(1 + exp(0.1/mV*(-42.5*mV - V_a))) : 1\n", 127 | "dh_Na/dt = (h_Na_inf - h_Na)/tau_h_Na : 1\n", 128 | "h_Na_inf = 1/(1 + exp(-0.13/mV*(-50*mV - V_a))) : 1\n", 129 | "tau_h_Na = 10*ms/(1 + exp(0.12/mV*(-77*mV - V_a))) : second\n", 130 | "\n", 131 | "dm_Kd/dt = (m_Kd_inf - m_Kd)/tau_m_Kd : 1\n", 132 | "m_Kd_inf = 1/(1 + exp(0.2/mV*(-41*mV - V_a))) : 1\n", 133 | "tau_m_Kd = 12.2*ms + 10.5*ms/(1 + exp(-0.05/mV*(58*mV - V_a))) : second\n", 134 | "\n", 135 | "# class-specific fixed maximal conductances\n", 136 | "g_Ls : siemens (constant)\n", 137 | "g_A : siemens (constant)\n", 138 | "g_proc : siemens (constant)\n", 139 | "\n", 140 | "# Adaptive conductances\n", 141 | "g_Ca = G_Ca/2*(1 + tanh(z)) : siemens\n", 142 | "g_K = G_K/2*(1 - tanh(z)) : siemens\n", 143 | "I_diff = (I_target + I_Ca) : amp\n", 144 | "dz/dt = tanh(I_diff/nA)/tau_z : 1\n", 145 | "I_target : amp (constant)\n", 146 | "\n", 147 | "# neuron class\n", 148 | "label : integer (constant)\n", 149 | "'''\n", 150 | "ABPD, LP, PY = 0, 1, 2\n", 151 | "\n", 152 | "circuit = NeuronGroup(3, eqs, method='rk2',\n", 153 | " threshold='m_Na > 0.5', refractory='m_Na > 0.5')\n", 154 | "\n", 155 | "# class-specific constants\n", 156 | "circuit.label = [ABPD, LP, PY]\n", 157 | "circuit.I_target = [0.4, 0.3, 0.5]*nA\n", 158 | "circuit.g_Ls = [30, 25, 15]*nS\n", 159 | "circuit.g_A = [450, 100, 250]*nS\n", 160 | "circuit.g_proc = [6, 8, 0]*nS\n", 161 | "\n", 162 | "# Initial conditions\n", 163 | "circuit.V_s = E_L\n", 164 | "circuit.V_a = E_L\n", 165 | "circuit.m_Ca = 'm_Ca_inf'\n", 166 | "circuit.h_Ca = 'h_Ca_inf'\n", 167 | "circuit.m_K = 'm_K_inf'\n", 168 | "circuit.m_A = 'm_A_inf'\n", 169 | "circuit.h_A = 'h_A_inf'\n", 170 | "circuit.m_proc = 'm_proc_inf'\n", 171 | "circuit.m_Na = 'm_Na_inf'\n", 172 | "circuit.h_Na = 'h_Na_inf'\n", 173 | "circuit.m_Kd = 'm_Kd_inf'" 174 | ] 175 | }, 176 | { 177 | "cell_type": "markdown", 178 | "metadata": {}, 179 | "source": [ 180 | "The definition of the synapses and the simulation protocol are identical to the simplified model:" 181 | ] 182 | }, 183 | { 184 | "cell_type": "code", 185 | "execution_count": null, 186 | "metadata": {}, 187 | "outputs": [], 188 | "source": [ 189 | "eqs_fast = '''\n", 190 | "g_fast : siemens (constant)\n", 191 | "I_fast_post = g_fast*(V_s_post - E_syn)/(1+exp(s_fast*(V_fast-V_s_pre))) : amp (summed)\n", 192 | "'''\n", 193 | "fast_synapses = Synapses(circuit, circuit, model=eqs_fast)\n", 194 | "fast_synapses.connect('label_pre != label_post and not (label_pre == PY and label_post == ABPD)')\n", 195 | "fast_synapses.g_fast['label_pre == ABPD and label_post == LP'] = 0.015*uS\n", 196 | "fast_synapses.g_fast['label_pre == ABPD and label_post == PY'] = 0.005*uS\n", 197 | "fast_synapses.g_fast['label_pre == LP and label_post == ABPD'] = 0.01*uS\n", 198 | "fast_synapses.g_fast['label_pre == LP and label_post == PY'] = 0.02*uS\n", 199 | "fast_synapses.g_fast['label_pre == PY and label_post == LP'] = 0.005*uS\n", 200 | "\n", 201 | "eqs_slow = '''\n", 202 | "k_2 : 1/second (constant)\n", 203 | "g_slow : siemens (constant)\n", 204 | "I_slow_post = g_slow*m_slow*(V_s_post-E_syn) : amp (summed)\n", 205 | "dm_slow/dt = k_1*(1-m_slow)/(1+exp(s_slow*(V_slow-V_s_pre))) - k_2*m_slow : 1 (clock-driven)\n", 206 | "'''\n", 207 | "slow_synapses = Synapses(circuit, circuit, model=eqs_slow, method='exact')\n", 208 | "slow_synapses.connect('label_pre == ABPD and label_post != ABPD')\n", 209 | "slow_synapses.g_slow['label_post == LP'] = 0.025*uS\n", 210 | "slow_synapses.k_2['label_post == LP'] = 0.03/ms\n", 211 | "slow_synapses.g_slow['label_post == PY'] = 0.015*uS\n", 212 | "slow_synapses.k_2['label_post == PY'] = 0.008/ms\n", 213 | "\n", 214 | "\n", 215 | "M = StateMonitor(circuit, 'V_s', record=True)\n", 216 | "spikes = SpikeMonitor(circuit)\n", 217 | "\n", 218 | "M.active = False\n", 219 | "run(init_time, report='text')\n", 220 | "M.active = True\n", 221 | "run(observe_time, report='text')\n", 222 | "M.active = False\n", 223 | "run(adapt_time, report='text')\n", 224 | "M.active = True\n", 225 | "run(observe_time, report='text')\n", 226 | "device.build(directory='example_1_complex')" 227 | ] 228 | }, 229 | { 230 | "cell_type": "markdown", 231 | "metadata": {}, 232 | "source": [ 233 | "We use the same analysis/plotting procedure as in the simplified model:" 234 | ] 235 | }, 236 | { 237 | "cell_type": "code", 238 | "execution_count": null, 239 | "metadata": {}, 240 | "outputs": [], 241 | "source": [ 242 | "spike_trains = spikes.spike_trains()\n", 243 | "\n", 244 | "# Plot\n", 245 | "from example_1_pyloric_net_plot import do_pyloric_net_plot\n", 246 | "do_pyloric_net_plot(spike_trains, M.t, M.V_s, 'V_s',\n", 247 | " init_time, observe_time, adapt_time);" 248 | ] 249 | } 250 | ], 251 | "metadata": { 252 | "kernelspec": { 253 | "display_name": "Python 3", 254 | "language": "python", 255 | "name": "python3" 256 | }, 257 | "language_info": { 258 | "codemirror_mode": { 259 | "name": "ipython", 260 | "version": 3 261 | }, 262 | "file_extension": ".py", 263 | "mimetype": "text/x-python", 264 | "name": "python", 265 | "nbconvert_exporter": "python", 266 | "pygments_lexer": "ipython3", 267 | "version": "3.6.7" 268 | } 269 | }, 270 | "nbformat": 4, 271 | "nbformat_minor": 2 272 | } 273 | -------------------------------------------------------------------------------- /example_2_eye_movements.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "### Quickstart\n", 8 | "To run the code below:\n", 9 | "\n", 10 | "1. Click on the cell to select it.\n", 11 | "2. Press `SHIFT+ENTER` on your keyboard or press the play button\n", 12 | " () in the toolbar above.\n", 13 | "\n", 14 | "Feel free to create new cells using the plus button\n", 15 | "(), or pressing `SHIFT+ENTER` while this cell\n", 16 | "is selected." 17 | ] 18 | }, 19 | { 20 | "cell_type": "markdown", 21 | "metadata": {}, 22 | "source": [ 23 | "# Example 2 (Smooth pursuit eye movements)\n", 24 | "This is an idealized model of the smooth pursuit reflex, including two ocular muscles, a moving visual stimulus and spiking neural control." 25 | ] 26 | }, 27 | { 28 | "cell_type": "code", 29 | "execution_count": null, 30 | "metadata": {}, 31 | "outputs": [], 32 | "source": [ 33 | "from brian2 import *\n", 34 | "seed(79620)" 35 | ] 36 | }, 37 | { 38 | "cell_type": "markdown", 39 | "metadata": {}, 40 | "source": [ 41 | "Each of the two antagonistic ocular muscles is modelled as a spring of elasticity $k$ and some friction. To simplify, we consider that the eye moves laterally, rather than rotate. If $x$ is the position of the eye with 0 being the center, then the lengths of the springs are $L+x$ and $L-x$. The dynamics of the eye is then given by a second-order differential equation:\n", 42 | "$$ m\\frac{d^2x}{dt^2} = - k\\left(\\left(L+x\\right)-x_L\\right) + k\\left(\\left(L-x\\right)-x_R\\right) - f\\frac{dx}{dt}$$\n", 43 | "or:\n", 44 | "$$ m\\frac{d^2x}{dt^2} = k(x_L-x_R-2x) - f\\frac{dx}{dt}$$\n", 45 | "\n", 46 | "We see that $x_0 = \\frac{1}{2}(x_L-x_R)$ is the equilibrium position of the eye. Here we have assumed that spring elasticities are identical. We can rewrite this equation with just two parameters $\\alpha$ and $\\beta$:\n", 47 | "$$ \\frac{d^2x}{dt^2} = \\alpha(x_0 - x) - \\beta\\frac{dx}{dt}$$\n", 48 | "\n", 49 | "We will assume that eye position can move between -1 and 1.\n", 50 | "\n", 51 | "We consider that the resting length is the variable on which motoneurons act. Each spike from a motoneuron produces a waveform of contraction (\"twitch\"), i.e., a change in resting length. We consider that contractions add linearly, and resting lengths relax exponentially. By linearity it follows that we can simply express the action of motoneurons on the equilibrium position of the eye $x_0$, which relaxes exponentially to the center position 0.\n", 52 | "\n", 53 | "Finally, we consider a visual object that performs a random walk according to an Ornstein–Uhlenbeck with 0 as the central location." 54 | ] 55 | }, 56 | { 57 | "cell_type": "code", 58 | "execution_count": null, 59 | "metadata": {}, 60 | "outputs": [], 61 | "source": [ 62 | "alpha = (1/(50*ms))**2 # characteristic relaxation time is 50 ms\n", 63 | "beta = 1/(50*ms) # friction parameter\n", 64 | "tau_muscle = 20*ms # relaxation time of muscle contraction\n", 65 | "tau_object = 500*ms # time constant of object movement\n", 66 | "\n", 67 | "eqs_eye = '''\n", 68 | "dx/dt = velocity : 1\n", 69 | "dvelocity/dt = alpha*(x0-x)-beta*velocity : 1/second\n", 70 | "dx0/dt = -x0/tau_muscle : 1\n", 71 | "dx_object/dt = (noise - x_object)/tau_object: 1\n", 72 | "dnoise/dt = -noise/tau_object + tau_object**-0.5*xi : 1\n", 73 | "'''\n", 74 | "eye = NeuronGroup(1, model=eqs_eye, method='euler')" 75 | ] 76 | }, 77 | { 78 | "cell_type": "markdown", 79 | "metadata": {}, 80 | "source": [ 81 | "We now define two motoneurons, one for each muscle:" 82 | ] 83 | }, 84 | { 85 | "cell_type": "code", 86 | "execution_count": null, 87 | "metadata": {}, 88 | "outputs": [], 89 | "source": [ 90 | "taum = 20*ms\n", 91 | "motoneurons = NeuronGroup(2, model= 'dv/dt = -v/taum : 1', threshold = 'v>1',\n", 92 | " reset = 'v=0', refractory = 5*ms, method='exact')" 93 | ] 94 | }, 95 | { 96 | "cell_type": "markdown", 97 | "metadata": {}, 98 | "source": [ 99 | "The motoneurons project to the eye, and each spike produces a small contraction." 100 | ] 101 | }, 102 | { 103 | "cell_type": "code", 104 | "execution_count": null, 105 | "metadata": {}, 106 | "outputs": [], 107 | "source": [ 108 | "motosynapses = Synapses(motoneurons, eye, model = 'w : 1', on_pre = 'x0+=w')\n", 109 | "motosynapses.connect() # connects all motoneurons to the eye\n", 110 | "motosynapses.w = [-0.5,0.5]" 111 | ] 112 | }, 113 | { 114 | "cell_type": "markdown", 115 | "metadata": {}, 116 | "source": [ 117 | "We now implement the sensory neurons, which we simplify by considering spiking neurons which directly respond to light, i.e they represent both photoreceptors and retinal ganglion cells. \n", 118 | "TODO: Talk about Gaussian dependence, et.c" 119 | ] 120 | }, 121 | { 122 | "cell_type": "code", 123 | "execution_count": null, 124 | "metadata": {}, 125 | "outputs": [], 126 | "source": [ 127 | "N = 20\n", 128 | "width = 2./N # width of receptive field\n", 129 | "gain = 4.\n", 130 | "eqs_retina = '''\n", 131 | "I = gain*exp(-((x_object-x_eye-x_neuron)/width)**2) : 1\n", 132 | "x_neuron : 1 (constant)\n", 133 | "x_object : 1 (linked) # position of the object\n", 134 | "x_eye : 1 (linked) # position of the eye\n", 135 | "dv/dt = (I-(1+gs)*v)/taum : 1\n", 136 | "gs : 1 # total synaptic conductance\n", 137 | "'''\n", 138 | "retina = NeuronGroup(N, model = eqs_retina, threshold = 'v>1', reset = 'v=0', method='exact')\n", 139 | "retina.v = 'rand()'\n", 140 | "retina.x_eye = linked_var(eye, 'x')\n", 141 | "retina.x_object = linked_var(eye, 'x_object')\n", 142 | "retina.x_neuron = '-1.0 + 2.0*i/(N-1)'" 143 | ] 144 | }, 145 | { 146 | "cell_type": "markdown", 147 | "metadata": {}, 148 | "source": [ 149 | "Finally we connect sensory neurons to motoneurons. Sensory neurons on each hemifield connects to the corresponding motoneuron, with a strength that scales with eccentricity:" 150 | ] 151 | }, 152 | { 153 | "cell_type": "code", 154 | "execution_count": null, 155 | "metadata": {}, 156 | "outputs": [], 157 | "source": [ 158 | "sensorimotor_synapses = Synapses(retina, motoneurons, model = 'w : 1 (constant)', on_pre = 'v+=w')\n", 159 | "sensorimotor_synapses.connect(j = 'int(x_neuron_pre > 0)')\n", 160 | "sensorimotor_synapses.w = '20*abs(x_neuron_pre)/N_pre'" 161 | ] 162 | }, 163 | { 164 | "cell_type": "markdown", 165 | "metadata": {}, 166 | "source": [ 167 | "We record the position of the eye, of the object, and spikes produced by the retina and motoneurons:" 168 | ] 169 | }, 170 | { 171 | "cell_type": "code", 172 | "execution_count": null, 173 | "metadata": {}, 174 | "outputs": [], 175 | "source": [ 176 | "M = StateMonitor(eye, ('x', 'x0', 'x_object'), record = True)\n", 177 | "S_retina = SpikeMonitor(retina)\n", 178 | "S_motoneurons = SpikeMonitor(motoneurons)" 179 | ] 180 | }, 181 | { 182 | "cell_type": "markdown", 183 | "metadata": {}, 184 | "source": [ 185 | "We now can run the simulation:" 186 | ] 187 | }, 188 | { 189 | "cell_type": "code", 190 | "execution_count": null, 191 | "metadata": {}, 192 | "outputs": [], 193 | "source": [ 194 | "run(10*second, report='text')" 195 | ] 196 | }, 197 | { 198 | "cell_type": "markdown", 199 | "metadata": {}, 200 | "source": [ 201 | "Finally, we plot the results" 202 | ] 203 | }, 204 | { 205 | "cell_type": "code", 206 | "execution_count": null, 207 | "metadata": {}, 208 | "outputs": [], 209 | "source": [ 210 | "from plotly import tools\n", 211 | "from plotly.offline import iplot, init_notebook_mode\n", 212 | "import plotly.graph_objs as go\n", 213 | "\n", 214 | "init_notebook_mode(connected=True)\n", 215 | "\n", 216 | "fig = tools.make_subplots(3, 1, specs=[[{'rowspan': 2}], [None], [{}]],\n", 217 | " shared_xaxes=True, print_grid=False)\n", 218 | "\n", 219 | "trace = go.Scatter(x=S_retina.t/second,\n", 220 | " y=S_retina.i,\n", 221 | " marker={'symbol': 'line-ns', 'line': {'width': 1, 'color':'black'}},\n", 222 | " mode='markers',\n", 223 | " name='retina',\n", 224 | " showlegend=False)\n", 225 | "fig.append_trace(trace, 1, 1)\n", 226 | "motoneuron_spikes = S_motoneurons.spike_trains()\n", 227 | "trace = go.Scatter(x=motoneuron_spikes[0]/second,\n", 228 | " y=np.ones(S_motoneurons.count[0])*N,\n", 229 | " marker={'symbol': 'line-ns', 'line': {'width': 1, 'color':'#1f77b4'},\n", 230 | " 'color':'#1f77b4'},\n", 231 | " mode='markers',\n", 232 | " name='left motoneuron',\n", 233 | " showlegend=False)\n", 234 | "fig.append_trace(trace, 1, 1)\n", 235 | "trace = go.Scatter(x=motoneuron_spikes[1]/second,\n", 236 | " y=np.ones(S_motoneurons.count[1])*(N+1),\n", 237 | " marker={'symbol': 'line-ns', 'line': {'width': 1, 'color':'#ff7f03'},\n", 238 | " 'color':'#ff7f03'},\n", 239 | " mode='markers',\n", 240 | " name='right motoneuron',\n", 241 | " showlegend=False)\n", 242 | "fig.append_trace(trace, 1, 1)\n", 243 | "\n", 244 | "trace = go.Scatter(x=M.t/second,\n", 245 | " y=M.x[0],\n", 246 | " mode='lines',\n", 247 | " line={'color': 'black'},\n", 248 | " name='eye')\n", 249 | "fig.append_trace(trace, 3, 1)\n", 250 | "trace = go.Scatter(x=M.t/second,\n", 251 | " y=M.x_object[0],\n", 252 | " mode='lines',\n", 253 | " line={'color': '#2ca02c'},\n", 254 | " name='object')\n", 255 | "fig.append_trace(trace, 3, 1)\n", 256 | "\n", 257 | "fig['layout'].update(xaxis1={'showline': False,\n", 258 | " 'zeroline': False,\n", 259 | " 'title': 'time (in s)'},\n", 260 | " yaxis1={'title': 'neuron index',\n", 261 | " 'showticklabels': False,\n", 262 | " 'showline': True},\n", 263 | " yaxis2={'tickmode': 'array',\n", 264 | " 'ticktext': ['left', 'right'],\n", 265 | " 'tickvals': [-1, 1],\n", 266 | " 'range': [-1.05, 1.05],\n", 267 | " 'zeroline': True,\n", 268 | " 'showline': True}\n", 269 | " )\n", 270 | "iplot(fig)" 271 | ] 272 | } 273 | ], 274 | "metadata": { 275 | "kernelspec": { 276 | "display_name": "Python 3", 277 | "language": "python", 278 | "name": "python3" 279 | }, 280 | "language_info": { 281 | "codemirror_mode": { 282 | "name": "ipython", 283 | "version": 3 284 | }, 285 | "file_extension": ".py", 286 | "mimetype": "text/x-python", 287 | "name": "python", 288 | "nbconvert_exporter": "python", 289 | "pygments_lexer": "ipython3", 290 | "version": "3.6.7" 291 | } 292 | }, 293 | "nbformat": 4, 294 | "nbformat_minor": 2 295 | } 296 | -------------------------------------------------------------------------------- /example_2_eye_movements_interactive.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "### Quickstart\n", 8 | "To run the code below:\n", 9 | "\n", 10 | "1. Click on the cell to select it.\n", 11 | "2. Press `SHIFT+ENTER` on your keyboard or press the play button\n", 12 | " () in the toolbar above.\n", 13 | "\n", 14 | "Feel free to create new cells using the plus button\n", 15 | "(), or pressing `SHIFT+ENTER` while this cell\n", 16 | "is selected." 17 | ] 18 | }, 19 | { 20 | "cell_type": "markdown", 21 | "metadata": {}, 22 | "source": [ 23 | "# Example 2 (Smooth pursuit eye movements) – interactive version\n", 24 | "\n", 25 | "This is an interactive verison of the idealized model of the smooth pursuit reflex. This version does not explain the model itself, but shows how Brian's \"runtime mode\" can be used to interact with a running simulation. In this mode, the generated code based on the model descriptions is seemlessly integrated with the Python environment and can execute arbitrary Python code at any point during the simulation via a specially annotated function, called a \"network operation\".\n", 26 | "\n", 27 | "For a non-interactive version of this example which generates the article's figure see [this notebook](example_2_eye_movements.ipynb).\n", 28 | "\n", 29 | "**This version uses the *plotly* library for consistency with the other examples. However, updating an existing figure is slower than with the *matplotlib* library, so it is not an ideal solution for this example. For a version based on *matplotlib*, see [this notebook](example_2_eye_movements_interactive_matplotlib.ipynb)**" 30 | ] 31 | }, 32 | { 33 | "cell_type": "code", 34 | "execution_count": null, 35 | "metadata": {}, 36 | "outputs": [], 37 | "source": [ 38 | "# Needs ipywidgets\n", 39 | "import ipywidgets as widgets\n", 40 | "import threading\n", 41 | "from brian2 import *" 42 | ] 43 | }, 44 | { 45 | "cell_type": "markdown", 46 | "metadata": {}, 47 | "source": [ 48 | "The model itself (mostly identical to the [non-interactive example](example_2_eye_movements.ipynb), except that some of the constants are included as parameters in the equation and can therefore change during the simulation):" 49 | ] 50 | }, 51 | { 52 | "cell_type": "code", 53 | "execution_count": null, 54 | "metadata": {}, 55 | "outputs": [], 56 | "source": [ 57 | "alpha = (1/(50*ms))**2 # characteristic relaxation time is 50 ms\n", 58 | "beta = 1/(50*ms) # friction parameter\n", 59 | "\n", 60 | "eqs_eye = '''\n", 61 | "dx/dt = velocity : 1\n", 62 | "dvelocity/dt = alpha*(x0-x)-beta*velocity : 1/second\n", 63 | "dx0/dt = -x0/tau_muscle : 1\n", 64 | "dx_object/dt = (noise - x_object)/tau_object: 1\n", 65 | "dnoise/dt = -noise/tau_object + tau_object**-0.5*xi : 1\n", 66 | "tau_object : second\n", 67 | "tau_muscle : second\n", 68 | "'''\n", 69 | "eye = NeuronGroup(1, model=eqs_eye, method='euler')\n", 70 | "taum = 20*ms\n", 71 | "motoneurons = NeuronGroup(2, model= 'dv/dt = -v/taum : 1', threshold = 'v>1',\n", 72 | " reset = 'v=0', refractory = 5*ms, method='exact')\n", 73 | "motosynapses = Synapses(motoneurons, eye, model = 'w : 1', on_pre = 'x0+=w')\n", 74 | "motosynapses.connect() # connects all motoneurons to the eye\n", 75 | "motosynapses.w = [-0.5,0.5]\n", 76 | "N = 20\n", 77 | "width = 2./N # width of receptive field\n", 78 | "gain = 4.\n", 79 | "eqs_retina = '''\n", 80 | "I = gain*exp(-((x_object-x_eye-x_neuron)/width)**2) : 1\n", 81 | "x_neuron : 1 (constant)\n", 82 | "x_object : 1 (linked) # position of the object\n", 83 | "x_eye : 1 (linked) # position of the eye\n", 84 | "dv/dt = (I-(1+gs)*v)/taum : 1\n", 85 | "gs : 1 # total synaptic conductance\n", 86 | "'''\n", 87 | "retina = NeuronGroup(N, model = eqs_retina, threshold = 'v>1', reset = 'v=0', method='exact')\n", 88 | "retina.v = 'rand()'\n", 89 | "retina.x_eye = linked_var(eye, 'x')\n", 90 | "retina.x_object = linked_var(eye, 'x_object')\n", 91 | "retina.x_neuron = '-1.0 + 2.0*i/(N-1)'\n", 92 | "sensorimotor_synapses = Synapses(retina, motoneurons, model = 'w : 1 (constant)', on_pre = 'v+=w')\n", 93 | "sensorimotor_synapses.connect(j = 'int(x_neuron_pre > 0)')\n", 94 | "sensorimotor_synapses.w = '20*abs(x_neuron_pre)/N_pre'\n", 95 | "M = StateMonitor(eye, ('x', 'x0', 'x_object'), record = True)\n", 96 | "S_retina = SpikeMonitor(retina)\n", 97 | "S_motoneurons = SpikeMonitor(motoneurons)\n" 98 | ] 99 | }, 100 | { 101 | "cell_type": "markdown", 102 | "metadata": {}, 103 | "source": [ 104 | "We create an empty plot that will be updated during the run:" 105 | ] 106 | }, 107 | { 108 | "cell_type": "code", 109 | "execution_count": null, 110 | "metadata": {}, 111 | "outputs": [], 112 | "source": [ 113 | "from plotly import tools\n", 114 | "from plotly.offline import iplot, init_notebook_mode\n", 115 | "import plotly.graph_objs as go\n", 116 | "\n", 117 | "init_notebook_mode(connected=True)\n", 118 | "\n", 119 | "fig = tools.make_subplots(3, 1, specs=[[{'rowspan': 2}], [None], [{}]],\n", 120 | " shared_xaxes=True, print_grid=False)\n", 121 | "\n", 122 | "retina_spikes = go.Scattergl(x=[],\n", 123 | " y=[],\n", 124 | " marker={'symbol': 'line-ns', 'line': {'width': 1, 'color':'black'}},\n", 125 | " mode='markers',\n", 126 | " name='retina',\n", 127 | " showlegend=False)\n", 128 | "fig.append_trace(retina_spikes, 1, 1)\n", 129 | "left_spikes = go.Scattergl(x=[],\n", 130 | " y=[],\n", 131 | " marker={'symbol': 'line-ns', 'line': {'width': 1, 'color':'#1f77b4'},\n", 132 | " 'color':'#1f77b4'},\n", 133 | " mode='markers',\n", 134 | " name='left motoneuron',\n", 135 | " showlegend=False)\n", 136 | "fig.append_trace(left_spikes, 1, 1)\n", 137 | "right_spikes = go.Scattergl(x=[],\n", 138 | " y=[],\n", 139 | " marker={'symbol': 'line-ns', 'line': {'width': 1, 'color':'#ff7f03'},\n", 140 | " 'color':'#ff7f03'},\n", 141 | " mode='markers',\n", 142 | " name='right motoneuron',\n", 143 | " showlegend=False)\n", 144 | "fig.append_trace(right_spikes, 1, 1)\n", 145 | "\n", 146 | "eye_position = go.Scattergl(x=[],\n", 147 | " y=[],\n", 148 | " mode='lines',\n", 149 | " line={'color': 'black'},\n", 150 | " name='eye')\n", 151 | "fig.append_trace(eye_position, 3, 1)\n", 152 | "object_position = go.Scattergl(x=[],\n", 153 | " y=[],\n", 154 | " mode='lines',\n", 155 | " line={'color': '#2ca02c'},\n", 156 | " name='object')\n", 157 | "fig.append_trace(object_position, 3, 1)\n", 158 | "\n", 159 | "fig['layout'].update(xaxis1={'showline': False,\n", 160 | " 'zeroline': False,\n", 161 | " 'title': 'time (in s)',\n", 162 | " 'range': (0, 10),\n", 163 | " 'ticktext': ['-10', '-8', '-6', '-4', '-2', '0'],\n", 164 | " 'tickvals': [0, 2, 4, 6, 8, 10]},\n", 165 | " yaxis1={'title': 'neuron index',\n", 166 | " 'showticklabels': False,\n", 167 | " 'showline': True,\n", 168 | " 'range': (0, N+2)},\n", 169 | " yaxis2={'tickmode': 'array',\n", 170 | " 'ticktext': ['left', 'right'],\n", 171 | " 'tickvals': [-1, 1],\n", 172 | " 'range': [-1.05, 1.05],\n", 173 | " 'zeroline': True,\n", 174 | " 'showline': True}\n", 175 | " )\n", 176 | "fig_widget = go.FigureWidget(fig)\n", 177 | "retina_spikes, left_spikes, right_spikes, eye_position, object_position = fig_widget.data" 178 | ] 179 | }, 180 | { 181 | "cell_type": "markdown", 182 | "metadata": {}, 183 | "source": [ 184 | "We now create interactive widgets that the user can use to start/stop the simulation, as well as for setting certain simulation parameters." 185 | ] 186 | }, 187 | { 188 | "cell_type": "code", 189 | "execution_count": null, 190 | "metadata": {}, 191 | "outputs": [], 192 | "source": [ 193 | "time_label = widgets.Label(value='Time: 0 s')\n", 194 | "start_stop_button = widgets.Button(tooltip='Start simulation', icon='play')\n", 195 | "\n", 196 | "tau_obj_slider = widgets.FloatSlider(orientation='horizontal', description='tau_object',\n", 197 | " value=500, min=100, max=1000)\n", 198 | "tau_muscle_slider = widgets.FloatSlider(orientation='horizontal', description='tau_muscle',\n", 199 | " value=20, min=5, max=100)\n", 200 | "weight_slider = widgets.FloatSlider(orientation='horizontal', description='w_muscle',\n", 201 | " value=0.5, min=0, max=2)\n", 202 | "sliders = widgets.VBox([widgets.HBox([time_label, start_stop_button]),\n", 203 | " tau_obj_slider, tau_muscle_slider, weight_slider])\n", 204 | "layout = widgets.HBox([fig_widget, sliders])" 205 | ] 206 | }, 207 | { 208 | "cell_type": "markdown", 209 | "metadata": {}, 210 | "source": [ 211 | "We interact with the running simulation via a \"network operation\", a Python function that will be regularly called by Brian during the simulation run (here, every 100ms of biological time). This function can access arbitrary attributes of the model to get or set their values. We use this here to 1) update the plot with the data from the last second and 2) set parameters of the model to the values requested by the user." 212 | ] 213 | }, 214 | { 215 | "cell_type": "code", 216 | "execution_count": null, 217 | "metadata": {}, 218 | "outputs": [], 219 | "source": [ 220 | "should_stop = False\n", 221 | "@network_operation(dt=500*ms)\n", 222 | "def plot_output(t):\n", 223 | " with fig_widget.batch_update():\n", 224 | " cutoff = (t - 10*second)\n", 225 | " # Plot the data of the last 10 seconds\n", 226 | " indices = S_retina.t > cutoff\n", 227 | " retina_spikes.x = (S_retina.t[indices] - cutoff)/second\n", 228 | " retina_spikes.y = S_retina.i[indices]\n", 229 | " motoneuron_trains = S_motoneurons.spike_trains()\n", 230 | " to_plot = motoneuron_trains[0][motoneuron_trains[0] > cutoff]\n", 231 | " left_spikes.x = (to_plot - cutoff)/second\n", 232 | " left_spikes.y = np.ones(len(to_plot))*N\n", 233 | " to_plot = motoneuron_trains[1][motoneuron_trains[1] > cutoff]\n", 234 | " right_spikes.x = (to_plot - cutoff)/second\n", 235 | " right_spikes.y = np.ones(len(to_plot))*(N+1)\n", 236 | " indices = M.t > cutoff\n", 237 | " eye_position.x = (M.t[indices] - cutoff)/second\n", 238 | " eye_position.y = M.x[0][indices]\n", 239 | " object_position.x = (M.t[indices] - cutoff)/second\n", 240 | " object_position.y = M.x_object[0][indices]\n", 241 | " time_label.value = 'Time: {:.1f}s'.format(float(t[:]))\n", 242 | " # Set the simulation parameters according to user settings\n", 243 | " eye.tau_object = tau_obj_slider.value*ms\n", 244 | " eye.tau_muscle = tau_muscle_slider.value*ms\n", 245 | " motosynapses.w = [-weight_slider.value, weight_slider.value]\n", 246 | " if should_stop:\n", 247 | " net.stop()" 248 | ] 249 | }, 250 | { 251 | "cell_type": "markdown", 252 | "metadata": {}, 253 | "source": [ 254 | "We store the model and the \"network operation\" in a `Network` object, and store its current state to allow for repeated execution." 255 | ] 256 | }, 257 | { 258 | "cell_type": "code", 259 | "execution_count": null, 260 | "metadata": {}, 261 | "outputs": [], 262 | "source": [ 263 | "net = Network(collect())\n", 264 | "net.store()" 265 | ] 266 | }, 267 | { 268 | "cell_type": "markdown", 269 | "metadata": {}, 270 | "source": [ 271 | "We now define two helper functions used to start/stop simulations. The actual simulation will be run in a background thread so that the user interface stays reactive while the simulation is running:" 272 | ] 273 | }, 274 | { 275 | "cell_type": "code", 276 | "execution_count": null, 277 | "metadata": {}, 278 | "outputs": [], 279 | "source": [ 280 | "def do_run(runtime):\n", 281 | " net.restore()\n", 282 | " net.run(runtime)\n", 283 | "running = False\n", 284 | "def button_pressed(b):\n", 285 | " global running\n", 286 | " global should_stop\n", 287 | " if running:\n", 288 | " should_stop = True\n", 289 | " running = False\n", 290 | " start_stop_button.tooltip = 'Start simulation'\n", 291 | " start_stop_button.icon = 'play'\n", 292 | " else:\n", 293 | " should_stop = False\n", 294 | " running = True\n", 295 | " time_label.value = 'starting...'\n", 296 | " start_stop_button.tooltip = 'Stop simulation'\n", 297 | " start_stop_button.icon = 'stop'\n", 298 | " thread = threading.Thread(target=do_run, args=(100*second, ))\n", 299 | " thread.start()\n", 300 | "start_stop_button.on_click(button_pressed)" 301 | ] 302 | }, 303 | { 304 | "cell_type": "markdown", 305 | "metadata": {}, 306 | "source": [ 307 | "We are now ready to display the plot and user interface, which can then be used to start the simulation and interact with the simulation parameters:" 308 | ] 309 | }, 310 | { 311 | "cell_type": "code", 312 | "execution_count": null, 313 | "metadata": {}, 314 | "outputs": [], 315 | "source": [ 316 | "display(layout)" 317 | ] 318 | } 319 | ], 320 | "metadata": { 321 | "kernelspec": { 322 | "display_name": "Python 3", 323 | "language": "python", 324 | "name": "python3" 325 | }, 326 | "language_info": { 327 | "codemirror_mode": { 328 | "name": "ipython", 329 | "version": 3 330 | }, 331 | "file_extension": ".py", 332 | "mimetype": "text/x-python", 333 | "name": "python", 334 | "nbconvert_exporter": "python", 335 | "pygments_lexer": "ipython3", 336 | "version": "3.6.7" 337 | } 338 | }, 339 | "nbformat": 4, 340 | "nbformat_minor": 2 341 | } 342 | -------------------------------------------------------------------------------- /example_2_eye_movements_interactive_matplotlib.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "### Quickstart\n", 8 | "To run the code below:\n", 9 | "\n", 10 | "1. Click on the cell to select it.\n", 11 | "2. Press `SHIFT+ENTER` on your keyboard or press the play button\n", 12 | " () in the toolbar above.\n", 13 | "\n", 14 | "Feel free to create new cells using the plus button\n", 15 | "(), or pressing `SHIFT+ENTER` while this cell\n", 16 | "is selected." 17 | ] 18 | }, 19 | { 20 | "cell_type": "markdown", 21 | "metadata": {}, 22 | "source": [ 23 | "# Example 2 (Smooth pursuit eye movements) – interactive version based on *matplotlib*\n", 24 | "\n", 25 | "\n", 26 | "This is an interactive verison of the idealized model of the smooth pursuit reflex. This version does not explain the model itself, but shows how Brian's \"runtime mode\" can be used to interact with a running simulation. In this mode, the generated code based on the model descriptions is seemlessly integrated with the Python environment and can execute arbitrary Python code at any point during the simulation via a specially annotated function, called a \"network operation\".\n", 27 | "\n", 28 | "For a non-interactive version of this example which generates the article's figure see [this notebook](example_2_eye_movements.ipynb).\n", 29 | "\n", 30 | "This notebook is based on *matplotlib* and *ipympl*, which enables quick updates of the plot in real-time. For a version based on *plotly* (as the other, non-interactive examples), see [this notebook](example_2_eye_movements_interactive.ipynb)." 31 | ] 32 | }, 33 | { 34 | "cell_type": "code", 35 | "execution_count": null, 36 | "metadata": {}, 37 | "outputs": [], 38 | "source": [ 39 | "# Needs ipywidgets and ipympl\n", 40 | "%matplotlib widget\n", 41 | "import ipywidgets as widgets\n", 42 | "import threading\n", 43 | "from brian2 import *\n", 44 | "\n", 45 | "plt.ioff()" 46 | ] 47 | }, 48 | { 49 | "cell_type": "markdown", 50 | "metadata": {}, 51 | "source": [ 52 | "The model itself (mostly identical to the [non-interactive example](example_2_eye_movements.ipynb), except that some of the constants are included as parameters in the equation and can therefore change during the simulation):" 53 | ] 54 | }, 55 | { 56 | "cell_type": "code", 57 | "execution_count": null, 58 | "metadata": {}, 59 | "outputs": [], 60 | "source": [ 61 | "alpha = (1/(50*ms))**2 # characteristic relaxation time is 50 ms\n", 62 | "beta = 1/(50*ms) # friction parameter\n", 63 | "\n", 64 | "eqs_eye = '''\n", 65 | "dx/dt = velocity : 1\n", 66 | "dvelocity/dt = alpha*(x0-x)-beta*velocity : 1/second\n", 67 | "dx0/dt = -x0/tau_muscle : 1\n", 68 | "dx_object/dt = (noise - x_object)/tau_object: 1\n", 69 | "dnoise/dt = -noise/tau_object + tau_object**-0.5*xi : 1\n", 70 | "tau_object : second\n", 71 | "tau_muscle : second\n", 72 | "'''\n", 73 | "eye = NeuronGroup(1, model=eqs_eye, method='euler')\n", 74 | "taum = 20*ms\n", 75 | "motoneurons = NeuronGroup(2, model= 'dv/dt = -v/taum : 1', threshold = 'v>1',\n", 76 | " reset = 'v=0', refractory = 5*ms, method='exact')\n", 77 | "motosynapses = Synapses(motoneurons, eye, model = 'w : 1', on_pre = 'x0+=w')\n", 78 | "motosynapses.connect() # connects all motoneurons to the eye\n", 79 | "motosynapses.w = [-0.5,0.5]\n", 80 | "N = 20\n", 81 | "width = 2./N # width of receptive field\n", 82 | "gain = 4.\n", 83 | "eqs_retina = '''\n", 84 | "I = gain*exp(-((x_object-x_eye-x_neuron)/width)**2) : 1\n", 85 | "x_neuron : 1 (constant)\n", 86 | "x_object : 1 (linked) # position of the object\n", 87 | "x_eye : 1 (linked) # position of the eye\n", 88 | "dv/dt = (I-(1+gs)*v)/taum : 1\n", 89 | "gs : 1 # total synaptic conductance\n", 90 | "'''\n", 91 | "retina = NeuronGroup(N, model = eqs_retina, threshold = 'v>1', reset = 'v=0', method='exact')\n", 92 | "retina.v = 'rand()'\n", 93 | "retina.x_eye = linked_var(eye, 'x')\n", 94 | "retina.x_object = linked_var(eye, 'x_object')\n", 95 | "retina.x_neuron = '-1.0 + 2.0*i/(N-1)'\n", 96 | "sensorimotor_synapses = Synapses(retina, motoneurons, model = 'w : 1 (constant)', on_pre = 'v+=w')\n", 97 | "sensorimotor_synapses.connect(j = 'int(x_neuron_pre > 0)')\n", 98 | "sensorimotor_synapses.w = '20*abs(x_neuron_pre)/N_pre'\n", 99 | "M = StateMonitor(eye, ('x', 'x0', 'x_object'), record = True)\n", 100 | "S_retina = SpikeMonitor(retina)\n", 101 | "S_motoneurons = SpikeMonitor(motoneurons)\n" 102 | ] 103 | }, 104 | { 105 | "cell_type": "markdown", 106 | "metadata": {}, 107 | "source": [ 108 | "We create an empty plot that will be updated during the run:" 109 | ] 110 | }, 111 | { 112 | "cell_type": "code", 113 | "execution_count": null, 114 | "metadata": {}, 115 | "outputs": [], 116 | "source": [ 117 | "# Plot preparation\n", 118 | "fig, (ax_spikes, ax_position) = plt.subplots(2, 1, gridspec_kw={'height_ratios': (2, 1)}, sharex=True)\n", 119 | "h_retina = ax_spikes.plot([], [], '|k', markeredgecolor='k', label='retina')[0]\n", 120 | "h_left = ax_spikes.plot([], [], '|', color='C0', markeredgecolor='C0', label='left motoneuron')[0]\n", 121 | "h_right = ax_spikes.plot([], [], '|', color='C1', markeredgecolor='C1', label='right motoneuron')[0]\n", 122 | "ax_spikes.set(yticks=[], ylabel='neuron index', xticks=[], xlim=(0, 10), ylim=(0, 22))\n", 123 | "ax_spikes.spines['bottom'].set_visible(False)\n", 124 | "\n", 125 | "ax_position.axhline(0, color='gray')\n", 126 | "h_eye = ax_position.plot([], [], 'k', label='eye')[0]\n", 127 | "h_object = ax_position.plot([], [], color='C2', label='object')[0]\n", 128 | "ax_position.set(yticks=[-1, 1], yticklabels=['left', 'right'], xlabel='time (s)',\n", 129 | " xticks=np.arange(11, 2), xticklabels=np.arange(11, 2)-10,\n", 130 | " xlim=(0, 10), ylim=(-1, 1))\n", 131 | "ax_position.legend(loc='upper right', bbox_to_anchor=(1.0, 2.0));" 132 | ] 133 | }, 134 | { 135 | "cell_type": "markdown", 136 | "metadata": {}, 137 | "source": [ 138 | "We now create interactive widgets that the user can use to start/stop the simulation, as well as for setting certain simulation parameters." 139 | ] 140 | }, 141 | { 142 | "cell_type": "code", 143 | "execution_count": null, 144 | "metadata": {}, 145 | "outputs": [], 146 | "source": [ 147 | "time_label = widgets.Label(value='Time: 0 s')\n", 148 | "start_stop_button = widgets.Button(tooltip='Start simulation', icon='play')\n", 149 | "\n", 150 | "tau_obj_slider = widgets.FloatSlider(orientation='horizontal', description='tau_object',\n", 151 | " value=500, min=100, max=1000)\n", 152 | "tau_muscle_slider = widgets.FloatSlider(orientation='horizontal', description='tau_muscle',\n", 153 | " value=20, min=5, max=100)\n", 154 | "weight_slider = widgets.FloatSlider(orientation='horizontal', description='w_muscle',\n", 155 | " value=0.5, min=0, max=2)\n", 156 | "sliders = widgets.VBox([widgets.HBox([time_label, start_stop_button]),\n", 157 | " tau_obj_slider, tau_muscle_slider, weight_slider])\n", 158 | "layout = widgets.HBox([fig.canvas, sliders])" 159 | ] 160 | }, 161 | { 162 | "cell_type": "markdown", 163 | "metadata": {}, 164 | "source": [ 165 | "We interact with the running simulation via a \"network operation\", a Python function that will be regularly called by Brian during the simulation run (here, every 100ms of biological time). This function can access arbitrary attributes of the model to get or set their values. We use this here to 1) update the plot with the data from the last second and 2) set parameters of the model to the values requested by the user." 166 | ] 167 | }, 168 | { 169 | "cell_type": "code", 170 | "execution_count": null, 171 | "metadata": {}, 172 | "outputs": [], 173 | "source": [ 174 | "should_stop = False\n", 175 | "@network_operation(dt=100*ms)\n", 176 | "def plot_output(t):\n", 177 | " cutoff = (t - 10*second)\n", 178 | " # Plot the data of the last 10 seconds\n", 179 | " indices = S_retina.t > cutoff\n", 180 | " h_retina.set_data((S_retina.t[indices] - cutoff)/second, S_retina.i[indices])\n", 181 | " motoneuron_trains = S_motoneurons.spike_trains()\n", 182 | " to_plot = motoneuron_trains[0][motoneuron_trains[0] > cutoff]\n", 183 | " h_left.set_data((to_plot - cutoff)/second, np.ones(len(to_plot))*N)\n", 184 | " to_plot = motoneuron_trains[1][motoneuron_trains[1] > cutoff]\n", 185 | " h_right.set_data((to_plot - cutoff)/second, np.ones(len(to_plot))*(N+1))\n", 186 | " indices = M.t > cutoff\n", 187 | " h_eye.set_data((M.t[indices] - cutoff)/second, M.x[0][indices])\n", 188 | " h_object.set_data((M.t[indices] - cutoff)/second, M.x_object[0][indices])\n", 189 | " fig.canvas.draw_idle()\n", 190 | " time_label.value = 'Time: {:.1f}s'.format(float(t[:]))\n", 191 | " # Set the simulation parameters according to user settings\n", 192 | " eye.tau_object = tau_obj_slider.value*ms\n", 193 | " eye.tau_muscle = tau_muscle_slider.value*ms\n", 194 | " motosynapses.w = [-weight_slider.value, weight_slider.value]\n", 195 | " if should_stop:\n", 196 | " net.stop()" 197 | ] 198 | }, 199 | { 200 | "cell_type": "markdown", 201 | "metadata": {}, 202 | "source": [ 203 | "We store the model and the \"network operation\" in a `Network` object, and store its current state to allow for repeated execution." 204 | ] 205 | }, 206 | { 207 | "cell_type": "code", 208 | "execution_count": null, 209 | "metadata": {}, 210 | "outputs": [], 211 | "source": [ 212 | "net = Network(collect())\n", 213 | "net.store()" 214 | ] 215 | }, 216 | { 217 | "cell_type": "markdown", 218 | "metadata": {}, 219 | "source": [ 220 | "We now define two helper functions used to start/stop simulations. The actual simulation will be run in a background thread so that the user interface stays reactive while the simulation is running:" 221 | ] 222 | }, 223 | { 224 | "cell_type": "code", 225 | "execution_count": null, 226 | "metadata": {}, 227 | "outputs": [], 228 | "source": [ 229 | "def do_run(runtime):\n", 230 | " net.restore()\n", 231 | " net.run(runtime)\n", 232 | "running = False\n", 233 | "def button_pressed(b):\n", 234 | " global running\n", 235 | " global should_stop\n", 236 | " if running:\n", 237 | " should_stop = True\n", 238 | " running = False\n", 239 | " start_stop_button.tooltip = 'Start simulation'\n", 240 | " start_stop_button.icon = 'play'\n", 241 | " else:\n", 242 | " should_stop = False\n", 243 | " running = True\n", 244 | " time_label.value = 'starting...'\n", 245 | " start_stop_button.tooltip = 'Stop simulation'\n", 246 | " start_stop_button.icon = 'stop'\n", 247 | " thread = threading.Thread(target=do_run, args=(100*second, ))\n", 248 | " thread.start()\n", 249 | "start_stop_button.on_click(button_pressed)" 250 | ] 251 | }, 252 | { 253 | "cell_type": "markdown", 254 | "metadata": {}, 255 | "source": [ 256 | "We are now ready to display the plot and user interface, which can then be used to start the simulation and interact with the simulation parameters:" 257 | ] 258 | }, 259 | { 260 | "cell_type": "code", 261 | "execution_count": null, 262 | "metadata": {}, 263 | "outputs": [], 264 | "source": [ 265 | "display(layout)" 266 | ] 267 | }, 268 | { 269 | "cell_type": "code", 270 | "execution_count": null, 271 | "metadata": {}, 272 | "outputs": [], 273 | "source": [] 274 | } 275 | ], 276 | "metadata": { 277 | "kernelspec": { 278 | "display_name": "Python 3", 279 | "language": "python", 280 | "name": "python3" 281 | }, 282 | "language_info": { 283 | "codemirror_mode": { 284 | "name": "ipython", 285 | "version": 3 286 | }, 287 | "file_extension": ".py", 288 | "mimetype": "text/x-python", 289 | "name": "python", 290 | "nbconvert_exporter": "python", 291 | "pygments_lexer": "ipython3", 292 | "version": "3.6.7" 293 | } 294 | }, 295 | "nbformat": 4, 296 | "nbformat_minor": 2 297 | } 298 | -------------------------------------------------------------------------------- /example_3_bisection.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "### Quickstart\n", 8 | "To run the code below:\n", 9 | "\n", 10 | "1. Click on the cell to select it.\n", 11 | "2. Press `SHIFT+ENTER` on your keyboard or press the play button\n", 12 | " () in the toolbar above.\n", 13 | "\n", 14 | "Feel free to create new cells using the plus button\n", 15 | "(), or pressing `SHIFT+ENTER` while this cell\n", 16 | "is selected." 17 | ] 18 | }, 19 | { 20 | "cell_type": "markdown", 21 | "metadata": {}, 22 | "source": [ 23 | "# Example 3 (Using bisection to find a neuron's voltage threshold)\n", 24 | "\n", 25 | "This example demonstrate how a control flow, where simulation parameters depend on the results of previous simulations, can be expressed by making use of standard control structures in Python. By having access to the full expressivity of a general purpose programming language, expressing such control flow is straight-forward; this would not be the case for a declarative model description.\n", 26 | "\n", 27 | "Our goal in this toy example is to find the threshold voltage of neuron as a function of the density of sodium channels.\n", 28 | "\n", 29 | "We start with the basic setup:" 30 | ] 31 | }, 32 | { 33 | "cell_type": "code", 34 | "execution_count": null, 35 | "metadata": {}, 36 | "outputs": [], 37 | "source": [ 38 | "from brian2 import *\n", 39 | "\n", 40 | "defaultclock.dt = 0.01*ms # small time step for stiff equations" 41 | ] 42 | }, 43 | { 44 | "cell_type": "markdown", 45 | "metadata": {}, 46 | "source": [ 47 | "Our model of the neuron is based on the classical model of from Hodgkin and Huxley (1952). Note that this is not actually a model of a neuron, but rather of a (space-clamped) axon. However, to avoid confusion with spatially extended models, we simply use the term \"neuron\" here. In this model, the membrane potential is shifted, i.e. the resting potential is at 0mV:" 48 | ] 49 | }, 50 | { 51 | "cell_type": "code", 52 | "execution_count": null, 53 | "metadata": {}, 54 | "outputs": [], 55 | "source": [ 56 | "El = 10.613*mV\n", 57 | "ENa = 115*mV\n", 58 | "EK = -12*mV\n", 59 | "gl = 0.3*msiemens/cm**2\n", 60 | "gK = 36*msiemens/cm**2\n", 61 | "gNa_max = 100*msiemens/cm**2\n", 62 | "gNa_min = 15*msiemens/cm**2\n", 63 | "C = 1*uF/cm**2\n", 64 | "\n", 65 | "eqs = '''\n", 66 | "dv/dt = (gl * (El-v) + gNa * m**3 * h * (ENa-v) + gK * n**4 * (EK-v)) / C : volt\n", 67 | "gNa : siemens/meter**2\n", 68 | "dm/dt = alpham * (1-m) - betam * m : 1\n", 69 | "dn/dt = alphan * (1-n) - betan * n : 1\n", 70 | "dh/dt = alphah * (1-h) - betah * h : 1\n", 71 | "alpham = (0.1/mV) * (-v+25*mV) / (exp((-v+25*mV) / (10*mV)) - 1)/ms : Hz\n", 72 | "betam = 4 * exp(-v/(18*mV))/ms : Hz\n", 73 | "alphah = 0.07 * exp(-v/(20*mV))/ms : Hz\n", 74 | "betah = 1/(exp((-v+30*mV) / (10*mV)) + 1)/ms : Hz\n", 75 | "alphan = (0.01/mV) * (-v+10*mV) / (exp((-v+10*mV) / (10*mV)) - 1)/ms : Hz\n", 76 | "betan = 0.125*exp(-v/(80*mV))/ms : Hz\n", 77 | "'''" 78 | ] 79 | }, 80 | { 81 | "cell_type": "markdown", 82 | "metadata": {}, 83 | "source": [ 84 | "We simulate 100 neurons at the same time, each of them having a density of sodium channels between 15 and 100 mS/cm²:" 85 | ] 86 | }, 87 | { 88 | "cell_type": "code", 89 | "execution_count": null, 90 | "metadata": {}, 91 | "outputs": [], 92 | "source": [ 93 | "neurons = NeuronGroup(100, eqs, method='rk4', threshold='v>50*mV')\n", 94 | "neurons.gNa = 'gNa_min + (gNa_max - gNa_min)*1.0*i/N'" 95 | ] 96 | }, 97 | { 98 | "cell_type": "markdown", 99 | "metadata": {}, 100 | "source": [ 101 | "We initialize the state variables to their resting state values, note that the values for $m$, $n$, $h$ depend on the values of $\\alpha_m$, $\\beta_m$, etc. which themselves depend on $v$. The order of the assignments ($v$ is initialized before $m$, $n$, and $h$) therefore matters, something that is naturally expressed by stating initial values as sequential assignments to the state variables. In a declarative approach, this would be potentially ambiguous." 102 | ] 103 | }, 104 | { 105 | "cell_type": "code", 106 | "execution_count": null, 107 | "metadata": {}, 108 | "outputs": [], 109 | "source": [ 110 | "neurons.v = 0*mV\n", 111 | "neurons.m = '1/(1 + betam/alpham)'\n", 112 | "neurons.n = '1/(1 + betan/alphan)'\n", 113 | "neurons.h = '1/(1 + betah/alphah)'" 114 | ] 115 | }, 116 | { 117 | "cell_type": "markdown", 118 | "metadata": {}, 119 | "source": [ 120 | "We record the spiking activity of the neurons and store the current network state so that we can later restore it and run another iteration of our experiment:" 121 | ] 122 | }, 123 | { 124 | "cell_type": "code", 125 | "execution_count": null, 126 | "metadata": {}, 127 | "outputs": [], 128 | "source": [ 129 | "S = SpikeMonitor(neurons)\n", 130 | "store()" 131 | ] 132 | }, 133 | { 134 | "cell_type": "markdown", 135 | "metadata": {}, 136 | "source": [ 137 | "The algorithm we use here to find the voltage threshold is a simple bisection: we try to find the threshold voltage of a neuron by repeatedly testing values and increasing or decreasing these values depending on whether we observe a spike or not. By continously halving the size of the correction, we quickly converge to a precise estimate.\n", 138 | "\n", 139 | "We start with the same initial estimate for all segments, 25mV above the resting potential, and the same value for the size of the \"correction step\":" 140 | ] 141 | }, 142 | { 143 | "cell_type": "code", 144 | "execution_count": null, 145 | "metadata": {}, 146 | "outputs": [], 147 | "source": [ 148 | "v0 = 25*mV*ones(len(neurons))\n", 149 | "step = 25*mV" 150 | ] 151 | }, 152 | { 153 | "cell_type": "markdown", 154 | "metadata": {}, 155 | "source": [ 156 | "For later visualization of how the estimates converged towards their final values, we also store the intermediate values of the estimates:" 157 | ] 158 | }, 159 | { 160 | "cell_type": "code", 161 | "execution_count": null, 162 | "metadata": {}, 163 | "outputs": [], 164 | "source": [ 165 | "estimates = np.full((11, len(neurons)), np.nan)*mV\n", 166 | "estimates[0, :] = v0" 167 | ] 168 | }, 169 | { 170 | "cell_type": "markdown", 171 | "metadata": {}, 172 | "source": [ 173 | "We now run 10 iterations of our algorithm:" 174 | ] 175 | }, 176 | { 177 | "cell_type": "code", 178 | "execution_count": null, 179 | "metadata": {}, 180 | "outputs": [], 181 | "source": [ 182 | "for i in range(10):\n", 183 | " # Reset to the initial state\n", 184 | " restore()\n", 185 | " # Set the membrane potential to our threshold estimate\n", 186 | " neurons.v = v0\n", 187 | " # Run the simulation for 20ms\n", 188 | " run(20*ms)\n", 189 | " # Decrease the estimates for neurons that spiked\n", 190 | " v0[S.count > 0] -= step\n", 191 | " # Increase the estimate for neurons that did not spike\n", 192 | " v0[S.count == 0] += step\n", 193 | " # Reduce step size and store current estimate\n", 194 | " step /= 2.0\n", 195 | " estimates[i + 1, :] = v0" 196 | ] 197 | }, 198 | { 199 | "cell_type": "markdown", 200 | "metadata": {}, 201 | "source": [ 202 | "After the 10 iteration steps, we plot the results:" 203 | ] 204 | }, 205 | { 206 | "cell_type": "code", 207 | "execution_count": null, 208 | "metadata": {}, 209 | "outputs": [], 210 | "source": [ 211 | "from plotly import tools\n", 212 | "from plotly.offline import iplot, init_notebook_mode\n", 213 | "import plotly.graph_objs as go\n", 214 | "\n", 215 | "init_notebook_mode(connected=True)\n", 216 | "\n", 217 | "fig = tools.make_subplots(2, 1, shared_yaxes=True, print_grid=False)\n", 218 | "colors = ['#1f77b4', '#ff7f03', '#2ca02c']\n", 219 | "examples = [10, 50, 90]\n", 220 | "for example, color in zip(examples, colors):\n", 221 | " trace = go.Scatter(x=np.arange(11),\n", 222 | " y=estimates[:, example] / mV, \n", 223 | " name='gNA = %.1fmS/cm$^2$' % (neurons.gNa[example]/(mS/cm**2)),\n", 224 | " marker={'color': color, 'size': 10},\n", 225 | " mode='markers+lines',\n", 226 | " showlegend=False)\n", 227 | " fig.append_trace(trace, 1, 1)\n", 228 | "\n", 229 | "trace = go.Scatter(x=neurons.gNa/(mS/cm**2),\n", 230 | " y=v0/mV,\n", 231 | " line={'color': 'gray'},\n", 232 | " mode='lines',\n", 233 | " name='threshold estimate',\n", 234 | " showlegend=False)\n", 235 | "fig.append_trace(trace, 2, 1)\n", 236 | "for idx, (example, color) in enumerate(zip(examples, colors)):\n", 237 | " trace = go.Scatter(x=[neurons.gNa[example]/(mS/cm**2)],\n", 238 | " y=[estimates[-1, example]/mV],\n", 239 | " mode='markers',\n", 240 | " marker={'color': color, 'symbol': 'circle', 'size': 15},\n", 241 | " showlegend=False,\n", 242 | " name='gNA = %.1fmS/cm$^2$' % (neurons.gNa[example]/(mS/cm**2)))\n", 243 | " fig.append_trace(trace, 2, 1)\n", 244 | "fig['layout'].update(xaxis1={'title': 'iteration'},\n", 245 | " xaxis2={'title': 'gNA (mS/cm²)'},\n", 246 | " yaxis1={'range': (0, 45),\n", 247 | " 'title': 'threshold estimate (mV)'},\n", 248 | " yaxis2={'range': (0, 45),\n", 249 | " 'title': 'threshold estimate (mV)'})\n", 250 | "\n", 251 | "iplot(fig)" 252 | ] 253 | } 254 | ], 255 | "metadata": { 256 | "kernelspec": { 257 | "display_name": "Python 3", 258 | "language": "python", 259 | "name": "python3" 260 | }, 261 | "language_info": { 262 | "codemirror_mode": { 263 | "name": "ipython", 264 | "version": 3 265 | }, 266 | "file_extension": ".py", 267 | "mimetype": "text/x-python", 268 | "name": "python", 269 | "nbconvert_exporter": "python", 270 | "pygments_lexer": "ipython3", 271 | "version": "3.6.7" 272 | } 273 | }, 274 | "nbformat": 4, 275 | "nbformat_minor": 2 276 | } 277 | -------------------------------------------------------------------------------- /example_4_microphone.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "### Quickstart\n", 8 | "To run the code below:\n", 9 | "\n", 10 | "1. Click on the cell to select it.\n", 11 | "2. Press `SHIFT+ENTER` on your keyboard or press the play button\n", 12 | " () in the toolbar above.\n", 13 | "\n", 14 | "Feel free to create new cells using the plus button\n", 15 | "(), or pressing `SHIFT+ENTER` while this cell\n", 16 | "is selected." 17 | ] 18 | }, 19 | { 20 | "cell_type": "markdown", 21 | "metadata": {}, 22 | "source": [ 23 | "# Example 4 (neural pitch processing with audio input)\n", 24 | "\n", 25 | "This example is a crude \"pitch detector\" network that performs autocorrelation of an audio signal. It works with coincidence detector neurons that receive two copies of the input (which has been transformed into spikes by an equally crude \"periphery neuron\" model), with a certain delay between the two inputs. Depending on their respective delay, neurons are sensitive to different periodicities.\n", 26 | "\n", 27 | "The example shows how Brian's high-level model descriptions can be seemlessly combined with low-level code in a target language, in this case C++. Such code can be necessary to extend Brian functionalities without sacrificing performance, e.g. in applications that necessitate real-time processing of external stimuli.\n", 28 | "\n", 29 | "In this code, we use this mechanism to provide two possible sources of audio input: a pre-recorded audio file (`use_microphone = False`), or real-time input from a microphone (`use_microphone = True`). For the latter, the `portaudio` library needs to be installed. Also note that access to the computers microphone is not possible when running the notebook on an external server such as [mybinder](https://mybinder.org)." 30 | ] 31 | }, 32 | { 33 | "cell_type": "code", 34 | "execution_count": null, 35 | "metadata": {}, 36 | "outputs": [], 37 | "source": [ 38 | "from brian2 import *\n", 39 | "import os" 40 | ] 41 | }, 42 | { 43 | "cell_type": "markdown", 44 | "metadata": {}, 45 | "source": [ 46 | "We'll use the high-performance C++ standalone mode, otherwise we are not guaranteed that processing is faster than realtime (necessary when using microphone input)." 47 | ] 48 | }, 49 | { 50 | "cell_type": "code", 51 | "execution_count": null, 52 | "metadata": {}, 53 | "outputs": [], 54 | "source": [ 55 | "set_device('cpp_standalone', directory='example_4')" 56 | ] 57 | }, 58 | { 59 | "cell_type": "markdown", 60 | "metadata": {}, 61 | "source": [ 62 | "We first set a few global parameters of the model:" 63 | ] 64 | }, 65 | { 66 | "cell_type": "code", 67 | "execution_count": null, 68 | "metadata": {}, 69 | "outputs": [], 70 | "source": [ 71 | "sample_rate = 44.1*kHz\n", 72 | "buffer_size = 128\n", 73 | "defaultclock.dt = 1/sample_rate\n", 74 | "runtime = 4.5*second\n", 75 | "\n", 76 | "# Receptor neurons (\"ear\")\n", 77 | "max_delay = 20*ms # 50 Hz\n", 78 | "tau_ear = 1*ms\n", 79 | "tau_th = 5*ms\n", 80 | "# Coincidence detectors\n", 81 | "min_freq = 50*Hz\n", 82 | "max_freq = 1000*Hz\n", 83 | "num_neurons = 300\n", 84 | "tau = 1*ms\n", 85 | "sigma = .1" 86 | ] 87 | }, 88 | { 89 | "cell_type": "markdown", 90 | "metadata": {}, 91 | "source": [ 92 | "The model equations (see code further down below) refer to a `get_sample` function that returns the next available audio sample. Since we cannot express this function as mathematical equations, we directly provide its implementation in the target language C++. Since the code is relatively long we do not include it directly here, but instead store the source code in a separate file. We provide two such files, `sound_from_mic.cpp` for sound input from a microphone (used when `use_microphone` is set to `True`), and `sound_from_file.cpp` for sound read out from an uncompressed WAV audio file. These files will be compiled when needed because we provide their names as arguments to the `sources` keyword. Similarly, we include the function declaration that is present in the `sound_input.h` header file (identical for both cases), by specifying it to the `headers` keyword. We further customize the code that gets compiled by providing preprocessor macros via the `define_macros` keyword. Finally, since we are making use of the `portaudio` library for microphone input, we link to the `portaudio` library via the `libraries` keyword:" 93 | ] 94 | }, 95 | { 96 | "cell_type": "code", 97 | "execution_count": null, 98 | "metadata": {}, 99 | "outputs": [], 100 | "source": [ 101 | "use_microphone = False\n", 102 | "if use_microphone:\n", 103 | " # Now comes the connection to the microphone code.\n", 104 | " @implementation('cpp','//actual code in sound_from_mic.cpp',\n", 105 | " sources=[os.path.abspath('sound_from_mic.cpp')],\n", 106 | " headers=['\"{}\"'.format(os.path.abspath('sound_input.h'))],\n", 107 | " libraries=['portaudio'],\n", 108 | " define_macros=[('BUFFER_SIZE', buffer_size),\n", 109 | " ('SAMPLE_RATE', sample_rate/Hz)])\n", 110 | " @check_units(t=second, result=1)\n", 111 | " def get_sample(t):\n", 112 | " raise NotImplementedError('Use a C++-based code generation target.')\n", 113 | "else:\n", 114 | " # Instead of using the microphone, use a sound file\n", 115 | " @implementation('cpp','//actual code in sound_from_file.cpp',\n", 116 | " sources=[os.path.abspath('sound_from_file.cpp')],\n", 117 | " headers=['\"{}\"'.format(os.path.abspath('sound_input.h'))],\n", 118 | " define_macros=[('FILENAME', r'\\\"{}\\\"'.format(os.path.abspath('scale_flute.wav')))])\n", 119 | " @check_units(t=second, result=1)\n", 120 | " def get_sample(t):\n", 121 | " raise NotImplementedError('Use a C++-based code generation target.')" 122 | ] 123 | }, 124 | { 125 | "cell_type": "markdown", 126 | "metadata": {}, 127 | "source": [ 128 | "We now specify our neural and synaptic model, making use of the `get_sample` function as if it were one of the standard functions provided by Brian:" 129 | ] 130 | }, 131 | { 132 | "cell_type": "code", 133 | "execution_count": null, 134 | "metadata": {}, 135 | "outputs": [], 136 | "source": [ 137 | "gain = 50\n", 138 | "\n", 139 | "# Note that the `get_sample` function does not actually make use of the time `t` that it is given, for simplicity\n", 140 | "# it assumes that it is called only once per time step. This is actually enforced by using our `constant over dt`\n", 141 | "# feature -- the variable `sound` can be used in several places (which is important here, since we want to\n", 142 | "# record it as well):\n", 143 | "eqs_ear = '''\n", 144 | "dx/dt = (sound - x)/tau_ear: 1 (unless refractory)\n", 145 | "dth/dt = (0.1*x - th)/tau_th : 1\n", 146 | "sound = clip(get_sample(t), 0, inf) : 1 (constant over dt)\n", 147 | "'''\n", 148 | "receptors = NeuronGroup(1, eqs_ear, threshold='x>th', reset='x=0; th = th*2.5 + 0.01',\n", 149 | " refractory=2*ms, method='exact')\n", 150 | "receptors.th = 1\n", 151 | "sound_mon = StateMonitor(receptors, 'sound', record=0)\n", 152 | "\n", 153 | "eqs_neurons = '''\n", 154 | "dv/dt = -v/tau+sigma*(2./tau)**.5*xi : 1\n", 155 | "freq : Hz (constant)\n", 156 | "'''\n", 157 | "\n", 158 | "neurons = NeuronGroup(num_neurons, eqs_neurons, threshold='v>1', reset='v=0',\n", 159 | " method='euler')\n", 160 | "neurons.freq = 'exp(log(min_freq/Hz)+(i*1.0/(num_neurons-1))*log(max_freq/min_freq))*Hz'\n", 161 | "synapses = Synapses(receptors, neurons, on_pre='v += 0.5',\n", 162 | " multisynaptic_index='k')\n", 163 | "synapses.connect(n=2) # one synapse without delay; one with delay\n", 164 | "synapses.delay['k == 1'] = '1/freq_post'" 165 | ] 166 | }, 167 | { 168 | "cell_type": "markdown", 169 | "metadata": {}, 170 | "source": [ 171 | "We record the spikes of the \"pitch detector\" neurons, and run the simulation:" 172 | ] 173 | }, 174 | { 175 | "cell_type": "code", 176 | "execution_count": null, 177 | "metadata": {}, 178 | "outputs": [], 179 | "source": [ 180 | "spikes = SpikeMonitor(neurons)\n", 181 | "\n", 182 | "run(runtime)" 183 | ] 184 | }, 185 | { 186 | "cell_type": "markdown", 187 | "metadata": {}, 188 | "source": [ 189 | "After the simulation ran through, we plot the raw sound input as well as its spectrogram, and the spiking activity of the detector neurons:" 190 | ] 191 | }, 192 | { 193 | "cell_type": "code", 194 | "execution_count": null, 195 | "metadata": {}, 196 | "outputs": [], 197 | "source": [ 198 | "from plotly import tools\n", 199 | "from plotly.offline import iplot, init_notebook_mode\n", 200 | "import plotly.graph_objs as go\n", 201 | "from scipy.signal import spectrogram\n", 202 | "init_notebook_mode(connected=True)\n", 203 | "\n", 204 | "fig = tools.make_subplots(5, 1, shared_xaxes=True,\n", 205 | " specs=[[{}], [{'rowspan': 2}], [None], [{'rowspan': 2}], [None]],\n", 206 | " print_grid=False\n", 207 | " # subplot_titles=('Raw sound signal', 'Spectrogram of sound signal',\n", 208 | " # 'Spiking activity')\n", 209 | " )\n", 210 | "\n", 211 | "trace = go.Scatter(x=sound_mon.t/second,\n", 212 | " y=sound_mon.sound[0],\n", 213 | " name='sound signal',\n", 214 | " mode='lines',\n", 215 | " line={'color':'#1f77b4'},\n", 216 | " showlegend=False\n", 217 | " )\n", 218 | "fig.append_trace(trace, 1, 1)\n", 219 | "f, t, Sxx = spectrogram(sound_mon.sound[0], fs=sample_rate/Hz, nperseg=2**12, window='hamming')\n", 220 | "\n", 221 | "trace = go.Heatmap(x=t, y=f, z=10*np.log10(Sxx), showscale=False,\n", 222 | " colorscale='Viridis', name='PSD')\n", 223 | "fig.append_trace(trace, 2, 1)\n", 224 | "\n", 225 | "trace = go.Scatter(x=spikes.t/second,\n", 226 | " y=neurons.freq[spikes.i]/Hz, \n", 227 | " marker={'symbol': 'line-ns', 'line': {'width': 1, 'color':'#1f77b4'},\n", 228 | " 'color':'#1f77b4'},\n", 229 | " mode='markers',\n", 230 | " name='spikes', showlegend=False)\n", 231 | "fig.append_trace(trace, 4, 1)\n", 232 | "\n", 233 | "fig['layout'].update(xaxis={'title': 'time (in s)',\n", 234 | " 'range': (0.4, runtime/second)},\n", 235 | " yaxis1={'title': 'amplitude',\n", 236 | " 'showticklabels': False},\n", 237 | " yaxis2={'type': 'log',\n", 238 | " 'range': (0.9*np.log10(min_freq/Hz), 1.1*np.log10(500)),\n", 239 | " 'title': 'Frequency (Hz)'},\n", 240 | " yaxis3={'type': 'log',\n", 241 | " 'range': (0.9*np.log10(min_freq/Hz), 1.1*np.log10(500)),\n", 242 | " 'title': 'Preferred\\nFrequency (Hz)'})\n", 243 | "\n", 244 | "iplot(fig)" 245 | ] 246 | }, 247 | { 248 | "cell_type": "markdown", 249 | "metadata": {}, 250 | "source": [ 251 | "If you ran the above code for the pre-recorded sound file, you should clearly see that four separate, ascending notes were played." 252 | ] 253 | } 254 | ], 255 | "metadata": { 256 | "kernelspec": { 257 | "display_name": "Python 3", 258 | "language": "python", 259 | "name": "python3" 260 | }, 261 | "language_info": { 262 | "codemirror_mode": { 263 | "name": "ipython", 264 | "version": 3 265 | }, 266 | "file_extension": ".py", 267 | "mimetype": "text/x-python", 268 | "name": "python", 269 | "nbconvert_exporter": "python", 270 | "pygments_lexer": "ipython3", 271 | "version": "3.6.7" 272 | } 273 | }, 274 | "nbformat": 4, 275 | "nbformat_minor": 2 276 | } 277 | -------------------------------------------------------------------------------- /example_appendix_parameter_exploration.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "### Quickstart\n", 8 | "To run the code below:\n", 9 | "\n", 10 | "1. Click on the cell to select it.\n", 11 | "2. Press `SHIFT+ENTER` on your keyboard or press the play button\n", 12 | " () in the toolbar above.\n", 13 | "\n", 14 | "Feel free to create new cells using the plus button\n", 15 | "(), or pressing `SHIFT+ENTER` while this cell\n", 16 | "is selected." 17 | ] 18 | }, 19 | { 20 | "cell_type": "markdown", 21 | "metadata": {}, 22 | "source": [ 23 | "# Appendix 4: parameter exploration\n", 24 | "\n", 25 | "In this example, we show how Brian can be used to do a parameter exploration. The most efficient way to implement this is to consider a group of neurons, where each of the neurons is described by the same model, but one or several model parameters systematically change across neurons." 26 | ] 27 | }, 28 | { 29 | "cell_type": "code", 30 | "execution_count": null, 31 | "metadata": {}, 32 | "outputs": [], 33 | "source": [ 34 | "%matplotlib notebook\n", 35 | "from brian2 import *" 36 | ] 37 | }, 38 | { 39 | "cell_type": "markdown", 40 | "metadata": {}, 41 | "source": [ 42 | "We can speed up this \"embarassingly parallel\" problem by parallelizing it over CPUs, making use of the OpenMP interface for multithreading:" 43 | ] 44 | }, 45 | { 46 | "cell_type": "code", 47 | "execution_count": null, 48 | "metadata": {}, 49 | "outputs": [], 50 | "source": [ 51 | "set_device('cpp_standalone')\n", 52 | "prefs.devices.cpp_standalone.openmp_threads = 4" 53 | ] 54 | }, 55 | { 56 | "cell_type": "markdown", 57 | "metadata": {}, 58 | "source": [ 59 | "Using the [Brian2GeNN](https://brian2genn.readthedocs.io) interface, this simulation could also run on a GPU (needs a [CUDA](https://developer.nvidia.com/cuda-zone)-enabled NVIDIA GPU, and an installation of `brian2genn`): " 60 | ] 61 | }, 62 | { 63 | "cell_type": "code", 64 | "execution_count": null, 65 | "metadata": {}, 66 | "outputs": [], 67 | "source": [ 68 | "# These two lines would replace the above two lines:\n", 69 | "# import brian2genn\n", 70 | "# set_device('genn')" 71 | ] 72 | }, 73 | { 74 | "cell_type": "markdown", 75 | "metadata": {}, 76 | "source": [ 77 | "We will first set some general constants for our model (a HH-type model with an injected current):" 78 | ] 79 | }, 80 | { 81 | "cell_type": "code", 82 | "execution_count": null, 83 | "metadata": {}, 84 | "outputs": [], 85 | "source": [ 86 | "area = 20000*umetre**2\n", 87 | "Cm = (1*ufarad*cm**-2) * area\n", 88 | "gl = (5e-5*siemens*cm**-2) * area\n", 89 | "\n", 90 | "El = -60*mV\n", 91 | "EK = -90*mV\n", 92 | "ENa = 50*mV\n", 93 | "g_kd = (30*msiemens*cm**-2) * area\n", 94 | "VT = -63*mV" 95 | ] 96 | }, 97 | { 98 | "cell_type": "markdown", 99 | "metadata": {}, 100 | "source": [ 101 | "We will explore the effect of the $g_{Na}$ conductance, and the effect of the injected current $I$, varying each over 100 values:" 102 | ] 103 | }, 104 | { 105 | "cell_type": "code", 106 | "execution_count": null, 107 | "metadata": {}, 108 | "outputs": [], 109 | "source": [ 110 | "g_na_values = np.linspace(10, 100, num=100)*msiemens*cm**-2 * area\n", 111 | "I_values = np.linspace(0, 20, num=100)*pA" 112 | ] 113 | }, 114 | { 115 | "cell_type": "markdown", 116 | "metadata": {}, 117 | "source": [ 118 | "We now define the model, with $g_{Na}$ and $I$ as parameters, set independently for each neuron, and create one neuron for each combination of parameters:" 119 | ] 120 | }, 121 | { 122 | "cell_type": "code", 123 | "execution_count": null, 124 | "metadata": {}, 125 | "outputs": [], 126 | "source": [ 127 | "eqs = Equations('''\n", 128 | "dv/dt = (gl*(El-v)-\n", 129 | " g_na*(m*m*m)*h*(v-ENa)-\n", 130 | " g_kd*(n*n*n*n)*(v-EK) + I)/Cm : volt\n", 131 | "dm/dt = alpha_m*(1-m)-beta_m*m : 1\n", 132 | "dn/dt = alpha_n*(1-n)-beta_n*n : 1\n", 133 | "dh/dt = alpha_h*(1-h)-beta_h*h : 1\n", 134 | "alpha_m = 0.32*(mV**-1)*(13*mV-v+VT)/\n", 135 | " (exp((13*mV-v+VT)/(4*mV))-1.)/ms : Hz\n", 136 | "beta_m = 0.28*(mV**-1)*(v-VT-40*mV)/\n", 137 | " (exp((v-VT-40*mV)/(5*mV))-1)/ms : Hz\n", 138 | "alpha_h = 0.128*exp((17*mV-v+VT)/(18*mV))/ms : Hz\n", 139 | "beta_h = 4./(1+exp((40*mV-v+VT)/(5*mV)))/ms : Hz\n", 140 | "alpha_n = 0.032*(mV**-1)*(15*mV-v+VT)/\n", 141 | " (exp((15*mV-v+VT)/(5*mV))-1.)/ms : Hz\n", 142 | "beta_n = .5*exp((10*mV-v+VT)/(40*mV))/ms : Hz\n", 143 | "I : amp (constant)\n", 144 | "g_na : siemens (constant)\n", 145 | "''')\n", 146 | "neuron = NeuronGroup(len(g_na_values)*len(I_values), eqs,\n", 147 | " method='exponential_euler',\n", 148 | " threshold='v>-20*mV', refractory='v>-20*mV')\n", 149 | "neuron.v = El\n", 150 | "spike_mon = SpikeMonitor(neuron)" 151 | ] 152 | }, 153 | { 154 | "cell_type": "markdown", 155 | "metadata": {}, 156 | "source": [ 157 | "We now create all combinations of the explored parameters, and assign them to the individual neurons. Running the \"network\" of neurons will then explore all the parameter combinations." 158 | ] 159 | }, 160 | { 161 | "cell_type": "code", 162 | "execution_count": null, 163 | "metadata": {}, 164 | "outputs": [], 165 | "source": [ 166 | "all_g_na_values, all_I_values = np.meshgrid(g_na_values, I_values)\n", 167 | "all_g_na_values = all_g_na_values.flat[:]\n", 168 | "all_I_values = all_I_values.flat[:]\n", 169 | "neuron.g_na = all_g_na_values\n", 170 | "neuron.I = all_I_values" 171 | ] 172 | }, 173 | { 174 | "cell_type": "markdown", 175 | "metadata": {}, 176 | "source": [ 177 | "We start the run and determine the firing rate for each neuron:" 178 | ] 179 | }, 180 | { 181 | "cell_type": "code", 182 | "execution_count": null, 183 | "metadata": {}, 184 | "outputs": [], 185 | "source": [ 186 | "run(10*second)\n", 187 | "rates = spike_mon.count/(10*second)/Hz" 188 | ] 189 | }, 190 | { 191 | "cell_type": "markdown", 192 | "metadata": {}, 193 | "source": [ 194 | "We can now plot the firing rate as a function of the two explored parameters (in this example here, vertical slices of the graph can also be interpreted as the f/I curve of the neuron for varying values of $g_{Na}$):" 195 | ] 196 | }, 197 | { 198 | "cell_type": "code", 199 | "execution_count": null, 200 | "metadata": {}, 201 | "outputs": [], 202 | "source": [ 203 | "I_index = ((neuron.I - np.min(I_values)) / np.diff(I_values)[0]).round().astype('int')\n", 204 | "Na_index = ((neuron.g_na - np.min(g_na_values)) / np.diff(g_na_values)[0]).round().astype('int')\n", 205 | "matrix = np.full((len(I_values), len(g_na_values)), np.nan)\n", 206 | "matrix[I_index, Na_index] = rates\n", 207 | "norm = mpl.colors.BoundaryNorm(np.arange(0, 19), plt.cm.viridis.N)\n", 208 | "fig, ax = plt.subplots()\n", 209 | "m = ax.imshow(matrix, norm=norm)\n", 210 | "# We do manual ticks, easier than using extent and getting the scaling right\n", 211 | "ticks = [0, 49, 99]\n", 212 | "ax.set(xticks=ticks, xticklabels=['%.1f' % (g_na_values[i]/(mS*cm**-2 * area)) for i in ticks],\n", 213 | " yticks=ticks, yticklabels=['%.1f' % (I_values[i]/pA) for i in ticks],\n", 214 | " xlabel='$g_{Na}$ (mS/cm²)', ylabel='$I$ (nA)')\n", 215 | "ax.axes.invert_yaxis()\n", 216 | "cbar = fig.colorbar(m)\n", 217 | "cbar.set_label('number of spikes')" 218 | ] 219 | } 220 | ], 221 | "metadata": { 222 | "kernelspec": { 223 | "display_name": "Python 3", 224 | "language": "python", 225 | "name": "python3" 226 | }, 227 | "language_info": { 228 | "codemirror_mode": { 229 | "name": "ipython", 230 | "version": 3 231 | }, 232 | "file_extension": ".py", 233 | "mimetype": "text/x-python", 234 | "name": "python", 235 | "nbconvert_exporter": "python", 236 | "pygments_lexer": "ipython3", 237 | "version": "3.6.7" 238 | } 239 | }, 240 | "nbformat": 4, 241 | "nbformat_minor": 2 242 | } 243 | -------------------------------------------------------------------------------- /index.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Brian example notebooks\n", 8 | "\n", 9 | "These notebooks showcase examples that demonstrate various features of the [Brian simulator](http://brian2.readthedocs.io):\n", 10 | "\n", 11 | "* [Example 1 (Pyloric network of the crustacean stomatogastric ganglion)](example_1_pyloric_network.ipynb)\n", 12 | " * [the same example using a more detailed neuron model](example_1_pyloric_network_complex.ipynb)\n", 13 | "* [Example 2 (Smooth pursuit eye movements)](example_2_eye_movements.ipynb)\n", 14 | " * [an interactive version of the same example (using *plotly*)](example_2_eye_movements_interactive.ipynb)\n", 15 | " * [an interactive version of the same example (using *matplotlib*)](example_2_eye_movements_interactive_matplotlib.ipynb)\n", 16 | "* [Example 3 (Using bisection to find a neuron's voltage threshold)](example_3_bisection.ipynb)\n", 17 | "* [Example 4 (neural pitch processing with audio input)](example_4_microphone.ipynb)\n", 18 | "\n", 19 | "\n", 20 | "* [Appendix: multicompartmental model](example_appendix_multicompartment_model.ipynb)\n", 21 | "* [Appendix: parameter exploration](example_appendix_parameter_exploration.ipynb)" 22 | ] 23 | } 24 | ], 25 | "metadata": { 26 | "kernelspec": { 27 | "display_name": "Python 3", 28 | "language": "python", 29 | "name": "python3" 30 | }, 31 | "language_info": { 32 | "codemirror_mode": { 33 | "name": "ipython", 34 | "version": 3 35 | }, 36 | "file_extension": ".py", 37 | "mimetype": "text/x-python", 38 | "name": "python", 39 | "nbconvert_exporter": "python", 40 | "pygments_lexer": "ipython3", 41 | "version": "3.6.7" 42 | } 43 | }, 44 | "nbformat": 4, 45 | "nbformat_minor": 2 46 | } 47 | -------------------------------------------------------------------------------- /scale_flute.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brian-team/brian2_paper_examples/73045cd61322e923e96883dc97c0848154f79f8c/scale_flute.wav -------------------------------------------------------------------------------- /sound_from_file.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #define CHECK(x) { if(!(x)) { \ 8 | fprintf(stderr, "%s:%i: failure at: %s\n", __FILE__, __LINE__, #x); \ 9 | _exit(1); } } 10 | 11 | int numChannels; 12 | int sampleRate; 13 | int bytesPerSample, bitsPerSample; 14 | 15 | std::string freadStr(FILE* f, size_t len) { 16 | std::string s(len, '\0'); 17 | CHECK(fread(&s[0], 1, len, f) == len); 18 | return s; 19 | } 20 | 21 | template 22 | T freadNum(FILE* f) { 23 | T value; 24 | CHECK(fread(&value, sizeof(value), 1, f) == 1); 25 | return value; // no endian-swap for now... WAV is LE anyway... 26 | } 27 | 28 | void readFmtChunk(FILE *wavfile, uint32_t chunkLen) { 29 | CHECK(chunkLen >= 16); 30 | uint16_t fmttag = freadNum(wavfile); 31 | CHECK(fmttag == 1 /*PCM*/); 32 | numChannels = freadNum(wavfile); 33 | CHECK(numChannels == 2); 34 | sampleRate = freadNum(wavfile); 35 | CHECK(sampleRate == 44100); 36 | uint32_t byteRate = freadNum(wavfile); 37 | uint16_t blockAlign = freadNum(wavfile); 38 | bitsPerSample = freadNum(wavfile); 39 | bytesPerSample = bitsPerSample / 8; 40 | CHECK(byteRate == sampleRate * numChannels * bytesPerSample); 41 | CHECK(blockAlign == numChannels * bytesPerSample); 42 | CHECK(bitsPerSample == 16); 43 | if(chunkLen > 16) { 44 | uint16_t extendedSize = freadNum(wavfile); 45 | CHECK(chunkLen == 18 + extendedSize); 46 | fseek(wavfile, extendedSize, SEEK_CUR); 47 | } 48 | } 49 | 50 | void readHeader(FILE *wavfile) { 51 | CHECK(freadStr(wavfile, 4) == "RIFF"); 52 | uint32_t wavechunksize = freadNum(wavfile); 53 | CHECK(freadStr(wavfile, 4) == "WAVE"); 54 | while(true) { 55 | std::string chunkName = freadStr(wavfile, 4); 56 | uint32_t chunkLen = freadNum(wavfile); 57 | if(chunkName == "fmt ") 58 | readFmtChunk(wavfile, chunkLen); 59 | else if(chunkName == "data") { 60 | CHECK(sampleRate != 0); 61 | CHECK(numChannels > 0); 62 | CHECK(bytesPerSample > 0); 63 | printf("bytesPerSample: %d\n", bytesPerSample); 64 | printf("len: %.2f secs\n", double(chunkLen) / sampleRate / numChannels / bytesPerSample); 65 | break; // start playing now 66 | } else { 67 | // skip chunk 68 | CHECK(fseek(wavfile, chunkLen, SEEK_CUR) == 0); 69 | } 70 | } 71 | } 72 | 73 | FILE *init_file() { 74 | FILE *wavfile = fopen(FILENAME, "r"); // will be replaced via macro 75 | readHeader(wavfile); 76 | return wavfile; 77 | } 78 | 79 | float get_sample(const double t) { 80 | static FILE *wavfile = init_file(); 81 | static int16_t samples[2]; 82 | if (fread(samples, bytesPerSample * numChannels, 1, wavfile) == 0) { 83 | // end of file 84 | return 0.0; 85 | } 86 | return samples[0]*1.0/32767; 87 | } 88 | -------------------------------------------------------------------------------- /sound_from_mic.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | PaStream *_init_stream() 10 | { 11 | PaStream* stream; 12 | PaError err; 13 | 14 | err = Pa_Initialize(); 15 | if (err != paNoError) 16 | { 17 | std::cerr << "Initializing PortAudio failed with error: " << Pa_GetErrorText(err) << std::endl; 18 | exit(err); 19 | } 20 | 21 | err = Pa_OpenDefaultStream(&stream, 1, 0, paFloat32, SAMPLE_RATE, BUFFER_SIZE, NULL, NULL); 22 | if (err != paNoError) 23 | { 24 | std::cerr << "Opening the default input stream failed with error: " << Pa_GetErrorText(err) << std::endl; 25 | exit(err); 26 | } 27 | 28 | err = Pa_StartStream(stream); 29 | if (err != paNoError) 30 | { 31 | std::cerr << "Starting the stream failed with error: " << Pa_GetErrorText(err) << std::endl; 32 | exit(err); 33 | } 34 | 35 | return stream; 36 | } 37 | 38 | float get_sample(const double t) 39 | { 40 | static PaStream* stream = _init_stream(); 41 | static float buffer[BUFFER_SIZE]; 42 | static int next_sample = BUFFER_SIZE; 43 | 44 | if (next_sample >= BUFFER_SIZE) 45 | { 46 | Pa_ReadStream(stream, buffer, BUFFER_SIZE); 47 | next_sample = 0; 48 | } 49 | return buffer[next_sample++]; 50 | } 51 | 52 | -------------------------------------------------------------------------------- /sound_input.h: -------------------------------------------------------------------------------- 1 | float get_sample(const double); 2 | -------------------------------------------------------------------------------- /tc200.CNG.swc: -------------------------------------------------------------------------------- 1 | # Original file tc200.swc edited by Duncan Donohue using SWCfix version 1.21 on 12/6/05. 2 | # Errors and fixes documented in tc200.swc.std. See SWCfix1.21.doc for more information. 3 | # 4 | # ORIGINAL_SOURCE 5 | # CREATURE 6 | # REGION 7 | # FIELD/LAYER 8 | # TYPE 9 | # CONTRIBUTOR 10 | # REFERENCE 11 | # RAW 12 | # EXTRAS 13 | # SOMA_AREA 14 | # SHRINKAGE_CORRECTION 15 | # VERSION_NUMBER 16 | # VERSION_DATE 17 | # ********************************************* 18 | # SCALE 1.0 1.0 1.0 19 | 1 1 -13.8 -3.059 -24.01 14.43 -1 20 | 2 3 -13.5 0. -38.5 0.70 1 21 | 3 3 -22.5 0.5 -33.5 0.4 2 22 | 4 3 -30. -1.5 -33.5 0.4 3 23 | 5 3 -36.5 -2. -33.5 0.4 4 24 | 6 3 -41. -2. -33.5 0.4 5 25 | 7 3 -47. -2. -28. 0.4 6 26 | 8 3 -53. -1. -21. 0.4 7 27 | 9 3 -60.5 1.5 -14.5 0.4 8 28 | 10 3 -66.5 2.5 -13. 0.4 9 29 | 11 3 -72.5 1. -13.5 0.4 10 30 | 12 3 -78.5 1.5 -13.5 0.4 11 31 | 13 3 -85.5 2. -12.5 0.4 12 32 | 14 3 -92.5 2. -11. 0.4 13 33 | 15 3 -99.5 3. -9.5 0.4 14 34 | 16 3 -106. 3.5 -8.5 0.4 15 35 | 17 3 -111. 5. -7.5 0.4 16 36 | 18 3 -113.5 6.5 -7. 0.4 17 37 | 19 3 -70. -1. -16. 0.4 11 38 | 20 3 -69. -3. -17.5 0.4 19 39 | 21 3 -70. -5.5 -20.5 0.4 20 40 | 22 3 -72.5 -8. -22. 0.4 21 41 | 23 3 -77.5 -10.5 -24. 0.4 22 42 | 24 3 -83.5 -12. -25.5 0.4 23 43 | 25 3 -89. -14. -25.5 0.4 24 44 | 26 3 -95. -14.5 -25.5 0.4 25 45 | 27 3 -100. -15. -25.5 0.4 26 46 | 28 3 -105. -15. -25.5 0.4 27 47 | 29 3 -109.5 -15.5 -25.5 0.4 28 48 | 30 3 -114. -16. -21. 0.4 29 49 | 31 3 -120. -16. -17.5 0.4 30 50 | 32 3 -125.5 -16.5 -14. 0.4 31 51 | 33 3 -131. -16. -12.5 0.4 32 52 | 34 3 -135.5 -16. -8.5 0.4 33 53 | 35 3 -26. 2.5 -36. 0.55 3 54 | 36 3 -31.5 2. -35.5 0.4 35 55 | 37 3 -38.5 2.5 -34.5 0.4 36 56 | 38 3 -45.5 4. -29. 0.4 37 57 | 39 3 -53.5 5. -24.5 0.4 38 58 | 40 3 -61.5 5.5 -20. 0.4 39 59 | 41 3 -67. 9. -21.5 0.4 40 60 | 42 3 -72.5 11.5 -22.5 0.4 41 61 | 43 3 -78.5 14. -22.5 0.4 42 62 | 44 3 -84. 14. -22.5 0.4 43 63 | 45 3 -90. 12. -22.5 0.4 44 64 | 46 3 -95. 9. -22.5 0.4 45 65 | 47 3 -101. 7. -20.5 0.4 46 66 | 48 3 -107. 4. -19. 0.4 47 67 | 49 3 -114. 0. -20. 0.4 48 68 | 50 3 -121. -5.5 -25.5 0.4 49 69 | 51 3 -61. 9. -21. 0.4 40 70 | 52 3 -63.5 13. -17.5 0.4 51 71 | 53 3 -69.5 16.5 -11.5 0.4 52 72 | 54 3 -75.5 20.5 -10. 0.4 53 73 | 55 3 -79. 22.5 -10. 0.4 54 74 | 56 3 -79. 25. -9. 0.4 55 75 | 57 3 -78. 26.5 -4.5 0.4 56 76 | 58 3 -77. 28. 0. 0.4 57 77 | 59 3 -76.5 29.5 3.5 0.4 58 78 | 60 3 -32. 8.5 -29. 0.4 35 79 | 61 3 -38. 15. -24.5 0.4 60 80 | 62 3 -45.5 22. -22.5 0.4 61 81 | 63 3 -52. 27.5 -20. 0.4 62 82 | 64 3 -58.5 33.5 -17. 0.4 63 83 | 65 3 -63. 40. -15. 0.4 64 84 | 66 3 -68.5 47.5 -13.5 0.4 65 85 | 67 1 -9.75 -1.5110 -21.67 14.16 1 86 | 68 1 -3.45 0.795 -15.44 11.89 67 87 | 69 3 -4.8 1.088 -17.57 2.550 68 88 | 70 3 -2.80 10.59 -8.066 2.550 69 89 | 71 3 -2.6 10.59 -8.066 2.550 70 90 | 72 3 -2.5 10.59 -8.066 2.550 71 91 | 73 3 -2.4 10.59 -8.066 2.550 72 92 | 74 3 -2.30 10.59 -8.066 2.550 73 93 | 75 3 -5.8 11.59 1.934 0.45 74 94 | 76 3 -8.3 14.59 8.9340 0.45 75 95 | 77 3 -9.3 19.09 12.93 0.45 76 96 | 78 3 -9.8 25.59 15.93 0.45 77 97 | 79 3 -12.8 30.59 19.43 0.45 78 98 | 80 3 -15.8 35.09 22.43 0.45 79 99 | 81 3 -18.8 37.09 25.93 0.45 80 100 | 82 3 -19.3 38.59 28.93 0.45 81 101 | 83 3 -18.8 40.59 32.43 0.45 82 102 | 84 3 -15.8 43.59 37.43 0.45 83 103 | 85 3 -12.3 46.09 40.93 0.45 84 104 | 86 3 -9.8 49.59 43.93 0.45 85 105 | 87 3 -10.3 54.59 47.93 0.45 86 106 | 88 3 -11.8 62.09 51.43 0.45 87 107 | 89 3 -13.8 70.09 53.93 0.45 88 108 | 90 3 -6.3 14.59 -7.066 1.40 74 109 | 91 3 -10.3 19.09 -7.066 1.40 90 110 | 92 3 -14.8 24.59 -7.066 1.40 91 111 | 93 3 -19.3 26.09 -8.066 1. 92 112 | 94 3 -25.3 29.09 -9.066 0.43 93 113 | 95 3 -35.80 33.09 -10.07 0.43 94 114 | 96 3 -47.80 37.09 -11.07 0.43 95 115 | 97 3 -59.80 40.09 -12.57 0.43 96 116 | 98 3 -68.8 40.59 -14.57 0.43 97 117 | 99 3 -78.3 38.59 -17.57 0.43 98 118 | 100 3 -17.8 28.09 -9.066 0.420 93 119 | 101 3 -17.3 32.09 -5.566 0.420 100 120 | 102 3 -17.8 38.09 0.434 0.420 101 121 | 103 3 -19.3 45.59 6.934 0.420 102 122 | 104 3 -23.3 55.09 8.9340 0.420 103 123 | 105 3 -28.8 66.09 8.4340 0.420 104 124 | 106 3 -36.80 77.59 10.43 0.420 105 125 | 107 3 -42.30 90.09 13.43 0.420 106 126 | 108 3 -46.30 103.60 17.93 0.420 107 127 | 109 3 -13.3 28.59 -18.07 0.55 92 128 | 110 3 -14.3 35.09 -26.57 0.55 109 129 | 111 3 -18.8 44.09 -32.07 0.55 110 130 | 112 3 -22.8 46.09 -43.07 0.4 111 131 | 113 3 -29.3 50.09 -48.07 0.4 112 132 | 114 3 -34.80 55.59 -54.07 0.4 113 133 | 115 3 -38.80 62.59 -58.07 0.4 114 134 | 116 3 -42.30 70.59 -60.07 0.4 115 135 | 117 3 -25.3 51.59 -44.07 0.4 112 136 | 118 3 -27.8 57.09 -47.57 0.4 117 137 | 119 3 -29.8 61.59 -56.07 0.4 118 138 | 120 3 -33.3 65.09 -67.070 0.4 119 139 | 121 3 -17.8 48.09 -31.57 0.4 111 140 | 122 3 -16.3 53.59 -29.07 0.4 121 141 | 123 3 -16.3 59.59 -29.07 0.4 122 142 | 124 3 -15.8 65.09 -27.57 0.4 123 143 | 125 3 -15.3 70.09 -29.07 0.4 124 144 | 126 3 -12.8 75.09 -27.07 0.4 125 145 | 127 3 -11.3 80.09 -28.57 0.4 126 146 | 128 3 -9.3 85.09 -29.57 0.4 127 147 | 129 3 -8.3 91.09 -31.07 0.4 128 148 | 130 3 -4.3 15.59 -6.066 0.4 73 149 | 131 3 -5.8 20.59 -3.0660 0.4 130 150 | 132 3 -7.3 25.09 0.934 0.4 131 151 | 133 3 -7.3 29.59 4.434 0.4 132 152 | 134 3 -6.8 34.09 8.9340 0.4 133 153 | 135 3 -5.3 37.59 12.43 0.4 134 154 | 136 3 -3.80 42.09 13.43 0.4 135 155 | 137 3 0.2 47.59 15.43 0.4 136 156 | 138 3 4.7 52.59 17.93 0.4 137 157 | 139 3 9.20 55.09 22.43 0.4 138 158 | 140 3 12.20 55.59 27.43 0.4 139 159 | 141 3 14.70 56.59 31.93 0.4 140 160 | 142 3 15.70 59.09 36.43 0.4 141 161 | 143 3 16.2 62.09 39.43 0.4 142 162 | 144 3 17.7 65.59 41.43 0.4 143 163 | 145 3 21.7 69.09 43.43 0.4 144 164 | 146 3 -3.80 16.09 -10.57 0.5 72 165 | 147 3 -4.3 21.09 -12.07 0.5 146 166 | 148 3 -4.3 26.09 -12.57 0.5 147 167 | 149 3 -3.80 31.09 -13.57 0.5 148 168 | 150 3 -1.8 15.59 -7.066 0.470 71 169 | 151 3 1.2 21.09 -9.066 0.470 150 170 | 152 3 5.2 27.59 -13.57 0.470 151 171 | 153 3 4.2 34.09 -14.07 0.4 152 172 | 154 3 4.2 41.09 -15.57 0.4 153 173 | 155 3 4.2 47.09 -17.07 0.4 154 174 | 156 3 3.7 51.59 -16.07 0.4 155 175 | 157 3 1.7 54.09 -13.57 0.4 156 176 | 158 3 9.70 31.59 -16.07 0.4 152 177 | 159 3 14.20 35.59 -17.57 0.4 158 178 | 160 3 20.2 39.09 -17.57 0.4 159 179 | 161 3 25.2 40.59 -17.57 0.4 160 180 | 162 3 30.2 42.09 -17.57 0.4 161 181 | 163 3 34.2 42.59 -14.07 0.4 162 182 | 164 3 38.7 43.09 -10.57 0.4 163 183 | 165 3 43.7 45.09 -6.566 0.4 164 184 | 166 3 48.7 49.59 -5.566 0.4 165 185 | 167 3 0.70 13.09 -7.066 1.3 70 186 | 168 3 3.2 17.09 -7.066 1.3 167 187 | 169 3 4.7 21.59 -7.066 1.3 168 188 | 170 3 9.20 23.09 -7.066 0.4 169 189 | 171 3 15.20 25.59 -6.566 0.4 170 190 | 172 3 21.7 28.09 -6.566 0.4 171 191 | 173 3 28.2 31.09 -6.566 0.4 172 192 | 174 3 36.2 33.09 -6.566 0.4 173 193 | 175 3 42.7 35.59 -8.066 0.4 174 194 | 176 3 49.2 38.59 -10.07 0.4 175 195 | 177 3 54.2 43.09 -14.07 0.4 176 196 | 178 3 59.7 49.59 -17.57 0.4 177 197 | 179 3 8.70 28.09 4.934 1. 169 198 | 180 3 8.8 28.09 4.934 0.950 179 199 | 181 3 9. 28.09 4.934 0.950 180 200 | 182 3 7.2 30.09 19.43 0.4 181 201 | 183 3 6.7 32.09 27.43 0.4 182 202 | 184 3 5.7 29.59 7.934 0.4 181 203 | 185 3 1.7 32.59 8.9340 0.4 184 204 | 186 3 -1.3 36.09 10.43 0.4 185 205 | 187 3 -3.30 41.09 12.93 0.4 186 206 | 188 3 -2.30 47.59 17.43 0.4 187 207 | 189 3 -0.3 52.09 22.43 0.4 188 208 | 190 3 2.2 55.59 27.43 0.4 189 209 | 191 3 4.2 56.59 30.93 0.4 190 210 | 192 3 5.7 58.09 33.93 0.4 191 211 | 193 3 6.7 59.59 36.93 0.4 192 212 | 194 3 8.2 31.59 7.934 0.4 184 213 | 195 3 10.20 35.09 11.93 0.4 194 214 | 196 3 14.70 39.09 13.93 0.4 195 215 | 197 3 21.7 41.59 14.93 0.4 196 216 | 198 3 27.2 45.59 14.43 0.4 197 217 | 199 3 31.7 49.59 14.43 0.4 198 218 | 200 3 35.2 52.59 14.93 0.4 199 219 | 201 3 38.7 54.59 15.43 0.4 200 220 | 202 3 42.2 56.09 17.93 0.4 201 221 | 203 3 46.2 58.59 20.93 0.4 202 222 | 204 3 50.7 62.09 25.93 0.4 203 223 | 205 3 9.70 32.09 7.434 0.4 194 224 | 206 3 13.20 35.59 9.9340 0.4 205 225 | 207 3 18.7 39.09 12.93 0.4 206 226 | 208 3 24.7 43.09 15.93 0.4 207 227 | 209 3 31.2 48.09 16.93 0.4 208 228 | 210 3 38.2 52.59 16.93 0.4 209 229 | 211 3 45.7 56.09 17.93 0.4 210 230 | 212 3 12.20 28.09 8.9340 0.5 180 231 | 213 3 17.7 28.09 12.93 0.5 212 232 | 214 3 22.2 27.09 4.934 0.4150 213 233 | 215 3 25.2 23.59 1.934 0.4 214 234 | 216 3 31.2 21.59 -0.5660 0.4 215 235 | 217 3 37.7 21.59 1.434 0.4 216 236 | 218 3 43.7 23.59 2.434 0.4 217 237 | 219 3 50.2 24.09 5.934 0.4 218 238 | 220 3 57.2 24.09 7.434 0.4 219 239 | 221 3 64.7 22.59 10.43 0.4 220 240 | 222 3 26.7 29.09 7.934 0.4 214 241 | 223 3 33.7 31.59 7.434 0.4 222 242 | 224 3 41.2 34.09 2.934 0.4 223 243 | 225 3 49.7 36.59 2.434 0.4 224 244 | 226 3 55.2 39.59 -0.0659 0.4 225 245 | 227 3 59.7 42.59 -3.0660 0.4 226 246 | 228 3 19.7 30.09 11.93 0.4150 213 247 | 229 3 22.7 32.59 10.43 0.4150 228 248 | 230 3 26.7 35.09 8.9340 0.4150 229 249 | 231 3 26.8 35.09 8.9340 0.4150 230 250 | 232 3 31.2 36.09 8.9340 0.4 231 251 | 233 3 35.7 38.09 10.43 0.4 232 252 | 234 3 40.2 41.59 10.43 0.4 233 253 | 235 3 43.7 45.09 8.9340 0.4 234 254 | 236 3 46.2 49.59 6.434 0.4 235 255 | 237 3 48.2 55.09 6.434 0.4 236 256 | 238 3 51.2 62.09 10.43 0.4 237 257 | 239 3 52.7 69.09 11.43 0.4 238 258 | 240 3 55.2 76.09 15.43 0.4 239 259 | 241 3 57.2 81.09 16.93 0.4 240 260 | 242 3 61.7 85.59 22.43 0.4 241 261 | 243 3 66.2 88.59 23.43 0.4 242 262 | 244 3 30.7 37.59 13.43 0.4 231 263 | 245 3 34.7 40.09 14.93 0.4 244 264 | 246 3 39.2 42.59 15.43 0.4 245 265 | 247 3 45.7 44.09 15.43 0.4 246 266 | 248 3 52.7 45.09 15.93 0.4 247 267 | 249 3 58.7 45.09 15.43 0.4 248 268 | 250 3 63.7 44.59 15.43 0.4 249 269 | 251 3 69.2 46.09 14.43 0.4 250 270 | 252 3 75.7 50.09 12.93 0.4 251 271 | 253 3 28.2 38.59 10.43 0.4 230 272 | 254 3 30.7 42.59 11.93 0.4 253 273 | 255 3 34.7 46.59 12.93 0.4 254 274 | 256 3 38.2 51.09 13.93 0.4 255 275 | 257 3 41.7 55.59 15.93 0.4 256 276 | 258 3 44.2 62.59 18.93 0.4 257 277 | 259 3 47.2 67.59 22.43 0.4 258 278 | 260 3 50.2 72.09 26.93 0.4 259 279 | 261 3 53.2 74.59 30.93 0.4 260 280 | 262 3 56.2 77.59 33.93 0.4 261 281 | 263 3 59.2 81.09 34.93 0.4 262 282 | 264 3 62.7 84.59 34.93 0.4 263 283 | 265 3 66.2 89.09 33.93 0.4 264 284 | 266 3 9.70 29.09 -3.0660 0.70 179 285 | 267 3 15.20 31.59 -3.5660 0.4 266 286 | 268 3 21.7 34.09 -5.066 0.4 267 287 | 269 3 29.7 37.59 -6.566 0.4 268 288 | 270 3 35.7 41.09 -7.066 0.4 269 289 | 271 3 40.7 45.09 -7.066 0.4 270 290 | 272 3 42.7 49.09 -7.066 0.4 271 291 | 273 3 42.7 52.59 -7.066 0.4 272 292 | 274 3 12.70 35.09 -7.066 0.4 266 293 | 275 3 16.2 41.09 -13.57 0.4 274 294 | 276 3 17.2 44.59 -24.07 0.4 275 295 | 277 3 15.70 45.59 -33.57 0.4 276 296 | 278 3 2.7 24.09 -5.066 0.4 168 297 | 279 3 0.70 28.09 -3.5660 0.4 278 298 | 280 3 -3.30 32.59 -4.566 0.4 279 299 | 281 3 -7.8 37.59 -5.066 0.4 280 300 | 282 3 -13.3 41.59 -8.566 0.4 281 301 | 283 3 -19.3 45.59 -12.07 0.4 282 302 | 284 3 -26.3 48.09 -13.57 0.4 283 303 | 285 3 -33.8 50.09 -12.07 0.4 284 304 | 286 1 -0.75 1.875 -11.42 7.692 68 305 | 287 3 -1.5 3. -5. 0.480 286 306 | 288 3 -1. 2.5 16. 0.480 287 307 | 289 3 -1. 1.5 38. 0.480 288 308 | 290 3 -1. 0. 52.5 0.480 289 309 | 291 3 -2. -2. 63.5 0.480 290 310 | 292 3 -3. -3.5 65. 0.480 291 311 | 293 3 -5. -5. 65. 0.480 292 312 | 294 3 -7.5 -4.5 65. 0.480 293 313 | 295 3 -9.5 -3. 63. 0.480 294 314 | 296 3 -10. 0. 56.5 0.480 295 315 | 297 3 -9. 2.5 50. 0.480 296 316 | 298 3 -7. 4.5 45. 0.480 297 317 | 299 3 -5. 5.5 42. 0.480 298 318 | 300 3 -4.5 7. 39. 0.480 299 319 | 301 3 -6.5 7.5 36. 0.480 300 320 | 302 3 -9. 8.5 36. 0.480 301 321 | 303 3 -10. 10. 36. 0.480 302 322 | 304 3 -9.5 12. 36. 0.480 303 323 | 305 3 -8. 13. 36. 0.480 304 324 | 306 3 -6. 13.5 40. 0.480 305 325 | 307 3 -4.5 14. 44.5 0.480 306 326 | 308 3 -4.5 15. 48. 0.480 307 327 | 309 3 -5. 16. 47. 0.480 308 328 | 310 3 -7. 17. 46. 0.480 309 329 | 311 3 -7.5 18. 47.5 0.480 310 330 | 312 3 -7.5 19. 49.5 0.480 311 331 | 313 3 -7. 20.5 53.5 0.480 312 332 | 314 3 -6.5 22. 55. 0.480 313 333 | 315 3 -6.5 23.5 57.5 0.480 314 334 | 316 3 -6.5 25. 59.5 0.480 315 335 | 317 3 -7. 27. 67.5 0.480 316 336 | 318 3 -9. 27.5 71. 0.480 317 337 | 319 3 -10. 29.5 75.5 0.480 318 338 | 320 3 -10. 32. 77. 0.480 319 339 | 321 1 1.5 3. -9. 1.85 286 340 | 322 3 7. -3. -5. 1.40 321 341 | 323 3 7.5 -4. 2.5 1.40 322 342 | 324 3 9. -6. 7.5 1.40 323 343 | 325 3 11. -8. 10.5 0.65 324 344 | 326 3 14. -8. 11. 0.65 325 345 | 327 3 17. -7.5 12.5 0.65 326 346 | 328 3 20.5 -6.5 14. 0.65 327 347 | 329 3 23.5 -4.5 13.5 0.65 328 348 | 330 3 27. -2.5 13. 0.65 329 349 | 331 3 27.1 -2.5 13. 1.1 330 350 | 332 3 29.5 -4. 15. 0.480 331 351 | 333 3 33. -5.5 18. 0.480 332 352 | 334 3 36.5 -8. 21.5 0.480 333 353 | 335 3 40. -9.5 23. 0.480 334 354 | 336 3 43. -9.5 24. 0.480 335 355 | 337 3 46.5 -7.5 24. 0.480 336 356 | 338 3 49.5 -6. 24. 0.480 337 357 | 339 3 53. -4.5 24. 0.480 338 358 | 340 3 56.5 -4. 25. 0.480 339 359 | 341 3 28. 0. 14.5 0.465 331 360 | 342 3 29.5 2. 15.5 0.465 341 361 | 343 3 31.5 4.5 15.5 0.465 342 362 | 344 3 33.5 7. 19. 0.465 343 363 | 345 3 35. 9.5 23. 0.465 344 364 | 346 3 37. 11. 29.5 0.465 345 365 | 347 3 39. 12.5 33.5 0.465 346 366 | 348 3 41.5 13.5 39. 0.465 347 367 | 349 3 44.5 15. 45. 0.465 348 368 | 350 3 47. 15.5 51.5 0.465 349 369 | 351 3 50. 16.5 55. 0.465 350 370 | 352 3 53. 18. 56. 0.465 351 371 | 353 3 55.5 19. 56. 0.465 352 372 | 354 3 57.5 20.5 56. 0.465 353 373 | 355 3 59. 22. 56. 0.465 354 374 | 356 3 60.5 22. 57. 0.465 355 375 | 357 3 63.5 21. 60.5 0.465 356 376 | 358 3 67. 20. 66.5 0.465 357 377 | 359 3 29. -0.5 11. 0.470 330 378 | 360 3 31.5 1. 10.5 0.470 359 379 | 361 3 34. 4. 10.5 0.470 360 380 | 362 3 37. 6.5 12. 0.470 361 381 | 363 3 39.5 8.5 15.5 0.470 362 382 | 364 3 42.5 10. 18.5 0.470 363 383 | 365 3 45. 11. 21.5 0.470 364 384 | 366 3 47.5 11.5 23.5 0.470 365 385 | 367 3 50. 11.5 27. 0.470 366 386 | 368 3 53. 12.5 30.5 0.470 367 387 | 369 3 57. 14. 33. 0.470 368 388 | 370 3 61. 15.5 35. 0.470 369 389 | 371 3 65.5 17. 38.5 0.470 370 390 | 372 3 69. 17.5 42. 0.470 371 391 | 373 3 72. 17.5 45. 0.470 372 392 | 374 3 75.5 17. 47. 0.4 373 393 | 375 3 79.5 17. 49. 0.4 374 394 | 376 3 83. 16.5 50.5 0.4 375 395 | 377 3 87. 16.5 50.5 0.4 376 396 | 378 3 91.5 16. 50.5 0.4 377 397 | 379 3 96. 17. 53.5 0.4 378 398 | 380 3 100. 19. 60. 0.4 379 399 | 381 3 74.5 18.5 38. 0.4 373 400 | 382 3 77. 20. 34.5 0.4 381 401 | 383 3 81. 21.5 34.5 0.4 382 402 | 384 3 86.5 24.5 34.5 0.4 383 403 | 385 3 12. -10. 10.5 0.6 325 404 | 386 3 15. -11. 14. 0.6 385 405 | 387 3 17.5 -12. 19.5 0.6 386 406 | 388 3 18.5 -14. 23.5 0.6 387 407 | 389 3 18. -16.5 26.5 0.6 388 408 | 390 3 17. -19. 30.5 0.6 389 409 | 391 3 14. -20. 31.5 0.465 390 410 | 392 3 12. -22. 35. 0.465 391 411 | 393 3 11.5 -24.5 40.5 0.465 392 412 | 394 3 12.5 -27.5 42.5 0.465 393 413 | 395 3 15. -29.5 41. 0.465 394 414 | 396 3 18. -21. 28. 0.46 390 415 | 397 3 19.5 -23.5 26.5 0.46 396 416 | 398 3 21. -24.5 23.5 0.46 397 417 | 399 3 23. -24. 22. 0.46 398 418 | 400 3 25.5 -22.5 22. 0.46 399 419 | 401 3 27.5 -21.5 27. 0.46 400 420 | 402 3 30. -21.5 34.5 0.46 401 421 | 403 3 31.5 -20. 39.5 0.455 402 422 | 404 3 33. -19.5 45. 0.455 403 423 | 405 3 34.5 -20. 50.5 0.455 404 424 | 406 3 35. -19. 58. 0.455 405 425 | 407 3 36.5 -18. 63. 0.455 406 426 | 408 3 37.5 -15. 66.5 0.455 407 427 | 409 3 40. -13. 68. 0.455 408 428 | 410 3 42.5 -10.5 72. 0.455 409 429 | 411 3 32.5 -22. 36. 0.455 402 430 | 412 3 35. -23. 37. 0.455 411 431 | 413 1 1.5 8. -1.5 0.8 321 432 | 414 3 1.7 10.59 -6.066 0.4 413 433 | 415 3 6.7 12.09 -4.066 0.4 414 434 | 416 3 11.70 14.59 -5.566 0.4 415 435 | 417 3 16.7 17.59 -8.066 0.4 416 436 | 418 3 21.2 20.09 -11.57 0.4 417 437 | 419 3 26.2 22.59 -10.57 0.4 418 438 | 420 3 30.7 26.09 -14.57 0.4 419 439 | 421 3 35.7 30.09 -23.07 0.4 420 440 | 422 3 11.5 9. -2.5 0.470 413 441 | 423 3 12. 11. -3.5 0.850 422 442 | 424 3 12.5 15.5 -1.5 0.850 423 443 | 425 3 15. 9. -2.5 0.470 422 444 | 426 3 19.5 8. -2.5 0.470 425 445 | 427 3 23. 8. -2.5 0.470 426 446 | 428 3 25.5 9.5 -2.5 0.470 427 447 | 429 3 30.5 11.5 -2.5 0.470 428 448 | 430 3 35. 13. -2.5 0.470 429 449 | 431 3 40.5 18.5 -2.5 0.470 430 450 | 432 3 45. 21.5 -2.5 0.470 431 451 | 433 3 53.5 23. -2.5 0.470 432 452 | 434 3 5.5 9.5 -13. 2. 413 453 | 435 3 12. 16.5 -18.5 2. 434 454 | 436 3 14.5 14. -19. 0.4 435 455 | 437 3 18.5 12. -19.5 0.4 436 456 | 438 3 23. 10.5 -19. 0.4 437 457 | 439 3 28. 9. -16. 0.4 438 458 | 440 3 32. 8. -13. 0.4 439 459 | 441 3 36.5 6. -10. 0.4 440 460 | 442 3 41. 5. -13. 0.4 441 461 | 443 3 44.5 3. -16. 0.4 442 462 | 444 3 47.5 1.5 -20. 0.4 443 463 | 445 3 50.5 2. -20. 0.4 444 464 | 446 3 54. 3.5 -25.5 0.4 445 465 | 447 3 57.5 6. -36. 0.4 446 466 | 448 3 11.5 17.5 0. 1.650 435 467 | 449 3 9. 18.5 0. 0.410 448 468 | 450 3 6.5 21.5 0. 0.410 449 469 | 451 3 3.5 26. 0.5 0.410 450 470 | 452 3 1. 32.5 3.5 0.410 451 471 | 453 3 -2. 40.5 9. 0.410 452 472 | 454 3 -0.5 46. 8.5 0.4 453 473 | 455 3 0.5 51. 9. 0.4 454 474 | 456 3 4. 56. 9. 0.4 455 475 | 457 3 7.5 61. 9.5 0.4 456 476 | 458 3 11. 64. 9. 0.4 457 477 | 459 3 13.5 64. 9.5 0.4 458 478 | 460 3 15.5 63.5 10.5 0.4 459 479 | 461 3 -4. 42.5 8.5 0.410 453 480 | 462 3 -7. 44.5 7. 0.410 461 481 | 463 3 -9.5 47.5 7.5 0.410 462 482 | 464 3 -13. 50.5 9.5 0.410 463 483 | 465 3 -15.5 52.5 13. 0.410 464 484 | 466 3 -17. 54. 16.5 0.410 465 485 | 467 3 -16.5 55. 22. 0.410 466 486 | 468 3 -15. 56. 26. 0.410 467 487 | 469 3 -13. 56.5 30.5 0.410 468 488 | 470 3 -10.5 56. 32.5 0.410 469 489 | 471 3 -8. 56. 34.5 0.410 470 490 | 472 3 -6. 57.5 34.5 0.410 471 491 | 473 3 13.5 19. 0. 1.35 448 492 | 474 3 14. 21.5 1.5 0.75 473 493 | 475 3 15. 24. 2.5 0.75 474 494 | 476 3 12.5 25. 2.5 0.4 475 495 | 477 3 11.5 27. 2.5 0.4 476 496 | 478 3 11.5 30. 3. 0.4 477 497 | 479 3 13.5 35. 3.5 0.4 478 498 | 480 3 15.5 40. 4. 0.4 479 499 | 481 3 18. 44. 4. 0.4 480 500 | 482 3 21. 47.5 4. 0.4 481 501 | 483 3 25. 50.5 4. 0.4 482 502 | 484 3 29. 55. 4. 0.4 483 503 | 485 3 33. 59.5 4. 0.4 484 504 | 486 3 36.5 63.5 4. 0.4 485 505 | 487 3 40. 68. 7. 0.4 486 506 | 488 3 43. 72.5 11. 0.4 487 507 | 489 3 46. 76.5 16. 0.4 488 508 | 490 3 47.5 80. 18.5 0.4 489 509 | 491 3 48.5 84.5 21. 0.4 490 510 | 492 3 50.5 88.5 22.5 0.4 491 511 | 493 3 52.5 92. 24. 0.4 492 512 | 494 3 55. 94. 26. 0.4 493 513 | 495 3 56. 97. 27.5 0.4 494 514 | 496 3 57.5 100.5 29. 0.4 495 515 | 497 3 58.5 105. 29. 0.4 496 516 | 498 3 59.5 110. 29. 0.4 497 517 | 499 3 60. 115.5 29. 0.4 498 518 | 500 3 61. 121. 29. 0.4 499 519 | 501 3 15. 26.5 0.5 0.4 475 520 | 502 3 17. 29.5 4.5 0.4 501 521 | 503 3 19. 34. 9. 0.4 502 522 | 504 3 22.5 38.5 13.5 0.4 503 523 | 505 3 24.5 42.5 15.5 0.4 504 524 | 506 3 27.5 44.5 19.5 0.4 505 525 | 507 3 31.5 45. 23.5 0.4 506 526 | 508 3 37.5 44.5 26.5 0.4 507 527 | 509 3 44. 44.5 28.5 0.4 508 528 | 510 3 50. 45. 30.5 0.4 509 529 | 511 3 57.5 45.5 30.5 0.4 510 530 | 512 3 65. 45.5 32. 0.4 511 531 | 513 3 72.5 45. 34. 0.4 512 532 | 514 3 78.5 43.5 36. 0.4 513 533 | 515 3 84. 41.5 36. 0.4 514 534 | 516 3 89. 39. 35.5 0.4 515 535 | 517 3 94.5 37.5 34.5 0.4 516 536 | 518 3 17. 24.5 -2.5 0.8 474 537 | 519 3 19. 29. -3. 0.8 518 538 | 520 3 20. 32.5 -2.5 0.8 519 539 | 521 3 21. 35. -2.5 0.4 520 540 | 522 3 24. 38. -2.5 0.4 521 541 | 523 3 27.5 41. 0. 0.4 522 542 | 524 3 32.5 44. 5. 0.4 523 543 | 525 3 36.5 45.5 4.5 0.4 524 544 | 526 3 42. 48.5 4. 0.4 525 545 | 527 3 47. 52. 4. 0.4 526 546 | 528 3 51. 55. 4. 0.4 527 547 | 529 3 37. 45. 10. 0.4 524 548 | 530 3 40. 46. -1.5 0.4 529 549 | 531 3 42. 47. -30.5 0.4 530 550 | 532 3 25. 35. -1.5 0.4 520 551 | 533 3 30. 38. -1.5 0.4 532 552 | 534 3 35.5 40.5 -2.5 0.4 533 553 | 535 3 41. 42. -2.5 0.4 534 554 | 536 3 48. 43.5 -2.5 0.4 535 555 | 537 3 54.5 45. -3. 0.4 536 556 | 538 3 60.5 48. -3.5 0.4 537 557 | 539 3 65.5 52.5 -5. 0.4 538 558 | 540 3 15.5 19. 0. 1. 473 559 | 541 3 18.5 20. 0. 1. 540 560 | 542 3 24.5 19. 0. 0.8 541 561 | 543 3 24.6 19. 0. 0.70 542 562 | 544 3 25.5 14.5 3. 0.4 543 563 | 545 3 27. 10. 6. 0.4 544 564 | 546 3 28. 6.5 7.5 0.4 545 565 | 547 3 30.5 3.5 9. 0.4 546 566 | 548 3 31.5 1. 9. 0.4 547 567 | 549 3 33. -0.5 9. 0.4 548 568 | 550 3 34.5 -2. 9. 0.4 549 569 | 551 3 39. -2.5 10. 0.4 550 570 | 552 3 45.5 -3. 11.5 0.4 551 571 | 553 3 52.5 -3. 13.5 0.4 552 572 | 554 3 58. -3. 14. 0.4 553 573 | 555 3 64. -4.5 15.5 0.4 554 574 | 556 3 69.5 -6. 17. 0.4 555 575 | 557 3 75.5 -9.5 15.5 0.4 556 576 | 558 3 80. -12.5 13. 0.4 557 577 | 559 3 83.5 -16.5 10.5 0.4 558 578 | 560 3 87.5 -19.5 11. 0.4 559 579 | 561 3 92. -23. 12.5 0.4 560 580 | 562 3 96.5 -26. 15.5 0.4 561 581 | 563 3 99. -29. 15.5 0.4 562 582 | 564 3 99. -32.5 13. 0.4 563 583 | 565 3 28.5 19. 1.5 0.4 543 584 | 566 3 32. 19. 2.5 0.4 565 585 | 567 3 35.5 19. 2.5 0.4 566 586 | 568 3 38. 18. 6. 0.4 567 587 | 569 3 41. 18. 6.5 0.4 568 588 | 570 3 43.5 19. 7.5 0.4 569 589 | 571 3 47. 21. 5. 0.4 570 590 | 572 3 50.5 23. 5. 0.4 571 591 | 573 3 56.5 23.5 6.5 0.4 572 592 | 574 3 63.5 25. 8. 0.4 573 593 | 575 3 70. 26.5 9.5 0.4 574 594 | 576 3 75.5 28.5 7.5 0.4 575 595 | 577 3 80.5 30.5 7. 0.4 576 596 | 578 3 86. 33. 7. 0.4 577 597 | 579 3 91.5 33.5 10.5 0.4 578 598 | 580 3 96. 34.5 12. 0.4 579 599 | 581 3 100.5 35. 14. 0.4 580 600 | 582 3 105. 36.5 13. 0.4 581 601 | 583 3 28. 21. -1. 0.4 542 602 | 584 3 33.5 22.5 -1. 0.4 583 603 | 585 3 39. 24. 0. 0.4 584 604 | 586 3 44. 25. 0. 0.4 585 605 | 587 3 47.5 26.5 0. 0.4 586 606 | 588 3 50.5 26.5 0. 0.4 587 607 | 589 3 55.5 28. 0. 0.4 588 608 | 590 3 63. 28.5 0. 0.4 589 609 | 591 3 70. 30.5 1. 0.4 590 610 | 592 3 77. 32.5 2.5 0.4 591 611 | 593 3 81.5 35.5 7. 0.4 592 612 | 594 3 86.5 39. 10. 0.4 593 613 | 595 3 90.5 42.5 14. 0.4 594 614 | 596 3 92.5 46. 14. 0.4 595 615 | 597 3 93. 50. 13. 0.4 596 616 | 598 3 19. 22.5 0. 0.55 541 617 | 599 3 23. 22.5 0. 0.4 598 618 | 600 3 26. 23.5 -0.5 0.4 599 619 | 601 3 28.5 25.5 -1.5 0.4 600 620 | 602 3 31.5 27. -2.5 0.4 601 621 | 603 3 35. 28.5 -1.5 0.4 602 622 | 604 3 38.5 31. -0.5 0.4 603 623 | 605 3 40.5 34. -1. 0.4 604 624 | 606 3 40. 36.5 -8. 0.4 605 625 | 607 3 39. 38.5 -23. 0.4 606 626 | 608 3 38. 39. -44. 0.4 607 627 | 609 3 22.5 25. 1.5 0.4 598 628 | 610 3 26.5 27.5 2.5 0.4 609 629 | 611 3 30.5 30.5 2.5 0.4 610 630 | 612 3 33.5 32.5 3.5 0.4 611 631 | 613 3 36.5 35.5 4. 0.4 612 632 | 614 3 39.5 39.5 4. 0.4 613 633 | 615 3 43.5 44.5 7. 0.4 614 634 | 616 3 49. 47.5 10. 0.4 615 635 | 617 3 54. 51. 13. 0.4 616 636 | 618 3 60.5 53. 13. 0.4 617 637 | 619 3 64. 57.5 12. 0.4 618 638 | 620 3 67. 63.5 10.5 0.4 619 639 | 621 3 29. 31. 0.5 0.4 611 640 | 622 3 28.5 33. 1.5 0.4 621 641 | 623 3 29.5 36. 3. 0.4 622 642 | 624 3 32.5 38.5 5. 0.4 623 643 | 625 3 37. 42.5 5. 0.4 624 644 | 626 3 41. 45.5 5. 0.4 625 645 | 627 3 45. 49. 5. 0.4 626 646 | 628 3 48. 51.5 6. 0.4 627 647 | 629 3 51.5 53. 7. 0.4 628 648 | 630 3 55.5 54.5 8. 0.4 629 649 | 631 3 59.5 55.5 9.5 0.4 630 650 | 632 3 63.5 56.5 11. 0.4 631 651 | 633 3 67. 58.5 13. 0.4 632 652 | 634 3 70.5 60.5 14. 0.4 633 653 | 635 3 73.5 62.5 15. 0.4 634 654 | 636 3 77.5 65. 16. 0.4 635 655 | 637 3 82.5 67. 16.5 0.4 636 656 | 638 3 87. 68.5 17.5 0.4 637 657 | 639 3 89.5 70. 19. 0.4 638 658 | 640 3 91.5 71.5 21.5 0.4 639 659 | 641 3 93. 73.5 23.5 0.4 640 660 | 642 3 95.5 75. 25. 0.4 641 661 | 643 3 98.5 76.5 27. 0.4 642 662 | 644 3 101.5 79.5 32. 0.4 643 663 | 645 3 4. 9.5 -3.5 0.8 413 664 | 646 3 7.7 9.5 -3.5 2.80 645 665 | 647 3 7.5 14.5 -1. 1.55 646 666 | 648 3 3.5 11.5 -3.5 0.9 645 667 | 649 3 2. 13.5 -1.5 0.9 648 668 | 650 3 0. 13.5 -5. 0.455 321 669 | 651 3 2. 14. -2.5 0.455 650 670 | 652 3 4.5 14.5 0.5 0.455 651 671 | 653 3 6.5 16. 4. 0.455 652 672 | 654 3 8.5 17. 7.5 0.455 653 673 | 655 3 10. 18.5 11. 0.455 654 674 | 656 3 12. 18.5 12.5 0.455 655 675 | 657 3 14. 19. 15. 0.455 656 676 | 658 3 16. 19. 16.5 0.455 657 677 | 659 3 18. 20. 18.5 0.455 658 678 | 660 3 21. 21. 21. 0.455 659 679 | 661 3 24.5 22.5 26.5 0.465 660 680 | 662 3 28. 24. 31.5 0.465 661 681 | 663 3 31. 26. 34.5 0.465 662 682 | 664 3 33.5 29. 36. 0.465 663 683 | 665 3 35.5 32. 36.5 0.465 664 684 | 666 3 38. 34.5 39.5 0.465 665 685 | 667 3 41.5 34.5 42. 0.465 666 686 | 668 3 45. 33.5 48.5 0.465 667 687 | 669 3 48. 33.5 52.5 0.465 668 688 | 670 3 50. 34.5 56.5 0.465 669 689 | 671 3 52.5 35.5 58. 0.465 670 690 | 672 3 55.5 34.5 59.5 0.465 671 691 | 673 3 58.5 34.5 61.5 0.465 672 692 | 674 3 60. 35. 64. 0.465 673 693 | 675 3 59.5 36.5 68. 0.465 674 694 | 676 3 24.5 25. 34. 0.43 661 695 | 677 3 25.5 28. 42. 0.43 676 696 | 678 3 26.5 30.5 47. 0.43 677 697 | 679 3 28.5 33. 50.5 0.43 678 698 | 680 3 31. 35. 51. 0.43 679 699 | 681 3 33.5 37.5 52. 0.43 680 700 | 682 3 36. 41.5 54.5 0.43 681 701 | 683 3 38. 45.5 57. 0.43 682 702 | 684 3 39.5 49.5 59. 0.43 683 703 | 685 3 41. 52.5 60. 0.43 684 704 | 686 3 42. 55.5 63. 0.43 685 705 | 687 3 42.5 58.5 63. 0.43 686 706 | 688 3 42.5 62.5 61. 0.43 687 707 | 689 3 1.5 5.5 0. 0.455 321 708 | 690 3 3.5 8.5 5.5 0.455 689 709 | 691 3 6. 10. 9. 0.455 690 710 | 692 3 9. 9.5 13. 0.455 691 711 | 693 3 12.5 9. 17. 0.455 692 712 | 694 3 15. 9.5 22. 0.455 693 713 | 695 3 17. 11.5 25. 0.455 694 714 | 696 3 18.5 13.5 29. 0.455 695 715 | 697 3 21.5 14.5 35.5 0.455 696 716 | 698 3 24. 16. 41.5 0.455 697 717 | 699 3 26.5 16. 49.5 0.455 698 718 | 700 3 29.5 17. 55. 0.455 699 719 | 701 3 33. 18. 58.5 0.455 700 720 | 702 3 37.5 18.5 61.5 0.455 701 721 | 703 3 42. 18.5 63.5 0.455 702 722 | 704 3 47. 18.5 66.5 0.455 703 723 | 705 3 6. 3.5 -9. 1.85 321 724 | 706 3 7.5 4.5 -10. 1.85 705 725 | 707 3 9.5 5. -10. 0.8 706 726 | 708 3 13.5 8.5 -10. 0.8 707 727 | 709 3 15.5 10. -9.5 0.8 708 728 | 710 3 14. 12. -9.5 0.4 709 729 | 711 3 15.5 14. -9.5 0.4 710 730 | 712 3 15.5 16. -9.5 0.4 711 731 | 713 3 13. 18. -9. 0.4 712 732 | 714 3 12. 18.5 -9. 0.4 713 733 | 715 3 10.5 19.5 -9. 0.4 714 734 | 716 3 8.5 21.5 -9. 0.4 715 735 | 717 3 7. 23.5 -10. 0.4 716 736 | 718 3 14.5 18. -8.5 0.4 713 737 | 719 3 14. 19. -8.5 0.4 718 738 | 720 3 13. 20.5 -8.5 0.4 719 739 | 721 3 11.5 20.5 -8.5 0.4 720 740 | 722 3 17.5 10. -7.5 0.4 709 741 | 723 3 20. 10. -10.5 0.4 722 742 | 724 3 23.5 8.5 -10. 0.4 723 743 | 725 3 30. 7.5 -10. 0.4 724 744 | 726 3 32. 7. -10. 0.4 725 745 | 727 3 32.5 5.5 -9. 0.4 726 746 | 728 3 35. 5.5 -9. 0.4 727 747 | 729 3 37.5 4.5 -10.5 0.4 728 748 | 730 3 40.5 2.5 -10. 0.4 729 749 | 731 3 43. 1.5 -10. 0.4 730 750 | 732 3 46. 4.5 -10.5 0.4 731 751 | 733 3 50. 6. -14.5 0.4 732 752 | 734 3 18. 11.5 -10.5 0.4 723 753 | 735 3 12. 12. -10. 0.4 734 754 | 736 3 8.5 13. -10. 0.4 735 755 | 737 3 6. 16. -10. 0.4 736 756 | 738 3 6. 18. -11.5 0.4 737 757 | 739 3 18. 9.5 -8. 0.4 722 758 | 740 3 21. 9. -8. 0.4 739 759 | 741 3 24. 8. -8. 0.4 740 760 | 742 3 21.5 10. -8. 0.4 741 761 | 743 3 20.5 11. -8. 0.4 742 762 | 744 3 25.5 9.5 -8. 0.4 743 763 | 745 3 30. 8.5 -8. 0.4 744 764 | 746 3 33.5 9. -8. 0.4 745 765 | 747 3 38.5 8.5 -8. 0.4 746 766 | 748 3 44.5 7.5 -8. 0.4 747 767 | 749 3 51. 7.5 -8. 0.4 748 768 | 750 3 56. 5.5 -8. 0.4 749 769 | 751 3 63.5 6. -8. 0.4 750 770 | 752 3 69. 5.5 -7.5 0.4 751 771 | 753 3 75. 7. -7. 0.4 752 772 | 754 3 79.5 8.5 -7. 0.4 753 773 | 755 3 85.5 6.5 -7. 0.4 754 774 | 756 3 88. 4. -7. 0.4 755 775 | 757 3 89. 0.5 -7. 0.4 756 776 | 758 3 0.15 1.56 -10.53 2.15 286 777 | 759 3 3.15 -1.44 -0.03 2.15 758 778 | 760 3 7.15 -4.94 7.97 0.850 759 779 | 761 3 4.65 -7.44 11.47 0.850 760 780 | 762 3 3.15 -9.94 13.97 0.850 761 781 | 763 3 3.15 -13.44 15.97 0.850 762 782 | 764 3 4.15 -16.44 18.47 0.6 763 783 | 765 3 4.15 -19.94 21.97 0.6 764 784 | 766 3 3.15 -23.94 24.97 0.6 765 785 | 767 3 2.15 -27.94 27.47 0.6 766 786 | 768 3 1.650 -32.44 27.97 0.6 767 787 | 769 3 2.15 -36.94 27.97 0.6 768 788 | 770 3 2.15 -40.94 30.970 0.6 769 789 | 771 3 2.15 -43.94 33.97 0.6 770 790 | 772 3 3.15 -46.44 36.47 0.6 771 791 | 773 3 4.15 -49.44 35.47 0.6 772 792 | 774 3 4.65 -52.44 34.47 0.6 773 793 | 775 3 4.15 -55.94 38.97 0.6 774 794 | 776 3 4.15 -59.44 43.47 0.6 775 795 | 777 3 5.65 -62.440 47.97 0.6 776 796 | 778 3 7.15 -66.44 47.97 0.6 777 797 | 779 3 6.65 -69.94 47.97 0.6 778 798 | 780 3 6.65 -72.44 48.97 0.6 779 799 | 781 3 8.65 -74.94 51.97 0.6 780 800 | 782 3 4.65 -13.94 20.97 0.6 763 801 | 783 3 5.65 -14.44 26.97 0.6 782 802 | 784 3 5.15 -15.44 30.970 0.6 783 803 | 785 3 3.65 -16.94 33.47 0.6 784 804 | 786 3 1.650 -18.94 33.47 0.6 785 805 | 787 3 -0.350 -21.44 35.47 0.6 786 806 | 788 3 -1.35 -24.44 39.47 0.6 787 807 | 789 3 -1.85 -26.94 43.97 0.6 788 808 | 790 3 -1.85 -27.44 48.47 0.6 789 809 | 791 3 -2.85 -27.44 50.47 0.6 790 810 | 792 3 -4.350 -27.44 52.47 0.6 791 811 | 793 3 -5.850 -27.44 56.47 0.6 792 812 | 794 3 -7.850 -25.94 61.97 0.6 793 813 | 795 3 -9.35 -22.94 64.97 0.6 794 814 | 796 3 -9.85 -20.44 64.97 0.6 795 815 | 797 3 -8.35 -17.44 63.97 0.6 796 816 | 798 3 -7.350 -14.94 63.47 0.6 797 817 | 799 3 -6.850 -11.94 63.47 0.6 798 818 | 800 3 -5.350 -9.94 63.47 0.6 799 819 | 801 3 -2.35 -7.94 64.47 0.6 800 820 | 802 3 -0.850 -6.44 64.47 0.6 801 821 | 803 3 -1.85 -3.44 64.97 0.6 802 822 | 804 3 -1.35 -0.940 64.97 0.6 803 823 | 805 3 -0.350 2.56 65.47 0.6 804 824 | 806 3 -0.850 4.060 64.97 0.6 805 825 | 807 3 -3.85 6.060 64.47 0.6 806 826 | 808 3 -6.350 7.060 58.97 0.6 807 827 | 809 3 -7.850 10.06 53.97 0.6 808 828 | 810 3 -8.85 14.06 49.97 0.6 809 829 | 811 3 -9.85 17.56 50.97 0.6 810 830 | 812 3 -11.35 21.06 50.47 0.6 811 831 | 813 3 -13.85 22.56 47.97 0.6 812 832 | 814 3 -16.85 24.560 46.97 0.6 813 833 | 815 3 -18.85 27.060 45.47 0.6 814 834 | 816 3 -20.35 30.060 39.97 0.6 815 835 | 817 3 -21.85 33.56 32.47 0.6 816 836 | 818 3 -23.35 36.06 29.47 0.6 817 837 | 819 3 -26.35 39.06 31.470 0.6 818 838 | 820 3 -28.35 43.06 35.97 0.6 819 839 | 821 3 -32.35 46.06 39.97 0.6 820 840 | 822 3 -35.85 48.56 45.47 0.6 821 841 | 823 3 -40.35 50.06 49.97 0.6 822 842 | 824 3 -45.35 51.56 52.47 0.6 823 843 | 825 3 -52.35 53.06 54.47 0.6 824 844 | 826 3 10.15 -6.94 12.97 1.150 760 845 | 827 3 13.15 -9.44 16.47 1.150 826 846 | 828 3 16.15 -11.44 18.47 1.150 827 847 | 829 3 16.25 -11.44 18.47 0.950 828 848 | 830 3 19.150 -13.44 16.47 0.4 829 849 | 831 3 22.650 -14.94 15.97 0.4 830 850 | 832 3 25.650 -16.44 15.97 0.4 831 851 | 833 3 28.150 -17.94 15.97 0.4 832 852 | 834 3 31.150 -20.44 16.47 0.4 833 853 | 835 3 33.65 -22.94 16.97 0.4 834 854 | 836 3 37.15 -25.94 16.47 0.4 835 855 | 837 3 40.65 -27.94 14.47 0.4 836 856 | 838 3 44.65 -29.44 13.47 0.4 837 857 | 839 3 48.65 -31.94 13.47 0.4 838 858 | 840 3 52.15 -35.44 13.97 0.4 839 859 | 841 3 55.15 -40.44 15.97 0.4 840 860 | 842 3 18.650 -9.94 18.47 0.850 829 861 | 843 3 22.150 -8.94 18.47 0.850 842 862 | 844 3 22.25 -8.94 18.47 0.850 843 863 | 845 3 24.150 -6.44 24.47 0.4 844 864 | 846 3 26.650 -4.94 29.47 0.4 845 865 | 847 3 29.650 -3.44 31.470 0.4 846 866 | 848 3 33.65 -2.44 33.47 0.4 847 867 | 849 3 37.65 -0.44 34.47 0.4 848 868 | 850 3 41.65 1.06 37.47 0.4 849 869 | 851 3 45.15 2.56 41.47 0.4 850 870 | 852 3 50.15 2.56 44.97 0.4 851 871 | 853 3 56.15 1.06 47.97 0.4 852 872 | 854 3 25.150 -8.44 23.47 0.445 844 873 | 855 3 29.150 -8.94 33.47 0.445 854 874 | 856 3 33.15 -6.94 30.47 0.4 855 875 | 857 3 37.15 -5.44 29.97 0.4 856 876 | 858 3 42.15 -3.94 30.970 0.4 857 877 | 859 3 47.15 -3.44 31.970 0.4 858 878 | 860 3 51.65 -3.44 31.970 0.4 859 879 | 861 3 54.65 -3.44 30.970 0.4 860 880 | 862 3 57.65 -3.44 29.97 0.4 861 881 | 863 3 60.65 -3.44 30.970 0.4 862 882 | 864 3 63.65 -2.94 34.97 0.4 863 883 | 865 3 66.15 -1.44 41.47 0.4 864 884 | 866 3 68.65 -0.940 44.97 0.4 865 885 | 867 3 72.65 -0.940 43.97 0.4 866 886 | 868 3 30.150 -10.44 34.97 0.4 855 887 | 869 3 31.650 -12.44 37.47 0.4 868 888 | 870 3 34.15 -13.94 40.47 0.4 869 889 | 871 3 36.65 -15.44 42.47 0.4 870 890 | 872 3 39.65 -16.44 43.47 0.4 871 891 | 873 3 42.15 -17.94 45.47 0.4 872 892 | 874 3 44.15 -20.44 47.47 0.4 873 893 | 875 3 46.15 -23.94 49.47 0.4 874 894 | 876 3 49.15 -27.94 49.47 0.4 875 895 | 877 3 25.150 -9.94 20.97 0.4 843 896 | 878 3 27.650 -10.94 25.97 0.4 877 897 | 879 3 29.150 -12.44 31.470 0.4 878 898 | 880 3 30.650 -13.94 33.97 0.4 879 899 | 881 3 33.15 -15.44 35.47 0.4 880 900 | 882 3 38.15 -15.94 38.97 0.4 881 901 | 883 3 43.15 -16.94 41.97 0.4 882 902 | 884 3 47.65 -18.44 46.47 0.4 883 903 | 885 3 50.65 -21.44 51.97 0.4 884 904 | 886 3 53.65 -23.44 57.97 0.4 885 905 | 887 3 56.65 -22.94 61.97 0.4 886 906 | 888 3 60.15 -20.94 65.47 0.4 887 907 | 889 3 63.15 -21.44 66.47 0.4 888 908 | 890 3 66.15 -22.94 66.97 0.4 889 909 | 891 3 66.65 -26.44 65.47 0.4 890 910 | 892 3 66.65 -30.44 65.47 0.4 891 911 | 893 3 15.15 -12.44 18.47 0.950 828 912 | 894 3 15.15 -14.44 18.47 0.950 893 913 | 895 3 17.150 -16.44 17.97 0.4 894 914 | 896 3 18.150 -18.44 18.97 0.4 895 915 | 897 3 19.150 -21.44 21.47 0.4 896 916 | 898 3 24.150 -21.94 27.47 0.4 897 917 | 899 3 26.650 -22.44 33.97 0.4 898 918 | 900 3 26.650 -23.94 42.47 0.4 899 919 | 901 3 28.650 -26.44 49.47 0.4 900 920 | 902 3 28.650 -28.44 53.47 0.4 901 921 | 903 3 28.650 -30.44 56.47 0.4 902 922 | 904 3 27.150 -33.94 62.47 0.4 903 923 | 905 3 18.650 -25.94 23.47 0.4 897 924 | 906 3 19.150 -30.44 25.47 0.4 905 925 | 907 3 19.650 -34.94 27.47 0.4 906 926 | 908 3 21.150 -39.44 29.97 0.4 907 927 | 909 3 23.150 -44.44 34.47 0.4 908 928 | 910 3 15.15 -15.44 18.47 0.4 894 929 | 911 3 16.15 -16.94 19.47 0.4 910 930 | 912 3 16.15 -18.94 20.47 0.4 911 931 | 913 3 16.15 -20.94 23.47 0.4 912 932 | 914 3 15.15 -22.94 25.97 0.4 913 933 | 915 3 16.15 -24.44 29.97 0.4 914 934 | 916 3 16.65 -26.44 32.47 0.4 915 935 | 917 3 17.650 -27.94 34.97 0.4 916 936 | 918 3 17.650 -29.94 40.47 0.4 917 937 | 919 3 18.150 -32.94 45.47 0.4 918 938 | 920 3 17.650 -37.94 49.47 0.4 919 939 | 921 3 12.15 -23.44 32.47 0.420 910 940 | 922 3 10.65 -38.44 49.47 0.420 921 941 | 923 1 -16.05 -4.264 -26.580 13.36 1 942 | 924 1 -16.95 -4.486 -27.55 12.68 923 943 | 925 3 -20.45 -2.986 -27.55 1.150 924 944 | 926 3 -26.45 -3.486 -27.55 0.8 925 945 | 927 3 -32.45 -3.486 -27.05 0.8 926 946 | 928 3 -38.95 -1.486 -26.55 0.8 927 947 | 929 3 -44.95 1.514 -26.05 0.8 928 948 | 930 3 -45.15 1.514 -26.05 1.35 929 949 | 931 3 -52.45 2.5140 -27.05 0.4 930 950 | 932 3 -60.45 4.014 -27.55 0.4 931 951 | 933 3 -66.95 5.514 -27.55 0.4 932 952 | 934 3 -71.45 6.514 -27.55 0.4 933 953 | 935 3 -76.95 3.0140 -27.55 0.4 934 954 | 936 3 -82.95 0.0139 -27.55 0.4 935 955 | 937 3 -89.45 -2.986 -27.55 0.4 936 956 | 938 3 -95.45 -5.486 -27.55 0.4 937 957 | 939 3 -101.5 -8.486 -27.55 0.4 938 958 | 940 3 -109.5 -10.99 -27.55 0.4 939 959 | 941 3 -117.5 -12.49 -27.55 0.4 940 960 | 942 3 -123. -13.49 -27.55 0.4 941 961 | 943 3 -125. -13.49 -27.55 0.4 942 962 | 944 3 -73.45 9.014 -27.55 0.4 934 963 | 945 3 -75.95 12.01 -27.55 0.4 944 964 | 946 3 -80.45 14.51 -27.55 0.4 945 965 | 947 3 -83.45 16.51 -27.55 0.4 946 966 | 948 3 -87.95 17.51 -27.55 0.4 947 967 | 949 3 -91.45 18.51 -32.55 0.4 948 968 | 950 3 -95.45 18.51 -39.550 0.4 949 969 | 951 3 -99.45 18.01 -46.550 0.4 950 970 | 952 3 -103. 18.51 -48.550 0.4 951 971 | 953 3 -107.5 18.51 -50.550 0.4 952 972 | 954 3 -112. 19.01 -52.050 0.4 953 973 | 955 3 -116.5 19.51 -54.050 0.4 954 974 | 956 3 -48.45 7.014 -26.05 0.4950 930 975 | 957 3 -53.45 12.51 -27.55 0.4950 956 976 | 958 3 -59.45 17.51 -31.55 0.4950 957 977 | 959 3 -67.45 21.01 -28.55 0.4 958 978 | 960 3 -74.45 23.51 -27.55 0.4 959 979 | 961 3 -78.45 26.01 -26.05 0.4 960 980 | 962 3 -82.45 28.51 -27.05 0.4 961 981 | 963 3 -85.95 31.51 -26.55 0.4 962 982 | 964 3 -89.45 34.01 -26.05 0.4 963 983 | 965 3 -92.95 36.51 -26.05 0.4 964 984 | 966 3 -97.95 40.51 -27.05 0.4 965 985 | 967 3 -104.5 45.01 -29.05 0.4 966 986 | 968 3 -111. 49.01 -33.05 0.4 967 987 | 969 3 -59.95 20.01 -33.55 0.4 958 988 | 970 3 -61.45 23.01 -36.550 0.4 969 989 | 971 3 -63.45 27.01 -39.050 0.4 970 990 | 972 3 -64.95 31.51 -42.050 0.4 971 991 | 973 3 -66.95 34.51 -44.050 0.4 972 992 | 974 3 -68.45 36.01 -47.550 0.4 973 993 | 975 3 -71.45 38.01 -49.550 0.4 974 994 | 976 3 -73.95 41.01 -51.550 0.4 975 995 | 977 3 -76.95 45.51 -56.550 0.4 976 996 | 978 3 -78.45 51.01 -60.050 0.4 977 997 | 979 3 -80.45 57.01 -65.05 0.4 978 998 | 980 3 -48.45 3.0140 -27.05 0.4 929 999 | 981 3 -55.95 5.014 -27.55 0.4 980 1000 | 982 3 -63.95 6.514 -27.55 0.4 981 1001 | 983 3 -71.45 7.514 -27.55 0.4 982 1002 | 984 3 -78.95 4.514 -27.55 0.4 983 1003 | 985 3 -86.95 1.014 -27.55 0.4 984 1004 | 986 3 -95.45 -2.986 -27.55 0.4 985 1005 | 987 3 -102.5 -6.486 -27.55 0.4 986 1006 | 988 3 -74.95 11.01 -30.05 0.4 983 1007 | 989 3 -77.95 15.01 -28.05 0.4 988 1008 | 990 3 -79.45 19.01 -18.05 0.4 989 1009 | 991 3 -80.45 25.51 -8.553 0.4 990 1010 | 992 3 -82.95 30.51 -3.053 0.4 991 1011 | 993 3 -86.45 34.51 -1.553 0.4 992 1012 | 994 3 -90.45 36.51 -2.053 0.4 993 1013 | 995 3 -93.95 39.01 -1.053 0.4 994 1014 | 996 3 -44.45 6.514 -27.55 0.4 928 1015 | 997 3 -45.95 12.51 -28.55 0.4 996 1016 | 998 3 -48.95 20.01 -28.55 0.4 997 1017 | 999 3 -53.45 25.51 -28.05 0.4 998 1018 | 1000 3 -56.45 31.01 -31.05 0.4 999 1019 | 1001 3 -58.95 35.51 -35.550 0.4 1000 1020 | 1002 3 -61.95 42.01 -41.050 0.4 1001 1021 | 1003 3 -65.45 50.01 -45.550 0.4 1002 1022 | 1004 3 -68.45 60.01 -51.550 0.4 1003 1023 | 1005 3 -23.45 0.0139 -30.05 1.150 925 1024 | 1006 3 -27.95 5.014 -31.55 1.150 1005 1025 | 1007 3 -33.95 11.51 -31.55 1.150 1006 1026 | 1008 3 -35.45 16.01 -31.55 0.70 1007 1027 | 1009 3 -38.45 21.51 -33.05 0.70 1008 1028 | 1010 3 -41.45 27.01 -35.050 0.70 1009 1029 | 1011 3 -44.95 33.01 -37.050 0.70 1010 1030 | 1012 3 -47.95 38.01 -39.550 0.70 1011 1031 | 1013 3 -50.45 43.51 -39.550 0.70 1012 1032 | 1014 3 -52.45 48.51 -38.050 0.70 1013 1033 | 1015 3 -57.45 56.01 -42.050 0.70 1014 1034 | 1016 3 -58.45 62.01 -44.550 0.4 1015 1035 | 1017 3 -57.95 68.51 -45.050 0.4 1016 1036 | 1018 3 -57.45 75.51 -48.050 0.4 1017 1037 | 1019 3 -56.95 82.51 -51.550 0.4 1018 1038 | 1020 3 -62.45 59.01 -43.050 0.4 1015 1039 | 1021 3 -67.45 63.01 -44.550 0.4 1020 1040 | 1022 3 -71.45 67.01 -45.550 0.4 1021 1041 | 1023 3 -76.45 71.01 -48.050 0.4 1022 1042 | 1024 3 -81.95 74.01 -51.550 0.4 1023 1043 | 1025 3 -53.45 53.01 -55.050 0.4 1014 1044 | 1026 3 -54.95 57.01 -64.55 0.4 1025 1045 | 1027 3 -56.95 61.51 -67.55 0.4 1026 1046 | 1028 3 -61.45 64.01 -67.55 0.4 1027 1047 | 1029 3 -54.95 65.01 -54.050 0.4 1027 1048 | 1030 3 -55.95 50.01 -35.050 0.4 1013 1049 | 1031 3 -58.45 52.01 -31.55 0.4 1030 1050 | 1032 3 -59.95 55.51 -29.55 0.4 1031 1051 | 1033 3 -60.95 58.51 -27.55 0.4 1032 1052 | 1034 3 -62.95 63.01 -27.55 0.4 1033 1053 | 1035 3 -66.95 67.01 -25.55 0.4 1034 1054 | 1036 3 -70.45 75.51 -23.55 0.4 1035 1055 | 1037 3 -72.95 86.01 -22.05 0.4 1036 1056 | 1038 3 -36.95 15.51 -36.050 0.950 1007 1057 | 1039 3 -40.95 21.01 -46.050 0.950 1038 1058 | 1040 3 -44.45 25.01 -46.050 0.490 1039 1059 | 1041 3 -47.95 29.51 -46.050 0.490 1040 1060 | 1042 3 -51.95 30.51 -48.050 0.4 1041 1061 | 1043 3 -56.45 32.51 -54.050 0.4 1042 1062 | 1044 3 -59.45 35.51 -59.050 0.4 1043 1063 | 1045 3 -62.95 37.01 -63.550 0.4 1044 1064 | 1046 3 -66.95 40.51 -65.05 0.4 1045 1065 | 1047 3 -73.45 45.51 -69.05 0.4 1046 1066 | 1048 3 -49.45 34.01 -49.550 0.4 1041 1067 | 1049 3 -50.95 40.01 -46.550 0.4 1048 1068 | 1050 3 -54.45 45.51 -42.550 0.4 1049 1069 | 1051 3 -58.45 50.01 -33.55 0.4 1050 1070 | 1052 3 -62.45 53.01 -27.55 0.4 1051 1071 | 1053 3 -37.95 27.51 -46.050 0.8 1039 1072 | 1054 3 -34.95 34.51 -47.550 0.8 1053 1073 | 1055 3 -32.45 42.51 -51.550 0.8 1054 1074 | 1056 3 -33.95 48.01 -60.550 0.4 1055 1075 | 1057 3 -35.95 54.01 -64.05 0.4 1056 1076 | 1058 3 -38.95 59.51 -65.55 0.4 1057 1077 | 1059 3 -41.45 64.51 -67.55 0.4 1058 1078 | 1060 3 -29.45 47.01 -52.550 0.4 1055 1079 | 1061 3 -28.45 51.51 -53.050 0.4 1060 1080 | 1062 3 -29.95 56.51 -55.050 0.4 1061 1081 | 1063 3 -32.95 60.51 -58.550 0.4 1062 1082 | 1064 3 -35.95 64.51 -63.550 0.4 1063 1083 | 1065 3 -45.45 17.01 -47.050 0.4150 1038 1084 | 1066 3 -50.45 16.51 -56.050 0.4150 1065 1085 | 1067 3 -56.45 19.01 -74.05 0.4150 1066 1086 | 1068 1 -20.1 -5.039 -28.7 12.49 924 1087 | 1069 1 -21. -5.888 -30.490 10.72 1068 1088 | 1070 1 -21.90 -6.18 -31.05 7.48 1069 1089 | 1071 1 -23.25 -7.350 -34.2 2.2 1070 1090 | 1072 3 -25.25 -7.350 -34.2 2.2 1071 1091 | 1073 3 -26.75 -7.350 -34.2 1.8 1072 1092 | 1074 3 -38.75 -8.85 -30.7 1.8 1073 1093 | 1075 3 -47.25 -9.35 -26.7 1.8 1074 1094 | 1076 3 -51.75 -8.85 -22.2 1.8 1075 1095 | 1077 3 -51.85 -8.85 -22.2 1.90 1076 1096 | 1078 3 -58.75 -14.35 -22.2 1.150 1077 1097 | 1079 3 -63.75 -18.35 -22.2 1.150 1078 1098 | 1080 3 -66.25 -20.35 -22.2 1.150 1079 1099 | 1081 3 -70.25 -26.85 -18.2 0.4 1080 1100 | 1082 3 -74.25 -31.85 -16.2 0.4 1081 1101 | 1083 3 -77.75 -37.35 -15.70 0.4 1082 1102 | 1084 3 -79.25 -41.85 -14.20 0.4 1083 1103 | 1085 3 -80.75 -47.35 -12.70 0.4 1084 1104 | 1086 3 -84.25 -51.35 -11.70 0.4 1085 1105 | 1087 3 -92.25 -56.35 -11.70 0.4 1086 1106 | 1088 3 -104.30 -62.35 -11.70 0.4 1087 1107 | 1089 3 -119.80 -68.850 -11.70 0.4 1088 1108 | 1090 3 -72.75 -24.85 -21.2 0.4 1080 1109 | 1091 3 -77.75 -27.85 -21.2 0.4 1090 1110 | 1092 3 -80.75 -27.85 -21.2 0.4 1091 1111 | 1093 3 -86.25 -28.35 -23.7 0.4 1092 1112 | 1094 3 -90.25 -28.35 -26.2 0.4 1093 1113 | 1095 3 -93.75 -29.35 -29.2 0.4 1094 1114 | 1096 3 -103.30 -31.85 -29.2 0.4 1095 1115 | 1097 3 -113.30 -35.35 -29.2 0.4 1096 1116 | 1098 3 -124.80 -38.85 -31.7 0.4 1097 1117 | 1099 3 -138.3 -42.85 -37.2 0.4 1098 1118 | 1100 3 -102.30 -31.85 -38.7 0.4 1095 1119 | 1101 3 -110.80 -36.85 -44.2 0.4 1100 1120 | 1102 3 -117.80 -42.85 -49.2 0.4 1101 1121 | 1103 3 -121.80 -46.35 -52.2 0.4 1102 1122 | 1104 3 -125.30 -49.35 -55.7 0.4 1103 1123 | 1105 3 -60.25 -11.35 -15.70 0.9 1077 1124 | 1106 3 -65.25 -12.35 -11.70 0.9 1105 1125 | 1107 3 -66.75 -12.35 -10.20 0.9 1106 1126 | 1108 3 -71.75 -18.85 -8.2 0.4 1107 1127 | 1109 3 -80.25 -23.85 -3.2 0.4 1108 1128 | 1110 3 -86.25 -27.85 4.3 0.4 1109 1129 | 1111 3 -91.75 -31.35 10.8 0.4 1110 1130 | 1112 3 -97.75 -31.85 13.8 0.4 1111 1131 | 1113 3 -105.80 -30.85 16.3 0.4 1112 1132 | 1114 3 -113.30 -26.85 19.3 0.4 1113 1133 | 1115 3 -118.30 -23.85 23.8 0.4 1114 1134 | 1116 3 -122.80 -21.35 26.8 0.4 1115 1135 | 1117 3 -126.80 -20.35 29.3 0.4 1116 1136 | 1118 3 -73.25 -10.35 -5.7 0.4 1107 1137 | 1119 3 -77.75 -9.35 -3.7 0.4 1118 1138 | 1120 3 -80.25 -9.85 -3.7 0.4 1119 1139 | 1121 3 -85.75 -11.85 2.30 0.4 1120 1140 | 1122 3 -93.25 -13.35 4.8 0.4 1121 1141 | 1123 3 -101.30 -14.35 6.8 0.4 1122 1142 | 1124 3 -111.30 -15.35 8.3 0.4 1123 1143 | 1125 3 -121.80 -15.85 11.3 0.4 1124 1144 | 1126 3 -132.3 -16.35 11.8 0.4 1125 1145 | 1127 3 -139.8 -16.35 12.3 0.4 1126 1146 | 1128 3 -89.25 -5.350 0.3 0.4 1120 1147 | 1129 3 -98.25 -0.850 3.80 0.4 1128 1148 | 1130 3 -105.30 1.650 4.8 0.4 1129 1149 | 1131 3 -114.80 0.65 4.8 0.4 1130 1150 | 1132 3 -120.80 -2.35 4.3 0.4 1131 1151 | 1133 3 -124.80 -5.850 4.3 0.4 1132 1152 | 1134 3 -52.75 -7.350 -22.2 1.6 1076 1153 | 1135 3 -53.25 -6.850 -22.2 1.6 1134 1154 | 1136 3 -65.25 -8.85 -17.7 0.75 1135 1155 | 1137 3 -74.75 -8.85 -17.2 0.75 1136 1156 | 1138 3 -83.25 -7.350 -22.2 0.75 1137 1157 | 1139 3 -89.75 -5.350 -26.2 0.75 1138 1158 | 1140 3 -93.75 -4.850 -29.2 0.75 1139 1159 | 1141 3 -101.30 -8.35 -28.2 0.4 1140 1160 | 1142 3 -109.30 -11.35 -27.2 0.4 1141 1161 | 1143 3 -115.80 -11.35 -27.2 0.4 1142 1162 | 1144 3 -125.80 -12.85 -26.2 0.4 1143 1163 | 1145 3 -135.8 -13.35 -26.2 0.4 1144 1164 | 1146 3 -146.8 -15.85 -23.7 0.4 1145 1165 | 1147 3 -154.8 -18.35 -19.7 0.4 1146 1166 | 1148 3 -100.30 -2.35 -29.7 0.4 1140 1167 | 1149 3 -106.80 -1.35 -30.2 0.4 1148 1168 | 1150 3 -111.80 -3.85 -27.2 0.4 1149 1169 | 1151 3 -117.30 -5.850 -29.2 0.4 1150 1170 | 1152 3 -123.30 -7.850 -35.7 0.4 1151 1171 | 1153 3 -112.80 2.65 -31.2 0.4 1149 1172 | 1154 3 -119.80 8.15 -33.2 0.4 1153 1173 | 1155 3 -128.3 14.15 -36.2 0.4 1154 1174 | 1156 3 -138.3 19.650 -39.7 0.4 1155 1175 | 1157 3 -54.25 -1.85 -18.7 0.4 1135 1176 | 1158 3 -56.75 2.15 -16.7 0.4 1157 1177 | 1159 3 -60.25 7.15 -16.2 0.4 1158 1178 | 1160 3 -66.75 12.65 -17.2 0.4 1159 1179 | 1161 3 -74.25 18.650 -21.7 0.4 1160 1180 | 1162 3 -82.75 23.650 -26.7 0.4 1161 1181 | 1163 3 -89.25 25.150 -31.2 0.4 1162 1182 | 1164 3 -94.25 26.650 -36.2 0.4 1163 1183 | 1165 3 -100.30 26.650 -42.2 0.4 1164 1184 | 1166 3 -107.80 27.150 -51.7 0.4 1165 1185 | 1167 3 -118.30 28.150 -62.2 0.4 1166 1186 | 1168 3 -28.75 -3.35 -31.7 0.8 1073 1187 | 1169 3 -34.25 2.15 -27.2 0.8 1168 1188 | 1170 3 -39.75 7.65 -22.2 0.8 1169 1189 | 1171 3 -43.25 10.15 -21.2 0.8 1170 1190 | 1172 3 -43.35 10.15 -21.2 0.6 1171 1191 | 1173 3 -43.45 11.15 -21.2 0.4150 1172 1192 | 1174 3 -56.75 12.65 -18.7 0.4 1173 1193 | 1175 3 -68.25 13.15 -15.70 0.4 1174 1194 | 1176 3 -77.75 12.15 -12.20 0.4 1175 1195 | 1177 3 -83.75 9.65 -11.70 0.4 1176 1196 | 1178 3 -89.75 6.65 -11.70 0.4 1177 1197 | 1179 3 -97.25 3.65 -11.70 0.4 1178 1198 | 1180 3 -105.30 0.65 -11.70 0.4 1179 1199 | 1181 3 -113.30 0.15 -11.70 0.4 1180 1200 | 1182 3 -118.30 1.150 -11.70 0.4 1181 1201 | 1183 3 -120.80 2.65 -11.70 0.4 1182 1202 | 1184 3 -45.75 12.15 -15.70 0.4 1173 1203 | 1185 3 -51.75 13.65 -13.70 0.4 1184 1204 | 1186 3 -59.75 15.65 -14.70 0.4 1185 1205 | 1187 3 -67.75 16.15 -13.70 0.4 1186 1206 | 1188 3 -74.75 16.15 -12.20 0.4 1187 1207 | 1189 3 -81.75 13.15 -11.70 0.4 1188 1208 | 1190 3 -88.25 10.65 -11.70 0.4 1189 1209 | 1191 3 -95.25 7.65 -11.70 0.4 1190 1210 | 1192 3 -99.75 5.65 -11.70 0.4 1191 1211 | 1193 3 -102.30 5.15 -11.70 0.4 1192 1212 | 1194 3 -45.75 14.15 -17.2 0.4 1172 1213 | 1195 3 -51.25 19.650 -15.70 0.4 1194 1214 | 1196 3 -55.75 23.650 -15.70 0.4 1195 1215 | 1197 3 -59.75 26.650 -15.70 0.4 1196 1216 | 1198 3 -71.75 32.65 -15.70 0.4 1197 1217 | 1199 3 -78.75 36.15 -15.70 0.4 1198 1218 | 1200 3 -81.75 37.65 -15.70 0.4 1199 1219 | 1201 3 -85.75 41.15 -15.70 0.4 1200 1220 | 1202 3 -91.75 45.15 -15.70 0.4 1201 1221 | 1203 3 -100.80 51.15 -20.7 0.4 1202 1222 | 1204 3 -111.80 58.15 -31.7 0.4 1203 1223 | 1205 3 -62.25 33.15 -23.2 0.4 1197 1224 | 1206 3 -67.25 41.15 -31.7 0.4 1205 1225 | 1207 3 -72.75 50.65 -39.2 0.4 1206 1226 | 1208 3 -78.75 59.65 -41.2 0.4 1207 1227 | 1209 3 -81.75 68.65 -53.2 0.4 1208 1228 | 1210 3 -84.25 61.65 -48.7 0.4 1208 1229 | 1211 3 -90.75 67.65 -50.2 0.4 1210 1230 | 1212 3 -46.25 22.650 -17.2 0.4 1171 1231 | 1213 3 -50.25 32.15 -17.7 0.4 1212 1232 | 1214 3 -54.25 39.65 -19.2 0.4 1213 1233 | 1215 3 -57.25 45.15 -22.2 0.4 1214 1234 | 1216 3 -61.25 52.15 -24.7 0.4 1215 1235 | 1217 3 -64.75 59.65 -28.7 0.4 1216 1236 | 1218 3 -66.75 65.15 -32.2 0.4 1217 1237 | 1219 3 -66.75 68.15 -35.7 0.4 1218 1238 | --------------------------------------------------------------------------------