From 6b2b96a1b62ef633448f495568cf3d01bb30e4fd Mon Sep 17 00:00:00 2001
From: George Katsikas <giorgakis.katsikas@gmail.com>
Date: Thu, 30 Jan 2025 18:28:04 +0100
Subject: [PATCH] =?UTF-8?q?feat(graphs):=20=E2=9C=A8=20add=20many=20resamp?=
 =?UTF-8?q?ling=20agg=20functions?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Adds new aggregation method choice when resampling the TimelinePlot. Also renames fields for consistency and UX.
---
 scipost_django/graphs/graphs/plotkind.py | 57 +++++++++++++++---------
 1 file changed, 37 insertions(+), 20 deletions(-)

diff --git a/scipost_django/graphs/graphs/plotkind.py b/scipost_django/graphs/graphs/plotkind.py
index 52e61c8ef..ebc4f58e4 100644
--- a/scipost_django/graphs/graphs/plotkind.py
+++ b/scipost_django/graphs/graphs/plotkind.py
@@ -106,16 +106,19 @@ class TimelinePlot(PlotKind):
 
         value_key = self.options.get("value_key", "id") or "id"
         timeline_key = self.options.get("timeline_key", "id") or "id"
-        resample_freq = self.options.get("resample_freq", None)
-        window_size = self.options.get("window_size", 1)
+        resample_method = self.options.get("resample_method", None)
+        averaging_unit = self.options.get("averaging_unit", None)
+        averaging_window = self.options.get("averaging_window", 1)
 
         try:
             x, y = self.get_data()
             if (
                 self.plotter.get_model_field_type(value_key) in ["int", "float"]
-                and resample_freq
+                and resample_method != "None"
             ):
-                x, y = self.resample_data(x, y, resample_freq, window_size)
+                x, y = self.resample_data(
+                    x, y, resample_method, averaging_unit, averaging_window
+                )
             ax.plot(x, y)
         except Exception as e:
             PlotKind.display_plotting_error(ax, e)
@@ -137,17 +140,18 @@ class TimelinePlot(PlotKind):
 
         return fig
 
-    def resample_data(self, dates, values, freq: str, window: int):
+    def resample_data(self, dates, values, method: str | None, freq: str, window: int):
         df = pd.DataFrame({"dates": pd.to_datetime(dates), "values": values})
 
         df.set_index("dates", inplace=True)
-        df = (
-            df.resample(freq)
-            .mean()
-            .interpolate(method="time")
-            .rolling(window, center=True)
-            .mean()
-        )
+        if method is not None:
+            df = (
+                df.resample(freq)
+                .agg(method)
+                .interpolate(method="time")
+                .rolling(window, center=True)
+                .mean()
+            )
 
         return [date.to_pydatetime() for date in df.index], df["values"].tolist()
 
@@ -194,20 +198,32 @@ class TimelinePlot(PlotKind):
             required=False,
             widget=forms.DateTimeInput(attrs={"type": "date"}),
         )
-        resample_freq = forms.ChoiceField(
-            label="Resample frequency",
+        resample_method = forms.ChoiceField(
+            label="Resample method",
+            choices=[
+                ("None", "None"),
+                ("mean", "Mean"),
+                ("count", "Count"),
+                ("sum", "Sum"),
+                ("max", "Max"),
+                ("min", "Min"),
+            ],
+            required=False,
+            initial="None",
+        )
+        averaging_unit = forms.ChoiceField(
+            label="Averaging unit",
             choices=[
-                ("", "None"),
                 ("D", "Days"),
                 ("W", "Weeks"),
                 ("ME", "Months"),
                 ("Y", "Years"),
             ],
             required=False,
-            initial=None,
+            initial="D",
         )
-        window_size = forms.IntegerField(
-            label="Window size",
+        averaging_window = forms.IntegerField(
+            label="Averaging window",
             required=False,
             initial=1,
             min_value=1,
@@ -221,8 +237,9 @@ class TimelinePlot(PlotKind):
             Div(Field("timeline_min"), css_class="col-6"),
             Div(Field("timeline_max"), css_class="col-6"),
             Div(Field("value_key"), css_class="col-12"),
-            Div(Field("window_size"), css_class="col-6"),
-            Div(Field("resample_freq"), css_class="col-6"),
+            Div(Field("resample_method"), css_class="col-12"),
+            Div(Field("averaging_window"), css_class="col-6"),
+            Div(Field("averaging_unit"), css_class="col-6"),
         )
 
 
-- 
GitLab