diff --git a/dash/.ipynb_checkpoints/dash-leaflet-checkpoint.ipynb b/dash/.ipynb_checkpoints/dash-leaflet-checkpoint.ipynb
index 1c391419ba01e92051c4e7663bdb8d537f941c70..e5812d1fe87a45781e0efff4a102b6abc53dfb27 100644
--- a/dash/.ipynb_checkpoints/dash-leaflet-checkpoint.ipynb
+++ b/dash/.ipynb_checkpoints/dash-leaflet-checkpoint.ipynb
@@ -46,7 +46,6 @@
    "cell_type": "markdown",
    "id": "adaf50a1-4fb2-4ed6-bbb2-7b18d2758e6f",
    "metadata": {
-    "jp-MarkdownHeadingCollapsed": true,
     "tags": []
    },
    "source": [
@@ -78,7 +77,7 @@
     "The first part of a Dash application is the layout, first of all we have to initialize our app : \n",
     "\n",
     "```Python\n",
-    "app = Dash(prevent_initial_callbacks=True, server_url=server_url, requests_pathname_prefix=base_path)\n",
+    "app = Dash(prevent_initial_callbacks=False, server_url=server_url, requests_pathname_prefix=base_path)\n",
     "``` \n",
     "\n",
     "Then we can add the components we want to the app layout, each component works like a HTML element to which we can set a CSS style attribute to manage its size, color, font, etc...\n",
@@ -112,7 +111,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 6,
+   "execution_count": 2,
    "id": "ed671aec-502e-458d-87fb-8034a2b2e79e",
    "metadata": {},
    "outputs": [
@@ -123,7 +122,7 @@
        "        <iframe\n",
        "            width=\"100%\"\n",
        "            height=\"650\"\n",
-       "            src=\"https://dev.tetras-lab.io:443/jupyter/app_proxy/8054/jupyter/app_proxy/8054/\"\n",
+       "            src=\"https://dev.tetras-lab.io:443/jupyter/app_proxy/8050/jupyter/app_proxy/8050/\"\n",
        "            frameborder=\"0\"\n",
        "            allowfullscreen\n",
        "            \n",
@@ -131,7 +130,7 @@
        "        "
       ],
       "text/plain": [
-       "<IPython.lib.display.IFrame at 0x7f7109a2f460>"
+       "<IPython.lib.display.IFrame at 0x7f74c2709e80>"
       ]
      },
      "metadata": {},
@@ -150,7 +149,7 @@
     "import dash_bootstrap_components as dbc\n",
     "import plotly.express as px\n",
     "\n",
-    "app = Dash(prevent_initial_callbacks=True, server_url=server_url, requests_pathname_prefix=base_path)\n",
+    "app = Dash(prevent_initial_callbacks=False, server_url=server_url, requests_pathname_prefix=base_path)\n",
     "\n",
     "dropdown = dcc.Dropdown(\n",
     "        id='demo-dropdown',\n",
@@ -172,7 +171,7 @@
    "id": "0d6f8c87-d80e-4520-9415-2a7be591b6b1",
    "metadata": {},
    "source": [
-    "We will now use the Dash_Leaflet Library to display an interactive map, the component to use is ```dl.Map()``` , without adding anything else, the only thing that will be displayed is a grey square, we need to draw some map tiles. By adding ``` dl.TileLayer()``` as an argument, Dash Leaflet will add a basic map layer.\n",
+    "We will now use the Dash_Leaflet Library to display an interactive map, the component to use is ```dl.Map()``` , without adding anything else, the only thing that will be displayed is a grey square, we need to draw some map tiles. By adding ``` dl.TileLayer()``` as an argument, Dash Leaflet will add a default map layer based on OpenStreetMap.\n",
     "\n",
     "```Python\n",
     "mapComponent = dl.Map(children=\n",
@@ -192,7 +191,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 10,
+   "execution_count": 3,
    "id": "06e83bd3-ba85-48f4-b3e0-99014887e3d1",
    "metadata": {},
    "outputs": [
@@ -203,7 +202,7 @@
        "        <iframe\n",
        "            width=\"100%\"\n",
        "            height=\"650\"\n",
-       "            src=\"https://dev.tetras-lab.io:443/jupyter/app_proxy/8059/jupyter/app_proxy/8059/\"\n",
+       "            src=\"https://dev.tetras-lab.io:443/jupyter/app_proxy/8051/jupyter/app_proxy/8051/\"\n",
        "            frameborder=\"0\"\n",
        "            allowfullscreen\n",
        "            \n",
@@ -211,7 +210,7 @@
        "        "
       ],
       "text/plain": [
-       "<IPython.lib.display.IFrame at 0x7f710a229850>"
+       "<IPython.lib.display.IFrame at 0x7f74c26b97c0>"
       ]
      },
      "metadata": {},
