From 51e5bc4ad0444b6c7562d07508bc0ee55b92ccac Mon Sep 17 00:00:00 2001 From: Miles Olson Date: Fri, 18 Oct 2024 10:24:08 -0700 Subject: [PATCH 1/2] Improve notebook display of AnalysisCards (#2899) Summary: Display title and subtitle, and sort cards by level in display_cards. Useful for using with AxClient in a notebook. Also add minimum_priority argument to display_cards, by default show everything but debug Differential Revision: D64495780 --- ax/analysis/analysis.py | 16 ++++++++++++---- ax/analysis/markdown/markdown_analysis.py | 2 +- ax/analysis/plotly/plotly_analysis.py | 3 ++- 3 files changed, 15 insertions(+), 6 deletions(-) diff --git a/ax/analysis/analysis.py b/ax/analysis/analysis.py index 03163ae3380..a6d7eb2564f 100644 --- a/ax/analysis/analysis.py +++ b/ax/analysis/analysis.py @@ -16,7 +16,7 @@ from ax.utils.common.base import Base from ax.utils.common.logger import get_logger from ax.utils.common.result import Err, ExceptionE, Ok, Result -from IPython.display import display +from IPython.display import display, Markdown logger: Logger = get_logger(__name__) @@ -79,15 +79,23 @@ def _ipython_display_(self) -> None: By default, this method displays the raw data in a pandas DataFrame. """ + display(Markdown(f"## {self.title}\n\n### {self.subtitle}")) display(self.df) -def display_cards(cards: Iterable[AnalysisCard]) -> None: +def display_cards( + cards: Iterable[AnalysisCard], minimum_level: int = AnalysisCardLevel.LOW +) -> None: """ Display a collection of AnalysisCards in IPython environments (ex. Jupyter). + + Args: + cards: Collection of AnalysisCards to display. + minimum_level: Minimum level of cards to display. """ - for card in cards: - display(card) + for card in sorted(cards, key=lambda x: x.level, reverse=True): + if card.level >= minimum_level: + display(card) class Analysis(Protocol): diff --git a/ax/analysis/markdown/markdown_analysis.py b/ax/analysis/markdown/markdown_analysis.py index 1ad794b6532..ff75d30b5bf 100644 --- a/ax/analysis/markdown/markdown_analysis.py +++ b/ax/analysis/markdown/markdown_analysis.py @@ -24,7 +24,7 @@ def _ipython_display_(self) -> None: IPython display hook. This is called when the AnalysisCard is printed in an IPython environment (ex. Jupyter). Here we want to render the Markdown. """ - display(Markdown(self.blob)) + display(Markdown(f"## {self.title}\n\n### {self.subtitle}\n\n{self.blob}")) class MarkdownAnalysis(Analysis): diff --git a/ax/analysis/plotly/plotly_analysis.py b/ax/analysis/plotly/plotly_analysis.py index a12e89cb45c..0f3dfeec86c 100644 --- a/ax/analysis/plotly/plotly_analysis.py +++ b/ax/analysis/plotly/plotly_analysis.py @@ -10,7 +10,7 @@ from ax.analysis.analysis import Analysis, AnalysisCard from ax.core.experiment import Experiment from ax.core.generation_strategy_interface import GenerationStrategyInterface -from IPython.display import display +from IPython.display import display, Markdown from plotly import graph_objects as go, io as pio @@ -25,6 +25,7 @@ def _ipython_display_(self) -> None: IPython display hook. This is called when the AnalysisCard is printed in an IPython environment (ex. Jupyter). Here we want to display the Plotly figure. """ + display(Markdown(f"## {self.title}\n\n### {self.subtitle}")) display(self.get_figure()) From e060008c929426ad7ca4be3d0bc5a2836defdfaf Mon Sep 17 00:00:00 2001 From: Miles Olson Date: Fri, 18 Oct 2024 10:24:08 -0700 Subject: [PATCH 2/2] Drop values without metric readings in ParallelCoordinatesPlot (#2898) Summary: Bugfix. If an arm does not have a value for its metric it will fail to plot. Noticed this while working on something else Differential Revision: D64496771 --- ax/analysis/plotly/parallel_coordinates.py | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/ax/analysis/plotly/parallel_coordinates.py b/ax/analysis/plotly/parallel_coordinates.py index f3f73e2ee1d..634d9978166 100644 --- a/ax/analysis/plotly/parallel_coordinates.py +++ b/ax/analysis/plotly/parallel_coordinates.py @@ -81,7 +81,7 @@ def _prepare_data(experiment: Experiment, metric: str) -> pd.DataFrame: for arm in trial.arms ] - return pd.DataFrame.from_records(records) + return pd.DataFrame.from_records(records).dropna() def _prepare_plot(df: pd.DataFrame, metric_name: str) -> go.Figure: @@ -96,10 +96,7 @@ def _prepare_plot(df: pd.DataFrame, metric_name: str) -> go.Figure: return go.Figure( go.Parcoords( - line={ - "color": df[metric_name], - "showscale": True, - }, + line={"color": df[metric_name], "showscale": True}, dimensions=[ *parameter_dimensions, {