diff --git a/toar_location_services/settings.py b/toar_location_services/settings.py
index 7e2caab3fcedfc699529ebc30b2766192e67df13..7afb2ab71381361af789acce6e880834d0c02c24 100644
--- a/toar_location_services/settings.py
+++ b/toar_location_services/settings.py
@@ -43,7 +43,8 @@ INSTALLED_APPS = [
     'major-roads',
     'population-density',
     'topography-tandem-x',
-    'stable_night_lights'
+    'stable_night_lights',
+    'wheat_production'
 ]
 
 MIDDLEWARE = [
@@ -145,4 +146,5 @@ USE_LOCAL_OVERPASS_DATA = False
 USE_DUMMY_POPULATION_DATA = True
 USE_DUMMY_TOPOGRAPHY_TANDEM_DATA = False
 USE_DUMMY_STABLE_NIGHT_LIGHTS_DATA = False
-
+USE_DUMMY_WHEAT_DATA = False
+PLOT_DATA = False
diff --git a/toar_location_services/urls.py b/toar_location_services/urls.py
index 8fb7bc0f1e2da53c5d0e4538e45b54cd895afc98..0fd8d49bdd7897755f20e3c8f07e7d75fc98499b 100644
--- a/toar_location_services/urls.py
+++ b/toar_location_services/urls.py
@@ -8,5 +8,6 @@ urlpatterns = [
     url(r'major-roads/', include('major-roads.urls'), name='major-roads'),
     url(r'population-density/', include('population-density.urls'), name='population-density-density'),
     url(r'topography-tandem-x/', include('topography-tandem-x.urls'), name='topography-tandem-x'),
-    url(r'stable_night_lights/', include('stable_night_lights.urls'), name='stable_night_lights')
+    url(r'stable_night_lights/', include('stable_night_lights.urls'), name='stable_night_lights'),
+    url(r'wheat_production/', include('wheat_production.urls'), name='wheat_production')
 ]
diff --git a/toar_location_services/views.py b/toar_location_services/views.py
index 075480761b458fa2bc8100b0d70ad7568431734b..a90aa29405f319a04c1be88af373a297009aded9 100644
--- a/toar_location_services/views.py
+++ b/toar_location_services/views.py
@@ -3,7 +3,6 @@ from rest_framework.views import APIView
 from rest_framework.response import Response
 
 
-
 class LocationServicesRootView(APIView):
     """Local services REST services"""
 
@@ -16,6 +15,7 @@ class LocationServicesRootView(APIView):
                 ('population-density', request.build_absolute_uri()+'population-density/'),
                 ('topography-tandem-x', request.build_absolute_uri()+'topography-tandem-x/'),
                 ('stable_night_lights', request.build_absolute_uri()+'stable_night_lights/'),
+                ('wheat_production', request.build_absolute_uri()+'wheat_production/'),
             ]),
         ]
         # add admin view if staff user
diff --git a/wheat_production/serializers.py b/wheat_production/serializers.py
new file mode 100644
index 0000000000000000000000000000000000000000..09234953d78f6f3c97f24dfb69d6360878675513
--- /dev/null
+++ b/wheat_production/serializers.py
@@ -0,0 +1,75 @@
+"""serializer for wheat production data
+"""
+
+from collections import OrderedDict
+import datetime as dt
+from rest_framework.serializers import BaseSerializer
+
+
+# helper functions
+
+def get_provenance(obj):
+    """construct provenance information on population density dataset"""
+    prov = OrderedDict([
+        ('dataset_name', '?'),
+        ('dataset_description', """Wheat production ?"""),
+        ('data_source', """?"""),
+        ('datacenter_url', '?'),
+        ('download_date', '?'),
+        ('timestamp', dt.datetime.now().isoformat())
+    ])
+    return prov
+
+
+# serializer classes
+class AggSerializer(BaseSerializer):
+    """ see http://www.django-rest-framework.org/api-guide/serializers/#baseserializer """
+
+    def to_representation(self, obj):
+        """takes dictionary-like obj and returns geojson compliant structure"""
+        agg_function = obj['agg_function']
+        val = obj[agg_function]
+
+        # build GeoJSON response with 'provenance' extension
+        # ToDo (probably in views): change content-type to application/vnd.geo+json
+        # ToDo: enable support for different output formats
+        # format properties depending on 'by_direction' (vector or not)
+        try:
+            vlength = len(val)
+        except TypeError:
+            vlength = 1
+        if vlength > 1:
+            properties = OrderedDict([
+                ('agg_function', agg_function),
+                ('many', True),
+                (agg_function, OrderedDict([
+                    (d, v) for d, v in zip(obj['direction'], val)
+                ])),
+                ('units', 'km-2'),
+                ('radius', obj['radius']),
+            ])
+            if obj['direction'] is None:
+                properties.pop('direction')
+        else:
+            properties = OrderedDict([
+                ('agg_function', agg_function),
+                ('many', False),
+                (agg_function, val),
+                ('units', 'km-2'),
+                ('radius', obj['radius']),
+                ('direction', obj['direction']),
+            ])
+            if obj['direction'] is None:
+                properties.pop('direction')
+
+        response = OrderedDict([
+            ('type', 'Feature'),
+            ('geometry', OrderedDict([
+                ('type', 'Point'),
+                ('coordinates', [obj['lon'], obj['lat']]),
+                ])),
+            ('properties', properties),
+            ('provenance', get_provenance(obj)),
+        ])
+
+        return response
diff --git a/wheat_production/tests.py b/wheat_production/tests.py
index 7ce503c2dd97ba78597f6ff6e4393132753573f6..1e0e74f059a55bd8bbf617f1ccb2fd0bcc3050ee 100644
--- a/wheat_production/tests.py
+++ b/wheat_production/tests.py
@@ -1,3 +1,10 @@
 from django.test import TestCase
 
 # Create your tests here.
