5. Geo Services Guide

This guide covers the details of geo data management and retrieval in rasdaman. The rasdaman Array DBMS is domain agnostic; the specific semantics of space and time is provided through a layer on top of rasdaman, historically known as petascope. It offers spatio-temporal access and analytics through APIs based on the OGC data standard Coverage Implementation Schema (CIS) and the OGC service standards Web Map Service (WMS), Web Coverage Service (WCS), and Web Coverage Processing Service (WCPS).


While the name petascope addresses a specific component we frequently use the name rasdaman to refer to the complete system, including petascope.

5.1. OGC Coverage Standards Overview

For operating rasdaman geo services as well as for accessing such geo services through these APIs it is important to understand the mechanics of the relevant standards. In particular, the concept of OGC / ISO coverages is important.

In standardization, coverages are used to represent space/time varying phenomena, concretely: regular and irregular grids, point clouds, and general meshes. The coverage standards offer data and service models for dealing with those. In rasdaman, focus is on multi-dimensional gridded (“raster”) coverages.

In rasdaman, the OGC standards WMS, WCS, and WCPS are supported, being reference implementation for WCS. These APIs serve different purposes:

  • WMS delivers a 2D map as a visual image, suitable for consunmption by humans
  • WCS delivers n-D data, suitable for further processing and analysis
  • WCPS performs flexible server-side processing, filtering, analytics, and fusion on coverages.

These coverage data and service concepts are summarized briefly below; for specific details on coordinate reference system handling see also CRS definition management. Ample material is also available on the Web for familiarization with coverages (best consult in this sequence):

5.1.1. Coverage Data

OGC CIS specifies an interoperable, conformance-testable coverage structure independent from any particular format encoding. Encodings are defined in OGC in GML, JSON, RDF, as well as a series of binary formats including GeoTIFF, netCDF, JPEG2000, and GRIB2).

By separating the data definition (CIS) from the service definition (WCS) it is possible for coverages to be served throuigh a variety of APIs, such as WMS, WPS, and SOS. However, WCS and WCPS have coverage-specific functionality making them particularly suitable for flexible coverage acess, analytics, and fusion.

5.1.2. Coverage Services

OGC WMS delivers 2D maps generated from styled layers stacked up. As such, WMS is a visualization service sitting at the end of processing pipelines, geared towards human consumption.

OGC WCS, on the other hand, rpovides data suitable for further processing (including visualization); as such, it is suitable also for machine-to-machine communication as it appears in the middle of longer processing pipelines. WCS is a modular suite of service functionality on coverages. WCS Core defines download of coverages and parts thereof, through subsetting directives, as well as delivery in some output format requested by the client. A set of WCS Extensions adds further functionality facets.

One of those is WCS Processing; it defines the ProcessCoverages request which allows sending a coverage analytics request through the WCPS spatio-temporal analytics language. WCPS supports extraction, analytics, and fusion of multi-dimensional coverage expressed in a high-level, declarative, and safe language.

5.2. OGC Web Services Endpoint

Once the petascope servlet is deployed (see rasdaman installation guide) coverages can be accessed through service endpoint /rasdaman/ows.


Endpoint /rasdaman/rasql, which by default is also available after deploying rasdaman, does not know about coverages and their services, but only knows domain-agnostic rasql.

For example, assuming that the service’s IP address is 123.456.789.1 and the service port is 8080, the following request URLs would deliver the Capabilities documents for OGC WMS and WCS, respectively:


5.3. OGC Coverage Implementation Schema (CIS)

A coverage consists mainly of:

  • domain set: provides information about where data sit in space and time. All coordinates expressed there are relative to the coverage’s Coordinate Reference System or Native CRS. Both CRS and its axes, units of measure, etc. are indiciated in the domain set. Petascope currently supports grid topologies whose axes are aligned with the axes of the CRS. Along these axes, grid lines can be spaced regularly or irregularly.
  • range set: the “pixel payload”, ie: the values (which can be atomic, like in a DEM, or records of values, like in hyperspectral imagery).
  • range type: the semantics of the range values, given by type information, null values, accuracy, etc.
  • metadata: a black bag which can contain any data: the coverage will not understand these, but duly transport them along so that the connection between data and metadata is not lost.

Further components include Envelope which gives a rough, simplified overview on the coverage’s location in space and time and CoverageFunction which is unused by any implementation known to us.

5.3.1. Coordinate Reference Systems in Coverages

Every coverage, as per OGC CIS, must have exactly one Native CRS. Sometimes definitions for such CRSs are readily available, such as with the EPSG registry where 2-D WGS84 is readily available under its code EPSG:4326. In particular spatio-temporal CRSs, however, are not always readily available, at least not in all combinations of spatial and temporal axes. To this end, composition of CRS is supported so that the single Native CRS can be built from “ingredient” CRSs by concatenating these CRSs into a composite one.

For instance, a time-series of WGS84 images would have the following Native CRS:


Coordinate tuples in this CRS represent an ordered composition of a geospatial CRS with Latitude followed by Longitude, as per EPSG:4326, followed by a temporal coordinate expressed in ISO 8601 syntax, such as: 2012-01-01T00:01:20Z.

Several ways exist for determining the Native CRS of coverage domain set:

  • in a WCS GetCapabilities response, check the wcs:CoverageSummary/ows:BoundingBox@crs attribute;
  • in a WCS DescribeCoverage response, check the @srsName attribute in the gml:domainSet;
  • in WCPS, use function crsSet(e) to determine the CRS of a coverage expression e;


In a coverage also consider the axisLabels attributes giving the axis names as used in the coverage, in proper sequence as per CRS; the uomLabels attribute contains the units of measure for each axis.

The following graphics illustrates, on the example of an image timeseries, how dimension, CRS, and axis labels affect the domain set in a CIS 1.0 RectifiedGridCoverage.



This handling of coordinates in CIS 1.0 bears some legacy burden from GML; in the GeneralGridCoverage introduced with CIS 1.1 coordinate handling is much simplified.

5.3.2. CRS Management

the Native CRS of a coverage is given by a URL, as per OGC convention. Resolving this URL should deliver the CRS definition. The OGC CRS resolver is one such service. Its implementation is running SECORE which is part of rasdaman community.

By providing the source code of the OGC resolver it is possible to deploy one’s own resolver under an own URL, such as http://rasdaman.org:8080/def/crs/EPSG/0/27700.

5.3.3. Range Type

Range values can be atomic or (possibly nested) records over atomic values, described by the range type. In rasdaman the following atomic data types are supported; all of these can be combined freely in records of values, such as in hyperspectral images or climate variables.

Table 5.1 Mapping of rasdaman base types to SWE Quantity types
rasdaman type size Quantity types
boolean 8 bit unsignedByte
octet 8 bit signedByte
char 8 bit unsignedByte
short 16 bit signedShort
unsigned short = ushort 16 bit unsignedShort
long 32 bit signedInt
unsigned long = ulong 32 bit unsignedInt
float 32 bit float32
double 64 bit float64
complex 64 bit cfloat32
complexd 128 bit cfloat64

5.3.4. Nil Values

Nil (“null”) values, as per SWE, are supported by rasdaman in an extended way:

  • null values can be defined over any data type
  • nulls can be single values
  • nulls can be intervals
  • a null definnition in a coverage can be a list of all of the above alternatives.


It is highly recommended to NOT define null values over floating-point numbers as this causes numerical problems well known in mathematics. This is not related to rasdaman, but intrinsic to the nature and handling of floating-point numbers in computers. If really desired, a floating-point interval should be defined around the desired float null value (this corresponds to interval arithmetics in numerical mathematics).

5.4. OGC Web Coverage Service

WCS Core offers request types:

  • GetCapabilities for obtaining a list of coverages offered together with an overall service description;
  • DescribeCoverage for obtaining information about a coverage without downloading it;
  • GetCoverage for downloading, extracting, and reformatting of coverages; this is the central workhorse of WCS.

WCS Extensions in part enhance GetCoverage with additional functionality controlled by further parameters, and in part establish new request types, such as:

  • WCS-T defining InsertCoverage, DeleteCoverage, and UpdateCoverage requests;
  • WCS Processing defining ProcessCoverages for submitting WCPS analytics code.

You can use http://localhost:8080/rasdaman/ows as service endpoints to which to send WCS requests, for example:


See example queries in the WCS systemtest which send KVP (key value pairs) GET request and XML POST request to Petascope.

5.4.1. Subsetting behavior

In general, subsetting in petascope behaves similarly to subsetting in gdal, with a couple of deviations necessary for n-D. Specifically, subsetting follows the next rules:

  • Slicing (geoPoint): the grid slice with index corresponding to the requested slicing geo point is returned. This is computed as follows:

    gridIndex = floor((geoPoint - minGeoLowerBound) / axisResolution)
  • Trimming (geoLowerBound:geoUpperBound): the lower bound of the grid interval is determined as in the case of slicing. The number of returned grid points follows gdal:

    • If axis resolution is positive (e.g. Long axis):
    • If axis resolution is negative (e.g. Lat axis):


    If a trimming subset is applied on an axis with (geoUpperBound - geoLowerBound) / axisResolution < 0.5, then lower grid bound is translated by the slicing formula and upper grid bound is set to lower grid bound.