@@ -221,12 +220,13 @@
    "source": [
     "server_url, host, port, proxy, base_path = get_tl_config()\n",
     "\n",
-    "app = Dash(prevent_initial_callbacks=True, server_url=server_url, requests_pathname_prefix=base_path)\n",
+    "app = Dash(prevent_initial_callbacks=False, server_url=server_url, requests_pathname_prefix=base_path)\n",
     "\n",
     "mapComponent = dl.Map(children=\n",
     "                    [dl.TileLayer()],style={'width': '80%','height':'80vh','float': 'center','margin': 'auto'},\n",
     "                    center = [46.5,2.25],\n",
-    "                    zoom = 5)\n",
+    "                    zoom = 5,\n",
+    "                    id = 'first_map')\n",
     "\n",
     "app.layout = html.Div(children = mapComponent)\n",
     "\n",
@@ -240,22 +240,27 @@
    "source": [
     "Now that we have our map, let's see what we can do with it. \n",
     "\n",
-    "The ```children``` attribute of the map component allows us to add different kinds of layers to the map.\n",
-    "\n",
-    "Markers : \n",
+    "The ```children``` attribute of the map component allows us to add different kinds of layers to the map such as markers, polygons, and many others.\n",
     "\n",
     "```Python\n",
-    "marker = dl.Marker(position = [46.5,2.25])\n",
-    "``` \n",
+    "marker = dl.Marker(position = [46.5,2.25], id ='marker')\n",
     "\n",
-    "```Python\n",
-    "polygon = dl.Polygon(positions =[[43,2],[46,2],[46,4],[43,3]])\n",
-    "```"
+    "polygon = dl.Polygon(positions =[[43,2],[46,2],[46,4],[43,3]], id='polygon')\n",
+    "\n",
+    "mapComponent = dl.Map(children = \n",
+    "                          [dl.TileLayer(),marker,polygon],\n",
+    "                    style={'width': '80%','height':'80vh','float': 'center','margin': 'auto'},\n",
+    "                    center = [46.5,2.25],\n",
+    "                    zoom = 5,\n",
+    "                    id = 'first_map')\n",
+    "```\n",
+    "\n",
+    "We assign an id to each component because the callbacks which we will define in the next part will use them as inputs or outputs."
    ]
   },
   {
    "cell_type": "code",
-   "execution_count": 20,
+   "execution_count": 4,
    "id": "ad986a0f-ea66-42ee-8e7e-5482ee1ddc8f",
    "metadata": {},
    "outputs": [
@@ -266,7 +271,7 @@
        "        <iframe\n",
        "            width=\"100%\"\n",
        "            height=\"650\"\n",
-       "            src=\"https://dev.tetras-lab.io:443/jupyter/app_proxy/8063/jupyter/app_proxy/8063/\"\n",
+       "            src=\"https://dev.tetras-lab.io:443/jupyter/app_proxy/8054/jupyter/app_proxy/8054/\"\n",
        "            frameborder=\"0\"\n",
        "            allowfullscreen\n",
        "            \n",
@@ -274,7 +279,7 @@
        "        "
       ],
       "text/plain": [
-       "<IPython.lib.display.IFrame at 0x7f710a064e80>"
+       "<IPython.lib.display.IFrame at 0x7f74c0dcd070>"
       ]
      },
      "metadata": {},
