Display data from widget

I’m two day’s into Panel and really like some of the examples that I see in galleries. However I think that I must be missing something in how to make panel work as I’m finding it very difficult to do simple things.

What I’m trying to do is create a editable dataframe so that a user can add biometric information and then write this to a db (note, in the example below I’ve change the db insert to a csv dump for this example)

When I dump the CSV I have the correct dates and group names in the data.

My issue is trying to print this information to the dashboard, date_text does not update when I select a date. How would I go about having this update? I’m sure I’m missing something simple

Thanks in advance
Aptperson

Here is my code so far:

from datetime import datetime

import numpy as np
import pandas as pd
import panel as pn

from panel.param import ParamFunction

pn.extension()

from panel.template import DarkTheme

bootstrap = pn.template.MaterialTemplate(title='Athletic Data Innovations Human Activity Classifier', theme=DarkTheme)
# bootstrap = pn.template.BootstrapTemplate(title='Bootstrap Template')

date_picker = pn.widgets.DatePicker(name='Date Picker')
group_name = pn.widgets.TextInput(name='Group name', value='all')

# @pn.depends(30, group_name.param.value)
def user_input_df(NUSERS=30):
    single_user_df = pd.DataFrame({
        'ID': [0],
        'Name': [''],
        'Height (cm)': [0],
        'Weight (kg)': [0],
        'IMU': [0]
    })
    all_users_df = pd.DataFrame(single_user_df.values.repeat(NUSERS, axis=0),
                                columns = single_user_df.columns)

    user_df_format = {
        'Height (cm)': {'type': 'number', 'min': 50, 'max':300, 'step': 1},
        'Weight (kg)': {'type': 'number', 'min': 20, 'max':300, 'step': 1},
        'IMU': {'type': 'select', 'values': [1, 3, 5]},
        'Group': {'type': 'input', 'maxlenght': 10}
    }
    return pn.widgets.Tabulator(all_users_df, editors = user_df_format)
    
    
def write_to_db(event):
    out_df = df_widget._value_param_value
    out_df = out_df.loc[out_df.ID != 0]
    out_df['Group'] = group_name.value
    out_df['date'] = date_picker.value
    if out_df.empty:
        text.value = f'No users submitted, please supply at least one ID'
    else:
        try:
            out_df.to_csv('test.csv')
            text.value = f'Submitted {out_df.shape[0]} users to db'
        except:
            text.value = 'data submittion error'


def insert_multiple_biometrics(conn, all_participants):

    for _, row in all_participants.iterrows():
        biometrics = (row.ID, row['Height (cm)'], row['Weight (kg)'], row.date)
        insert_biometrics(conn, biometrics)


def insert_multiple_participants(conn, all_participants):

    for _, row in all_participants.iterrows():
        participant = (row.ID, row.Name, row.date)
        insert_participant(conn, participant)


text = pn.widgets.TextInput(value='Waiting for data to submit')
date_text = pn.widgets.TextInput(value = str(date_picker.value))
    
submit_button = pn.widgets.Button(name='Sumbit users')
submit_button.on_click(write_to_db)

df_widget = ParamFunction.eval(user_input_df)

bootstrap.sidebar.append(date_picker)
bootstrap.sidebar.append(date_text)

panel_layout = pn.Column(pn.Row(group_name, pn.Column(submit_button, text)), df_widget)

bootstrap.main.append(pn.Row(panel_layout))
bootstrap.show()

Hi @aptperson .

It looks like you have already come a long way. Congrats.

If you are asking how you can update the date_text widget from the date_picker widget (?), then you can do that by adding

@pn.depends(date=date_picker, watch=True)
def update_date_text(date):
    date_text.value = str(date)

the working example

from datetime import datetime

import numpy as np
import pandas as pd
import panel as pn

from panel.param import ParamFunction

pn.extension()

from panel.template import DarkTheme

bootstrap = pn.template.MaterialTemplate(title='Athletic Data Innovations Human Activity Classifier', theme=DarkTheme)
# bootstrap = pn.template.BootstrapTemplate(title='Bootstrap Template')

date_picker = pn.widgets.DatePicker(name='Date Picker')
group_name = pn.widgets.TextInput(name='Group name', value='all')

# @pn.depends(30, group_name.param.value)
def user_input_df(NUSERS=30):
    single_user_df = pd.DataFrame({
        'ID': [0],
        'Name': [''],
        'Height (cm)': [0],
        'Weight (kg)': [0],
        'IMU': [0]
    })
    all_users_df = pd.DataFrame(single_user_df.values.repeat(NUSERS, axis=0),
                                columns = single_user_df.columns)

    user_df_format = {
        'Height (cm)': {'type': 'number', 'min': 50, 'max':300, 'step': 1},
        'Weight (kg)': {'type': 'number', 'min': 20, 'max':300, 'step': 1},
        'IMU': {'type': 'select', 'values': [1, 3, 5]},
        'Group': {'type': 'input', 'maxlenght': 10}
    }
    return pn.widgets.Tabulator(all_users_df, editors = user_df_format)


def write_to_db(event):
    out_df = df_widget._value_param_value
    out_df = out_df.loc[out_df.ID != 0]
    out_df['Group'] = group_name.value
    out_df['date'] = date_picker.value
    if out_df.empty:
        text.value = f'No users submitted, please supply at least one ID'
    else:
        try:
            out_df.to_csv('test.csv')
            text.value = f'Submitted {out_df.shape[0]} users to db'
        except:
            text.value = 'data submittion error'


def insert_multiple_biometrics(conn, all_participants):

    for _, row in all_participants.iterrows():
        biometrics = (row.ID, row['Height (cm)'], row['Weight (kg)'], row.date)
        insert_biometrics(conn, biometrics)


def insert_multiple_participants(conn, all_participants):

    for _, row in all_participants.iterrows():
        participant = (row.ID, row.Name, row.date)
        insert_participant(conn, participant)


text = pn.widgets.TextInput(value='Waiting for data to submit')
date_text = pn.widgets.TextInput(value = str(date_picker.value))

@pn.depends(date=date_picker, watch=True)
def update_date_text(date):
    date_text.value = str(date)

submit_button = pn.widgets.Button(name='Sumbit users')
submit_button.on_click(write_to_db)

df_widget = ParamFunction.eval(user_input_df)

bootstrap.sidebar.append(date_picker)
bootstrap.sidebar.append(date_text)

panel_layout = pn.Column(pn.Row(group_name, pn.Column(submit_button, text)), df_widget)

bootstrap.main.append(pn.Row(panel_layout))
bootstrap.show()

A few ideas for improvements

  • Try out the FastListTemplate instead of the MaterialTemplate if you want to go for dark theme.
  • change .show to .servable and start your script using panel serve NAME_OF_SCRIPT.py --auto --show during development. It will speed up your development process.
  • add pn.extension(sizing_mode="stretch_width") just below your imports to get something that is nicely stretched and responsive.

Thanks @Marc, I appreciate your help.

Is there a general rule for updating data to display vs how I’m grabbing the value for the data frame?

I.e. previously the data would not update in the display, however I would have the correct date in the data frame. I’m confused as to why the two would be different given that I’m accessing the same value.