4

I have created a script that suppose to create scatter plot based between two images with the same size, one has NDVI values and one has db values from Sentinel 1. The problem is that I get the next error:

Array: Parameter 'values' is required.

I can't find the reason. This is my code:


//STEP 1:NDVI

/**
 * Function to mask clouds using the Sentinel-2 QA band
 * @param {ee.Image} image Sentinel-2 image
 * @return {ee.Image} cloud masked Sentinel-2 image
 */
function maskS2clouds(image) {
  var qa = image.select('QA60');

  // Bits 10 and 11 are clouds and cirrus, respectively.
  var cloudBitMask = 1 << 10;
  var cirrusBitMask = 1 << 11;

  // Both flags should be set to zero, indicating clear conditions.
  var mask = qa.bitwiseAnd(cloudBitMask).eq(0)
      .and(qa.bitwiseAnd(cirrusBitMask).eq(0));

  return image.updateMask(mask).divide(10000)
  .copyProperties(image, ['system:time_start']);
}

// Map the function over one year of data and take the median.
// Load Sentinel-2 TOA reflectance data.
var dataset = ee.ImageCollection('COPERNICUS/S2')
                  .filterDate('2019-01-01', '2019-11-12')
                  // Pre-filter to get less cloudy granules.
                  .filter(ee.Filter.lt('CLOUDY_PIXEL_PERCENTAGE', 20))
                  .select('B2','B3','B4','B8','QA60')
                  .filterBounds(geometry)
                  .map(maskS2clouds);

var clippedCol=dataset.map(function(im){ 
   return im.clip(geometry);
});

// Get the number of images.
var count = dataset.size();
print('Count: ',count);
// print(clippedCol);//here I get the error messege "collection query aborted after accumulation over 5000 elements
// print(dataset,'dataset');//the same error here

//function to calculate NDVI
var addNDVI = function(image) {
  var ndvi = image.normalizedDifference(['B8', 'B4'])
  .rename('NDVI')
  .copyProperties(image,['system:time_start']);
  return image.addBands(ndvi);

};

//NDVI to the clipped image collection
var withNDVI = clippedCol.map(addNDVI).select('NDVI');


var NDVIcolor = {
  min: 0,
  max:1,
  palette: ['FFFFFF', 'CE7E45', 'DF923D', 'F1B555', 'FCD163', '99B718', '74A901',
    '66A000', '529400', '3E8601', '207401', '056201', '004C00', '023B01',
    '012E01', '011D01', '011301'],
};

//Filter according to number of pixels

var ndviWithCount = withNDVI.map(function(image){
  var countpixels = ee.Number(image.reduceRegion({
  reducer: ee.Reducer.count(),
  geometry: geometry,
  crs: 'EPSG:4326',
  scale: 20,
  }).get('NDVI'));

  return image.set('count', countpixels);
});

print(ndviWithCount, 'ndviWithCount');

var max = ndviWithCount.reduceColumns(ee.Reducer.max(),  ["count"]);
print('Number of pixels max:',max.get('max'));


//filter between a range
var filterNDVI = ndviWithCount.filter(ee.Filter.rangeContains(
          'count', 98258, 98258));
print('Filtered NDVI:', filterNDVI);

var listOfImages =(filterNDVI.toList(filterNDVI.size()));

var listOfNumbers = [5]



for (var i in listOfNumbers) {
  var image = ee.Image(listOfImages.get(listOfNumbers[i]));
  var toexport=image.visualize(NDVIcolor).addBands(image);


  // do what ever you need with image
  Map.addLayer(image, NDVIcolor, i);
  Export.image.toDrive({
  image: toexport.toFloat(),
  description: i,
  scale:20,
  crs:'EPSG:4326',
  maxPixels:1310361348,
  region:geometry.geometry().bounds()


});


 }
Map.centerObject(geometry);


//STEP2: SAR

// Filter the collection for the VH product from the descending track

