def data_viewer(dataset, tables, columns_per_table, **widget_args): """Show all data in a downloadable table""" formatters = { "ng_vsh40_pct": NumberFormatter(format="0 %"), "thickness_mtvd": NumberFormatter(format="0.0"), "top_depth_mtvd": NumberFormatter(format="0.0"), "base_depth_mtvd": NumberFormatter(format="0.0"), } def get_filename(table): return f"{dataset}-{table}.xlsx" def get_data(table_name): columns = columns_per_table.get(table_name, {}) return (readers.read_all( config.app.apps.reader, dataset, table_name).loc[:, columns.keys()].sort_values( by="ng_vsh40_pct", ascending=False).reset_index(drop=True)) table_name = pn.widgets.Select( name="Choose table", options={t.title(): t for t in tables}, value=tables[0], size=1, ) filename = pn.widgets.TextInput(name="File name", value=get_filename(table_name.value)) @pn.depends(table_name.param.value) def table(table_name): data = get_data(table_name).assign( ng_vsh40_pct=lambda d: d.ng_vsh40_pct / 100 # Show N:G as percent ) return pn.widgets.Tabulator( data, disabled=True, titles=columns_per_table[table_name], formatters=formatters, layout="fit_data_table", **widget_args, ) @pn.depends(table_name.param.value, watch=True) def update_filename(table_name): filename.value = get_filename(table_name) def download_file(): """Download data as an Excel file""" output_bytes = io.BytesIO() # Write data as Excel excel_writer = pd.ExcelWriter(output_bytes, engine="xlsxwriter") get_data(table_name.value).to_excel( excel_writer, sheet_name=table_name.value.title(), index=False) excel_writer.save() # Reset output stream and return it output_bytes.seek(0) return output_bytes @pn.depends(filename.param.value) def download_button(filename): return pn.widgets.FileDownload(callback=download_file, filename=filename, button_type="success") return pn.Row( pn.Column( table_name, filename, download_button, ), pn.Column(table, sizing_mode="stretch_width"), )
def load_app(config_file): pn.config.sizing_mode = 'stretch_both' impact_hour_data = read_impact_hour_data() # TECH t = TECH( total_impact_hours=impact_hour_data['Assumed IH'].sum(), impact_hour_data=impact_hour_data, total_cstk_tokens=1000000, config=config_file['tech']) # DandelionVoting dandelion = DandelionVoting(17e6, config=config_file['dandelion_voting']) updating_results = pn.widgets.Button(name="Updating", disabled=True) # Share Button comments_tech = pn.widgets.TextAreaInput( name='What is your Hatch Strategy?', max_length=1024, placeholder='Tell us why you configured the Hatch this way') comments_dandelion = pn.widgets.TextAreaInput( name='What is your Dandelion Voting strategy?', max_length=1024, placeholder='What intended effects will your Dandelion Voting Parameters have?') share_button = pn.widgets.Button(name='Submit Hatch Config Proposal', button_type='primary', disabled=True) url = pn.widgets.TextInput(name='URL', value='') share_button.js_on_click(args={'target': url}, code='window.open(target.value)') results_button = pn.widgets.Button(name='See your results', button_type='success') # Run buttons run_dandelion = pn.widgets.Button(name='Run simulation', button_type='success') run_impact_hours = pn.widgets.Button(name='Run simulation', button_type='success') def update_params_by_url_query(): queries = curdoc().session_context.request.arguments queries = {i: j[0] for i, j in queries.items()} if queries: if 'ihminr' in queries: t.min_raise = int(queries['ihminr']) if 'ihmaxr' in queries: t.max_raise = int(queries['ihmaxr']) if 'tgihr' in queries: t.impact_hour_rate_at_target_goal = float(queries['tgihr']) if 'maxihr' in queries: t.maximum_impact_hour_rate = float(queries['maxihr']) if 'ihtr' in queries: t.target_raise = int(queries['ihtr']) if 'hor' in queries: t.hatch_oracle_ratio = float(queries['hor']) if 'hpd' in queries: t.hatch_period_days = int(queries['hpd']) if 'her' in queries: t.hatch_exchange_rate = float(queries['her']) if 'ht' in queries: t.hatch_tribute_percentage = int(queries['ht']) if 'sr' in queries: dandelion.support_required_percentage = int(queries['sr']) if 'maq' in queries: dandelion.minimum_accepted_quorum_percentage = int(queries['maq']) if 'vdd' in queries: dandelion.vote_duration_days = int(queries['vdd']) if 'vbh' in queries: dandelion.vote_buffer_hours = int(queries['vbh']) if 'rqh' in queries: dandelion.rage_quit_hours = int(queries['rqh']) if 'tfx' in queries: dandelion.tollgate_fee_xdai = float(queries['tfx']) t.param.trigger('action') # Update dashboard dandelion.param.trigger('action') @pn.depends(updating_results) def update_input_output_pane(results_button_on): if results_button_on: input_output_pane = pn.pane.GIF('media/inputs_outputs.gif') else: input_output_pane = pn.pane.Markdown('') return input_output_pane @pn.depends(updating_results) def update_output_scenarios(results_button_on): if results_button_on: output_scenarios = pn.panel(t.output_scenarios_view() .hvplot.table()) else: output_scenarios = pn.pane.Markdown('') return output_scenarios @pn.depends(updating_results) def update_result_score(results_button_on): if results_button_on: t.param.trigger('action') # Update dashboard dandelion.param.trigger('action') data_table = { 'Parameters': [ "Target Goal (wxDai)", "Maximum Goal (wxDai)", "Minimum Goal (wxDai)", "Impact Hour Rate at Target Goal (wxDai/IH)", "Impact Hour Rate at Infinity (wxDai/IH)", "Hatch Membership Ratio (wxDai/CSTK)", "Hatch Period (days)", "Hatch Minting rate (TECH/wxDai)", "Hatch Tribute (%)", "Support Required (%)", "Minimum Quorum (%)", "Vote Duration (days)", "Vote Buffer (hours)", "Ragequit Delay (hours)", "Tollgate Fee (wxDai)"], 'Values': [ int(t.target_raise), int(t.max_raise), int(t.min_raise), t.impact_hour_rate_at_target_goal, t.maximum_impact_hour_rate, t.hatch_oracle_ratio, t.hatch_period_days, t.hatch_exchange_rate, t.hatch_tribute_percentage, dandelion.support_required_percentage, dandelion.minimum_accepted_quorum_percentage, dandelion.vote_duration_days, dandelion.vote_buffer_hours, dandelion.rage_quit_hours, dandelion.tollgate_fee_xdai] } df = pd.DataFrame(data=data_table) # Define output pane output_pane = pn.Row(pn.Column(t.impact_hours_plot, t.redeemable_plot), pn.Column(dandelion.vote_pass_view, t.pie_charts_view)) output_pane.save('output.html') pn.panel(t.output_scenarios_view() .hvplot.table()).save('out_scenarios.html') scenarios = codecs.open("out_scenarios.html", 'r') charts = codecs.open("output.html", 'r') data_charts = { 'html': charts.read(), 'css': ".box { color: white; background-color: #0f79b9; padding: 10px; font-family: Roboto }", 'google_fonts': "Roboto"} data_scenarios = { 'html': scenarios.read(), 'css': ".box { color: white; background-color: #0f79b9; padding: 10px; font-family: Roboto }", 'google_fonts': "Roboto"} charts = requests.post(url=HCTI_API_ENDPOINT, data=data_charts, auth=(HCTI_API_USER_ID, HCTI_API_KEY)) scenarios = requests.post(url=HCTI_API_ENDPOINT, data=data_scenarios, auth=(HCTI_API_USER_ID, HCTI_API_KEY)) # Parameters string url_fork = '{url}?ihminr={ihf_minimum_raise}&tgihr={impact_hour_rate_at_target_goal}&maxihr={maximum_impact_hour_rate}&ihtr={ihf_target_raise}&ihmaxr={ifh_maximum_raise}&hor={hatch_oracle_ratio}&hpd={hatch_period_days}&her={hatch_exchange_rate}&ht={hatch_tribute_percentage}&sr={support_required}&maq={minimum_accepted_quorum}&vdd={vote_duration_days}&vbh={vote_buffer_hours}&rqh={rage_quit_hours}&tfx={tollgate_fee_xdai}"'.format(tollgate_fee_xdai=dandelion.tollgate_fee_xdai, vote_duration_days=dandelion.vote_duration_days, rage_quit_hours=dandelion.rage_quit_hours, ihf_minimum_raise=int(t.min_raise), impact_hour_rate_at_target_goal=t.impact_hour_rate_at_target_goal, maximum_impact_hour_rate=t.maximum_impact_hour_rate, ihf_target_raise=t.target_raise, ifh_maximum_raise=int(t.max_raise), hatch_oracle_ratio=t.hatch_oracle_ratio, hatch_period_days=t.hatch_period_days, hatch_exchange_rate=t.hatch_exchange_rate, hatch_tribute_percentage=t.hatch_tribute_percentage, support_required=dandelion.support_required_percentage, minimum_accepted_quorum=dandelion.minimum_accepted_quorum_percentage, vote_buffer_hours=dandelion.vote_buffer_hours, max_wxdai_ratio=int(1125*t.hatch_oracle_ratio), total_votes_per_year=int(24/dandelion.vote_buffer_hours*365), single_tech_mint=float(1/t.hatch_exchange_rate), url=config_file['url']) # Title title = '## Check out my proposal for the Hatch! <a href="' + url_fork + ' target="_blank">Click here to preload the Hatch Configuration Dashboard with my parameters if you think you can do better</a>.' meme_image = """ ![image](https://i.imgflip.com/57zyrl.jpg) """ graphical_summary = """ # Graphical Summary ![image]({image_charts}) """.format(image_charts=charts.json()['url']) graph_descriptions = """ ## Graph Descriptions - Top Left, **Impact Hour Rate vs wxDai Collected**: The Impact Hour Rate determines the Minting Rate for Builders, making 1 Impact Hour equivalent to sending this amount of wxDai to the Hatch. - Top Right, **Proposal Acceptance Criteria**: Shows the range of possibilities for DAO vote outcomes and whether they succeed or not given the Support Required & Minimum Quorum I chose. - Bottom Left, **Backer's Rage Quit % vs wxDai Collected**: The Backer's Rage Quit % is the percent of wxDai that the Backers sent to the Hatch that would be returned if they decide to Ragequit. - Bottom Right, **Redeem-ability of the DAO's wxDai**: Shows who has rights to the wxDai held by the DAO. All of the DAO's funds are collectively governed but some can be withdrawn if token holders Ragequit. This shows the results of my parameter choices at the 3 different goals. """ simulated_outcomes = """ # Simulated Outcomes ![image]({image_scenarios}) """.format(image_scenarios=scenarios.json()['url']) parameters_data = """ # My Hatch Configuration | Parameter|Value| |:-|-:| |Target Goal (wxDai)|{target_goal:,}| |Maximum Goal (wxDai)|{max_goal:,}| |Minimum Goal (wxDai)|{min_goal:,}| |Impact Hour Rate at Target Goal (wxDai/IH)|{ih_rate_tg_goal:,}| |Impact Hour Rate at Infinity (wxDai/IH)|{ih_rate_infinity:,}| |Hatch Membership Ratio (wxDai/CSTK)|{hatch_membership_ratio:,}| |Hatch Period (days)|{hatch_period_days}| |Hatch Minting rate (TECH/wxDai)|{hatch_minting_rate:,}| |Hatch Tribute (%)|{hatch_tribute}| |Support Required (%)|{support_required}| |Minimum Quorum (%)|{minimum_quorum}| |Vote Duration (days)|{vote_duration_days}| |Vote Buffer (hours)|{vote_buffer_hours}| |Ragequit (hours)|{ragequit}| |Tollgate Fee (wxDai)|{tollgate_fee:,}|</a>""".format(target_goal=t.target_raise, max_goal=t.max_raise, min_goal=t.min_raise, ih_rate_tg_goal=t.impact_hour_rate_at_target_goal, ih_rate_infinity=t.maximum_impact_hour_rate, hatch_membership_ratio=t.hatch_oracle_ratio, hatch_period_days=t.hatch_period_days, hatch_minting_rate=t.hatch_exchange_rate, hatch_tribute=t.hatch_tribute_percentage, support_required=dandelion.support_required_percentage, minimum_quorum=dandelion.minimum_accepted_quorum_percentage, vote_duration_days=dandelion.vote_duration_days, vote_buffer_hours=dandelion.vote_buffer_hours, ragequit=dandelion.rage_quit_hours, tollgate_fee=dandelion.tollgate_fee_xdai) results_header = """ # Summary """ default_comment = "To use the defaults... Technocracy for the win" if not comments_tech.value: print(comments_tech.value) comment_tech = default_comment else: comment_tech = comments_tech.value if not comments_dandelion.value: comment_dandelion = default_comment else: comment_dandelion = comments_dandelion.value string_comments_tech = """ ## Hatch Strategy <p>{comments}</p> """.format(comments=comment_tech) string_comments_dandelion = """ ## DAO Strategy <p>{comments}</p> """.format(comments=comment_dandelion) string_data = """ <h2>Hatch Details</h2> - Trusted Seed members can send wxDai to the Hatch for {hatch_period_days} days. - The target goal will be {ihf_target_raise} wxDai, with a minimum of {ihf_minimum_raise} wxDai necessary for the TEC Hatch DAO to be launched and a cap at {ifh_maximum_raise} wxDai. - Backers will need to send in {single_tech_mint} wxDai to mint 1 TECH. - The membership ratio is set at {hatch_oracle_ratio} wxDai/CSTK, so a Trusted Seed member with the minimum CSTK Score of 1125 CSTK can send up to {max_wxdai_ratio} wxDai to the Hatch. <h2>TEC Hatch DAO Voting Details</h2> - Proposals will be voted on for {vote_duration_days} days. They will require at least {support_required}% support, and a minimum of {minimum_accepted_quorum}% of the TECH Tokens will have to vote yes for a proposal to pass. - TECH token holders will have {rage_quit_hours} hours to exit the DAO if they don't like the result of a vote (as long as they didn't vote yes) before it is executed. - There will be a minimum of {vote_buffer_hours} hours between proposals so people always have time to exit safely if they voted yes on a previous vote, this means we can have at most {total_votes_per_year} votes per year. - To prevent griefing attacks, it will cost {tollgate_fee_xdai} wxDai to make a proposal. If you have Impact Hours, you can see how much money you will get with my configuration <a href="{url}?ihminr={ihf_minimum_raise}&tgihr={impact_hour_rate_at_target_goal}&maxihr={maximum_impact_hour_rate}&ihtr={ihf_target_raise}&ihmaxr={ifh_maximum_raise}&hor={hatch_oracle_ratio}&hpd={hatch_period_days}&her={hatch_exchange_rate}&ht={hatch_tribute_percentage}&sr={support_required}&maq={minimum_accepted_quorum}&vdd={vote_duration_days}&vbh={vote_buffer_hours}&rqh={rage_quit_hours}&tfx={tollgate_fee_xdai}" target="_blank">here, just check out the Impact Hour Results table. """.format(tollgate_fee_xdai=dandelion.tollgate_fee_xdai, vote_duration_days=dandelion.vote_duration_days, rage_quit_hours=dandelion.rage_quit_hours, ihf_minimum_raise=int(t.min_raise), impact_hour_rate_at_target_goal=t.impact_hour_rate_at_target_goal, maximum_impact_hour_rate=t.maximum_impact_hour_rate, ihf_target_raise=t.target_raise, ifh_maximum_raise=int(t.max_raise), hatch_oracle_ratio=t.hatch_oracle_ratio, hatch_period_days=t.hatch_period_days, hatch_exchange_rate=t.hatch_exchange_rate, hatch_tribute_percentage=t.hatch_tribute_percentage, support_required=dandelion.support_required_percentage, minimum_accepted_quorum=dandelion.minimum_accepted_quorum_percentage, vote_buffer_hours=dandelion.vote_buffer_hours, max_wxdai_ratio=int(1125*t.hatch_oracle_ratio), total_votes_per_year=int(24/dandelion.vote_buffer_hours*365), single_tech_mint=float(1/t.hatch_exchange_rate), url=config_file['url']) markdown_panel = pn.pane.Markdown(parameters_data + string_comments_tech + string_comments_dandelion + results_header + string_data + graphical_summary) markdown_panel = pn.pane.Markdown(title + meme_image + graphical_summary + graph_descriptions + simulated_outcomes + string_comments_tech + string_comments_dandelion + results_header + string_data + parameters_data) body = urllib.parse.quote(markdown_panel.object, safe='') url.value = (config_file['repo'] + "/issues/new?title=Vote%20for%20My%20Params&labels=" + config_file['label'] + "&body=" + body) results_button.name = "Update your results" markdown_panel = pn.pane.Markdown(results_header + string_data) return markdown_panel pn.state.onload(update_params_by_url_query) def help_icon(href, text): return """ <style> .tooltip {{ position: relative; display: inline-block; align-self: flex-end; }} .tooltip .tooltiptext {{ visibility: hidden; width: 200px; background-color: #555; color: #fff; text-align: center; border-radius: 6px; padding: 10px; position: absolute; z-index: 1; bottom: 125%; left: 50%; margin-left: -110px; opacity: 0; transition: opacity 0.3s; }} .tooltip .tooltiptext::after {{ content: ""; position: absolute; top: 100%; left: 50%; margin-left: -5px; border-style: solid; border-color: #555 transparent transparent transparent; }} .tooltip:hover .tooltiptext {{ visibility: visible; opacity: 1; }} .icon {{ width: 24px; height: 24px; }} .flex {{ height: 100%; display: flex; justify-content: center; }} </style> <div class="flex"> <div class="tooltip"> <a href="{href}" target="_blank"> <img class="icon" src="http://cdn.onlinewebfonts.com/svg/img_295214.png" /> </a> <span class="tooltiptext">{text}</span> </div> </div> """.format(href=href, text=text) def param_with_tooltip(param, tooltip, height=50): return pn.Row(pn.Column(param, sizing_mode="stretch_width"), pn.pane.HTML(help_icon(tooltips[tooltip]['href'], tooltips[tooltip]['text']), sizing_mode="fixed", width=30, height=height, align="end")) def run_simulation_dandelion(event): dandelion.param.trigger('action') def run_simulation_impact_hours(event): t.param.trigger('action') def update_results(event): results_button.disabled = True share_button.disabled = True updating_results.value = True share_button.disabled = False results_button.disabled = False updating_results.value = False results_button.on_click(update_results) run_dandelion.on_click(run_simulation_dandelion) run_impact_hours.on_click(run_simulation_impact_hours) # Front-end tmpl = pn.Template(template=template) tmpl.add_variable('app_title', config_file['title']) tmpl.add_panel('B', pn.Column( param_with_tooltip( t.param.min_raise, tooltip='min_raise'), param_with_tooltip( t.param.max_raise, tooltip='max_raise'), param_with_tooltip( t.param.target_raise, tooltip='target_raise'), param_with_tooltip( t.param.impact_hour_rate_at_target_goal, tooltip='impact_hour_rate_at_target_goal'), param_with_tooltip( t.param.maximum_impact_hour_rate, tooltip='maximum_impact_hour_rate', height=40), param_with_tooltip( t.param.hatch_tribute_percentage, tooltip='hatch_tribute_percentage'), param_with_tooltip( t.param.hatch_oracle_ratio, tooltip='hatch_oracle_ratio'), param_with_tooltip( t.param.hatch_period_days, tooltip='hatch_period_days'), param_with_tooltip( t.param.hatch_exchange_rate, tooltip='hatch_exchange_rate'), run_impact_hours )) tmpl.add_panel('C', t.outputs_overview_view) tmpl.add_panel('E', t.payout_view) tmpl.add_panel('D', pn.Column(t.redeemable_plot, t.impact_hours_plot)) tmpl.add_panel('M', t.trigger_unbalanced_parameters) tmpl.add_panel('F', t.pie_charts_view) tmpl.add_panel('V', pn.Column( param_with_tooltip( pn.Column(dandelion.param.support_required_percentage), tooltip='support_required_percentage', height=40), param_with_tooltip( dandelion.param.minimum_accepted_quorum_percentage, tooltip='minimum_accepted_quorum_percentage', height=40), param_with_tooltip( dandelion.param.vote_buffer_hours, tooltip='vote_buffer_hours'), param_with_tooltip( dandelion.param.tollgate_fee_xdai, tooltip='tollgate_fee_xdai'), param_with_tooltip( dandelion.param.vote_duration_days, tooltip='vote_duration_days'), param_with_tooltip( dandelion.param.rage_quit_hours, tooltip='rage_quit_hours'), run_dandelion )) tmpl.add_panel('W', dandelion.vote_pass_view) tmpl.add_panel('G', update_input_output_pane) tmpl.add_panel('R', update_result_score) tmpl.add_panel('CO', pn.Column(comments_tech, comments_dandelion)) tmpl.add_panel('BU', pn.Column(results_button, share_button, url)) tmpl.add_panel('OU', update_output_scenarios) tmpl.servable(title=config_file['title'])
def statuses_panel(self): statuses_table = pn.widgets.DataFrame.from_param(self.param.statuses, width=1300) \ if self.statuses is not None else pn.pane.Alert('No status information available.', alert_type='info') if self.disable_update: buttons = None else: update_btn = pn.widgets.Button.from_param(self.param.update, button_type='primary', width=100) terminate_btn = pn.widgets.Button.from_param( self.param.terminate_btn, button_type='danger', width=100) yes_btn = pn.widgets.Button.from_param(self.param.yes_btn, button_type='danger', width=100) cancel_btn = pn.widgets.Button.from_param(self.param.cancel_btn, button_type='success', width=100) yes_btn.visible = False cancel_btn.visible = False msg = pn.indicators.String( value= 'Are you sure you want to terminate the job. This cannot be undone.', css_classes=['bk', 'alert', 'alert-danger'], default_color='inherit', font_size='inherit', visible=False, ) terminate_confirmation = pn.Column( msg, pn.Row(yes_btn, cancel_btn, margin=20), background='#ffffff', ) args = { 'update_btn': update_btn, 'terminate_btn': terminate_btn, 'statuses_table': statuses_table, 'msg': msg, 'yes_btn': yes_btn, 'cancel_btn': cancel_btn, 'term_col': terminate_confirmation } terminate_code = 'update_btn.disabled=true; terminate_btn.visible=false; ' \ 'msg.visible=true; yes_btn.visible=true; cancel_btn.visible=true; ' \ 'term_col.css_classes=["panel-widget-box"]' cancel_code = 'update_btn.disabled=false; terminate_btn.visible=true; ' \ 'msg.visible=false; yes_btn.visible=false; cancel_btn.visible=false; term_col.css_classes=[]' terminate_btn.js_on_click(args=args, code=terminate_code) cancel_btn.js_on_click(args=args, code=cancel_code) code = 'btn.css_classes.push("pn-loading", "arcs"); btn.properties.css_classes.change.emit(); ' \ 'other_btn.disabled=true; ' \ 'statuses_table.push("pn-loading", "arcs"); statuses_table.properties.css_classes.change.emit();' update_btn.js_on_click( args={ 'btn': update_btn, 'other_btn': terminate_btn, 'statuses_table': statuses_table }, code=code, ) yes_btn.js_on_click( args={ 'btn': terminate_btn, 'other_btn': update_btn, 'statuses_table': statuses_table }, code=code, ) buttons = pn.Row(update_btn, terminate_btn, terminate_confirmation) return pn.Column( statuses_table, buttons, sizing_mode='stretch_width', )
def plot_rgb(dataset, bands=['blue', 'green', 'red'], dims=['x', 'y'], height=700, width=700, clims=None, norm='eq_hist', cmap=['black', 'white'], nodata=1): """Interactive RGB visualization of a xarray time series Description ---------- Takes an xarray time dataset and creates an interactive panel which allows to inspect the different data variables at different time steps Parameters ---------- dataset : xarray.Dataset A multi-dimensional array with x,y and time dimensions and one or more data variables. bands: int, str A list of names defining the data variables used for the red, green and blue band dim : list, str A list containing the names of the x and y dimension. height: int Height of the created plot specified in pixels. width: int Width of the created plot specified in pixels. clims: int,float Min and max data values to use for colormap interpolation. norm : The normalization operation applied before colormapping. Valid options include 'linear', 'log', 'eq_hist', 'cbrt'. cmap : list, str Used for the colormap of single-layer datashader output. nodata: int Value defining the nodata value for the dataset """ pn.extension() list_vars = [] time_list = [] for ts in dataset.time.values: ts = pd.Timestamp(ts).to_pydatetime("%Y-%M-%D") time_list.append(ts) for var in dataset.data_vars: list_vars.append(var) r_select = pn.widgets.Select(name='R', value='red', options=list_vars) g_select = pn.widgets.Select(name='G', value='green', options=list_vars) b_select = pn.widgets.Select(name='B', value='blue', options=list_vars) time_select = pn.widgets.Select(name='Time', value=time_list[0], options=time_list) def combine_bands(r, g, b, time): xs, ys = dataset[r].sel(time=time)[dims[0]], dataset[r].sel( time=time)[dims[1]] r, g, b = [ ds.utils.orient_array(img) for img in (dataset[r].sel(time=time), dataset[g].sel(time=time), dataset[b].sel(time=time)) ] a = (np.where(np.logical_or(np.isnan(r), r <= nodata), 0, 255)).astype(np.uint8) r = (normalize_data(r)).astype(np.uint8) g = (normalize_data(g)).astype(np.uint8) b = (normalize_data(b)).astype(np.uint8) return regrid(hv.RGB( (xs, ys[::-1], r, g, b, a), vdims=list('RGBA'))).redim(x=dims[0], y=dims[1]).opts(width=width, height=height) def on_r_select(event): var = event.obj.value col[-1] = combine_bands(r=r_select.value, b=b_select.value, g=g_select.value, time=time_select.value) def on_b_select(event): var = event.obj.value col[-1] = combine_bands(r=r_select.value, b=b_select.value, g=g_select.value, time=time_select.value) def on_g_select(event): var = event.obj.value col[-1] = combine_bands(r=r_select.value, b=b_select.value, g=g_select.value, time=time_select.value) def on_time_select(event): time = event.obj.value col[-1] = combine_bands(r=r_select.value, b=b_select.value, g=g_select.value, time=time_select.value) r_select.param.watch(on_r_select, parameter_names=['value']) g_select.param.watch(on_r_select, parameter_names=['value']) b_select.param.watch(on_r_select, parameter_names=['value']) time_select.param.watch(on_time_select, parameter_names=['value']) col = pn.Row( pn.Column(pn.WidgetBox(r_select, g_select, b_select, time_select)), combine_bands(r=r_select.value, b=b_select.value, g=g_select.value, time=time_select.value)) return col
def generate_chart(self): self.chart = pn.Column(self.content, sizing_mode="stretch_both")
def __init__(self, cats=None, logo=True): self.source = SourceGUI() self.cat = CatGUI(cats=cats, done_callback=self.done_callback) self.panel = pn.Column(name='GUI', width_policy='max', max_width=MAX_WIDTH) self.visible = True self.logo = logo
def submit_view(self): return pn.Column( self.view, self.action_button, name='Submit', )
from bokeh.models.formatters import DatetimeTickFormatter data = { "x": [ pd.Timestamp("2020-01-01"), pd.Timestamp("2020-01-02"), pd.Timestamp("2020-01-03") ], "y": [2, 4, 5], } XFORMATTER = DatetimeTickFormatter(days=["%m %d, %Y"], hours=["%Y-%m-%d %H:%M"]) s1 = bk.plotting.figure(plot_width=500, plot_height=250, title=None) s1.scatter(source=data) s1.xaxis.formatter = XFORMATTER s2 = bk.plotting.figure(plot_width=500, plot_height=250, title=None, x_range=s1.x_range) s2.vbar( x="x", top="y", bottom=0, source=data, ) s2.xaxis.formatter = XFORMATTER p = bk.layouts.gridplot([[s1], [s2]]) pn.Column(p).servable()
], value='all', ) # - @pn.depends(alpha=alpha_slider.param.value, time=time_slider.param.value, concentration=concentration_slider.param.value) def plot_overlaid_ecdfs_pn(alpha, time, concentration): return plot_overlaid_ecdfs(alpha, time, concentration) widgets = pn.Column(pn.Spacer(width=30), alpha_slider, time_slider, concentration_slider, width=500) panel = pn.Column(plot_overlaid_ecdfs_pn, widgets) panel.save('interactive', embed=True, max_opts=40) def main(): p = plot_overlaid_ecdfs(2, 1 / .005, 'all') bokeh.io.show(p) return True if __name__ == '__main__': main()
def getDebugPanel(self): self.debugPanel = pn.Column(self.param) return self.debugPanel
class Base(object): """ Base class for composable panel objects that make up the GUI. Parameters ---------- children: list of panel objects children that will be used to populate the panel when visible panel: panel layout object instance of a panel layout (row or column) that contains children when visible watchers: list of param watchers watchers that are set on children - cleaned up when visible is set to false. visible: bool whether or not the instance should be visible. When not visible ``panel`` is empty. logo : bool, opt whether to show the intake logo in a panel to the left of the main panel. Default is False """ children = None panel = None watchers = None visible_callback = None logo_panel = pn.Column(pn.pane.PNG(ICONS['logo'], align='center'), margin=(25, 0, 0, 0), width=50) logo = False def __init__(self, visible=True, visible_callback=None, logo=False): self.visible = visible self.visible_callback = visible_callback self.logo = logo @property def panel(self): if not self.logo: return self._panel return pn.Row(self.logo_panel, self._panel, margin=0) @panel.setter def panel(self, panel): self._panel = panel def servable(self, *args, **kwargs): return self.panel.servable(*args, **kwargs) def show(self, *args, **kwargs): return self.panel.show(*args, **kwargs) def __repr__(self): """Print output""" return self.panel.__repr__() def _repr_mimebundle_(self, *args, **kwargs): """Display in a notebook or a server""" try: return self.panel._repr_mimebundle_(*args, **kwargs) except: raise NotImplementedError("Panel does not seem to be set " "up properly") def setup(self): """Should instantiate widgets, set ``children``, and set watchers""" raise NotImplementedError @property def visible(self): """Whether or not the instance should be visible.""" return self._visible @visible.setter def visible(self, visible): """When visible changed, do setup or unwatch and call visible_callback""" self._visible = visible if visible and len(self._panel.objects) == 0: self.setup() self._panel.extend(self.children) elif not visible and len(self._panel.objects) > 0: self.unwatch() self._panel.clear() if self.visible_callback: self.visible_callback(visible) def unwatch(self): """Get rid of any lingering watchers and remove from list""" if self.watchers is not None: unwatched = [] for watcher in self.watchers: watcher.inst.param.unwatch(watcher) unwatched.append(watcher) self.watchers = [w for w in self.watchers if w not in unwatched] def __getstate__(self): """Serialize the current state of the object""" return {'visible': self.visible} def __setstate__(self, state): """Set the current state of the object from the serialized version. Works inplace. See ``__getstate__`` to get serialized version and ``from_state`` to create a new object.""" self.visible = state.get('visible', True) return self @classmethod def from_state(cls, state): """Create a new object from a serialized exising object. Example ------- original = cls() copy = cls.from_state(original.__getstate__()) """ return cls().__setstate__(state)
def serve_dashboard(): dashboard = pn.Column("# My Async Dashboard") return dashboard.servable()
dashboard = build_dashboard_google_trends_btc( price_curve_btc, cumulative_return_curve_btc, google_predicted_positive_return_curve_btc, google_cumulative_return_plot_btc ) # Return the dashboard return dashboard # Make interactive drop-down lists which users can choose a social source and crypto user_input = interact_manual( analyse, Source=['Select Source', 'Elon Musk Tweets', 'Google Trends Data'], Ticker=['Select Ticker', 'Bitcoin', 'Dogecoin'] ) # Make the upper half interface in the app interface = pn.Column( '# SillyCon App', '## Analyse correlations between Social Sources and Crypto Prices', '### Select a Source and Crypto Ticker, then press Run Interact', user_input ) # Launch the app in browser interface.servable() interface.show()
def multiple_choice(param, popup_label=None): """Create a multiple choice widget""" return pn.Column( headline(param.label, popup_label=popup_label), pn.widgets.RadioBoxGroup.from_param(param), )
def _open(self): self.__panel = pn.Column(sizing_mode='stretch_width')
def on_gsr_dataframe_btn(self): if self.gsr_dataframe_btn.clicks == 0: return df = self.robot.get_dataframe(with_geo=True) return pn.Column(self._df(df), sizing_mode='stretch_width')
def panel(self): return pn.Column( pn.panel(self.param, expand_button=False, show_name=False), self.view)
import panel as pn import plotly.express as px data = { "Day": [ "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", ], "Orders": [ 15539, 21345, 18483, 24003, 23489, 24092, 12034, ], } dataframe = pd.DataFrame(data) app = pn.Column( dataframe, sizing_mode="stretch_width", background="gray", ) app.servable()
select_gene = pn.widgets.Select(name='Select gene', options=list(outdict.keys())) select_growth = pn.widgets.Select(name='Select growth', options=list( outdict[select_gene.value].keys())) def plot_infoshift(gene='aphA', growth='arabinose'): plt.clf() plt.cla() s = outdict[gene][growth] colorinputs = np.zeros((160)) for i in range(160): if s[i] < 0: colorinputs[i] = 0.0 else: colorinputs[i] = 1.0 fig, ax = plt.subplots(figsize=(10, 2)) shiftcolors = plt.cm.bwr(colorinputs) s_abs = np.abs(s) ax.bar(range(160), np.abs(s), color=shiftcolors) #fig = plt.bar(range(160),np.abs(s),color=shiftcolors) plt.close(fig) return fig m = pn.interact(plot_infoshift, gene=select_gene, growth=select_growth) mout = pn.Row(pn.Column(m[0]), pn.Column(m[1])).servable() mout.save('/home/bill/test.html')
# + artists_points = create_artists_points(artists) albums_points = create_albums_points(x=x_select.value, y=y_select.value, color=color_select.value, data=albums) layout = pn.Column(pn.Row( pn.Column( pn.Pane(title, width=400), pn.Pane(instruction, width=400), ), pn.Pane(artists_points), ), pn.Row( pn.Column( decade_box, axes_box, width=400, ), pn.Pane(albums_points), ), width_policy="max", height_policy="max") # - # ### Interactivity and selections # +
def data_explorer_app(doc): tmpl = pn.Template('') # Load the modules we want. obs_explorer = ObservationsExplorer(name='Search Observations') stats = Stats(name='Overall Stats') def _stat_card(label, value): return pn.pane.HTML(f''' <div class="card"> <div class="card-body"> <h1><span class="badge badge-info">{value}</span></h1> <h3>{label}</h3> </div> </div> ''') stats_row = pn.Row( pn.Column( pn.Row( _stat_card('Hours Exptime', int(stats.df['Total Hours'].sum())), _stat_card('Total Images', int(stats.df['Images'].sum())), ), pn.Row( _stat_card('Observations', int(stats.df['Observations'].sum())), _stat_card('Contributing Units', len(stats.df['Unit'].unique())), )), stats.widget_box, stats.plot, sizing_mode='stretch_both', ) obs_widget_box = pn.WidgetBox(pn.Param( obs_explorer.param, widgets={ 'unit_id': pn.widgets.MultiChoice, 'search_name': { "type": pn.widgets.TextInput, "placeholder": "Lookup RA/Dec by object name", }, }, disabled=True), sizing_mode='stretch_both', max_width=320) observations_row = pn.Column( pn.panel('#### Observations'), pn.Row( obs_widget_box, obs_explorer.table, pn.Column( obs_explorer.selected_title, obs_explorer.image_preview, # obs_explorer.image_table, obs_explorer.table_download_button, obs_explorer.sources_download_button), sizing_mode='stretch_both', )) main_layout = pn.Column(stats_row, observations_row) tmpl.add_panel('mainArea', main_layout) return tmpl.server_doc(doc=doc)
title='Correlation Histogram') dig_dist_his = hv.Histogram( (dig_dist_edges, dig_dist_freq)).opts(xlabel='Distance', height=300, width=400, title='Distance Histogram') dash = (dig_corr_img + dig_corr_his + dig_dist_img + dig_dist_his).opts( opts.Layout(shared_axes=False)).cols(2) # Dashboard of all plots return dash # Display all digits data plots and widgets # ----------------------------------------- pn.Column(dig_CorrRange, dig_plots) # *** # ## Fashion Data # # The MNIST fashion data is loaded from https://github.com/zalandoresearch/fashion-mnist. The data set consists of a training set of 60,000 images and a test set of 10,000 images. Each image is a 28x28 grayscale image, associated with a label from 10 classes. # * Number of samples: 10,000 (test only) # * Number of features: 784 (28x28) # * Number of groups: 10 # * Pixle value range: 0-255 # # | Label | Description | Number of Samples | # | :---: | :---: | :---: | # | 0 | T-shirt/top | 1000 | # | 1 | Trouser | 1000 | # | 2 | Pullover | 1000 |
def plot_band(dataset, dims=['x', 'y'], height=500, width=500, clims=None, norm='eq_hist', cmap=['black', 'white'], nodata=1): """Interactive visualization of xarray time series Description ---------- Takes an xarray time dataset and creates an interactive panel which allows to inspect the different data variables at different time steps Parameters ---------- dataset : xarray.Dataset A multi-dimensional array with x,y and time dimensions and one or more data variables. dim : list, str A list containing the names of the x and y dimension. height: int Height of the created plot specified in pixels. width: int Width of the created plot specified in pixels. clims: int,float Min and max data values to use for colormap interpolation. norm : The normalization operation applied before colormapping. Valid options include 'linear', 'log', 'eq_hist', 'cbrt'. cmap : list, str Used for the colormap of single-layer datashader output. nodata: int Value defining the nodata value for the dataset """ pn.extension() list_vars = [] time_list = [] for ts in dataset.time.values: ts = pd.Timestamp(ts).to_pydatetime("%Y-%M-%D") time_list.append(ts) for var in dataset.data_vars: list_vars.append(var) bands_select = pn.widgets.Select(name='Band', value=list_vars[0], options=list_vars) time_select = pn.widgets.Select(name='Time', value=time_list[0], options=time_list) def one_band(band, time): xs, ys = dataset[band].sel(time=time)[dims[0]], dataset[band].sel( time=time)[dims[1]] b = ds.utils.orient_array(dataset[band].sel(time=time)) a = (np.where(np.logical_or(np.isnan(b), b <= nodata), 0, 255)).astype(np.uint8) return shade(regrid( hv.RGB((xs, ys[::-1], b, b, b, a), vdims=list('RGBA'))), cmap=cmap, clims=clims, normalization=norm).redim(x=dims[0], y=dims[1]).opts(width=width, height=height) def on_var_select(event): var = event.obj.value col[-1] = one_band(band=bands_select.value, time=time_select.value) print(time=time_select.value) def on_time_select(event): time = event.obj.value col[-1] = one_band(band=bands_select.value, time=time_select.value) print(time_select.value) bands_select.param.watch(on_var_select, parameter_names=['value']) time_select.param.watch(on_time_select, parameter_names=['value']) col = pn.Row(pn.Column(pn.WidgetBox(bands_select, time_select)), one_band(band=bands_select.value, time=time_select.value)) return col
def __init__(self, columns): super().__init__() self.columns = columns self.panel = pn.Column(name='Fields') self._register(None, "changed")
def update_result_score(results_button_on): if results_button_on: t.param.trigger('action') # Update dashboard dandelion.param.trigger('action') data_table = { 'Parameters': [ "Target Goal (wxDai)", "Maximum Goal (wxDai)", "Minimum Goal (wxDai)", "Impact Hour Rate at Target Goal (wxDai/IH)", "Impact Hour Rate at Infinity (wxDai/IH)", "Hatch Membership Ratio (wxDai/CSTK)", "Hatch Period (days)", "Hatch Minting rate (TECH/wxDai)", "Hatch Tribute (%)", "Support Required (%)", "Minimum Quorum (%)", "Vote Duration (days)", "Vote Buffer (hours)", "Ragequit Delay (hours)", "Tollgate Fee (wxDai)"], 'Values': [ int(t.target_raise), int(t.max_raise), int(t.min_raise), t.impact_hour_rate_at_target_goal, t.maximum_impact_hour_rate, t.hatch_oracle_ratio, t.hatch_period_days, t.hatch_exchange_rate, t.hatch_tribute_percentage, dandelion.support_required_percentage, dandelion.minimum_accepted_quorum_percentage, dandelion.vote_duration_days, dandelion.vote_buffer_hours, dandelion.rage_quit_hours, dandelion.tollgate_fee_xdai] } df = pd.DataFrame(data=data_table) # Define output pane output_pane = pn.Row(pn.Column(t.impact_hours_plot, t.redeemable_plot), pn.Column(dandelion.vote_pass_view, t.pie_charts_view)) output_pane.save('output.html') pn.panel(t.output_scenarios_view() .hvplot.table()).save('out_scenarios.html') scenarios = codecs.open("out_scenarios.html", 'r') charts = codecs.open("output.html", 'r') data_charts = { 'html': charts.read(), 'css': ".box { color: white; background-color: #0f79b9; padding: 10px; font-family: Roboto }", 'google_fonts': "Roboto"} data_scenarios = { 'html': scenarios.read(), 'css': ".box { color: white; background-color: #0f79b9; padding: 10px; font-family: Roboto }", 'google_fonts': "Roboto"} charts = requests.post(url=HCTI_API_ENDPOINT, data=data_charts, auth=(HCTI_API_USER_ID, HCTI_API_KEY)) scenarios = requests.post(url=HCTI_API_ENDPOINT, data=data_scenarios, auth=(HCTI_API_USER_ID, HCTI_API_KEY)) # Parameters string url_fork = '{url}?ihminr={ihf_minimum_raise}&tgihr={impact_hour_rate_at_target_goal}&maxihr={maximum_impact_hour_rate}&ihtr={ihf_target_raise}&ihmaxr={ifh_maximum_raise}&hor={hatch_oracle_ratio}&hpd={hatch_period_days}&her={hatch_exchange_rate}&ht={hatch_tribute_percentage}&sr={support_required}&maq={minimum_accepted_quorum}&vdd={vote_duration_days}&vbh={vote_buffer_hours}&rqh={rage_quit_hours}&tfx={tollgate_fee_xdai}"'.format(tollgate_fee_xdai=dandelion.tollgate_fee_xdai, vote_duration_days=dandelion.vote_duration_days, rage_quit_hours=dandelion.rage_quit_hours, ihf_minimum_raise=int(t.min_raise), impact_hour_rate_at_target_goal=t.impact_hour_rate_at_target_goal, maximum_impact_hour_rate=t.maximum_impact_hour_rate, ihf_target_raise=t.target_raise, ifh_maximum_raise=int(t.max_raise), hatch_oracle_ratio=t.hatch_oracle_ratio, hatch_period_days=t.hatch_period_days, hatch_exchange_rate=t.hatch_exchange_rate, hatch_tribute_percentage=t.hatch_tribute_percentage, support_required=dandelion.support_required_percentage, minimum_accepted_quorum=dandelion.minimum_accepted_quorum_percentage, vote_buffer_hours=dandelion.vote_buffer_hours, max_wxdai_ratio=int(1125*t.hatch_oracle_ratio), total_votes_per_year=int(24/dandelion.vote_buffer_hours*365), single_tech_mint=float(1/t.hatch_exchange_rate), url=config_file['url']) # Title title = '## Check out my proposal for the Hatch! <a href="' + url_fork + ' target="_blank">Click here to preload the Hatch Configuration Dashboard with my parameters if you think you can do better</a>.' meme_image = """ ![image](https://i.imgflip.com/57zyrl.jpg) """ graphical_summary = """ # Graphical Summary ![image]({image_charts}) """.format(image_charts=charts.json()['url']) graph_descriptions = """ ## Graph Descriptions - Top Left, **Impact Hour Rate vs wxDai Collected**: The Impact Hour Rate determines the Minting Rate for Builders, making 1 Impact Hour equivalent to sending this amount of wxDai to the Hatch. - Top Right, **Proposal Acceptance Criteria**: Shows the range of possibilities for DAO vote outcomes and whether they succeed or not given the Support Required & Minimum Quorum I chose. - Bottom Left, **Backer's Rage Quit % vs wxDai Collected**: The Backer's Rage Quit % is the percent of wxDai that the Backers sent to the Hatch that would be returned if they decide to Ragequit. - Bottom Right, **Redeem-ability of the DAO's wxDai**: Shows who has rights to the wxDai held by the DAO. All of the DAO's funds are collectively governed but some can be withdrawn if token holders Ragequit. This shows the results of my parameter choices at the 3 different goals. """ simulated_outcomes = """ # Simulated Outcomes ![image]({image_scenarios}) """.format(image_scenarios=scenarios.json()['url']) parameters_data = """ # My Hatch Configuration | Parameter|Value| |:-|-:| |Target Goal (wxDai)|{target_goal:,}| |Maximum Goal (wxDai)|{max_goal:,}| |Minimum Goal (wxDai)|{min_goal:,}| |Impact Hour Rate at Target Goal (wxDai/IH)|{ih_rate_tg_goal:,}| |Impact Hour Rate at Infinity (wxDai/IH)|{ih_rate_infinity:,}| |Hatch Membership Ratio (wxDai/CSTK)|{hatch_membership_ratio:,}| |Hatch Period (days)|{hatch_period_days}| |Hatch Minting rate (TECH/wxDai)|{hatch_minting_rate:,}| |Hatch Tribute (%)|{hatch_tribute}| |Support Required (%)|{support_required}| |Minimum Quorum (%)|{minimum_quorum}| |Vote Duration (days)|{vote_duration_days}| |Vote Buffer (hours)|{vote_buffer_hours}| |Ragequit (hours)|{ragequit}| |Tollgate Fee (wxDai)|{tollgate_fee:,}|</a>""".format(target_goal=t.target_raise, max_goal=t.max_raise, min_goal=t.min_raise, ih_rate_tg_goal=t.impact_hour_rate_at_target_goal, ih_rate_infinity=t.maximum_impact_hour_rate, hatch_membership_ratio=t.hatch_oracle_ratio, hatch_period_days=t.hatch_period_days, hatch_minting_rate=t.hatch_exchange_rate, hatch_tribute=t.hatch_tribute_percentage, support_required=dandelion.support_required_percentage, minimum_quorum=dandelion.minimum_accepted_quorum_percentage, vote_duration_days=dandelion.vote_duration_days, vote_buffer_hours=dandelion.vote_buffer_hours, ragequit=dandelion.rage_quit_hours, tollgate_fee=dandelion.tollgate_fee_xdai) results_header = """ # Summary """ default_comment = "To use the defaults... Technocracy for the win" if not comments_tech.value: print(comments_tech.value) comment_tech = default_comment else: comment_tech = comments_tech.value if not comments_dandelion.value: comment_dandelion = default_comment else: comment_dandelion = comments_dandelion.value string_comments_tech = """ ## Hatch Strategy <p>{comments}</p> """.format(comments=comment_tech) string_comments_dandelion = """ ## DAO Strategy <p>{comments}</p> """.format(comments=comment_dandelion) string_data = """ <h2>Hatch Details</h2> - Trusted Seed members can send wxDai to the Hatch for {hatch_period_days} days. - The target goal will be {ihf_target_raise} wxDai, with a minimum of {ihf_minimum_raise} wxDai necessary for the TEC Hatch DAO to be launched and a cap at {ifh_maximum_raise} wxDai. - Backers will need to send in {single_tech_mint} wxDai to mint 1 TECH. - The membership ratio is set at {hatch_oracle_ratio} wxDai/CSTK, so a Trusted Seed member with the minimum CSTK Score of 1125 CSTK can send up to {max_wxdai_ratio} wxDai to the Hatch. <h2>TEC Hatch DAO Voting Details</h2> - Proposals will be voted on for {vote_duration_days} days. They will require at least {support_required}% support, and a minimum of {minimum_accepted_quorum}% of the TECH Tokens will have to vote yes for a proposal to pass. - TECH token holders will have {rage_quit_hours} hours to exit the DAO if they don't like the result of a vote (as long as they didn't vote yes) before it is executed. - There will be a minimum of {vote_buffer_hours} hours between proposals so people always have time to exit safely if they voted yes on a previous vote, this means we can have at most {total_votes_per_year} votes per year. - To prevent griefing attacks, it will cost {tollgate_fee_xdai} wxDai to make a proposal. If you have Impact Hours, you can see how much money you will get with my configuration <a href="{url}?ihminr={ihf_minimum_raise}&tgihr={impact_hour_rate_at_target_goal}&maxihr={maximum_impact_hour_rate}&ihtr={ihf_target_raise}&ihmaxr={ifh_maximum_raise}&hor={hatch_oracle_ratio}&hpd={hatch_period_days}&her={hatch_exchange_rate}&ht={hatch_tribute_percentage}&sr={support_required}&maq={minimum_accepted_quorum}&vdd={vote_duration_days}&vbh={vote_buffer_hours}&rqh={rage_quit_hours}&tfx={tollgate_fee_xdai}" target="_blank">here, just check out the Impact Hour Results table. """.format(tollgate_fee_xdai=dandelion.tollgate_fee_xdai, vote_duration_days=dandelion.vote_duration_days, rage_quit_hours=dandelion.rage_quit_hours, ihf_minimum_raise=int(t.min_raise), impact_hour_rate_at_target_goal=t.impact_hour_rate_at_target_goal, maximum_impact_hour_rate=t.maximum_impact_hour_rate, ihf_target_raise=t.target_raise, ifh_maximum_raise=int(t.max_raise), hatch_oracle_ratio=t.hatch_oracle_ratio, hatch_period_days=t.hatch_period_days, hatch_exchange_rate=t.hatch_exchange_rate, hatch_tribute_percentage=t.hatch_tribute_percentage, support_required=dandelion.support_required_percentage, minimum_accepted_quorum=dandelion.minimum_accepted_quorum_percentage, vote_buffer_hours=dandelion.vote_buffer_hours, max_wxdai_ratio=int(1125*t.hatch_oracle_ratio), total_votes_per_year=int(24/dandelion.vote_buffer_hours*365), single_tech_mint=float(1/t.hatch_exchange_rate), url=config_file['url']) markdown_panel = pn.pane.Markdown(parameters_data + string_comments_tech + string_comments_dandelion + results_header + string_data + graphical_summary) markdown_panel = pn.pane.Markdown(title + meme_image + graphical_summary + graph_descriptions + simulated_outcomes + string_comments_tech + string_comments_dandelion + results_header + string_data + parameters_data) body = urllib.parse.quote(markdown_panel.object, safe='') url.value = (config_file['repo'] + "/issues/new?title=Vote%20for%20My%20Params&labels=" + config_file['label'] + "&body=" + body) results_button.name = "Update your results" markdown_panel = pn.pane.Markdown(results_header + string_data) return markdown_panel
import panel as pn ABOUT = """\ # About [Panel](https://panel.pyviz.org/) is a powerful framework for building awesome-analytics apps in [Python](https://www.python.org/). The purpose of this app is to test that a **multi-page Dashboard Layout** similar to the [bootstrap dashboard template](https://getbootstrap.com/docs/4.3/examples/dashboard/) from [getboostrap.com](https://getbootstrap.com/) can be implemented in [Panel](https://panel.pyviz.org/). """ IMAGE = "https://getbootstrap.com/docs/4.4/assets/img/examples/dashboard.png" INFO = """\ Navigate to the **Dashboard Page** via the **Sidebar** to see the result. Or Navigate to the **Limitations Page** to learn of some of the limitations of Panel that I've experienced.""" about = pn.layout.Row(pn.pane.Markdown(ABOUT)) image = pn.pane.PNG(IMAGE) info = pn.layout.Row(pn.pane.Markdown( INFO, background="#d1ecf1", )) app = pn.Column( about, image, info, ) app.servable()
def param_with_tooltip(param, tooltip, height=50): return pn.Row(pn.Column(param, sizing_mode="stretch_width"), pn.pane.HTML(help_icon(tooltips[tooltip]['href'], tooltips[tooltip]['text']), sizing_mode="fixed", width=30, height=height, align="end"))
def __init__(self): self.panel = pn.Column(pn.Spacer()) self.dirty = True # don't use kwargs until source is set
bounds=( start, end, ), ) number = param.Number( default=0, bounds=( -5.0, 5.0, ), ) view = pn.Param( CustomExample.param, widgets={ "select_string": pn.widgets.RadioButtonGroup, "date": pn.widgets.DatePicker, "number": pn.widgets.FloatSlider, }, ) app = pn.Column( __doc__, view, pn.pane.Markdown("# Stand Alone Widget"), width=1000, ) app.servable()
chopiness * Chopiness_offset_4SRad, color="green", line_alpha=0.5, legend_label=data.WSPD.name, ) p4.grid.grid_line_alpha = 0.3 p4.xaxis.axis_label = "Date" p4.yaxis.axis_label = '"Chopiness" f(Wave Height, Wave separation, Wind Gusts)' p4.legend.location = "top_left" p4.name = "Solar" button = pn.widgets.Button( name= "Update Data (station updates every 30 min at bottom and top of the hour)") button.on_click(import_data) bar_width = 300 big_bar_width = 3 * bar_width + 40 pn.Column( pn.Tabs(p1, p2, p3, p4), pn.layout.HSpacer(), pn.pane.Markdown('## How safe is it to go out? (based on "chopiness") '), pn.widgets.Progress( active=True, width=big_bar_width, bar_color=bar_color, value=int(curr_chopiness), ), # button, ).servable()