The Processes

The default location for processes is PYWPS_INSTALLATION_PATH/pywps/processes. You can create custom directory anywhere in your system and set PYWPS_PROCESSES environmental variable (on how to do this for the web server, refer to your Server documentation, see sections :role:`Wrapper script` and :role:`Customising PyWPS Installation` for details).

Alternatively you can set the processesPath variable in the configuration file. Following example will describe buffering process. Several example processes are distributed along with PyWPS source code (they are in the doc/examples/processes directory) – feel free to get inspired by them.

Process initialization and configuration – the init() method

  1. Create file foo.py in PYWPS_PROCESSES directory.
  2. Add ‘foo’ to __all__ list in the __init__.py file.

Each process is stand-alone python script with one class :class:Process, which has two methods: __init__(), execute(). It is possible also to add as many your functions/methods, as you wish.:

from pywps.Process.Process import WPSProcess
class Process(WPSProcess):
    """Main process class"""
    def __init__(self):
        """Process initialization"""
        # init process
        WPSProcess.__init__(self,
            identifier = "foo", # must be same, as filename
            title="Buffer",
            version = "0.2",
            storeSupported = "true",
            statusSupported = "true",
            abstract="Create a buffer around an input vector file",

We defined new process called foo. The process is allowed to store it’s output data on the server (storeSupported) and it is also possible to run it in asynchronous mode (statusSupported). The process will run within GRASS GIS environment (grassLocation = True) – temporary location will be created and deleted again, after the processes is done.

Mandatory parameters of the __init__() method

identifier
{String} process identifier
title
{String} process title

Optional parameters of the __init__() method

abstract

{String} process description

default: None

metadata

List of additional metadata. See http://www.opengeospatial.org/standards/common, table 32 on page 65

example {"foo":"bar"}

default None

profile

{String} URL

default: None

version
{String} process version default: None
statusSupported

{Boolean} this process can be run asynchronously

default: True

storeSupported

{Boolean} outputs from this process can be stored for later download

default: True

grassLocation

{String} or {Boolean} name of GRASS Location within gisdbase directory (from pywps.cfg configuration file). If set to True, temporary GRASS Location will be created and grass environment will be started. If None or False, no GRASS environment will be started.

default: None

Data Inputs

Three types of data inputs are defined:

Literal Input
Basic literal input – single number or text value
ComplexValue Input
Mostly vector file will be included in input XML request. It can be also only referenced (only URL will be send).
BoundingBox Input
Coordinates for lower-left and upper-right corner.

ComplexInput

Complex input can be raster or vector file, to be processed.

self.dataIn = self.addComplexInput(identifier="data",
                     title = "Input data")
Mandatory parameters
identifier
String input identifier
title
String input title
Optional parameters
abstract
String input description.

default: None

metadata
List of Dict {key:value} pairs.

default: None

minOccurs

Integer minimum number of occurrences.

default: 1

maxOccurs

Integer maximum number of occurrences.

default: 1

formats

List of Dict according to table 23 (page 25) in WPS 1.0.0 spec.

Example::
[

{“mimeType”: “image/tiff”}, {

“mimeType”: “text/xml”, “encoding”: “utf-8”, “schema”:”http://foo/bar

}

]

default: [{"mimeType":"text/xml"}]

maxmegabites

Float Maximum input file size. Can not be bigger, as defined in global configuration file.

default: 5

LiteralInput

With literal input, you can obtain any type of character string. You will obtain instance of LiteralInput class using addLiteralInput():

self.widthIn = self.addLiteralInput(identifier = "width",
                     title = "Width")
Mandatory parameters
identifier
String input identifier
title
String input title
Optional parameters
abstract

String input description.

Default: None

uoms

List of String value units

Default: ()

minOccurs

Integer minimum number of occurrences.

Default: 1

maxOccurs

Integer maximum number of occurrences.

Default: 1

allowedValues
List of String or other allowed values,

which can be used with this input. You can set interval using list with two items, like:

(1,2,3,(5,9),10,"a",("d","g"))

This will produce allowed values 1,2,3,10, “a” and any value between 5 and 9 or “d” and “g”.

If "*" is used, it means “any value”

default: (“*”)

type
types.TypeType value type, e.g. Integer, String, etc. you

can uses the types module of python.

default: types.IntType

default

Any default value.

default: None

metadata

List of Dict Additional metadata.

example:

{"foo":"bar"}

default: None

BoundingBox Input

The input is added to the process using addBBoxInput().

Mandatory parameters
identifier
String input identifier
title
String input title
Optional parameters
abstract
String input description.

default: None

metadata

List of Dict {key:value} pairs.

default: None

minOccurs

Integer minimum number of occurrences.

default: 1

maxOccurs

Integer maximum number of occurrences.

default: 1

crss

List of `String`s supported coordinate systems.

default: ["EPSG:4326"]

For further documentation, refer to example processes distributed with the source code as well as pydoc pywps/Wps/Process/Process.py.

Data Outputs

Data outputs can be defined in similar way. * Literal Output * ComplexValue Output * BoundingBox Output

ComplexValue Output

The complex value can be raster or vector file (or any other binary or text file).:

self.bufferOut = self.addComplexOutput(identifier="buffer",
                        title="Output buffer file")
Mandatory parameters
identifier
String input identifier
title
String input title
Optional parameters
abstract
String input description.

default: None

metadata
List of Dict {key:value} pairs.

default: None

formats

List of Dict according to table 23 (page 25) in WPS 1.0.0 spec.

Example::
[

{“mimeType”: “image/tiff”}, {

“mimeType”: “text/xml”, “encoding”: “utf-8”, “schema”:”http://foo/bar

}

]

default: [{"mimeType":"text/xml"}]

Literal Output

If you want to output any text string.:

self.textOut = self.addLiteralOutput(identifier="text",
                     title="just some text")
Mandatory parameters
identifier
String input identifier
title
String input title
Optional parameters
abstract

String input description.

Default: None

uoms

List of String value units

Default: ()

type
types.TypeType value type, e.g. Integer, String, etc. you

can uses the types module of python.

default: types.IntType

default

Any default value.

default: None

BoundingBox Output

BoundingBox output is added with the addBBoxOutput() method

Mandatory parameters
identifier
String input identifier
title
String input title
Optional parameters
abstract
String input description.

default: None

crss

List of `String`s supported coordinate systems.

default: ["EPSG:4326"]

dimensions

Integer number of dimensions

default: 2

For further documentation, refer to example processes distributed with the source code as well as pydoc pywps/Wps/Process/Process.py.

Process Programming – the execute() method

The process must be defined in the execute() method. Basically, you want to get input values and set output values. For this purpose, you can use getInputValue() and setOutputValue() methods of the Process or getValue() and setValue() of the input/output objects (see below).

If you need to execute some shell command, you should use cmd() instead of e.g.

os.system() or os.popen functions.

Calculation progress can be set using self.status.set(string message, number percent) method.

Example follows:

def execute(self):
        """Execute process.

        Each command will be executed and output values will be set
        """

         # run some command from the command line
         self.cmd("g.region -d")

         # set status value
         self.status.set("Importing data",20)
         self.cmd("v.in.ogr dsn=%s output=data" %\
                 (self.getInputValue('data')))

         self.status.set("Buffering",50)
         self.cmd("v.buffer input=data output=data_buff buffer=%s scale=1.0 tolerance=0.01" %\
                 (self.getInputValue('width')))

         self.status.set("Exporting data",90)

         self.cmd("v.out.ogr type=area format=GML input=data_buff dsn=out.xml olayer=path.xml")

         self.bufferOut.setValue("out.xml")
         self.textOut.setValue("hallo, world")
         return

Error handling

At the end of the execute() function, None value should be returned. Any other value means, that the calculation will be stopped and error report will be returned back to the client, example:

def execute(self):
    ...
    return "Ups, something failed!"

Using GRASS GIS

Configuration is done using standard pywps configuration file see Configuration).

