{ "cells": [ { "cell_type": "markdown", "id": "4712c176", "metadata": {}, "source": [ "# Imports" ] }, { "cell_type": "markdown", "id": "52d46fef", "metadata": {}, "source": [ "## Useful packages" ] }, { "cell_type": "code", "execution_count": null, "id": "56355a52", "metadata": {}, "outputs": [], "source": [ "import numpy as np\n", "from functools import partial\n", "import pandas as pd\n", "import netCDF4\n", "from scipy.interpolate import interp1d" ] }, { "cell_type": "markdown", "id": "64c9441f", "metadata": {}, "source": [ "## plotting" ] }, { "cell_type": "code", "execution_count": null, "id": "1d1d65e1", "metadata": {}, "outputs": [], "source": [ "import holoviews as hv\n", "from holoviews import opts\n", "from holoviews.streams import Stream, param\n", "from holoviews.plotting.links import RangeToolLink\n", "import panel as pn\n", "from bokeh.models.formatters import PrintfTickFormatter\n", "from bokeh.models.renderers import GlyphRenderer\n", "from bokeh.models import Range1d, LinearAxis\n", "from bokeh.models import HoverTool" ] }, { "cell_type": "markdown", "id": "f9541e25", "metadata": {}, "source": [ "## Define css objects used in layout template" ] }, { "cell_type": "code", "execution_count": null, "id": "517fa202", "metadata": {}, "outputs": [], "source": [ "css = '''\n", "app {\n", " display: flex;\n", " flex-direction: column;\n", " height: 97vh;\n", "}\n", "\n", "menu_and_figures {\n", " flex: 1;\n", "}\n", "'''" ] }, { "cell_type": "markdown", "id": "265e6cbe", "metadata": {}, "source": [ "## set panel and holoviews extension" ] }, { "cell_type": "code", "execution_count": null, "id": "fe815e88", "metadata": {}, "outputs": [], "source": [ "pn.extension('katex', raw_css=[css], loading_color='#000000')\n", "hv.extension('bokeh', width=100)" ] }, { "cell_type": "markdown", "id": "0e6f1d76", "metadata": {}, "source": [ "## OGGM" ] }, { "cell_type": "code", "execution_count": null, "id": "4deefb86", "metadata": {}, "outputs": [], "source": [ "from oggm.core.massbalance import MassBalanceModel, PastMassBalance, ConstantMassBalance\n", "from oggm.utils import ncDataset, date_to_floatyear, floatyear_to_date\n", "from oggm import cfg\n", "from oggm.cfg import SEC_IN_YEAR, SEC_IN_MONTH\n", "\n", "cfg.initialize_minimal()" ] }, { "cell_type": "markdown", "id": "5a6d8d68", "metadata": {}, "source": [ "## Other Stuff" ] }, { "cell_type": "code", "execution_count": null, "id": "cc2d16a5", "metadata": {}, "outputs": [], "source": [ "from app_template import template\n", "from version import __version__" ] }, { "cell_type": "markdown", "id": "718a434f-c833-44d6-b283-e0573248397b", "metadata": {}, "source": [ "## Analytics" ] }, { "cell_type": "code", "execution_count": null, "id": "f7641b2b-6f80-46e7-a95a-43c70df4cd9c", "metadata": {}, "outputs": [], "source": [ "analytics = pn.pane.HTML('')" ] }, { "cell_type": "markdown", "id": "af113f5f", "metadata": {}, "source": [ "# define some settings" ] }, { "cell_type": "code", "execution_count": null, "id": "1b09aaa9", "metadata": {}, "outputs": [], "source": [ "cfg.PARAMS['use_bias_for_run'] = False\n", "\n", "climate_data_dir = 'climate_data/'" ] }, { "cell_type": "markdown", "id": "cf82a780", "metadata": {}, "source": [ "# Define some default values" ] }, { "cell_type": "code", "execution_count": null, "id": "ac7cb54d", "metadata": {}, "outputs": [], "source": [ "# set default language\n", "language = 'en'\n", "\n", "# help variable for setting a new base climate (needed for different languages)\n", "climate_meta_data = ['_HEF', 1300, 4600]\n", "\n", "# variable to keep track which figures are already updated (for each tab)\n", "tab_figures_updated = [True, True, True]\n", "climographs_updated = [True, True, True]\n", "active_tab = 0" ] }, { "cell_type": "markdown", "id": "6b780c2b", "metadata": {}, "source": [ "# Define Language Selector" ] }, { "cell_type": "markdown", "id": "caec48c4", "metadata": {}, "source": [ "Help functions to set new language" ] }, { "cell_type": "code", "execution_count": null, "id": "4864e777", "metadata": {}, "outputs": [], "source": [ "def language_selector_function(arg=None):\n", " global language\n", " language = language_selector.value\n", " change_language()\n", "\n", "\n", "def change_language():\n", " toogle_figures_loading()\n", "\n", " set_climate_tab_language()\n", "\n", " set_mb_months_language()\n", "\n", " # change base climate name language for mb models (use filesuffix)\n", " for i, climate_meta_data in enumerate(climate_tab_text['base_climate_meta_data']):\n", " file_suffix = climate_meta_data[0]\n", " if file_suffix == mb_models[0].input_filesuffix:\n", " mb_models[0].base_climate_name = climate_tab_text['base_climate_names'][language][i]\n", " if file_suffix == mb_models[1].input_filesuffix:\n", " mb_models[1].base_climate_name = climate_tab_text['base_climate_names'][language][i]\n", "\n", " set_mb_settings_tab_language()\n", "\n", " # change headings in menu\n", " set_tab_menu_tabs()\n", "\n", " set_change_selected_MB_RadioButtonGroup_language()\n", "\n", " # change headings for figures\n", " set_figures_tab_tabs()\n", "\n", " set_period_buttons_language()\n", "\n", " set_select_months_language()\n", "\n", " # update figures\n", " tab_figures_updated = [False, False, False]\n", " climographs_updated = [False, False, False]\n", " update_current_figures()\n", "\n", " toogle_figures_loading()" ] }, { "cell_type": "markdown", "id": "85283b56", "metadata": {}, "source": [ "Actual Language Selector" ] }, { "cell_type": "code", "execution_count": null, "id": "0d75c6f1", "metadata": {}, "outputs": [], "source": [ "from app_text import supported_languages\n", "\n", "language_selector = pn.widgets.RadioBoxGroup(name='select your language',\n", " options=supported_languages,\n", " inline=True,\n", " margin=(0, 0),\n", " width=70,\n", " align='center',\n", " height=15,\n", " )\n", "language_selector.param.watch(language_selector_function, 'value');" ] }, { "cell_type": "markdown", "id": "bcafd69c", "metadata": {}, "source": [ "# Define Menu" ] }, { "cell_type": "code", "execution_count": null, "id": "03fa6815", "metadata": {}, "outputs": [], "source": [ "# define background color of tab menu\n", "menu_background = '#f4f4f4'\n", "\n", "# define width for menu-tabs\n", "panel_width = 280\n", "\n", "# define width for whole menu\n", "tab_menu_width = 400\n", "\n", "# needed for some initialisations for start of app\n", "initial_run = True\n", "\n", "current_mb_i = 0" ] }, { "cell_type": "markdown", "id": "7d5fbac2", "metadata": {}, "source": [ "## Climate Tab" ] }, { "cell_type": "code", "execution_count": null, "id": "9d9faf06", "metadata": {}, "outputs": [], "source": [ "# Import Text for Climate Tab\n", "from app_text import climate_tab_text" ] }, { "cell_type": "code", "execution_count": null, "id": "d92fbef6", "metadata": {}, "outputs": [], "source": [ "# Function to change language of Climate Tab\n", "def set_climate_tab_language():\n", " base_climate_select.name = climate_tab_text['base_climate_select_name'][language]\n", "\n", " base_climate_select.options = climate_tab_text['base_climate_names'][language]\n", "\n", " y_start_slider.name = climate_tab_text['y_start_slider_name'][language]\n", "\n", " y_end_slider.name = climate_tab_text['y_end_slider_name'][language]\n", "\n", " set_climate_button.name = climate_tab_text['set_climate_button_name'][language]" ] }, { "cell_type": "code", "execution_count": null, "id": "02006bf2", "metadata": {}, "outputs": [], "source": [ "base_climate_select = pn.widgets.Select()\n", "\n", "y_end_slider = pn.widgets.IntSlider(start=1902,\n", " end=2020,\n", " step=1,\n", " value=2020)\n", "\n", "\n", "def change_y_end_slider_start(event):\n", " if y_start_slider.value > y_end_slider.value:\n", " y_end_slider.value = y_start_slider.value + 1\n", " if y_start_slider.value == 2019:\n", " y_end_slider.disabled = True\n", " else:\n", " y_end_slider.disabled = False\n", " y_end_slider.start = y_start_slider.value + 1\n", "\n", "\n", "y_start_slider = pn.widgets.IntSlider(start=1902,\n", " end=2019,\n", " step=1,\n", " value=1990)\n", "y_start_slider.param.watch(change_y_end_slider_start, ['value_throttled'])\n", "change_y_end_slider_start(None)\n", "\n", "\n", "def set_climate_button_click(event):\n", " global climate_meta_data\n", "\n", " set_default_mb_settings()\n", " # set file suffix for current selection\n", " for i, base_name in enumerate(climate_tab_text['base_climate_names'][language]):\n", " if base_name == base_climate_select.value:\n", " climate_meta_data = climate_tab_text['base_climate_meta_data'][i]\n", "\n", " set_climate_of_mb_model(current_mb_i)\n", "\n", " tab_figures_updated[current_mb_i] = False\n", " tab_figures_updated[2] = False\n", " climographs_updated[current_mb_i] = False\n", " climographs_updated[2] = False\n", " update_current_figures()\n", "\n", "\n", "set_climate_button = pn.widgets.Button(sizing_mode='stretch_width')\n", "set_climate_button.on_click(set_climate_button_click)\n", "\n", "set_climate_tab_language()\n", "\n", "climate_tab = pn.Column(base_climate_select,\n", " y_start_slider,\n", " y_end_slider,\n", " set_climate_button,\n", " background=menu_background,\n", " width=panel_width,\n", " sizing_mode='stretch_height')" ] }, { "cell_type": "markdown", "id": "f4810c32", "metadata": {}, "source": [ "## MB Settings" ] }, { "cell_type": "code", "execution_count": null, "id": "eca0386c", "metadata": {}, "outputs": [], "source": [ "from app_text import mb_settings_tab_text" ] }, { "cell_type": "code", "execution_count": null, "id": "584eeec9", "metadata": {}, "outputs": [], "source": [ "# Function to change language of MB Settings Tab\n", "def set_mb_settings_tab_language():\n", " mu_slider.name = mb_settings_tab_text['mu_slider_name'][language]\n", "\n", " temp_bias_slider.name = mb_settings_tab_text['temp_bias_slider_name'][language]\n", "\n", " temp_grad_slider.name = mb_settings_tab_text['temp_grad_slider_name'][language]\n", "\n", " prcp_fac_slider.name = mb_settings_tab_text['prcp_fac_slider_name'][language]\n", "\n", " temp_melt_slider.name = mb_settings_tab_text['temp_melt_slider_name'][language]\n", "\n", " temp_solid_slider.name = mb_settings_tab_text['temp_solid_slider_name'][language]\n", "\n", " temp_liquid_slider.name = mb_settings_tab_text['temp_liquid_slider_name'][language]\n", "\n", " set_mb_settings_button.name = mb_settings_tab_text['set_mb_settings_button_name'][language]" ] }, { "cell_type": "code", "execution_count": null, "id": "905a2188", "metadata": {}, "outputs": [], "source": [ "# MB Settings\n", "default_mu = 200\n", "min_mu = 100\n", "max_mu = 300\n", "mu_unit = 'kg m⁻² °C⁻¹ mth⁻¹'\n", "mu_slider = pn.widgets.IntSlider(start=min_mu,\n", " end=max_mu,\n", " step=10,\n", " value=default_mu)\n", "mu_slider.format = PrintfTickFormatter(format='%d ' + mu_unit)\n", "\n", "default_temp_bias = 0\n", "temp_bias_slider = pn.widgets.FloatSlider(start=-5,\n", " end=5,\n", " step=0.1,\n", " value=default_temp_bias)\n", "temp_bias_slider.format = PrintfTickFormatter(format='%.1f °C')\n", "\n", "temp_grad_slider = pn.widgets.FloatSlider(start=cfg.PARAMS['temp_local_gradient_bounds'][0] * 100,\n", " end=cfg.PARAMS['temp_local_gradient_bounds'][1] * 100,\n", " step=0.01,\n", " value=cfg.PARAMS['temp_default_gradient'] * 100)\n", "temp_grad_slider.format = PrintfTickFormatter(format='%.2f °C/100m')\n", "\n", "prcp_fac_slider = pn.widgets.FloatSlider(start=0.5,\n", " end=5,\n", " step=0.1,\n", " value=cfg.PARAMS['prcp_scaling_factor'])\n", "\n", "temp_melt_slider = pn.widgets.FloatSlider(start=-2,\n", " end=0,\n", " step=0.1,\n", " value=cfg.PARAMS['temp_melt'])\n", "temp_melt_slider.format = PrintfTickFormatter(format='%.1f °C')\n", "\n", "temp_solid_slider = pn.widgets.FloatSlider(start=-0.5,\n", " end=0.5,\n", " step=0.1,\n", " value=cfg.PARAMS['temp_all_solid'])\n", "temp_solid_slider.format = PrintfTickFormatter(format='%.1f °C')\n", "\n", "temp_liquid_slider = pn.widgets.FloatSlider(start=0.5,\n", " end=3,\n", " step=0.1,\n", " value=cfg.PARAMS['temp_all_liq'])\n", "temp_liquid_slider.format = PrintfTickFormatter(format='%.1f °C')\n", "\n", "\n", "def set_mb_settings_click(event):\n", " set_mb_settings_of_mb_model(current_mb_i)\n", " \n", " tab_figures_updated[current_mb_i] = False\n", " tab_figures_updated[2] = False\n", " update_current_figures()\n", "\n", "\n", "def set_default_mb_settings():\n", " mu_slider.value = default_mu\n", " temp_bias_slider.value = default_temp_bias\n", " temp_grad_slider.value = cfg.PARAMS['temp_default_gradient'] * 100\n", " prcp_fac_slider.value = cfg.PARAMS['prcp_scaling_factor']\n", " temp_melt_slider.value = cfg.PARAMS['temp_melt']\n", " temp_solid_slider.value = cfg.PARAMS['temp_all_solid']\n", " temp_liquid_slider.value = cfg.PARAMS['temp_all_liq']\n", "\n", "\n", "set_mb_settings_button = pn.widgets.Button(name='Set MB Settings',\n", " sizing_mode='stretch_width')\n", "set_mb_settings_button.on_click(set_mb_settings_click)\n", "\n", "set_mb_settings_tab_language()\n", "\n", "MB_settings_tab = pn.Column(mu_slider,\n", " temp_bias_slider,\n", " temp_grad_slider,\n", " prcp_fac_slider,\n", " temp_melt_slider,\n", " temp_solid_slider,\n", " temp_liquid_slider,\n", " set_mb_settings_button,\n", " width=panel_width,\n", " sizing_mode='stretch_height')" ] }, { "cell_type": "markdown", "id": "25a24e65", "metadata": {}, "source": [ "## But all Tabs together" ] }, { "cell_type": "code", "execution_count": null, "id": "1223c600", "metadata": {}, "outputs": [], "source": [ "tab_menu = pn.Tabs(('', []),\n", " height=420,\n", " width=tab_menu_width,\n", " background=menu_background,\n", " tabs_location='left')\n", "\n", "# is necassary to change the tabs title language\n", "\n", "\n", "def set_tab_menu_tabs():\n", " tab_menu.clear()\n", "\n", " tab_menu.append((climate_tab_text['heading'][language],\n", " climate_tab))\n", "\n", " tab_menu.append((mb_settings_tab_text['heading'][language],\n", " MB_settings_tab))\n", "\n", "\n", "set_tab_menu_tabs()" ] }, { "cell_type": "markdown", "id": "ac781de7", "metadata": {}, "source": [ "## functions toggle figures loading status" ] }, { "cell_type": "code", "execution_count": null, "id": "bc007b4c", "metadata": {}, "outputs": [], "source": [ "def toogle_figures_loading():\n", " figures_tab.loading = not figures_tab.loading" ] }, { "cell_type": "markdown", "id": "00482de4", "metadata": {}, "source": [ "# Logos for App" ] }, { "cell_type": "code", "execution_count": null, "id": "b57acc52", "metadata": {}, "outputs": [], "source": [ "oggm_edu_logo_link = ('
')\n", "hv_logo_link = '' + __version__ + '
',\n", " height=20,\n", " margin=(0, 0),\n", " align='end',),\n", " sizing_mode='stretch_width'))\n", "app.add_panel('menu_and_figures', pn.Row(pn.Column(tab_menu,\n", " all_logos,\n", " ),\n", " figures_tab,\n", " sizing_mode='stretch_both'))\n", "app.servable(title='Mass Balance Simulator ' + __version__)" ] }, { "cell_type": "markdown", "id": "d97d9c47", "metadata": {}, "source": [ "As long as you are running this notebook \"live\" (in Jupyter, not viewing a website or a static copy), the above notebook cell should contain the fully operational dashboard here in the notebook. You can also launch the dashboard at a separate port that shows up in a new browser tab, either by changing .servable() to .show() above and re-executing that cell, or by leaving the cell as it is and running bokeh serve --show simulator.ipynb." ] } ], "metadata": { "kernelspec": { "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.10.16" }, "toc": { "base_numbering": 1, "nav_menu": {}, "number_sections": true, "sideBar": true, "skip_h1_title": false, "title_cell": "Table of Contents", "title_sidebar": "Contents", "toc_cell": false, "toc_position": { "height": "calc(100% - 180px)", "left": "10px", "top": "150px", "width": "296.467px" }, "toc_section_display": true, "toc_window_display": false } }, "nbformat": 4, "nbformat_minor": 5 }