adding a local html file into a Div in plotly/dash - html

I created a Dash app. On one tab I have a dropdown and a submit button. In a callback I generate an html file, saved locally, based on quantstats library (reports.html)
I am trying to producing this html within an html.Div but no success so far. All I managed to do is to print out an hyperlink to my local file but not the file itself.
Here is the layout part:
layout = html.Div([
dbc.Container([
dbc.Row([
dbc.Col(html.H1("Reports", className="text-center"), className="mb-5 mt-5")
]),
dbc.Row([
dbc.Col(dcc.Dropdown(id='reports_type',
options=[
{'label': 'YTD', 'value': 1},
{'label': 'ITD', 'value': 2},
],
value=1,
style={'display': 'block'},
)),
dbc.Col(html.Button('Run report', id='reports_submit')),
])
]),
html.Div(id='reports_holder')
])
Here is the callback:
#app.callback(
Output('reports_holder', 'children'),
[
Input('reports_submit', 'n_clicks')
],
[
State('reports_type', 'value')
],
prevent_initial_call=True
)
def produce_report(n_clicks, reports_type):
if n_clicks:
df = some dataframe
if reports_type == 1: #YTD
current_df = df[df.index.year == datetime.date.today().year]
my_pfo = pd.Series(current_df['Close'].values, name='Close', index=current_df.index)
qs.reports.html(my_pfo, "SPY", output='quantstats-tearsheet.html', title='YTD Tearsheet')
else: #ITD
my_pfo = pd.Series(df['Close'].values, name='Close', index=df.index)
qs.reports.html(my_pfo, "SPY", output='quantstats-tearsheet.html', title='ITD Tearsheet')
f = codecs.open('quantstats-tearsheet.html', 'r')
return f
Here is my latest try using the codecs library (this creates an error because the html documents cannot be JSON serializable). If I return f.read() instead then this is not html formated.
As said before I tried html.A instead of html.Div in my layout but this produces only an hyperlink (as expected with html.A). Should I use the property target with html.A but then how do I sepcify that the document should be opened in that same html.A? There must be a straightforward solution to this but I can't find it (most solutions involve opening a local html file into a new browser tab...)
Edit: here is an example of the html report generated via quantstats

Related

How can I have my dash app comment list all the previously inputted comments?

I am trying to create a comment section in my dash app where the comments submitted will be updated as new comments are submitted.I tried different ways but it wasn't working.. this is the current code I have now which is able to return the most recent comment submitted.
layout = html.Div([
html.H3(children='Write Comments'),
dcc.Textarea(
id='textarea',
value='',
style={'width': '100%', 'height': 200},
),
html.Button('Submit', id='button', n_clicks=0),
html.Div(id='comment-output', style={'whiteSpace': 'pre-line'})
])
# Submit comment through pushing the 'submit' button
#callback(
Output('comment-output', 'children'),
Input('button', 'n_clicks'),
State('textarea', 'value')
)
def update_output(n_clicks, value):
if n_clicks > 0:
return 'Submitted Comment: {}'.format(value)
You have to include the history with the callback and then add to it, otherwise it will just overwrite with the latest. I've tried this locally and it works:
#callback(
Output('comment-output', 'children'),
Input('button', 'n_clicks'),
[
State('textarea', 'value'),
State('comment-output', 'children'),
],
)
def update_output(n_clicks, value, children):
if n_clicks > 0:
return f'{children}\n Submitted Comment: {value}'
else:
return ''

How to connect HTML elements with Dash Callback in Python

