3

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);
  • Do you have a working example, e.g. list of images is not defined/shared.. – Jobbo90 Nov 25 '19 at 12:03
  • @Jobbo90 I have had added it now – Reut Nov 28 '19 at 13:16
4
+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);
  • 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) – Reut Dec 5 '19 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. – JepsonNomad Dec 5 '19 at 7:33
  • @JasonNomad why did you choose to use sampleRegions and not just Sample? – Reut Dec 5 '19 at 8:22
  • 1
    Because if you don’t specify a scale it samples all pixels in the region – JepsonNomad Dec 5 '19 at 16:50

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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