Source code for langcheck.plot._histogram

import math

import plotly.express as px
from dash import Dash, Input, Output, dcc, html

from langcheck.metrics.metric_value import MetricValue, MetricValueWithThreshold
from langcheck.plot._css import GLOBAL_CSS
from langcheck.plot._utils import Axis, _plot_threshold


[docs] def histogram(metric_value: MetricValue, jupyter_mode: str = "inline") -> None: """Shows an interactive histogram of all data points in :class:`~langcheck.metrics.metric_value.MetricValue`. When run in a notebook, this usually displays the chart inline in the cell output. Args: metric_value: The :class:`~langcheck.metrics.metric_value.MetricValue` to plot. other_metric_value: If provided, another :class:`~langcheck.metrics.metric_value.MetricValue` to plot on the same chart. jupyter_mode: Defaults to 'inline', which displays the chart in the cell output. For Colab, set this to 'external' instead. See the Dash documentation for more info: https://dash.plotly.com/workspaces/using-dash-in-jupyter-and-workspaces#display-modes """ # Rename some MetricValue fields for display df = metric_value.to_df() df.rename(columns={"metric_values": metric_value.metric_name}, inplace=True) # Define layout of the Dash app (histogram + input for number of bins) app = Dash(__name__) app.layout = html.Div( [ html.Div( [ html.Label("Number of bins: "), dcc.Slider( id="num_bins", min=1, max=50, step=1, value=10, marks={ 1: "1", 10: "10", 20: "20", 30: "30", 40: "40", 50: "50", }, tooltip={"placement": "bottom", "always_visible": True}, ), ] ), dcc.Graph( id="histogram", config={ "displaylogo": False, "modeBarButtonsToRemove": [ "select", "lasso2d", "resetScale", ], }, ), ], style=GLOBAL_CSS, ) # This function gets called whenever the user changes the num_bins value @app.callback( Output("histogram", "figure"), Input("num_bins", "value"), ) def update_figure(num_bins): # Plot the histogram fig = px.histogram(df, x=metric_value.metric_name) if isinstance(metric_value, MetricValueWithThreshold): _plot_threshold( fig, metric_value.threshold_op, metric_value.threshold, Axis.vertical, ) # Manually set the number of bins in the histogram. We can't use the # nbins parameter of px.histogram() since it's just a suggested number # of bins. See: https://community.plotly.com/t/histogram-bin-size-with-plotly-express/38927/5 start = math.floor(df[metric_value.metric_name].min()) end = math.ceil(df[metric_value.metric_name].max()) step_size = (end - start) / int(num_bins) fig.update_traces(xbins={"start": start, "end": end, "size": step_size}) # Explicitly set the default axis ranges (with a little padding) so that # the range plotted would not be influenced by threshold settings fig.update_xaxes( range=[ min(-0.1, math.floor(df[metric_value.metric_name].min())), max(1.1, math.ceil(df[metric_value.metric_name].max())), ] ) # If the user manually zoomed in, keep that zoom level even when # update_figure() re-runs fig.update_layout(uirevision="constant") # Disable drag-to-zoom by default (the user can still enable it in the # modebar) fig.update_layout(dragmode=False) return fig # Display the Dash app inline in the notebook app.run(jupyter_mode=jupyter_mode) # type: ignore