Hi,
Could you please also provide us the other request with a different time range which returned the same NDVI values? Thank you.
Please check
“timeRange”: {
“from”: “2000-07-12T00:00:00Z”,
“to”: “2023-08-07T23:59:59Z”
}
And just change the ‘from’ value to, for example, “timeRange”: {
“from”: “2023-07-12T00:00:00Z”,
“to”: “2023-08-07T23:59:59Z”
}
Is it clearer now?
Thanks
Hi,
This is clear now. The reason behind this is that by default the mosaicking is SIMPLE
and the mosaickingOrder is mostRecent
, meaning that the API will return the imagery mosaicked with the most recent acquisition over your AOI.
If you’re interested in getting a NDVI time series, please refer to the NDVI time series script.
Would you please tell me how did you know that I was using ‘mosaicking’ with most recent values?i mean, which part of the request I posted in the question indicates that ?
Would you please provide an example?
Hi,
The curl request you provided contains all the information about your request. Please refer to the API reference for the request body schema.
Since mosaickingOrder
is not specified in the request body, it is using the default option mostRecent
. Also, mosaicking
is not specified in your Evalscript so the default option SIMPLE
is used in this case.
as stated in the link you provided for the time series script, should I just copy and paste the evaluation-script and modify the ‘responses’ object accordingly please
I just noticed an error in the response (we will fix it later). Please copy and paste the following responses
to your request body:
"reponses": [
{
"identifier": "default",
"format": {
"type": "image/tiff"
}
},
{
"identifier": "userdata",
"format": {
"type": "application/json"
}
}
]
good morning,
actually, i tried the script you provided in this link i also used the responses parameter/object as you stated in your last reply message. i tried it in the request_builder, but the tiff files i am getting still contains the same ndvi values.
i changed the from date but the tiff files i am getting are identical.
would you please help me fix it and solve it
Note:
when i copy and pasted the script mentioned below in the request-builder, the ‘“evalscript”:’ parameter gets automatically changed to be as follows
eval-script in request-builder
"evalscript": "//VERSION=3\n function setup() {\n return{\n input: {\n bands: \"B04\", \"B08\"],\n units: \"DN\"\n }],\n output: {\n id: \"default\",\n bands: 1,\n sampleType: SampleType.FLOAT32\n }\n }\n }\n\n function evaluatePixel(sample) {\n let ndvi = (sample.B08 - sample.B04) / (sample.B08 + sample.B04)\n return ndvi ]\n }"
my request:
curl -X POST https://services.sentinel-hub.com/api/v1/process \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer xxx' \
-H 'Accept: application/tar' \
-d '{
"input": {
"bounds": {
"geometry": {
"type": "Polygon",
"coordinates": n
1579250.82367497,
6861560.75494123
],
1579262.05009723,
6861568.0993758
],
1579274.53666044,
6861572.98902966
],
1579287.75641312,
6861575.2175475
],
1579301.15146001,
6861574.6908805
],
1579314.15650793,
6861571.431256
],
1580614.32240361,
6861098.63910992
],
1580626.20934827,
6861092.89222752
],
1580636.69971985,
6861084.86506323
],
1580645.36441237,
6861074.88597658
],
1580651.8490035,
6861063.36316948
],
1580655.88825164,
6861050.76798707
],
1580657.31694429,
6861037.61563564
],
1580656.07665425,
6861024.44410741
],
1580652.2181275,
6861011.79217384
],
1580213.19772315,
6859964.91889461
],
1580207.16807032,
6859953.72991754
],
1580199.09260609,
6859943.92221921
],
1580189.27663079,
6859935.86657521
],
1580178.09124157,
6859929.86752367
],
1580165.95930318,
6859926.15185373
],
1580153.33946234,
6859924.86003288
],
1580140.70880969,
6859926.0408975
],
1580128.5448448,
6859929.64980675
],
1578507.57893836,
6860588.16085359
],
1578495.82259782,
6860594.40233978
],
1578485.57332546,
6860602.90455025
],
1578477.25717289,
6860613.31406842
],
1578471.21983892,
6860625.19819229
],
1578467.71229861,
6860638.06291925
],
1578466.88036911,
6860651.37347985
],
1578468.75864619,
6860664.57656646
],
1578473.26906401,
6860677.12333377
],
1578480.22413819,
6860688.49221449
],
1578750.38594929,
6861043.08417387
],
1578750.45489957,
6861043.17450606
],
1578969.96138274,
6861330.22514622
],
1578980.66035828,
6861341.24507847
],
1579250.82367497,
6861560.75494123
]
]
]
},
"properties": {
"crs": "http://www.opengis.net/def/crs/EPSG/0/3857"
}
},
"data": "
{
"dataFilter": {
"timeRange": {
"from": "2000-07-12T00:00:00Z",
"to": "2023-08-07T23:59:59Z"
}
},
"type": "sentinel-2-l2a"
}
]
},
"output": {
"width": 512,
"height": 276.639,
"responses": o
{
"identifier": "default",
"format": {
"type": "image/tiff"
}
},
{
"identifier": "userdata",
"format": {
"type": "application/json"
}
}
]
},
"evalscript": "//VERSION=3\n function setup() {\n return{\n input: {\n bands: \"B04\", \"B08\"],\n units: \"DN\"\n }],\n output: {\n id: \"default\",\n bands: 1,\n sampleType: SampleType.FLOAT32\n }\n }\n }\n\n function evaluatePixel(sample) {\n let ndvi = (sample.B08 - sample.B04) / (sample.B08 + sample.B04)\n return ndvi ]\n }"
}'
Please try the request below. Note that requesting data from 2016 to 2023 at once is too much for Processing API. You can either use Asynchronous Processing API or shorten the time range as I did.
curl -X POST https://services.sentinel-hub.com/api/v1/process \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer ' \
-H 'Accept: application/tar' \
-d '{
"input": {
"bounds": {
"geometry": {
"type": "Polygon",
"coordinates": [
[
[
1579250.82367497,
6861560.75494123
],
[
1579262.05009723,
6861568.0993758
],
[
1579274.53666044,
6861572.98902966
],
[
1579287.75641312,
6861575.2175475
],
[
1579301.15146001,
6861574.6908805
],
[
1579314.15650793,
6861571.431256
],
[
1580614.32240361,
6861098.63910992
],
[
1580626.20934827,
6861092.89222752
],
[
1580636.69971985,
6861084.86506323
],
[
1580645.36441237,
6861074.88597658
],
[
1580651.8490035,
6861063.36316948
],
[
1580655.88825164,
6861050.76798707
],
[
1580657.31694429,
6861037.61563564
],
[
1580656.07665425,
6861024.44410741
],
[
1580652.2181275,
6861011.79217384
],
[
1580213.19772315,
6859964.91889461
],
[
1580207.16807032,
6859953.72991754
],
[
1580199.09260609,
6859943.92221921
],
[
1580189.27663079,
6859935.86657521
],
[
1580178.09124157,
6859929.86752367
],
[
1580165.95930318,
6859926.15185373
],
[
1580153.33946234,
6859924.86003288
],
[
1580140.70880969,
6859926.0408975
],
[
1580128.5448448,
6859929.64980675
],
[
1578507.57893836,
6860588.16085359
],
[
1578495.82259782,
6860594.40233978
],
[
1578485.57332546,
6860602.90455025
],
[
1578477.25717289,
6860613.31406842
],
[
1578471.21983892,
6860625.19819229
],
[
1578467.71229861,
6860638.06291925
],
[
1578466.88036911,
6860651.37347985
],
[
1578468.75864619,
6860664.57656646
],
[
1578473.26906401,
6860677.12333377
],
[
1578480.22413819,
6860688.49221449
],
[
1578750.38594929,
6861043.08417387
],
[
1578750.45489957,
6861043.17450606
],
[
1578969.96138274,
6861330.22514622
],
[
1578980.66035828,
6861341.24507847
],
[
1579250.82367497,
6861560.75494123
]
]
]
},
"properties": {
"crs": "http://www.opengis.net/def/crs/EPSG/0/3857"
}
},
"data": [
{
"dataFilter": {
"timeRange": {
"from": "2023-07-01T00:00:00Z",
"to": "2023-08-07T23:59:59Z"
}
},
"type": "sentinel-2-l2a"
}
]
},
"output": {
"resx": 10,
"resy": 10,
"responses": [
{
"identifier": "default",
"format": {
"type": "image/tiff"
}
},
{
"identifier": "userdata",
"format": {
"type": "application/json"
}
}
]
},
"evalscript": "//VERSION=3\n// Script to extract a time series of NDVI values using \n// Sentinel 2 Level 2A data and metadata file.\nfunction setup() {\n return {\n input: [{\n bands: [\"B04\", \"B08\"],\n units: \"DN\"\n }],\n output: {\n bands: 1,\n sampleType: SampleType.FLOAT32\n },\n mosaicking: Mosaicking.ORBIT\n }\n \n }\n \n // The following function is designed to update the number of\n // output bands without knowing beforehand how many there are\n function updateOutput(outputs, collection) {\n Object.values(outputs).forEach((output) => {\n output.bands = collection.scenes.length;\n });\n }\n // function to generate a json file with a list of the NDVI \n // dates used in the analysis. \n function updateOutputMetadata(scenes, inputMetadata, outputMetadata) {\n var dds = [];\n for (i=0; i<scenes.length; i++){\n dds.push(scenes[i].date)\n }\n outputMetadata.userData = { \"acquisition_dates\": JSON.stringify(dds) }\n }\n \n function evaluatePixel(samples) {\n // Precompute an array to contain NDVI observations\n var n_observations = samples.length;\n let ndvi = new Array(n_observations).fill(0);\n \n // Fill the array with NDVI values\n samples.forEach((sample, index) => {\n ndvi[index] = (sample.B08 - sample.B04) / (sample.B08 + sample.B04) ;\n });\n \n return ndvi;\n }"
}'
i tried the request you sent.please find the results below.unfortunately they are still identical.
please let me know what i have been doing wrong.
first time range
https://ibb.co/8grLgd0
second time range:
https://ibb.co/0JV3Pkm
Hi,
These are multi-band tiffs. Each band represents the NDVI value of one acquisition, and you can find the timestamp in the userdata.json
file.
By default, the image is shown as Multiband color
(Figure 1). Please select Singleband gray
to explore data from different acquisitions (Figure 2).
Figure 1
Figure 2
Hi,
i would like to know please,
1.is every band represents specific date of acquisition?
2.in qgis, i can visulaize the tiff in grayscale and there are, for each tiff, 27 canal. how can i see the bands? the reason i am asking is, i request ndvis as time-series for two dates. the first, is from 15-06-2023 and the second is from 15-2-2023, and both till 09-08-2023. i receive identical tiffs each has 27 canal. when compariing, for example, canal 1 in the first tiff to canal 2 in the second tiff, they are different.but when comparaing canal 1 of the first tiff to canal 1 of the second tiff, they are the same!!
i would like to, have something like as posted in this link please refer to section Description of representative images
it shows two different ndvi values for 4th and 9th of july. i would like to have something like that please. ans that what i expected to see given the start/from
and to
dates mentioned above.
kindly please explain why that is happeneing and thanks in advance.
Hi,
-
Yes, please look at the userdata.json
file which is downloaded together with the tiff. It contains the timestamp for each band of your tiff. The first date in the file represents the timestamp of the first channel of your tiff.
-
Could you please provide the two requests you made in the curl format as I did in the previous response? I can check the requests for you.
-
The representative image you mentioned is a manually-produced gif. You need to check the userdata.json
to find out the timestamp of each band. The time range From
and To
defines the time range you are interested in. Then, with the ndvi time series script using ORBIT
mosaicking, the API creates a mosaic for each day in the defined time range as described in the doc and put the data into a multi-band tiff. The order of the bands depends on the mosaickingOrder
. If this parameter is not specified in the request, the default option is mostRecent
and you will get a tiff having data from the most recent date (09-08-2023 in your case) in the first channel and data from the least recent date (15-06-2023 or 15-2-2023 in your case) in the last channel.
I would recommend you going through the following webinar, which should help you understand how Processing API and Evalscript work.
Hi,
In addition to @chung.horng’s detailed response, I would like to add that you can split these bands within the .tif
file into individual layers using the Split Raster Bands
feature of the Semi-automatic classification plugin on QGIS. This in combination with the ordered list of dates within the userdata.json
file will tell you which layer belongs to which date of acquisition. This is just a suggestion and there may be multiple ways to achieve it.
thank you your assistance.i think it is now clear to me.
would you please tell me how can i modify the below posted evalscript
so that the mosaicking type is **leastRecent**
as mentioned here
eval-script for ndvi as time-series
//VERSION=3
// Script to extract a time series of NDVI values using
// Sentinel 2 Level 2A data and metadata file.
function setup() {
return {
input: [{
bands: ["B04", "B08"],
units: "DN"
}],
output: {
bands: 1,
sampleType: SampleType.FLOAT32
},
mosaicking: Mosaicking.ORBIT
}
}
// The following function is designed to update the number of
// output bands without knowing beforehand how many there are
function updateOutput(outputs, collection) {
Object.values(outputs).forEach((output) => {
output.bands = collection.scenes.length;
});
}
// function to generate a json file with a list of the NDVI
// dates used in the analysis.
function updateOutputMetadata(scenes, inputMetadata, outputMetadata) {
var dds = [];
for (i=0; i<scenes.length; i++){
dds.push(scenes[i].date)
}
outputMetadata.userData = { "acquisition_dates": JSON.stringify(dds) }
}
function evaluatePixel(samples) {
// Precompute an array to contain NDVI observations
var n_observations = samples.length;
let ndvi = new Array(n_observations).fill(0);
// Fill the array with NDVI values
samples.forEach((sample, index) => {
ndvi[index] = (sample.B08 - sample.B04) / (sample.B08 + sample.B04) ;
});
return ndvi;
}
You can do so by including "mosaickingOrder": "leastRecent"
in the data
part of your request. An example curl request is below.
curl -X POST https://services.sentinel-hub.com/api/v1/process \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer <YOUR_TOKEN_HERE>' \
-H 'Accept: application/tar' \
-d '{
"input": {
"bounds": {
"bbox": [
12.44693,
41.870072,
12.541001,
41.917096
]
},
"data": [
{
"dataFilter": {
"timeRange": {
"from": "2023-02-15T00:00:00Z",
"to": "2023-08-09T23:59:59Z"
},
"mosaickingOrder": "leastRecent"
},
"type": "sentinel-2-l2a"
}
]
},
"output": {
"width": 779.8034286939699,
"height": 523.469,
"responses": [
{
"identifier": "default",
"format": {
"type": "image/tiff"
}
},
{
"identifier": "userdata",
"format": {
"type": "application/json"
}
}
]
},
"evalscript": "//VERSION=3\n// Script to extract a time series of NDVI values using \n// Sentinel 2 Level 2A data and metadata file.\nfunction setup() {\n return {\n input: [{\n bands: [\"B04\", \"B08\"],\n units: \"DN\"\n }],\n output: {\n bands: 1,\n sampleType: SampleType.FLOAT32\n },\n mosaicking: Mosaicking.ORBIT\n }\n \n }\n \n // The following function is designed to update the number of\n // output bands without knowing beforehand how many there are\n function updateOutput(outputs, collection) {\n Object.values(outputs).forEach((output) => {\n output.bands = collection.scenes.length;\n });\n }\n // function to generate a json file with a list of the NDVI \n // dates used in the analysis. \n function updateOutputMetadata(scenes, inputMetadata, outputMetadata) {\n var dds = [];\n for (i=0; i<scenes.length; i++){\n dds.push(scenes[i].date)\n }\n outputMetadata.userData = { \"acquisition_dates\": JSON.stringify(dds) }\n }\n \n function evaluatePixel(samples) {\n // Precompute an array to contain NDVI observations\n var n_observations = samples.length;\n let ndvi = new Array(n_observations).fill(0);\n \n // Fill the array with NDVI values\n samples.forEach((sample, index) => {\n ndvi[index] = (sample.B08 - sample.B04) / (sample.B08 + sample.B04) ;\n });\n \n return ndvi;\n }"
}'
You can also set this in the Request Builder by enabling Show Advanced Options
under Data Collections as shown at the end of my reply to your question.
Please do go through the very descriptive documentation and API Reference available to make it easy for the users to create their own requests.