For example, a 2D coverage has Long (X) and Lat (Y) axes with CRS EPSG:4326. The resolution for axis Long is 10 and the resolution for axis Lat is -10. The geo bounds of axis Long are [0:180] and the geo bounds of axis Lat are [0:90].

  • Calculate slicing on Long axis by geo coordinates to grid coordinates:

    - Long(0):          returns [0]
    - Long(9):          returns [0]
    - Long(10):         returns [1]
    - Long(15):         returns [1]
    - Long(20):         returns [2]
    - Long(40):         returns [4]
    - Long(49.99999):   returns [4]
    - Long(50.0):       returns [5]
  • Calculate trimming on Long axis by geo coordinates to grid coordinates:

    - Long(0:5):         returns [0:0]
    - Long(0:10):        returns [0:0]
    - Long(0:14.999):    returns [0:0]
    - Long(0:15):        returns [0:1]
    - Long(0:24.999):    returns [0:1]
    - Long(0:25.0):      returns [0:2]
    - Long(9,11): returns [0:0]

5.4.2. CIS 1.0 to 1.1 Transformation

Under WCS 2.1 - ie: with SERVICE=2.1.0 - both DescribeCoverage``and ``GetCoverage requests understand the proprietary parameter OUTPUTTYPE=GeneralGridCoverage which formats the result as CIS 1.1 GeneralGridCoverage even if it has been imported into the server as a CIS 1.0 coverage, for example:



5.4.3. Polygon/Raster Clipping

WCS and WCPS support clipping of polygons expressed in the WKT format format. Polygons can be MultiPolygon (2D), Polygon (2D) and LineString (1D+). The result is always a 2D coverage in case of MultiPolygon and Polygon, and is a 1D coverage in case of LineString.

Further clipping patterns include curtain and corridor on 3D+ coverages from Polygon (2D) and Linestring (1D). The result of curtain clipping has the same dimensionality as the input coverage whereas the result of corridor clipping is always a 3D coverage, with the first axis being the trackline of the corridor by convention.

Below some examples are presented expaining the mimics for WCS.

Syntactically, clipping is expressed by adding a &CLIP= parameter to the request. If the SUBSETTINGCRS parameter is specified then this CRS also applies to the clipping WKT, otherwise it is assumed that the WKT is in the Native coverage CRS. Clipping Examples

  • Polygon clipping on coverage with Native CRS EPSG:4326, for example:

    ▶ show

  • Polygon clipping with coordinates in EPSG:3857 (from subsettingCRS parameter) on coverage with Native CRS EPSG:4326, for example:

    ▶ show

  • Linestring clipping on a 3D coverage with axes X, Y, ansidate, for example:

    ▶ show

  • Multipolygon clipping on 2D coverage, for example:

    ▶ show

  • Curtain clipping by a Linestring on 3D coverage, for example:

    ▶ show

  • Curtain clipping by a Polygon on 3D coverage, for example:

    ▶ show

  • Corridor clipping by a Linestring on 3D coverage, for example:

    ▶ show

  • Corridor clipping by a Polygon on 3D coverage, for example:

    ▶ show

5.4.4. WCS-T

Currently, WCS-T supports importing coverages in GML format. The metadata of the coverage is thus explicitly specified, while the raw cell values can be stored either explicitly in the GML body, or in an external file linked in the GML body, as shown in the examples below. The format of the file storing the cell values must be

The coverage metadata must be in XML or JSON format; any other format will lead to an error.

In addition to the WCS-T standard parameters petascope supports additional proprietary parameters.


For coverage management normally WCS-T is not used directly. Rather, the more convenient wcst_import Python importing tool is recommended for Data Import. Inserting coverages

Inserting a new coverage into the server’s WCS offerings is done using the InsertCoverage request.

Table 5.2 WCS-T Standard Parameters
Request Parameter Value Description Required
SERVICE WCS service standard Yes
VERSION 2.0.1 or later WCS version used Yes
REQUEST InsertCoverage Request type to be performed Yes
INPUTCOVERAGEREF {url} URl pointing to the coverage to be inserted One of inputCoverageRef or inputCoverage is required
INPUTCOVERAGE {coverage} A coverage to be inserted One of inputCoverageRef or inputCoverage is required
USEID new | existing Indicates wheter to use the coverage’s id (“existing”) or to generate a new unique one (“new”) No (default: existing)
Table 5.3 WCS-T Proprietary Enhancements
Request Parameter Value Description Required
PIXELDATATYPE GDAL supported base data type (eg: “Float32”) or comma-separated concatenated data types, (eg: “Float32,Int32,Float32”) In cases where range values are given in the GML body the datatype can be indicated through this parameter. Default: Byte. No
TILING rasdaman tiling clause, see wiki:Tiling Indicates the array tiling to be applied during insertion No

The response of a successful coverage request is the coverage id of the newly inserted coverage. For example: The coverage available at http://schemas.opengis.net/gmlcov/1.0/examples/exampleRectifiedGridCoverage-1.xml can be imported with the following request:


The following example shows how to insert a coverage stored on the server on which rasdaman runs. The cell values are stored in a TIFF file (attachment:myCov.gml), the coverage id is generated by the server and aligned tiling is used for the array storing the cell values:

    &TILING=aligned[0:500,0:500] Updating Coverages

Updating an existing coverage into the server’s WCS offerings is done using the UpdateCoverage request.

Table 5.4 WCS-T Standard Parameters
Request Parameter Value Description Required
SERVICE WCS service standard Yes
VERSION 2.0.1 or later WCS version used Yes
REQUEST UpdateCoverage Request type to be performed Yes
COVERAGEID {string} Identifier of the coverage to be updated Yes
INPUTCOVERAGEREF {url} URl pointing to the coverage to be inserted One of inputCoverageRef or inputCoverage is required
INPUTCOVERAGE {coverage} A coverage to be updated One of inputCoverageRef or inputCoverage is required
SUBSET AxisLabel(geoLowerBound, geoUpperBound) Trim or slice expression, one per updated coverage dimension No

The following example shows how to update an existing coverage test_mr_metadata from a generated GML file by wcst_import tool:

    &INPUTCOVERAGEREF=file:///tmp/4514863c_55bb_462f_a4d9_5a3143c0e467.gml Deleting Coverages

The DeleteCoverage request type serves to delete a coverage (consisting of the underlying rasdaman collection, the associated WMS layer (if exists) and the petascope metadata). For example: The coverage test_mr can be deleted as follows:

  &COVERAGEID=test_mr Renaming coverage

The UpdateCoverageId request allows to update a coverage’s id and the associated WMS layer if one exists (v10.0+).

For example, the coverage test_mr can be renamed to test_mr_new as follows:


5.4.5. Coverage Metadata Update

Coverage metadata can be updated through the interactive rasdaman WSClient by selecting a text file (MIME type one of: text/xml, application/json, text/plain) containing new metadata and upload it to petascope. Then, petascope will read the content of the text file and update corresponding coverage’s metadata.


This WSClient feature is login protected: OGC WCS > Describe Coverage tab when one is already logged in with petascope admin user in Admin tab.

The service URL for this feature is http://localhost:8080/rasdaman/admin/UpdateCoverageMetadata which operates through multipart/form-data POST requests. The request should contain 2 parts: the first part is coverageId to update, the second part is a path to a local text file to be uploaded to server.

Alternatively, one can use REST API to update a coverage metadata with petascope admin user’s credentials via basic authentication headers method by curl tool. For example: Metadata of coverage test_mr_metadata will be updated from the local XML file at /home/rasdaman/Downloads/test_metadata.xml:

curl --user petauser:PETASCOPE_ADMIN_PASSWORD
            -F "coverageId=test_mr_metadata"
            -F "file=@/home/rasdaman/Downloads/test_metadata.xml"
            "http://localhost:8080/rasdaman/admin/UpdateCoverageMetadata" Check if a coverage / layer exists

In v10+, rasdaman supports nonstandard REST request to check if a coverage / layer exists. The result is true/false string literal.


5.5. OGC Web Coverage Processing Service (WCPS)

The OGC Web Coverage Processing Service (WCPS) standard defines a protocol-independent language for the extraction, processing, analysis, and fusion of multi-dimensional gridded coverages, often called datacubes.

5.5.1. General

WCPS requests can be submitted in both abstract syntax (example) and in XML (example).

For example, using the WCS GET/KVP protocol binding a WCPS request can be sent through the following ProcessCoverages request:


The following subsections list enhancements rasdaman offers over the OGC WCPS standard. A brief introduction to the WCPS language is given in the WCPS cheatsheet; more educational material is available on EarthServer.

5.5.2. Polygon/Raster Clipping

The proprietary clip() function with the same effect as clipping is available with WCPS. The signature is as follows:

clip( coverageExpression, wkt [, subsettingCrs ] )

where - coverageExpression is an expression of result type coverage, eg: dem + 10; - wkt is a valid WKT (Well-Known Text) expression, e.g. POLYGON((...)), LineString(...); - subsettingCrs is an optional CRS in which the wkt``coordinates are expressed, eg: ``http://opengis.net/def/crs/EPSG/0/4326. Clipping Examples

  • Polygon clipping with coordinates in EPSG:4326 on coverage with Native CRS EPSG:3857:

    ▶ show

  • Linestring clipping on 3D coverage with axes X, Y, datetime.

    ▶ show

  • Linestring clipping on 2D coverage with axes X, Y.

    ▶ show

  • Multipolygon clipping on 2D coverage.

    ▶ show

  • Curtain clipping by a Linestring on 3D coverage

    ▶ show

  • Curtain clipping by a Polygon on 3D coverage

    ▶ show

  • Corridor clipping by a Linestring on 3D coverage

    ▶ show

  • Corridor clipping by a Polygon on 3D coverage (geo CRS: EPSG:4326) with input geo coordinates in EPSG:3857.

    ▶ show