+
+from wheat_file_extraction import read_proxydata
+
+
+FILENAME = "wheat.txt"
+
+read_proxydata(FILENAME, dummy=False)
diff --git a/wheat_production/urls.py b/wheat_production/urls.py
new file mode 100644
index 0000000000000000000000000000000000000000..8b0dbc25b9c680646c3b023897bc7c349228820d
--- /dev/null
+++ b/wheat_production/urls.py
@@ -0,0 +1,6 @@
+from django.conf.urls import url
+from .views import WheatView
+
+urlpatterns = [
+    url(r'^$', WheatView.as_view()),
+    ]
diff --git a/wheat_production/views.py b/wheat_production/views.py
index 91ea44a218fbd2f408430959283f0419c921093e..7134e695b5d2bd3b7b802ecf9141b4f79cf12147 100644
--- a/wheat_production/views.py
+++ b/wheat_production/views.py
@@ -1,3 +1,94 @@
-from django.shortcuts import render
+import datetime as dt
+import numpy as np
+from collections import OrderedDict
+from rest_framework.views import APIView
+from rest_framework.response import Response
+
+from toar_location_services.settings import DEBUG
+from .wheat_file_extraction import read_proxydata
+from .serializers import AggSerializer
+from utils.views_commons import get_query_params, get_agg_function
+from utils.geoutils import Directions
+from utils.extraction_tools import extract_value, extract_value_stats
+
+FILENAME = "wheat.txt"
+
+lonvec, latvec, data, datainfo = read_proxydata(FILENAME)
+
+if DEBUG:
+    print("File %s successfully loaded" % FILENAME, datainfo)
+
+
+class WheatView(APIView):
+
+    def _extract(self, lat, lon, radius, agg, direction, by_direction):
+        """perform actual extraction of desired quantity"""
+        print('**by_direction:', by_direction, '** radius, agg = ', radius, agg)
+        if agg is not None and radius is not None and radius > 0.:
+            agg_function = get_agg_function(agg)
+            min_angle = None
+            max_angle = None
+            if by_direction:
+                result = np.zeros((16,))
+                direction = Directions.LABELS
+                for i, d in enumerate(Directions.LABELS):
+                    min_angle, max_angle = Directions.edges(d)
+                    # ToDo: once we serve the data via rasdaman the calls with directions should use
+                    # a polygon query for efficiency reasons.
+                    result[i] = extract_value_stats(lonvec, latvec, data, lon, lat, default_value=-999.,
+                                                 out_of_bounds_value=0., min_valid=0., max_valid=2.e6,
+                                                 radius=radius, min_angle=min_angle, max_angle=max_angle,
+                                                 agg=agg_function)
+            else:
+                if direction is not None:
+                    min_angle, max_angle = Directions.edges(direction)
+                    # ToDo: once we serve the data via rasdaman the calls with directions should use
+                    # a polygon query for efficiency reasons.
+                result = extract_value_stats(lonvec, latvec, data, lon, lat, default_value=-999.,
+                                             out_of_bounds_value=0., min_valid=0., max_valid=2.e6,
+                                             radius=radius, min_angle=min_angle, max_angle=max_angle,
+                                             agg=agg_function)
+        else:
+            agg = 'value'
+            result = extract_value(lonvec, latvec, data, lon, lat, default_value=-999.,
+                                   out_of_bounds_value=0., min_valid=0., max_valid=2.e6)
+        # return data, also return agg and direction as they may have been overwritten
+        return result, agg, direction
+
+    def get(self, request, format=None):
+        """process GET requests for wheat_production app
+
+        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.).
+        by_direction: if True, data are returned as vector with one value aggregated
+            over each of 16 wind directions.
+        """
+        lat, lon, radius, agg, direction, by_direction = get_query_params(request.query_params,
+                                                 ['lat', 'lon', 'radius', 'agg', 'direction', 'by_direction'])
+        result, agg, direction = self._extract(lat, lon, radius, agg, direction, by_direction)
+
+        rawdata = OrderedDict([
+            ("lat", lat),
+            ("lon", lon),
+            ("radius", radius),
+            ("direction", direction),
+            ("agg_function", agg),
+            (agg, result),
+        ])
+        response = AggSerializer(rawdata).data
+        return Response(response)
 
