How do I generate only positive NDVI values from Google Earth Engine for my study area? - time-series

Please, how do get positive values of NDVI for my study area?
Please see my Javascript code below. Unfortunately, after running the code, the NDVI chart generated are mostly negative. (See image attached). How do I correct this please?
Image of generated NDVI chart
See my Javascript code:
var startDate = '2001-01-01'
var endDate = '2020-12-31'
var images = landsat7.filter(ee.Filter.date(startDate, endDate));
print(images);
var ndvi = function(image){
var ndv = image.normalizedDifference(['B4', 'B3']);
// for Sentinel, use var scaled = image.normalizedDifference(['SR_B4', 'SR_B3']);
return ndv.copyProperties(image, ['system:index', 'system:time_start'])
}
var ndvi = images.map(ndvi)
print(ndvi);
var nd = ndvi.max().clip(finni);
Map.addLayer(nd, {min:0,max:1,palette:['white', 'Green']}, 'NDVI');
var chart = ui.Chart.image.seriesByRegion({
imageCollection:ndvi,
regions:finni,
reducer: ee.Reducer.mean(),
scale:30,
});
print(chart);

Related

Extract pixel values from image collection to make composite in google earth engine

I am trying to make a cloud-free landsat composite in Google Earth Engine in an area with a lot of clouds (Indonesian cloud-forest). Previously, I accomplished this successfully by making a greenest pixel composite, in which I used the pixel with the highest NDVI value to make sure I was using non-cloud pixels in my composite image.
//Filter landsat 8 image collection by date, area
var collection = landsat
.filterBounds(bounds)
.filterDate(2016-08-01, 2016-10-31);
// Sort from least to most cloudy and get first (least cloudy) image
var sorted = collection.sort('CLOUD_COVER');
var image = ee.Image(sorted.first());
//Function to get NDVI
var addNDVI = function(image) {
var ndvi = image.normalizedDifference(['B5', 'B4']).rename('NDVI');
return image.addBands(ndvi);
};
//Add NDVI bands to image collection
var withNDVI = landsat.map(addNDVI);
// Make a "greenest" pixel composite using NDVI
var greenest = withNDVI.qualityMosaic('NDVI');
Map.addLayer(greenest, {bands: ['B4', 'B3', 'B2'], max: 0.15}, 'greenest');
The code works fine, however, I am concerned using the highest NDVI pixels to make my composite is over-representing forested area. Therefore, I am looking for a method to extract the pixels with the highest NDVI (to get rid of the clouds), and then using all 7 other bands of that pixel in my composite (instead of using the NDVI band itself). My questions are: would this even get rid of forest over-representation, or would I still have the same problem? Second, if this method does seem like a legitimate way to get rid clouds while making a composite that does not over-represent forest, how can I extract pixels of a high NDVI, and then use their other bands to make a composite?
It seems like however you do a quality mosaic with the greenest pixel it will almost always accentuate the forest in tropical regions (because forests are really green). I suggest you use the Landsat simple cloud score algorithm to find pixels that are least likely to be cloudy and then do your compositing based on that. Here is some code that gives you two options to make a composite. One is based on masking cloudy pixels and taking the median, another is based on the qualityMosaic() function while using the likelihood of cloud band.
var bounds = /* color: #d63000 */ee.Geometry.Polygon(
[[[94.93602603806119, -12.072520735360198],
[141.8696197880612, -13.187431968041206],
[142.3969635380612, 6.019400576838261],
[94.67235416306119, 6.456250813337956]]]),
landsat = ee.ImageCollection("LANDSAT/LC08/C01/T1_RT_TOA");
//Filter landsat 8 image collection by date, area
var collection = landsat
.filterBounds(bounds)
.filterDate('2016-08-01', '2016-10-31');
//Function to get Inverse Cloud Score
var addCloud = function(image) {
var cloudImg = ee.Algorithms.Landsat.simpleCloudScore(image);
var clouds = cloudImg.select('cloud');
var inverseClouds = ee.Image(100).subtract(clouds).rename('inverse_cloud');
return image.addBands(inverseClouds);
};
//Add cloud bands to image collection
var withCloudBand = landsat.map(addCloud);
// Option 1: Median composite after masking clouds
var noCloudsMedian = withCloudBand.map(function(img){
return img.updateMask(img.select('inverse_cloud').gt(90));
}).median();
Map.addLayer(noCloudsMedian, {bands: ['B4', 'B3', 'B2'], max: 0.30}, 'Option 1');
// Option 2: Quality mosaic based on least cloudy pixel
var noCloudQualityMosaic = withCloudBand.qualityMosaic('inverse_cloud');
Map.addLayer(noCloudQualityMosaic, {bands: ['B4', 'B3', 'B2'], max: 0.30}, 'Option 2');
Here is a link to the code to view the results: https://code.earthengine.google.com/7ea8e59b5c72340c6d784d850db856f4