5.5.3. Auto-ratio for scaling X or Y axis in WCPS

As aproprietary extension, the scale() function in WCPS allows to specify the target extent of only one of the spatial horizontal axes, instead of both. In this case, the extent of the other axis will be determined automatically while preserving the original ratio between the two spatial axes.

For example in the request below, petascope will automatically set the extent of Lat to a value that preserves the ratio in the output result:

▶ show

5.5.4. Implicitly add full domains in scale() for unspecified non X/Y axes in WCPS

The scale() function in WCPS will implicitly add the full domains of unspecified non X/Y axes of a given coverage in the scales’ domain intervals. In other words, unspecified non X/Y axes will not be scaled.

For example in this query below, if a coverage is 3D and one only specified X (E) and Y (N) axes as scale’s domain intervals, then the time axis’s domains will be added implicitly in petascope.

▶ show

5.5.5. Automatic domain extraction

The domain interval can be extracted from a domain, including an imageCrsDomain (in modern nomenclature: index domain). Both the interval - ie: [lowerBound:upperBound] - and lower as well as upper bound can be retrieved for each axis.



with .lo or .hi returning the lower bound or upper bound of this interval.

Coverage test_eobstest has 3 dimensions with extent (0:5,0:29,0:39).
Expression imageCrsdomain(c,Long) in this case returns 0:39
whereas imageCrsdomain(c,Long).hi returns 39.

Further, the third argument of the domain() operator, the CRS URL, is now optional. If not specified, domain() will use the CRS of the selected axis (ie, the second argument) instead.

5.5.6. LET clause in WCPS

An optional LET clause is supported in WCPS queries. It allows binding alias variables to valid WCPS query sub-expressions, and subsequently make use of the variables in the return clause instead of repeating the aliased sub-expressions.

The syntax is

LET $variable := assignment [ , $variable := assignment ]


assignment ::= coverageExpression | domainExpression
for $c in (test_mr)
let $a := $c[i(0:50), j(0:40)],
    $b := avg($c) * 2
  encode( scale( $c, { imageCrsDomain( $c ) } ) + $b, "image/png" )

A special shorthand subset expression allows to conveniently specify domains. The variable in the LET clause follows this syntax:

LET $variable := [ dimensionalIntervalList ]

This can readily be used in a subset expression:

for $c in (test_mr)
let $a := [i(20), j(40)],
    $b := 10
  encode( $c[ $a ] + $b, "itext/json" )

5.5.7. Binary min, max operations in WCPS

Since v10+, rasdaman supports binary min() and max() operations. For two compatible coverages A and B they calculate a result coverage with the minimum / maximum for each pair of corresponding cell values of A and B. Example:

min(A, B)

where A and B are coverage expressions.

5.5.8. Positional parameter in WCPS

Since v10+, rasdaman supports positional parameters in WCPS (non-standard). Positional parameters allow to reference binary or string values in a WCPS query. The binary/string values are specified in a POST request, in addition to the WCPS query. Syntax

The syntax for the positional parameter is:

$POSITIVE_INTEGER e.g: $1, $2,..

The endpoint to send WCPS query by POST with extra values is:


with the mandatory parameter query and optional positional parameters: 1, 2,… The value of a positional parameter can be either binary file content or string value. Example

One can use curl tool as a client to send a WCPS request with positional parameters to rasdaman via POST. curl reads the contents of the selected files automatically via file paths with @ parameter.

For example, one wants to combine an existing coverage ($c variable) with two temporary covarages ($d and $e variables) in png format from positional parameters $1, $2 and $3 respectively :

curl -s "http://localhost:8080/rasdaman/ows?SERVICE=WCS&VERSION=2.0.1&REQUEST=ProcessCoverages" \
-F 'query=for $c in (existing_coverage), $d in (decode($1)), $e in (decode($2)) return encode(($c + $d + $e)[Lat(0:90), Long(-180:180)], "$3"))' \
-F "1=@/home/rasdaman/file1.tiff" \
-F "2=@/home/rasdaman/file2.tiff" \
-F "3=png" \
> ~/Downloads/test.png

5.5.9. Decode Operator in WCPS

Since v10+, rasdaman supports the non-standard decode() operator in WCPS. This feature allows one to combine existing coverages with temporary coverages created in memory from input files attached in POST request body. Syntax

The syntax for the decode() operator is:


with ${positional_parameter) refers to the indicated files in the POST request. See positional parameters in WCPS.


Currently, WCPS decode() operator supports only 2D geo-referenced files readable by GDAL. One way to check if a file is readable by GDAL is with gdalinfo ${file}. netCDF/GRIB format is not supported.

5.5.10. Case Distinction

As another proprietary extension, conditional evaluation is added to WCPS following the overall XQuery-oriented syntax. Syntax

  CASE condExp RETURN resultExp
  [ CASE condExp RETURN resultExp ]*
  DEFAULT RETURN resultExpDefault

where condExp and resultExp are either scalar-valued or coverage-valued expressions. Constraints

  • All condition expressions must return either boolean values or boolean coverages
  • All result expressions must return either scalar values, or coverages
  • The domain of all condition expressions must be the same
  • The domain of all result expressions must be the same (that means same extent, resolution/direct positions, crs) Evaluation Rules

If the result expressions return scalar values, the returned scalar value on a branch is used in places where the condition expression on that branch evaluates to True. If the result expressions return coverages, the values of the returned coverage on a branch are copied in the result coverage in all places where the condition coverage on that branch contains pixels with value True.

The conditions of the statement are evaluated in a manner similar to the IF-THEN-ELSE statement in programming languages such as Java or C++. This implies that the conditions must be specified by order of generality, starting with the least general and ending with the default result, which is the most general one. A less general condition specified after a more general condition will be ignored, as the expression meeting the less general expression will have had already met the more general condition.

Furthermore, the following hold:

  • domainSet(result) = domainSet(condExp1)
  • metadata(result) = metadata(condExp1)
  • rangeType(result) = rangeType(resultExp1). In case resultExp1 is a scalar, the result range type is the range type describing the coverage containing the single pixel resultExp1. Examples

  case $c < 10 return {red: 0;   green: 0;   blue: 255}
  case $c < 20 return {red: 0;   green: 255; blue:   0}
  case $c < 30 return {red: 255; green: 0;   blue:   0}
  default      return {red: 0;   green: 0;   blue:   0}

The above example assigns blue to all pixels in the $c coverage having a value less than 10, green to the ones having values at least equal to 10, but less than 20, red to the ones having values at least equal to 20 but less than 30 and black to all other pixels.

  case $c > 0 return log($c)
  default     return 0

The above example computes log of all positive values in $c, and assigns 0 to the remaining ones.

  case $c < 10 return $c * {red: 0;   green: 0;   blue: 255}
  case $c < 20 return $c * {red: 0;   green: 255; blue: 0}
  case $c < 30 return $c * {red: 255; green: 0;   blue: 0}
  default      return      {red: 0;   green: 0;   blue: 0}

The above example assigns blue: 255 multiplied by the original pixel value to all pixels in the $c coverage having a value less than 10, green: 255 multiplied by the original pixel value to the ones having values at least equal to 10, but less than 20, red: 255 multiplied by the original pixel value to the ones having values at least equal to 20 but less than 30 and black to all other pixels.

5.5.11. CIS 1.0 to CIS 1.1 Transformation

For output format application/gml+xml WCPS supports delivery as CIS 1.1 outputType=GeneralGridCoverage by specifying an additional proprietary parameter outputType in the encode() function.

for c in (test_irr_cube_2)
return encode( c, "application/gml+xml",
                  "{\"outputType\":\"GeneralGridCoverage\"}" )

5.5.12. Query Parameter

In v10+, rasdaman supports the q parameter besides the query parameter to store a WCPS query. A request must contain only one q or query parameter.


5.5.13. Describe Operator in WCPS

For some coverageExpression the describe() function delivers a “coverage description” consisting of the result coverage, except the range set, in either GML or JSON. This function is not part of the WCPS standard. Syntax

describe( coverageExpression, outputFormat [ , extraParameter ] )


  • outputFormat is a string specifying the format encoding in which the result will be formatted. Formats are indicated through their MIME type identifier, just as in encode(). Formats supported:

    • application/gml+xml (or short: gml) for GML
    • application/json (or short: json) for JSON
  • extraParameters is an optional string containing parameters for fine-tuning the output, just as in encode(). Options supported:

    • "outputType=GeneralGridCoverage" to return a CIS 1.1 General Grid Coverage structure Semantics

A describe() operation returns a description of the coverage resulting from the coverage expression passed, consisting of domain set, range type, and metadata, but not the range set. As such, this operator is the WCPS equivalent to a WCS DescribeCoverage request, and the output adheres to the same WCS schema.

The coverage description generated will follow the coverage’s type, so one of Rectified Grid Coverage (CIS 1.0), ReferenceableGridCoverage (CIS 1.0), General Grid Coverage (CIS 1.0).

