For the below posted code of evalscript
and json request
, at run time, i receive a tar
file composed of only one band which is always has been the last one listed in both of evalscript
and json request
while i have requested six bands. in other words,
for the bands specified in my question below, i receive a tar
file contains only the band of percentageOfCloudy
. When i comment out all the relevant code for percentageOfCloudy
in both of the evalscript
and json request
, then i receive a tar
contains
only the band of percentageOfCloudFree
and so on. So, I receive always a tar
contains the last band listed while i have requested six band to be delivered altoghether.
Below is always posted how i receive the response of the output of evalscript
and json request
. So, for the very first three code sections how connectForTar() is called
, requestNDVIsGeoTIFFAsTarForTS1
and connectForTar()
they show how the code is
related.
Is there any obvious reason when i always receive a .tar
file composed of only the last band listed or requested.
I wish my question is clear.
how connectForTar() is called
await Promise.all([
sentinelHubProcessAPI.requestNDVIsGeoTIFFAsTarForTS1(resp.access_token,geojson,satelliteMissionType,endpoint, operand1StartDay,operand1StartMonth,operand1StartYear,operand1EndDay,operand1EndMonth,operand1EndYear, (resultCode, contents) => {
})
.catch(rejObj => {
this.#msg = ({msg:WTFTag + 'WS:/WSSentinelhubProcessAPINDVIsProcessor/ requestNDVIsGeoTIFFAsTarForTS1 failed.', error: rejObj });
console.error(this.#msg);
throw new Error(this.#msg);
}),
.....
.....
.....
.....
])
.then(async resp => {
processAPIResultsForTS1 = resp[0];
processAPIResultsForTS2 = resp[1];
})
.then(async () => {
await Promise.all([
IOUtils.writeForPath(tarTitleForTS1, IOResources.CONST_OUTPUT_PATH_FOR_TARS.description, processAPIResultsForTS1.contents, '.tar')
.then(ioResults => {
processAPITarOfGeoTIFFsIOResultsForTS1 = ioResults;
this.#msg = ({msg:infoTag + 'WS:/WSSentinelhubProcessAPINDVIsProcessor/ tiff-contents are written to file. writeForPath() for TS1 succeeded.',
processAPIPathToTarOfGeoTIFFsForTS1: processAPITarOfGeoTIFFsIOResultsForTS1.fullPath,
processAPITarOfGeoTIFFsNameForTS1: processAPITarOfGeoTIFFsIOResultsForTS1.fileName,
});
console.info(this.#msg);
IOUtils.untarForPath(processAPITarOfGeoTIFFsIOResultsForTS1.fullPath, IOResources.CONST_OUTPUT_PATH_FOR_UNTARS.description)
.then(untarInfo => {
this.#msg = ({msg:infoTag + 'WS:/WSSentinelhubProcessAPINDVIsProcessor/ untarForPath for TS1 succeeded.',
untarInfo: untarInfo,
});
console.info(this.#msg);
});
})
.catch(error => {
this.#msg = ({msg:infoTag + 'WS:/WSSentinelhubProcessAPINDVIsProcessor/ tiff-contents failed to be written to file. writeForPath() for TS1 failed',
error: error,
});
console.info(this.#msg);
throw new Error(this.#msg);
}),
.....
.....
.....
.....
requestNDVIsGeoTIFFForTS1
requestNDVIsGeoTIFFForTS1(fetchedToken,coordsInEPSG3857,satMissionType,endpoint, sDay,sMonth,sYear,eDay,eMonth,eYear, onResult) {
return new Promise(async (resolve,reject) => {
switch(endpoint) {
case SentinelhubMissionsEndpoints.CONST_SENTINELHUB_ENDPOINT_IS_SEVICES.description:
this.#connOptsForTS1 = this.#processHTTPAPIForTS1.createOptionsForEndpointIsServices('POST', SentinelHubRequestHeader.getRequestHeaderMultipartFormData(fetchedToken));
break;
case SentinelhubMissionsEndpoints.CONST_SENTINELHUB_ENDPOINT_IS_CREODIAS.description:
this.#connOptsForTS1 = this.#processHTTPAPIForTS1.createOptionsForEndpointIsCreodias('POST', SentinelHubRequestHeader.getRequestHeaderMultipartFormData(fetchedToken));
break;
case SentinelhubMissionsEndpoints.CONST_SENTINELHUB_ENDPOINT_IS_CODEDE.description:
this.#connOptsForTS1 = this.#processHTTPAPIForTS1.createOptionsForEndpointIsCodeDE('POST', SentinelHubRequestHeader.getRequestHeaderMultipartFormData(fetchedToken));
break;
case SentinelhubMissionsEndpoints.CONST_SENTINELHUB_ENDPOINT_IS_USWEST2.description:
this.#connOptsForTS1 = this.#processHTTPAPIForTS1.createOptionsForEndpointIsUSWEST2('POST', SentinelHubRequestHeader.getRequestHeaderMultipartFormData(fetchedToken));
break;
default:
this.#msg = ({msg:errorTag + 'Unhandeled condition. where:', endpoint:endpoint});
console.log(this.#msg);
throw new Error(this.#msg);
};
await this.#processHTTPAPIForTS1.connectForTIFF(this.#connOptsForTS1,SentinelhubJSONRequest.jsonRequestNDVIAsTimeSeriesInGeoTIFFForParameters(satMissionType,coordsInEPSG3857,sDay,sMonth,sYear,eDay,eMonth,eYear), (resultCode, contents) => {
if (resultCode < 200 || resultCode > 299) {
reject({msg:errorTag + 'requestNDVIsGeoTIFFForTS1() failed. connectForTIFF() returns a rejected promise', resultCode:resultCode, contents: contents});
onResult(resultCode, contents);
} else {
resolve({msg:infoTag + 'requestNDVIsGeoTIFFForTS1() succeeded. connectForTIFF() returns a resolved promise', resultCode:resultCode, contents: contents});
onResult(resultCode, contents);
}
});
});
}
connectForTar
connectForTar(options, body, onResult) {
const resCallback = (response) => {
if (response.statusCode < 200 || response.statusCode > 299) {
console.error(errorTag,"Did not get an OK from the server. Code:",response.statusCode);
console.error(errorTag,"Did not get an OK from the server. Msg:",response.statusMessage);
onResult(response.statusCode, null, ({msg:'Did not get an OK from the server',statusMessage:statusMessage}));
response.resume();
return;
}
let data = [];
let buffer = null;
response.on('data', (chunk) => {
data.push(chunk);
});
response.on('end', () => {
buffer = Buffer.concat(data);
console.info({msg:infoTag +' response ended',contents:buffer});
onResult(response.statusCode, buffer, null);
});
}
const req = https.request(options, resCallback);
req.write(JSON.stringify(body));
req.on('error', (err) => {
console.error(errorTag + "problem with request.e.:", err);
console.error(errorTag + "problem with request.e.stack:", err.stack);
onResult(response.statusCode, null, err);
});
req.end();
}
how the bands are request in json request:
"input": {
"bounds": {
"geometry": coordsInEPSG3857,
"properties": {
"crs": "http://www.opengis.net/def/crs/EPSG/0/3857"
}
},
"data": [
{
"dataFilter": {
"timeRange": {
"from": sYear + "-" + sMonth + "-" + sDay + "T" + "00:00:00Z",
"to": eYear + "-" + eMonth + "-" + eDay + "T" + "00:00:00Z"
}
},
"type": satMissionType
}
]
},
"output": {
// "width": 1535.8321176437041,
// "height": 1646.6445869835497,
// "resx": LSP,
// "resy": LSP,
"responses": [
{
"identifier": "default",
"format": {
"type": "image/tiff",
},
"identifier": "averages",
"format": {
"type": "image/tiff",
},
"identifier": "numOfCloudFreeSamples",
"format": {
"type": "image/tiff",
},
"identifier": "numOfCloudySamples",
"format": {
"type": "image/tiff",
},
"identifier": "percentageOfCloudFree",
"format": {
"type": "image/tiff",
},
"identifier": "percentageOfCloudy",
"format": {
"type": "image/tiff",
}
},
]
},
"evalscript": evalscript,
evalscript:
how the band are generated evalscript:
//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", "CLD"],
units: "DN"
}],
output: [
{
id: "default",
bands: 5,
sampleType: "FLOAT32",
nodataValue: NaN,
},
{
id: "averages",
bands: 1,
sampleType: "FLOAT32",
nodataValue: NaN,
},
{
id: "numOfCloudFreeSamples",
bands: 1,
sampleType: "FLOAT32",
nodataValue: NaN,
},
{
id: "numOfCloudySamples",
bands: 1,
sampleType: "FLOAT32",
nodataValue: NaN,
},
{
id: "percentageOfCloudFree",
bands: 1,
sampleType: "FLOAT32",
nodataValue: NaN,
},
{
id: "percentageOfCloudy",
bands: 1,
sampleType: "FLOAT32",
nodataValue: NaN,
}
],
mosaicking: Mosaicking.ORBIT
}
}
// function updateOutput(output, collection) {
// output.default.bands = collection.scenes.length
// }
function samplesParser(samples) {
const cloudFreeSamples = new Array();
const cloudySamples = new Array();
samples.forEach((sample) => {
if (sample.CLD > 0) {
cloudySamples.push(sample);
} else {
cloudFreeSamples.push(sample);
}
});
return [cloudySamples, cloudFreeSamples];
}
function calcAverage(samples) {
let sum = 0;
for(let i = 0;i < samples.length; i++) {
sum += samples[i];
}
let avg = sum / samples.length;
return avg;
}
function calcNDVIForSamples(samples) {
const ndvis = new Array(samples.length).fill(NaN);
samples.forEach((sample, index) => {
ndvis[index] = (sample.B08 - sample.B04) / (sample.B08 + sample.B04) ;
});
return ndvis;
}
function calcPercentage(total, incidences) {
if (total <= 0) {
return NaN;
}
return ((incidences / total) * 100);
}
function evaluatePixel(samples) {
if (samples.length < 1) {
return {
default: [NaN, NaN, NaN, NaN, NaN],
averages: [NaN],
numOfCloudFreeSamples: [NaN],
numOfCloudySamples: [NaN],
percentageOfCloudFree: [NaN],
percentageOfCloudy: [NaN]
};
}
const parsedSamples = samplesParser(samples);
const ndvis = calcNDVIForSamples(parsedSamples[1]);
const averages = calcAverage(ndvis);
const numOfCloudySamples = parsedSamples[0].length;
const numOfCloudFreeSamples = parsedSamples[1].length;
const totalNumOfSamples = numOfCloudySamples + numOfCloudFreeSamples;
const percentageOfCloudy = calcPercentage(totalNumOfSamples, numOfCloudySamples);
const percentageOfCloudFree = calcPercentage(totalNumOfSamples, numOfCloudFreeSamples);
return {
default: [averages, numOfCloudFreeSamples, numOfCloudySamples, percentageOfCloudFree, percentageOfCloudy],
averages: [averages],
numOfCloudFreeSamples: [numOfCloudFreeSamples],
numOfCloudySamples: [numOfCloudySamples],
percentageOfCloudFree: [percentageOfCloudFree],
percentageOfCloudy: [percentageOfCloudy],
};
}
writeForPath
static writeForPath(fileName, outputPath, contents, ext='.tiff') {
let updatedExt = '';
return new Promise((resolve,reject)=> {
if (!fs.existsSync(outputPath)) {
fs.mkdirSync(outputPath, {recursive:true});
}
const fullPath = outputPath + fileName + updatedExt;
fs.writeFile(fullPath, contents,{flag:'w'},(error)=> {
if (error) {
reject(new Error({msg:errorTag + "error occured while writing data to file", err:error}));
throw new Error({msg:errorTag + "error occured while writing data to file", err:error.message});
}
resolve({msg:infoTag + "successfully saved the data to file", fullPath:fullPath, fileName: fileName + updatedExt});
});
});
}
untarForPath:
static untarForPath(pathToTarFileTobExtracted, untarPath) {
return new Promise((resolve,reject)=> {
if (!fs.existsSync(untarPath, untarPath)) {
fs.mkdirSync(untarPath, {recursive:true});
}
const tarStream = fs.createReadStream(pathToTarFileTobExtracted);
tarStream.pipe(tarFs.extract(untarPath))
.on('finish', () => {
fs.readdir(untarPath, (err, files) => {
if (err) {
this.msg = ({msg:errorTag + 'untarForPath().', err:err});
console.error(this.msg);
reject(this.msg);
throw new Error(this.msg);
}
this.msg = ({msg:infoTag + 'untarForPath().', untarFiles:files, numOfFilesUntar:files.length});
console.info(this.msg);
resolve(this.msg);
});
})
.on('error', (err) => {
this.msg = ({msg:errorTag + 'untarForPath().', err:err});
console.error(this.msg);
reject(this.msg);
throw new Error(this.msg);
});
});
}
Amr is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.