ADE-Explorer-MCP / plotting.py
Jonas
Add error handling and placeholder charts in app.py; implement create_placeholder_chart in plotting.py
2262f59
import plotly.graph_objects as go
import pandas as pd
from typing import Dict, Any, Optional
def create_placeholder_chart(message: str) -> go.Figure:
"""
Creates a placeholder chart with a text message.
Args:
message (str): The message to display on the chart.
Returns:
go.Figure: A Plotly figure object with the message.
"""
fig = go.Figure()
fig.add_annotation(
text=message,
xref="paper",
yref="paper",
showarrow=False,
font=dict(size=16)
)
fig.update_layout(
xaxis=dict(showgrid=False, zeroline=False, visible=False),
yaxis=dict(showgrid=False, zeroline=False, visible=False),
plot_bgcolor="rgba(0,0,0,0)",
paper_bgcolor="rgba(0,0,0,0)",
)
return fig
def create_bar_chart(data: dict, drug_name: str):
"""
Creates a Plotly bar chart from the OpenFDA data.
Args:
data (dict): The data from the OpenFDA client.
drug_name (str): The name of the drug.
Returns:
A Plotly Figure object if data is valid, otherwise None.
"""
if "error" in data or "results" not in data or not data["results"]:
return None
try:
df = pd.DataFrame(data["results"])
df = df.rename(columns={"term": "Adverse Event", "count": "Report Count"})
# Ensure 'Report Count' is numeric
df['Report Count'] = pd.to_numeric(df['Report Count'])
# Sort for better visualization
df = df.sort_values(by="Report Count", ascending=True)
fig = go.Figure(
go.Bar(
x=df["Report Count"],
y=df["Adverse Event"],
orientation='h',
marker=dict(color='skyblue')
)
)
fig.update_layout(
title_text=f"Top Reported Adverse Events for {drug_name.title()}",
xaxis_title="Number of Reports",
yaxis_title="Adverse Event",
yaxis=dict(automargin=True),
height=max(400, len(df) * 30) # Dynamically adjust height
)
return fig
except Exception:
return None
def create_outcome_chart(data: dict, drug_name: str):
"""
Creates a Plotly bar chart for serious outcomes from OpenFDA data.
Args:
data (dict): The data from the OpenFDA client.
drug_name (str): The name of the drug.
Returns:
A Plotly Figure object if data is valid, otherwise None.
"""
if "error" in data or "results" not in data or not data["results"]:
return None
try:
df = pd.DataFrame(data["results"])
df = df.rename(columns={"term": "Serious Outcome", "count": "Report Count"})
df['Report Count'] = pd.to_numeric(df['Report Count'])
df = df.sort_values(by="Report Count", ascending=True)
fig = go.Figure(
go.Bar(
x=df["Report Count"],
y=df["Serious Outcome"],
orientation='h',
marker=dict(color='crimson') # Different color for distinction
)
)
fig.update_layout(
title_text=f"Top Serious Outcomes for {drug_name.title()}",
xaxis_title="Number of Reports",
yaxis_title="Serious Outcome",
yaxis=dict(automargin=True),
height=max(400, len(df) * 40)
)
return fig
except Exception:
return None
def create_time_series_chart(data: dict, drug_name: str, event_name: str, time_aggregation: str = 'Y'):
"""
Creates a Plotly time-series chart from OpenFDA data.
Args:
data (dict): The data from the OpenFDA client.
drug_name (str): The name of the drug.
event_name (str): The name of the adverse event.
time_aggregation (str): The time unit for aggregation ('Y' for year, 'Q' for quarter).
Returns:
A Plotly Figure object if data is valid, otherwise None.
"""
if "error" in data or "results" not in data or not data["results"]:
return None
try:
df = pd.DataFrame(data["results"])
df['time'] = pd.to_datetime(df['time'], format='%Y%m%d')
# Resample data
df = df.set_index('time').resample(time_aggregation)['count'].sum().reset_index()
aggregation_label = "Year" if time_aggregation == 'Y' else "Quarter"
fig = go.Figure(
go.Scatter(
x=df["time"],
y=df["count"],
mode='lines+markers',
line=dict(color='royalblue'),
)
)
fig.update_layout(
title_text=f"Report Trend for {drug_name.title()} and {event_name.title()}",
xaxis_title=f"Report {aggregation_label}",
yaxis_title="Number of Reports",
yaxis=dict(automargin=True),
)
return fig
except Exception as e:
print(f"Error creating time-series chart: {e}")
return None
def create_pie_chart(data: dict, drug_name: str):
"""
Creates a Plotly pie chart for report source breakdown.
Args:
data (dict): The data from the OpenFDA client.
drug_name (str): The name of the drug.
Returns:
A Plotly Figure object if data is valid, otherwise None.
"""
if "error" in data or "results" not in data or not data["results"]:
return None
try:
df = pd.DataFrame(data["results"])
df = df.rename(columns={"term": "Source", "count": "Count"})
fig = go.Figure(
go.Pie(
labels=df["Source"],
values=df["Count"],
hole=.3,
pull=[0.05] * len(df) # Explode slices slightly
)
)
fig.update_layout(
title_text=f"Report Sources for {drug_name.title()}",
showlegend=True
)
return fig
except Exception as e:
print(f"Error creating pie chart: {e}")
return None