Răsfoiți Sursa

add web endpoint for plots

Daniel Sheffield 2 ani în urmă
părinte
comite
ab7e7a696e
3 a modificat fișierele cu 64 adăugiri și 0 ștergeri
  1. 6 0
      app/rest/Dockerfile
  2. 56 0
      app/rest/pyapi.py
  3. 2 0
      app/rest/requirements.txt

+ 6 - 0
app/rest/Dockerfile

@@ -0,0 +1,6 @@
+FROM python:3-slim
+WORKDIR /usr/src/app
+COPY  requirements.txt ./
+RUN pip install --no-cache-dir -r requirements.txt
+COPY pyapi.py .
+CMD [ "python", "./pyapi.py" ]

+ 56 - 0
app/rest/pyapi.py

@@ -0,0 +1,56 @@
+#
+# Copyright (c) Daniel Sheffield 2023
+# All rights reserved
+#
+# THIS SOFTWARE IS PROVIDED AS IS WITHOUT WARRANTY
+from bottle import route, request, run, response, abort
+from psycopg import sql, Cursor, connect
+from datetime import date, datetime
+import os
+import matplotlib.pyplot as plt
+import seaborn as sns
+from ..activities.Plot import (
+    get_data,
+)
+from ..data.QueryManager import QueryManager, display_mapper
+def line(pivot, ylabel=None, xlabel=None):
+    ax = sns.lineplot(data=pivot, markers=True)
+    ax.set_xlabel(xlabel)
+    ax.set_ylabel(ylabel)
+
+ALL_UNITS = {'g','kg','mL','L','Pieces','Bunches','Bags'}
+PARAMS ={ 'group', 'category', 'product', 'unit' }
+host = f"host={os.getenv('HOST')}"
+db = f"dbname={os.getenv('DB', 'grocery')}"
+user = f"user={os.getenv('USER', 'das')}"
+password = f"password={os.getenv('PASSWORD','')}"
+if not password.split('=',1)[1]:
+    password = ''
+conn = connect(f"{host} {db} {user} {password}")
+from io import StringIO
+@route('/grocery/trend')
+def trend():
+    try:
+        with conn.cursor() as cur:
+            query_manager = QueryManager(cur, display_mapper)
+            fields = { k: request.query[k] for k in request.query.keys() if k in PARAMS }
+            unit = fields['unit'] = fields['unit'] if 'unit' in fields else None or 'kg'
+            if unit not in ALL_UNITS:
+                raise abort(400, f"Unsupported unit {unit}")
+            
+            data = get_data(query_manager, **fields)
+            if data.empty:
+                raise abort(404, f"No data for {fields}")
+            pivot = data.pivot_table(index=['ts_raw',], columns=['product',], values=['$/unit'], aggfunc='mean')
+            pivot.columns = pivot.columns.droplevel()
+            plt.figure(figsize=[16, 9])
+            line(pivot, xlabel='Time', ylabel=f'$ / {unit}')
+            f = StringIO()
+            plt.savefig(f, format='svg')
+    finally:
+        conn.commit()
+
+    response.content_type = 'image/svg+xml; charset=utf-8'
+    return f.getvalue()
+
+run(host='127.0.0.1', port=6772)

+ 2 - 0
app/rest/requirements.txt

@@ -0,0 +1,2 @@
+psycopg[binary]
+bottle