Data Fusion
Sentinel Hub (SH) allows you to combine the data from various data sources in the same request. To use this functionality you need to prepare a request with several data sources as explained below. Data fusion can be used for any data available in Sentinel Hub including PlanetScope (TPDI) and your own data (BYOC) and with all SH data-processing APIs (Process, Statistical, Batch, etc).
All SH endpoint locations support data fusion of collections hosted at that endpoint. However, only the Processing API endpoint services.sentinel-hub.com/api/v1/process also allows combining collections hosted at different SH endpoints, such as this example.
We invite you to read our Data Fusion blog post, where you will find 6 interesting use cases and a short guide on how to use data fusion in Sentinel Hub.
Note: Using this functionality can consume more Processing Units since it processes more data. The rules listed here apply.
Preparing a Data Fusion Request
Preparing a data fusion request is very similar to preparing any process
API request that uses a single data source. Thus, only the parts which differ when performing data fusion requests are described below.
Request Body
In the body of the request, more specifically in the input.data
array, you need to add more than one data
object. For each of these objects you can optionally specify the property:
id
(optional) - a string of your choosing. It is used as an identifier for this input so that it can be referred to in the evalscript. It is not mandatory to define it but we recommend to do so, see examples below. Note that the type (e.g., "sentinel-2-l1c") is insufficient as an identifier because you may use multiple inputs from the same data collection.
An example of the input.data
array with two elements:
{"input": {"data": [{"type": "sentinel-2-l1c","id": "l1c","dataFilter": {"timeRange": {"from": "2018-10-01T00:00:00Z","to": "2018-11-01T00:00:00Z"},"mosaickingOrder": "leastRecent"}},{"type": "sentinel-2-l2a","id": "l2a","dataFilter": {"timeRange": {"from": "2018-10-01T00:00:00Z","to": "2018-11-01T00:00:00Z"},"mosaickingOrder": "leastRecent"}}]}}
As you can see in the example above all data collection specific options are still available.
Evalscript
Setup
In the evalscript, under the input
array in the setup
function, specify all input collections. Optionally, match the id
from the input.data
object of the request body to the datasource
parameter of each input collection. This ensures that the correct collection will be used for input bands. For example:
//VERSION=3function setup() {return {input: [{datasource: "l2a", bands: ["SCL"], units: "DN"},{datasource: "l1c", bands: ["B02", "B03", "B04"], units: "REFLECTANCE"}],output: [{bands: 3, sampleType: SampleType.AUTO}]}}
Since the datasource
parameter is optional, in case you choose to omit it, the order of the input objects becomes relevant and must be the same as in the request body.
//VERSION=3function setup() {return {input: [{bands: ["B02", "B03", "B04"], units: "REFLECTANCE"}, // sentinel-2-l1c{bands: ["SCL"], units: "DN"} // sentinel-2-l2a],output: [{bands: 3, sampleType: SampleType.AUTO}]}}
Specifying mosaicking for each input is also possible. Simply add the mosaicking
parameter to each input object. This overrides the global mosaicking
parameter which you typically use outside the input
object. Combinations of both are therefore possible, and when present, the value within the input
object is used. The default remains SIMPLE
. In the example below, the global default SIMPLE
mosaicking value is never used as ORBIT
is specified for all inputs.
//VERSION=3function setup() {return {input: [{bands: ["B02", "B03", "B04"], units: "REFLECTANCE", mosaicking: "ORBIT"}, // sentinel-2-l1c{bands: ["SCL"], units: "DN", mosaicking: "ORBIT"} // sentinel-2-l2a],output: [{bands: 3, sampleType: SampleType.AUTO}]}}
Data Access
Data from each collection can be accessed inside the evaluatePixel
function, however as now multiple inputs are accessible the syntax is slightly different to the single data collection case. Assuming the evaluatePixel
parameter is called samples
, this object is always a key-value pair (dictionary). Obtain data for each collection in one of two ways.
If you are using the datasource
object in your setup
function, simply use its values as keys to the samples
object. This gets an array of mosaicked values. Each array behaves exactly the same way as a non-datafusion non-SIMPLE
mosaicking samples
object. Note that this is an array even for datafusion with SIMPLE
mosaicking, unlike non-datafusion requests; of course in this case the array either contains exactly one object or is empty.
If datasource
was specified in setup
:
function evaluatePixel(samples) {// "l1c" and "l2a" match the datasource values specified in the setup functionvar l1cMosaics = samples.l1c; // gets the array of sentinel-2-l1c mosaicsvar l1cSample = l1cMosaics[0]; // gets the first mosaic. access bands from this objectvar scl = samples.l2a[0].SCL; // gets the SCL band of the first sentinel-2-l2a mosaicif (2 <= scl && scl <= 7) {return [l1cSample.B04, l1cSample.B03, l1cSample.B02];}return [0,0,0];}
If datasource
wasn't specified in setup
, you can access the data with keys being ordinal numbers starting with 0
. Again, the order is as specified in the request body.
function evaluatePixel(samples) {// '0' is the identifier of the first input in the input.data array (sentinel-2-l1c)// '1' is the identifier of the second input in the input.data array (sentinel-2-l2a)var l1cMosaics = samples['0']; // gets the array of mosaics of the first input (sentinel-2-l1c)var l1cSample = l1cMosaics[0]; // gets the first mosaic. access bands from this objectvar scl = samples['1'][0].SCL; // gets the SCL band of the first mosaic of the second input (sentinel-2-l2a)if (2 <= scl && scl <= 7) {return [l1cSample.B04, l1cSample.B03, l1cSample.B02];}return [0,0,0];}
Note: While the above example works for all mosaicking types, it makes most sense for SIMPLE
mosaicking. This is because only one mosaic is accessed for each input in the script, any additional mosaics, which would get generated if ORBIT
or TILE
mosaicking was used, are ignored.