//var geometry=MITR;
var Sentinel1 = ee.ImageCollection('COPERNICUS/S1_GRD')
        .filter(ee.Filter.listContains('transmitterReceiverPolarisation', 'VH'))
        .filter(ee.Filter.eq('orbitProperties_pass', 'DESCENDING'))
        .filter(ee.Filter.eq('instrumentMode', 'IW'))
        .select('VH')
        .filterDate('2019-01-01','2019-11-12')
        .filterBounds(geometry);

var clippedVH= Sentinel1.map(function(im){ 
   return im.clip(geometry);
}); 

var clippedVHsize=clippedVH.size();
print('SAR Size:',clippedVHsize);
print('SAR images data:',clippedVH)

var listOfImagesSAR =(clippedVH.toList(clippedVH.size()));

var listOfNumbersSAR = [3];

for (var i in listOfNumbersSAR) {
  var image = ee.Image(listOfImagesSAR.get(listOfNumbersSAR[i]));
  var toexport=image.visualize({min: -30, max: 1}).addBands(image);


  // do what ever you need with image
  Map.addLayer(image,{min: -30, max: 1}, i);
  Export.image.toDrive({
  image: toexport.toFloat(),
  description: i,
  scale:10,
  crs:'EPSG:4326',
  maxPixels:1310361348,
  region:geometry.geometry().bounds()

});


 }


var imageNDVIcor=ee.Image(listOfImages.get(5));
var imageSARcor=ee.Image(listOfImagesSAR.get(3));

// print(imageNDVIcor)
// print(imageSARcor)


// Convert the band data to plot on the y-axis to arrays.
var x= ee.Array(imageNDVIcor.get('NDVI'));
var y = ee.Array(imageSARcor.get('VH'));

// Make a band correlation chart.
var chart = ui.Chart.array.values(y, 0, x)
    .setSeriesNames(['SAR vs NDVI'])
    .setOptions({
      title: 'NDVI vs SAR VH',
      hAxis: {'title': 'SAR VH'},
      vAxis: {'title': 'NDVI'},
      pointSize: 3,
});

// Print the chart.
print(chart);

edit: I have tried also to change projection but I have gotten the same error: The projection changes has been done with the following script:

//select the images for scatter plot
//select NDVI
var imageNDVIcor=ee.Image(listOfImages.get(5));
var imageSARcor=ee.Image(listOfImagesSAR.get(3));

// Get information about the  projection.
var sar1Projection =  imageSARcor.projection();
print('SAR projection:', sar1Projection);

var NDVIProjection =  imageNDVIcor.projection();
print('NDVI projection:',  NDVIProjection);

var SARreproject=imageSARcor.reduceResolution({reducer: ee.Reducer.mean()}).reproject({crs: NDVIProjection});



// print(imageNDVIcor)
// print(imageSARcor)
//Map.addLayer(imageNDVIcor,NDVIcolor,'NDVI select');
//Map.addLayer(imageSARcor,{min: -30, max: 1},'SAR select');




// Convert the band data to plot on the y-axis to arrays.
var x= ee.Array(imageNDVIcor.get('NDVI'));
var y = ee.Array(SARreproject.get('VH'));

// Make a band correlation chart.
var chart = ui.Chart.array.values(y, 0, x)
    .setSeriesNames(['SAR vs NDVI'])
    .setOptions({
      title: 'NDVI vs SAR VH',
      hAxis: {'title': 'SAR VH'},
      vAxis: {'title': 'NDVI'},
      pointSize: 3,
});

// Print the chart.
print(chart);
2
  • Do you have a working example, e.g. list of images is not defined/shared..
    – Jobbo90
    Commented Nov 25, 2019 at 12:03
  • @Jobbo90 I have had added it now
    – ReutKeller
    Commented Nov 28, 2019 at 13:16

2 Answers 2

5
+50

My understanding of your problem is that you want to generate a paired scatterplot, where each point on the plot represents a pixel in the imagery, paired across NDVI and SAR from the two datasets. The approach I use to solve this derives largely from Kevin's work here. Because a geometry isn't included above, I choose a small county in Maine as a starting point.

