{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# 2. How to Build a Model\n", "\n", "`Model` is composed of a set of `Species` and `ReactionRule`s.\n", "\n", "* `Species` describes a molecule entitie (e.g. a type or state of a protein) in the model. `Species` also has its attributes like the size. \n", "* `ReactionRule` describes the interactions between `Species` (e.g. binding and unbinding)." ] }, { "cell_type": "code", "execution_count": 1, "metadata": { "collapsed": false }, "outputs": [], "source": [ "%matplotlib inline\n", "from ecell4 import *" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 2.1. Species\n", "\n", "`Species` can be generated with its name:" ] }, { "cell_type": "code", "execution_count": 2, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "A\n" ] } ], "source": [ "sp1 = Species(\"A\")\n", "print(sp1.serial())" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "A name of `Species` (called `serial`) has a number of naming rules.\n", "It requires attention to use special symbols (e.g. parenthesis `()`, dot `.`, underbar `_`), numbers and brank.\n", "\n", "`Species` has a set of APIs for handling its attributes:" ] }, { "cell_type": "code", "execution_count": 3, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "0.005\n", "False\n" ] } ], "source": [ "sp1.set_attribute(\"radius\", \"0.005\")\n", "sp1.set_attribute(\"D\", \"1\")\n", "sp1.set_attribute(\"location\", \"cytoplasm\")\n", "print(sp1.get_attribute(\"radius\"))\n", "sp1.remove_attribute(\"radius\")\n", "print(sp1.has_attribute(\"radius\"))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The arguments in `set_attribute` is the name of attribute and its value. Both of them have to be string. There is a shortcut to set the attributes above at once because `radius`, `D` (a diffusion coefficient) and `location` are frequently used." ] }, { "cell_type": "code", "execution_count": 4, "metadata": { "collapsed": true }, "outputs": [], "source": [ "sp1 = Species(\"A\", \"0.005\", \"1\", \"cytoplasm\") # serial, radius, D, location" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The equality between `Species` is just evaluated based on their serial:" ] }, { "cell_type": "code", "execution_count": 5, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "False True\n" ] } ], "source": [ "print(Species(\"A\") == Species(\"B\"), Species(\"A\") == Species(\"A\"))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "A Species consists of one or more UnitSpecies:" ] }, { "cell_type": "code", "execution_count": 6, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "C\n", "C.A.B 3\n" ] } ], "source": [ "sp1 = Species()\n", "usp1 = UnitSpecies(\"C\")\n", "print(usp1.serial())\n", "sp1.add_unit(usp1)\n", "sp1.add_unit(UnitSpecies(\"A\"))\n", "sp1.add_unit(UnitSpecies(\"B\"))\n", "print(sp1.serial(), sp1.num_units())" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "A Species can be reproduced from a serial. In a serial, all serials of UnitSpecies are joined with the separator, dot `.`. The comparison between Species **matters** the oder of UnitSpecies in each Species." ] }, { "cell_type": "code", "execution_count": 7, "metadata": { "collapsed": false, "scrolled": true }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "C.A.B\n", "False\n", "True\n" ] } ], "source": [ "sp1 = Species(\"C.A.B\")\n", "print(sp1.serial())\n", "print(Species(\"A.B.C\") == Species(\"C.A.B\"))\n", "print(Species(\"A.B.C\") == Species(\"A.B.C\"))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`UnitSpecies` can have sites. Sites consists of a `name`, `state` and `bond`, and are sorted automatically in `UnitSpecies`. `name` must be unique in a `UnitSpecies`. All the value have to be string. Do not include parenthesis, dot and blank, and not start from numbers except for `bond`." ] }, { "cell_type": "code", "execution_count": 8, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "A(bs^_,ps=p^_,us=u)\n" ] } ], "source": [ "usp1 = UnitSpecies(\"A\")\n", "usp1.add_site(\"us\", \"u\", \"\")\n", "usp1.add_site(\"ps\", \"p\", \"_\")\n", "usp1.add_site(\"bs\", \"\", \"_\")\n", "print(usp1.serial())" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`UnitSpecies` can be also reproduced from its serial. Please be careful with the order of sites where a site with a state must be placed after sites with no state specification:" ] }, { "cell_type": "code", "execution_count": 9, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "A(bs^_,ps=p^_,us=u)\n" ] } ], "source": [ "usp1 = UnitSpecies()\n", "usp1.deserialize(\"A(bs^_, us=u, ps=p^_)\")\n", "print(usp1.serial())" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Of course, a site of `UnitSpecies` is available even in `Species`' serial." ] }, { "cell_type": "code", "execution_count": 10, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "A(bs^1,ps=u).A(bs,ps=p^1)\n", "2\n" ] } ], "source": [ "sp1 = Species(\"A(bs^1, ps=u).A(bs, ps=p^1)\")\n", "print(sp1.serial())\n", "print(sp1.num_units())" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The information (`UnitSpecies` and its `site`) is used for rule-based modeling. The way of rule-based modeling in E-Cell4 will be explained in **7. Introduction of Rule-based Modeling** [local ipynb](tutorial7.ipynb) [readthedocs](http://ecell4.readthedocs.io/en/latest/tutorials/tutorial7.html)." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 2.2. ReactionRule\n", "\n", "`ReactionRule` consists of `reactants`, `products` and `k`. `reactants` and `products` are a list of `Species`, and `k` is a kinetic rate given as a floating number." ] }, { "cell_type": "code", "execution_count": 11, "metadata": { "collapsed": false }, "outputs": [], "source": [ "rr1 = ReactionRule()\n", "rr1.add_reactant(Species(\"A\"))\n", "rr1.add_reactant(Species(\"B\"))\n", "rr1.add_product(Species(\"C\"))\n", "rr1.set_k(1.0)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Here is a binding reaction from `A` and `B` to `C`. In this reaction definition, you don't need to set attributes to `Species`. This is equivalent to call an utility function as follows: `create_binding_reaction_rule(Species(\"A\"), Species(\"B\"), Species(\"C\"), 1.0)`.\n", "\n", "To inspect `ReactionRule`, `as_string` function is available:" ] }, { "cell_type": "code", "execution_count": 12, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "A+B>C|1\n" ] } ], "source": [ "rr1 = create_binding_reaction_rule(Species(\"A\"), Species(\"B\"), Species(\"C\"), 1.0)\n", "print(rr1.as_string())" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "You can also provide components to the constructor:" ] }, { "cell_type": "code", "execution_count": 13, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "A+B>C|1\n" ] } ], "source": [ "rr1 = ReactionRule([Species(\"A\"), Species(\"B\")], [Species(\"C\")], 1.0)\n", "print(rr1.as_string())" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "In general, `ReactionRule` suggests a mass action reaction with rate `k`. `ode` solver also supports rate laws thought it's under development yet. `ode.ODERatelaw` is explained in **6. How to Solve ODEs with Rate Law Functions** [local ipynb](tutorial6.ipynb) [readthedocs](http://ecell4.readthedocs.io/en/latest/tutorials/tutorial6.html)." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 2.3. NetworkModel\n", "\n", "Now you have known how to create components of `Model`. Next let's register these components to `Model`." ] }, { "cell_type": "code", "execution_count": 14, "metadata": { "collapsed": true }, "outputs": [], "source": [ "sp1 = Species(\"A\", \"0.005\", \"1\")\n", "sp2 = Species(\"B\", \"0.005\", \"1\")\n", "sp3 = Species(\"C\", \"0.01\", \"0.5\")" ] }, { "cell_type": "code", "execution_count": 15, "metadata": { "collapsed": true }, "outputs": [], "source": [ "rr1 = create_binding_reaction_rule(Species(\"A\"), Species(\"B\"), Species(\"C\"), 0.01)\n", "rr2 = create_unbinding_reaction_rule(Species(\"C\"), Species(\"A\"), Species(\"B\"), 0.3)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`NetworkModel` has interfaces to register `Species` and `ReactionRule` named `add_species_attribute` and `add_reaction_rule`." ] }, { "cell_type": "code", "execution_count": 16, "metadata": { "collapsed": true }, "outputs": [], "source": [ "m1 = NetworkModel()\n", "m1.add_species_attribute(sp1)\n", "m1.add_species_attribute(sp2)\n", "m1.add_species_attribute(sp3)\n", "m1.add_reaction_rule(rr1)\n", "m1.add_reaction_rule(rr2)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Here is a simple model with binding and unbinding reactions. To inspect `Model`, `species_attributes` and `reaction_rules` is available:" ] }, { "cell_type": "code", "execution_count": 17, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "['A', 'B', 'C']\n", "['A+B>C|0.01', 'C>A+B|0.3']\n" ] } ], "source": [ "print([sp.serial() for sp in m1.species_attributes()])\n", "print([rr.as_string() for rr in m1.reaction_rules()])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`Species`' attributes in `Model` are indispensable for spatial simulations, but not necessarily needed for non-spatial algorithms, i.e. `gillespie` and `ode`. The attribute pushed first has higher priority than one pushed later. You can also attribute a `Species` based on the attributes in a `Model`." ] }, { "cell_type": "code", "execution_count": 18, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "False\n", "True\n", "0.005\n" ] } ], "source": [ "sp1 = Species(\"A\")\n", "print(sp1.has_attribute(\"radius\"))\n", "sp2 = m1.apply_species_attributes(sp1)\n", "print(sp2.has_attribute(\"radius\"))\n", "print(sp2.get_attribute(\"radius\"))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "All functions related to `Species`, `ReactionRule` and `NetworkModel` above are available even on C++ in the same way.\n", "\n", "You can solve this model with `run_simulation` as explained in **1. Brief Tour of E-Cell4 Simulations** [local ipynb](tutorial1.ipynb) [readthedocs](http://ecell4.readthedocs.io/en/latest/tutorials/tutorial1.html) :" ] }, { "cell_type": "code", "execution_count": 19, "metadata": { "collapsed": false }, "outputs": [ { "data": { "image/png": "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\n", "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "run_simulation(10.0, model=m1, y0={'C': 60})" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 2.4. Python Utilities to Build a Model\n", "\n", "As shown in **1. Brief Tour of E-Cell4 Simulations** [local ipynb](tutorial1.ipynb) [readthedocs](http://ecell4.readthedocs.io/en/latest/tutorials/tutorial1.html), E-Cell4 also provides the easier way to build a model using `with` statement:" ] }, { "cell_type": "code", "execution_count": 20, "metadata": { "collapsed": true }, "outputs": [], "source": [ "with species_attributes():\n", " A | B | {'radius': '0.005', 'D': '1'}\n", " C | {'radius': '0.01', 'D': '0.5'}\n", "\n", "with reaction_rules():\n", " A + B == C | (0.01, 0.3)\n", "\n", "m1 = get_model()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "For reversible reactions, `<>` is also available instead of `==` on Python 2, but deprecated on Python3. In the `with` statement, undeclared variables are automaticaly assumed to be a `Species`. Any Python variables, functions and statement are available even in the `with` block." ] }, { "cell_type": "code", "execution_count": 21, "metadata": { "collapsed": true }, "outputs": [], "source": [ "from math import log\n", "\n", "ka, kd, kf = 0.01, 0.3, 0.1\n", "tau = 10.0\n", "\n", "with reaction_rules():\n", " E0 + S == ES | (ka, kd)\n", "\n", " if tau > 0:\n", " ES > E1 + P | kf\n", " E1 > E0 | log(2) / tau\n", " else:\n", " ES > E0 + P | kf\n", "\n", "m1 = get_model()\n", "del ka, kd, kf, tau" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Meanwhile, once some variable is declared even outside the block, you can not use its name as a `Species` as follows:" ] }, { "cell_type": "code", "execution_count": 22, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "RuntimeError('invalid expression; \"10\" given',)\n" ] } ], "source": [ "A = 10\n", "\n", "try:\n", " with reaction_rules():\n", " A + B == C | (0.01, 0.3)\n", "except Exception as e:\n", " print(repr(e))\n", "\n", "del A" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "where `A + B == C` exactly means `10 + B == C`.\n", "\n", "In the absence of left or right hand side of `ReactionRule` like synthesis or degradation, you may want to describe like:\n", "\n", "\n", "```python\n", "with reaction_rules():\n", " A > | 1.0 # XXX: will raise SyntaxError\n", " > A | 1.0 # XXX: will raise SyntaxError\n", "```\n", "\n", "However, they are not accepted because of `SyntaxError` on Python. To describe these cases, a special operator, tilde `~`, is available. `~` sets a stoichiometric coefficient of the following `Species` as zero, which means the `Species` is just ignored in the `ReactionRule`." ] }, { "cell_type": "code", "execution_count": 23, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "['>A|2', 'A>|1']\n" ] } ], "source": [ "with reaction_rules():\n", " ~A > A | 2.0 # equivalent to `create_synthesis_reaction_rule`\n", " A > ~A | 1.0 # equivalent to `create_degradation_reaction_rule`\n", "\n", "m1 = get_model()\n", "print([rr.as_string() for rr in m1.reaction_rules()])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The following `Species`' name is not necessarily needed to be the same as others. The model above describes $[A]'=2-[A]$:" ] }, { "cell_type": "code", "execution_count": 24, "metadata": { "collapsed": false }, "outputs": [ { "data": { "image/png": "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\nM888w65du+jevTu7du3KcwznHFdddRVZWVkMHDiQrl27MmTIEG677bY82918880MGTKELl268Mwz\nzxAbG0vXrl0PGSPy66+/8ssvv5CWlsbLL79Mnz59mDx5MmeddRZ79uw5uF3t2rUZNGgQGRkZ9OrV\ni9q1a9OvXz9mz54d6FsdPs65iHgAqYCbOXOmk+DIyXHunnucA+eGD/c6jUj5N3PmTBcJf8d27Njh\nXn/9dde2bVtnZi4lJcXdeuut7pdffjlk25EjR7qoqCi3YsWKg2179uw5ZLvevXu7ihUruqysrINt\nnTp1clFRUe7dd9892LZo0SJnZi4mJsb9+uuvB9u/+uorZ2burbfeOtj26KOPOjNzl112WZ5z3X77\n7S4qKsrNmTPHOefc77//7szM9evXL89211xzjYuKinKPPfbYYbNPnz7dmZkbPXr0oW+Wc+63335z\nffv2dVWrVnVm5lJTU92wYcPc1q1bC9w+vwO/V08++aR744033ODBg92mTZsK3AZIdSX8PFaPhwTs\nscdg0CAYMsR3qUVESp+1O9aSvja90Mf8jfOPeIz5G+cXuO/aHWuDmnX9+vXcdNNN1K5dm969e5OY\nmMioUaNYt24dr732GqeddlqRjhMfH3/w3zt37mTTpk20b9+ezMxMFi5cmGfbihUrctVVVx18fuyx\nx1K5cmWaN29OmzZtDrYfOPfSpUvz7G9m3H777Xna+vXrh3OOzz77DIBJkyZhZvTr1y/Pdv379z/w\nxbjA7Pv372fz5s00atSIypUrk56eXuDP27p1a4YOHcratWsZO3Ys1apVo1+/ftSuXZtrr72W1atX\nF/xGeUR3tUhAnnvOV3g8/TTk+/+SiJQir818jce+f6zQ11vUaMG8vvMOe4zu73cvsEB5pOMjPNrp\n0ZJGPGjhwoWMHDmS2NhYnn32We666y6io6OLfZz58+fzr3/9i++++47t27cfbDezQwal1q1b95D9\nU1JSqFevXp625ORkALZs2XLI9k2aNMnzvHHjxkRFRbF8+XLAN24jKiqKxo0b59nuuOOOO+RYe/bs\n4amnnmLkyJGsWbPmYGFSUPb84uLi6NmzJ927d+e///0v//znPxk7dizdu3cv8Of0igoPKbb+r3zO\nSw+151//qsQDD3idRkQO57bWt3HJcZcU+npCTMIRj/F+9/fZs3/PIe21K9YuUbb8TjnlFIYOHcrw\n4cO59957GThwIL169eLGG2/kxBNPLNIxtm3bxplnnknlypV58sknadSoEQkJCcycOZMHHnjgkAGm\nhRU2hbXn76EoSEnm9rjjjjt46623GDBgAG3btiUlJQUzo0ePHodkz2/BggW8+eabjB49mvXr13P8\n8cdzyy23cNZZZwWcJxRUeEixDHz/a17aeDGn3PE4T2ieDpFSr3al2tSuVLICoUWNFkFKc3iJiYn0\n6dOHPn36MHv2bN544w1GjhzJiy++SGpqKjfeeCNXX301VaoUPhPylClT2LJlCxMmTKBdu3YH25cs\nWRKy3IsXL+aYY445+Pyvv/4iJyeHhv51Io455hhycnJYsmRJnkGx+S/7AHz44YfccMMNPPvsswfb\n9u7dy9atWws89/bt23nnnXd48803mT59OpUqVaJnz57ccsstnHLKKcH6EYNKYzykyMb/PJcHZ11J\nje3n8cPT96EJ+0QkVFq1asUrr7zC2rVrGTVqFJUqVeLOO+/k6KOPpkePHmzatKnA/aKjo3HO5ekd\nyMrKYtiwYSHJ6Zxj6NChedqGDBmCmdGlSxcALrjgApxzDBkyJM92L7744iG9I9HR0Yf0bAwZMoTs\n7Ow8bTt37jx4N0ufPn2IiopixIgRrF27ltdee63UFh2gHg8potlL1tL94wtJ2N+Q2Q+9S0KcfnVE\nJPTi4+Pp1asXvXr1YsmSJQwfPpy33nqLNWvWUK1atUO2P+OMM6hSpQrXXXcdd97pm1No9OjRIZ3a\nfNmyZVx66aV06dKFqVOnMmbMGHr16nXw8lDLli1JS0tj2LBhbN26lTPOOIPJkyezZMmSQy7dXHTR\nRbz99tskJyfTokULpk2bxuTJk6levXqe7TZt2sTXX39N3759uemmm2jevOxMZaBPDzmiDVt20e6V\ni3Gx2fzQ+1OOrlbJ60giEoEaN27MU089xZNPPnlID8ABVatWZdKkSdxzzz08/PDDVKlShWuvvZaz\nzz6b888//5DtCypICluDpaD2qKgo3n33XR5++GEefPBBYmJiuPPOO/NcKgF48803qVmzJmPGjGHC\nhAl07tyZSZMmUa9evTzHHDJkCDExMYwdO5Y9e/bQvn17vvnmG84///w829WtW5c1a9YQE1P2Psat\nKANlygMzSwVmzpw5k9TUVK/jlBn7s3Oo98/LWJf4Le+c9yM9OrbyOpJIxEpPT6d169bo75gE04Hf\nqyeffJJatWqxY8cOrrvuOqpWrXrINkBr51zB9/UWUdkrlSSsLnxyEOtSPuGRpp+o6BARkRLT4FIp\n1GefwdfPX8sVUaN49JquXscREZFyQIWHFGjpUrjmGujasRbvPdTL6zgiIlJOqPCQQ+zeDVdcAVWr\nwttvQ5R+S0REJEg0xkPycA769oWFC+GXX+Aw8/SIiIgUmwoPyeONN2DkSHjrLWjZ0us0IiJS3qgT\nXQ5asADuvBNuuw2uu87rNCIiUh6p8BAAdu7O4qIBn9OgAbzwgtdpRESkvNKlFgHgnP/8m6WnvsCn\nDy0mMfGYI+8gIp5ZsGCB1xGkHAn375MKD+HFj6cwPeZZusQ+Tdf2KjpESqvq1auTmJhIr166xV2C\nKyEhgUqVwrMchgqPCLds7Rb++fN1pOw7kwnP/dPrOCJyGPXr12fBggVkZGSwbds2Pv30U5KSkoiP\nj/c6mpRxlSpVonr16uzevTvk5ypx4WFm0cCJwArn3JaSR5JwyclxdHyuD9nx2/n8xlHExUZ7HUlE\njqB+/frUr1+fzZs38/vvvxMXF6fCQ4Ji9+7d7N27N+TnKXbhYWYvAnOcc8P9Rcf3wBlAppld5Jyb\nEuSMEiL933iXVSnvcketsZzeor7XcUSkGOLj40lOTmb79u1kZWV5HUfKkeTk5JAWs4H0eFwJjPb/\n+2KgIdAMuBb4D9AuONEklBav3sQrS+6kzr4rePmRNK/jiEgxJSUl0aNHj7B8Q5XIEh8fT1JSUsiO\nH0jhUR1Y5//3hcD7zrk/zWwEcFfQkklI3fXkfKxCJSbd8YrXUUQkQElJSSH9gBAJhUDm8VgPtPBf\nZukCfO1vTwSyAwlhZh3MbKKZrTGzHDO75Ajbd/Rvl/uRbWY1Azl/pPnmG/j8tQ4Ma7GIlo1reR1H\nREQiSCA9Hm8C7wFrAQd8428/DVgYYI4kYDYwHPioiPs44Fhgx8EG5zYEeP6IkZnpm5m0Uye49Rbd\n1CQiIuFV7E8e59yjZjYXqIfvMsuBC4zZwMBAQjjnvgC+ADAzK8auG51z2wM5Z6R69FFYswa++AKK\n9U6LiIgEQUBfeZ1zHwCYWUKutreCFaqIDJjtzzAXeNQ5NzXMGcqU9HTfdOhPPAFNm3qdRkREIlGx\nx3iYWbSZPWxma4CdZtbI3/6Emd0c9IQFWwvcBlwBXA6sAqaYWaswnb/Myc6Gf/wDjj8e/ql5wkRE\nxCOB9Hj8C7geuA94PVf7XKA/vnEaIeWc+xP4M1fTL2bWGBjgzyb5DB/u6/GYNg1iY71OIyIikSqQ\nwuM64Fbn3GQzezVX++/45vPwygyKMIfIgAEDSElJydOWlpZGWlr5ncti+bot3PvadK67rgtt23qd\nRkRESrNx48Yxbty4PG3btm0L2vHNOVe8Hcx2A82ccyvMbAfQ0jm31MxaADOccxVLFMgsB+jmnJtY\nzP2+ArY7564s5PVUYObMmTNJTU0tScQyJ/XBAcyKep25t6zg+IbVvI4jIiJlTHp6Oq1btwZo7ZxL\nL8mxAunxmA90AFbka78SmBVICDNLAprgGzAK0MjMWgKbnXOrzOxp4Gjn3PX+7e8ClgHzgATgH8BZ\nwLmBnL88+3T6AmbFvsL5cU+o6BAREc8FUng8DrxlZnXwDU693MyOw3cJ5qIAc7QBvsM3N4cDBvnb\n3wJuAmrhu333gDj/NkcDmcAfQGfn3A8Bnr9cyslx3PDOAGKi6/POff29jiMiIhLQPB4TzOxi4N/A\nLnyFSDpwsXPu68PuXPgxv+cwd9g4527M9/w54LlAzhVJHh/3GZsqf8kDDcZTuWLCkXcQEREJsUDn\n8fgRXdYo1XbuzuKp9AFUye7Mfx6+1Os4IiIiQICFh5R+aS++zL6KSxh+3kdERWmKUhERKR2KVHiY\n2RZ8Yy+OyDlXtUSJpMQ2b8nms4yXaR79Dy5rd4LXcURERA4qao+HRiaWIS+9GE3sm7/y7q9eJxER\nEcmrSIWHB+uwSIA2bvStx3Jnnxqc2NjrNCIiInkVe4yHmdU/3OvOuZWBx5GSGjjQt+rs/fd7nURE\nRORQgQwuXc7hx3tEBxZFSmr1ahg6FB58EKpprjARESmFAik8Ts73PNbfdje+BeTEI088ARUrwoAB\nXicREREpWCATiP1eQPNvZvY3cC/wUYlTSbH99ZdvBdpnnoHkZK/TiIiIFKzQ2UIDsAg4JYjHk2J4\n5BE46ijo29frJCIiIoUrduFhZsn5Hilm1gx4Elgc/IhyJON/nsvYrJ7c/dAmKlTwOo2IiEjhAhnj\nsZVDB5casAroWeJEUmwDPnqa6AbT6HOjrrGIiEjpFkjhcTZ5C48cYCPwl3Nuf1BSSZFN+X0pKyq+\nw5UVXyIxIdbrOCIiIocVyODSKSHIIQG6fcxzmFXn1btv9jqKiIjIEQUyxuNBM7uxgPabzEzTVoXR\n7CVrmR8/gnMr9adaigZ3iIhI6RfIXS23AfMLaJ8H9C5ZHCmOW0cMhuwEXr9Vt7KIiEjZEEjhUQvY\nUED7RqB2yeJIUS1bu4Vf+S9to/tSv2aK13FERESKJJDCYxXQroD2dsDfJYsjRfXA618DObx+kxYO\nFhGRsiOQu1peB140s1jgW39bZ+BZYFCwgknhdu2CyUOu4qa0szihYQ2v44iIiBRZIIXHc0A1YBgQ\n52/bAzzjnHs6WMGkcG+8AVu3wsP3qOgQEZGyJZDbaR1wv5k9ATQHdgOLnXN7gx1ODrVvHwwaBFdf\nDQ0aeJ1GRESkeEqyVkstoCqwxDm318wsSJnkMD7+GFatgnvu8TqJiIhI8QUyj0c1M5sM/Al8xv/u\nZBluZhrjEWIvvwxnngktW3qdREREpPgC6fEYDOwD6gOZudrfBboEI5QUbNYs+PFHuPNOr5OIiIgE\nJpDBpecB5zvnVue7urIYOCYoqaRAL78M9erBpZd6nURERCQwgfR4JJG3p+OAqoAGmIbIolUZjFr9\nEDf02UxMIOWiiIhIKRBI4fEjcF2u587MooD7gO+CkkoOcedbr5N96iCu6ZXjdRQREZGABfLd+T5g\nspm1wTePx7PA8fh6PAqa0VRKaPfe/UzeNoxjuYbj6lX3Oo6IiEjAit3j4ZybCxwL/ARMwHfp5SPg\nZOfckuDGE4CHRn9MdsXVPH5RP6+jiIiIlEhAowWcc9uA/wQ5ixTijTlDSOFMenTUPbQiIlK2Fanw\nMLOTinpA59wfgceR/MZNmcX2Kj9yd933vY4iIiJSYkXt8ZgNOOBIs5M6ILpEiSSPxyYNI5q6/Ofa\nbl5HERERKbGiFh4NQ5pCCrRu804Wxb1Dx9h7SIjTPbQiIlL2FenTzDm3ItRB5FCfjk+EcRN4dlIz\nr6OIiIgERUBfo82sMdAf3+q0APOBl3RXS3C9OSKK85qezanNj7ytiIhIWRDIInHn4ys0TgX+8D9O\nA+aZ2bnBjRe5FiyAqVPh5pu9TiIiIhI8gfR4DAQGO+ceyN1oZgOBZ4CvgxEs0g0fDtWqaV0WEREp\nXwKZMr05MLyA9hFAi5LFEYCsLBg1Cq69FuLjvU4jIiISPIEUHhuBVgW0twI2lCyOAHz6KWzcqMss\nIiJS/gRyqeV14P+ZWSNgqr+tHXA/8EKwgkWy4cPh1FPhhBO8TiIiIhJcgRQeTwA7gHuAp/1tfwOP\nAkOCEytyLVy6g8+/ieG1Vyp4HUVERCToAlkkzjnnBjvn6gIpQIpzrq5z7iXnnAt+xMhyx+iXoF9T\nrui+3+swO0OcAAAdC0lEQVQoIiIiQVei6TCdczuCFURgf3YO328fQWPOpWplzVQqIiLlT5E/3czs\n26Js55w7O/A4ke2VT35gf6VlDGg9yusoIiIiIVGcr9WdgBXAJGBfSNJEuNemjiUmpwG9L2zndRQR\nEZGQKE7hcT9wI9AdGAOMcM7NDUmqCLRzdxaLoj/g9IQ+REUdaRFgERGRsqnIg0udc88551oA3YBK\nwM9mNsPMeptZcsgSRohnPvgSl7CF+7pc7XUUERGRkAnkrpZpzrl/ALWBocBNwN8qPkpm1OyxJGw9\niUvPON7rKCIiIiETyMylB6QCHfFNoT4XjfsI2I4djtXbV9GxWprXUUREREKqWPdsmtnRwA3+RzIw\nGjjNOTc/6MkiyMSJRs4bPzF0SbbXUUREREKqOLfTfgacBXwF3AtMcs5plqsgGDcO2rWDxo2ivY4i\nIiISUsXp8egCrAXqA48Aj5gdeveFcy41ONEiQ0YGfPklvPSS10lERERCrziFx2MhSxHBPvgAnIPu\n3b1OIiIiEnpFLjyccyo8QmDsWDj3XKhRw+skIiIioVeSu1qkhFauhB9/hKs1dYeIiEQIFR4eevdd\nSEiAbt28TiIiIhIeKjw8NPSHcZzXLYNKlbxOIiIiEh4qPDwy5felrGhzNU3OmeJ1FBERkbApUuFh\nZpvNrLr/3yPMTN/RS2jQZ+Nhfzz3XtbF6ygiIiJhU9Qejzh8M5UCXA8khCZO5Ph+/XiO2nketapW\n9DqKiIhI2BT1dtppwMdmNhMwYIiZ7S5oQ+fcTcEKV17NXbaeHZWnclX1EV5HERERCauiFh69gAFA\nY8ABKajXI2ADJ0wAF8X93S72OoqIiEhYFanwcM6tBx4AMLNlwLXOuU2hDFaefbHiIyq7M2lat5rX\nUURERMKq2He1OOcaqugI3MoN29hU6Vs617nM6ygiIiJhF9DttGbW0cw+MbO//I+JZtYh2OHKow8/\ny4Al53LvRZo1TEREIk+xCw8z6wV8A2QCQ/yP3cBkM9Pk30cwdVJjTlk8idOa1/M6ioiISNgVZ3Xa\nA/4F3OecG5yrbYiZ3Q08DIwNSrJyaPdu+OwzeOghr5OIiIh4I5BLLY2ATwponwg0DCSEmXXwX65Z\nY2Y5ZnZJEfbpZGYzzWyPmf1pZtcHcu5w+vpryMyEyy/3OomIiIg3Aik8VgGdC2g/x/9aIJKA2UBf\nfLfrHpaZNQA+BSYDLYGXgDfM7NwAzx8W48dD8+Zw3HFeJxEREfFGIJdaBuG7tNIKmOpvawfcANwV\nSAjn3BfAFwBmZkXYpQ+w1Dl3n//5IjNrj2+uka8DyRBq+/fDxInQu7fXSURERLxT7MLDOfdfM1sH\n3ANc5W9eAPRwzk0IZrjDaItvgGtuXwKDC9i2VPjhB9i8GS7TXbQiIhLBAunxwDk3Hhgf5CzFUQtY\nn69tPZBsZvHOub0eZDqsiROhbl1o3drrJCIiIt4JaB4PKb4xSwfT/pIlFOlCkoiISDkVUI9HKbAO\nOCpf21HA9iP1dgwYMICUlJQ8bWlpaaSlpQU3YS7fpC8mo/XdNGrUGN9yNyIiIqXTuHHjGDduXJ62\nbdu2Be34ZbXwmAZckK/tPH/7YQ0ePJjU1NSQhCrMq5M/h/1x9Ot6dljPKyIiUlwFfRlPT0+ndZDG\nCpSKSy1mlmRmLf13ygA08j+v53/9aTN7K9cur/q3ecbMjjOzvsCVwAthjl4k3//9GVV3nEmtqhW9\njiIiIuKpYhUeZhZrZkvMrHmQc7QBZgEz8c3jMQhIBx7zv14LODjHuHNuOdAV39whs/HdRnuzcy7/\nnS6ey9iWSUbFKbSvdaHXUURERDxXrEstzrl9ZpYQ7BDOue85TBHknLuxgLYfgFJ/j8grk76DmL3c\ndnb+K0MiIiKRJ5BLLUOB+82srI4PCauP/vicmB0N6dJG05WKiIgEUjycgm/K9PPMbA6wK/eLzjmt\nROKXk+NYsP8zmkVfQFSU7qMVEREJpPDYCnwY7CDl0ZwFe9j/Z2d69rzC6ygiIiKlQiBTph8y3kIK\n9t3XFYj/6nX6jzvytiIiIpEgoNtpzSzGzM4xs9vMrJK/7Wgz0/2iuXz2GXTsCElJXicREREpHYpd\neJjZMcAcYAK+gaY1/C/dDzwfvGhl265d8P33cKHuohURETkokB6Pl4DfgCrA7lzt4/ENOhXg228h\nKwsu0F20IiIiBwUyuLQDcIZzLsvyrni2HKgTjFDlweefQ+PG0LSp10lERERKj0B6PKKA6ALa6wI7\nShanfHDON77jggvQarQiIiK5BFJ4fAX0z/Xc+QeVPgZ8FpRUZdyiRbBihS6ziIiI5BfIpZZ7gC/N\nbD6QAIwFmgIZQOjWli9DXv38B6Kb76Bjx65eRxERESlVApnHY7WZtQR6AicBFYHhwBjn3O7D7hwh\n3lv5IknnZZCUpMJDREQkt4DWW3HO7QdGBzlLuZC1L5t1Cd/RMaH/kTcWERGJMAEVHmZ2HNAPaO5v\nWgC84pxbGKxgZdV7P8zGJWzlitSzvY4iIiJS6gQygdgVwFx8S9L/7n+kAnP8r0W0sb9MhqxEbjjn\nNK+jiIiIlDqB9Hg8CzztnPt37kYze8z/WkQvIDcjYzLV3ZlUrBDndRQREZFSJ5DbaWsDowpoH+1/\nLWLt3J3FpqQfObWmLrOIiIgUJJDCYwq+2Uvzaw/8WKI0ZdybX/8Csbu5uq1mjhcRESlIkS61mNkl\nuZ5OBJ4xs9bAL/62tkB34JHgxitbfk3fR8yqc+jeoaXXUUREREqloo7x+LiAtr7+R25DgVdLlKgM\nWza5MxfX6ExcrNdJRERESqciXWpxzkUV8VHQGi4RYdcu+OUX6KyrLCIiIoUKZIyHFODHH2H/fjhb\n40pFREQKFegEYqcAZwE1yVe8OOfuDkKuMufbb6F2bWjWzOskIiIipVexCw8z+z/gSWARsB5wuV52\nBe4UASZP9vV2mHmdREREpPQKpMfjLuAm59zIIGcpszZvhlmz4I47vE4iIiJSugUyxiMH+DnYQcqy\nKVPAOY3vEBEROZJACo/BwO3BDlKWjfl+GvVPWsExx3idREREpHQL5FLL88AkM1sCzAf25X7ROXd5\nMIKVJZ9G30yj89sD/8/rKCIiIqVaID0eQ/Dd0fInsAnYlu8RURatyiArZQGdGp7pdRQREZFSL5Ae\nj+uBK5xzk4IdpiwaNWUqANd0aO9xEhERkdIvkMJjM7Ak2EHKqq8X/kR0Vl3OaKEBHiIiIkcSyKWW\nR4HHzCwxyFnKpAWZP1Inpz1RUZrAQ0RE5EgC6fG4E2gMrDez5Rw6uDQ1CLnKhIxtmeysNJMLknt5\nHUVERKRMCKTwKGil2og0ZsqvEL2PK0/V+A4REZGiKHbh4Zx7LBRByqKf/1iDba9Ht9NP8DqKiIhI\nmaDVaUtg+89Xc/6CFcTFRnsdRUREpEwoduFhZjlmll3YIxQhS6PsbJg6FTq016BSERGRogpkjMdl\n+Z7HAifjm9/jkRInKiPmzIEdO6C9hneIiIgUWSBjPCYU0PyBmc0DegDDS5yqDPjpJ4iNhVNO8TqJ\niIhI2RHMMR6/AJ2DeLxS7aeffEVHhQpeJxERESk7glJ4mFkFfPN7rAnG8Uo75+DHH3WZRUREpLiK\nfanFzLYALncTUAnIBCJiJq3ly+Hvv1V4iIiIFFcgg0v753ueA2wEpjvntpQ8Uun31Q/bwCpyxhm6\njVZERKQ4Ahlc+lYogpQlL867jwp3zKZateleRxERESlTilx4mFn9omznnFsZeJyyYdn+n2iU0MHr\nGCIiImVOcXo8lpN3bMcBlqvdFfOYZc7i1ZvYmzKfjjUf9DqKiIhImVOcIuHkQtoN6InvrpadJU5U\nyo387mcArumgkaUiIiLFVeTCwzn3e/42MzsHGAgcCzwLDApetNJp8qKpRGUdzRktjvE6ioiISJkT\n0GURM0sFngE6AG8AFzrnNgQzWGm1aOcMakWdRlSU1mgREREprmJNIGZmjc3sXWAGvltoWzjn7oiU\noiNrXzZbk37lpGqneR1FRESkTCpy4WFmw4D5QArQxjl3tXNuaciSlUKf/7oQ4nZybotTvY4iIiJS\nJhXnUktvYA9QExhhVvClBudcahBylUoZC1rAS0u5dkltr6OIiIiUScUpPB4LWYoy4tdfjeOPbkiN\nKl4nERERKZuKc1dLxBce06fDaRreISIiErCgrE4bCTIzYc4cOFXDO0RERAKmwqOI0tMhO1s9HiIi\nIiWhwqOIZsyAChXghBO8TiIiIlJ2qfAoounToXVriCnXK9GIiIiEVokKDzNLCFaQ0m7GDI3vEBER\nKaliFx5mFmVmD5vZGmCnmTXytz9hZjcHPWEpMG/5BpZ3PoOaLWd5HUVERKRMC6TH4yHgBuA+ICtX\n+1zgliBkKnXe/WkG1JtGu1RN4CEiIlISgRQe1wG3OufGANm52n8HmgUlVSkzZfEMLLOGVqQVEREp\noUCGStYB/iqgPQqILVmc0mn+tunUMK1IKyIiUlKB9HjMBzoU0H4lUO4GQeTkODZXmMEJVTSyVERE\npKQC6fF4HHjLzOrgK1wuN7Pj8F2CuSiY4UqDr9MX4xK2ck4zzRwmIiJSUsXu8XDOTQAuBs4BduEr\nRJoDFzvnvg5uPO99/OsMAHp2OMXjJCIiImVfQNNhOed+BM4NcpZS6ecV04nddywNa+uOFhERkZIK\neAIxM4szs7pmVj/3owTHu93MlpnZbjP7xcwK7WIws45mlpPvkW1mNQM9f2H2/X4FbTMfD/ZhRURE\nIlKxezzMrCkwAjgj/0uAA6IDOGYPYBBwKzADGAB8aWbHOucyCtnNAccCOw42OLehuOc+nL17Yem3\nnbh9UDCPKiIiErkCudQyEtiPbyDpWnwFQEkNAF5zzo0CMLPeQFfgJuDZw+y30Tm3PQjnL9CcOZCV\nBadoeIeIiEhQBFJ4tAJaO+cWBiOAmcUCrYGnDrQ555yZfQOcfrhdgdn+9WLmAo8656YGI9MBs2ZB\ndDScdFIwjyoiIhK5Ap3Ho3oQM1THd3lmfb729UCtQvZZC9wGXAFcDqwCpphZqyDmYtYsaNYMKlQI\n5lFFREQiV5F6PMwsOdfT+4Fnzez/gDnAvtzbhvLSR65z/An8mavpFzNrjO+SzfWH23fAgAGkpKTk\naUtLSyMtLe2QbdPT4eSTS55XRESkrBg3bhzjxo3L07Zt27agHb+ol1q2kncshwGT820T6ODSDHxr\nvhyVr/0oYF0xjjMDaHekjQYPHkxqauoRD5adDX/8AVddVYwEIiIiZVxBX8bT09Np3bp1UI5f1MLj\nrKCcrQDOuX1mNhPoDEwEMDPzPx9SjEO1wncJJigWLYLdu6EINYqIiIgUUZEKD+fc92b2b+B551xm\nCHK8AIz0FyAHbqdNxHcHDWb2NHC0c+56//O7gGXAPCAB+Ae+4ihok5p9MO1XaDWPli2vx9eZIyIi\nIiVVnLtaHgFeBYJeeDjn3jOz6vimXz8KmA2c75zb6N+kFlAv1y5x+Ob9ONqf5w+gs3Puh2Blmrjk\nHWI6j6dKlRuCdUgREZGIV5zCI6Rf+51zw4Bhhbx2Y77nzwHPhTLPksxZ1DRdZxEREQmm4t5OG4zJ\nwkq9nBzHtgqzaFFVt7SIiIgEU3EnEPvTzA5bfDjnqpYgT6nw09zluISttG+swkNERCSYilt4PAIE\n72beUurTmbMAuPQ0FR4iIiLBVNzC451gL8RWGk1bPouo3bVo1bi211FERETKleIUHhExvgNg0fZ0\nqqHeDhERkWArzuDSiJnMYueGqpxQsZPXMURERMqdIvd4OOcCWVCuzFm/HnaPfZu+73udREREpPyJ\niGKiOGb5xpVqcTgREZEQUOGRT3o6pKRAo0ZeJxERESl/VHjkM2sWtGoFFjEjWkRERMJHhUc+s2bp\nMouIiEioqPDIZds2WLJEhYeIiEioqPDIZfZs339TtTaciIhISKjwyOXn9C3EV9hPs2ZeJxERESmf\nVHjkMnxNf2L/0ZGY4k4kLyIiIkWiwiOXv7NnUzf+eK9jiIiIlFsqPPwy9+xjT6UFnFDjJK+jiIiI\nlFsqPPy+mb0YovfRrukJXkcREREpt1R4+E2eMweArm1O9DiJiIhI+aVhlH7pq+cStbs2TetW8zqK\niIhIuaXCw++v7XOo4tTbISIiEkq61OKXET2HBoka3yEiIhJK6vEAdu2C/W98S9pz0V5HERERKddU\neADz5gHbjqGj1mgREREJKV1qAebOBTNo0cLrJCIiIuWbCg9gzhxo3BgSE71OIiIiUr6p8MBXeJyo\nG1pERERCToUHvkstJ+iGFhERkZCL+MJj40ZYv149HiIiIuEQ8YXH3Lm+/6rwEBERCb2ILzzenvkh\n0V3706SJ10lERETKv4ifx2Pq+i+Ja/orMRH/ToiIiIRexPd4rNk/h1pRus4iIiISDhFdeGRnO3Ym\nzqVZVd3SIiIiEg4RXXhMW7AC4nbStpF6PERERMIhoguPL2fNAeD8VurxEBERCYeILjxmLJ8Le1I4\n5bi6XkcRERGJCBF9L8eirXNIzj6RqCjzOoqIiEhEiOjCI2tJO1o2ivY6hoiISMSI2EstWVmwcdLt\n9GzS2+soIiIiESNiC48//4T9+7U4nIiISDhFbOFxYI0WFR4iIiLhE7GFx/z5UKsWVK3qdRIREZHI\nEbGFx4IF0Ly51ylEREQiS8QWHgsXqvAQEREJt4gsPLKzfYNLmzXzOomIiEhkicjC449F28iq/huN\nj83yOoqIiEhEicjCY3z6j3DrKdRosMHrKCIiIhElIguP9JULIasirZvW8TqKiIhIRInIKdP/3LKA\nxP3NtEaLiIhImEVkj8e6fQs5KkojS0VERMIt4gqPnBzHzgoLaFxZhYeIiEi4RVzhsWzdFlzCFlrV\n0SQeIiIi4RZxhcevi5cD0KGFejxERETCLeIKj3mrV0FONGe3bOJ1FBERkYgTcYVH5XWX0vijDVSs\nEOd1FBERkYgTcYXHsmVwfCMtSSsiIuKFiCw8tEaLiIiINyKu8Fi3TqvSioiIeCXiCg9Qj4eIiIhX\nVHiIiIhI2ERc4VGtGlSu7HUKERGRyBRxhUeDBl4nEBERiVwRV3hw3ESvE4iIiESsiCs8kqvv8jqC\niIhIxIq4wqNF7QZeRxAREYlYpabwMLPbzWyZme02s1/M7JQjbN/JzGaa2R4z+9PMri/Kedo0aRCU\nvFI048aN8zpCxNF7Hn56z8NP73nZVSoKDzPrAQwCHgFOBn4HvjSz6oVs3wD4FJgMtAReAt4ws3OP\ndK4WxxwVnNBSJPrjEH56z8NP73n46T0vu0pF4QEMAF5zzo1yzi0EegOZwE2FbN8HWOqcu885t8g5\nNxT4wH+cw4qJLi0/soiISOTx/FPYzGKB1vh6LwBwzjngG+D0QnZr6389ty8Ps72IiIiUAp4XHkB1\nIBpYn699PVCrkH1qFbJ9spnFBzeeiIiIBEuM1wHCKAFgwYIFXueIKNu2bSM9Pd3rGBFF73n46T0P\nP73n4ZXrszOhpMcqDYVHBpAN5B/1eRSwrpB91hWy/Xbn3N5C9mkA0KtXr8BSSsBat27tdYSIo/c8\n/PSeh5/ec080AKaW5ACeFx7OuX1mNhPoDEwEMDPzPx9SyG7TgAvytZ3nby/Ml8A1wHJgTwkii4iI\nRJoEfEXHlyU9kPnGcXrLzK4CRuK7m2UGvrtTrgSaOec2mtnTwNHOuev92zcA5gDDgBH4ipQXgQud\nc/kHnYqIiEgp4XmPB4Bz7j3/nB2P47tkMhs43zm30b9JLaBeru2Xm1lXYDBwJ7AauFlFh4iISOlW\nKno8REREJDKUhttpRUREJEKo8BAREZGwiYjCo7gL0EngzOxBM5thZtvNbL2ZjTezY73OFUnM7AEz\nyzGzF7zOUp6Z2dFm9raZZZhZppn9bmapXucqr8wsysyeMLOl/vf7LzN7yOtc5YmZdTCziWa2xv83\n5JICtnnczP72/2/wtZk1Ke55yn3hUdwF6KTEOgAvA6cB5wCxwFdmVsHTVBHCX1Tfiu/3XELEzCoD\nPwN7gfOB5sA9wBYvc5VzDwC3AX2BZsB9wH1mdoenqcqXJHw3d/QFDhkAamb3A3fg+xtzKrAL3+dp\nXHFOUu4Hl5rZL8B059xd/ucGrAKGOOee9TRcBPAXeBuAM51zP3mdpzwzs4rATHyLKD4MzHLO3e1t\nqvLJzAYCpzvnOnqdJVKY2SfAOufcP3K1fQBkOueu8y5Z+WRmOUA359zEXG1/A8855wb7nyfjW67k\neufce0U9drnu8QhwAToJrsr4KufNXgeJAEOBT5xz33odJAJcDPxmZu/5Lymmm9ktXocq56YCnc2s\nKYCZtQTaAZ95mipCmFlDfFNb5P483Q5Mp5ifp6ViHo8QOtwCdMeFP05k8fcuvQj85Jyb73We8szM\negKtgDZeZ4kQjfD1LA0C/oOv23mIme11zr3tabLyayCQDCw0s2x8X5z/5Zx7x9tYEaMWvi+RxVnQ\ntUDlvfAQbw0DWuD7ViIhYmZ18RV45zjn9nmdJ0JEATOccw/7n/9uZifgm31ZhUdo9ACuBnoC8/EV\n2i+Z2d8q9sqWcn2phcAWoJMgMLNXgAuBTs65tV7nKedaAzWAdDPbZ2b7gI7AXWaW5e95kuBaC+Rf\n6noBUN+DLJHiWWCgc+5959w859wYfLNXP+hxrkixDjCC8HlargsP/7e/AwvQAXkWoCvR6npSOH/R\ncSlwlnNupdd5IsA3wIn4vgG29D9+A0YDLV15H0HujZ859HLtccAKD7JEikR8XyRzy6Gcf46VFs65\nZfgKjNyfp8n47mAs1udpJFxqeQEY6V8B98ACdIn4FqWTIDOzYUAacAmwy8wOVMfbnHNaFTgEnHO7\n8HU9H2Rmu4BNzrn838olOAYDP5vZg8B7+P743gL847B7SUl8AjxkZquBeUAqvr/nb3iaqhwxsySg\nCb6eDYBG/kG8m51zq/Bd0n3IzP7Ct9L7E/jWSptQrPNEwpchM+uL757vAwvQ9XPO/eZtqvLJfwtW\nQb9UNzrnRoU7T6Qys2+B2bqdNnTM7EJ8Ax6bAMuAQc65Ed6mKr/8H4pPAJcBNYG/gbHAE865/V5m\nKy/MrCPwHYf+DX/LOXeTf5tH8c3jURn4EbjdOfdXsc4TCYWHiIiIlA66NiYiIiJho8JDREREwkaF\nh4iIiISNCg8REREJGxUeIiIiEjYqPERERCRsVHiIiIhI2KjwEBERkbBR4SEiYWFmHc0s27++g4hE\nKBUeIlJiZpbjLypyCnhkm9m/8S2sVts5t93rvCLiHU2ZLiIlZmY1cz3tCTwGHMv/Fpva6ZzLDHsw\nESl11OMhIiXmnNtw4AFs8zW5jbnaM/2XWnIOXGoxs+vNbIuZdTWzhWa2y8zeM7MK/teWmdlmM3vJ\nzA4UMJhZnJk9b2arzWynmU3zL24lImVAjNcBRCSi5O9iTQT6AVcBycB4/2MLcAHQCPgI+Al437/P\nUKCZf5+1+FYr/dzMTnTOLQn1DyAiJaPCQ0S8FAP0ds4tBzCzD4BeQE3n3G5goZl9B5wFvG9m9YEb\ngHrOuXX+Y7xgZhcANwIPhTm/iBSTCg8R8VLmgaLDbz2w3F905G47MIbkBCAa+DP35RcgDsgIZVAR\nCQ4VHiLipX35nrtC2g6MR6sI7AdSgZx82+0MejoRCToVHiJSlszC1+NxlHPuZ6/DiEjx6a4WEQkn\nO/ImhXPOLQbGAqPM7DIza2Bmp5rZA/5xHiJSyqnwEJFwCsbEQTcAo4DngYX47nppA6wMwrFFJMQ0\ngZiIiIiEjXo8REREJGxUeIiIiEjYqPAQERGRsFHhISIiImGjwkNERETCRoWHiIiIhI0KDxEREQkb\nFR4iIiISNio8REREJGxUeIiIiEjYqPAQERGRsFHhISIiImHz/wFXhVvpQ2CIZAAAAABJRU5ErkJg\ngg==\n", "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "from math import exp\n", "run_simulation(10.0, model=m1, opt_args=['-', lambda t: 2.0 * (1 - exp(-t)), '--'])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "A chain of serial reactions can be described in one line. To split a line into two or more physical lines, wrap lines in a parenthesis:" ] }, { "cell_type": "code", "execution_count": 25, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "['E+S>ES|0.5', 'ES>E+S|1', 'ES>E+P|1.5']\n" ] } ], "source": [ "with reaction_rules():\n", " (E + S == ES | (0.5, 1.0)\n", " > E + P | 1.5)\n", "\n", "m1 = get_model()\n", "print([rr.as_string() for rr in m1.reaction_rules()])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The method uses global variables in `ecell4.util.decorator` (e.g. `REACTION_RULES`) to cache objects created in the `with` statement:" ] }, { "cell_type": "code", "execution_count": 26, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[, ]\n", "[]\n" ] } ], "source": [ "import ecell4.util.decorator\n", "\n", "with reaction_rules():\n", " A + B == C | (0.01, 0.3)\n", "\n", "print(ecell4.util.decorator.REACTION_RULES) #XXX: Only for debugging\n", "get_model()\n", "print(ecell4.util.decorator.REACTION_RULES) #XXX: Only for debugging" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "For the modularity in building `Model`, decorator functions are also usefull. " ] }, { "cell_type": "code", "execution_count": 27, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[, , ]\n", "[, ]\n" ] } ], "source": [ "@species_attributes\n", "def attrgen1(radius, D):\n", " A | B | {'radius': str(radius), 'D': str(D)}\n", " C | {'radius': str(radius * 2), 'D': str(D * 0.5)}\n", "\n", "@reaction_rules\n", "def rrgen1(kon, koff):\n", " A + B == C | (kon, koff)\n", "\n", "attrs1 = attrgen1(0.005, 1)\n", "rrs1 = rrgen1(0.01, 0.3)\n", "print(attrs1)\n", "print(rrs1)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Do **not** add parenthesis after decorators in contrast to the case of the `with` statement. The functions decorated by `reaction_rules` and `species_attributes` return a list of `ReactionRule`s and `Species` respectively. The list can be registered to `Model` at once by using `add_reaction_rules` and `add_species_attributes`. " ] }, { "cell_type": "code", "execution_count": 28, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "2\n" ] } ], "source": [ "m1 = NetworkModel()\n", "m1.add_species_attributes(attrs1)\n", "m1.add_reaction_rules(rrs1)\n", "print(m1.num_reaction_rules())" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "This method is modular and reusable relative to the way using `with` statement." ] } ], "metadata": { "kernelspec": { "display_name": "Python [conda root]", "language": "python", "name": "conda-root-py" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.5.2" } }, "nbformat": 4, "nbformat_minor": 0 }