From fb819f21b86e58f10a4cab7042a23baaa11f0377 Mon Sep 17 00:00:00 2001 From: Matthew Evans <7916000+ml-evs@users.noreply.github.com> Date: Tue, 22 Aug 2023 17:33:04 +0100 Subject: [PATCH] Better sanitize inputs for plot cycle selector (#438) --- pydatalab/pydatalab/apps/echem/utils.py | 13 ++++++++++++- pydatalab/pydatalab/bokeh_plots.py | 6 +++++- webapp/src/components/datablocks/CycleBlock.vue | 10 ++++++++++ 3 files changed, 27 insertions(+), 2 deletions(-) diff --git a/pydatalab/pydatalab/apps/echem/utils.py b/pydatalab/pydatalab/apps/echem/utils.py index 7e4ad4729..a9bc70d03 100644 --- a/pydatalab/pydatalab/apps/echem/utils.py +++ b/pydatalab/pydatalab/apps/echem/utils.py @@ -146,15 +146,26 @@ def filter_df_by_cycle_index( if cycle_list is None: return df + cycle_list = sorted(i for i in cycle_list if i > 0) + if "half cycle" not in df.columns: if "cycle index" not in df.columns: raise ValueError( "Input dataframe must have either 'half cycle' or 'cycle index' column" ) + + if len(cycle_list) == 1 and max(cycle_list) > df["cycle index"].max(): + cycle_list[0] = df["cycle index"].max() return df[df["cycle index"].isin(i for i in cycle_list)] try: - half_cycles = [i for item in cycle_list for i in [(2 * int(item)) - 1, 2 * int(item)]] + if len(cycle_list) == 1 and 2 * max(cycle_list) > df["half cycle"].max(): + cycle_list[0] = df["half cycle"].max() // 2 + half_cycles = [ + i + for item in cycle_list + for i in [max((2 * int(item)) - 1, df["half cycle"].min()), 2 * int(item)] + ] except ValueError as exc: raise ValueError( f"Unable to parse `cycle_list` as integers: {cycle_list}. Error: {exc}" diff --git a/pydatalab/pydatalab/bokeh_plots.py b/pydatalab/pydatalab/bokeh_plots.py index d229413bf..cca6f9db9 100644 --- a/pydatalab/pydatalab/bokeh_plots.py +++ b/pydatalab/pydatalab/bokeh_plots.py @@ -441,8 +441,12 @@ def double_axes_echem_plot( else: y = "dV/dQ (V/mA)" + # if filtering has removed all cycles, skip making the plot + if len(df) < 1: + raise RuntimeError("No data remaining to plot after filtering.") + # trim the end of the colour cycle for visibility on a white background - color_space = np.linspace(0.3, 0.7, int(df["half cycle"].max())) # type: ignore + color_space = np.linspace(0.3, 0.7, max(int(df["half cycle"].max()), 1)) # type: ignore for _, group in grouped_by_half_cycle: line = plot.line( diff --git a/webapp/src/components/datablocks/CycleBlock.vue b/webapp/src/components/datablocks/CycleBlock.vue index e2d1f7b16..69b08be1e 100644 --- a/webapp/src/components/datablocks/CycleBlock.vue +++ b/webapp/src/components/datablocks/CycleBlock.vue @@ -15,6 +15,7 @@