{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "7a2b09cc-c5da-47d7-ba51-f492767a6518",
   "metadata": {},
   "source": [
    "# Events\n",
    "\n",
    "Events are sudden changes to counts in the simulation happening at specific times or due to the fulfillment of certain conditions. \n",
    "For the first example, we focus only on the specific time by setting the count of a meta-species to 200 every 5 seconds. \n",
    "The event notation for time-based events lies in putting the simulation object under context with Python's native \"with\" notation and then using the event\\_time method. \n",
    "When the simulation is under context with Python's \"with,\" every count assignment performed will not be an initial condition but an event. "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "71d02875-b3ad-4474-8d65-86ee2888fc87",
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Compiling model\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "Species\n",
      "A,200\n",
      "\n",
      "Mappings\n",
      "A :\n",
      "A\n",
      "\n",
      "Parameters\n",
      "volume,1\n",
      "\n",
      "Reactions\n",
      "reaction_0,{'re': [(1, 'A')], 'pr': [], 'kin': 'A * 1'}\n",
      "\n",
      "Events\n",
      "event_0,{'trigger': 'true', 'delay': '10', 'assignments': [('A', '200')]}\n",
      "event_1,{'trigger': 'true', 'delay': '5', 'assignments': [('A', '200')]}\n",
      "\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Starting Simulator\n",
      "Simulation is Over\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n"
     ]
    },
    {
     "data": {
      "image/png": "[encoded data, 17612 characters]\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "from mobspy import *\n",
    "\n",
    "A = BaseSpecies()\n",
    "\n",
    "A >> Zero [1]\n",
    "\n",
    "A(200)\n",
    "S = Simulation(A)\n",
    "S.method = 'stochastic'\n",
    "S.duration = 15\n",
    "S.output_event = True\n",
    "\n",
    "with S.event_time(5):\n",
    "    A(200)\n",
    "\n",
    "with S.event_time(10):\n",
    "    set_counts({A: 200})\n",
    "\n",
    "print(S.compile())\n",
    "S.run()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "0d21ab0d-ce99-4a71-bc79-53c9299f853f",
   "metadata": {},
   "source": [
    "The other type of event is condition-based. Condition-based events trigger when the total amount of a meta-species reaches a specific value. \n",
    "The notation is similar to the time event by putting a simulation under context. However, the method used is called event_condition. This method also receives as an argument a logic expression constructed by using meta-species. "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "3f9188eb-84a8-42bc-97c6-a6a9ca530d2d",
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Compiling model\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "Species\n",
      "A.a1,100\n",
      "A.a2,100\n",
      "B.b1,120\n",
      "B.b2,120\n",
      "\n",
      "Mappings\n",
      "A :\n",
      "A.a1\n",
      "A.a2\n",
      "B :\n",
      "B.b1\n",
      "B.b2\n",
      "\n",
      "Parameters\n",
      "volume,1\n",
      "\n",
      "Reactions\n",
      "reaction_0,{'re': [(1, 'A.a1'), (1, 'B.b1')], 'pr': [], 'kin': 'A.a1 * B.b1 * 0.01 * volume^-1'}\n",
      "reaction_1,{'re': [(1, 'A.a2'), (1, 'B.b2')], 'pr': [], 'kin': 'A.a2 * B.b2 * 0.02 * volume^-1'}\n",
      "\n",
      "Events\n",
      "event_0,{'trigger': '( ( (A.a1 + A.a2) <= 50 ) && ( (B.b1 + B.b2) <= 50 ) ) ', 'delay': '0', 'assignments': [('A.a1', '100'), ('A.a2', '100'), ('B.b1', '120'), ('B.b2', '120')]}\n",
      "\n",
      "\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Starting Simulator\n",
      "Simulation is Over\n"
     ]
    },
    {
     "data": {
      "image/png": "[encoded data, 20096 characters]\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "from mobspy import *\n",
    "\n",
    "A, B = BaseSpecies()\n",
    "\n",
    "A.a1, A.a2, B.b1, B.b2\n",
    "\n",
    "A.a1 + B.b1 >> Zero [0.01]\n",
    "A.a2 + B.b2 >> Zero [0.02]\n",
    "\n",
    "All[A](100), All[B](120)\n",
    "S = Simulation(A | B)\n",
    "S.duration = 10\n",
    "S.output_event = True\n",
    "\n",
    "logic_expression = (A <= 50) & (B <= 50)\n",
    "with S.event_condition(logic_expression):\n",
    "    All[A](100), All[B](120)\n",
    "\n",
    "print(S.compile())\n",
    "S.run()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "194f9418-78b0-4525-9f80-52bbaa0072f5",
   "metadata": {},
   "source": [
    "In logic expressions, MobsPy automatically maps all states of a meta-species through a sum to evaluate their total amount (in the example, A = A.a1 + A.a2 and B = B.b1 + B.b2). If the sum of the counts of the species states satisfies the logic condition, it will trigger. The logic expressions are also compatible with the dot notation query to specify only a sum of substates of a meta-species.\n",
    "\n",
    "Unfortunately, logical clauses in MobsPy must be isolated in parenthesis when combined to respect Python operator precedence. As if the parenthesis were not there, Python would try to resolve the and operator '&' before the inequalities. \n",
    "\n",
    "The accepted operators and operations are the following: sum of different meta-species, multiplication by constant, greater and equal (>=), smaller and equal (<=), greater (>), smaller (<), and ('&'), and or ('|'). Notice that equality is not accepted as it is not an overridable operator in Python. In that case, the user must use the combination of greater and equal (>=), smaller and equal (<=), and the and ('&'). "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "da032cc5-b958-4aa6-aba2-2c1d2bfb5aac",
   "metadata": {
    "tags": []
   },
   "outputs": [],
   "source": [
    "# Perform a query \n",
    "c1 = A.a1 <= 10 \n",
    "# Combine clauses\n",
    "c2 = ((A.a1 <= 10) | (B >= 5)) & (A.a2 >= 5)\n",
    "\n",
    "# EQUALITY IS NOT ALLOWED AND WILL PRODUCE ERRORS \n",
    "# The alternative is them \n",
    "c3 = (A <= 5) & (A >= 5)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e99fdd73-49b9-452e-ac6c-894371dd7d67",
   "metadata": {},
   "source": [
    "Logical expressions can also create simulations with a conditional duration by setting the duration equal to one. \n",
    "For instance, the simulation below runs until either A or B reaches zero."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "5e2fb56e-3242-4f49-bdad-40824edb06e7",
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Compiling model\n",
      "Starting Simulator\n",
      "Simulation is Over\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n"
     ]
    },
    {
     "data": {
      "image/png": "[encoded data, 12004 characters]\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "from mobspy import *\n",
    "\n",
    "A, B = BaseSpecies()\n",
    "\n",
    "A + B >> Zero [0.01]\n",
    "\n",
    "A(110), B(100)\n",
    "S = Simulation(A | B)\n",
    "S.method = 'stochastic'\n",
    "S.duration = (A <= 0) | (B <= 0)\n",
    "S.run()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "55b7ca50-bee4-4b65-9487-8bbf942db978",
   "metadata": {},
   "source": [
    "As an important note, reactions CANNOT be added as events."
   ]
  }
 ],
 "metadata": {
  "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.8.8"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