I'm using both html elements and dash bootstrap components in my code and wonder if I can connect an HTML component with a Dash component in callback. For example, I have a dash dropdown menu and want to update the html text based on the input of the dropdown menu.
#dropdown
html.Div =(
[
dcc.Dropdown(
id="dropdown",
options=[
{"label": "option1", "value": "option1"},
{"label": "option2", "value": "option2"},
],
multi=True,
)
]
)
# HTML Components
html.Div =(
[
html.H2("The selected option is")
html.P(id="text-holder", children =["text"])
]
)
#app.callback(
Output("text-holder", "children"),
Input("dropdown", "value)
)
def fill_text(value):
return value
Once a user selects a value from the dropdown menu, I want the selected value to appear on the text line created by html.P. For example, if "option1" is selected from the dropdown menu, the text that appears on the HTML part should be also "option1".
If I run the current script, I don't get any error message but the html part doesn't get updated at all. I think the callback is incorrect but am not sure how to fix it.
Using html.Div =( ... alters the value of html.Div. And it's really important to get the layout right.
Perhaps this is what you're looking for:
from dash import dcc, html, Dash, Output, Input
app = Dash(__name__)
app.layout = html.Div(
[
# dropdown
html.Div(
[
dcc.Dropdown(
id="dropdown",
options=[
{"label": f"option{idx}", "value": f"option{idx}"}
for idx in range(1, 5)
],
multi=True,
value="not specified",
)
]
),
# HTML Components
html.Div([html.H2("The selected option is"), html.P(id="text-holder")]),
]
)
#app.callback(Output("text-holder", "children"), Input("dropdown", "value"))
def fill_text(value):
return value
if __name__ == "__main__":
app.run_server()

Graph not showing

I have the following code
# -*- coding: utf-8 -*-
# # Two Pie Charts
import time
import dash
import dash_bootstrap_components as dbc
import plotly.express as px
import pandas as pd
from dash import Input, Output, dcc, html
# Data treatment
df = pd.read_csv('https://raw.githubusercontent.com/JorgeMiguelGomes/LEG2022_MediaMonitor/main/legislativas_2022_media_monitor_29jan2022/data_products/legislativas_2022_final_dataset_percentages.csv')
df_individuals = pd.read_csv('https://raw.githubusercontent.com/JorgeMiguelGomes/LEG2022_MediaMonitor/main/legislativas_2022_media_monitor_29jan2022/data_products/legislativas_2022_all_candidates_filtered.csv')
df_individuals = df_individuals.drop(columns=["Unnamed: 0"])
df_indivuduals = df_individuals.drop(columns=["Post Created Date"])
df_individuals_melt=pd.melt(df_individuals,id_vars=['candidato','Page Name'])
# Styling
pie_color_map = {
"Angry":"#EB9486",
"Love":"#CAE7B9"
}
app = dash.Dash(external_stylesheets=[dbc.themes.BOOTSTRAP],suppress_callback_exceptions=True,
meta_tags=[{"name": "viewport", "content": "width=device-width, initial-scale=1"}],
)
app.layout = dbc.Container(
[
# First Row
dbc.Row(
[
dbc.Col(html.Hr(style={'borderWidth': "2vh", "width": "100%", "borderColor": "#CAE7B9","opacity": "unset"}),width={'size':2}),
dbc.Col(html.Hr(style={'borderWidth': "2vh", "width": "100%", "borderColor": "#F3DE8A","opacity": "unset"}),width={'size':2}),
dbc.Col(html.Hr(style={'borderWidth': "2vh", "width": "100%", "borderColor": "#EB9486","opacity": "unset"}),width={'size':2}),
dbc.Col(html.Hr(style={'borderWidth': "2vh", "width": "100%", "borderColor": "#7E7F9A","opacity": "unset"}),width={'size':2}),
dbc.Col(html.Hr(style={'borderWidth': "2vh", "width": "100%", "borderColor": "#97A7B3","opacity": "unset"}),width={'size':2}),
],className="g-0",
), # end of first row
dbc.Tabs(
[
dbc.Tab(label="About", tab_id="method", label_style={"color": "#CAE7B9"},tab_style={'background-color': '#97A7B3'},active_label_style={"background-color":"#080808"}),
dbc.Tab(label="Metrics by Totals", tab_id="totals", label_style={"color": "#F3DE8A"},tab_style={'background-color': '#7E7F9A'}, active_label_style={"background-color":"#080808"}),
dbc.Tab(label="Stacked Analysis", tab_id="stacked", label_style={"color": "#EB9486"},tab_style={'background-color': '#F3DE8A'}, active_label_style={"background-color":"#080808"}),
dbc.Tab(label="Love vs Angry", tab_id="love_angry", label_style={"color": "#7E7F9A"},tab_style={'background-color': '#EB9486'}, active_label_style={"background-color":"#080808"}),
dbc.Tab(label="Conclusions", tab_id="conclusions", label_style={"color": "#97A7B3"},tab_style={'background-color': '#F3DE8A'}, active_label_style={"background-color":"#080808"}),
],
id="tabs",
active_tab="love_angry", # this is the tab that will be active when the user comes to the website
), # end of tabs
html.Div(id="tab-content", className="p-5"),
]
)
# Callbacks
# Pie Chart for Candidates
# #app.callback(
# Output(component_id='graph_individuals', component_property='figure'),
# [Input(component_id='dropdown_candidates', component_property='value')],
# )
# def build_graph_individuals(column_chosen):
# dff = df
# totals_sentiment = dff.groupby(['candidato'])[['Love','Angry']].sum().reset_index()
# totals_sentiment_melt = pd.melt(totals_sentiment,id_vars="candidato")
# totals_sentiment_melt = totals_sentiment_melt[totals_sentiment_melt['candidato'] == column_chosen]
# fig_individuals = px.pie(totals_sentiment_melt,names="variable",values="value",hole=0.5, color="variable",color_discrete_map=pie_color_map)
# candidato_filter = column_chosen
# return fig_individuals
# Pie Chart for Media Outlets
#app.callback(
Output(component_id='graph_shares_comments', component_property='figure'),
Output(component_id='graph_individuals', component_property='figure'),
Input(component_id='dropdown_media_outlet', component_property='value'),
Input(component_id='dropdown_candidates', component_property='value')
)
def build_graphs(column_chosen, candidato_filter):
# Data Treatment for candidate graph
dff = df
totals_sentiment = dff.groupby(['candidato'])[['Love','Angry']].sum().reset_index()
totals_sentiment_melt = pd.melt(totals_sentiment,id_vars="candidato")
totals_sentiment_melt = totals_sentiment_melt[totals_sentiment_melt['candidato'] == column_chosen]
# Data Treatment for media graph
dff_m = df[df['candidato']== candidato_filter]
print(dff_m)
totals_sentiment_media = dff_m.groupby(['Page Name'])[['Love','Angry']].sum().reset_index()
totals_sentiment_media_melt = pd.melt(totals_sentiment_media,id_vars="Page Name")
totals_sentiment_media_melt = totals_sentiment_media_melt[totals_sentiment_media_melt['Page Name'] == column_chosen]
print("HELLO HELLO")
print(totals_sentiment_media_melt)
# Pice Charts
fig_candidates = px.pie(totals_sentiment_melt,names="variable",values="value",hole=0.5, color="variable",color_discrete_map=pie_color_map)
fig_media = px.pie(totals_sentiment_media_melt,names="variable",values="value",hole=0.6, color="variable",color_discrete_map=pie_color_map)
return fig_candidates, fig_media
# TABS CALLBACKS -------------------------------------
#app.callback(Output("tab-content", "children"),
[Input("tabs", "active_tab")])
def switch_tab(at):
if at == "love_angry":
tab4_content = dbc.Row(
[
dbc.Col(
[
dcc.Dropdown(
id='dropdown_candidates',
options=[{'label': i, 'value': i} for i in df_individuals_melt.candidato.unique()
],
optionHeight=35, #height/space between dropdown options
value='António Costa', #dropdown value selected automatically when page loads
disabled=False, #disable dropdown value selection
multi=False, #allow multiple dropdown values to be selected
searchable=True, #allow user-searching of dropdown values
search_value='', #remembers the value searched in dropdown
placeholder='Please select...', #gray, default text shown when no option is selected
clearable=True, #allow user to removes the selected value
style={'width':"100%"}, #use dictionary to define CSS styles of your dropdown
# className='select_box', #activate separate CSS document in assets folder
# persistence=True, #remembers dropdown value. Used with persistence_type
# persistence_type='memory' #remembers dropdown value selected until...
),
dbc.Col(
dcc.Graph(id='graph_individuals'),
),
],width={'size':6, 'offset':0}
),
dbc.Col(
[
dcc.Dropdown(
id='dropdown_media_outlet',
options=[{'label': i, 'value': i} for i in df['Page Name'].unique()
],
optionHeight=35, #height/space between dropdown options
value='Agência Lusa', #dropdown value selected automatically when page loads
disabled=False, #disable dropdown value selection
multi=False, #allow multiple dropdown values to be selected
searchable=True, #allow user-searching of dropdown values
search_value='', #remembers the value searched in dropdown
placeholder='Please select...', #gray, default text shown when no option is selected
clearable=True, #allow user to removes the selected value
style={'width':"100%"}, #use dictionary to define CSS styles of your dropdown
# className='select_box', #activate separate CSS document in assets folder
# persistence=True, #remembers dropdown value. Used with persistence_type
# persistence_type='memory' #remembers dropdown value selected until...
),
dbc.Col(
dcc.Graph(id='graph_shares_comments'),
),
],width={'size':6, 'offset':0}
),
],
),
return tab4_content
# Error Message
return html.P("FOR SUPPORT PURPOSES ONLY")
if __name__ == "__main__":
app.run_server(debug=True, port=8888)
The code is running without errors but as you can see in the image below, the chart on the left side is not rendering, and I'm totally lost.
I have inserted a print command in the script, and when I change the dropdowns the values change accordingly as they should.
However the pie chart remains empty, like it's not getting any information.
Maybe I've been looking at the same code for more hours than I should, and I'm missing something really simple, but I just can't spot it.
Any help would be really appreciated.
Disclosure This is not a commercial project nor will I use it in any commercial way.
You were filtering with the wrong keyword for totals_sentiment_melt, use this to correct it:
totals_sentiment_melt = totals_sentiment_melt[totals_sentiment_melt['candidato'] == candidato_filter]

