Commit d30066e2 authored by Niklas Selke's avatar Niklas Selke
Browse files

changed the views to use mixin classes

parent 0c772525
Pipeline #97262 passed with stages
in 49 seconds
from rest_framework.views import APIView
# from geo_location_services.settings import DEBUG, USE_LOCAL_DATA
# from services.file_extractions.built_up_area_file_extraction import read_proxydata
from .serializers import AggSerializer
from utils.views_commons import CommonViews
from utils.views_commons import CommonView
# if USE_LOCAL_DATA: # pragma: no cover
......@@ -12,7 +11,7 @@ from utils.views_commons import CommonViews
# print("File %s successfully loaded" % FILENAME, datainfo)
class BuildUpAreaView(APIView, CommonViews):
class BuildUpAreaView(CommonView):
def __init__(self):
......@@ -23,4 +22,4 @@ class BuildUpAreaView(APIView, CommonViews):
max_valid=100,
serializer=AggSerializer)
CommonViews.__init__(self, **opts)
super().__init__(self, **opts)
from rest_framework.views import APIView
# from geo_location_services.settings import DEBUG, USE_LOCAL_DATA, USE_SMALL_DATA
# from services.file_extractions.climatic_zones_file_extraction import read_proxydata
from .serializers import AggSerializer
from utils.views_commons import CommonViews
from utils.views_commons import CommonView
from .apps import ClimaticZonesConfig as Config
......@@ -16,7 +15,7 @@ from .apps import ClimaticZonesConfig as Config
# print("File %s successfully loaded" % FILENAME, datainfo)
class ClimaticZonesView(APIView, CommonViews):
class ClimaticZonesView(CommonView):
def __init__(self):
......@@ -27,5 +26,5 @@ class ClimaticZonesView(APIView, CommonViews):
serializer=AggSerializer,
service_type=Config.name)
CommonViews.__init__(self, **opts)
super().__init__(**opts)
self.keep_only_given_agg_allowed({})
from rest_framework.views import APIView
from .serializers import AggSerializer
from utils.views_commons import CommonViews
from utils.views_commons import CommonView
from .apps import EcoregionsConfig as Config
class EcoregionsView(APIView, CommonViews):
class EcoregionsView(CommonView):
def __init__(self):
......@@ -15,5 +14,5 @@ class EcoregionsView(APIView, CommonViews):
serializer=AggSerializer,
service_type=Config.name)
CommonViews.__init__(self, **opts)
super().__init__(**opts)
self.keep_only_given_agg_allowed({})
......@@ -4,7 +4,7 @@ from rest_framework.response import Response
import numpy as np
import geo_location_services.settings as settings
from .serializers import AggSerializer
from utils.views_commons import CommonViews
from utils.views_commons import BaseView
regions = dict(
......@@ -23,7 +23,7 @@ class HTAPRegionsTier1View(APIView):
for k in param_keys:
k = k.lower()
if k == 'lat':
val = CommonViews.get_latitude_param(params)
val = BaseView.get_latitude_param(params)
tmp['lat'] = val
else:
val = params.get('country')
......
from rest_framework.views import APIView
# from geo_location_services.settings import DEBUG, USE_LOCAL_DATA, USE_SMALL_DATA
# from services.file_extractions.htap_regions_tier2_file_extraction import read_proxydata
from .serializers import AggSerializer
from utils.views_commons import CommonViews
from utils.views_commons import CommonView
from utils.statistics import most_common_value, relative_frequency_categorical
......@@ -22,7 +21,7 @@ bins = list(range(20, 29)) + list(range(31, 37)) + list(range(41, 45)) + list(ra
+ [151, 150, 160, 161] # pragma: no cover
class HTAPView(APIView, CommonViews):
class HTAPView(CommonView):
def __init__(self):
opts = dict(# lonvec=lonvec,
......@@ -34,7 +33,7 @@ class HTAPView(APIView, CommonViews):
bins=bins
)
CommonViews.__init__(self, **opts)
super().__init__(self, **opts)
self.keep_only_given_agg_allowed(dict(maxclass=most_common_value,
frequency=relative_frequency_categorical),
frequency=dict(bins=self.bins))
from rest_framework.views import APIView
from .serializers import AggSerializer
from utils.views_commons import CommonViewsWithYear
from utils.views_commons import YearMixin, CommonView
from .apps import LandcoverConfig as Config
class LandcoverView(APIView, CommonViewsWithYear):
class LandcoverView(YearMixin, CommonView):
def __init__(self):
......@@ -15,5 +14,5 @@ class LandcoverView(APIView, CommonViewsWithYear):
serializer=AggSerializer,
service_type=Config.name)
CommonViewsWithYear.__init__(self, **opts)
super().__init__(**opts)
self.keep_only_given_agg_allowed({})
from collections import OrderedDict
import json
from rest_framework.views import APIView
from rest_framework.renderers import TemplateHTMLRenderer
from rest_framework.response import Response
from utils.views_commons import CommonViews
from utils.views_commons import BaseView
from .overpass_api import OverpassRoadAPI
from .serializers import NearestSerializer, NearestDirectionSerializer, RawdataSerializer
class MajorRoadsView(APIView, CommonViews):
class MajorRoadsView(BaseView):
def __init__(self):
CommonViews.__init__(self, service_type="major_roads")
super().__init__(service_type="major_roads")
def get(self, request, format=None):
"""process GET requests for major_roads app
......@@ -38,7 +37,7 @@ class MajorRoadsView(APIView, CommonViews):
request.query_params,
['lat', 'lon', 'radius', 'direction', 'highway_types'],
add_agg=False
)
).values()
# execute Overpass query, return ways with coordinates and metadata
# note that direction is only evaluated in serializer
......@@ -69,10 +68,10 @@ class MajorRoadsView(APIView, CommonViews):
return Response(response)
class MajorRoadsMapView(APIView, CommonViews):
class MajorRoadsMapView(BaseView):
def __init__(self):
CommonViews.__init__(self, service_type="major_roads")
super().__init__(service_type="major_roads")
renderer_classes = [TemplateHTMLRenderer]
template_name = 'map_view.html'
......@@ -85,7 +84,7 @@ class MajorRoadsMapView(APIView, CommonViews):
request.query_params,
['lat', 'lon', 'radius', 'direction', 'highway_types'],
add_agg=False
)
).values()
# execute Overpass query, return ways with coordinates and metadata
# note that direction is only evaluated in serializer
......
from rest_framework.views import APIView
# from geo_location_services.settings import DEBUG, USE_LOCAL_DATA, USE_SMALL_DATA
# from services.file_extractions.nox_emissions_file_extraction import read_proxydata
from .serializers import AggSerializer
from utils.views_commons import CommonViewsWithYear
from utils.views_commons import YearMixin, CommonView
from .apps import NOxEmissionsConfig as Config
......@@ -16,7 +15,7 @@ from .apps import NOxEmissionsConfig as Config
# print("File %s successfully loaded" % FILENAME, datainfo)
class NOxEmissionsView(APIView, CommonViewsWithYear):
class NOxEmissionsView(YearMixin, CommonView):
def __init__(self):
......@@ -27,4 +26,4 @@ class NOxEmissionsView(APIView, CommonViewsWithYear):
serializer=AggSerializer,
service_type=Config.name)
CommonViewsWithYear.__init__(self, **opts)
super().__init__(**opts)
from rest_framework.views import APIView
# from geo_location_services.settings import DEBUG, USE_LOCAL_DATA, USE_SMALL_DATA
# from services.file_extractions.omi_no2_file_extraction import read_proxydata
from .serializers import AggSerializer
from utils.views_commons import CommonViews
from utils.views_commons import CommonView
# if USE_LOCAL_DATA: # pragma: no cover
......@@ -19,7 +18,7 @@ from utils.views_commons import CommonViews
# print("File %s successfully loaded" % FILENAME, datainfo)
class OMINoxView(APIView, CommonViews):
class OMINoxView(CommonView):
def __init__(self):
......@@ -30,4 +29,4 @@ class OMINoxView(APIView, CommonViews):
max_valid=2.e6,
serializer=AggSerializer)
CommonViews.__init__(self, **opts)
super().__init__(self, **opts)
......@@ -36,7 +36,7 @@ class PopulationDensityView(PopulationNumberView):
direction: return data aggregation in one direction (wind sector) only.
Direction must be given as wind sector (e.g. 'N', 'NNE', 'NE', etc.).
"""
result = PopulationNumberView.get(self, request, format=format)
result = super().get(request, format=format)
properties = result.data["properties"]
radius = properties["radius"]
arcsec = 30 if radius is not None and radius > 10000 else 9
......
from rest_framework.views import APIView
# from geo_location_services.settings import DEBUG, USE_LOCAL_DATA
# from services.file_extractions.population_density_ghs_file_extraction import read_proxydata
from .serializers import AggSerializer
from utils.views_commons import CommonViews
from utils.views_commons import CommonView
# if USE_LOCAL_DATA: # pragma: no cover
......@@ -12,7 +11,7 @@ from utils.views_commons import CommonViews
# print("File %s successfully loaded" % FILENAME, datainfo)
class PopulationView(APIView, CommonViews):
class PopulationView(CommonView):
def __init__(self):
......@@ -23,4 +22,4 @@ class PopulationView(APIView, CommonViews):
max_valid=2.e6,
serializer=AggSerializer)
CommonViews.__init__(self, **opts)
super().__init__(self, **opts)
from rest_framework.views import APIView
# from geo_location_services.settings import DEBUG, USE_LOCAL_DATA
# from services.file_extractions.population_number_file_extraction import read_proxydata
from .serializers import AggSerializer
from utils.views_commons import CommonViewsWithYear
from utils.views_commons import YearMixin, CommonView
from .apps import PopulationNumberConfig as Config
......@@ -13,7 +12,7 @@ from .apps import PopulationNumberConfig as Config
# print("File %s successfully loaded" % FILENAME, datainfo)
class PopulationNumberView(APIView, CommonViewsWithYear):
class PopulationNumberView(YearMixin, CommonView):
def __init__(self):
......@@ -24,4 +23,4 @@ class PopulationNumberView(APIView, CommonViewsWithYear):
serializer=AggSerializer,
service_type=Config.name)
CommonViewsWithYear.__init__(self, **opts)
super().__init__(**opts)
from rest_framework.views import APIView
# from geo_location_services.settings import DEBUG, USE_LOCAL_DATA, USE_SMALL_DATA
# from services.file_extractions.rice_production_file_extraction import read_proxydata
from .serializers import AggSerializer
from utils.views_commons import CommonViews
from utils.views_commons import CommonView
from .apps import RiceProductionConfig as Config
......@@ -16,7 +15,7 @@ from .apps import RiceProductionConfig as Config
# print("File %s successfully loaded" % FILENAME, datainfo)
class RiceView(APIView, CommonViews):
class RiceView(CommonView):
def __init__(self):
......@@ -25,4 +24,4 @@ class RiceView(APIView, CommonViews):
serializer=AggSerializer,
service_type=Config.name)
CommonViews.__init__(self, **opts)
super().__init__(self, **opts)
from rest_framework.views import APIView
# from geo_location_services.settings import DEBUG, USE_LOCAL_DATA
# from services.file_extractions.stable_nightlights_file_extraction import read_proxydata
from .serializers import AggSerializer
from utils.views_commons import CommonViewsWithYear
from utils.views_commons import YearMixin, CommonView
from .apps import StableNightlightsConfig as Config
......@@ -13,7 +12,7 @@ from .apps import StableNightlightsConfig as Config
# print("File %s successfully loaded" % FILENAME, datainfo)
class StableNightlightsView(APIView, CommonViewsWithYear):
class StableNightlightsView(YearMixin, CommonView):
def __init__(self):
......@@ -24,4 +23,4 @@ class StableNightlightsView(APIView, CommonViewsWithYear):
serializer=AggSerializer,
service_type=Config.name)
CommonViewsWithYear.__init__(self, **opts)
super().__init__(**opts)
from collections import OrderedDict
from rest_framework.views import APIView
from rest_framework.response import Response
from geo_location_services.settings import DEBUG, DEFAULT_RELATIVE
# from geo_location_services.settings import USE_LOCAL_DATA
# from services.file_extractions.topography_srtm_file_extraction import read_proxydata
from .serializers import AggSerializer
from utils.views_commons import CommonViews
from utils.views_commons import RelativeMixin, CommonView
from .apps import TopographySRTMConfig as Config
......@@ -16,7 +12,7 @@ from .apps import TopographySRTMConfig as Config
# print("File %s successfully loaded" % FILENAME, datainfo)
class TopographySRTMView(APIView, CommonViews):
class TopographySRTMView(RelativeMixin, CommonView):
def __init__(self):
......@@ -27,65 +23,5 @@ class TopographySRTMView(APIView, CommonViews):
serializer=AggSerializer,
service_type=Config.name)
CommonViews.__init__(self, **opts)
super().__init__(**opts)
self.remove_agg_allowed('sum')
@staticmethod
def get_relative_param(params):
"""This is a mandatory parameter"""
val = params.get('relative')
# if not found, raise error
if val is None:
if DEBUG:
val = DEFAULT_RELATIVE
else:
raise KeyError('relative is a mandatory query argument')
if isinstance(val, str):
if val.lower() in ['true', 'yes', 'y']:
val = True
elif val.lower() in ['false', 'no', 'n']:
val = False
else:
raise ValueError('query argument for relative (%s) must be true or false' % (val))
return val
def get(self, request, format=None):
"""process GET requests
returns a Geo-JSON response with information about the wheat production at or
around a point location.
required arguments:
lat: latitude in degrees_north
lng: longitude in degrees_east (can be either -180 to 180 or 0 to 360)
optional arguments:
radius: search radius in m. See settings.py for default and max allowed values.
Without 'agg', the radius defaults to None and the wheat production at the
point location is returned.
agg: method of aggregation for data around point location. See settings.py for
default method. Only evaluated if radius > 0. Allowed methods are mean,
min, max, median, and NN-percentile (see views_commons.py)
direction: return data aggregation in one direction (wind sector) only.
Direction must be given as wind sector (e.g. 'N', 'NNE', 'NE', etc.).
"""
query_params = self.get_query_params(request.query_params, ['lat', 'lon', 'radius', 'agg', 'direction',
'check_is_circle_inside'])
lat, lon, radius, agg, direction, check_is_circle_inside = query_params
relative = self.get_relative_param(request.query_params)
result, provenance, agg, direction, bins = self._extract(lat, lon, radius, agg, direction, check_is_circle_inside,
relative=relative)
rawdata = OrderedDict([
("lat", lat),
("lon", lon),
("radius", radius),
("direction", direction),
("bins", bins),
("agg_function", agg),
(agg, result),
("provenance", provenance),
("additional_properties", {"relative": relative})
])
response = self.AggSerializer(rawdata).data
return Response(response)
from rest_framework.views import APIView
# from geo_location_services.settings import DEBUG, USE_LOCAL_DATA, USE_SMALL_DATA
# from services.file_extractions.wheat_production_file_extraction import read_proxydata
from .serializers import AggSerializer
from utils.views_commons import CommonViews
from utils.views_commons import CommonView
from .apps import WheatProductionConfig as Config
......@@ -16,7 +15,7 @@ from .apps import WheatProductionConfig as Config
# print("File %s successfully loaded" % FILENAME, datainfo)
class WheatView(APIView, CommonViews):
class WheatView(CommonView):
def __init__(self):
......@@ -25,4 +24,4 @@ class WheatView(APIView, CommonViews):
serializer=AggSerializer,
service_type=Config.name)
CommonViews.__init__(self, **opts)
super().__init__(self, **opts)
......@@ -415,24 +415,24 @@ class TestExtractionTools(TestCase):
check_is_circle_inside=True), -777.)
class TestCommonViews(TestCase):
class TestCommonView(TestCase):
def setUp(self):
self.view_blank = views_commons.CommonViews()
self.view_blank = views_commons.CommonView()
np.random.seed(0)
self.view = views_commons.CommonViews(lonvec=[1, 2, 3], latvec=[0., 0., 0.], data=np.random.rand(3, 3),
self.view = views_commons.CommonView(lonvec=[1, 2, 3], latvec=[0., 0., 0.], data=np.random.rand(3, 3),
default_value=-999, out_of_bounds_value=-888, min_valid=0, max_valid=10,
bins=list(range(0, 11)), global_data=False)
self.data = np.zeros((11, 11))
self.data[:6, :6] = 4
self.data[:5, :5] = 8
self.data[:3, :3] = 10
self.view_specific = views_commons.CommonViews(lonvec=np.arange(35, 45), latvec=np.arange(5, 15),
self.view_specific = views_commons.CommonView(lonvec=np.arange(35, 45), latvec=np.arange(5, 15),
data=self.data, provenance=TestAggSerializer.get_provenance(None),
default_value=-999, out_of_bounds_value=-888,
min_valid=0, max_valid=10, bins=list(range(0, 11)),
serializer=TestAggSerializer)
self.view_categorical = views_commons.CommonViews(lonvec=np.arange(35, 45), latvec=np.arange(5, 15),
self.view_categorical = views_commons.CommonView(lonvec=np.arange(35, 45), latvec=np.arange(5, 15),
data=self.data, provenance=TestAggSerializer.get_provenance(None),
default_value=-999, out_of_bounds_value=-888,
min_valid=0, max_valid=10, bins=list(range(0, 11)))
......@@ -440,7 +440,7 @@ class TestCommonViews(TestCase):
frequency=relative_frequency),
frequency=dict(bins=len(self.view_categorical.bins),
start_bin=self.view_categorical.min_valid))
self.view_categorical_nobins = views_commons.CommonViews(lonvec=np.arange(35, 45), latvec=np.arange(5, 15),
self.view_categorical_nobins = views_commons.CommonView(lonvec=np.arange(35, 45), latvec=np.arange(5, 15),
data=self.data, provenance=TestAggSerializer.get_provenance(None),
default_value=-999, out_of_bounds_value=-888,
min_valid=0, max_valid=10)
......@@ -660,41 +660,41 @@ class TestCommonViews(TestCase):
params = {'lat': 45,
'lon': 30}
response = (45., 30., None)
self.assertTupleEqual(f(params, ['lat', 'lon', 'radius']), response)
self.assertTupleEqual(tuple(f(params, ['lat', 'lon', 'radius']).values()), response)
params = {'lat': 45,
'lon': 30}
response = (30., 45., None)
self.assertTupleEqual(f(params, ['lon', 'lat', 'radius']), response)
self.assertTupleEqual(tuple(f(params, ['lon', 'lat', 'radius']).values()), response)
params = {'latitude': 5,
'lon': 35,
'radius': 0}
response = (5., 35., 0.)
self.assertTupleEqual(f(params, ['lat', 'lon', 'radius']), response)
self.assertTupleEqual(tuple(f(params, ['lat', 'lon', 'radius']).values()), response)
params = {'lat': 45,
'longitude': 30,
'radius': 5000,
'direction': 'N,S'}
response = (45., 30., 5000., 'mean')
self.assertTupleEqual(f(params, ['lat', 'lon', 'radius']), response)
self.assertTupleEqual(tuple(f(params, ['lat', 'lon', 'radius']).values()), response)
params = {'lat': 45,
'longitude': 30,
'radius': 5000,
'direction': 'N,S'}
response = (45., 30., 5000., ['N', 'S'], 'mean')
self.assertTupleEqual(f(params, ['lat', 'lon', 'radius', 'direction']), response)
self.assertTupleEqual(tuple(f(params, ['lat', 'lon', 'radius', 'direction']).values()), response)
params = {'agg': 'mean',
'direction': 'all',
'generic': 24}
response = (25000, 'mean')
self.assertTupleEqual(f(params, ['radius']), response)
self.assertTupleEqual(tuple(f(params, ['radius']).values()), response)
params = {'agg': 'max',
'generic': 24}
response = (settings.DEFAULT_RADIUS, 'max', 24)
self.assertTupleEqual(f(params, ['radius', 'agg', 'generic']), response)
self.assertTupleEqual(tuple(f(params, ['radius', 'agg', 'generic']).values()), response)
f = self.view_categorical.get_query_params
params = {'radius': 5000}
response = (5000, None)
self.assertTupleEqual(f(params, ['radius', 'agg']), response)
self.assertTupleEqual(tuple(f(params, ['radius', 'agg']).values()), response)
def test_get_list(self):
f = self.view._get_list
......
......@@ -23,13 +23,13 @@ import numpy as np
from functools import partial
import geo_location_services.settings as settings
from utils.geoutils import Directions
import inspect
from utils.extraction_tools import extract_value, extract_value_stats
from rest_framework.response import Response
from rest_framework.views import APIView
from utils.geocube_connection import GeoCube
class CommonViews:
class BaseView(APIView):
def __init__(self, lonvec=None, latvec=None, data=None, provenance=None, default_value=-999., out_of_bounds_value=-888.,
min_valid=None, max_valid=None, serializer=None, bins=None, service_type=None, global_data=True,
......@@ -282,7 +282,7 @@ class CommonViews:
'aggregated value')
# return values as tuple for unpacking
return tuple(tmp.values())
return tmp
@staticmethod
def _get_list(val):
......@@ -349,6 +349,29 @@ class CommonViews:
# return data, also return agg and direction as they may have been overwritten
return result, self.provenance, agg, direction, bins
class CommonView(BaseView):
def get_query_params(self, params, param_keys=None, add_agg=True):
if isinstance(param_keys, list):
keys = param_keys
else:
keys = ['lat', 'lon', 'radius', 'agg', 'direction', 'check_is_circle_inside']
return super().get_query_params(params, keys, add_agg)
@staticmethod
def get_rawdata(query_params, direction, bins, agg, result, provenance):
return OrderedDict([
("lat", query_params['lat']),
("lon", query_params['lon']),
("radius", query_params['radius']),
("direction", direction),
("bins", bins),
("agg_function", agg),
(agg, result),
("provenance", provenance),
])
def get(self, request, format=None):
"""process GET requests
......@@ -369,26 +392,15 @@ class CommonViews:
direction: return data aggregation in one direction (wind sector) only.
Direction must be given as wind sector (e.g. 'N', 'NNE', 'NE', etc.).
"""