# -*- coding: utf-8 -*- """ Created on Thu Mar 9 14:48:52 2023 @author: BorowyP """ import pandas as pd import hvplot import hvplot.pandas # Adds .hvplot and .interactive methods to Pandas dataframes import panel as pn # Panel is a simple, flexible and enterprise-ready data app framework import holoviews as hv from holoviews.operation.timeseries import rolling, rolling_outlier_std import panel as pn from bokeh.models import ColumnDataSource, PrintfTickFormatter, FuncTickFormatter, LabelSet from bokeh.palettes import GnBu3, OrRd3 from bokeh.plotting import figure, show, output_notebook, output_file, save from bokeh.layouts import row from bokeh.io import curdoc hv.extension('bokeh') pn.extension('tabulator') pn.extension(sizing_mode="stretch_width") #pd.set_option("precision", 0) PALETTE = ["#ff6f69", "#ffcc5c", "#88d8b0", ] ACCENT_BASE_COLOR = PALETTE[0] import time start = time.time() print('load data') import numpy as np Stndrt_button = pn.widgets.RadioButtonGroup( name='Standort', options=['Glienig', 'Groß Liebitz', 'Halbe', 'Krausnick', 'Hangelsberg', 'Spreeau'], button_type = 'success' ) mpa = pd.read_excel('2023_01_30_Mittelwerte_Masseverlust.xlsx', header=5, #decimal=',' ) def create_df(standort): name = str(standort) tiefen = [ '40-50','30-40', '20-30', '10-20', '0-10', '-10-0'] zeitpunkt = ['März 21', 'Oktober 21', 'Oktober 22'] mrz21 = mpa.loc[mpa['Bestand'] == standort].loc[mpa['Kalk?'] == 'Kalk'].loc[mpa['bau'] == '2021-03-01'][['50-60.1', '40-50.1', '30-40.1', '20-30.1', '10-20.1', '0-10.1']].values[0] okt21 = mpa.loc[mpa['Bestand'] == standort].loc[mpa['Kalk?'] == 'Kalk'].loc[mpa['bau'] == '2021-10-01'][['50-60.1', '40-50.1', '30-40.1', '20-30.1', '10-20.1', '0-10.1']].values[0] okt22 = mpa.loc[mpa['Bestand'] == standort].loc[mpa['Kalk?'] == 'Kalk'].loc[mpa['bau'] == '2022-10-01'][['50-60.1', '40-50.1', '30-40.1', '20-30.1', '10-20.1', '0-10.1']].values[0] kiefer_k = pd.DataFrame({'tiefen' : tiefen, '10 Mon' : mrz21, '16 Mon' : okt21, '28 Mon' : okt22}) kiefer_k_label = pd.DataFrame({'tiefen' : tiefen, '10 Mon' : mrz21, '16 Mon' : okt21, '28 Mon' : okt22}) kiefer_k['28 Mon'] = kiefer_k['28 Mon']-kiefer_k['16 Mon'] kiefer_k['16 Mon'] = kiefer_k['16 Mon']-kiefer_k['10 Mon'] mrz21 = mpa.loc[mpa['Bestand'] == standort].loc[mpa['Kalk?'] == 'Kalk'].loc[mpa['bau'] == '2021-03-01'][['50-60.3', '40-50.3', '30-40.3', '20-30.3', '10-20.3', '0-10.3']].values[0] okt21 = mpa.loc[mpa['Bestand'] == standort].loc[mpa['Kalk?'] == 'Kalk'].loc[mpa['bau'] == '2021-10-01'][['50-60.3', '40-50.3', '30-40.3', '20-30.3', '10-20.3', '0-10.3']].values[0] okt22 = mpa.loc[mpa['Bestand'] == standort].loc[mpa['Kalk?'] == 'Kalk'].loc[mpa['bau'] == '2022-10-01'][['50-60.3', '40-50.3', '30-40.3', '20-30.3', '10-20.3', '0-10.3']].values[0] buche_k = pd.DataFrame({'tiefen' : tiefen, '10 Mon' : mrz21, '16 Mon' : okt21, '28 Mon' : okt22}) buche_k_label = pd.DataFrame({'tiefen' : tiefen, '10 Mon' : mrz21, '16 Mon' : okt21, '28 Mon' : okt22}) buche_k['28 Mon'] = buche_k['28 Mon']-buche_k['16 Mon'] buche_k['16 Mon'] = buche_k['16 Mon']-buche_k['10 Mon'] buche_k[['10 Mon', '16 Mon', '28 Mon']] = buche_k[['10 Mon', '16 Mon', '28 Mon']]*-1 ########################################## K E I N K A L K (ohne Kalk) ############################################################################ mrz21 = mpa.loc[mpa['Bestand'] == standort].loc[mpa['Kalk?'] == 'ohne Kalk'].loc[mpa['bau'] == '2021-03-01'][['50-60.1', '40-50.1', '30-40.1', '20-30.1', '10-20.1', '0-10.1']].values[0] okt21 = mpa.loc[mpa['Bestand'] == standort].loc[mpa['Kalk?'] == 'ohne Kalk'].loc[mpa['bau'] == '2021-10-01'][['50-60.1', '40-50.1', '30-40.1', '20-30.1', '10-20.1', '0-10.1']].values[0] okt22 = mpa.loc[mpa['Bestand'] == standort].loc[mpa['Kalk?'] == 'ohne Kalk'].loc[mpa['bau'] == '2022-10-01'][['50-60.1', '40-50.1', '30-40.1', '20-30.1', '10-20.1', '0-10.1']].values[0] kiefer_nk = pd.DataFrame({'tiefen' : tiefen, '10 Mon' : mrz21, '16 Mon' : okt21, '28 Mon' : okt22}) kiefer_nk_label = pd.DataFrame({'tiefen' : tiefen, '10 Mon' : mrz21, '16 Mon' : okt21, '28 Mon' : okt22}) kiefer_nk['28 Mon'] = kiefer_nk['28 Mon']-kiefer_nk['16 Mon'] kiefer_nk['16 Mon'] = kiefer_nk['16 Mon']-kiefer_nk['10 Mon'] mrz21 = mpa.loc[mpa['Bestand'] == standort].loc[mpa['Kalk?'] == 'ohne Kalk'].loc[mpa['bau'] == '2021-03-01'][['50-60.3', '40-50.3', '30-40.3', '20-30.3', '10-20.3', '0-10.3']].values[0] okt21 = mpa.loc[mpa['Bestand'] == standort].loc[mpa['Kalk?'] == 'ohne Kalk'].loc[mpa['bau'] == '2021-10-01'][['50-60.3', '40-50.3', '30-40.3', '20-30.3', '10-20.3', '0-10.3']].values[0] okt22 = mpa.loc[mpa['Bestand'] == standort].loc[mpa['Kalk?'] == 'ohne Kalk'].loc[mpa['bau'] == '2022-10-01'][['50-60.3', '40-50.3', '30-40.3', '20-30.3', '10-20.3', '0-10.3']].values[0] buche_nk = pd.DataFrame({'tiefen' : tiefen, '10 Mon' : mrz21, '16 Mon' : okt21, '28 Mon' : okt22}) buche_nk_label = pd.DataFrame({'tiefen' : tiefen, '10 Mon' : mrz21, '16 Mon' : okt21, '28 Mon' : okt22}) buche_nk['28 Mon'] = buche_nk['28 Mon']-buche_nk['16 Mon'] buche_nk['16 Mon'] = buche_nk['16 Mon']-buche_nk['10 Mon'] buche_nk[['10 Mon', '16 Mon', '28 Mon']] = buche_nk[['10 Mon', '16 Mon', '28 Mon']]*-1 ###################################################################################################################### return buche_k.round(1), kiefer_k.round(1), buche_nk.round(1), kiefer_nk.round(1), buche_k_label.round(1), kiefer_k_label.round(1), buche_nk_label.round(1), kiefer_nk_label.round(1), name def plot(df): curdoc().clear() tiefen = [ '40-50','30-40', '20-30', '10-20', '0-10', '-10-0'] zeitpunkt = ['10 Mon', '16 Mon', '28 Mon'] hoehe = 500 breite = 600 plot_k = figure(y_range=tiefen, height=hoehe,width=breite, x_range=([-100, 100]), title="Masseverlust Bu/Ki (K)", toolbar_location='left') plot_k.xaxis.axis_label = 'Masseverlust [%]' plot_k.yaxis.axis_label = 'Tiefenstufe' #plot_k.image_url(url=['Bodenhorizont_entnahme_pruefkoerper.jpg'], # x=-300, # y=9, # #dw = 100, # #dh = 100, # w=600, # h=10 # ) plot_k.hbar_stack(zeitpunkt, y='tiefen', height=0.9, color=GnBu3, source=ColumnDataSource(df[1]), legend_label=["Ki %s" % x for x in zeitpunkt], fill_alpha = 0.7) plot_k.hbar_stack(zeitpunkt, y='tiefen', height=0.9, color=OrRd3, source=ColumnDataSource(df[0]), legend_label=["Bu %s" % x for x in zeitpunkt], fill_alpha = 0.7) plot_k.xaxis.ticker = [ -100, -75 , -50 , -25 , 0 , 25 , 50 , 75 , 100 ] plot_k.xaxis.major_label_overrides = { -100: '100', -75:' ', -50 : '50', -25 : ' ' , 0 : '0', 25: ' ',50 : '50', 75 : ' ', 100 :'100'} plot_k.y_range.range_padding = 0.1 plot_k.ygrid.grid_line_color = None plot_k.axis.minor_tick_line_color = None plot_k.outline_line_color = None labels = {'x': ( list((df[1][zeitpunkt].cumsum(axis=1)['28 Mon'] + 10).to_numpy().flatten() ) + list((df[0][zeitpunkt].cumsum(axis=1)['28 Mon'] -10).to_numpy().flatten() ) ), 'y': list(np.array([i+0.5 for i in range(len(tiefen))]))*2, 'labels': ( list(np.around(df[5][zeitpunkt]['28 Mon'], 2).abs().astype(str).replace('^0$','', regex=True).to_numpy().flatten() ) +list(np.around(df[4][zeitpunkt]['28 Mon'], 2).abs().astype(str).replace('^0$','', regex=True).to_numpy().flatten() ) ) } labels = LabelSet(x="x", y="y", text='labels', text_font_size="11px", text_color="#555555", source=ColumnDataSource(labels), text_align='center') plot_k.add_layout(labels) plot_k.legend.title = df[8] plot_k.legend.title_text_font_style = "bold" plot_k.legend.title_text_font_size = "10px" plot_k.add_layout(plot_k.legend[0], 'right') bokeh_k = pn.pane.Bokeh(plot_k) ############################## P L O T n_k ################################################## plot_nk = figure(y_range=tiefen, height=hoehe,width=breite-150, x_range=([-100, 100]), title="Masseverlust Bu/Ki (nK)", toolbar_location='right', y_axis_location="right") plot_nk.xaxis.axis_label = 'Masseverlust [%]' plot_nk.yaxis.axis_label = 'Tiefenstufe' #plot_nk.image_url(url=['Bodenhorizont_entnahme_pruefkoerper.jpg'], # x=-300, # y=9, # #dw = 100, # #dh = 100, # w=600, # h=10 # ) plot_nk.hbar_stack(zeitpunkt, y='tiefen', height=0.9, color=GnBu3, source=ColumnDataSource(df[3]), legend_label=["Ki %s" % x for x in zeitpunkt], fill_alpha = 0.7) plot_nk.hbar_stack(zeitpunkt, y='tiefen', height=0.9, color=OrRd3, source=ColumnDataSource(df[2]), legend_label=["Bu %s" % x for x in zeitpunkt], fill_alpha = 0.7) plot_nk.xaxis.ticker = [ -100, -75 , -50 , -25 , 0 , 25 , 50 , 75 , 100 ] plot_nk.xaxis.major_label_overrides = { -100: '100', -75:' ', -50 : '50', -25 : ' ' , 0 : '0', 25: ' ',50 : '50', 75 : ' ', 100 :'100'} plot_nk.y_range.range_padding = 0.1 plot_nk.ygrid.grid_line_color = None plot_nk.legend.location = (600,100) plot_nk.axis.minor_tick_line_color = None plot_nk.outline_line_color = None labels = {'x': ( list((df[3][zeitpunkt].cumsum(axis=1)['28 Mon']+10).to_numpy().flatten()) + list((df[2][zeitpunkt].cumsum(axis=1)['28 Mon']-10).to_numpy().flatten()) ), 'y': list(np.array([i+0.5 for i in range(len(tiefen))]))*2, 'labels': ( list(np.around(df[7][zeitpunkt]['28 Mon'], 2).abs().astype(str).replace('^0$','', regex=True).to_numpy().flatten() ) +list(np.around(df[6][zeitpunkt]['28 Mon'], 2).abs().astype(str).replace('^0$','', regex=True).to_numpy().flatten() ) ) } labels = LabelSet(x="x", y="y", text='labels', text_font_size="11px", text_color="#555555", source=ColumnDataSource(labels), text_align='center') plot_nk.add_layout(labels) bokeh_nk = pn.pane.Bokeh(plot_nk) return pn.Row(bokeh_k, bokeh_nk) df_mpa = pd.DataFrame({'Standort' : ['Glienig', 'Groß Liebitz', 'Halbe', 'Krausnick', 'Hangelsberg', 'Spreeau']}) df_mpa_i = df_mpa.interactive() df_mpa_pipe = df_mpa_i[ (df_mpa_i.Standort == Stndrt_button) ] glienig = create_df('KVF 3 Glienig') grliebitz = create_df('KVF 4 Groß Liebitz') halbe = create_df('KVF 12 Halbe') krausnick = create_df('KVF 9 Krausnick') hangelsberg = create_df('KVF 10 Hangelsberg') spreeau = create_df('KVF 19 Spreeau') mittelwerte = create_df('Mittelwerte') plot_mittelwerte = plot(mittelwerte) def callback(df_mpa_pipe): if Stndrt_button.value == 'Groß Liebitz': return plot(grliebitz) if Stndrt_button.value == 'Glienig': return plot(glienig) if Stndrt_button.value == 'Halbe': return plot(halbe) if Stndrt_button.value == 'Krausnick': return plot(krausnick) if Stndrt_button.value == 'Hangelsberg': return plot(hangelsberg) if Stndrt_button.value == 'Spreeau': return plot(spreeau) masseverlust_plot = df_mpa_pipe.pipe(callback) hd_logo = pn.pane.PNG('HD_Logo.png', width=100) hd_logo lfe_logo = pn.pane.PNG('LFE_Logo.png', width=100) fnr_logo = pn.pane.PNG('fnr_logo.png', width=100) sidebar_link_list = pn.pane.HTML( '''
''') sidebar_menu = pn.Column(hd_logo, pn.pane.Markdown("## Menu"), sidebar_link_list, lfe_logo, fnr_logo ) diagram_text = 'Die Diagramme stellen die zu den 3 Ausbauzeitpunkten ermittelten Masseverluste für die Buche (BU)- und Kiefer (KI)-Prüfkörper in allen 6 Tiefenstufen, auf dem jeweiligen Standort (Fläche) sowie für die Teilflächen gekalkt (K) und ungekalkt (nK) dar. Dabei sind die für die Holzart BU ermittelten Werte ausgehend von der vertikalen Mittellinie nach links in rot/gelb dargestellt und die für die Holzart KI ausgehend von der Mittellinie nach rechts in blau/grün. Die Masseverluste wurden vor Einbau und zu den Ausbauzeitpunkten (an den bei 103° C bis zur Massekonstanz gedarrten Stab-Prüfkörpern) bestimmt und sind auf der Abszisse in Prozent ablesbar.' template = pn.template.FastListTemplate( title='Holzdeko Dashboard', sidebar=[sidebar_menu ], main=[pn.pane.Markdown("## Masseverlust"), masseverlust_plot, pn.pane.Markdown(f'{diagram_text}'), pn.pane.Markdown("## Mittelwerte"), plot_mittelwerte ], accent_base_color="#00613a", header_background="#00613a",) template.servable(); #print('fertig!') # To launch this dashboard as a web server, we can simply run # cd C:\Users\BorowyP\Desktop\Dashboard-Preasi\MPA_Masseverlust_docker # panel serve 2023_03_09_MW_MPA.ipynb --autoreload