{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "6f716cf0",
   "metadata": {},
   "source": [
    "<img src=\"https://raw.githubusercontent.com/holoviz/param/main/doc/_static/logo_horizontal.png\" style=\"display:block;margin-left:auto;margin-right:auto;width:50%;max-width:500px\">"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "fbaa7540",
   "metadata": {},
   "source": [
    "# Introduction"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "cddd48c6",
   "metadata": {},
   "source": [
    "**Param is a library providing Parameters:**<br>\n",
    "<div style=\"padding-left:1cm;\">\n",
    "\n",
    "Python attributes extended to have features such as\n",
    "* type and range checking\n",
    "* dynamically generated values\n",
    "* documentation strings\n",
    "* default values\n",
    "* events\n",
    "</div>\n",
    "\n",
    "**Param enables you to write robust and powerful applications in just a few lines of code**.\n",
    "\n",
    "**Param  is free, open source, small, and has no external dependencies**, so that it can easily be included as part of other projects."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "aee0b3e3",
   "metadata": {},
   "source": [
    "# Example: A Parameterized Class"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "3d689222",
   "metadata": {},
   "source": [
    "The [Pythagorean Theorem](https://en.wikipedia.org/wiki/Pythagorean_theorem) is one of the world's most famous equations.\n",
    "<img src=\"https://miro.medium.com/max/658/1*SsN2DG__Z5DyOI0uf7hbwQ.png\" style=\"display:block;margin-top:0.5cm;margin-left:2cm;margin-right:auto;width:40%;max-width:700px;border: 2px solid black;\">\n",
    "\n",
    "<br>\n",
    "\n",
    "**We will illustrate how powerful Param is** by building a model of the Pythagorean Theorem."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "0e23597c",
   "metadata": {},
   "source": [
    "### **Pythagorean Theorem Class**"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "5e1b9718",
   "metadata": {},
   "outputs": [],
   "source": [
    "import param, math, time"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "d32f4629",
   "metadata": {},
   "outputs": [],
   "source": [
    "class PythagoreanTheorem(param.Parameterized):\n",
    "    \"\"\"Model of the Pythagorean Theorem\"\"\"\n",
    "\n",
    "    a = param.Number(default=0, bounds=(0,None), doc=\"Length of side a\")\n",
    "    b = param.Number(default=0, bounds=(0,None), doc=\"Length of side b\")\n",
    "    c = param.Number(default=0, bounds=(0,None), doc=\"Length of the hypotenuse c\",\n",
    "                     constant=True)\n",
    "\n",
    "\n",
    "    def __init__(self, **params):\n",
    "        super().__init__(**params) # Sets values a and b if provided in the params\n",
    "        \n",
    "        self._update_hypotenuse() # Sets the value c\n",
    "\n",
    "\n",
    "    @param.depends(\"a\", \"b\", watch=True) # Triggers a run of the function whenever a or b is changed\n",
    "    def _update_hypotenuse(self):\n",
    "        \"\"\"Updates the length of the hypotenuse\"\"\"\n",
    "        with param.edit_constant(self):\n",
    "            self.c = math.sqrt(self.a**2+self.b**2)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "6644582b",
   "metadata": {},
   "source": [
    "### **Pythagorean Theorem Object**"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "90d79024",
   "metadata": {},
   "source": [
    "**Lets try to use the model**"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "dc521631",
   "metadata": {},
   "outputs": [],
   "source": [
    "pythagoras = PythagoreanTheorem(a=3, b=4)     # create an object with initial values for the parameters a and b\n",
    "pythagoras.c                                  # print the result for c"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f8cf6a71",
   "metadata": {},
   "source": [
    "### **Using the Parameters**"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "92c716bf",
   "metadata": {},
   "source": [
    "We will now **take a closer look** at what these few lines of code provide us:"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "3701b783",
   "metadata": {},
   "source": [
    "#### **Param Provides Parameter Validation**"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "c35d3cb2",
   "metadata": {},
   "outputs": [],
   "source": [
    "# check admissible parameter values\n",
    "try:\n",
    "    pythagoras1 = PythagoreanTheorem(a=-1, b=4)\n",
    "except Exception as ex:\n",
    "    print(ex)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "8f4f72ac",
   "metadata": {},
   "outputs": [],
   "source": [
    "# check parameter types\n",
    "try:\n",
    "    pythagoras2 = PythagoreanTheorem(a=\"length is 3\", b=4)\n",
    "except Exception as ex:\n",
    "    print(ex)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "504d07f4",
   "metadata": {},
   "source": [
    "Param contains a wide range of useful parameter types, including\n",
    "* `String`\n",
    "* `Integer`\n",
    "* `Float`\n",
    "* `Bool`\n",
    "* `DataFrame`"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "0a90d64b",
   "metadata": {},
   "source": [
    "#### **Param Provides Constant Parameters**"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "47e2e544",
   "metadata": {},
   "outputs": [],
   "source": [
    "# constant values cannot be changed\n",
    "try:\n",
    "    pythagoras.c = 3\n",
    "except Exception as ex:\n",
    "    print(ex)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "7b79b3b7",
   "metadata": {},
   "source": [
    "#### **Param Provides Default Values**"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "1ea6f981",
   "metadata": {},
   "outputs": [],
   "source": [
    "print( f\"{pythagoras.param.a.name} = {pythagoras.param.a.default}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "31978876",
   "metadata": {},
   "source": [
    "#### **Param Provides Documentation**"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "5254cd8f",
   "metadata": {},
   "outputs": [],
   "source": [
    "?pythagoras"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "1f403192",
   "metadata": {},
   "outputs": [],
   "source": [
    "# more extensive documentation\n",
    "help(pythagoras)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "b2968d3e",
   "metadata": {},
   "source": [
    "#### **Param Provides Events**"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "c3b96a84",
   "metadata": {},
   "source": [
    "You can **use events to react to parameter changes.**"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "aeaddec1",
   "metadata": {},
   "source": [
    "We have already reacted to events by using the `@param.depends(\"a\", \"b\", watch=True)` annotation<br>\n",
    "$\\quad$ to react to `a` or `b` changing by updating the calculated hypotenuse.\n",
    "\n",
    "Here we will use the alternative **`param.watch`** to just watch for changes to the hypotenuse `c` and print the event raised."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "92cdbf02",
   "metadata": {},
   "outputs": [],
   "source": [
    "def print_event(event):\n",
    "    print(event, end='\\n\\n')\n",
    "\n",
    "watcher = pythagoras.param.watch(print_event, \"c\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "f0677602",
   "metadata": {},
   "outputs": [],
   "source": [
    "for _ in range(3):\n",
    "    pythagoras.b += 1\n",
    "    time.sleep(1)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "881f0acb",
   "metadata": {},
   "source": [
    "We can also **stop watching** again:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "7ff52ca7",
   "metadata": {},
   "outputs": [],
   "source": [
    "pythagoras.param.unwatch(watcher)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "811ee5fc",
   "metadata": {},
   "source": [
    "## **Param Makes it Easy to Create GUIs**"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "5cd8053b",
   "metadata": {},
   "source": [
    "On top of param you can **quickly build interactive applications and graphical user interfaces.**"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "2fe8fe4e",
   "metadata": {},
   "source": [
    "The whole [HoloViz](https://holoviz.org) ecosystem is built in this way! \n",
    "\n",
    "<table>\n",
    "<tr style=\"background-color:transparent\">\n",
    "    <td> <a href=\"https://panel.holoviz.org\"><img style=\"height:100px;margin-right:1em;margin-left: 1em\" src=\"https://holoviz.org/assets/panel.png\"/></a></td>\n",
    "    <td> <a href=\"https://hvplot.holoviz.org\"><img style=\"height:100px;margin-right:1em;margin-left: 1em\" src=\"https://holoviz.org/assets/hvplot.png\"/></a></td>\n",
    "    <td> <a href=\"https://holoviews.org\"><img style=\"height:100px;margin-right:1em;margin-left: 1em\" src=\"https://holoviz.org/assets/holoviews.png\"/></a></td>\n",
    "    <td> <a href=\"https://geoviews.org\"><img style=\"height:100px;margin-right:1em;margin-left: 1em\" src=\"https://holoviz.org/assets/geoviews.png\"/></a></td>\n",
    "    <td> <a href=\"https://datashader.org\"><img style=\"height:100px;margin-right:1em;margin-left: 1em\" src=\"https://holoviz.org/assets/datashader.png\"/></a></td>\n",
    "    <td> <a href=\"https://param.holoviz.org\"><img style=\"height:100px;margin-right:1em;margin-left: 1em\" src=\"https://holoviz.org/assets/param.png\"/></a></td>\n",
    "    <td> <a href=\"https://colorcet.holoviz.org\"><img style=\"height:100px;margin-right:1em;margin-left: 1em\" src=\"https://holoviz.org/assets/colorcet.png\"/></a></td>\n",
    "</tr>\n",
    "</table>"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f5987dd3",
   "metadata": {},
   "source": [
    "Let's use **[Panel](https://panel.holoviz.org/) to illustrate how powerful this is.**"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "72a42b5c",
   "metadata": {},
   "outputs": [],
   "source": [
    "import panel as pn\n",
    "pn.extension()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "dd27729a",
   "metadata": {},
   "outputs": [],
   "source": [
    "pn.Param(pythagoras)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "7a0df37c",
   "metadata": {},
   "source": [
    "# Visit the Param Website"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "5ffe786d",
   "metadata": {},
   "source": [
    "**Please visit [Param's website](https://param.holoviz.org) for more information** like official releases, installation instructions, documentation, and examples.\n",
    "\n",
    "And **join the community** on the [HoloViz Discourse](https://discourse.holoviz.org/)."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "ef3afcd5",
   "metadata": {},
   "source": [
    "[<img src=\"assets/param-is-powerful.png\" style=\"display:block;margin-left:1cm;margin-right:auto;width:80%;max-width:1000px;border:2px solid black;\">](https://discourse.holoviz.org/)"
   ]
  }
 ],
 "metadata": {
  "language_info": {
   "name": "python",
   "pygments_lexer": "ipython3"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}