Hi.
How can I convert the data from a ‘normal’ sentinel hub request for a geometry to the same format given by the statistical batch API returns?
For the same geometry’ I’ve seen distinct values from the two APIs.
I.E. for a given date and geometry in sentinel 2 batch statistical API, the band 08 has returned:
B08_B0_mean: 0.3256
When I get the same data with a standard SentinelHubRequest and average the values for the geometry pixels on band B08 I get:
Band 8 mean: 3273.40
The same issue happens for SAR data.
In the stats API:
VV_B0_mean 0.056809
VH_B0_mean 0.01612
In the request API (average over field geometry’ pixels):
VV: 11.31
VH: 3.21
Is the batch statistical returns normalized in some way?
Could you point me for the documentation or let me know how to convert the process api ‘normal’ returns to the same normalized format of the batch statistical api?
I am attaching the eval scripts for sentinel 2 below, for reference.
Batch Stats API:
evalscript = """
//VERSION=3
function setup() {
return {
input: [{
bands: [
"B02", // Blue (10m)
"B03", // Green (10m)
"B04", // Red (10m)
"B05", // Vegetation Red Edge (20m)
"B06", // Vegetation Red Edge (20m)
"B07", // Vegetation Red Edge (20m)
"B08", // NIR (10m)
"B8A", // NIR Narrow (20m)
"B11", // SWIR (20m)
"B12", // SWIR (20m)
"SCL", // Scene Classification (20m) - used for cloud detection
"AOT", // Aerosol Optical Thickness (10m)
"dataMask" // Data mask (10m)
]
}],
output: [
{ id: "B02", bands: 1, sampleType: "FLOAT32" }, // Blue
{ id: "B03", bands: 1, sampleType: "FLOAT32" }, // Green
{ id: "B04", bands: 1, sampleType: "FLOAT32" }, // Red
{ id: "B05", bands: 1, sampleType: "FLOAT32" }, // Vegetation Red Edge
{ id: "B06", bands: 1, sampleType: "FLOAT32" }, // Vegetation Red Edge
{ id: "B07", bands: 1, sampleType: "FLOAT32" }, // Vegetation Red Edge
{ id: "B08", bands: 1, sampleType: "FLOAT32" }, // NIR
{ id: "B8A", bands: 1, sampleType: "FLOAT32" }, // NIR Narrow
{ id: "B11", bands: 1, sampleType: "FLOAT32" }, // SWIR
{ id: "B12", bands: 1, sampleType: "FLOAT32" }, // SWIR
{ id: "SCL", bands: 1 }, // Scene Classification
{ id: "AOT", bands: 1 }, // Aerosol Optical Thickness
{ id: "dataMask", bands: 1 }, // Data Mask
{ id: "cloudCoverage", bands: 1, sampleType: "UINT8" } // Cloud Coverage
]
}
}
function evaluatePixel(samples) {
// Determine cloud coverage based on SCL classes (classes 3, 8, 9, 10, 11 indicate clouds or shadows)
let isCloud = (samples.SCL === 3 || samples.SCL === 8 || samples.SCL === 9 || samples.SCL === 10 || samples.SCL === 11) ? 1 : 0;
return {
B02: [samples.B02], // Blue
B03: [samples.B03], // Green
B04: [samples.B04], // Red
B05: [samples.B05], // Vegetation Red Edge
B06: [samples.B06], // Vegetation Red Edge
B07: [samples.B07], // Vegetation Red Edge
B08: [samples.B08], // NIR
B8A: [samples.B8A], // NIR Narrow
B11: [samples.B11], // SWIR
B12: [samples.B12], // SWIR
SCL: [samples.SCL], // Scene Classification
AOT: [samples.AOT], // Aerosol Optical Thickness
dataMask: [samples.dataMask], // Data Mask
cloudCoverage: [isCloud] // Cloud coverage (0 for clear, 1 for cloud)
}
}
"""
request_payload = {
"input": {
"features":{
"s3": {
"url": f"s3://{S3_BUCKET_BATCH_API}/{path_geopackage_s3}",
"accessKey": AWS_ID,
"secretAccessKey": AWS_SECRET
}
},
"data": [
{
"type": "sentinel-2-l2a",
"dataFilter": {
"mosaickingOrder": "leastCC"
}
}
]
},
"aggregation": {
"timeRange": {
"from": f"{date_start}T00:00:00Z",
"to": f"{date_end}T00:00:00Z"
},
"aggregationInterval": {
"of": interval
},
"evalscript": evalscript,
"resx": resolution,
"resy": resolution
},
"output": {
"s3": {
"url": f"s3://{S3_BUCKET_BATCH_API}/{path_output_s3}",
"region": "eu-west-1",
"accessKey": AWS_ID,
"secretAccessKey": AWS_SECRET
}
}
}
headers = {
'Content-Type': 'application/json',
'Accept': 'application/json'
}
url = "https://services.sentinel-hub.com/api/v1/statistics/batch"
‘Normal’ pixel data Sentinel Request:
evalscript = """
//VERSION=3
function setup() {
return {
input: [{
bands: ["B02", "B03", "B04", "B05", "B06", "B07", "B08", "B8A", "B11", "B12", "dataMask", "SCL", "AOT"],
units: "DN"
}],
output: {
id: "default",
bands: 13,
sampleType: SampleType.FLOAT32
}
}
}
function evaluatePixel(sample) {
return [sample.B02, sample.B03, sample.B04, sample.B05, sample.B06, sample.B07, sample.B08,
sample.B8A, sample.B11, sample.B12, sample.dataMask, sample.SCL, sample.AOT]
}
"""
request = SentinelHubRequest(
data_folder=_data_folder,
evalscript=evalscript,
input_data=[
SentinelHubRequest.input_data(
data_collection=DataCollection.SENTINEL2_L2A,
time_interval=_time_interval,
mosaicking_order='leastCC',
other_args={"dataFilter": {"maxCloudCoverage": MAX_CC, "mosaickingOrder": "leastCC"}, "processing": {"upsampling": "BILINEAR"}}
),
],
responses=[
SentinelHubRequest.output_response('default', MimeType.TIFF),
],
bbox=_bbox,
geometry=geometry,
size=size,
config=config
)
try:
response = request.get_data(save_data=True)
filename_d = request.get_filename_list()
return filename_d
except Exception as e:
print('Error getting sentinel imagery {0}'.format(e))