dash Dropdown provides either string or list depending on number of selections

I'm currently working on a stock analysis tool utilizing dash. I have a dropdown populated with the NASDAQ 100 symbols and am attempting to get it to return a line graph with a line for each symbol selected.
With the dropdown, if I have one symbol selected the returned value is a string, if I select multiple it's then a list.
I'm trying to use a callback such as:
#app.callback(
Output(component_id='stock-graph-line', component_property='figure'),
Input(component_id='stock-input', component_property='value'),
suppress_callback_exceptions = True
)
def update_stock_symbol(input_value):
for i in input_value:
fig.append_trace({'x':df.index,'y':df[([i], 'close')], 'type':'scatter','name':'Price [Close]'},1,1)
fig['layout'].update(height=1000, title=input_value, template="plotly_dark")
return fig
However, the for loop does not work with only one symbol selected as it's getting a string, not a list. Is there an option in dash to specify the return type of the callbacks? (Can I force it to pass on the one symbol as a list item?) Or does this have to be handled with if statements testing the type?
I set up a dropdown and it is always returning either None or a list:
dcc.Dropdown(
id='dropdown-id',
options=[
{'label': 'a', 'value': 'a'},
{'label': 'b', 'value': 'b'},
{'label': 'c', 'value': 'c'},
{'label': 'd', 'value': 'd'},
{'label': 'e', 'value': 'e'},
],
multi=True
),
Perhaps yours is set up differently. If that won't work, then just check like this:
def update_stock_symbol(input_value):
if isinstance(input_value, str):
input_value = [input_value]
for i in input_value:
...

How to unpickle inferSent and load model?

I had a working code that simply loads the infersent model. Now, it wont unpickle the model
MODEL_PATH = "./encoder/infersent1.pkl"
params_model = {'bsize': 64, 'word_emb_dim': 300, 'enc_lstm_dim': 2048,
'pool_type': 'max', 'dpout_model': 0.0, 'version':
model_version}
inferSent = InferSent(params_model)
print(MODEL_PATH)
inferSent.load_state_dict(torch.load(MODEL_PATH))
use_cuda = False
inferSent = inferSent.cuda() if use_cuda else inferSent
# If infersent1 -> use GloVe embeddings. If infersent2 -> use InferSent
embeddings.
W2V_PATH = './dataset/GloVe/glove.840B.300d.txt' if model_version == 1 else
'../dataset/fastText/crawl-300d-2M.vec'
inferSent.set_w2v_path(W2V_PATH)
UnpicklingError: invalid load key, '<'.
The reason of this problem is that your pickle file has not been downloaded properly.
Check the size of your file, it should be around 160 MB. For some reason, the links in the infersent repo don't work. You can build your own NLI model using the train_nli.py script provided in the repository.
python train_nli.py --word_emb_path 'Your word embedding(for example GloVe/fastText)'