4

I'm using gdal_calc.py to do some raster operations. The raster files stores precipitation values that are between 0 - 40 l/m2 aprox. in some cases and the operations i'm trying to do:

  1. Values greater than 20 --> reclasify to 20.
  2. Values lower than 0 --> reclasify to 0.
  3. 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);
 });
})
asked Aug 8, 2016 at 12:58
2
  • 1
    More of an FYI but you should probably put brackets in "A+B/2" so it looks like --calc="(A+B)/2" :) Commented Aug 8, 2016 at 13:12
  • I'm not sure if you can chain calculations together like that, and expect it to well. For me, it is quite interesting that it actually runs, and doesn't just crash when you try that. Commented Aug 8, 2016 at 13:19

1 Answer 1

2

If you use a simple --calc option gdal_calc.py should work fine:

gdal_calc.py -A ./datos/10072016p -B ./datos/9072016p --calc="(20*(A>20)+0*(A<0)+20*(B>20)+0*(B<0))/2" --outfile=result.tiff
answered Aug 8, 2016 at 13:39
3
  • Hi! I've tried but i'm getting the same output. I think your syntx is the right one, but the error should be coming from something different. Thank you for your answer! =) Commented Aug 8, 2016 at 14:50
  • If the maxA = 0.399 and maxB = 2.599 both rasters values are always lower than 20. Furthermore, the range 0-20 is not covered in your conditions and so in the expression. Hope this helps. Commented Aug 8, 2016 at 15:32
  • I put those rasters as examples, this is done with some other raster files whose values are in this range. Commented Aug 8, 2016 at 15:41

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.