I remove a lot of unnecessary code, and focus on the image that you choose to extract from listOfImages and listofImagesSAR. Because I used a different geometry, I accordingly choose different/arbitrary image indices to plot from. I also changed the bounds that you designate for the number of pixels (filterNDVI) because the appropriate values for that will depend on the size of your geometry. Note that the sampling scheme (var sample ...) incorporates a scale (here, 2000), because it's easy to max out the 5000 elements thing in Earth Engine when comparing raster datasets, especially ones with a scale as fine as Sentinel data. If you want to make a chart for all pixels, you'll have to generate it without defining a scale argument, and then export rather than print to the console.

var geometry = ee.FeatureCollection('TIGER/2016/Counties')
  .filter(ee.Filter.eq('NAME', 'Waldo'));

//STEP 1:NDVI

/**
 * Function to mask clouds using the Sentinel-2 QA band
 * @param {ee.Image} image Sentinel-2 image
 * @return {ee.Image} cloud masked Sentinel-2 image
 */
function maskS2clouds(image) {
  var qa = image.select('QA60');

  // Bits 10 and 11 are clouds and cirrus, respectively.
  var cloudBitMask = 1 << 10;
  var cirrusBitMask = 1 << 11;

  // Both flags should be set to zero, indicating clear conditions.
  var mask = qa.bitwiseAnd(cloudBitMask).eq(0)
      .and(qa.bitwiseAnd(cirrusBitMask).eq(0));

  return image.updateMask(mask).divide(10000)
  .copyProperties(image, ['system:time_start']);
}

// Map the function over one year of data and take the median.
// Load Sentinel-2 TOA reflectance data.
var dataset = ee.ImageCollection('COPERNICUS/S2')
                  .filterDate('2019-01-01', '2019-11-12')
                  // Pre-filter to get less cloudy granules.
                  .filter(ee.Filter.lt('CLOUDY_PIXEL_PERCENTAGE', 20))
                  .select('B2','B3','B4','B8','QA60')
                  .filterBounds(geometry)
                  .map(maskS2clouds);

var clippedCol=dataset.map(function(im){ 
   return im.clip(geometry);
});

// Get the number of images.
var count = dataset.size();
print('Count: ',count);
// print(clippedCol);//here I get the error messege "collection query aborted after accumulation over 5000 elements
// print(dataset,'dataset');//the same error here

//function to calculate NDVI
var addNDVI = function(image) {
  var ndvi = image.normalizedDifference(['B8', 'B4'])
  .rename('NDVI')
  .copyProperties(image,['system:time_start']);
  return image.addBands(ndvi);

};

//NDVI to the clipped image collection
var withNDVI = clippedCol.map(addNDVI).select('NDVI');


var NDVIcolor = {
  min: 0,
  max:1,
  palette: ['FFFFFF', 'CE7E45', 'DF923D', 'F1B555', 'FCD163', '99B718', '74A901',
    '66A000', '529400', '3E8601', '207401', '056201', '004C00', '023B01',
    '012E01', '011D01', '011301'],
};

//Filter according to number of pixels

var ndviWithCount = withNDVI.map(function(image){
  var countpixels = ee.Number(image.reduceRegion({
  reducer: ee.Reducer.count(),
  geometry: geometry,
  crs: 'EPSG:4326',
  scale: 20,
  }).get('NDVI'));

  return image.set('count', countpixels);
});

print('ndviWithCount', ndviWithCount);

var max = ndviWithCount.reduceColumns(ee.Reducer.max(),  ["count"]);
print('Number of pixels max:',max.get('max'));


// filter between a range
// Note that I change the filter because these values depend 
// strongly on the size of your geometry
var filterNDVI = ndviWithCount.filter(ee.Filter.rangeContains(
          'count', 400258, 5000000));
print('Filtered NDVI:', filterNDVI);

var listOfImages =(filterNDVI.toList(filterNDVI.size()));
print("listOfImages", listOfImages);

Map.centerObject(geometry, 8);


//STEP 2: SAR

// Filter the collection for the VH product from the descending track

//var geometry=MITR;