By default, the coverage will be provided as Rectified or Referenceable Grid Coverage (in accordance with its type); optionally, a General Grid Coverage can be generated instead. However, generation of a General Grid Coverage structure can be enforced through "outputType=GeneralGridCoverage". As JSON is supported only from OGC CIS 1.1 onwards this format is only available (i) if the coverage is stored as a CIS 1.1 General Grid Coverage (currently not supported) or (ii) this output type is selected explicitly through extraParameter.

Efficiency: The describe() operator normally does not materialize the complete coverage, but determines only the coverage description making this function very efficient. A full evaluation is only required if coverageExpression contains a clip() performing a curtain, corridor, or linestring operation. Examples

  • Determine coverage description as a CIS 1.0 Rectified Grid Coverage in GML, without evaluating the range set:

    for $c in (Cov)
    return describe( $c.red[Lat(10:20), Long(30:40), "application/gml+xml" )
  • Deliver coverage description as a CIS 1.1 General Grid Coverage in GML, where range type changes in the query:

    for $c in (Cov)
    return describe( { $c.red; $c.green; $c.blue }, "application/gml+xml",
                                        "outputType=GeneralGridCoverage" )
  • Deliver coverage description as a CIS 1.1 General Grid Coverage, in JSON:

    for $c in (Cov)
    return describe( $c, "application/json", "outputType=GeneralGridCoverage" ) Specific Exceptions

  • Unsupported output format
  • This format only supported for General Grid Coverage
  • Illegal extra parameter

5.6. OGC Web Map Service (WMS)

The OGC Web Map Service (WMS) standard provides a simple HTTP interface for requesting overlays of geo-registered map images, ready for display.

With petascope, geo data can be served simultaneously via WMS, WCS, and WCPS. Further information:

5.6.1. WMS GetMap: Special Functionality Transparency

By adding a parameter transparent=true to WMS requests the returned image will have NoData Value=0 in the metadata indicating to the client that all pixels with value 0 value should be considered transparent for PNG encoding format.

▶ show Interpolation

If in a GetMap request the output CRS requested is different from the coverage’s Native CRS petascope will duly reproject the map applying resampling and interpolation. The algorithm used can be controlled with the proprietary GetMap parameter interpolation={method}; default is nearest-neighbour interpolation. See Geographic projection for the methods available and their meaning.

▶ show

5.6.2. 3D+ Coverages as WMS Layers

Petascope allows to import a 3D+ coverage as a WMS layer. To this end, the ingrdients file used for wcst_import must contain wms_import": true. This works for 3D+ coverages with recipes regular_time_series, irregular_time_series, and general_coverage recipes. This example demonstrates how to define an irregular_time_series 3D coverage from 2D GeoTIFF files.

Once the coverage is ingested, a GetMap request can use the additional (non-horizontal) axes for subsetting according to the OGC WMS 1.3.0 standard.

Table 5.5 WMS Subset Parameters for Different Axis Types
Axis Type Subset parameter
Time time=…
Elevation elevation=…
Other dim_AxisName=… (e.g dim_pressure=…)

According to the WMS 1.3.0 specification, the subset for non-geo-referenced axes can have these formats:

  • Specific value (value1): time=‘2012-01-01T00:01:20Z, dim_pressure=20,…
  • Range values (min/max): time=‘2012-01-01T00:01:20Z’/‘2013-01-01T00:01:20Z, dim_pressure=20/30,…
  • Multiple values (value1,value2,value3,…): time=‘2012-01-01T00:01:20Z, ‘2013-01-01T00:01:20Z, dim_pressure=20,30,60,100,…
  • Multiple range values (min1/max1,min2/max2,…): dim_pressure=20/30,40/60,…


A GetMap request always returns a 2D result. If a non-geo-referenced axis is omitted from the request it will be considered as a slice on the upper bound along this axis. For example, in a time-series the youngest timeslice will be delivered).


5.6.3. WMS Layer Management

Additional proprietary requests, beyond the WMS standard, allow for service maintenance.

Layers can be easily created from existing coverages in WCS in two ways:

  • By specifying WMS setup during import coverage in the respective ingredients file; see wms_import;
  • By sending an InsertWCSLayer HTTP request to petascope.

The following proprietary WMS request types serve to manage the WMS offering of rasdaman:

  • InsertWCSLayer: create a new WMS layer from an existing coverage.

▶ show

  • UpdateWCSLayer: update an existing WMS layer from an existing coverage which associates with this WMS layer.

▶ show

  • A layer can be removed either directly with a DeleteLayer request (since rasdaman v10.0), or indirectly when deleting a coverage (removing the associated WCS coverage). The DeleteLayer request is of the form:

▶ show

5.6.4. WMS Style Management

Styles can be created for layers using rasql and WCPS query fragments. This allows users to define several visualization options for the same dataset in a flexible way. Examples of such options would be color classification, NDVI detection etc. The following HTTP request will create a style with the name, abstract and layer provided in the KVP parameters below


For Tomcat version 7+ it requires the query (WCPS/rasql fragment) to be URL-encoded correctly. This site offers such an encoding service. Style Definition Variants

  • WCPS query fragment example (since rasdaman 9.5):

    ▶ show

    Variable $c will be replaced by a layer name when sending a GetMap request containing this layer’s style.

  • Rasql query fragment examples:

    ▶ show

    Variable $Iterator will be replaced with the actual name of the rasdaman collection and the whole fragment will be integrated inside the regular GetMap request.

  • Multiple layers can be used in a style definition. Besides the iterators $c in WCPS query fragments and $Iterator in rasql query fragments, which always refer to the current layer, other layers can be referenced by name using an iterator of the form $LAYER_NAME in the style expression.

    Example: create a WCPS query fragment style referencing 2 layers ($c refers to layer sentinel2_B4 which defines the style):

    ▶ show

    Then, in any GetMap request using this style the result will be obtained from the combination of the 2 layers sentinel2_B4 and sentinel2_B8:

    ▶ show

  • WMS styling supports a ColorTable definition which allows to colorize the result of WMS GetMap request when the style is requested. A style can contain either one or both query fragment and Color Table definitions. The InsertStyle request supports two new non-standard extra parameters colorTableType (valid values: ColorMap, GDAL and SLD) and colorTableDefintion containing corresponding definition, example:

    ▶ show

    Below the supported color table definitions for each color table type are explained:

    • Rasdaman ColorMap: check Coloring Arrays for more details. The color table definition must be a JSON object, for example:

      ▶ show

    • GDAL ColorPalette: check encode for more details. The color table definition must be a JSON object and contains 256 color arrays in colorTable array, example:

      ▶ show

    • WMS Styled Layer Descriptor (SLD): The color table definition must be valid XML and contains ColorMap element. Check Coloring Arrays for details about the supported types (ramp (default), values, intervals), example ColorMap with type="values":

      ▶ show WMS Style Removal

The proprietary DeleteStyle WMS request type allows to remove a particular style of an existing WMS layer.


5.6.5. Testing a WMS Setup

A rasdaman WMS service can be tested with any conformant client through a GetMap request like the following:

▶ show

5.6.6. Errors and Workarounds

Cannot load new WMS layer in QGIS
In this case, the problem is due to QGIS caching the WMS GetCapabilities from the last request so the new layer does not exist (see clear caching solution).

5.6.7. WMS Pyramid Management

The following proprietary WMS requests are used to manage downscaled coverages. Internally they are used for efficient zooming in/out in WMS, and downscaling when using the scale() function in WCPS or scaling extension in WCS.

  • CreatePyramidMember: create a pyramid member coverage c for a base coverage b with given scale factors for each axis (note: only regular axis can have scale factor > 1); e.g. to create a downscaled coverage cov_3D_4 of a 3D coverage cov_3D that is 4x smaller for Lat and Long regular axes (Time is irregular axis, hence, scale factor must be 1):

    ▶ show

  • AddPyramidMember: add an existing coverage c as a pyramid member coverage for a base coverage b. The scale factors for each axis of the pyramid member coverage will be calculated implicitly based on axis resolutions. If harvesting=true (default is false), recursively collect pyramid members of coverage c and add them as pyramid member of coverage b; e.g. to add a downscaled coverage cov_3D_4 (4x smaller) and its pyramid members recursively as pyramid member coverages of base coverage cov_3D:

    ▶ show

  • RemovePyramidMember: remove an existing pyramid member coverage c from a base coverage b (coverage c still exists, until admin deletes with WCS-T DeleteCoverage request); e.g. to remove downscaled coverage cov_3D_4 from base coverage cov_3D:

    ▶ show

  • ListPyramidMembers: get a JSON list with objects of all pyramid member coverages associated with a base coverage:

    ▶ show

    Output example:

    ▶ show

wcst_import can send CreatePyramidMember requests automatically when importing data with it with scale_levels or scale_factors option in the ingredients file, more details here.

5.7. Data Import

Raster data in a variety of formats, such as TIFF, netCDF, GRIB, etc. can be imported in rasdaman through the wcst_import.sh utility. Internally it is based on WCS-T requests, but hides the complexity and maintains the geo-related metadata in its so-called petascopedb while the raster data get ingested into the rasdaman array store.

Building large time-series / datacubes, mosaics, etc. and keeping them up-to-date as new data become available is supported for a large variety of data formats and file/directory organizations.

The systemtest contains many examples for importing different types of data.

5.7.1. Introduction

The wcst_import.sh tool is based on two concepts:

  • Recipe - A recipe defines how a set of data files can be combined into a well-defined coverage (e.g. a 2-D mosaic, regular or irregular 3-D timeseries, etc.);
  • Ingredients - A JSON file that configures how the recipe should build the coverage (e.g. the server endpoint, the coverage name, which files to consider, etc.).

