I'm using gdal_calc.py
to do some raster operations. The raster files stores precipitation values that are between 0 - 40 l/m² aprox. in some cases and the operations i'm trying to do:
- Values greater than 20 --> reclasify to 20.
- Values lower than 0 --> reclasify to 0.
- Average of the reclasified rasters.
Here are some information of the inputs raster:
- RASTER "A":
Band 1 Block=256x16 Type=Float32, ColorInterp=undefined Description = 1072016p
Min=0 Max=0.399 NoData Value=-3.4028234663852886e+38
- RASTER "B"
Band 1 Block=256x16 Type=Float32, ColorInterp=undefined Description = 972016p
Min=0 Max=2.599 NoData Value=-3.4028234663852886e+38
This is what I tried:
gdal_calc.py -A ./datos/10072016p -B ./datos/9072016p --calc="20*(A>20)" --calc="0*(A<0)" --calc="20*(B>20)" --calc="0*(B<0)" --calc="A+B/2" --outfile=result.tiff
And the result i'm getting:
Band 1 Block=3922x1 Type=Float32, ColorInterp=Gray
Min=-4294967295 Max=4294967295 NoData Value=1.175494351e-38
So, as you can see is not the expected result? What i'm missing or what i'm doing wrong?
EDIT 17/08/2016
After some work trying to understand what's happening I've conclude that the operations that was failling was 0*(A<0)
, 20*(A>20)
, ...
It works if I just calculate the average of all rasters:
(A + B + C + ...)/length
So the problem, really is that I can't reclassify the values lower than 0 and greater than 20.
Here is the approach i'm using that is working (NodeJS Script) :
const fs = require('fs'),
Exec = require('child_process').exec,
path = require('path'),
dataDir = './datos', // Directorio de donde coger los archivos raster
reg = /.*p$/, // Regex detecto p al final del archivo
// Devuelve una letra entre A-Z y A1-Z1 si se supera length > 26
getNums = length => length <= 26 ?
Array.from({length}, (el, i)=> String.fromCharCode(i + 65)) :
Array.from({length : 26}, (el, i)=> String.fromCharCode(i + 65)).concat(Array.from({length : length - 26}, (el, i)=> String.fromCharCode(i + 65) + 1)),
// Comprueba que sea el tipo de archivo que se quiere
_RasterFile = file => reg.exec(file),
// Coge el fichero raster y obtiene la fecha
_ParseDate = date => new Date(
+date.substring(date.length - 5, date.length - 1),
+date.substring(date.length - 7, date.length - 5) - 1,
+date.substring(0, date.length - 7)
),
// Fecha de hoy
today = new Date(),
// Fecha hace 40 días
last40days = new Date();
last40days.setDate(last40days.getDate() - 40);
// Lista de archivos finales
let listFiles = [];
// nombre del archivo resultante
let resultRasterName = `${today.getDate()}${today.getMonth() + 1 < 10 ? '0' + (today.getMonth() + 1) : today.getMonth() + 1}${today.getFullYear()}rp.tiff`;
fs.readdir(dataDir, (err, files)=>{
if(err) return console.error(err);
// Ficheros filtrados con el Regex
let rasterFiles = files.filter(_RasterFile);
// Fecha de los ficheros anteriores
let dateList = rasterFiles.map(_ParseDate);
// Puesta en común de las dos listas
listFiles = rasterFiles.map( (f, i) => ({
name : f,
path : dataDir + '/' + f,
date : dateList[i]
}))
// Cogiendo los ficheros de los últimos 40 días
.filter( f => f.date.getTime() >= last40days.getTime() )
// Ordenándolas por fecha
.sort( (a, b) => b.date.getTime() - a.date.getTime() );
// Array de letras en base a el número de archivos
let ArrayLetras = getNums(listFiles.length);
// Expresión de los cálculos a realizar ej : (A + B + C + ...)/length
let calc = '(' + ArrayLetras.join(' + ') + ')/' + ArrayLetras.length;
// Comando final que se ejecutará ej: gdal_calc.py -A ./datos/10072016p -B ... --calc="expresión" --outfile nombreArchivoFinal.tiff
let exec = listFiles.reduce( (execString, file, idx) => execString + '-' + ArrayLetras[idx] + ' ' + file.path + ' ', 'gdal_calc.py ') +
'--calc="' + calc + '" --outfile ' + resultRasterName;
console.log('executing...', exec);
Exec(exec, (error, stdout, stderr)=>{
console.log(stdout);
});
})
"A+B/2"
so it looks like--calc="(A+B)/2"
:)