{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "ece0914b",
   "metadata": {},
   "source": [
    "# Dynamic or programmatic"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a614873f",
   "metadata": {},
   "source": [
    "To create a model dynamically,\n",
    "we need to create a `Builder` instance from a `Compartment`:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "6cd978fd",
   "metadata": {},
   "outputs": [],
   "source": [
    "from simbio.components import EmptyCompartment\n",
    "from simbio.reactions import single\n",
    "\n",
    "\n",
    "builder = EmptyCompartment.to_builder()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "2b1c3369",
   "metadata": {},
   "source": [
    "A `Builder` add several `add_*` methods,\n",
    "to add species, parameters and reactions.\n",
    "\n",
    "For instance,\n",
    "to add a species:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "3f47ac54",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Reference(name='A', type=<class 'simbio.components.types.Species'>, parent=<class 'simbio.components._dsl.EmptyCompartment'>, stoichiometry=1.0)"
      ]
     },
     "execution_count": 2,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "A = builder.add_species(name=\"A\", value=1)\n",
    "\n",
    "A"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "cefc36b4",
   "metadata": {},
   "source": [
    "The variable `A` is a `Reference` to the `Species`,\n",
    "which we can use in reactions:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "81471a67",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<simbio.reactions.single.Creation at 0x7f669874f0a0>"
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "builder.add_reaction(\"create_A\", single.Creation(A=A, rate=1))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "1d98ad4a",
   "metadata": {},
   "source": [
    "We can also obtain a `Reference` to `A` using attribute access:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "34429aec",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Reference(name='A', type=<class 'simbio.components.types.Species'>, parent=<class 'simbio.components._dsl.EmptyCompartment'>, stoichiometry=1.0)"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "builder.A"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "9ea1216c",
   "metadata": {},
   "source": [
    "When we finished building the model,\n",
    "we need to use the `.build()` method\n",
    "to obtain the underlying `Compartment`:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "769a8609",
   "metadata": {},
   "outputs": [],
   "source": [
    "model = builder.build()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "fc8e0a7b",
   "metadata": {},
   "source": [
    "Then,\n",
    "it can be used in a `Simulator`,\n",
    "just as a class-based model:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "108209c0",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<AxesSubplot: xlabel='time'>"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {
      "filenames": {
       "image/png": "/home/docs/checkouts/readthedocs.org/user_builds/simbio/checkouts/latest/docs/_build/jupyter_execute/model/dynamic_12_1.png"
      }
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "import numpy as np\n",
    "from simbio.simulator import Simulator\n",
    "\n",
    "t = np.linspace(0, 10, 100)\n",
    "Simulator(model).run(t).plot()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "93982896",
   "metadata": {},
   "source": [
    "## Inheriting and combining models\n",
    "\n",
    "We can inherit from a previous model\n",
    "by calling it `.to_builder()` method:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "3498d944",
   "metadata": {},
   "outputs": [],
   "source": [
    "from simbio.components import Species\n",
    "\n",
    "\n",
    "class Base(EmptyCompartment):\n",
    "    A: Species = 1\n",
    "\n",
    "\n",
    "builder = Base.to_builder()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "6dffa492",
   "metadata": {},
   "source": [
    "Or we can use the update method on an existing `Builder` instance:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "55591d02",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<simbio.components.types.CompartmentBuilder at 0x7f66678fece0>"
      ]
     },
     "execution_count": 8,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "builder = EmptyCompartment.to_builder()\n",
    "builder.update(Base)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "368abc93",
   "metadata": {},
   "source": [
    "As in the class-based models,\n",
    "adding an existing species raises an error:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "b967dbfd",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "A already exists.\n"
     ]
    }
   ],
   "source": [
    "try:\n",
    "    builder.add_species(\"A\", 2)\n",
    "except ValueError as e:\n",
    "    print(e)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "6707aef8",
   "metadata": {},
   "source": [
    "If we want to replace it,\n",
    "we must explicitly tell `SimBio`:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "id": "776b8f14",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Reference(name='A', type=<class 'simbio.components.types.Species'>, parent=<class 'simbio.components._dsl.EmptyCompartment'>, stoichiometry=1.0)"
      ]
     },
     "execution_count": 10,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "builder.add_species(\"A\", 2, replace=True)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "7a3e3f97",
   "metadata": {},
   "source": [
    "Check out the [chained reactions](../examples/chained-reactions.md) example,\n",
    "to see it in action."
   ]
  }
 ],
 "metadata": {
  "jupytext": {
   "text_representation": {
    "extension": ".md",
    "format_name": "myst",
    "format_version": 0.13,
    "jupytext_version": "1.14.0"
   }
  },
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "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.10.8"
  },
  "source_map": [
   12,
   16,
   21,
   27,
   35,
   39,
   44,
   46,
   50,
   52,
   58,
   60,
   66,
   72,
   79,
   88,
   92,
   95,
   100,
   105,
   110,
   112
  ]
 },
 "nbformat": 4,
 "nbformat_minor": 5
}