In earth engine, I divided my Image in several tiles and want to sample 500 pixels from each tile, then export the samples in separate .csv file to my drive. I don't find a solution to name the files for export in a unique way. In the code below, I created a basename ("Tile_") and unique tile indices ("indices"). However, I don't find a way to bring "Tile_" and the individual index together in the mapping process.
// sample random pixels from each tile
// Step 1: Convert the grid to a FeatureCollection
var gridFc = ee.FeatureCollection(ee.List(grid));
// Step 2: Dynamically define band names
var bandNames = ee.List.sequence(0, 20).map(function(i) {
i = ee.Number(i).format('%d'); // Format the number as an integer (no decimal)
return ee.List(['temperature_2m', 'precipitation', 'snowCover']).map(function(varName) {
return ee.String(i).cat('_').cat(varName);
});
}).flatten();
print('Dynamic Band Names:', bandNames);
// Step 4: Function to process and export each tile
// Function to process each tile and sample 500 random pixels
var processTile = function(tileFeature, index) {
var tileGeometry = tileFeature.geometry(); // Correctly retrieve the geometry from the tile
// Sample 500 random pixels from the tile
var tileSamples = standImage.sample({
region: tileGeometry,
scale: pixelSize, // Match the pixel size of the image
projection: crs,
numPixels: 500, // Limit to 500 random pixels per tile
geometries: true // Include pixel geometry for indexing
});
// Ensure the samples are valid before proceeding
// tileSamples = ee.FeatureCollection(tileSamples).filter(ee.Filter.notNull(['latitude', 'longitude']));
// Generate a description using the index for naming the export task
var description = ee.String('Tile_Samples_').cat(ee.Number(index).format('%d')); // Correct tile name
print(description, 'description');
var bandNames = bandNames;
print(bandnames, 'var bandnames');
// Create the export task
Export.table.toDrive({
collection: tileSamples, // Collection of sampled pixels
description: description, // Use description to set the name
fileFormat: 'CSV', // Export as CSV
selectors: bandNames // Use valid band names for the export
});
return tileFeature; // Return the tileFeature for continued processing
};
// Get the number of tiles in the grid
var numTiles = grid.size();
// Create a list of tile indices
var indices = ee.List.sequence(0, numTiles.subtract(1));
// Map the processTile function to each tile
indices.evaluate(function(indicesList) {
indicesList.forEach(function(index) {
var tileFeature = grid.filter(ee.Filter.eq('system:index', ee.Number(index).format('%d'))).first();
// Only process if tileFeature is valid (it should have geometry)
if (tileFeature) {
processTile(tileFeature, index); // Process and export each tile
}
});
});
This results in useless file names: "ee.String({ "type": "Invocation", "arguments": { "string1": "Tile_Samples_", "string2": { "type": "Invocation", "arguments": { "number": 0, "pattern": "%d" }, "functionName": "Number.format" } }, "functionName": "String.cat"})"
.
Although the print log looks the way it should: "Tile_Samples_1"
etc.
When using the foreach javascrit method you are actually running a client side process where all the API invocation are just the json description you see as file name. the quick and dirty solution is to use getInfo() in the eport method.
Note that it's a bad way of creating a GEE query, you should rethink a bit the logic to make it work with a .map
instead and run everything in one single query to GEE servers.