1

I am building a chart using Bokeh. I need to create an empty Figure and when the page is loaded, if I click on a button, data is loaded and displayed on the chart.

I wrote this code but it doesn't work.

def _op_produttivitaRidge1day(db, custom_attrs, start_date, end_date, postazione, stazione: str, mongo_coll, hours: list, hours2: list, stazione2: str, stazione3: str, cod_avaria: str):

def crosscorr(datax, datay, lag=0, wrap=False):
    """ Lag-N cross correlation.
    Shifted data filled with NaNs

    Parameters
    ----------
    lag : int, default 0
    datax, datay : pandas.Series objects of equal length
    Returns
    ----------
    crosscorr : float
    """
    if wrap:
        shiftedy = datay.shift(lag)
        shiftedy.iloc[:lag] = datay.iloc[-lag:].values
        return datax.corr(shiftedy)
    else:
        return datax.corr(datay.shift(lag))

# custom data
custom_attrs = {
    "OP30": ["ST7_LETTURA_INI_TRASD", "ST7_LETTURA_TRASD", "ST3_CONT_SCARTI_CONS", "ST4_CONT_SCARTI_CONS",
             "ST7_CONT_SCARTI_CONS"],
    "OP40": ["ST2_VAL_CRIMPATURA", "ST2_VAL_INI_CRIMPATURA", "ST5_CNT_SCARTI_CONS_CHECKER", "ST1_CONT_SCARTI_CONS",
             "ST2_CONT_SCARTI_CONS", "ST5_CONT_SCARTI_CONS"],
    "OP50": ["ST3_CNT_VETRINO_SALD", "ST1_VAL_PRESSIONE", "ST1_VAL_PERDITA", "ST2_CONT_SCARTI_CONS",
             "ST3_CONT_SCARTI_CONS"],
    "OP60": ["ST2_LETTURA_INI_TRASD", "ST3_COUNT_CONTROLLO_VETRINO", "ST4_CONT_FOTO1_COGNEX",
             "ST4_CONT_FOTO2_COGNEX", "ST4_RIPROVE_SCARTO", "ST1_CONT_SCARTI_CONS", "ST2_CONT_SCARTI_CONS",
             "ST3_CONT_SCARTI_CONS", "ST4_CONT_SCARTI_CONS"],
    "OP70": ["ST1_CONT_SCARTI_CONS"],
    "OP80": ["ST1_COUNT_CONTROLLO_VETRINO", "ST1_CONT_SCARTI_CONS", "ST2_CONT_SCARTI_CONS"],
    "OP90": ["ST1_VAL_TRASD_DAMPER", "ST1_VAL_TRASD_INI_DAMPER", "ST1_VAL_TRASD_CUP_INI_DAMPER",
             "ST1_VAL_TRASD_CUP_DAMPER", "ST1_CONT_SCARTI_CONS"],
    "OP100": [],
    "OP110": [],
    "OP120": ["ST1_VAL_MISURA_PISTON", "ST1_VAL_TRASD_INI", "ST1_CONT_SCARTI_CONS"]
}

# Produttività Ridge Graph
# day, hour, number of items produced
attr_name = stazione + "_PZ_IN"
attr_value = "$" + attr_name
c5 = db[mongo_coll].aggregate([
    {"$match": {"$and": [{"Timestamp": {"$gte": start_date}}, {"Timestamp": {"$lte": end_date}}]}},
    # {"$match": {{"$substr": ["$Timestamp" , 0, 10]} : {"$in": days_list}}},
    {"$project": {"DAY": {"$substr": ["$Timestamp", 0, 10]}, "HOUR": {"$substr": ["$Timestamp", 11, 4]},
                  attr_name: 1}},
    {"$group": {"_id": {"DAY": "$DAY", "HOUR": "$HOUR"}, "ITEM_COUNT": {"$sum": attr_value}}},
    {"$project": {"_id": 0, "DAY": "$_id.DAY", "HOUR": "$_id.HOUR", "ITEM_COUNT": 1}},
    {"$sort": {"DAY": 1, "HOUR": 1}}
])
c5_df = pd.DataFrame(list(c5))
days = sorted(c5_df["DAY"].unique())
PR = figure(title="Produzione " + postazione + " " + stazione, y_range=days, plot_width=900, x_range=(-2, 208),
            toolbar_location=None)