-# Create your views here.
diff --git a/wheat_production/wheat_file_extraction.py b/wheat_production/wheat_file_extraction.py
new file mode 100644
index 0000000000000000000000000000000000000000..c855e51796a4c7b9383cb42a319ea87ee4132cd3
--- /dev/null
+++ b/wheat_production/wheat_file_extraction.py
@@ -0,0 +1,90 @@
+#!/usr/bin/python
+"""
+Import wheat production from .txt-file
+
+Author: Lukas Leufen, FZ Juelich (24th May 2019)
+"""
+
+import numpy as np
+import os
+from toar_location_services.settings import DATA_DIR, DEBUG, USE_DUMMY_WHEAT_DATA, PLOT_DATA
+import matplotlib.pyplot as plt
+
+
+def read_proxydata(filename, dummy=DEBUG and USE_DUMMY_WHEAT_DATA):
+    """Read the ascii file and return the data array together with
+    some dataset properties for use in the extraction routines.
+
+    filename: name of data file (wheat.txt)
+    dummy: if true a small set of dummy data are returned to speed up development of other services
+    """
+
+    if dummy:
+        return create_dummy_data()
+
+    if DEBUG:
+        print("DATA_DIR =  ", DATA_DIR, "...")
+        print("Opening ", os.path.join(DATA_DIR, filename), "...")
+
+    with open(os.path.join(DATA_DIR, filename), "r") as dataset:
+        tok, cols = dataset.readline().split()
+        tok, rows = dataset.readline().split()
+        cols = int(cols)
+        rows = int(rows)
+        tok, lon0 = dataset.readline().split()
+        tok, lat0 = dataset.readline().split()
+        tok, dlon = dataset.readline().split()
+        lon0 = float(lon0)
+        lat0 = float(lat0)
+        dlon = float(dlon)
+        dlat = dlon
+        tok, missval = dataset.readline().split()
+
+        # construct data array and lonvec, latvec
+        data = np.zeros((rows, cols), dtype='f4')
+        lonvec = np.linspace(lon0, lon0 + cols * dlon, cols)
+        latvec = np.linspace(lat0, lat0 + rows * dlat, rows)
+
+        # data are flipped, therefore reverse latitudes
+        # trick from http://stackoverflow.com/questions/6771428/most-efficient-way-to-reverse-a-numpy-array
+        latvec = np.fliplr(np.atleast_2d((latvec)))[0]
+
+        # read actual data
+        for i, line in enumerate(dataset):
+            row = np.array([float(x) for x in line.split()], dtype='f4')
+            data[i, :] = row
+
+        # correct missing values
+        data[data == float(missval)] = np.nan
+
+    logdata = data.copy()
+    logdata[logdata <= 1.e-4] = 1.e-4
+
+    if DEBUG and PLOT_DATA:
+        plt.contourf(lonvec, latvec, np.log10(logdata))
+        plt.savefig('../plots/global_wheat_production.png')
+        plt.close()
+
+    # set metadata
+    boundingbox = [lon0, lat0, lonvec.max(), latvec.max()]
+
+    datainfo = {'size': (rows, cols), 'resolution': (np.abs(dlon), np.abs(dlat)),
+                'boundingbox': boundingbox}
+    return lonvec, latvec, data, datainfo
+
+
+def create_dummy_data():
+    """generate some small dummy data set for testing of other services
+    This avoids loading of a large file
+    Eventually this should become obsolete when we have rasdaman running..."""
+    lonvec = np.array([4., 5., 6.])
+    latvec = np.array([52., 53., 54.])
+    data = np.array([[1., 10., 11.], [0., 2.5, 3.], [6., 7., 8.]])
+    datainfo = {'size': (3, 3), 'resolution': (1., 1.),
+                'boundingbox': [4., 52., 6., 54.]}
+    msg = "#DEBUG: Using dummy data for wheat production"
+    if DEBUG:
+        print(msg)
+    else:
+        raise UserWarning(msg)
+    return lonvec, latvec, data, datainfo