Google Earth Engine: mask clouds and map a function over an image collection of different sensors

I want to combine all the Landsat sensors from 1985 up today in Google Earth Engine, remove the clouds and calculate the time-series of the NBR index. As a new GEE user I have the following:
// find all data and filter them by date
var lst5 = ee.ImageCollection('LANDSAT/LT5_SR').filterDate('1984-10-01', '2011-10-01');
var lst7 = ee.ImageCollection('LANDSAT/LE7_SR').filterDate('2011-10-01', '2013-04-07');
var lst8 = ee.ImageCollection('LANDSAT/LC8_SR').filterDate('2013-04-07', '2018-05-01');
var lst7_08 = ee.ImageCollection('LANDSAT/LE7_SR').filterDate('2007-12-01', '2008-02-01');
var lst7_92 = ee.ImageCollection('LANDSAT/LT4_SR').filterDate('1992-01-02', '1992-04-01');
// Combine all landsat data, 1985 through 2015
var everything = ee.ImageCollection(lst5.merge(lst7));
everything = everything.merge(lst8);
everything = everything.merge(lst7_08);
everything = everything.merge(lst7_92);
var alltogether = ee.ImageCollection(everything.filterDate('1984-01-01', '2018-05-01'));
From this point, I do not know how to remove the clouds and calculate the NBR index (NBR index here) for every image in my final collection.
Can anyone help me?
Thank you.
EDIT:
I think that I need to map a normalizedDifference function over my collection in order to get the NBR index but I am not sure how to do this for my collection with the different sensors.
You've got quite a lot going on here, but here's what I think you want. You should check this very carefully to ensure it's behaving as intended:
// Function to cloud mask Landsat 8.
var maskL8SR = function(image) {
// Bits 3 and 5 are cloud shadow and cloud, respectively.
var cloudShadowBitMask = ee.Number(2).pow(3).int();
var cloudsBitMask = ee.Number(2).pow(5).int();
// Get the QA band.
var qa = image.select('pixel_qa');
// Both flags should be set to zero, indicating clear conditions.
var mask = qa.bitwiseAnd(cloudShadowBitMask).eq(0).and(
qa.bitwiseAnd(cloudsBitMask).eq(0));
return image
// Scale the data to reflectance and temperature.
.select(['B5', 'B7'], ['NIR', 'SWIR']).multiply(0.0001)
.addBands(image.select(['B11'], ['Thermal']).multiply(0.1))
.updateMask(mask);
};
// Function to cloud mask Landsats 5-7
var maskL57SR = function(image) {
var qa = image.select('pixel_qa');
// Second bit must be zero, meaning none to low cloud confidence.
var mask1 = qa.bitwiseAnd(ee.Number(2).pow(7).int()).eq(0).and(
qa.bitwiseAnd(ee.Number(2).pow(3).int()).lte(0)); // cloud shadow
// This gets rid of irritating fixed-pattern noise at the edge of the images.
var mask2 = image.select('B.*').gt(0).reduce('min');
return image
.select(['B4', 'B7'], ['NIR', 'SWIR']).multiply(0.0001)
.addBands(image.select(['B6'], ['Thermal']).multiply(0.1))
.updateMask(mask1.and(mask2));
};
// find all data and filter them by date
var lst5 = ee.ImageCollection('LANDSAT/LT05/C01/T1_SR')
.filterDate('1984-10-01', '2011-10-01')
.map(maskL57SR)
var lst7 = ee.ImageCollection('LANDSAT/LE07/C01/T1_SR')
.filterDate('2011-10-01', '2013-04-07')
.map(maskL57SR)
var lst8 = ee.ImageCollection('LANDSAT/LC08/C01/T1_SR')
.filterDate('2013-04-07', '2018-05-01')
.map(maskL8SR)
var lst7_08 = ee.ImageCollection('LANDSAT/LE07/C01/T1_SR')
.filterDate('2007-12-01', '2008-02-01')
.map(maskL57SR)
var lst7_92 = ee.ImageCollection('LANDSAT/LT04/C01/T1_SR')
.filterDate('1992-01-02', '1992-04-01')
.map(maskL57SR)
// Combine all landsat data, 1985 through 2015
var everything = ee.ImageCollection(lst5.merge(lst7));
everything = everything.merge(lst8);
everything = everything.merge(lst7_08);
everything = everything.merge(lst7_92);
// NBR:
var nbrFunction = function(image) {
image = ee.Image(image)
return image.addBands(image.expression(
'(nir - 0.0001 * swir * thermal) / ' +
'(nir + 0.0001 * swir * thermal)', {
nir: image.select(['NIR']),
swir: image.select(['SWIR']),
thermal: image.select(['Thermal'])
}).rename('NBR').clamp(-1, 1));
};
everything = everything.map(nbrFunction);
var check = ee.Image(everything.first());
Map.centerObject(check);
Map.addLayer(check);
The answer works great for SR imagery! Thanks! Sorry I can't just comment because I don't have 50 reputation yet, but I saw #Abhilash Singh Chauhan's question about why ee.Number(2).pow(3)... is used for the variables cloudshadow and clouds. I had the same question and I wanted to answer that it's because of the fact that the QA Pixel bands are Decimal integers that contain Binary information. So for example band 3 for surface reflectance LANDSAT products indicates the band for cloud shadow but the values are in binary. To get the values you need to convert the band to binary, hence 2^3 and similarly 2^5 for cloud values. I hope that clarifies the comment. you can check this here: https://www.usgs.gov/landsat-missions/landsat-4-7-surface-reflectance-quality-assessment

