diff --git a/dash/.ipynb_checkpoints/dash-leaflet-checkpoint.ipynb b/dash/.ipynb_checkpoints/dash-leaflet-checkpoint.ipynb index b512141fab88443df6371f871b47fa3427600417..dc91bfe71f1c876f63ab174618fa7a1da6a37c8c 100644 --- a/dash/.ipynb_checkpoints/dash-leaflet-checkpoint.ipynb +++ b/dash/.ipynb_checkpoints/dash-leaflet-checkpoint.ipynb @@ -63,11 +63,10 @@ "cell_type": "markdown", "id": "adaf50a1-4fb2-4ed6-bbb2-7b18d2758e6f", "metadata": { - "jp-MarkdownHeadingCollapsed": true, "tags": [] }, "source": [ - "<h1><span style=\"color:green\"> Tetras-Lab for interactive geographical data visualisation</span></h1>\n", + "<h1><span style=\"color:green\"> Tetras-Lab for interactive geographical data visualisation using Dash Leaflet</span></h1>\n", "\n", "In this galery you will learn how to create dashboards using the open source data intelligence platform Tetras-Lab and easily visualize and share them as a web app.\n", "\n", @@ -77,6 +76,7 @@ "\n", "The following imports are gonna be required : \n", "\n", + "\n", "```Python\n", "from dash import html\n", "import dash_leaflet as dl\n", @@ -90,19 +90,23 @@ "import plotly.express as px\n", "``` \n", "\n", + "\n", "<h2><span style=\"color:green\"> Basic layout </span></h2>\n", "\n", "The first part of a Dash application is the layout, first of all we have to initialize our app : \n", "\n", + "\n", "```Python\n", - "server_url, host, port, proxy, base_path = get_tl_config()\n", + "server_url, host, port, proxy, base_path = get_tl_config() #This line is mandatory to run Dash apps in Tetras-Lab and has to be put in each cell\n", "app = Dash(prevent_initial_callbacks=False, server_url=server_url, requests_pathname_prefix=base_path)\n", "``` \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", "\n", "Exemple for a dropdown selector, first we declare the component : \n", "\n", + "\n", "```Python\n", "dropdown = dcc.Dropdown(\n", " id='demo-dropdown',\n", @@ -116,14 +120,18 @@ " )\n", "```\n", "\n", + "\n", "Then we add it to the layout \n", "\n", + "\n", "```Python\n", "app.layout = html.Div(dropdown)\n", "```\n", "\n", + "\n", "Finnaly ,to run the app we add : \n", "\n", + "\n", "```Python \n", "app.run_server(mode='inline', host=host, port=port, proxy=proxy)\n", "```" @@ -195,6 +203,7 @@ "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.\n", "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", + "\n", "```Python\n", "mapComponent = dl.Map(children=\n", " [dl.TileLayer()],\n", @@ -263,6 +272,7 @@ "\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", + "\n", "```Python\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", @@ -274,6 +284,7 @@ " id = 'first_map')\n", "```\n", "\n", + "\n", "We assign an id to each component because the callbacks which we will define in the next part will use them to refer to the components we want to use as inputs or outputs." ] }, @@ -335,21 +346,28 @@ "source": [ "<h2><span style=\"color:green\">Interactivity using callbacks </span></h2>\n", "\n", + "Once we have a map and know how to display elements on it, we would like to be able to click on a map component and have its information ( e.g the name of a country ) retrieved outside the map and usable in our program.\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", + "\n", "```Python\n", "@app.callback(Output('result','children'),Input('marker','n_clicks'))\n", "```\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", + "\n", "```Python\n", "def print_click(n):\n", " return ('Marker clicks : ' + str(n))\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", + "\n", "```Python \n", "txt_output = html.Div(id='result')\n", "app.layout = html.Div(children = (txt_output, mapComponent)) #Just like the map component, to have multiple components in our layout they have to be in a list in the children attribute.\n", @@ -361,7 +379,7 @@ }, { "cell_type": "code", - "execution_count": 10, + "execution_count": 88, "id": "1d00d6d3-8c1f-4336-83ca-dcb40e408d2d", "metadata": {}, "outputs": [ @@ -372,7 +390,7 @@ " <iframe\n", " width=\"100%\"\n", " height=\"650\"\n", - " src=\"https://dev.tetras-lab.io:443/jupyter/app_proxy/8106/jupyter/app_proxy/8106/\"\n", + " src=\"https://dev.tetras-lab.io:443/jupyter/app_proxy/8053/jupyter/app_proxy/8053/\"\n", " frameborder=\"0\"\n", " allowfullscreen\n", " \n", @@ -380,7 +398,7 @@ " " ], "text/plain": [ - "<IPython.lib.display.IFrame at 0x7f392476a730>" + "<IPython.lib.display.IFrame at 0x7f74b055cc40>" ] }, "metadata": {}, @@ -390,10 +408,10 @@ "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", + "app = Dash(prevent_initial_callbacks=True, 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':'green'})\n", + "txt_output = html.Div(id='result',children='Click the marker !', style={'float': 'left','margin': 'auto','color':'green'})\n", "\n", "mapComponent = dl.Map(children = \n", " [dl.TileLayer(),marker],\n", @@ -422,6 +440,7 @@ "\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 a State will not trigger the callback, their purpose is to give information on the state of the app.\n", "\n", + "\n", "```Python\n", "polygon = dl.Polygon(positions =[[40,0],[49,0],[46,7],[43,7]], id='polygon')\n", "colorselector = dcc.Dropdown(\n", @@ -445,6 +464,7 @@ "def poly_color(click,color):\n", " if click is not None:\n", " return color\n", + " \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." @@ -525,6 +545,7 @@ "\n", "Here with 2 different GeoJSON files : departements.geojson for France's departments and regions.geojson for France's regions we can create a toggle which will make the geojson layer display either the regions or the departements.\n", "\n", + "\n", "```Python\n", "geojson = dl.GeoJSON(url=base_path+'assets/regions.geojson', # url to geojson file\n", " zoomToBounds=True, # when true, zooms to bounds when data changes (e.g. on load)\n", @@ -550,9 +571,12 @@ "def switch_file(value):\n", " return (base_path+'assets/' + value + 's.geojson')\n", "```\n", + "\n", + "\n", "So the GeoJSON layer works as a callback output, but it can also work as an input. \n", "Each polygon drawn in the layer has different features such as the `click_feature` which updates when any of the polygon is clicked and allows us to get informations on it.\n", "\n", + "\n", "```Python\n", "txt_output = html.Div(id='result',style={'float': 'left','margin': 'auto','color':'red'})\n", "@app.callback(Output('result','children'),Input('geojson-layer','click_feature'),State('radio-buttons','value'))\n", diff --git a/dash/dash-leaflet.ipynb b/dash/dash-leaflet.ipynb index b512141fab88443df6371f871b47fa3427600417..dc91bfe71f1c876f63ab174618fa7a1da6a37c8c 100644 --- a/dash/dash-leaflet.ipynb +++ b/dash/dash-leaflet.ipynb @@ -63,11 +63,10 @@ "cell_type": "markdown", "id": "adaf50a1-4fb2-4ed6-bbb2-7b18d2758e6f", "metadata": { - "jp-MarkdownHeadingCollapsed": true, "tags": [] }, "source": [ - "<h1><span style=\"color:green\"> Tetras-Lab for interactive geographical data visualisation</span></h1>\n", + "<h1><span style=\"color:green\"> Tetras-Lab for interactive geographical data visualisation using Dash Leaflet</span></h1>\n", "\n", "In this galery you will learn how to create dashboards using the open source data intelligence platform Tetras-Lab and easily visualize and share them as a web app.\n", "\n", @@ -77,6 +76,7 @@ "\n", "The following imports are gonna be required : \n", "\n", + "\n", "```Python\n", "from dash import html\n", "import dash_leaflet as dl\n", @@ -90,19 +90,23 @@ "import plotly.express as px\n", "``` \n", "\n", + "\n", "<h2><span style=\"color:green\"> Basic layout </span></h2>\n", "\n", "The first part of a Dash application is the layout, first of all we have to initialize our app : \n", "\n", + "\n", "```Python\n", - "server_url, host, port, proxy, base_path = get_tl_config()\n", + "server_url, host, port, proxy, base_path = get_tl_config() #This line is mandatory to run Dash apps in Tetras-Lab and has to be put in each cell\n", "app = Dash(prevent_initial_callbacks=False, server_url=server_url, requests_pathname_prefix=base_path)\n", "``` \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", "\n", "Exemple for a dropdown selector, first we declare the component : \n", "\n", + "\n", "```Python\n", "dropdown = dcc.Dropdown(\n", " id='demo-dropdown',\n", @@ -116,14 +120,18 @@ " )\n", "```\n", "\n", + "\n", "Then we add it to the layout \n", "\n", + "\n", "```Python\n", "app.layout = html.Div(dropdown)\n", "```\n", "\n", + "\n", "Finnaly ,to run the app we add : \n", "\n", + "\n", "```Python \n", "app.run_server(mode='inline', host=host, port=port, proxy=proxy)\n", "```" @@ -195,6 +203,7 @@ "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.\n", "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", + "\n", "```Python\n", "mapComponent = dl.Map(children=\n", " [dl.TileLayer()],\n", @@ -263,6 +272,7 @@ "\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", + "\n", "```Python\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", @@ -274,6 +284,7 @@ " id = 'first_map')\n", "```\n", "\n", + "\n", "We assign an id to each component because the callbacks which we will define in the next part will use them to refer to the components we want to use as inputs or outputs." ] }, @@ -335,21 +346,28 @@ "source": [ "<h2><span style=\"color:green\">Interactivity using callbacks </span></h2>\n", "\n", + "Once we have a map and know how to display elements on it, we would like to be able to click on a map component and have its information ( e.g the name of a country ) retrieved outside the map and usable in our program.\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", + "\n", "```Python\n", "@app.callback(Output('result','children'),Input('marker','n_clicks'))\n", "```\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", + "\n", "```Python\n", "def print_click(n):\n", " return ('Marker clicks : ' + str(n))\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", + "\n", "```Python \n", "txt_output = html.Div(id='result')\n", "app.layout = html.Div(children = (txt_output, mapComponent)) #Just like the map component, to have multiple components in our layout they have to be in a list in the children attribute.\n", @@ -361,7 +379,7 @@ }, { "cell_type": "code", - "execution_count": 10, + "execution_count": 88, "id": "1d00d6d3-8c1f-4336-83ca-dcb40e408d2d", "metadata": {}, "outputs": [ @@ -372,7 +390,7 @@ " <iframe\n", " width=\"100%\"\n", " height=\"650\"\n", - " src=\"https://dev.tetras-lab.io:443/jupyter/app_proxy/8106/jupyter/app_proxy/8106/\"\n", + " src=\"https://dev.tetras-lab.io:443/jupyter/app_proxy/8053/jupyter/app_proxy/8053/\"\n", " frameborder=\"0\"\n", " allowfullscreen\n", " \n", @@ -380,7 +398,7 @@ " " ], "text/plain": [ - "<IPython.lib.display.IFrame at 0x7f392476a730>" + "<IPython.lib.display.IFrame at 0x7f74b055cc40>" ] }, "metadata": {}, @@ -390,10 +408,10 @@ "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", + "app = Dash(prevent_initial_callbacks=True, 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':'green'})\n", + "txt_output = html.Div(id='result',children='Click the marker !', style={'float': 'left','margin': 'auto','color':'green'})\n", "\n", "mapComponent = dl.Map(children = \n", " [dl.TileLayer(),marker],\n", @@ -422,6 +440,7 @@ "\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 a State will not trigger the callback, their purpose is to give information on the state of the app.\n", "\n", + "\n", "```Python\n", "polygon = dl.Polygon(positions =[[40,0],[49,0],[46,7],[43,7]], id='polygon')\n", "colorselector = dcc.Dropdown(\n", @@ -445,6 +464,7 @@ "def poly_color(click,color):\n", " if click is not None:\n", " return color\n", + " \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." @@ -525,6 +545,7 @@ "\n", "Here with 2 different GeoJSON files : departements.geojson for France's departments and regions.geojson for France's regions we can create a toggle which will make the geojson layer display either the regions or the departements.\n", "\n", + "\n", "```Python\n", "geojson = dl.GeoJSON(url=base_path+'assets/regions.geojson', # url to geojson file\n", " zoomToBounds=True, # when true, zooms to bounds when data changes (e.g. on load)\n", @@ -550,9 +571,12 @@ "def switch_file(value):\n", " return (base_path+'assets/' + value + 's.geojson')\n", "```\n", + "\n", + "\n", "So the GeoJSON layer works as a callback output, but it can also work as an input. \n", "Each polygon drawn in the layer has different features such as the `click_feature` which updates when any of the polygon is clicked and allows us to get informations on it.\n", "\n", + "\n", "```Python\n", "txt_output = html.Div(id='result',style={'float': 'left','margin': 'auto','color':'red'})\n", "@app.callback(Output('result','children'),Input('geojson-layer','click_feature'),State('radio-buttons','value'))\n",