I've tried javascript code, but I'm not familiar with JS and the filtering is not working properly. fig.write_html doesn't work because the checkboxes will not show up.
For context, I have 2 main traces on my graph, go.Scatter and px.timeline. The checkbox will filter which medications show up on the y-axis, and remove/add the scatter points and horizontal bars accordingly.
server = Flask(__name__)
app = Dash(__name__, server = server)
ipharm_meds = list(ipharm['meds'].unique())
eimr_meds = list(eimr['meds'].unique())
unique_meds = list(set(ipharm_meds + eimr_meds))
'''
wrapping text so that it can appear nicely on graph on hover
need to play with width value according to the length of text
'''
wrapper = textwrap.TextWrapper(width = 100)
notes['summary'] = notes['summary'].apply(lambda x: wrapper.fill(x))
notes['summary'] = notes['summary'].apply(lambda x: x.replace('\n', '<br>'))
app.layout = html.Div([
html.Div([
dcc.Checklist(
id = 'med-checklist',
options = [{'label': med, 'value': med} for med in unique_meds],
value = unique_meds,
inline = True
),
], style = {'width': '100%', 'padding': '10px'}),
dcc.Graph(id = 'timeline-graph')
])
@app.callback(
Output('timeline-graph', 'figure'),
Input('med-checklist', 'value')
)
def update_graph(selected_meds):
# filtered based on checkbox values
ipharm_filtered = ipharm[ipharm['meds'].isin(selected_meds)]
ipharm_filtered['Start'] = pd.to_datetime(ipharm_filtered['Start'])
ipharm_filtered['End'] = pd.to_datetime(ipharm_filtered['End'])
ipharm_filtered['Start_str'] = ipharm_filtered['Start'].dt.strftime("%d-%m-%Y")
ipharm_filtered['End_str'] = ipharm_filtered['End'].dt.strftime("%d-%m-%Y")
# broken barh for ipharm
fig = px.timeline(
ipharm_filtered,
x_start = 'Start',
x_end = 'End',
y = 'meds',
hover_data = {'Start': False,
'End': False,
'Start_str': True,
'End_str': True,
'FREQUENCY': True,
'DOSAGE INSTRUCTION': True,
'dose': True}
)
# Add scatter for eimr
for med in selected_meds:
med_data = eimr[eimr['meds'] == med]
if not med_data.empty:
fig.add_trace(go.Scatter(
x=med_data['ServingDateTime'],
y=[med] * len(med_data),
mode='markers',
marker=dict(size=5, color = 'red'),
name=f'eIMR_{med}',
text=med_data['Dose'],
hoverinfo='text',
showlegend=False
)
)
# Add shaded regions for ward duration
for _, row in ward.iterrows():
fig.add_vrect(
x0=row['Adm.Date'],
x1=row['Disch.Date'],
fillcolor='grey',
opacity=0.5,
line_width=0
)
# Add vertical lines for consults
for _, row in notes.iterrows():
fig.add_shape(
type = 'line',
x0 = row['Date'],
x1 = row['Date'],
y0 = 0,
y1 = 1,
yref = 'paper',
line = dict(color = 'black', width = 1)
)
# Add scatter points vertically on every vline
# for hover functionality
for med in selected_meds:
fig.add_trace(go.Scatter(
x = [row['Date']],
y = [med],
opacity = 0, # make points invisible
mode = 'markers',
marker = dict(size = 5, color = 'black'),
text = row['summary'],
hoverinfo = 'text',
showlegend=False
))
# Update layout
fig.update_layout(
xaxis=dict(showgrid=True),
yaxis=dict(showgrid=True)
)
return fig
def save_html():
# Create the initial figure with all medications
initial_fig = update_graph(unique_meds)
# Create JavaScript function for checkbox interactivity
checkbox_js = """
<script>
function updateVisibility() {
var checkboxes = document.getElementsByClassName('med-checkbox');
var gd = document.getElementById('timeline-graph');
var traces = gd.data;
var selectedMeds = Array.from(checkboxes)
.filter(cb => cb.checked)
.map(cb => cb.value);
var visibility = traces.map(trace => {
if (trace.y && trace.y.length > 0) {
return selectedMeds.includes(trace.y[0]) ||
selectedMeds.includes(trace.name?.replace('eIMR_', ''));
}
return false;
});
Plotly.update('timeline-graph',
{visible: visibility},
{height: selectedMeds.length * 40},
);
}
window.addEventListener('load', function() {
var gd = document.getElementById('timeline-graph');
window.originalData = JSON.parse(JSON.stringify(gd.data));
});
</script>
"""
Create HTML string with checkboxes
checkbox_html = """
<div style="width:100%; padding:10px">
"""
for med in unique_meds:
checkbox_html += f"""
<label style="margin-right:10px">
<input type="checkbox" class="med-checkbox" value="{med}"
checked onclick="updateVisibility()">
{med}
</label>
"""
checkbox_html += "</div>"
# Convert figure to HTML
fig_html = initial_fig.to_html(
full_html=False,
include_plotlyjs=True,
div_id='timeline-graph'
)
# Combine everything
full_html = f"""
<html>
<head>
<title>Medication Timeline</title>
{checkbox_js}
</head>
<body>
{checkbox_html}
{fig_html}
</body>
</html>
"""
with open('graph_v1.html', 'w', encoding = 'utf-8') as f:
f.write(full_html)
if __name__ == "__main__":
save_html()
I've tried javascript code, but I'm not familiar with JS and the filtering is not working properly. fig.write_html doesn't work because the checkboxes will not show up.
For context, I have 2 main traces on my graph, go.Scatter and px.timeline. The checkbox will filter which medications show up on the y-axis, and remove/add the scatter points and horizontal bars accordingly.
server = Flask(__name__)
app = Dash(__name__, server = server)
ipharm_meds = list(ipharm['meds'].unique())
eimr_meds = list(eimr['meds'].unique())
unique_meds = list(set(ipharm_meds + eimr_meds))
'''
wrapping text so that it can appear nicely on graph on hover
need to play with width value according to the length of text
'''
wrapper = textwrap.TextWrapper(width = 100)
notes['summary'] = notes['summary'].apply(lambda x: wrapper.fill(x))
notes['summary'] = notes['summary'].apply(lambda x: x.replace('\n', '<br>'))
app.layout = html.Div([
html.Div([
dcc.Checklist(
id = 'med-checklist',
options = [{'label': med, 'value': med} for med in unique_meds],
value = unique_meds,
inline = True
),
], style = {'width': '100%', 'padding': '10px'}),
dcc.Graph(id = 'timeline-graph')
])
@app.callback(
Output('timeline-graph', 'figure'),
Input('med-checklist', 'value')
)
def update_graph(selected_meds):
# filtered based on checkbox values
ipharm_filtered = ipharm[ipharm['meds'].isin(selected_meds)]
ipharm_filtered['Start'] = pd.to_datetime(ipharm_filtered['Start'])
ipharm_filtered['End'] = pd.to_datetime(ipharm_filtered['End'])
ipharm_filtered['Start_str'] = ipharm_filtered['Start'].dt.strftime("%d-%m-%Y")
ipharm_filtered['End_str'] = ipharm_filtered['End'].dt.strftime("%d-%m-%Y")
# broken barh for ipharm
fig = px.timeline(
ipharm_filtered,
x_start = 'Start',
x_end = 'End',
y = 'meds',
hover_data = {'Start': False,
'End': False,
'Start_str': True,
'End_str': True,
'FREQUENCY': True,
'DOSAGE INSTRUCTION': True,
'dose': True}
)
# Add scatter for eimr
for med in selected_meds:
med_data = eimr[eimr['meds'] == med]
if not med_data.empty:
fig.add_trace(go.Scatter(
x=med_data['ServingDateTime'],
y=[med] * len(med_data),
mode='markers',
marker=dict(size=5, color = 'red'),
name=f'eIMR_{med}',
text=med_data['Dose'],
hoverinfo='text',
showlegend=False
)
)
# Add shaded regions for ward duration
for _, row in ward.iterrows():
fig.add_vrect(
x0=row['Adm.Date'],
x1=row['Disch.Date'],
fillcolor='grey',
opacity=0.5,
line_width=0
)
# Add vertical lines for consults
for _, row in notes.iterrows():
fig.add_shape(
type = 'line',
x0 = row['Date'],
x1 = row['Date'],
y0 = 0,
y1 = 1,
yref = 'paper',
line = dict(color = 'black', width = 1)
)
# Add scatter points vertically on every vline
# for hover functionality
for med in selected_meds:
fig.add_trace(go.Scatter(
x = [row['Date']],
y = [med],
opacity = 0, # make points invisible
mode = 'markers',
marker = dict(size = 5, color = 'black'),
text = row['summary'],
hoverinfo = 'text',
showlegend=False
))
# Update layout
fig.update_layout(
xaxis=dict(showgrid=True),
yaxis=dict(showgrid=True)
)
return fig
def save_html():
# Create the initial figure with all medications
initial_fig = update_graph(unique_meds)
# Create JavaScript function for checkbox interactivity
checkbox_js = """
<script>
function updateVisibility() {
var checkboxes = document.getElementsByClassName('med-checkbox');
var gd = document.getElementById('timeline-graph');
var traces = gd.data;
var selectedMeds = Array.from(checkboxes)
.filter(cb => cb.checked)
.map(cb => cb.value);
var visibility = traces.map(trace => {
if (trace.y && trace.y.length > 0) {
return selectedMeds.includes(trace.y[0]) ||
selectedMeds.includes(trace.name?.replace('eIMR_', ''));
}
return false;
});
Plotly.update('timeline-graph',
{visible: visibility},
{height: selectedMeds.length * 40},
);
}
window.addEventListener('load', function() {
var gd = document.getElementById('timeline-graph');
window.originalData = JSON.parse(JSON.stringify(gd.data));
});
</script>
"""
Create HTML string with checkboxes
checkbox_html = """
<div style="width:100%; padding:10px">
"""
for med in unique_meds:
checkbox_html += f"""
<label style="margin-right:10px">
<input type="checkbox" class="med-checkbox" value="{med}"
checked onclick="updateVisibility()">
{med}
</label>
"""
checkbox_html += "</div>"
# Convert figure to HTML
fig_html = initial_fig.to_html(
full_html=False,
include_plotlyjs=True,
div_id='timeline-graph'
)
# Combine everything
full_html = f"""
<html>
<head>
<title>Medication Timeline</title>
{checkbox_js}
</head>
<body>
{checkbox_html}
{fig_html}
</body>
</html>
"""
with open('graph_v1.html', 'w', encoding = 'utf-8') as f:
f.write(full_html)
if __name__ == "__main__":
save_html()
Share
Improve this question
edited Mar 6 at 3:36
Noel Teo
asked Mar 6 at 3:32
Noel TeoNoel Teo
32 bronze badges
1 Answer
Reset to default 0The callbacks rely on a flask server backend which means you won't be able to save anything besides the initial state of your app.
Credit goes to this answer by @Emil on the plotly community form.
发布者:admin,转转请注明出处:http://www.yc00.com/questions/1744997916a4605307.html
评论列表(0条)