From 168d8d23ceacf80e4edff3592c8bc8faebc8b60b Mon Sep 17 00:00:00 2001
From: Clemens Berteld <clemens@berteld.com>
Date: Mon, 13 Sep 2021 10:24:36 +0200
Subject: [PATCH] Interpolation is calculated using weights

---
 dataacquisition/GetAverageData.py | 38 +++++++++++++++++++++++--------
 dataacquisition/api.py            |  4 ++--
 dataacquisition/config.ini        |  5 +++-
 dataacquisition/sandbox.py        | 21 +++++++++++------
 4 files changed, 48 insertions(+), 20 deletions(-)

diff --git a/dataacquisition/GetAverageData.py b/dataacquisition/GetAverageData.py
index 38d1716..48d947e 100644
--- a/dataacquisition/GetAverageData.py
+++ b/dataacquisition/GetAverageData.py
@@ -6,7 +6,9 @@ from psycopg2 import sql
 cfg = configparser.ConfigParser()
 cfg.read('config.ini')
 assert "POSTGRES" in cfg, "missing POSTGRES in config.ini"
+assert "INTERPOLATION" in cfg, "missing INTERPOLATION in config.ini"
 param_postgres = cfg["POSTGRES"]
+param_interpol = cfg["INTERPOLATION"]
 
 
 def get_year_columns(cursor):