If you want to use GRASS GIS commands in your process, and there is no GRASS Location to be used, you have to set grassLocation=True in process definition:

WPSProcess.__init__(self, identifier = "foo",
    ...
    grassLocation = True)

In this case, temporary GRASS Location will be created and after the process is done, it will be deleted again. By default, no GRASS Location is created.

You can also work in existing GRASS Location, then just set only the location name. The gisdbase should be set in the configuration file Configuration:

WPSProcess.__init__(self, identifier = "foo",
    ...
    grassLocation = "spearfish60")

In this case, you had to specify gisdbase option in [grass] section of the configuration file. Otherwise, you have to specify full path to existing location, e.g.:

WPSProcess.__init__(self,
    identifier = "foo",
    ...
    grassLocation = "/foo/bar/grassdata/spearfish60")

Testing your new process

To test your PyWPS installation, you run it either as Webserver cgi-application or in the command line directly. It is always good to start with the command line test, so do not have to check error.log of the web server or the file, you set as logFile in the configuration file.

GetCapabilities request::

$ wps.py “service=wps&request=getcapabilities”

$ wget -nv -q -O - “http://localhost/cgi-bin/wps.py?
service=Wps&request=getcapabilities”

DescribeProcess request:

$ wps.py "version=1.0.0&service=Wps&\
            request=DescribeProcess&\
            Identifier=bufferExampleProcess"

$ wget -nv -q -O - "http://localhost/cgi-bin/wps.py?\
                    version=0.4.0&service=Wps&\
                    request=DescribeProcess&Identifier=foo"
Execute request:

For data inputs encoding, using HTTP Get method, see WPS 1.0.0 specification, page 38 Execute HTTP GET request KVP encoding:

./wps.py "version=1.0.0&service=Wps&request=Execute&\
Identifier=foo&datainputs=data=http://foo/bar/roads.gml;width=0.5”

Some examples of XML request econding are available in doc/examples directory.

Before testing WPS via HTTP POST, you have to set REQUEST_METHOD environment variable, then you can redirect input XML into wps.py script via standard input:

$ export REQUEST_METHOD=POST
$ cat doc/wps_execute_request-responsedocument.xml| wps.py