diff --git a/src/feelpp/benchmarking/reframe/config/configPlots.py b/src/feelpp/benchmarking/reframe/config/configPlots.py index 755f04e7..5e7dedbd 100644 --- a/src/feelpp/benchmarking/reframe/config/configPlots.py +++ b/src/feelpp/benchmarking/reframe/config/configPlots.py @@ -27,6 +27,7 @@ class Plot(BaseModel): secondary_axis:Optional[PlotAxis] = None yaxis:PlotAxis color_axis:Optional[PlotAxis] = None + layout_modifiers: Optional[Dict] = {} @field_validator("xaxis","secondary_axis", mode="after") diff --git a/src/feelpp/benchmarking/report/figureFactory.py b/src/feelpp/benchmarking/report/figureFactory.py index d0a984d4..4e06c483 100644 --- a/src/feelpp/benchmarking/report/figureFactory.py +++ b/src/feelpp/benchmarking/report/figureFactory.py @@ -21,8 +21,9 @@ def createFigure(self,df): class ScatterFigure(Figure): """ Concrete Figure class for scatter figures """ - def __init__(self, plot_config,transformation_strategy): + def __init__(self, plot_config,transformation_strategy,fill_lines=[]): super().__init__(plot_config,transformation_strategy) + self.fill_lines = fill_lines def createAnimation(self,df): """ Creates a plotly figure from a multiIndex dataframe @@ -39,14 +40,19 @@ def createAnimation(self,df): for j,dim in enumerate(anim_dimension_values): frame_df = df.xs(dim,level=self.config.secondary_axis.parameter,axis=0) - frames.append([ - go.Scatter( - x = frame_df.index, - y = frame_df.loc[:,col], - name=col + + frame_traces = [] + for i,col in enumerate(self.fill_lines): + frame_traces.append( + go.Scatter( x = frame_df.index, y = frame_df.loc[:,col], name = col, fill='tonexty' if i > 0 else None, line=dict(color="black",dash="dash") ,mode="lines") ) - for col in frame_df.columns - ]) + + for col in [c for c in frame_df.columns if c not in self.fill_lines]: + frame_traces.append( + go.Scatter( x = frame_df.index, y = frame_df.loc[:,col], name = col ) + ) + + frames.append(frame_traces) ranges.append([ frame_df.min().min() - frame_df.min().min()*range_epsilon, frame_df.max().max() + frame_df.min().min()*range_epsilon @@ -84,11 +90,7 @@ def createSimple(self,df): Returns: go.Figure: Scatter plot """ - return go.Figure( - data = [ - go.Scatter( x = df.index, y = df.loc[:,col], name = col ) - for col in df.columns - ], + figure = go.Figure( layout=go.Layout( title=self.config.title, xaxis=dict( title = self.config.xaxis.label ), @@ -96,6 +98,16 @@ def createSimple(self,df): legend=dict(title=self.config.color_axis.label if self.config.color_axis else "") ) ) + for i,col in enumerate(self.fill_lines): + figure.add_trace( + go.Scatter( x = df.index, y = df.loc[:,col], name = col, fill='tonexty' if i > 0 else None, line=dict(color="black",dash="dash") ,mode="lines") + ) + + for col in [c for c in df.columns if c not in self.fill_lines]: + figure.add_trace( + go.Scatter( x = df.index, y = df.loc[:,col], name = col ) + ) + return figure def createFigure(self,df): """ Creates a scatter plot from the master dataframe @@ -107,9 +119,11 @@ def createFigure(self,df): df = self.transformation_strategy.calculate(df) if isinstance(df.index,MultiIndex): - return self.createAnimation(df) + figure = self.createAnimation(df) else: - return self.createSimple(df) + figure = self.createSimple(df) + figure.update_layout(self.config.layout_modifiers) + return figure class TableFigure(Figure): @@ -163,10 +177,11 @@ def createFigure(self,df): df = self.transformation_strategy.calculate(df) if isinstance(df.index,MultiIndex): - return self.createMultiindex(df) + figure = self.createMultiindex(df) else: - return self.createSimple(df) - + figure = self.createSimple(df) + figure.update_layout(self.config.layout_modifiers) + return figure class StackedBarFigure(Figure): """ Concrete Figure class for stacked bar charts""" @@ -236,9 +251,12 @@ def createFigure(self,df): df = self.transformation_strategy.calculate(df) if isinstance(df.index,MultiIndex): - return self.createGrouped(df) + figure = self.createGrouped(df) else: - return self.createSimple(df) + figure = self.createSimple(df) + + figure.update_layout(self.config.layout_modifiers) + return figure class GroupedBarFigure(Figure): #TODO: FACTOR animation and bar... def __init__(self, plot_config, transformation_strategy): @@ -321,10 +339,12 @@ def createFigure(self,df): df = self.transformation_strategy.calculate(df) if isinstance(df.index,MultiIndex): - return self.createGrouped(df) + figure = self.createGrouped(df) else: - return self.createSimple(df) + figure = self.createSimple(df) + figure.update_layout(self.config.layout_modifiers) + return figure class FigureFactory: """ Factory class to dispatch concrete figure elements""" @@ -338,7 +358,10 @@ def create(plot_config): figures = [] for plot_type in plot_config.plot_types: if plot_type == "scatter": - figures.append(ScatterFigure(plot_config,strategy)) + fill_lines = [] + if plot_config.transformation=="speedup": + fill_lines = ["optimal","half-optimal"] + figures.append(ScatterFigure(plot_config,strategy, fill_lines)) elif plot_type == "table": figures.append(TableFigure(plot_config,strategy)) elif plot_type == "stacked_bar": diff --git a/src/feelpp/benchmarking/report/strategies.py b/src/feelpp/benchmarking/report/strategies.py index 4be78b75..79d280ef 100644 --- a/src/feelpp/benchmarking/report/strategies.py +++ b/src/feelpp/benchmarking/report/strategies.py @@ -87,10 +87,14 @@ def calculate(self,df): pivot = super().calculate(df) if isinstance(pivot.index, pd.MultiIndex): - return pivot.xs(pivot.index.get_level_values(self.dimensions["xaxis"]).min(),level=self.dimensions["xaxis"],axis=0) / pivot + pivot = pivot.xs(pivot.index.get_level_values(self.dimensions["xaxis"]).min(),level=self.dimensions["xaxis"],axis=0) / pivot + pivot["optimal"] = pivot.index.get_level_values(self.dimensions["xaxis"]) / pivot.index.get_level_values(self.dimensions["xaxis"]).min() else: - return pivot.loc[pivot.index.min(),:] / pivot + pivot = pivot.loc[pivot.index.min(),:] / pivot + pivot["optimal"] = pivot.index / pivot.index.min() + pivot["half-optimal"] = (pivot["optimal"] -1) / 2 + 1 + return pivot class StrategyFactory: """ Factory class to dispatch concrete transformation strategies"""