@@ -29,23 +31,23 @@ def get_neighbours(cursor, lat, lon, columns):
 
     query = sql.SQL("""
                 SELECT array_to_json(array_agg(row_to_json(t))) from (
-                    SELECT {columns} FROM stations 
-                    ORDER BY ST_Distance(ST_MakePoint(lon, lat), ST_MakePoint({lon}, {lat})) 
-                    LIMIT 10
+                    SELECT {columns}, ST_Distance(ST_MakePoint(lon, lat), ST_MakePoint({lon}, {lat})) AS distance 
+                    FROM stations 
+                    ORDER BY distance 
+                    LIMIT {amount_neighbours}
                 ) t;
-                    """).format(columns=columns, lon=sql.Placeholder(), lat=sql.Placeholder())
+                    """).format(columns=columns, lon=sql.Placeholder(), lat=sql.Placeholder(), amount_neighbours=sql.SQL(param_interpol["amount_neighbours"]))
     cursor.execute(query, values)
     neighbours = cursor.fetchall()[0][0]
     return neighbours
 
 
+# Unused
 def calc_averages(neighbours, years):
     averages = {}
     for year in years:
         values = []
-        # print(neighbours)
         for neighbour in neighbours:
-
             # print(neighbour[str(year)])
             if not neighbour[str(year)] == 'NaN': values.append(neighbour[str(year)])
         avg = round(sum(values) / len(values), 3)
@@ -53,17 +55,33 @@ def calc_averages(neighbours, years):
     return averages
 
 
-def get_average_data_for_point(lat, lon, columns):
+def calc_idw(neighbours, years):
+    weighted_values = {}
+    for year in years:
+        values = []
+        # print(neighbours)
+        distances = []
+        for neighbour in neighbours:
+            distances.append(neighbour['distance'])
+        for neighbour in neighbours:
+            normalizer = float(param_interpol["amount_neighbours"]) / sum(distances)
+            weight = neighbour['distance'] * normalizer
+            print('weight', weight)
+            if not neighbour[str(year)] == 'NaN': values.append(neighbour[str(year)] * weight)
+        avg = round(sum(values) / len(values), 3)
+        weighted_values[year] = avg
+    return weighted_values
+
+
+def get_interpolation_data_for_point(lat, lon, columns):
     with psycopg2.connect(database=param_postgres["dbName"], user=param_postgres["user"], password=param_postgres["password"], host=param_postgres["host"], port=param_postgres["port"]) as connection:
         with connection.cursor() as cursor:
-            print(columns)
             if '*' in str(columns):
                 year_columns = get_year_columns(cursor)
             else:
                 year_columns = (str(columns).replace("""SQL('""", "").replace('"', '').replace("')", "")).split(',')
-                print(year_columns)
             neighbours = get_neighbours(cursor, lat, lon, columns)
-            avg_data = calc_averages(neighbours, year_columns)
+            avg_data = calc_idw(neighbours, year_columns)
             print(avg_data)
             return avg_data
 
diff --git a/dataacquisition/api.py b/dataacquisition/api.py
index d4d984c..5e16b76 100644
--- a/dataacquisition/api.py
+++ b/dataacquisition/api.py
@@ -4,7 +4,7 @@ import psycopg2
 from flask import Flask, jsonify, request
 from psycopg2 import sql
 import configparser
-from GetAverageData import get_average_data_for_point
+from GetAverageData import get_interpolation_data_for_point
 
 cfg = configparser.ConfigParser()
 cfg.read('config.ini')
@@ -39,7 +39,7 @@ def index():
     if 'lat' in request.args or 'lng' in request.args:
         lat = request.args['lat']
         lon = request.args['lon']
-        return get_average_data_for_point(lat, lon, columns)
+        return get_interpolation_data_for_point(lat, lon, columns)
 
     else:
         if 'id' in request.args:
diff --git a/dataacquisition/config.ini b/dataacquisition/config.ini
index dfbe24d..7d49d0c 100644
--- a/dataacquisition/config.ini
+++ b/dataacquisition/config.ini
@@ -3,4 +3,7 @@ host = localhost
 port = 5432
 user = postgres
 password = postgres
-dbName = temperatures_berteld_morstein
\ No newline at end of file
+dbName = temperatures_berteld_morstein
+
+[INTERPOLATION]
+amount_neighbours = 5
\ No newline at end of file
diff --git a/dataacquisition/sandbox.py b/dataacquisition/sandbox.py
index 7b1e42c..f245d89 100644
--- a/dataacquisition/sandbox.py
+++ b/dataacquisition/sandbox.py
@@ -1,9 +1,16 @@
-import psycopg2
-from psycopg2 import sql
+# import psycopg2
+# from psycopg2 import sql
+#
+# query = sql.SQL("select {0} from {1} where {2} LIKE {3} {4}").format(sql.SQL(', ').join([sql.Identifier('foo'), sql.Identifier('bar')]), sql.Identifier('table'), sql.Identifier('coulumn'), sql.Placeholder(),
+#                                                                      sql.SQL('AND 1 = 1'))
+#
+# with psycopg2.connect(database='temperatures_berteld_morstein', user='postgres', password='postgres', host='localhost', port=5432) as connection:
+#     with connection.cursor() as cursor:
+#         print(query.as_string(cursor))
 
-query = sql.SQL("select {0} from {1} where {2} LIKE {3} {4}").format(sql.SQL(', ').join([sql.Identifier('foo'), sql.Identifier('bar')]), sql.Identifier('table'), sql.Identifier('coulumn'), sql.Placeholder(),
-                                                                     sql.SQL('AND 1 = 1'))
 
-with psycopg2.connect(database='temperatures_berteld_morstein', user='postgres', password='postgres', host='localhost', port=5432) as connection:
-    with connection.cursor() as cursor:
-        print(query.as_string(cursor))
+weights = [2, 1.25, 0.75, 0.6, 0.4]
+neighbours = [{'2015': 'NaN', '2010': 9.333, '2014': 'NaN', '1998': 'NaN', 'distance': 0.0223606797750006}, {'2015': 11.233, '2010': 8.883, '2014': 11.458, '1998': 10.05, 'distance': 0.0300000000000011}, {'2015': 11.133, '2010': 8.767, '2014': 11.467, '1998': 'NaN', 'distance': 0.108166538263921}, {'2015': 10.667, '2010': 8.208, '2014': 11.025, '1998': 9.8, 'distance': 0.111803398874988}, {'2015': 10.667, '2010': 8.35, '2014': 10.908, '1998': 'NaN', 'distance': 0.176918060129539}]
+
+for weight, neighbour in zip(weights, neighbours):
+    print(weight, neighbour['2015'])
-- 
GitLab