@@ -284,7 +289,7 @@
    "source": [
     "server_url, host, port, proxy, base_path = get_tl_config()\n",
     "\n",
-    "app = Dash(prevent_initial_callbacks=True, server_url=server_url, requests_pathname_prefix=base_path)\n",
+    "app = Dash(prevent_initial_callbacks=False, server_url=server_url, requests_pathname_prefix=base_path)\n",
     "\n",
     "marker = dl.Marker(position = [46.5,2.25], id ='marker')\n",
     "polygon = dl.Polygon(positions =[[43,2],[46,2],[46,4],[43,3]], id='polygon')\n",
@@ -294,12 +299,222 @@
     "                          [dl.TileLayer(),marker,polygon],\n",
     "                    style={'width': '80%','height':'80vh','float': 'center','margin': 'auto'},\n",
     "                    center = [46.5,2.25],\n",
-    "                    zoom = 5)\n",
+    "                    zoom = 5,\n",
+    "                    id = 'first_map')\n",
     "\n",
     "app.layout = html.Div(children = mapComponent)\n",
     "\n",
     "app.run_server(mode='inline', host=host, port=port, proxy=proxy)"
    ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "e1937848-90cb-4021-8ff0-a0488e8131bc",
+   "metadata": {},
+   "source": [
+    "## Interactivity using callbacks\n",
+    "\n",
+    "A Dash callback is made of 2 parts : A function that will be called when a specified component is updated, and a function decorator which will define the inputs : the variables the app is gonna watch for updates, and the output : the component that's gonna be changed when the function is called. \n",
+    "\n",
+    "```Python\n",
+    "@app.callback(Output('result','children'),Input('marker','n_clicks'))\n",
+    "```\n",
+    "\n",
+    "This decorator means the app will be looking for any updates to the number of times the marker has been clicked, and that the result of the following function will be sent to the component with the 'result' id.\n",
+    "\n",
+    "```Python\n",
+    "def print_click(n):\n",
+    "    return str(n)\n",
+    "``` \n",
+    "\n",
+    "The print_click function will be called every time the app detects an update on the 'n_clicks' component of the marker.\n",
+    "\n",
+    "```Python \n",
+    "txt_output = html.Div(id='result')\n",
+    "app.layout = html.Div(children = (txt_output, mapComponent))\n",
+    "\n",
+    "@app.callback(Output('result','children'),Input('marker','n_clicks'))\n",
+    "def print_click(n):\n",
+    "    return ('Marker clicks : ' + str(n))\n",
+    "``` \n",
+    "\n",
+    "Callbacks are to be put after the app layout. "
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 5,
+   "id": "1d00d6d3-8c1f-4336-83ca-dcb40e408d2d",
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/html": [
+       "\n",
+       "        <iframe\n",
+       "            width=\"100%\"\n",
+       "            height=\"650\"\n",
+       "            src=\"https://dev.tetras-lab.io:443/jupyter/app_proxy/8056/jupyter/app_proxy/8056/\"\n",
+       "            frameborder=\"0\"\n",
+       "            allowfullscreen\n",
+       "            \n",
+       "        ></iframe>\n",
+       "        "
+      ],
+      "text/plain": [
+       "<IPython.lib.display.IFrame at 0x7f74c056b880>"
+      ]
+     },
+     "metadata": {},
+     "output_type": "display_data"
+    }
+   ],
+   "source": [
+    "server_url, host, port, proxy, base_path = get_tl_config()\n",
+    "\n",
+    "app = Dash(prevent_initial_callbacks=False, server_url=server_url, requests_pathname_prefix=base_path)\n",
+    "\n",
+    "marker = dl.Marker(position = [46.5,2.25], id ='marker')\n",
+    "txt_output = html.Div(id='result',style={'float': 'left','margin': 'auto','color':'red'})\n",
+    "\n",
+    "mapComponent = dl.Map(children = \n",
+    "                          [dl.TileLayer(),marker],\n",
+    "                    style={'width': '80%','height':'80vh','float': 'center','margin': 'auto'},\n",
+    "                    center = [46.5,2.25],\n",
+    "                    zoom = 5,\n",
+    "                    id = 'first_map')\n",
+    "\n",
+    "app.layout = html.Div(children = (txt_output,mapComponent ))\n",
+    "\n",
+    "@app.callback(Output('result','children'),Input('marker','n_clicks'))\n",
+    "def print_click(n):\n",
+    "    return ('Marker clicks : ' + str(n))\n",
+    "\n",
+    "app.run_server(mode='inline', host=host, port=port, proxy=proxy)"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "6bcdc84b-d5e4-4ff5-973c-c5070539275c",
+   "metadata": {},
+   "source": [
+    "A callback may have as many inputs and outputs as needed, the linked function will be called when any one of the inputs is updated.\n",
+    "\n",
+    "But two different callbacks can not have the same output, this is to prevent overlapping issues that could happen if the two callbacks are triggered at the same time.\n",
+    "\n",
+    "The function decorator may also have a third kind of argument : States. Just like inputs they are entry variables to the function, but updating them will not trigger the callback, their purpose is to give information on the state of the app.\n",
+    "\n",
+    "```Python\n",
+    "polygon = dl.Polygon(positions =[[40,0],[49,0],[46,7],[43,7]], id='polygon')\n",
+    "\n",
+    "colorselector = dcc.Dropdown(\n",
+    "                    id='color-dropdown',\n",
+    "                    options=[\n",
+    "                        {'label': 'Red', 'value': 'red'},\n",
+    "                        {'label': 'Green', 'value': 'green'},\n",
+    "                        {'label': 'Yellow', 'value': 'yellow'}\n",
+    "                    ],\n",
+    "                    value='red'\n",
+    "                            )\n",
+    "button = html.Button(id='input_button', children='Change color',style={'float':'left','width':'10%','height':'7vh'})\n",
+    "\n",
+    "mapComponent = dl.Map(children = \n",
+    "                          [dl.TileLayer(),polygon],\n",
+    "                    style={'width': '80%','height':'80vh','float': 'center','margin': 'auto'},\n",
+    "                    center = [46.5,2.25],\n",
+    "                    zoom = 5,\n",
+    "                    id = 'first_map')\n",
+    "\n",
+    "app.layout = html.Div(children = (colorselector,button, mapComponent ))\n",
+    "\n",
+    "@app.callback(Output('polygon','fillColor'),Input('input_button','n_clicks'),State('color-dropdown','value'))\n",
+    "def poly_color(click,color):\n",
+    "    if click is not None:\n",
+    "        return color\n",
+    "```\n",
+    "\n",
+    "Here we choose a color for the polygon with the selector, its values is a State, but the change only happens once the button is clicked because it is the input."
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 30,
+   "id": "d1bc382b-d86a-425b-96c9-53bbb0291267",
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/html": [
+       "\n",
+       "        <iframe\n",
+       "            width=\"100%\"\n",
+       "            height=\"650\"\n",
+       "            src=\"https://dev.tetras-lab.io:443/jupyter/app_proxy/8078/jupyter/app_proxy/8078/\"\n",
+       "            frameborder=\"0\"\n",
+       "            allowfullscreen\n",
+       "            \n",
+       "        ></iframe>\n",
+       "        "
+      ],
+      "text/plain": [
+       "<IPython.lib.display.IFrame at 0x7f74c026ff70>"
+      ]
+     },
+     "metadata": {},
+     "output_type": "display_data"
+    }
+   ],
+   "source": [
+    "server_url, host, port, proxy, base_path = get_tl_config()\n",
+    "\n",
+    "app = Dash(prevent_initial_callbacks=False, server_url=server_url, requests_pathname_prefix=base_path)\n",
+    "\n",
+    "polygon = dl.Polygon(positions =[[40,0],[49,0],[49,7],[40,7]], id='polygon')\n",
+    "\n",
+    "colorselector = dcc.Dropdown(\n",
+    "                    id='color-dropdown',\n",
+    "                    options=[\n",
+    "                        {'label': 'Red', 'value': 'red'},\n",
+    "                        {'label': 'Green', 'value': 'green'},\n",
+    "                        {'label': 'Yellow', 'value': 'yellow'}\n",
+    "                    ],\n",
+    "                    value='red'\n",
+    "                            )\n",
+    "button = html.Button(id='input_button', children='Change color',style={'float':'left','width':'10%','height':'7vh'})\n",
+    "\n",
+    "mapComponent = dl.Map(children = \n",
+    "                          [dl.TileLayer(),polygon],\n",
+    "                    style={'width': '80%','height':'80vh','float': 'center','margin': 'auto'},\n",
+    "                    center = [46.5,2.25],\n",
+    "                    zoom = 5,\n",
+    "                    id = 'first_map')\n",
+    "\n",
+    "app.layout = html.Div(children = (colorselector,button, mapComponent ))\n",
+    "\n",
+    "@app.callback(Output('polygon','fillColor'),Input('input_button','n_clicks'),State('color-dropdown','value'))\n",
+    "def poly_color(click,color):\n",
+    "    if click is not None:\n",
+    "        return color\n",
+    "\n",
+    "app.run_server(mode='inline', host=host, port=port, proxy=proxy)"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "5f7e56c9-e08f-47f1-907d-43dccad26996",
+   "metadata": {},
+   "source": [
+    "## GeoJSON rendering\n",
+    "\n"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "72ade10f-9d80-4507-8e54-15d667ae15a9",
+   "metadata": {},
+   "outputs": [],
+   "source": []
   }
  ],
  "metadata": {
diff --git a/dash/dash-leaflet.ipynb b/dash/dash-leaflet.ipynb
index 1c391419ba01e92051c4e7663bdb8d537f941c70..e5812d1fe87a45781e0efff4a102b6abc53dfb27 100644
--- a/dash/dash-leaflet.ipynb
+++ b/dash/dash-leaflet.ipynb
@@ -46,7 +46,6 @@
    "cell_type": "markdown",
    "id": "adaf50a1-4fb2-4ed6-bbb2-7b18d2758e6f",
    "metadata": {
-    "jp-MarkdownHeadingCollapsed": true,
     "tags": []
    },
    "source": [
@@ -78,7 +77,7 @@
     "The first part of a Dash application is the layout, first of all we have to initialize our app : \n",
     "\n",
     "```Python\n",
-    "app = Dash(prevent_initial_callbacks=True, server_url=server_url, requests_pathname_prefix=base_path)\n",
+    "app = Dash(prevent_initial_callbacks=False, server_url=server_url, requests_pathname_prefix=base_path)\n",
     "``` \n",
     "\n",
     "Then we can add the components we want to the app layout, each component works like a HTML element to which we can set a CSS style attribute to manage its size, color, font, etc...\n",
@@ -112,7 +111,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 6,
+   "execution_count": 2,
    "id": "ed671aec-502e-458d-87fb-8034a2b2e79e",
    "metadata": {},
    "outputs": [
@@ -123,7 +122,7 @@
        "        <iframe\n",
        "            width=\"100%\"\n",
        "            height=\"650\"\n",
-       "            src=\"https://dev.tetras-lab.io:443/jupyter/app_proxy/8054/jupyter/app_proxy/8054/\"\n",
+       "            src=\"https://dev.tetras-lab.io:443/jupyter/app_proxy/8050/jupyter/app_proxy/8050/\"\n",
        "            frameborder=\"0\"\n",
        "            allowfullscreen\n",
        "            \n",
@@ -131,7 +130,7 @@
        "        "
       ],
       "text/plain": [
-       "<IPython.lib.display.IFrame at 0x7f7109a2f460>"
+       "<IPython.lib.display.IFrame at 0x7f74c2709e80>"
       ]
      },
      "metadata": {},
@@ -150,7 +149,7 @@
     "import dash_bootstrap_components as dbc\n",
     "import plotly.express as px\n",
     "\n",
-    "app = Dash(prevent_initial_callbacks=True, server_url=server_url, requests_pathname_prefix=base_path)\n",
+    "app = Dash(prevent_initial_callbacks=False, server_url=server_url, requests_pathname_prefix=base_path)\n",
     "\n",
     "dropdown = dcc.Dropdown(\n",
     "        id='demo-dropdown',\n",
@@ -172,7 +171,7 @@
    "id": "0d6f8c87-d80e-4520-9415-2a7be591b6b1",
    "metadata": {},
    "source": [
-    "We will now use the Dash_Leaflet Library to display an interactive map, the component to use is ```dl.Map()``` , without adding anything else, the only thing that will be displayed is a grey square, we need to draw some map tiles. By adding ``` dl.TileLayer()``` as an argument, Dash Leaflet will add a basic map layer.\n",
+    "We will now use the Dash_Leaflet Library to display an interactive map, the component to use is ```dl.Map()``` , without adding anything else, the only thing that will be displayed is a grey square, we need to draw some map tiles. By adding ``` dl.TileLayer()``` as an argument, Dash Leaflet will add a default map layer based on OpenStreetMap.\n",
     "\n",
     "```Python\n",
     "mapComponent = dl.Map(children=\n",
@@ -192,7 +191,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 10,
+   "execution_count": 3,
    "id": "06e83bd3-ba85-48f4-b3e0-99014887e3d1",
    "metadata": {},
    "outputs": [
@@ -203,7 +202,7 @@
        "        <iframe\n",
        "            width=\"100%\"\n",
        "            height=\"650\"\n",
-       "            src=\"https://dev.tetras-lab.io:443/jupyter/app_proxy/8059/jupyter/app_proxy/8059/\"\n",
+       "            src=\"https://dev.tetras-lab.io:443/jupyter/app_proxy/8051/jupyter/app_proxy/8051/\"\n",
        "            frameborder=\"0\"\n",
        "            allowfullscreen\n",
        "            \n",
@@ -211,7 +210,7 @@
        "        "
       ],
       "text/plain": [
-       "<IPython.lib.display.IFrame at 0x7f710a229850>"
+       "<IPython.lib.display.IFrame at 0x7f74c26b97c0>"
       ]
      },
      "metadata": {},
@@ -221,12 +220,13 @@
    "source": [
     "server_url, host, port, proxy, base_path = get_tl_config()\n",
     "\n",
-    "app = Dash(prevent_initial_callbacks=True, server_url=server_url, requests_pathname_prefix=base_path)\n",
+    "app = Dash(prevent_initial_callbacks=False, server_url=server_url, requests_pathname_prefix=base_path)\n",
     "\n",
     "mapComponent = dl.Map(children=\n",
     "                    [dl.TileLayer()],style={'width': '80%','height':'80vh','float': 'center','margin': 'auto'},\n",
     "                    center = [46.5,2.25],\n",
-    "                    zoom = 5)\n",
+    "                    zoom = 5,\n",
+    "                    id = 'first_map')\n",
     "\n",
     "app.layout = html.Div(children = mapComponent)\n",
     "\n",
@@ -240,22 +240,27 @@
    "source": [
     "Now that we have our map, let's see what we can do with it. \n",
     "\n",
-    "The ```children``` attribute of the map component allows us to add different kinds of layers to the map.\n",
-    "\n",
-    "Markers : \n",
+    "The ```children``` attribute of the map component allows us to add different kinds of layers to the map such as markers, polygons, and many others.\n",
     "\n",
     "```Python\n",
-    "marker = dl.Marker(position = [46.5,2.25])\n",
-    "``` \n",
+    "marker = dl.Marker(position = [46.5,2.25], id ='marker')\n",
     "\n",
-    "```Python\n",
-    "polygon = dl.Polygon(positions =[[43,2],[46,2],[46,4],[43,3]])\n",
-    "```"
+    "polygon = dl.Polygon(positions =[[43,2],[46,2],[46,4],[43,3]], id='polygon')\n",
+    "\n",
+    "mapComponent = dl.Map(children = \n",
+    "                          [dl.TileLayer(),marker,polygon],\n",
+    "                    style={'width': '80%','height':'80vh','float': 'center','margin': 'auto'},\n",
+    "                    center = [46.5,2.25],\n",
+    "                    zoom = 5,\n",
+    "                    id = 'first_map')\n",
+    "```\n",
+    "\n",
+    "We assign an id to each component because the callbacks which we will define in the next part will use them as inputs or outputs."
    ]
   },
   {
    "cell_type": "code",
-   "execution_count": 20,
+   "execution_count": 4,
    "id": "ad986a0f-ea66-42ee-8e7e-5482ee1ddc8f",
    "metadata": {},
    "outputs": [
@@ -266,7 +271,7 @@
        "        <iframe\n",
        "            width=\"100%\"\n",
        "            height=\"650\"\n",
-       "            src=\"https://dev.tetras-lab.io:443/jupyter/app_proxy/8063/jupyter/app_proxy/8063/\"\n",
+       "            src=\"https://dev.tetras-lab.io:443/jupyter/app_proxy/8054/jupyter/app_proxy/8054/\"\n",
        "            frameborder=\"0\"\n",
        "            allowfullscreen\n",
        "            \n",
@@ -274,7 +279,7 @@
        "        "
       ],
       "text/plain": [
-       "<IPython.lib.display.IFrame at 0x7f710a064e80>"
+       "<IPython.lib.display.IFrame at 0x7f74c0dcd070>"
       ]
      },
      "metadata": {},
@@ -284,7 +289,7 @@
    "source": [
     "server_url, host, port, proxy, base_path = get_tl_config()\n",
     "\n",
-    "app = Dash(prevent_initial_callbacks=True, server_url=server_url, requests_pathname_prefix=base_path)\n",
+    "app = Dash(prevent_initial_callbacks=False, server_url=server_url, requests_pathname_prefix=base_path)\n",
     "\n",
     "marker = dl.Marker(position = [46.5,2.25], id ='marker')\n",
     "polygon = dl.Polygon(positions =[[43,2],[46,2],[46,4],[43,3]], id='polygon')\n",
@@ -294,12 +299,222 @@
     "                          [dl.TileLayer(),marker,polygon],\n",
     "                    style={'width': '80%','height':'80vh','float': 'center','margin': 'auto'},\n",
     "                    center = [46.5,2.25],\n",
-    "                    zoom = 5)\n",
+    "                    zoom = 5,\n",
+    "                    id = 'first_map')\n",
     "\n",
     "app.layout = html.Div(children = mapComponent)\n",
     "\n",
     "app.run_server(mode='inline', host=host, port=port, proxy=proxy)"
    ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "e1937848-90cb-4021-8ff0-a0488e8131bc",
+   "metadata": {},
+   "source": [
+    "## Interactivity using callbacks\n",
+    "\n",
+    "A Dash callback is made of 2 parts : A function that will be called when a specified component is updated, and a function decorator which will define the inputs : the variables the app is gonna watch for updates, and the output : the component that's gonna be changed when the function is called. \n",
+    "\n",
+    "```Python\n",
+    "@app.callback(Output('result','children'),Input('marker','n_clicks'))\n",
+    "```\n",
+    "\n",
+    "This decorator means the app will be looking for any updates to the number of times the marker has been clicked, and that the result of the following function will be sent to the component with the 'result' id.\n",
+    "\n",
+    "```Python\n",
+    "def print_click(n):\n",
+    "    return str(n)\n",
+    "``` \n",
+    "\n",
+    "The print_click function will be called every time the app detects an update on the 'n_clicks' component of the marker.\n",
+    "\n",
+    "```Python \n",
+    "txt_output = html.Div(id='result')\n",
+    "app.layout = html.Div(children = (txt_output, mapComponent))\n",
+    "\n",
+    "@app.callback(Output('result','children'),Input('marker','n_clicks'))\n",
+    "def print_click(n):\n",
+    "    return ('Marker clicks : ' + str(n))\n",
+    "``` \n",
+    "\n",
+    "Callbacks are to be put after the app layout. "
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 5,
+   "id": "1d00d6d3-8c1f-4336-83ca-dcb40e408d2d",
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/html": [
+       "\n",
+       "        <iframe\n",
+       "            width=\"100%\"\n",
+       "            height=\"650\"\n",
+       "            src=\"https://dev.tetras-lab.io:443/jupyter/app_proxy/8056/jupyter/app_proxy/8056/\"\n",
+       "            frameborder=\"0\"\n",
+       "            allowfullscreen\n",
+       "            \n",
+       "        ></iframe>\n",
+       "        "
+      ],
+      "text/plain": [
+       "<IPython.lib.display.IFrame at 0x7f74c056b880>"
+      ]
+     },
+     "metadata": {},
+     "output_type": "display_data"
+    }
+   ],
+   "source": [
+    "server_url, host, port, proxy, base_path = get_tl_config()\n",
+    "\n",
+    "app = Dash(prevent_initial_callbacks=False, server_url=server_url, requests_pathname_prefix=base_path)\n",
+    "\n",
+    "marker = dl.Marker(position = [46.5,2.25], id ='marker')\n",
+    "txt_output = html.Div(id='result',style={'float': 'left','margin': 'auto','color':'red'})\n",
+    "\n",
+    "mapComponent = dl.Map(children = \n",
+    "                          [dl.TileLayer(),marker],\n",
+    "                    style={'width': '80%','height':'80vh','float': 'center','margin': 'auto'},\n",
+    "                    center = [46.5,2.25],\n",
+    "                    zoom = 5,\n",
+    "                    id = 'first_map')\n",
+    "\n",
+    "app.layout = html.Div(children = (txt_output,mapComponent ))\n",
+    "\n",
+    "@app.callback(Output('result','children'),Input('marker','n_clicks'))\n",
+    "def print_click(n):\n",
+    "    return ('Marker clicks : ' + str(n))\n",
+    "\n",
+    "app.run_server(mode='inline', host=host, port=port, proxy=proxy)"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "6bcdc84b-d5e4-4ff5-973c-c5070539275c",
+   "metadata": {},
+   "source": [
+    "A callback may have as many inputs and outputs as needed, the linked function will be called when any one of the inputs is updated.\n",
+    "\n",
+    "But two different callbacks can not have the same output, this is to prevent overlapping issues that could happen if the two callbacks are triggered at the same time.\n",
+    "\n",
+    "The function decorator may also have a third kind of argument : States. Just like inputs they are entry variables to the function, but updating them will not trigger the callback, their purpose is to give information on the state of the app.\n",
+    "\n",
+    "```Python\n",
+    "polygon = dl.Polygon(positions =[[40,0],[49,0],[46,7],[43,7]], id='polygon')\n",
+    "\n",
+    "colorselector = dcc.Dropdown(\n",
+    "                    id='color-dropdown',\n",
+    "                    options=[\n",
+    "                        {'label': 'Red', 'value': 'red'},\n",
+    "                        {'label': 'Green', 'value': 'green'},\n",
+    "                        {'label': 'Yellow', 'value': 'yellow'}\n",
+    "                    ],\n",
+    "                    value='red'\n",
+    "                            )\n",
+    "button = html.Button(id='input_button', children='Change color',style={'float':'left','width':'10%','height':'7vh'})\n",
+    "\n",
+    "mapComponent = dl.Map(children = \n",
+    "                          [dl.TileLayer(),polygon],\n",
+    "                    style={'width': '80%','height':'80vh','float': 'center','margin': 'auto'},\n",
+    "                    center = [46.5,2.25],\n",
+    "                    zoom = 5,\n",
+    "                    id = 'first_map')\n",
+    "\n",
+    "app.layout = html.Div(children = (colorselector,button, mapComponent ))\n",
+    "\n",
+    "@app.callback(Output('polygon','fillColor'),Input('input_button','n_clicks'),State('color-dropdown','value'))\n",
+    "def poly_color(click,color):\n",
+    "    if click is not None:\n",
+    "        return color\n",
+    "```\n",
+    "\n",
+    "Here we choose a color for the polygon with the selector, its values is a State, but the change only happens once the button is clicked because it is the input."
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 30,
+   "id": "d1bc382b-d86a-425b-96c9-53bbb0291267",
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/html": [
+       "\n",
+       "        <iframe\n",
+       "            width=\"100%\"\n",
+       "            height=\"650\"\n",
+       "            src=\"https://dev.tetras-lab.io:443/jupyter/app_proxy/8078/jupyter/app_proxy/8078/\"\n",
+       "            frameborder=\"0\"\n",
+       "            allowfullscreen\n",
+       "            \n",
+       "        ></iframe>\n",
+       "        "
+      ],
+      "text/plain": [
+       "<IPython.lib.display.IFrame at 0x7f74c026ff70>"
+      ]
+     },
+     "metadata": {},
+     "output_type": "display_data"
+    }
+   ],
+   "source": [
+    "server_url, host, port, proxy, base_path = get_tl_config()\n",
+    "\n",
+    "app = Dash(prevent_initial_callbacks=False, server_url=server_url, requests_pathname_prefix=base_path)\n",
+    "\n",
+    "polygon = dl.Polygon(positions =[[40,0],[49,0],[49,7],[40,7]], id='polygon')\n",
+    "\n",
+    "colorselector = dcc.Dropdown(\n",
+    "                    id='color-dropdown',\n",
+    "                    options=[\n",
+    "                        {'label': 'Red', 'value': 'red'},\n",
+    "                        {'label': 'Green', 'value': 'green'},\n",
+    "                        {'label': 'Yellow', 'value': 'yellow'}\n",
+    "                    ],\n",
+    "                    value='red'\n",
+    "                            )\n",
+    "button = html.Button(id='input_button', children='Change color',style={'float':'left','width':'10%','height':'7vh'})\n",
+    "\n",
+    "mapComponent = dl.Map(children = \n",
+    "                          [dl.TileLayer(),polygon],\n",
+    "                    style={'width': '80%','height':'80vh','float': 'center','margin': 'auto'},\n",
+    "                    center = [46.5,2.25],\n",
+    "                    zoom = 5,\n",
+    "                    id = 'first_map')\n",
+    "\n",
+    "app.layout = html.Div(children = (colorselector,button, mapComponent ))\n",
+    "\n",
+    "@app.callback(Output('polygon','fillColor'),Input('input_button','n_clicks'),State('color-dropdown','value'))\n",
+    "def poly_color(click,color):\n",
+    "    if click is not None:\n",
+    "        return color\n",
+    "\n",
+    "app.run_server(mode='inline', host=host, port=port, proxy=proxy)"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "5f7e56c9-e08f-47f1-907d-43dccad26996",
+   "metadata": {},
+   "source": [
+    "## GeoJSON rendering\n",
+    "\n"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "72ade10f-9d80-4507-8e54-15d667ae15a9",
+   "metadata": {},
+   "outputs": [],
+   "source": []
   }
  ],
  "metadata": {