To execute an ingredients file in order to import some data:

$ wcst_import.sh path/to/my_ingredients.json

Alternatively, wcst_import.sh can be started in the background as a daemon:

$ wcst_import.sh path/to/my_ingredients.json --daemon start

or as a daemon that is “watching” for new data at some interval (in seconds):

$ wcst_import.sh path/to/my_ingredients.json --watch <interval>

For further informations regarding the usage of wcst_import.sh:

$ wcst_import.sh --help

The workflow behind is depicted approximately on Figure 5.1.


Figure 5.1 Ingestion process with wcst_import.sh

An ingredients file showing all possible options (across all recipes) can be found here in the same directory there are several examples of different recipes.

The following recipes are provided in the rasdaman repository:

For each one of these there is an ingredients example under the ingredients/ directory, together with an example for the available parameters Further on each recipe type is described in turn, starting with the common options shared by all recipes.

5.7.2. Common Options

Some options are commonly applicable to all recipes. We describe these options for each top-level section of an ingredient file: config, input, recipe, and hooks. config section

  • service_url - The endpoint of the WCS service with the WCS-T extension enabled

  • mock - Print WCS-T requests but do not execute anything if set to true. Set to false by default.

  • automated - Set to true to avoid any interaction during the ingestion process. Useful in production environments for automated deployment for example. By default it is false, i.e. user confirmation is needed to execute the ingestion.

  • blocking (since v9.8) - Set to false to analyze and import each file separately (non-blocking mode). By default blocking is set to true, i.e. wcst_import will analyze all input files first to create corresponding coverage descriptions, and only then import them. The advantage of non-blocking mode is that the analyzing and importing happens incrementally (in blocking mode the analyzing step can take a long time, e.g. days, before the import can even begin).


    When importing in non-blocking import mode for coverages with irregular axes, it will only rely on sorted files by filenames and it can fail if these axes’ coefficients are collected from input files’ metadata (e.g: DateTime value in TIFF’s tag or GRIB metadata) as they might not be consecutive. wcst_import will not analyze all files to collect metadata to be sorted by DateTime as in default blocking import mode.

  • default_null_values - This parameter adds default null values for bands that do not have a null value provided by the file itself. The value for this parameter should be an array containing the desired null value either as a closed interval low:high or single values. Example:

    ▶ show


    If set this parameter will override the null/nodata values present in the input files.


    If a null value interval is specified, e.g. e.g "9.96921e+35:*", during encode it will not be preserved as-is because null value intervals are not supported by most formats. In this case it is recommended to first specify a non-interval null value, followed by the interval, e.g. [9.96921e+35, "9.96921e+35:*"].

  • tmp_directory - Temporary directory in which gml and data files are created; should be readable and writable by rasdaman, petascope and current user. By default this is /tmp.

  • crs_resolver - The crs resolver to use for generating WCS-T request. By default it is determined from the petascope.properties setting.

  • url_root - In case the files are exposed via a web-server and not locally, you can specify the root file url here; the default value is "file://".

  • skip - Set to true to ignore files that failed to import; by default it is false, i.e. the ingestion is terminated when a file fails to import.

  • retry - Set to true to retry a failed request. The number of retries is either 5, or the value of setting retries if specified. This is set to false by default.

  • retries - Control how many times to retry a failed WCS-T request; set to 5 by default.

  • retry_sleep - Set number of seconds to wait before retrying after an error; a floating-point number can also be specified for sub-second precision. Default values is 1.

  • track_files - Set to true to allow files to be tracked in order to avoid reimporting already imported files. This setting is enabled by default.

  • resumer_dir_path - The directory in which to store the track file. By default it will be stored next to the ingredients file.

  • slice_restriction - Limit the slices that are imported to the ones that fit in a specified bounding box. Each subset in the bounding box should be of form { "low": 0, "high": <max> }, where low/high are given in the axis format. Example:

    ▶ show

  • description_max_no_slices - Maximum number of slices (files) to show for preview before starting the actual ingestion.

  • subset_correction (deprecated since v9.6) - In some cases the resolution is small enough to affect the precision of the transformation from domain coordinates to grid coordinates. To allow for corrections that will make the import possible, set this parameter to true. input section

  • coverage_id - The name of the coverage to be created; if the coverage already exists, it will be updated with the new files collected by paths.
  • paths - List of absolute or relative (to the ingredients file) paths or regex patterns that would work with the ls command. Multiple paths separated by commas can be specified. The collected paths are sorted by file name by default, unless specified otherwise in the recipe section (e.g. by date/time for time-series recipes). recipe section

  • import_order - Allow to sort the input files (ascending (default) or descending).Currently, it sorts by datetime which allows to import coverage from the first date or the recent date. Example:

    ▶ show

  • tiling - Specifies the tile structure to be created for the coverage in rasdaman. You can set arbitrary tile sizes for the tiling option only if the tile name is ALIGNED. Example:

    ▶ show

    For more information on tiling please check the Storage Layout Language

  • wms_import - If set to true, after importing data to coverage, it will also create a WMS layer from the imported coverage and populate metadata for this layer. After that, this layer will be available from WMS GetCapabilties request. Example:

    ▶ show

  • scale_levels - Enable the WMS pyramids feature. Level must be positive number and greater than 1 (note: only spatial geo axes, e.g. Lat and Long are scaled down in the pyramid member coverage). A new coverage as pyramid member of the importing coverage will be created with this pattern. Syntax:

    ▶ show

  • scale_factors - Enable the WMS pyramids feature. It is a more flexible variant of the scale_levels setting. The two settings are exclusive, either scale_levels or scale_factors can exist in the ingredient file. The coverage_id of each factor must be unique in rasdaman and manually set by the user. The factors is a list of decimal values corresponding to the coverage axes according to its CRS order; a scale value for an irregular axis must be 1, while for a regular axis it should be greater than 1; see more details here. For example, you can create two pyramid member 2D coverages which are 2x smaller (cov_level_2) and 4x smaller (cov_level_4) on the regular Lat and Long axes:

    ▶ show

  • pyramid_members - List of existing coverages which can be added as pyramid members of the importing coverage, see request. Syntax:

    ▶ show Image pyramids

Since v9.7 it is possible to create downscaled versions of a given coverage, eventually achieving something like an image pyramid, in order to enable faster WMS requests when zooming in/out.

By using the scale_levels option of wcst_import when importing a coverage with WMS enabled, petascope will create downscaled collections in rasdaman following this pattern: coverageId_<level>. If level is a float, then the dot is replaced with an underscore, as dots are not permitted in a collection name. Some examples:

  • MyCoverage, level 2 -> MyCoverage_2
  • MyCoverage, level 2.45 -> MyCoverage_2_45

Example ingredients specification to create two downscaled levels which are 8x and 32x smaller than the original coverage:

▶ show

Two new WCS-T non-standard requests are utilized by wcst_import for this feature, see here for more information. hooks section

Since v9.8, it is possible to run shell commands before/after ingestion by adding optional hooks configuration in an ingredient file. There are 2 types of ingestion hooks:

  • before_ingestion - Run shell commands before analyzing the input files, e.g. reproject input files from EPSG:3857 to EPSG:4326 with gdalwarp and import the reprojected files only.
  • after_ingestion - Run shell commands after importing the input files, e.g. clean all projected files from running gdalwarp above.

When import mode is set to non-blocking ("blocking": false), wcst_import will run before/after hook(s) for the file which is being used to update coverage, while the default blocking importing mode will run before/after hooks for all input files before/after they are updated to a coverage. Parameters are explained below.

▶ show

Example: Import GDAL subdatasets

The example ingredients below contains a pre-hook which replaces the collected file path into a GDAL subdataset form; in this particular case, with the GDAL driver for NetCDF a single variable from the collected NetCDF files is imported.

▶ show

5.7.3. Recipe map_mosaic

Well suited for importing a tiled map, not necessarily continuous; it will place all input files given under a single coverage and deal with their position in space. Parameters are explained below.

▶ show

5.7.4. Recipe time_series_regular

Well suited for importing multiple 2-D slices created at regular intervals of time (e.g sensor data, satelite imagery etc) as 3-D cube with the third axis being a temporal one. Parameters are explained below

▶ show

5.7.5. Recipe time_series_irregular

Well suited for importing multiple 2-D slices created at irregular intervals of time into a 3-D cube with the third axis being a temporal one. There are two types of time parameters in “options”, one needs to be choosed according to the particular use case:

  • tag_name - e.g. TIFFTAG_DATETIME in the image’s metadata; the metadata should be checked with gdalinfo <file>, as not every image may have the tag. Below is an example:

    ▶ show

  • filename allows an arbitrary pattern to extract the time information from the data file paths. Below is an example:

    ▶ show

5.7.6. Recipe general_coverage

This is a highly flexible recipe that can handle any kind of data files (be it 2D, 3D or n-D) and model them in coverages of any dimensionality. It does that by allowing users to define their own coverage models with any number of bands and axes and fill the necesary coverage information through the so called ingredient sentences inside the ingredients. Coverage parameters