bt = Button(
    label="Show data",
    button_type="success",
    width=50
)



def createPR(FIG, rm_num_values):

    c5_df['ITEM_COUNT_RM'] = c5_df.iloc[:, 0].rolling(window=rm_num_values).mean().fillna(0)

    for d in days:
        y = []
        for h in hours:
            try:
                # hf = str(int(h)).zfill(2)
                hf = h
                num_items = (c5_df.loc[c5_df["HOUR"] == hf].loc[c5_df["DAY"] == d].iloc[0]["ITEM_COUNT_RM"]) / 80
                # print(hf,d,num_items)
                if num_items > 1:
                    num_items = 1
            except:
                num_items = 0
            y.append([d, num_items])
        # print(y)
        s5 = ColumnDataSource(data=dict(x=range(146)))
        s5.add(y, d)
        FIG.patch('x', d, source=s5)

    FIG.outline_line_color = None
    FIG.background_fill_color = "#efefef"
    FIG.y_range.range_padding = 0.12

    FIG.xaxis.ticker = FixedTicker(
        ticks=[0, 6, 12, 18, 24, 30, 36, 42, 48, 54, 60, 66, 72, 78, 84, 90, 96, 102, 108, 114, 120, 126, 132, 138])
    FIG.xaxis.major_label_overrides = {0: '0', 6: '1', 12: '2', 18: '3', 24: '4', 30: '5', 36: '6', 42: '7', \
                                       48: '8', 54: '9', 60: '10', 66: '11', 72: '12', 78: '13', 84: '14', 90: '15', \
                                       96: '16', 102: '17', 108: '18', 114: '19', 120: '20', 126: '21', 132: '22',
                                       138: '23'}
    FIG.outline_line_color = background
    FIG.border_fill_color = background
    FIG.background_fill_color = background
    return FIG
#PR = createPR(PR, 3)
bt.on_click(createPR(PR, 3))


return column(bt, PR)
Tony
  • 7,767
  • 2
  • 22
  • 51
bircastri
  • 2,169
  • 13
  • 50
  • 119
  • Your code has a messy layout, is missing the data and is not executable. Is it OK to give you just an example how to create a plot with patches using another data ? – Tony May 26 '21 at 12:50
  • Yes I want a code sample to load data on it. – bircastri May 26 '21 at 14:01

1 Answers1

1

This code was written for Bokeh v2.1.1. Run it with bokeh serve -show main.py.

Replace data = dict(x=[1, 2, 3, 2], y=[6, 7, 2, 2]) with your data acquisition function: data = _op_produttivitaRidge1day(db, custom_attrs, start_date, end_date, ...) Everything should work if your function returns a dictionary with x and y vectors of equal length.

The approach is to first pass an empty data_source to the figure and then after a button click, download the data from your MongoDB and assign it as dictionary to the patch.data_source.data.

main.py:

from bokeh.plotting import curdoc, figure
from bokeh.models import Column, Button

plot = figure()
patch = plot.patch(x=[], y=[])

def callback():
    data = dict(x=[1, 2, 3, 2], y=[6, 7, 2, 2]) # <-- your data acquisition function comes here 
    patch.data_source.data = data

button = Button()
button.on_click(callback)

curdoc().add_root(Column(plot, button))
Tony
  • 7,767
  • 2
  • 22
  • 51
  • i must load data source from database after click on button. In you case I need to load data before render chart. I need a code to load data from database after click on button – bircastri May 27 '21 at 06:49