Home > Develop > Documentation > API > Custom evaluation script

Custom evaluation script

Custom evaluation script usage

Custom scripts are a piece of Javascript code you provide and are the way you control what values the Sentinel-Hub services will return. Each of your layers requires a custom script. This is configurable in the Configuration Utility and a multitude of pre-configured scripts are available which you may use directly or modify as necessary.

The script can use any Javascript function or language structures, as long as a valid array of numbers with fixed number of elements is returned at any point. The number of the returned array elements represent the number of the components in the output image. Note that JPEG and PNG can only support 1 or 3 color components (plus an alpha channel, if set).

Custom scripts version 2:

Custom scripts version 2 (v2) builds upon version 1 (v1). Conceptually and structurally it is very similar, but offers increased flexibility with input/output data. Sentinel-Hub will continue to support v1.

The difference between v1 and v2 lies in more flexible data handling. Most of these improvements lie in the "setup" function.
Whereas in v1 you would use the setInputComponents and setOutputComponentCount functions, in v2 the capabilities are expanded to be more powerful and transparent.

Added capabilities:

Data normalization:
In v1 data normalization was always enabled. This is now parametrizable and remains on by default.
Data normalization is the scaling of satellite digital numbers to their meaningful physical quanities. This is not applicable for all satellites (it is not necessary where digital numbers equal their physical quantities). But for Sentinel-2, for example, this means mapping to the reflectance range which is typically in the interval [0, 1].
To use: add "normalization: false" to the setup function to turn it off (see the example script below).

To get the normalization constant add the metadata parameter to the evaluatePixel function. The metadata parameter contains only the normalizationFactor field which is a double type and contains the normalization factor of the bands. See the example below.

Output data normalization:
With V2 it is possible to set the output raster type. The "sampleType" parameter in the setup function sets this. An explicit sampleType, such as SampleType.INT8 means that the evaluatePixel should return values which fit into an 8 bit integer directly. Values outside this range will be clipped. The SampleType.AUTO value is provided to emulate V1 script behavior. With this set the evaluatePixel should return values in the interval [0 1], and these values will be scaled to the output value range of the selected output format. For OGC requests using SampleType.AUTO makes most sense.

Multiple raster output:
In v1 you would always get one single raster as the output. V2 allows getting multiple rasters as the output, each with their own output bands and sample format (e.g. INT8, FLOAT32). Note however, that OGC requests do not support this functionality, and will return data of the first raster only!

Temporal support:
Temporal rendering is now supported directly within the script. Simply set "temporal: true" in the setup function and implement the necessary temporal functions.
The parameter "mosaicking" can also be set to control how temporal mosaicking takes place. If setting the parameter value to "Mosaicking.TILE" this will ensure that each output pixel is generated from input pixels from the same Sentinel-2 MGRS grid tile.

To use V2:

You also need to prefix your script with: //VERSION=2. If converting from v1, don't forget to adjust the setup function (and add temporal functions, if necessary).

Example V2 script:

//VERSION=2
function setup(ds) { // setup is now a function which returns parameters
    return {
        components: [ds.B02, ds.B03, ds.B04], // the "components" parameter says which bands to use
        output: [ // two output rasters are defined in this example
            {
                id: "default", // this is the ID of this output raster
                sampleType: SampleType.INT8, // other possibilities listed above
                componentCount: 3 // three components in this raster
            },
            {
                id: "raw",
                sampleType: SampleType.INT16,
                componentCount: 3
            },

        ],
        normalization: false  // disables input band normalization, input values to the evaluatePixel function are therefore raw digital numbers
    };
}

function evaluatePixel(samples, scenes, metadata) {
    var factor = metadata.normalizationFactor * 2.5;
    return {
        default: [ // this example raster is a visualized raster, it normalizes and brightens then converts to INT8
            toInt8(factor * samples[0].B04),
            toInt8(factor * samples[0].B03),  
            toInt8(factor * samples[0].B02) ],
        raw: [ // this raster just returns the raw digital numbers with no further processing
            samples[0].B04,
            samples[0].B03,
            samples[0].B02
        ]        
    };  // outputs are treated "as-they-are", values aren't changed in any way after this step
}

function toInt8(val) { // convenience function, used above
    return Math.max(0, Math.min(val * 255, 255));
}

Custom scripts version 1:

To get custom scripts to work only two functions need to be implemented. The "setup" and "evaluatePixel" functions. Setup lets the system know what bands you wish to use and how many components it can expect in the output file. EvaluatePixel is a mapping which maps the input band values and metadata into output values.

In their simplest form they look something like this:

function evaluatePixel(samples, scenes) {
    return [samples[0].B04, samples[0].B03, samples[0].B02]; // this is an RGB visualization
}

function setup(ds) {
    setInputComponents([ds.B02, ds.B03, ds.B04]);
    setOutputComponentCount(3);
}

The evaluatePixel input parameters are samples and scenes.
Samples are an array of arrays. Think of this as a set of input bands grouped by scene. A scene is a single satellite acquisition. For non-temporal scripts there will be only one scene available (or zero if there is no data). Input bands are normalized to their corresponding physical quantities. For example, if a band represents reflectance, its values will typically be in the interval [0 1]. Values returned from the evaluatePixel function will be mapped from [0 1] to the corresponding output format range ([0 255] for JPG, or [0 65535] for 16bit TIFF, for example) for each band automatically.
Scenes are therefore equal in number to samples (being an array of bands for each scene). Each scene contains metadata about it:
scene.date - javascript Date type; is the datetime of the product/tile.
scene.idx - javascript integer type; order index of this scene within all scenes of this timerange starting with 0 up to (number of scenes - 1).
scene.tileOriginalId - String type; the original name of the tile/product used.
scene.orbitId - javascript integer type; the orbit ID of the product/tile. Depends on the datasource and might not be available.

The setup input parameter is ds (short for datasource). This contains all the input bands. Which bands are avilable depends on the datasource.

 

Utility Functions:

Beside the standard Javascript functions, Sentinel WMS service also provides two additional utility functions:

Utility functions info

colorMap(inputNumber, indexArray, outputValueArray)

This method returns the value in "outputValueArray" at the same index as is the location of "inputValue" in the "indexArray". For example, when indexArray = [0, 0.2, 0.4], inputValue in the interval [0, 0.2) will make coloMap to return the outputValueArray value at index 0, inputValue in the interval [0.2, 0.4) will return value at index 1, etc. InputValue lesser than the first indexArray value will return the first value in outputValueArray and inputValue greater than the last indexArray value will return the last outputValueArray value. outputValueArray can contains single numbers or even arrays of numbers (in which case, colorMap will return an array instead of a single number).

  Example of colorMap:

var value = colorMap(B04, [0, 0.2, 0.4, 0.6, 0.8, 1], [0, 0.1, 0.25, 0.4, 0.75, 1]); return [value, value, value];

colorBlend(inputNumber, indexArray, outputValueArray)

similar to colorMap, except the returned value is interpolated between two consecutive values in outputValueArray.

  Example of colorBlend:

return colorBlend(B04, [0, 0.2, 0.4, 0.6, 0.8, 1], [[0,0,0], [0.1,0.2,0.5], [0.25,0.4,0.5], [0.4,0.6,0.5], [0.75,0.8,0.5], [1,1,0.5]]);