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 :wikipedia-en:`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.