Using ingredient sentences we can define any coverage model directly in the options of the ingredients file. Each coverage model contains the following parts:

  • crs - Indicates the crs of the coverage to be constructed. Either a CRS url can be used e.g. http://opengis.net/def/crs/EPSG/0/4326 or the shorthand notation CRS1@CRS2@CRS3, e.g. OGC/0/AnsiDate@EPSG/0/4326 for indicating a time/date + spatial CRS.
  • metadata - A group of options controlling metadata extraction and consolidation; more detailed information follows below
  • slicer - A group of options controlling the data decoding and placement into the overall datacube; more detailed information follows below. metadata section

The metadata section specifies in which format you want the metadata (json or xml). It can only contain characters and is limited in size by the backend database limit for CLOB columns; for postgresql (the default backend for petascope) the maximum size is 2GB (source).

  • type - Specifies the format for storing the coverage metadata; xml and json are supported, and it is set to xml by default.

  • global - Specifies fields which should be saved once for the whole coverage (e.g. the data licence, the creator etc). For example a “Title” metadata value can be set with "global": { "Title": "'Drought code'", ... }.

  • local - Specifies fields which are fetched from each input file to be stored in coverage’s metadata. When subsetting in the output coverage only local metadata associated to the subsetted areas will be added to the result. E.g., "local": { "LocalMetadataKey": "${netcdf:metadata:LOCAL_METADATA}" } sets LocalMetadataKey to a metadata value extracted from the input data; the ${..} is explained in Data expressions. For a more detailed explanation of local metadata see the dedicated Local metadata from input files section.

  • colorPaletteTable - Controls collection of color palette table for the created coverage, which can then be used internally when encoding coverage to, e.g. PNG, to colorize the result. Currently only GDAL-style colorTable with 256 color entries is supported.

    A path to an explicit Color Palette Table file can be specified, see example file; such a file can be referenced in the ingredients file with, e.g., "colorPaletteTable": "PATH/TO/table.cpt".

    If colorPaletteTable is set to "auto" or not specified at all, and the slicer is set to gdal (see next section for info on slicers), then the color table will be read automatically from the first input file if its metadata contains one.

    If colorPaletteTable is set to an empty string "", any color table metadata will be ignored when creating coverage’s global metadata.

  • bands and axes - Allow specifying metadata for the coverage bands and/or axes; more details can be found in Band and axis metadata in global metadata. slicer section

