From bce9f35de731c3426f1f69a3cb2c205205924b2e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zoufin=C3=A9=20Lauer-Bar=C3=A9?= <82505312+zolabar@users.noreply.github.com> Date: Fri, 15 Jul 2022 08:15:11 +0200 Subject: [PATCH] oop --- trendpy_webapp.ipynb | 389 +++---------------------------------------- 1 file changed, 20 insertions(+), 369 deletions(-) diff --git a/trendpy_webapp.ipynb b/trendpy_webapp.ipynb index f324a82..4822d7d 100644 --- a/trendpy_webapp.ipynb +++ b/trendpy_webapp.ipynb @@ -6,19 +6,7 @@ "metadata": {}, "outputs": [], "source": [ - "import pandas as pd\n", - "import ipywidgets as widgets\n", - "from ipywidgets import interact, interactive\n", - "import plotly as plt\n", - "import plotly.express as px\n", - "import plotly.graph_objects as go\n", - "import io\n", - "from IPython.display import display, clear_output\n", - "from traitlets import traitlets\n", - "import TrendPy.methods as tm\n", - "import numpy as np\n", - "import warnings\n", - "warnings.filterwarnings('ignore')" + "from TrendPy.webApp import App" ] }, { @@ -29,7 +17,7 @@ { "data": { "application/vnd.jupyter.widget-view+json": { - "model_id": "8525cd5e7c8447b8ae2009cbd91f6798", + "model_id": "feceaae87b61499a97d7841b1dfa09f7", "version_major": 2, "version_minor": 0 }, @@ -39,31 +27,11 @@ }, "metadata": {}, "output_type": "display_data" - } - ], - "source": [ - "box_layout = widgets.Layout(display='flex',\n", - " justify_content='center')\n", - "header = widgets.HTML(\n", - " value='

TrendPy Webapp

\\\n", - "

Visualization of trends in (time series) data

')\n", - "\n", - "logo = widgets.HTML(\n", - " value='\"TrendPy')\n", - "\n", - "logo_container = widgets.HBox([logo, header],layout=box_layout)\n", - "display(logo_container)\n" - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "metadata": {}, - "outputs": [ + }, { "data": { "application/vnd.jupyter.widget-view+json": { - "model_id": "145f26514368407b9eb33fc1f72529fa", + "model_id": "23e159e1c1c5405e95594d3b66a9e37a", "version_major": 2, "version_minor": 0 }, @@ -73,23 +41,11 @@ }, "metadata": {}, "output_type": "display_data" - } - ], - "source": [ - "header2 = widgets.HTML(\n", - " value='

Upload a .csv file here

')\n", - "header2" - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "metadata": {}, - "outputs": [ + }, { "data": { "application/vnd.jupyter.widget-view+json": { - "model_id": "cf0f3310cd134ed080d82f02d0759e22", + "model_id": "2992614500c248299a2d6ffb8c4e97d6", "version_major": 2, "version_minor": 0 }, @@ -99,80 +55,11 @@ }, "metadata": {}, "output_type": "display_data" - } - ], - "source": [ - "uploaded_excel_file = widgets.FileUpload(accept=\".csv\", multiple=False)\n", - "container = widgets.HBox([uploaded_excel_file],layout=box_layout)\n", - "\n", - "display(container)" - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "metadata": {}, - "outputs": [], - "source": [ - "#create pandas dataframe\n", - "out = widgets.Output()\n", - "def create_pandas_dataframe(b):\n", - " \n", - " # resetting everything for a new calculation\n", - " with out:\n", - " clear_output()\n", - " with out2:\n", - " clear_output()\n", - " input_dropdown.options = []\n", - " output_dropdown.options = []\n", - " fig_widget.update_traces(x=[],y=[],selector=({'name':'datapoints'}))\n", - " fig_widget.update_traces(x=[],y=[],selector=({'name':'trendline'}))\n", - " trend_dropdown.value='No trendline'\n", - " polynomial_deg_selection.disabled=True\n", - " r2_checkbox.value=False\n", - " r2_checkbox.disabled=True\n", - " \n", - " #checking whether data has been uploaded succesfully\n", - " if (uploaded_excel_file.value=={}):\n", - " button.button_style='warning'\n", - " with out:\n", - " print(\"No data entered. Please upload a .csv file.\")\n", - " \n", - " else:\n", - " try:\n", - " \n", - " \n", - " button.button_style='success'\n", - " \n", - " #transforming the uploaded .csv file back to the type .csv in order to then create a pandas dataframe\n", - " time_series_file = list(uploaded_excel_file.value.values())[0]\n", - " content=time_series_file['content']\n", - " content=io.StringIO(content.decode('utf-8'))\n", - " time_series_data = pd.read_csv(content)\n", - " \n", - " #filling the drop down menus with the columns of the dataframe as options\n", - " input_dropdown.options = time_series_data.select_dtypes(include='number').columns\n", - " output_dropdown.options = time_series_data.select_dtypes(include='number').columns\n", - " b.value = time_series_data\n", - " \n", - " with out: \n", - " print(\"Data entered. Please select the X and Y values now. (Only works if header is in the first row of your file.)\")\n", - " except:\n", - " button.button_style='warning'\n", - " with out:\n", - " print('Invalid input! Make sure that header of the file is in first row and general format is correct!')\n", - " " - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "metadata": {}, - "outputs": [ + }, { "data": { "application/vnd.jupyter.widget-view+json": { - "model_id": "5c1b9c20023840c3ae287b1813187747", + "model_id": "f6271d98c44849ea94334f0e917f29ed", "version_major": 2, "version_minor": 0 }, @@ -186,7 +73,7 @@ { "data": { "application/vnd.jupyter.widget-view+json": { - "model_id": "367b0f80407843629a17fb95776a728d", + "model_id": "121ff83ad17e4875a2732a015e92b459", "version_major": 2, "version_minor": 0 }, @@ -196,97 +83,11 @@ }, "metadata": {}, "output_type": "display_data" - } - ], - "source": [ - "#using a loaded button in order to make the pandas dataframe of the function above available outside of the function\n", - "class LoadedButton(widgets.Button):\n", - "\n", - " def __init__(self, value=None, *args, **kwargs):\n", - " super(LoadedButton, self).__init__(*args, **kwargs)\n", - " self.add_traits(value=traitlets.Any(value))\n", - "\n", - "button = LoadedButton(description='Start calculation', disable=False, tooltip='Click to start calculation', icon='check', button_style='')\n", - "button.on_click(create_pandas_dataframe)\n", - "\n", - "\n", - "container2 = widgets.HBox([button],layout=box_layout)\n", - "container_out = widgets.HBox([out],layout=box_layout)\n", - "display(container2,container_out)\n" - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "metadata": {}, - "outputs": [ - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "9d84c14b89424d7a8ea2f55fe6647dfb", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "HTML(value='

Elements down below are interactive, button above only ha…" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "header4 = widgets.HTML(\n", - " value='

Elements down below are interactive, button above only has to be pressed\\\n", - " if a new excel-file has been uploaded

')\n", - "header4" - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "metadata": {}, - "outputs": [], - "source": [ - "# creates the graphics based on the input parameters defined in the interactive widgets below\n", - "def create_graphics(values_in,values_out,trend,deg=2,r2=False):\n", - " if trend == 'polynomial':\n", - " polynomial_deg_selection.disabled=False\n", - " else:\n", - " polynomial_deg_selection.disabled=True\n", - " \n", - " if values_in == '' or values_out=='':\n", - " print(\"Please select your X and Y values in the dropdown menus above.\")\n", - " else:\n", - " try: # sometimes an error is occuring when user hasn't changed the standard dropdown X and Y values yet\n", - " # through try/except the user does not see the error and won't notice it, because standard values are\n", - " # usually not going to be used\n", - " \n", - " # updateing the plot based on the input data\n", - " fig_widget.layout.xaxis.title = values_in\n", - " fig_widget.layout.yaxis.title = values_out\n", - " fig_widget.update_traces(x=button.value[values_in], y=button.value[values_out], selector=({'name':'datapoints'}))\n", - " if trend!=\"No trendline\":\n", - " with out2:\n", - " clear_output()\n", - " r2_checkbox.disabled=False\n", - " calculate_trendline(values_in, values_out, trend, deg, r2) # function that calculates and draws trendline is called\n", - " else:\n", - " fig_widget.update_traces(x=[],y=[],selector=({'name':'trendline'}))\n", - " r2_checkbox.disabled=True\n", - " except:\n", - " pass\n" - ] - }, - { - "cell_type": "code", - "execution_count": 9, - "metadata": {}, - "outputs": [ + }, { "data": { "application/vnd.jupyter.widget-view+json": { - "model_id": "c956a50b07c14a3ab6db36b1d95cf40b", + "model_id": "eb0172a96c864a0b880d3d8d29f7482c", "version_major": 2, "version_minor": 0 }, @@ -300,7 +101,7 @@ { "data": { "application/vnd.jupyter.widget-view+json": { - "model_id": "e2741480625f49c3bbfd0a777ec09a03", + "model_id": "155f46c9feea4069812c2101984312d8", "version_major": 2, "version_minor": 0 }, @@ -314,7 +115,7 @@ { "data": { "application/vnd.jupyter.widget-view+json": { - "model_id": "489278d2911448df87fc685ea5006fc7", + "model_id": "643d857692b14bca8f6cbbe1b4c5f6f5", "version_major": 2, "version_minor": 0 }, @@ -328,7 +129,7 @@ { "data": { "application/vnd.jupyter.widget-view+json": { - "model_id": "aa7a7b445bcb40d0ae15bd06525f6724", + "model_id": "bdb94e9a33aa413b824651ff0b04cb7f", "version_major": 2, "version_minor": 0 }, @@ -338,76 +139,17 @@ }, "metadata": {}, "output_type": "display_data" - } - ], - "source": [ - "# defining the interactive dropdown options\n", - "input_dropdown = widgets.Dropdown(\n", - " options=[''],\n", - " value='',\n", - " description='Input (X):',\n", - " disabled=False,\n", - " )\n", - "\n", - "output_dropdown = widgets.Dropdown(\n", - " options=[''],\n", - " value='',\n", - " description='Target (Y):',\n", - " disabled=False,\n", - " )\n", - "\n", - "trend_dropdown = widgets.Dropdown(\n", - " options=['No trendline','linear','polynomial','trigonometric','exponential'],\n", - " value='No trendline',\n", - " description='trendline:',\n", - " disabled=False,\n", - " )\n", - "\n", - "polynomial_deg_selection = widgets.Dropdown(\n", - " options=[2,3,4,5,6],\n", - " value=2,\n", - " description='deg (polyn.)',\n", - " disabled=True,\n", - " )\n", - "\n", - "r2_checkbox = widgets.Checkbox(\n", - " value=False,\n", - " description='Show R2 score',\n", - " disabled=False,\n", - " indent=True\n", - ")\n", - "\n", - "# arrangement of dropdown menus\n", - "dropdown_elements = widgets.HBox([input_dropdown, output_dropdown], layout=box_layout)\n", - "trend_selection = widgets.HBox([trend_dropdown, polynomial_deg_selection], layout=box_layout)\n", - "r2_container = widgets.HBox([r2_checkbox],layout=box_layout)\n", - "\n", - "\n", - "# making all the widgets interactive, so no button needs to be pressed when changing a dropdown value \n", - "out2 = widgets.interactive_output(create_graphics, {'values_in': input_dropdown, 'values_out': output_dropdown, \\\n", - " 'trend':trend_dropdown, 'deg':polynomial_deg_selection, \\\n", - " 'r2':r2_checkbox})\n", - "\n", - "out2_container = widgets.HBox([out2],layout=box_layout)\n", - "\n", - "display(dropdown_elements, trend_selection, r2_container, out2_container)\n" - ] - }, - { - "cell_type": "code", - "execution_count": 22, - "metadata": {}, - "outputs": [ + }, { "data": { "application/vnd.jupyter.widget-view+json": { - "model_id": "f902023156a347a1969588cc8e397ba0", + "model_id": "5ae4f5229e154e30b7657cf35e2aaead", "version_major": 2, "version_minor": 0 }, "text/plain": [ "FigureWidget({\n", - " 'data': [{'mode': 'markers', 'name': 'datapoints', 'type': 'scatter', 'uid': '05554fd6-971a…" + " 'data': [{'mode': 'markers', 'name': 'datapoints', 'type': 'scatter', 'uid': '7dad9081-b371…" ] }, "metadata": {}, @@ -415,79 +157,9 @@ } ], "source": [ - "# defining a figure widget, that is created in the beginning and remains static, only graphs are updated\n", - "# it is needed to define all needed graphs as empty ones here, so that you can use update_traces\n", - "fig_widget = go.FigureWidget()\n", - "fig_widget.layout.margin=dict(l=120, r=120, b=25, t=25)\n", - "fig_widget.layout.height=400\n", - "fig_widget.add_scatter(mode='markers', name='datapoints')\n", - "fig_widget.add_scatter(mode='lines', name='trendline', line=dict(shape='spline'))\n", - "fig_widget.update_layout(title_text=\"Time Series Regression\", template='ggplot2')\n", - "fig_widget" - ] - }, - { - "cell_type": "code", - "execution_count": 11, - "metadata": {}, - "outputs": [], - "source": [ - "# calculating and drawing the trendline based on selected options\n", - "def calculate_trendline(values_in, values_out, trend, deg, r2):\n", - " sorted_df = button.value.sort_values(by=values_in) # without sorting trendlines can not be plotted correctly\n", - " x_values=sorted_df[values_in].to_numpy()\n", - " y_values=sorted_df[values_out].to_numpy()\n", - " \n", - " # in all cases coefficients are calculated first by calling function from methods.py\n", - " # after that the predicted y-values are calculated by calling function from methods.py\n", - " # with the data from y_pred-function it is then possible to plot the trendline\n", - " # at last r2-score is calculated\n", - " if trend=='linear':\n", - " coefs=tm.linReg(x_values,y_values)\n", - " print('coefficients: ', coefs)\n", - " y_pred=tm.pred('linReg',coefs, x_values)\n", - " fig_widget.update_traces(x=sorted_df[values_in], y=y_pred, selector=({'name':'trendline'}))\n", - " fig_widget.update_layout(title_text=r\"$f(x)=c_0\\cdot x+c_1$\")\n", - " if r2==True:\n", - " r2_score = tm.r2(y_values, y_pred)\n", - " print('R2-score: ', r2_score)\n", - " \n", - " elif trend=='polynomial':\n", - " try:\n", - " coefs = tm.polReg(x_values,y_values,deg)\n", - " print('coefficients: ', coefs)\n", - " y_pred = tm.pred('polReg', coefs, x_values)\n", - " fig_widget.update_traces(x=sorted_df[values_in], y=y_pred, selector=({'name':'trendline'}), line=dict(shape='spline'))\n", - " fig_widget.update_layout(title_text=r\"$f(x)=c_0\\cdot x^N+c_1 x^{N-1}+...+c_N$\")\n", - " if r2==True:\n", - " r2_score = tm.r2(y_values, y_pred)\n", - " print('R2-score: ', r2_score)\n", - " except:\n", - " print('Selected regression might not be a good fit for the entered values! Please lower degree or choose other regression!')\n", - " elif trend=='trigonometric':\n", - " try:\n", - " coefs = tm.trigReg(x_values,y_values)\n", - " print('coefficients: ', coefs)\n", - " y_pred = tm.pred('trigReg', coefs, x_values)\n", - " fig_widget.update_traces(x=sorted_df[values_in], y=y_pred, selector=({'name':'trendline'}))\n", - " fig_widget.update_layout(title_text=r\"$f(x)=c_0\\cdot \\text(\\cos(2\\pi\\cdot c_1+c_2))$\")\n", - " if r2==True:\n", - " r2_score = tm.r2(y_values, y_pred)\n", - " print('R2-score: ', r2_score)\n", - " except:\n", - " print('Selected regression might not be a good fit for the entered values! Please choose other regression!')\n", - " elif trend=='exponential':\n", - " try:\n", - " coefs = tm.expReg(x_values,y_values)\n", - " print('coefficients: ', coefs)\n", - " y_pred = tm.pred('expReg', coefs, x_values)\n", - " fig_widget.update_traces(x=sorted_df[values_in], y=y_pred, selector=({'name':'trendline'}))\n", - " fig_widget.update_layout(title_text=r\"$f(x)=c_0\\cdot e^{c_1\\cdot x}$\")\n", - " if r2==True:\n", - " r2_score = tm.r2(y_values, y_pred)\n", - " print('R2-score: ', r2_score)\n", - " except:\n", - " print('Selected regression might not be a good fit for the entered values! Please choose other regression!')" + "a = App()\n", + "\n", + "a.show()\n" ] }, { @@ -497,27 +169,6 @@ "outputs": [], "source": [] }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - }, { "cell_type": "code", "execution_count": null,