Friday, 20 February 2015

Returning image for each iteration using Google Earth Engine?



I'm trying to map the maximal amount of days without rain using the TRMM dataset in Google Earth Engine. I'm doing this by iterating over the collection and if no rain has fallen, one gets added to the cell (code below). When rain has fallen the value gets multiplied by 0 so the "counter" is reset. Then I would like to store each result of each iteration in a Image collection and then select the maximum value to get the longest consecutive dry period.


But that is the theory. When I put this in a script I get an error while adding the image of one iteration to a list.


Does anyone know why this is and how this can be solved?


Code:


var list = [];
function drylength(current, previous){
var mask = current.remap([0], [1], 0,"precipitation").rename('precipitation');
var sum = mask.add(previous).multiply(mask);

list.push(sum);

return sum;
}

var dataset = TRMM
.filterDate("2015-01-01","2015-02-01")
.sort('system:time_start:');

var totalPrecipitation = dataset.iterate(drylength, dataset.max()
.remap([0], [0], 0, "precipitation")
.rename('precipitation'));


print(list);
print(totalPrecipitation);
Map.addLayer(ee.Image(totalPrecipitation), imageVisParam);

Furthermore it appears only 3 items are stored in the list which makes me assume the iteration is more complex than a literal iteration where all images are calculated one by one?


Here is an image of the error:


Google Earth Engine errors


Errors written if image is not visible or for search engines:


Failed to decode JSON.

Error: Field 'value' of object '{"type":"ArgumentRef","value":null}' is missing or null.
Object: {"type":"ArgumentRef","value":null}.

and:


Unknown variable references: [_MAPPING_VAR_0_0, _MAPPING_VAR_0_1].

Answer




Furthermore it appears only 3 items are stored in the list which makes me assume the iteration is more complex than a literal iteration where all images are calculated one by one?



You've got some of the idea.



In Earth Engine, your JavaScript code is, by default, not at all involved in the substantial computation. Instead, it is executed to construct a data structure representing the desired computation (in JSON), which is then sent to the Earth Engine servers to be run.


Therefore, any client-side function in map or iterate is not called for every item in the collection, but once to get that representation. (Or in this case, three times because you have three separate server calls: two prints and a Map.addLayer.)


The documentation for map mentions this, but I see the documentation for iterate doesn't.



The mapped function is limited in the operations it can perform. Specifically, it can’t modify variables outside the function; it can’t print anything; it can’t use JavaScript ‘if’ or ‘for’ statements. However, you can use ee.Algorithms.If() to perform conditional operations in a mapped function.



So, you cannot expect the code you have written, which modifies a variable from inside the function supplied to iterate, to be useful. It does not collect the actual data, but only the placeholders that are meant to be used by iterate (hence names like _MAPPING_VAR_0_0).


Instead, what you must do is put the data you want to generate in the iterated value. In this case, this is easy to do — just return the accumulated list, and when you want the previous image take the last element of the list. So, I think this is what you wanted to do:


function drylength(current, previous){
previous = ee.List(previous); // cast to establish the client-side type

var mask = current.remap([0], [1], 0,"precipitation").rename('precipitation');
var sum = mask.add(previous.get(-1)).multiply(mask);

return previous.add(sum);
}

var dataset = TRMM
.filterDate("2015-01-01","2015-02-01")
.sort('system:time_start:');


var list = ee.List(dataset.iterate(drylength, ee.List([
dataset.max()
.remap([0], [0], 0, "precipitation")
.rename('precipitation')
])));
var totalPrecipitation = list.get(-1);

print(list);
print(totalPrecipitation);
Map.addLayer(ee.Image(totalPrecipitation), imageVisParam);


(Disclaimer: I have only modified the code so that it runs successfully, not checked whether the outputs are scientifically reasonable.)


No comments:

Post a Comment

arcpy - Changing output name when exporting data driven pages to JPG?

Is there a way to save the output JPG, changing the output file name to the page name, instead of page number? I mean changing the script fo...