Unit 28 - PyWPS LST point statsΒΆ

Second version of our WPS process will return LST statistics for given point in Germany (referenced in EPSG:3035). Input parameters are defined on lines 10, 12, 14. The output is defined as JSON, see line 17.

The pixel extraction is done by t.rast.what on line 62. Statistics is computed based on command output somehow manually on lines 73-96. Resultant Python dictionary is converted to JSON structure using json Python library on line 98.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
import os
import json

from pywps import Process, LiteralInput, ComplexOutput, Format

__author__ = 'Martin Landa'

class ModisV2(Process):
    def __init__(self):
        inputs = [LiteralInput('coords', 'UTM coordinates',
                               data_type='string'),
                  LiteralInput('start', 'Start date (eg. 2017-03-01)',
                               data_type='string'),
                  LiteralInput('end', 'End date (eg. 2017-04-01)',
                               data_type='string')
        ]
        outputs = [ComplexOutput('stats', 'Computed LST statistics',
                                 supported_formats=[Format('application/json')])
        ]

        super(ModisV2, self).__init__(
            self._handler,
            identifier='modis-v2',
            version='0.2',
            title="Modis process (v2)",
            abstract='The process uses the GRASS GIS to compute LST ' \
            'statistics for given period in 2017 for Germany',
            profile='',
            inputs=inputs,
            outputs=outputs,
            store_supported=True,
            status_supported=True,
            grass_location="/opt/grassdata/germany-modis"
        )

    def check_date(self, date_str):
        from datetime import datetime

        d = datetime.strptime(date_str, '%Y-%m-%d')
        if d.year != 2017:
            raise Exception("Only year 2017 allowed")

    def _handler(self, request, response):
        from subprocess import PIPE
        
        from grass.pygrass.modules import Module
        from grass.exceptions import CalledModuleError
        
        start = request.inputs['start'][0].data
        end = request.inputs['end'][0].data
        self.check_date(start)
        self.check_date(end)

        x, y = request.inputs['coords'][0].data.split(',')
        
        # be silent
        os.environ['GRASS_VERBOSE'] = '0'

        # need to set computation region (would be nice g.region strds or t.region)
        Module('g.region', raster='c_001')
        try:
            ret = Module('t.rast.what',
                         stdout_=PIPE,
                         strds='modis_c@PERMANENT',
                         coordinates=[x, y],
                         separator=',',
                         where="start_time > '{start}' and start_time < '{end}'".format(
                             start=start, end=end
            ))
        except CalledModuleError:
            raise Exception('Unable to compute statistics')

        tsum = 0
        stats = {
            'min' : None,
            'max' : None,
            'mean' : None,
            'count' : 0,
        }
        count = 0
        for line in ret.outputs.stdout.splitlines():
            items = line.split(',')
            if items[-1] == '*': # no data
                continue
            val = float(items[-1])
            if stats['min'] is None:
                stats['min'] = stats['max'] = stats['mean'] = val
            else:
                if val < stats['min']:
                    stats['min'] = val
                if val > stats['max']:
                    stats['max'] = val
            tsum += val
            stats['count'] += 1
                    
        stats['mean'] = tsum / stats['count']
        
        response.outputs['stats'].data = json.dumps(stats)
        
        return response

Sample process to download: modis_v2.py

Do not forget to import process as done in Unit 27 and restart demo PyWPS server.

Example of execute request:

http://localhost:5000/wps?request=Execute&service=WPS&identifier=modis-v2&version=1.0.0&datainputs=start=2017-03-01;end=2017-04-01;coords=4351849,3120313

Possible response.

<wps:ComplexData mimeType="application/json">
{"count": 14, "max": 16.93, "mean": 6.598571428571452, "min": -1.22999999999996}
</wps:ComplexData>

Try to improve the process in order to validate coordinates. Only Germany area is supported.