The slicer subsection specifies the driver to use to read from the data files, the required bands from data files and for each axis from the CRS how to obtain the bounds and resolution corresponding to each file.

  • type - Specifies the decoding driver to be used; currently the following are supported:

    • gdal - for TIFF, PNG, and other encoding format that can be read with GDAL (check with gdalinfo <file>);

    • netcdf - for importing NetCDF data. If a netCDF file is flipped on Lat axis (South -> North coordinates increase in the output of ncdump -c) instead of GDAL style (North -> South coordinates decrease), then it is necessary to flip it before importing as rasdaman, e.g. with cdo invertlat input.nc output.nc.

    • grib - for GRIB data. Currently, rasdaman only supports GRIB files with gridType format of regular lat long regular_ll. If the format is different, it is necessary to preprocess the input files into regular grid type. The grid type can be retreived with grib_dump file.grib | grep 'gridType'.

      If a GRIB file is flipped on Lat axis (South -> North with jScansPositively = 0 in the output of grib_dump) instead of GDAL style (North -> South with jScansPositively = 1), then it is necessary to flip it before importing to rasdaman, e.g. with cdo invertlat input.grib output.grib.

  • pixelIsPoint - Only valid if type is netcdf or grib. In some cases, by convention in the input files, the coordinates are set in the middle of grid pixels, hence, set to true to extend the lower and upper bounds of each regular axis by half grid pixel to be able to import. By default it is set to false.

  • bands - A list of bands/chanels/variables from the input files which should be imported to the importing coverage. Each entry is a JSON object with the following options, of which identifier and name are mandatory to specify while the rest are optional:

    • identifier - The name of the band in the input file;
    • name - The name of the band which will be used in the created coverage; this can be set to different from the indentifier;
    • description - Metadata description of the band;
    • nilValue` - Metadata null value of the band;
    • nilReason - Metadata reason for the null value of the band;
    • uomCode - Set the Unit of measurement (uom) code of the band. Besides setting it directly, it can also be derived from the input file metadata, with e.g. ${netcdf:variable:NAME:units} for NetCDF or ${grib:unitsOfFirstFixedSurface} for GRIB.
    • Further "key": "value" entries can be specified to add customized band metadata to the global coverage metadata.
  • axes - A JSON object which configures the properties of each axis of the created coverage with "axisLabel": { properties... }. The possible properties are listed below; generally, gridOrder, min, max, and resolution have to be specified, except for irregular axes where resolution is not applicable.

    • gridOrder - The index of the axis in the input file (0-based);
    • crsOrder - Specifies a different name for this axis than the one configured in the CRS’s definition; more details can be found here;
    • min - The lower bound of the axis (coordinates in the axis CRS);
    • max- The upper bound of the axis (coordinates in the axis CRS);
    • resolution - The resolution of the axis from the input file; if this axis is irregular, the resolution is set to 1;
    • statements - Import python utility libraries (e.g. datetime / timedelta) to support calculating min, max, resolution, etc; covered in more detail in a subsequent section;

    A few additional options are specific to irregular axes:

    • irregular - Set to true to specify that this axis is irregular, e.g. a time axis with irregular datetime indexes; if not specified, it is set to false by default;
    • directPositions - A list of coefficients which are extracted or calculated from the axis values specified in the input file; for an example see this ingredients file;
    • dataBound - Set to false to specify that this axis should be imported as a slicing point instead of a subset with lower and upper bounds; typical use case for this is when extracting irregular datetime values from the input file names. When not specified it is set to true by default.
    • sliceGroupSize - Group multiple input slices into a single slice in the created coverage, e.g., multiple daily data files onto a single week index on the coverage time axis; explained in more detail here; Examples

The examples below illustrate importing data in different formats with the general_coverage recipe; many more can be found in the rasdaman test suite.

  • Commented example for importing GRIB data (only the recipe section is shown for brevity):

    ▶ show

  • Example for importing NetCDF data (full ingredients file here):

    ▶ show

  • Example for importing TIFF data with the gdal driver (full ingredients file here):

    ▶ show Ingredient sentences

An ingredient sentence can be of multiple types:

  • Numeric - e.g. 2, 4.5
  • Strings - e.g. 'Some information'
  • Functions - e.g. datetime('2012-01-01', 'YYYY-mm-dd')
  • Data expressions - Allow to collect information from the data file being imported with a specific format driver. An expression is of form ${driverName:driverOperation} - e.g. ${gdal:minX} or ${netcdf:variable:time:min. All possible expressions are documented in Data expressions.
  • Python expressions - The types above can be combined into any valid Python expression; this allows to do mathematical operations, string parsing, date/time manipulation, etc. E.g. ${gdal:minX} + 1/2 * ${gdal:resolutionX} or datetime(${netcdf:variable:time:min} * 24 * 3600). Expressions can use functions from any Python library which just needs to be explicitly imported as explained in Using libraries in sentences. Data expressions

Each driver allows expressions to extract information from input files. We will mark with capital letters things that vary in the expression. E.g. ${gdal:metadata:FIELD} means that you can replace FIELD with any valid gdal metadata tag such as TIFFTAG_DATETIME. Example ingredients where data expressions are used can be found in Examples. NetCDF
Type Description Examples
Metadata information ${netcdf:metadata:YOUR_METADATA_FIELD} ${netcdf:metadata:title}
Variable information ${netcdf:variable:VAR_NAME:MODIFIER} where VAR_NAME can be any variable in the file and MODIFIER can be one of: first|last|max|min; Any extra modifiers will return the corresponding metadata field on the given variable ${netcdf:variable:t:min} ${netcdf:variable:t:units}
Dimension information ${netcdf:dimension:DIM_NAME} where DIM_NAME can be any dimension in the file. This will return the value on the selected dimension. ${netcdf:dimension:time} GDAL

Relevant for TIFF, PNG, JPEG, and other 2D data formats.

Type Description Examples
Metadata information ${gdal:metadata:METADATA_FIELD} ${gdal:metadata:TIFFTAG}
Geo Bounds ${gdal:BOUND_NAME} where BOUND_NAME can be one of the minX|maxX|minY|maxY ${gdal:minX}
Geo Resolution ${gdal:RESOLUTION_NAME} where RESOLUTION_NAME can be one of the resolutionX|resolutionY ${gdal:resolutionX}
Origin ${gdal:ORIGIN_NAME} where ORIGIN_NAME can be one of the originX|originY ${gdal:originY} GRIB
Type Description Examples
GRIB Key ${grib:KEY} where KEY can be any of the keys contained in the GRIB file ${grib:messagenumber} is the special value to get the current processed GRIB message index (starting from 1) ${grib:experimentVersionNumber} File
Type Description Examples
File Information ${file:PROPERTY} where property can be one of path|name|dir_path|original_path|original_dir_path original_* allows to get the original input file’s path/directory (used only when using pre-hook with replace_path to replace original input file paths with customized file paths). ${file:path}
Imported File Information ${imported_file:PROPERTY} where property can be one of path|name|dir_path|original_path|original_dir_path Files which were imported to rasdaman (excluded skipped files). This variable is used only for after_ingestion hooks. ${imported_file:path} Special functions

A couple of special functions are available to help with more complicated expressions:

Function and Arguments Description Examples


  • date
  • time
This function helps to deal with the usual grib date and time format. It returns back a datetime string in ISO format.


  • date
  • format
This function helps to deal with strange date time formats. It returns back a datetime string in ISO format.


  • string
  • regex
  • group
This function extracts information from a string using regex; input is the string you parse, regex is the regular expression, group is the regex group you want to select
    '(.*)_(\\d*-\\d\\d)(.*)', 2),


  • str
  • old
  • new
Replaces all occurrences of a substring with another substring in the input string
        '.tiff', '.xml') Using libraries in sentences

In case the ingredient sentences require functionality from extra Python libraries, they can be imported with a statements option. For example, to calculate the lower bound and upper bound for the time axis ansi (starting days from 1978-12-31T12:00:00) one could use datetime and timedelta from the datatime library.

▶ show

Python functions imported in this way override the special functions provided by wcst_import. For example, the special utility function datetime(date_time_string, format) to convert a string of datetime to an ISO date time format will be overridden when the datetime module is imported with a statements setting. Local metadata from input files

Beside the global metadata of a coverage, you can add local metadata for each file which is a part of the whole coverage (e.g. a 3D time-series coverage mosaiced from 2D GeoTiff files).

Under the metadata section add a “local” object with keys and values extracted by using format type expression. Example of extracting an attribute from a netCDF input file:

▶ show

Each file’s envelope (geo domain) and its local metadata will be added to the coverage metadata under <slice>...</slice> element if coverage metadata is imported in XML format. Example of a coverage containing local metadata in XML from 2 netCDF files:

▶ show

Since v10.0, local metadata for input files can be also fetched from corresponding external text files with the optional metadata_file option. For example:

▶ show

When subsetting a coverage which contains a local metadata section from input files (via WC(P)S requests), if the geo domains of subsetted coverage intersect with some input files’ envelopes, only local metadata of these files will be added to the output coverage metadata.

For example: a GetCoverage request with a trim such that crs axis subsets are within netCDF file 1:

▶ show

The coverage’s metadata result will contain local metadata only from netCDF file 1:

▶ show Customized axis labels

By default, the axes to be configured must be matched by their name as defined by the coverage CRS. For example, a CRS OGC/0/AnsiDate@EPSG:4326 defines three axes with labels ansi, Long, and Lat. To configure them, we would have a section as bellow:

▶ show

Since v9.8, one can change the default axis label defined by the CRS through indicating the axis index in the CRS (0-based) with the "crsOrder" setting. For example, to change the axis labels to MyDateTimeAxis, MyLatAxis, and MyLongAxis:

▶ show Group coverage slices

Since v9.8, wcst_import allows to group input files on irregular axes (with "dataBound": false) through the sliceGroupSize option, which would specify the group size as a positive number. E.g:

▶ show

If each input slice corresponds to index X, and one wants to have slice groups of size N, then the index would be translated with this option to X - (X % N).

Typical use case is importing 3D coverage from 2D satellite imagery where the time axis is irregular and its values are fetched from input files by regex expression. Then, all input files which belong to the same time window (e.g 7 days in AnsiDate CRS with "sliceGroupSize": 7) will have the same value, which is the first date of the week. Band and axis metadata in global metadata

Metadata can be individually specified for each band and axis in the ingredient file. Example:

▶ show

Since v9.7, the following metadata can also be automatically derived from the input netCDF files. band metadata
  • For netCDF: If "bands" is set to "auto" or does not exist under "metadata" in the ingredient file, all user-specified bands will have metadata which is fetched directly from the netCDF file. Metadata for 1 band is collected automatically if: 1) band is not added. 2) band is set to "auto".

  • Otherwise, the user could specify metadata explicitly by a dictionary of keys/values. Example:

    ▶ show axis metadata
  • For netCDF: If "axes" is set to "auto" or does not exist under "metadata" in the ingredient file, all user-specified axes will have metadata which is fetched directly from the netCDF file. Metadata for 1 axis is collected automatically if: 1) axis is not added. 2) axis is set to "auto". 3) axis is set with ${netcdf:variable:Name:metadata}. The axis label for variable is detected from the min or max value of CRS axis configuration under "slicer/axes" section. For example:

    ▶ show

  • Otherwise, the user could specify metadata explicitly as a dictionary of keys/values.

    ▶ show

5.7.7. Recipe wcs_extract

Allows to import a coverage from a remote petascope endpoint into the local petascope. Parameters are explained below.

▶ show

5.7.8. Recipe sentinel1

This is a convenience recipe for importing Sentinel 1 data in particular; currently only GRD/SLC product types are supported, and only geo-referenced tiff files. Below is an example:

▶ show

The recipe extends general_coverage so the "recipe" section has the same structure. However, a lot of information is automatically filled in by the recipe now, so the ingredients file is much simpler as the example above shows.

The other obvious difference is that the "coverage_id" is templated with several variables enclosed in ${ and } which are automatically replaced to generate the actual coverage name during import:

  • modebeam - the mode beam of input files, e.g. IW/EW.
  • polarisation - single polarisation of input files, e.g: HH/HV/VV/VH

If the files collected by "paths" are varying in any of these parameters, the corresponding variables must appear somewhere in the "coverage_id" (as for each combination a separate coverage will be constructed). Otherwise, the ingestion will either fail or result in invalid coverages. E.g. if all data’s mode beam is IW, but still different polarisations, the "coverage_id" could be "MyCoverage_${polarisation}";

In addition, the data to be ingested can be optionall filtered with the following options in the "input" section:

  • modebeams - specify a subset of mode beams to ingest from the data, e.g. only the IW mode beam; if not specified, data of all supported mode beams will be ingested.
  • polarisations - specify a subset of polarisations to ingest, e.g. only the HH polarisation; if not specified, data of all supported polarisations will be ingested.


  • Only GRD/SLC products are supported.
  • Data must be geo-referenced.
  • Filenames are assumed to be of the format: s1[ab]-(.*?)-grd(.?)-(.*?)-(.*?)-(.*?)-(.*?)-(.*?)-(.*?).tiff or s1[ab]-(.*?)-slc(.?)-(.*?)-(.*?)-(.*?)-(.*?)-(.*?)-(.*?).tiff.

5.7.9. Recipe sentinel2

This is a convenience recipe for importing Sentinel 2 data in particular. It relies on support for Sentinel 2 in more recent GDAL versions. Importing zipped Sentinel 2 is also possible and automatically handled.

Below is an example:

▶ show

The recipe extends general_coverage so the "recipe" section has the same structure. However, a lot of information is automatically filled in by the recipe now, so the ingredients file is much simpler as the example above shows.

The other obvious difference is that the "coverage_id" is templated with several variables enclosed in ${ and } which are automatically replaced to generate the actual coverage name during import:

  • crsCode - the CRS EPSG code of the imported files, e.g. 32757 for WGS 84 / UTM zone 57S.
  • resolution - Sentinel 2 products bundle several subdatasets of different resolutions:
    • 10m - bands B4, B3, B2, and B8 (base type unsigned short)
    • 20m - bands B5, B6, B7, B8A, B11, and B12 (base type unsigned short)
    • 60m - bands B1, B8, and B10 (base type unsigned short)
    • TCI - True Color Image (red, green, blue char bands); also 10m as it is derived from the B2, B3, and B4 10m bands.
  • level - L1C or L2A

If the files collected by "paths" are varying in any of these parameters, the corresponding variables must appear somewhere in the "coverage_id" (as for each combination a separate coverage will be constructed). Otherwise, the ingestion will either fail or result in invalid coverages. E.g. if all data is level L1C with CRS 32757, but still different resolutions, the "coverage_id" could be "MyCoverage_${resolution}"; the other variables can still be specified though, so "MyCoverage_${resolution}_${crsCode}" is valid as well.

In addition, the data to be ingested can be optionall filtered with the following options in the "input" section:

  • resolutions - specify a subset of resolutions to ingest from the data, e.g. only the “10m” subdataset; if not specified, data of all supported resolutions will be ingested.
  • levels - specify a subset of levels to ingest, so that files of other levels will be fully skipped; if not specified, data of all supported levels will be ingested.
  • crss - specify a list of CRSs (EPSG codes as strings) to ingest; if not specified or empty, data of any CRS will be ingested.

5.7.10. Creating your own recipe

The recipes above cover a frequent but limited subset of what is possible to model using a coverage. WCSTImport allows to define your own recipes in order to fill these gaps. In this tutorial we will create a recipe that can construct a 3D coverage from 2D georeferenced files. The 2D files that we want to target have all the same CRS and cover the same geographic area. The time information that we want to retrieve is stored in each file in a GDAL readable tag. The tag name and time format differ from dataset to dataset so we want to take this information as an option to the recipe. We would also want to be flexible with the time crs that we require so we will add this option as well.

Based on this usecase, the following ingredient file seems to fulfill our need:

▶ show

To create a new recipe start by creating a new folder in the recipes folder. Let’s call our recipe my_custom_recipe:

▶ show

The last command is needed to tell python that this folder is containing python sources, if you forget to add it, your recipe will not be automatically detected. Let’s first create an example of our ingredients file so we get a feeling for what we will be dealing with in the recipe. Our recipe will just request from the user two parameters Let’s now create our recipe, by creating a file called recipe.py

▶ show

Use your favorite editor or IDE to work on the recipe (there are type annotations for most WCSTImport classes so an IDE like PyCharm would give out of the box completion support). First, let’s add the skeleton of the recipe (please note that in this tutorial, we will omit the import section of the files (your IDE will help you auto import them)):

▶ show

The first thing you need to do is to make sure the get_name() method returns the name of your recipe. This name will be used to determine if an ingredient file should be processed by your recipe. Next, you will need to focus on the constructor. Let’s examine it. We get a single parameter called session which contains all the information collected from the user plus a couple more useful things. You can check all the available methods of the class in the session.py file, for now we will just save the options provided by the user that are available in session.get_recipe() in a class attribute.

In the validate() method, you will validate the options for the recipe provided by the user. It’s generally a good idea to call the super method to validate some of the general things like the WCST Service availability and so on although it is not mandatory. We also want to validate our custom recipe options here. This is how the recipe looks like now:

▶ show

Now that our recipe can validate the recipe options, let’s move to the describe() method. This method allows you to let your users know any relevant information about the ingestion before it actually starts. The irregular_timeseries recipe prints the timestamp for the first couple of slices for the user to check if they are correct. Similar behaviour should be done based on what your recipe has to do.

Next, we should define the ingest behaviour. The framework does not make any assumptions about how the correct method of ingesting is, however it offers a lot of utility functionality that help you do it in a more standardized way. We will continue this tutorial by describing how to take advantage of this functionality, however, note that this is not required for the recipe to work. The first thing that you need to do is to define an importer object. This importer object, takes a coverage object and ingests it using WCST requests. The object has two public methods, ingest(), which ingests the coverage into the WCS-T service (note: ingest can be an insert operation when the coverage was not defined, or update if the coverage exists. The importer will handle both cases for you, so you don’t have to worry if the coverage already exists.) and get_progress() which returns a tuple containing the number of imported slices and the total number of slices. After adding the importer, the code should look like this:

▶ show

In order to build the importer, we need to create a coverage object. Let’s see how we can do that. The coverage constructor requires a

  • coverage_id: the id of the coverage
  • slices: a list of slices that compose the coverage. Each slice defines the position in the coverage and the data that should be defined at the specified position
  • range_fields: the range fields for the coverage
  • crs: the crs of the coverage
  • pixel_data_type: the type of the pixel in gdal format, e.g. Byte, Float32 etc

The coverage object can be built in many ways, we will present one such method. Let’s start from the crs of the coverage. For our recipe, we want a 3D crs, composed of the CRS of the 2D images and a time CRS as indicated. The following lines of code give us exactly this:

▶ show

Let’s also get the range fields for this coverage. We can extract them again from the 2D image using a helper class that can use GDAL to get the relevant information:

▶ show

Let’s also get the pixel base type, again using the gdal helper:

pixel_type = gdal_dataset.get_band_gdal_type()

Let’s see what we have so far:

▶ show

As you can notice, the only thing left to do is to implement the _get_slices() method. To do so we need to iterate over all the input files and create a slice for each. Here’s an example on how we could do that

▶ show

And we are done we now have a valid coverage object. The last thing needed is to define the status method. This method need to provide a status update to the framework in order to display it to the user. We need to return the number of finished work items and the number of total work items. In our case we can measure this in terms of slices and the importer can already provide this for us. So all we need to do is the following:

▶ show

We now have a functional recipe. You can try the ingredients file against it and see how it works.

▶ show

5.8. Data export

WCS formats are requested via the format KVP key (<gml:format> elements for XML POST requests), and take a valid MIME type as value. Output encoding is passed on to the the GDAL library, so the limitations on output formats are devised accordingly by the supported raster formats of GDAL. The valid MIME types which Petascope may support can be checked from the WCS 2.0.1 GetCapabilities response:

▶ show

In case of encode processing expressions, besides MIME types WCPS (and rasql) can also accept GDAL format identifiers or other commonly-used format abbreviations like “CSV” for Comma-Separated-Values for instance.

5.9. rasdaman / petascope Geo Service Administration

The petascope conpoment, which geo services contact through its OGC APIs, uses rasdaman for storing the raster arrays; geo-related data parts (such as geo-referencing), as per coverage standard, are maintained by petascope itself.

Petascope is implemented as a war file of Java servlets. Internally, incoming requests requiring coverage evaluation are translated by petascope, with the help of the coverage metadata, into rasql queries executed by rasdaman as the central workhorse. Results returned from rasdaman are forwarded by petascope to the client.


rasdaman can maintain arrays not visible via petascope (such as non-geo objects like human brain images). Data need to be imported via Data Import, not rasql, for being visible as coverages.

For further internal documentation on petascope see Developer introduction to petascope and its metadata database.

5.9.1. Service Startup and Shutdown

  • For external petascope and SECORE servlets, start/stop external tomcat which deploys these web applications.
  • For embedded petascope and secore servlets normally get started and stopped automatically through the standard scripts, start_rasdaman.sh``and ``stop_rasdaman.sh.

5.9.2. petascope Configuration

The petascope services are configured in file $RMANHOME/etc/petascope.properties.


For changes to take effect Tomcat needs to be restarted after editing this file.

5.9.3. petascope Security

In $RMANHOME/etc/petascope.properties, by default only local IP addresses configured by allow_write_requests_from setting key are allowed to send write requests to petascope (e.g: InsertCoverage, DeleteCoverage,…).

Any write requests from a not-listed IP address will be blocked. However, if one has petascope admin user credentials, configured by petascope_admin_user and petascope_admin_pass setting keys, then one can send write requests with these credentials via basic authentication header. Petascope will accept requests as they come from petascope admin user.

This typical case is used by WSClient, when one has logged in as petascope admin user and can send requests to delete a coverage or insert WMS styles for a WMS layer.

5.9.4. Meta Database Connectivity

Non-array data of coverages (here loosely called metadata) are stored in another database, separate from the rasdaman database. This backend is configured in $RMANHOME/etc/petascope.properties.

As a first action it is strongly recommended to substitute {db-username} and {db-password} by some safe settings; keeping obvious values constitutes a major security risk.

Note that the choice is exclusive: only one such database can be used at any time. Changing to another database system requires a database migration which is entirely the responsibility of the service operator and involves substantially more effort than just changing these entries; generally, it is strongly discouraged to change the meta database backend.

If necessary, add the path to the JDBC jar driver to petascope.properties using metadata_jdbc_jar_path and spring.datasource.jdbc_jar_path.

Several different systems are supported as metadata backends. Below is a list of petascope.properties settings for different systems that have been tested successfully with rasdaman. Postgresql (default)

The following configuration in petascope.properties enables PostgreSQL as metadata backend:

▶ show HSQLDB

The following configuration in petascope.properties enables HSQLDB as metadata backend:

▶ show H2

The following configuration in petascope.properties enables H2 as metadata backend:

▶ show

5.9.5. petascope Standalone Deployment

The petascope and secore servlets can be deployed through any suitable servlet container, or can be operated standalone using its built-in embedded container. The embedded variant is activated through the directive java_server=embedded in the respective configuration file.

Below are excerpts from the two configuration files affected showing how to configure this mode.

  • $RMANHOME/etc/petascope.properties

    ▶ show

  • $RMANHOME/etc/secore.properties

    ▶ show

In this standalone mode petascope and secore can be started individually using the central startup/shutdown scripts of rasdaman:

$ start_rasdaman.sh --service [secore | petascope]
$ stop_rasdaman.sh --service [secore | petascope]

Both servlets can beven be started from the command line:

$ java -jar rasdaman.war [ --petascope.confDir={path-to-properties-file} ]
$ java -jar def.war
  • The port required by the embedded tomcat will be fetched from the server.port setting in petascope.properties. Assuming the port is set to 9009, petascope can be accessed via URL http://localhost:9009/rasdaman/ows.
  • For secore, the port required by the embedded tomcat will be fetched from the server.port setting in secore.properties. Assuming the port is set to 9010, secore can be accessed via URL http://localhost:9010/def.


Configuration parameter secoredb.path must be set in secore.properties file to a directoy where the effective SECORE user has write access for creating the XML database files.

5.9.6. petascope Serving Static Content

Serving external static content (such as HTML, CSS, and Javascript) residing outside rasdaman.war through petascope can be enabled with the following setting in petascope.properties:


with an absolute path to a readable directory containing an index.html. This will be served as the root, ie: at URL http://localhost:8080/rasdaman/.

5.9.7. Logging

Configuration file petascope.properties also defines logging. The log level can be adjusted in verbosity. Tomcat restart is required for new settings to become effective.


Make sure that Tomcat has write permissions on the petascope.log file specified.

5.10. Geo Service Standards Compliance

rasdaman community is OGC WCS reference implementation and supports the following conformance classes:

  • OGC CIS:
  • CIS 1.0:
  • Class GridCoverage
  • Class RectifiedGridCoverage
  • Class ReferenceableGridCoverage
  • Class gml-coverage
  • Class multipart-coverage
  • CIS 1.1:
  • Class grid-regular
  • Class grid-irregular
  • Class gml-coverage
  • Class json-coverage
  • Class other-format-coverage
  • WCS 2.0:
  • WCS Core
  • WCS Range Subsetting
  • WCS Processing (supporting WCPS 1.0)
  • WCS Transaction
  • WCS Scaling
  • WCS Interpolation
  • WMS 1.3.0:
    • all raster functionality, including SLD ColorMap styling


With WCS 2.1, petascope provides an additional proprietary parameter to request CIS 1.0 coverages to be returned as CIS 1.1 coverages. This is specified by adding parameter outputType=GeneralGridCoverage.