var Sentinel1 = ee.ImageCollection('COPERNICUS/S1_GRD')
        .filter(ee.Filter.listContains('transmitterReceiverPolarisation', 'VH'))
        .filter(ee.Filter.eq('orbitProperties_pass', 'DESCENDING'))
        .filter(ee.Filter.eq('instrumentMode', 'IW'))
        .select('VH')
        .filterDate('2019-01-01','2019-11-12')
        .filterBounds(geometry);

var clippedVH = Sentinel1.map(function(im){ 
   return im.clip(geometry);
}); 

var clippedVHsize=clippedVH.size();
print('SAR Size:',clippedVHsize);
print('SAR images data:',clippedVH);

var listOfImagesSAR =(clippedVH.toList(clippedVH.size()));

var imageNDVIcor=ee.Image(listOfImages.get(4));
var imageSARcor=ee.Image(listOfImagesSAR.get(4));

print("imageNDVIcor",imageNDVIcor);
print("imageSARcor",imageSARcor);
Map.addLayer(imageNDVIcor, {min:-1,max:1}, "ndvi");
Map.addLayer(imageSARcor, {min:-40,max:0}, "sar");

// make an image for the two variables
var pairedImage =  ee.ImageCollection.fromImages([imageNDVIcor,imageSARcor]).toBands().rename(["NDVI","SAR"]);
print("pairedImage",pairedImage);
// Generate a sample of points within the region
var sample = pairedImage.sampleRegions(geometry, null, 2000);
print("sample",sample);
// Generate chart from sample
var chart = ui.Chart.feature.byFeature(sample, 'NDVI', 'SAR')
    .setChartType('ScatterChart');
print("chart",chart);
4
  • thankj you for your answer, very helpful. Does the sample points are taken randomly? it seems like every time I run it I get less and less points even though I go up with the numbers of pixels (in 100 I got more than in 500)
    – ReutKeller
    Commented Dec 5, 2019 at 7:10
  • Based on the documentation I don’t think so, but it seems that image.sample() (as opposed to sampleRegions) does have a randomization because it allows you to set the seed. Commented Dec 5, 2019 at 7:33
  • @JasonNomad why did you choose to use sampleRegions and not just Sample?
    – ReutKeller
    Commented Dec 5, 2019 at 8:22
  • 1
    Because if you don’t specify a scale it samples all pixels in the region Commented Dec 5, 2019 at 16:50
2

An alternative approach is to use the reprojection tool:

var polygon = ee.Geometry.Polygon(
    [[[-52.783150546150175, -28.4951815593877],
        [-52.783150546150175, -28.572396589959027],
        [-52.684273593025175, -28.572396589959027],
        [-52.684273593025175, -28.4951815593877]]], null, false); 
        
var Sel_im11 =  ee.Image('LANDSAT/LC08/C01/T1_SR/LC08_222080_20190806');
var Sel_im12 = ee.Image('COPERNICUS/S2_SR/20190806T133231_20190806T133228_T22JCP');   

Map.addLayer(Sel_im11, {min:0, max:1000}, 'S2')
Map.addLayer(polygon, {}, 'Polygon')   

// Reproject to the finest spatial resolution image
var selected_crs = Sel_im12.select('B3').projection(); 
var Sel_im11_rep =  Sel_im11.reproject({ crs: selected_crs  }); 
var xVar_ndvi1 = Sel_im11_rep.normalizedDifference(['B5', 'B4']);
var yVar_ndvi2 = Sel_im12.normalizedDifference(['B8', 'B4']); 

// make an image for the two variables 
var pairedImage =  ee.ImageCollection.fromImages([xVar_ndvi1, yVar_ndvi2])
                .toBands().rename(["NDVI Landsat","NDVI S2"]); 
// Generate a sample of points within the region
var sample = pairedImage.sampleRegions({collection: polygon, 
            scale: 300});

// Generate chart from sample
var chart = ui.Chart.feature.byFeature(sample, 'NDVI Landsat', 'NDVI S2')
.setChartType('ScatterChart'); 

print("chart",chart);

Your Answer

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.