Draw Circle at Intersection of points in highcharts heatmap

I have a heatmap where the X and Y axis are populated dynamically. I have used the following code to render a circle at the intersection of X and Y. This is based off a fiddle where it was done for a scatter plot and worked in pre-5 highcharts. Now it doesn't work. Any help would be greatly appreciated.
This is the portion of the code that is added to the sales heatmap:
var circleX = 'Lukas';
var circleY = 'Wednesday';
var circleR = 1.0;
function addCircle(chart){
if (this.circle){
$(this.circle.element).remove();
}
var pixelX = chart.xAxis[0].toPixels(chart.xAxis[0].categories.indexOf(circleX));
var pixelY = chart.yAxis[0].toPixels(chart.yAxis[0].categories.indexOf(circleY));
var pixelR = chart.xAxis[0].toPixles(circleR) - chart.xAxis[0].toPixels(0);
Here is a fiddle: Fiddle

how to show vector layers from shp in geoserver fast

i have so many columns in my shp,
i use data from my shp to show vector layer,
and i did it but sometimes take a long time even unresponsive script
can anyone help me how to show vector layers from shp in geoserver faster
this is my code that im using
var hitungJumlah = vectorSource.getFeatures();
for(var k=0;k<hitungJumlah.length;k++){
var id = vectorSource.getFeatures()[k].getId();
var feature = vectorSource.getFeatureById(id);
if(feature.get('klas')!=null){
var a = feature.get('klas');
}else{
a = "";
}
if(a=="Utama"){
//warna is my ol.layer.Vector
warna.getSource().addFeature(feature);
}
}

Is it possible to add a icon symbol to a polygon

I am currently working on a openlayers 3 project and for better visulaizing i need to show both. The Polygon shape(attribute based color) which works great and an icon on the polygon position. I know that the polygon contains multiple coordinates and so its not so easy to define a position for the icon. Now i have some kind of workaround that creates an seperate overlay with the interior Points of the polygon to mark the position of the icons. To make the project more simple i want to combine these two styling. Does anyone know if its possible?
Kind Regards
I presumes that you use a ol.source.serversource for your data.
The trick is to test all your features for being a polygon. If it is, you create a point feature you add to your source.
First create the source and the layer:
var avlVectorSource = new ol.source.ServerVector({
format: new ol.format.GeoJSON(),
loader: function(extent, resolution, projection) {
myLoader(resolution);
}
});
var myLayer = new ol.layer.Vector({
source: myVectorSource,
style: myStyleFunction
});
The layer has a style function to set the right icon.
The main thing is the loader:
var myLoader = function(resolution){
$.ajax({
url: "http://myJsonSource.com",
timeout: 1000,
success: function(response) {
var layerJSONString = $.parseJSON(response);
var newFeatures = [];
j= 0;
var size=layerJSONString.features.length;
for (i = 0; i < size; i++){
var feat = layerJSONString.features[i];
var geom = feat.geometry;
var type = geom.type;
if(type == "Polygon")
{
var poly = new ol.geom.Polygon(geom.coordinates);
var extent = poly.getExtent();
var coord = [];
coord[0] = (extent[2]-extent[0])/2 + extent[0];
coord[1] = (extent[3]-extent[1])/2 + extent[1];
var point = new ol.geom.Point(coord);
newFeatures[j++] = new ol.Feature({
geometry : point,
StyleName : feat.properties.StyleName
});
}
}
avlVectorSource.addFeatures(myVectorSource.readFeatures(response));
avlVectorSource.addFeatures(newFeatures);
},
error: myLoadError
});
}
};
The documentation says that ol.geom.Polygon has a method called getInteriorPoint(). It has but I can get it to work. So I calculate the center point of the extent of the polygon.
I use "StyleName" to set the right icon in my style function.

Resources