Justify / figure.py
dzs
added quick start guide
e743fc5
import plotly.graph_objects as go
import pandas as pd
import numpy as np
def build_figure(dataframe: pd.DataFrame) -> go.Figure:
fig = go.Figure()
# Condition 1
fig.add_bar(
y=dataframe["Condition 1"],
x=dataframe["CASRN"],
name="Condition 1",
orientation="v",
error_y=dict(
type="data",
symmetric=False,
array=dataframe["Cond1_err_plus"], # +x direction
arrayminus=dataframe["Cond1_err_minus"], # -x direction
visible=True,
),
marker=dict(color="red"),
)
# Condition 2
fig.add_bar(
y=dataframe["Condition 2"],
x=dataframe["CASRN"],
name="Condition 2",
orientation="v",
error_y=dict(
type="data",
symmetric=False,
array=dataframe["Cond2_err_plus"],
arrayminus=dataframe["Cond2_err_minus"],
visible=True,
),
marker=dict(color="blue"),
)
#fig.add_hline(
# y=0.9,
# line_width=3,
# line_color="green",
# line_dash="longdash"
#)
# --- Compute data-driven x-range (include error bars) ---
x1 = dataframe["Condition 1"].to_numpy(dtype=float)
x2 = dataframe["Condition 2"].to_numpy(dtype=float)
# --- Compute upper bounds including error bars ---
x1_max = x1 - dataframe["Cond1_err_minus"].to_numpy(dtype=float)
x2_max = x2 - dataframe["Cond2_err_minus"].to_numpy(dtype=float)
# Piecewise maxima across the two conditions (array length = number of CASRN)
piecewise_max = np.maximum(x1_max, x2_max)
# Minimum of the piecewise maxima array (ignoring NaNs)
min_of_piecewise_max = np.nanmin(piecewise_max)
# Fallback if everything is NaN or non-finite
if not np.isfinite(min_of_piecewise_max):
min_of_piecewise_max = 1.0
# Minimum y = 3 orders of magnitude below that
y_min = float(min_of_piecewise_max * 1e-1)
# Ensure strictly positive for log scale
y_min = float(np.maximum(y_min, np.nextafter(0.0, 1.0)))
fig.update_layout(
barmode="group",
legend=dict(
orientation="h",
x=0.5,
xanchor="center",
y=1.08,
font=dict(size=18) # ← legend text size
),
yaxis=dict(
title=dict(
text=r"Fraction released",
font=dict(size=18) # ← axis label size
),
type="log",
range=[np.log10(y_min), np.log10(1.)]
),
xaxis=dict(
title=dict(
text=r"Representative boundary chemicals (CAS)",
standoff=0, # adjust: try 0–10 depending on how close you want it
font = dict(size=18) # ← axis label size
)
),
margin=dict(l=50, r=50, t=20, b=20),
autosize=False,
height=600,
width=800,
)
fig.update_xaxes(tickfont=dict(size=14))
fig.update_yaxes(tickfont=dict(size=14))
return fig