Created
August 17, 2022 19:09
-
-
Save xhluca/32b6e126485b6f4c4ddaf7cc477a3930 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"cells": [ | |
{ | |
"cell_type": "markdown", | |
"metadata": { | |
"id": "R-S6u7gJ8em3" | |
}, | |
"source": [ | |
"# Setup app" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 1, | |
"metadata": { | |
"colab": { | |
"base_uri": "https://localhost:8080/" | |
}, | |
"id": "598h-F3U9Fn2", | |
"outputId": "683ac043-0b8a-40b8-9129-d253ebe971d2" | |
}, | |
"outputs": [ | |
{ | |
"output_type": "stream", | |
"name": "stdout", | |
"text": [ | |
"\u001b[K |████████████████████████████████| 9.9 MB 6.7 MB/s \n", | |
"\u001b[K |████████████████████████████████| 357 kB 49.8 MB/s \n", | |
"\u001b[K |████████████████████████████████| 1.6 MB 45.5 MB/s \n", | |
"\u001b[?25h Building wheel for retrying (setup.py) ... \u001b[?25l\u001b[?25hdone\n" | |
] | |
} | |
], | |
"source": [ | |
"!pip install -q jupyter-dash" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 2, | |
"metadata": { | |
"id": "5-jwKXiG9HlB" | |
}, | |
"outputs": [], | |
"source": [ | |
"from jupyter_dash import JupyterDash" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"source": [ | |
"import dash\n", | |
"from dash import dcc\n", | |
"from dash import html\n", | |
"import pandas as pd" | |
], | |
"metadata": { | |
"id": "DwyOpGpOBitn" | |
}, | |
"execution_count": 3, | |
"outputs": [] | |
}, | |
{ | |
"cell_type": "code", | |
"source": [ | |
"df = pd.read_csv('https://plotly.github.io/datasets/country_indicators.csv')\n", | |
"available_indicators = df['Indicator Name'].unique()" | |
], | |
"metadata": { | |
"id": "DwykzOM_Bnty" | |
}, | |
"execution_count": 4, | |
"outputs": [] | |
}, | |
{ | |
"cell_type": "code", | |
"source": [ | |
"external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css']\n", | |
"\n", | |
"app = JupyterDash(__name__, external_stylesheets=external_stylesheets)\n", | |
"\n", | |
"# Create server variable with Flask server object for use with gunicorn\n", | |
"server = app.server\n", | |
"\n", | |
"app.layout = html.Div([\n", | |
" html.Div([\n", | |
"\n", | |
" html.Div([\n", | |
" dcc.Dropdown(\n", | |
" id='crossfilter-xaxis-column',\n", | |
" options=[{'label': i, 'value': i} for i in available_indicators],\n", | |
" value='Fertility rate, total (births per woman)'\n", | |
" ),\n", | |
" dcc.RadioItems(\n", | |
" id='crossfilter-xaxis-type',\n", | |
" options=[{'label': i, 'value': i} for i in ['Linear', 'Log']],\n", | |
" value='Linear',\n", | |
" labelStyle={'display': 'inline-block'}\n", | |
" )\n", | |
" ],\n", | |
" style={'width': '49%', 'display': 'inline-block'}),\n", | |
"\n", | |
" html.Div([\n", | |
" dcc.Dropdown(\n", | |
" id='crossfilter-yaxis-column',\n", | |
" options=[{'label': i, 'value': i} for i in available_indicators],\n", | |
" value='Life expectancy at birth, total (years)'\n", | |
" ),\n", | |
" dcc.RadioItems(\n", | |
" id='crossfilter-yaxis-type',\n", | |
" options=[{'label': i, 'value': i} for i in ['Linear', 'Log']],\n", | |
" value='Linear',\n", | |
" labelStyle={'display': 'inline-block'}\n", | |
" )\n", | |
" ], style={'width': '49%', 'float': 'right', 'display': 'inline-block'})\n", | |
" ], style={\n", | |
" 'borderBottom': 'thin lightgrey solid',\n", | |
" 'backgroundColor': 'rgb(250, 250, 250)',\n", | |
" 'padding': '10px 5px'\n", | |
" }),\n", | |
"\n", | |
" html.Div([\n", | |
" dcc.Graph(\n", | |
" id='crossfilter-indicator-scatter',\n", | |
" hoverData={'points': [{'customdata': 'Japan'}]}\n", | |
" )\n", | |
" ], style={'width': '49%', 'display': 'inline-block', 'padding': '0 20'}),\n", | |
" html.Div([\n", | |
" dcc.Graph(id='x-time-series'),\n", | |
" dcc.Graph(id='y-time-series'),\n", | |
" ], style={'display': 'inline-block', 'width': '49%'}),\n", | |
"\n", | |
" html.Div(dcc.Slider(\n", | |
" id='crossfilter-year--slider',\n", | |
" min=df['Year'].min(),\n", | |
" max=df['Year'].max(),\n", | |
" value=df['Year'].max(),\n", | |
" marks={str(year): str(year) for year in df['Year'].unique()},\n", | |
" step=None\n", | |
" ), style={'width': '49%', 'padding': '0px 20px 20px 20px'})\n", | |
"])\n", | |
"\n", | |
"\n", | |
"@app.callback(\n", | |
" dash.dependencies.Output('crossfilter-indicator-scatter', 'figure'),\n", | |
" [dash.dependencies.Input('crossfilter-xaxis-column', 'value'),\n", | |
" dash.dependencies.Input('crossfilter-yaxis-column', 'value'),\n", | |
" dash.dependencies.Input('crossfilter-xaxis-type', 'value'),\n", | |
" dash.dependencies.Input('crossfilter-yaxis-type', 'value'),\n", | |
" dash.dependencies.Input('crossfilter-year--slider', 'value')])\n", | |
"def update_graph(xaxis_column_name, yaxis_column_name,\n", | |
" xaxis_type, yaxis_type,\n", | |
" year_value):\n", | |
" dff = df[df['Year'] == year_value]\n", | |
"\n", | |
" return {\n", | |
" 'data': [dict(\n", | |
" x=dff[dff['Indicator Name'] == xaxis_column_name]['Value'],\n", | |
" y=dff[dff['Indicator Name'] == yaxis_column_name]['Value'],\n", | |
" text=dff[dff['Indicator Name'] == yaxis_column_name]['Country Name'],\n", | |
" customdata=dff[dff['Indicator Name'] == yaxis_column_name]['Country Name'],\n", | |
" mode='markers',\n", | |
" marker={\n", | |
" 'size': 25,\n", | |
" 'opacity': 0.7,\n", | |
" 'color': 'orange',\n", | |
" 'line': {'width': 2, 'color': 'purple'}\n", | |
" }\n", | |
" )],\n", | |
" 'layout': dict(\n", | |
" xaxis={\n", | |
" 'title': xaxis_column_name,\n", | |
" 'type': 'linear' if xaxis_type == 'Linear' else 'log'\n", | |
" },\n", | |
" yaxis={\n", | |
" 'title': yaxis_column_name,\n", | |
" 'type': 'linear' if yaxis_type == 'Linear' else 'log'\n", | |
" },\n", | |
" margin={'l': 40, 'b': 30, 't': 10, 'r': 0},\n", | |
" height=450,\n", | |
" hovermode='closest'\n", | |
" )\n", | |
" }\n", | |
"\n", | |
"\n", | |
"def create_time_series(dff, axis_type, title):\n", | |
" return {\n", | |
" 'data': [dict(\n", | |
" x=dff['Year'],\n", | |
" y=dff['Value'],\n", | |
" mode='lines+markers'\n", | |
" )],\n", | |
" 'layout': {\n", | |
" 'height': 225,\n", | |
" 'margin': {'l': 20, 'b': 30, 'r': 10, 't': 10},\n", | |
" 'annotations': [{\n", | |
" 'x': 0, 'y': 0.85, 'xanchor': 'left', 'yanchor': 'bottom',\n", | |
" 'xref': 'paper', 'yref': 'paper', 'showarrow': False,\n", | |
" 'align': 'left', 'bgcolor': 'rgba(255, 255, 255, 0.5)',\n", | |
" 'text': title\n", | |
" }],\n", | |
" 'yaxis': {'type': 'linear' if axis_type == 'Linear' else 'log'},\n", | |
" 'xaxis': {'showgrid': False}\n", | |
" }\n", | |
" }\n", | |
"\n", | |
"\n", | |
"@app.callback(\n", | |
" dash.dependencies.Output('x-time-series', 'figure'),\n", | |
" [dash.dependencies.Input('crossfilter-indicator-scatter', 'hoverData'),\n", | |
" dash.dependencies.Input('crossfilter-xaxis-column', 'value'),\n", | |
" dash.dependencies.Input('crossfilter-xaxis-type', 'value')])\n", | |
"def update_y_timeseries(hoverData, xaxis_column_name, axis_type):\n", | |
" country_name = hoverData['points'][0]['customdata']\n", | |
" dff = df[df['Country Name'] == country_name]\n", | |
" dff = dff[dff['Indicator Name'] == xaxis_column_name]\n", | |
" title = '<b>{}</b><br>{}'.format(country_name, xaxis_column_name)\n", | |
" return create_time_series(dff, axis_type, title)\n", | |
"\n", | |
"\n", | |
"@app.callback(\n", | |
" dash.dependencies.Output('y-time-series', 'figure'),\n", | |
" [dash.dependencies.Input('crossfilter-indicator-scatter', 'hoverData'),\n", | |
" dash.dependencies.Input('crossfilter-yaxis-column', 'value'),\n", | |
" dash.dependencies.Input('crossfilter-yaxis-type', 'value')])\n", | |
"def update_x_timeseries(hoverData, yaxis_column_name, axis_type):\n", | |
" dff = df[df['Country Name'] == hoverData['points'][0]['customdata']]\n", | |
" dff = dff[dff['Indicator Name'] == yaxis_column_name]\n", | |
" return create_time_series(dff, axis_type, yaxis_column_name)" | |
], | |
"metadata": { | |
"id": "jRsFklzuBp6K" | |
}, | |
"execution_count": 5, | |
"outputs": [] | |
}, | |
{ | |
"cell_type": "code", | |
"source": [ | |
"app.run_server(port=8051)" | |
], | |
"metadata": { | |
"colab": { | |
"base_uri": "https://localhost:8080/", | |
"height": 52 | |
}, | |
"id": "AheccBwxBzuJ", | |
"outputId": "7e9dbe84-b1e9-4fdc-c147-20e93b69f71d" | |
}, | |
"execution_count": 6, | |
"outputs": [ | |
{ | |
"output_type": "stream", | |
"name": "stdout", | |
"text": [ | |
"Dash app running on:\n" | |
] | |
}, | |
{ | |
"output_type": "display_data", | |
"data": { | |
"text/plain": [ | |
"<IPython.core.display.Javascript object>" | |
], | |
"application/javascript": [ | |
"(async (port, path, text, element) => {\n", | |
" if (!google.colab.kernel.accessAllowed) {\n", | |
" return;\n", | |
" }\n", | |
" element.appendChild(document.createTextNode(''));\n", | |
" const url = await google.colab.kernel.proxyPort(port);\n", | |
" const anchor = document.createElement('a');\n", | |
" anchor.href = new URL(path, url).toString();\n", | |
" anchor.target = '_blank';\n", | |
" anchor.setAttribute('data-href', url + path);\n", | |
" anchor.textContent = text;\n", | |
" element.appendChild(anchor);\n", | |
" })(8051, \"/\", \"http://127.0.0.1:8051/\", window.element)" | |
] | |
}, | |
"metadata": {} | |
} | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"source": [ | |
"## Use cloudflare tunnel" | |
], | |
"metadata": { | |
"id": "YK0Us9YxKHMc" | |
} | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 7, | |
"metadata": { | |
"colab": { | |
"base_uri": "https://localhost:8080/" | |
}, | |
"id": "8CWgQoII9fJA", | |
"outputId": "739376ef-9221-4277-dea9-5b75ac478f6a" | |
}, | |
"outputs": [ | |
{ | |
"output_type": "stream", | |
"name": "stdout", | |
"text": [ | |
"Selecting previously unselected package cloudflared.\n", | |
"(Reading database ... 155676 files and directories currently installed.)\n", | |
"Preparing to unpack cloudflared-linux-amd64.deb ...\n", | |
"Unpacking cloudflared (2022.8.2) ...\n", | |
"Setting up cloudflared (2022.8.2) ...\n", | |
"Processing triggers for man-db (2.8.3-2ubuntu0.1) ...\n" | |
] | |
} | |
], | |
"source": [ | |
"!wget -q https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-amd64.deb && dpkg -i cloudflared-linux-amd64.deb" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"source": [ | |
"!cloudflared tunnel --url localhost:8051 --protocol http2" | |
], | |
"metadata": { | |
"colab": { | |
"base_uri": "https://localhost:8080/" | |
}, | |
"id": "QntdP0TSB6Id", | |
"outputId": "59aeac4a-c080-4eb9-8fee-ee51aba6da3f" | |
}, | |
"execution_count": null, | |
"outputs": [ | |
{ | |
"output_type": "stream", | |
"name": "stdout", | |
"text": [ | |
"\u001b[90m2022-08-17T18:53:30Z\u001b[0m \u001b[32mINF\u001b[0m Thank you for trying Cloudflare Tunnel. Doing so, without a Cloudflare account, is a quick way to experiment and try it out. However, be aware that these account-less Tunnels have no uptime guarantee. If you intend to use Tunnels in production you should use a pre-created named tunnel by following: https://developers.cloudflare.com/cloudflare-one/connections/connect-apps\n", | |
"\u001b[90m2022-08-17T18:53:30Z\u001b[0m \u001b[32mINF\u001b[0m Requesting new quick Tunnel on trycloudflare.com...\n", | |
"\u001b[90m2022-08-17T18:53:33Z\u001b[0m \u001b[32mINF\u001b[0m +--------------------------------------------------------------------------------------------+\n", | |
"\u001b[90m2022-08-17T18:53:33Z\u001b[0m \u001b[32mINF\u001b[0m | Your quick Tunnel has been created! Visit it at (it may take some time to be reachable): |\n", | |
"\u001b[90m2022-08-17T18:53:33Z\u001b[0m \u001b[32mINF\u001b[0m | https://diverse-zshops-designing-beads.trycloudflare.com |\n", | |
"\u001b[90m2022-08-17T18:53:33Z\u001b[0m \u001b[32mINF\u001b[0m +--------------------------------------------------------------------------------------------+\n", | |
"\u001b[90m2022-08-17T18:53:33Z\u001b[0m \u001b[32mINF\u001b[0m Cannot determine default configuration path. No file [config.yml config.yaml] in [~/.cloudflared ~/.cloudflare-warp ~/cloudflare-warp /etc/cloudflared /usr/local/etc/cloudflared]\n", | |
"\u001b[90m2022-08-17T18:53:33Z\u001b[0m \u001b[32mINF\u001b[0m Version 2022.8.2\n", | |
"\u001b[90m2022-08-17T18:53:33Z\u001b[0m \u001b[32mINF\u001b[0m GOOS: linux, GOVersion: go1.18.5, GoArch: amd64\n", | |
"\u001b[90m2022-08-17T18:53:33Z\u001b[0m \u001b[32mINF\u001b[0m Settings: map[p:http2 protocol:http2 url:localhost:8051]\n", | |
"\u001b[90m2022-08-17T18:53:33Z\u001b[0m \u001b[32mINF\u001b[0m Generated Connector ID: 74539447-91fb-4aee-947a-5398418c6cf6\n", | |
"\u001b[90m2022-08-17T18:53:33Z\u001b[0m \u001b[32mINF\u001b[0m cloudflared will not automatically update if installed by a package manager.\n", | |
"\u001b[90m2022-08-17T18:53:33Z\u001b[0m \u001b[32mINF\u001b[0m Initial protocol http2\n", | |
"\u001b[90m2022-08-17T18:53:33Z\u001b[0m \u001b[32mINF\u001b[0m Starting metrics server on 127.0.0.1:34683/metrics\n", | |
"\u001b[90m2022-08-17T18:53:33Z\u001b[0m \u001b[1m\u001b[31mERR\u001b[0m\u001b[0m Register tunnel error from server side \u001b[31merror=\u001b[0m\u001b[31m\"Unauthorized: Failed to get tunnel\"\u001b[0m \u001b[36mconnIndex=\u001b[0m0 \u001b[36mip=\u001b[0m198.41.200.113\n", | |
"\u001b[90m2022-08-17T18:53:33Z\u001b[0m \u001b[32mINF\u001b[0m Retrying connection in up to 2s seconds \u001b[36mconnIndex=\u001b[0m0 \u001b[36mip=\u001b[0m198.41.200.113\n", | |
"\u001b[90m2022-08-17T18:53:34Z\u001b[0m \u001b[1m\u001b[31mERR\u001b[0m\u001b[0m Register tunnel error from server side \u001b[31merror=\u001b[0m\u001b[31m\"Unauthorized: Failed to get tunnel\"\u001b[0m \u001b[36mconnIndex=\u001b[0m0 \u001b[36mip=\u001b[0m198.41.200.113\n", | |
"\u001b[90m2022-08-17T18:53:34Z\u001b[0m \u001b[32mINF\u001b[0m Retrying connection in up to 4s seconds \u001b[36mconnIndex=\u001b[0m0 \u001b[36mip=\u001b[0m198.41.200.113\n", | |
"\u001b[90m2022-08-17T18:53:34Z\u001b[0m \u001b[1m\u001b[31mERR\u001b[0m\u001b[0m Register tunnel error from server side \u001b[31merror=\u001b[0m\u001b[31m\"Unauthorized: Failed to get tunnel\"\u001b[0m \u001b[36mconnIndex=\u001b[0m0 \u001b[36mip=\u001b[0m198.41.200.113\n", | |
"\u001b[90m2022-08-17T18:53:34Z\u001b[0m \u001b[32mINF\u001b[0m Retrying connection in up to 8s seconds \u001b[36mconnIndex=\u001b[0m0 \u001b[36mip=\u001b[0m198.41.200.113\n", | |
"\u001b[90m2022-08-17T18:53:37Z\u001b[0m \u001b[1m\u001b[31mERR\u001b[0m\u001b[0m Register tunnel error from server side \u001b[31merror=\u001b[0m\u001b[31m\"Unauthorized: Failed to get tunnel\"\u001b[0m \u001b[36mconnIndex=\u001b[0m0 \u001b[36mip=\u001b[0m198.41.200.113\n", | |
"\u001b[90m2022-08-17T18:53:37Z\u001b[0m \u001b[32mINF\u001b[0m Retrying connection in up to 16s seconds \u001b[36mconnIndex=\u001b[0m0 \u001b[36mip=\u001b[0m198.41.200.113\n", | |
"\u001b[90m2022-08-17T18:53:52Z\u001b[0m \u001b[32mINF\u001b[0m Connection fff28f06-8b7d-4cd4-97d6-5786b32c93cd registered \u001b[36mconnIndex=\u001b[0m0 \u001b[36mip=\u001b[0m198.41.200.113 \u001b[36mlocation=\u001b[0mATL\n", | |
"\u001b[90m2022-08-17T18:53:53Z\u001b[0m \u001b[32mINF\u001b[0m Connection f1b6ecf8-4241-4aa7-8095-758c9bed1067 registered \u001b[36mconnIndex=\u001b[0m1 \u001b[36mip=\u001b[0m198.41.192.7 \u001b[36mlocation=\u001b[0mATL\n", | |
"\u001b[90m2022-08-17T18:53:53Z\u001b[0m \u001b[32mINF\u001b[0m Connection 91672451-3620-4f26-b0d3-f6506d0571e5 registered \u001b[36mconnIndex=\u001b[0m2 \u001b[36mip=\u001b[0m198.41.200.53 \u001b[36mlocation=\u001b[0mATL\n", | |
"\u001b[90m2022-08-17T18:53:54Z\u001b[0m \u001b[32mINF\u001b[0m Connection 289ed333-a198-434f-ae0d-c88a71186e50 registered \u001b[36mconnIndex=\u001b[0m3 \u001b[36mip=\u001b[0m198.41.192.37 \u001b[36mlocation=\u001b[0mATL\n" | |
] | |
} | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"source": [ | |
"You can also set the tunnel to go to a subdomain that you own through Cloudflare. To do this, follow this guide: https://developers.cloudflare.com/cloudflare-one/connections/connect-apps/install-and-setup/tunnel-guide/remote/" | |
], | |
"metadata": { | |
"id": "9O6FXZemKMgH" | |
} | |
}, | |
{ | |
"cell_type": "code", | |
"source": [ | |
"" | |
], | |
"metadata": { | |
"id": "uiTT7eaZKS-H" | |
}, | |
"execution_count": null, | |
"outputs": [] | |
} | |
], | |
"metadata": { | |
"colab": { | |
"name": "Dash Cloudflared experiments.ipynb", | |
"provenance": [], | |
"collapsed_sections": [] | |
}, | |
"kernelspec": { | |
"display_name": "Python 3", | |
"name": "python3" | |
}, | |
"language_info": { | |
"name": "python" | |
} | |
}, | |
"nbformat": 4, | |
"nbformat_minor": 0 | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment