From 9b75fc252e9ecb517c706adc4870ff3f8a58113b Mon Sep 17 00:00:00 2001 From: Suma Reddy <150843228+sumalreddy17@users.noreply.github.com> Date: Fri, 22 Nov 2024 06:30:00 -0800 Subject: [PATCH 1/4] Robyn one pager end to end flow for tutorial 1 --- .../src/robyn/reporting/onepager_reporting.py | 35 ++++++++++-------- python/src/robyn/robyn.py | 34 ++++++++++-------- python/src/robyn/tutorials/tutorial1.ipynb | 36 +++++++++---------- 3 files changed, 58 insertions(+), 47 deletions(-) diff --git a/python/src/robyn/reporting/onepager_reporting.py b/python/src/robyn/reporting/onepager_reporting.py index 01281758b..45d981c79 100644 --- a/python/src/robyn/reporting/onepager_reporting.py +++ b/python/src/robyn/reporting/onepager_reporting.py @@ -219,27 +219,27 @@ def _add_title_and_metrics(self, fig: plt.Figure, solution_id: str) -> None: """Add title and metrics text to the figure.""" try: model_info = self._get_model_info(solution_id) - metrics_text = model_info.get('formatted_text', '') - + metrics_text = model_info.get("formatted_text", "") + # Add title with larger font and bold fig.suptitle( f"MMM Analysis One-Pager for Model: {solution_id}", - fontsize=24, # Increased from 18 + fontsize=24, # Increased from 18 y=0.98, - weight='bold', # Makes the text bold - fontfamily='sans-serif' # Clear font family + weight="bold", # Makes the text bold + fontfamily="sans-serif", # Clear font family ) - + # Add metrics text if available if metrics_text: fig.text( - 0.5, # Center horizontally - 0.955, # Position below title + 0.5, # Center horizontally + 0.955, # Position below title metrics_text, fontsize=16, # Increased from 14 - ha='center', - va='top', - weight='bold' # Also make metrics bold + ha="center", + va="top", + weight="bold", # Also make metrics bold ) except Exception as e: logger.error(f"Error adding title and metrics: {str(e)}") @@ -248,8 +248,8 @@ def _add_title_and_metrics(self, fig: plt.Figure, solution_id: str) -> None: f"MMM Analysis One-Pager for Model: {solution_id}", fontsize=24, y=0.98, - weight='bold', - fontfamily='sans-serif' + weight="bold", + fontfamily="sans-serif", ) def _generate_solution_plots( @@ -387,7 +387,7 @@ def _generate_solution_plots( def generate_one_pager( self, solution_ids: Union[str, List[str]] = "all", - plots: Optional[List[str]] = None, + plots: Optional[List[PlotType]] = None, # Changed from List[str] figsize: tuple = (30, 34), save_path: Optional[str] = None, top_pareto: bool = False, @@ -404,6 +404,13 @@ def generate_one_pager( Returns: List[plt.Figure]: List of generated figures, one per solution """ + # Convert string plot types to PlotType if necessary + if plots and isinstance(plots[0], str): + try: + plots = [PlotType[plot.upper()] for plot in plots] + except KeyError as e: + raise ValueError(f"Invalid plot type: {e}") + # Use default plots if none provided plots = plots or self.default_plots diff --git a/python/src/robyn/robyn.py b/python/src/robyn/robyn.py index 3f8df4d67..53915c334 100644 --- a/python/src/robyn/robyn.py +++ b/python/src/robyn/robyn.py @@ -5,6 +5,8 @@ from pathlib import Path from typing import Dict, Optional, List import numpy as np +from robyn.modeling.entities.clustering_results import ClusteredResult +from robyn.data.entities.enums import AdstockType, PlotType from robyn.data.entities.mmmdata import MMMData from robyn.data.entities.holidays_data import HolidaysData from robyn.data.entities.hyperparameters import Hyperparameters @@ -398,29 +400,31 @@ def optimize_budget( logger.error("Budget optimization failed: %s", str(e)) raise - @staticmethod - def generate_one_pager( - pareto_result: ParetoResult, - cluster_result: Optional[ClusteringConfig] = None, - mmm_data: Optional[MMMData] = None, - plots: Optional[List[str]] = None, - ) -> None: + def plot_one_pager(self) -> None: + """Generate one pager plots for the model.""" + try: + self._generate_one_pager() # Call instance method + except Exception as e: + logging.error(f"Failed to generate one pager plots: {str(e)}") + raise + + def _generate_one_pager(self, plots: Optional[List[PlotType]] = None) -> None: """ Generate one-page summary report. - + Args: - pareto_result: Pareto optimization results - cluster_result: Optional clustering results - mmm_data: Optional MMM data for additional context plots: Optional list of specific plots to include """ try: onepager = OnePager( - pareto_result=pareto_result, - clustered_result=cluster_result, - mmm_data=mmm_data, + pareto_result=self.pareto_result, + clustered_result=self.cluster_result, + adstock=self.hyperparameters.adstock, + mmm_data=self.mmm_data, + holidays_data=self.holidays_data ) - onepager.generate_one_pager(plots=plots) + figures = onepager.generate_one_pager(plots=plots, top_pareto=True) + return figures except Exception as e: logging.error("One-pager generation failed: %s", str(e)) diff --git a/python/src/robyn/tutorials/tutorial1.ipynb b/python/src/robyn/tutorials/tutorial1.ipynb index b568d393f..af6478fd0 100644 --- a/python/src/robyn/tutorials/tutorial1.ipynb +++ b/python/src/robyn/tutorials/tutorial1.ipynb @@ -272,6 +272,24 @@ "robyn.evaluate_models(cluster_config=configs)" ] }, + { + "cell_type": "markdown", + "id": "7cebb194", + "metadata": {}, + "source": [ + "## Robyn One Pager Report" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "a0f68f80", + "metadata": {}, + "outputs": [], + "source": [ + "robyn.plot_one_pager()" + ] + }, { "cell_type": "markdown", "id": "8ede6c0d", @@ -342,24 +360,6 @@ "# Display the allocation result\n", "print(allocation_result)" ] - }, - { - "cell_type": "markdown", - "id": "6e68b36c", - "metadata": {}, - "source": [ - "## Robyn One Pager Report" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "cf46898f", - "metadata": {}, - "outputs": [], - "source": [ - "# robyn.generate_one_pager()" - ] } ], "metadata": { From d832ea874764aed966ffb9c3c48692b6a22c6cfa Mon Sep 17 00:00:00 2001 From: Suma Reddy <150843228+sumalreddy17@users.noreply.github.com> Date: Fri, 22 Nov 2024 06:33:19 -0800 Subject: [PATCH 2/4] Format files --- python/src/robyn/reporting/onepager_reporting.py | 2 +- python/src/robyn/robyn.py | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/python/src/robyn/reporting/onepager_reporting.py b/python/src/robyn/reporting/onepager_reporting.py index 45d981c79..057fe6915 100644 --- a/python/src/robyn/reporting/onepager_reporting.py +++ b/python/src/robyn/reporting/onepager_reporting.py @@ -404,7 +404,7 @@ def generate_one_pager( Returns: List[plt.Figure]: List of generated figures, one per solution """ - # Convert string plot types to PlotType if necessary + # Convert string plot types to PlotType if necessary if plots and isinstance(plots[0], str): try: plots = [PlotType[plot.upper()] for plot in plots] diff --git a/python/src/robyn/robyn.py b/python/src/robyn/robyn.py index 53915c334..688c98ca2 100644 --- a/python/src/robyn/robyn.py +++ b/python/src/robyn/robyn.py @@ -411,7 +411,7 @@ def plot_one_pager(self) -> None: def _generate_one_pager(self, plots: Optional[List[PlotType]] = None) -> None: """ Generate one-page summary report. - + Args: plots: Optional list of specific plots to include """ @@ -421,7 +421,7 @@ def _generate_one_pager(self, plots: Optional[List[PlotType]] = None) -> None: clustered_result=self.cluster_result, adstock=self.hyperparameters.adstock, mmm_data=self.mmm_data, - holidays_data=self.holidays_data + holidays_data=self.holidays_data, ) figures = onepager.generate_one_pager(plots=plots, top_pareto=True) return figures From b9c7497879e4a807f0cbea5fd8651efe63d72168 Mon Sep 17 00:00:00 2001 From: Suma Reddy <150843228+sumalreddy17@users.noreply.github.com> Date: Fri, 22 Nov 2024 09:11:49 -0800 Subject: [PATCH 3/4] Allow user to pass in a single solution id from client interface layer --- python/src/robyn/robyn.py | 32 +++++++++++++++++----- python/src/robyn/tutorials/tutorial1.ipynb | 12 +++++++- 2 files changed, 36 insertions(+), 8 deletions(-) diff --git a/python/src/robyn/robyn.py b/python/src/robyn/robyn.py index 688c98ca2..bc900398a 100644 --- a/python/src/robyn/robyn.py +++ b/python/src/robyn/robyn.py @@ -400,20 +400,30 @@ def optimize_budget( logger.error("Budget optimization failed: %s", str(e)) raise - def plot_one_pager(self) -> None: - """Generate one pager plots for the model.""" + def plot_one_pager(self, solution_id: Optional[str] = None) -> None: + """Generate one pager plots for the model. + + Args: + solution_id: Optional specific solution ID to plot. + If None, generates plots for top pareto solutions + """ try: - self._generate_one_pager() # Call instance method + self._generate_one_pager(solution_id=solution_id) except Exception as e: logging.error(f"Failed to generate one pager plots: {str(e)}") raise - def _generate_one_pager(self, plots: Optional[List[PlotType]] = None) -> None: + def _generate_one_pager( + self, + plots: Optional[List[PlotType]] = None, + solution_id: Optional[str] = None + ) -> None: """ Generate one-page summary report. - + Args: plots: Optional list of specific plots to include + solution_id: Optional specific solution ID to plot """ try: onepager = OnePager( @@ -421,9 +431,17 @@ def _generate_one_pager(self, plots: Optional[List[PlotType]] = None) -> None: clustered_result=self.cluster_result, adstock=self.hyperparameters.adstock, mmm_data=self.mmm_data, - holidays_data=self.holidays_data, + holidays_data=self.holidays_data + ) + + # Set top_pareto based on whether solution_id is provided + top_pareto = solution_id is None + + figures = onepager.generate_one_pager( + plots=plots, + solution_ids=solution_id if solution_id else "all", + top_pareto=top_pareto ) - figures = onepager.generate_one_pager(plots=plots, top_pareto=True) return figures except Exception as e: diff --git a/python/src/robyn/tutorials/tutorial1.ipynb b/python/src/robyn/tutorials/tutorial1.ipynb index af6478fd0..c8272095f 100644 --- a/python/src/robyn/tutorials/tutorial1.ipynb +++ b/python/src/robyn/tutorials/tutorial1.ipynb @@ -30,7 +30,7 @@ "source": [ "import sys\n", "\n", - "sys.path.append(\"/Users/yijuilee/robynpy_release_reviews/Robyn/python/src\")\n", + "sys.path.append(\"/Users/sumalreddy/workspace/Robyn/python/src\")\n", "import pandas as pd\n", "import numpy as np\n", "from robyn.robyn import Robyn\n", @@ -290,6 +290,16 @@ "robyn.plot_one_pager()" ] }, + { + "cell_type": "code", + "execution_count": null, + "id": "9ed54130", + "metadata": {}, + "outputs": [], + "source": [ + "robyn.plot_one_pager(solution_id=\"1_4_1\")" + ] + }, { "cell_type": "markdown", "id": "8ede6c0d", From c19636edcbc106c94e8d8ea2ca1f251f1e22f318 Mon Sep 17 00:00:00 2001 From: Suma Reddy <150843228+sumalreddy17@users.noreply.github.com> Date: Fri, 22 Nov 2024 10:18:51 -0800 Subject: [PATCH 4/4] Address comments --- python/src/robyn/robyn.py | 30 +++++----------------- python/src/robyn/tutorials/tutorial1.ipynb | 6 ++--- 2 files changed, 9 insertions(+), 27 deletions(-) diff --git a/python/src/robyn/robyn.py b/python/src/robyn/robyn.py index bc900398a..cbc9da2d5 100644 --- a/python/src/robyn/robyn.py +++ b/python/src/robyn/robyn.py @@ -400,27 +400,10 @@ def optimize_budget( logger.error("Budget optimization failed: %s", str(e)) raise - def plot_one_pager(self, solution_id: Optional[str] = None) -> None: - """Generate one pager plots for the model. - - Args: - solution_id: Optional specific solution ID to plot. - If None, generates plots for top pareto solutions - """ - try: - self._generate_one_pager(solution_id=solution_id) - except Exception as e: - logging.error(f"Failed to generate one pager plots: {str(e)}") - raise - - def _generate_one_pager( - self, - plots: Optional[List[PlotType]] = None, - solution_id: Optional[str] = None - ) -> None: + def generate_one_pager(self, solution_id: Optional[str] = None) -> None: """ Generate one-page summary report. - + Args: plots: Optional list of specific plots to include solution_id: Optional specific solution ID to plot @@ -431,16 +414,15 @@ def _generate_one_pager( clustered_result=self.cluster_result, adstock=self.hyperparameters.adstock, mmm_data=self.mmm_data, - holidays_data=self.holidays_data + holidays_data=self.holidays_data, ) - + # Set top_pareto based on whether solution_id is provided top_pareto = solution_id is None - + figures = onepager.generate_one_pager( - plots=plots, solution_ids=solution_id if solution_id else "all", - top_pareto=top_pareto + top_pareto=top_pareto, ) return figures diff --git a/python/src/robyn/tutorials/tutorial1.ipynb b/python/src/robyn/tutorials/tutorial1.ipynb index c8272095f..2b0e73e57 100644 --- a/python/src/robyn/tutorials/tutorial1.ipynb +++ b/python/src/robyn/tutorials/tutorial1.ipynb @@ -30,7 +30,7 @@ "source": [ "import sys\n", "\n", - "sys.path.append(\"/Users/sumalreddy/workspace/Robyn/python/src\")\n", + "sys.path.append(\"/Users/yijuilee/robynpy_release_reviews/Robyn/python/src\")\n", "import pandas as pd\n", "import numpy as np\n", "from robyn.robyn import Robyn\n", @@ -287,7 +287,7 @@ "metadata": {}, "outputs": [], "source": [ - "robyn.plot_one_pager()" + "robyn.generate_one_pager()" ] }, { @@ -297,7 +297,7 @@ "metadata": {}, "outputs": [], "source": [ - "robyn.plot_one_pager(solution_id=\"1_4_1\")" + "robyn.generate_one_pager(solution_id=\"1_4_1\")" ] }, {