I want to calculate and output the area of a year, but I keep showing the date - date

enter code here
function processS2Collection(year,month, region) {
var startDate = ee.Date.fromYMD(year, month, 1);
var endDate = ee.Date.fromYMD(year, month+1, 1);
var collection = ee.ImageCollection("COPERNICUS/S2")
.filterDate('startDate, endDate')
.filterBounds(roi)
.filter(ee.Filter.lt('CLOUDY_PIXEL_PERCENTAGE', 80))
//.map(scaleS2Image)
.map(maskS2clouds)
.map(removeShadow)
.map(addSnowIce)
.map(addS2VIs)
.median() ;
var MNDWI_S2=collection.select('mNDWI');
var histogram = MNDWI_S2.reduceRegion({
reducer: ee.Reducer.histogram(),
geometry: roi,
scale: 30,
maxPixels: 1e13,
tileScale: 8
});
var threshold_S2 = otsu(histogram.get("mNDWI"));
var threshold = ee.Number(threshold_S2);
var mask = MNDWI_S2.gte(threshold);
print(threshold,'threshold')
var water_S2 = mask.updateMask(mask).rename("water");
var waterarea_S2_based=ee.Number((((water_S2.multiply(0.000001).multiply(ee.Image.pixelArea()))
.reduceRegion({
reducer: ee.Reducer.sum(),
geometry: roi,
scale: 30,
maxPixels: 1e13,})).get('water')))
Map.addLayer(water_S2.clip(table),{min:0,max:1,palette:['#DDDDDD','#FF3300']},'water_S2_otsu_based');
print('waterarea_S2_based',waterarea_S2_based)
}
for (var i=1; i<=11; i++) {
var month=i;
processS2Collection(2017,month, roi);
}
//I want to calculate and output the area of a year, but I keep showing the date
//Source code link:https://code.earthengine.google.com/51a90e5845e6732d0f241fa4fda64c8a
Anyone has a solution?

Related

Error in Google Earth Engine: Computed value is too large

I'm trying to achieve classification for image collection over 30 years as the code shows below:
var roi = ee.FeatureCollection("users/471033961/YellowRiver");
var empty = ee.Image().toByte();
var outline = empty.paint({
featureCollection:roi,
color:0,
width:3
});
Map.addLayer(outline, {palette: "ff0000"}, "outline");
//////////////////////////////landsat 5,7
function l57class(year){
var startDate = ee.Date.fromYMD(year, 1, 1);
var endDate = ee.Date.fromYMD(year+1, 1, 1);
var LC57_BANDS = ['B1', 'B2', 'B3', 'B4', 'B5', 'B7']; //Landsat57
var STD_NAMES = ['B2', 'B3', 'B4', 'B5', 'B6', 'B7'];
var cloudMaskL457 = function(image) {
var qa = image.select('pixel_qa');
// If the cloud bit (5) is set and the cloud confidence (7) is high
// or the cloud shadow bit is set (3), then it's a bad pixel.
var cloud = qa.bitwiseAnd(1 << 5)
.and(qa.bitwiseAnd(1 << 7))
.or(qa.bitwiseAnd(1 << 3));
// Remove edge pixels that don't occur in all bands
var mask2 = image.mask().reduce(ee.Reducer.min());
return image.updateMask(cloud.not()).updateMask(mask2);
}
var collection1 = ee.ImageCollection("LANDSAT/LE07/C01/T1_SR")
.filterDate(startDate, endDate)
.filterBounds(roi)
.filter(ee.Filter.lte('CLOUD_COVER',10))
.map(cloudMaskL457)
var collection2 = ee.ImageCollection("LANDSAT/LT05/C01/T1_SR")
.filterDate(startDate, endDate)
.filterBounds(roi)
.filter(ee.Filter.lte('CLOUD_COVER',10))
.map(cloudMaskL457)
var collection = collection1.merge(collection2).select(LC57_BANDS, STD_NAMES)
var image=collection.mosaic().clip(roi)
function NDWI(img){
var nir = img.select('B4');
var green = img.select('B2');
var ndwi = img.expression(
'(B3-B5)/(B3+B5)',
{
'B5':nir,
'B3':green
});
return ndwi;
}
function EWI(img){
var swir1 = img.select('B6')
var nir = img.select('B5');
var green = img.select('B3');
var ewi = img.expression(
'(B3-B5-B6)/(B3+B5+B6)',
{
'B6':swir1,
'B5':nir,
'B3':green
});
return ewi;
}
var MNDWI = image.normalizedDifference(['B3', 'B6']).rename('MNDWI');
var ndbi = image.normalizedDifference(['B6', 'B5']).rename('NDBI');
var ndvi = image.normalizedDifference(['B5', 'B4']).rename('NDVI');
var ewi = EWI(image).rename('EWI');
var ndwi = NDWI(image).rename('NDWI');
var lswi = image.normalizedDifference(['B5','B6']).rename('LSWI')
var nbr2 = image.normalizedDifference(["B6", "B7"]).rename("NBR2")
var awei = image.expression(
'4*(green-SWIR1)-(0.25*NIR+2.75*SWIR2)',{
green:image.select('B3'),
NIR:image.select('B5'),
SWIR1:image.select('B6'),
SWIR2:image.select('B7'),
}).float().rename('AWEI')
image=image
.addBands(ndvi)
.addBands(ndbi)
.addBands(MNDWI)
.addBands(ndwi)
.addBands(ewi)
.addBands(lswi)
.addBands(awei)
.addBands(nbr2)
var classNames = city.merge(water).merge(tree).merge(crop).merge(bare);
var bands = ['B2', 'B3', 'B4', 'B5', 'B6', 'B7','MNDWI','NDBI','NDVI','EWI','NDWI','AWEI','LSWI',"NBR2"];
var training = image.select(bands).sampleRegions({
collection: classNames,
properties: ['landcover'],
scale: 30
});
var withRandom = training.randomColumn('random');
var split = 0.8;
var trainingPartition = withRandom.filter(ee.Filter.lt('random', split));
var testingPartition = withRandom.filter(ee.Filter.gte('random', split));
var classProperty = 'landcover';
var classifier = ee.Classifier.smileRandomForest(100).train({
features: trainingPartition,
classProperty: 'landcover',
inputProperties: bands
});
var classified = image.select(bands).classify(classifier);
var test = testingPartition.classify(classifier);
var confusionMatrix = test.errorMatrix('landcover', 'classification');
print(year)
print('confusionMatrix',confusionMatrix);
print('overall accuracy', confusionMatrix.accuracy());
print('kappa accuracy', confusionMatrix.kappa());
Map.addLayer(classified,{}, "classified"+year);
Export.image.toDrive({
image: classified,
description: 'YR_cart'+year,
folder: 'YR_cart'+year,
scale: 30,
region: roi,
maxPixels:34e10
});
}
////////////////////////////////////////////////////////////////////////////////
function l8class(year){
var startDate = ee.Date.fromYMD(year, 1, 1);
var endDate = ee.Date.fromYMD(year+1, 1, 1);
var collection = ee.ImageCollection("LANDSAT/LC08/C01/T1_RT")
.filterDate(startDate, endDate)
.filterBounds(roi)
.filter(ee.Filter.lte('CLOUD_COVER',20))
var remove_cloud=function(collection)
{
var fun_calCloudScore = function(image) {
return ee.Algorithms.Landsat.simpleCloudScore(ee.Image(image));
};
var calCloudScore = ee.ImageCollection(collection)
.map(fun_calCloudScore)
;
var fun_maskCloud = function(image) {
var mask = image.select(['cloud']).lte(10);
return image.updateMask(mask);
};
var vsParam={band:['B2', 'B3', 'B4', 'B5', 'B6', 'B7'],min:0,max:0.3};
var maskCloud = ee.ImageCollection(calCloudScore)
.map(fun_maskCloud) ;
var maskCloud2=maskCloud.mean()
return maskCloud;
}
var image=remove_cloud(collection).mosaic().clip(roi);
function NDWI(img){
var nir = img.select('B4');
var green = img.select('B2');
var ndwi = img.expression(
'(B3-B5)/(B3+B5)',
{
'B5':nir,
'B3':green
});
return ndwi;
}
function EWI(img){
var swir1 = img.select('B6')
var nir = img.select('B5');
var green = img.select('B3');
var ewi = img.expression(
'(B3-B5-B6)/(B3+B5+B6)',
{
'B6':swir1,
'B5':nir,
'B3':green
});
return ewi;
}
var MNDWI = image.normalizedDifference(['B3', 'B6']).rename('MNDWI');
var ndbi = image.normalizedDifference(['B6', 'B5']).rename('NDBI');
var ndvi = image.normalizedDifference(['B5', 'B4']).rename('NDVI');
var ewi = EWI(image).rename('EWI');
var ndwi = NDWI(image).rename('NDWI');
var lswi = image.normalizedDifference(['B5','B6']).rename('LSWI')
var nbr2 = image.normalizedDifference(["B6", "B7"]).rename("NBR2")
var awei = image.expression(
'4*(green-SWIR1)-(0.25*NIR+2.75*SWIR2)',{
green:image.select('B3'),
NIR:image.select('B5'),
SWIR1:image.select('B6'),
SWIR2:image.select('B7'),
}).float().rename('AWEI')
image=image
.addBands(ndvi)
.addBands(ndbi)
.addBands(MNDWI)
.addBands(ndwi)
.addBands(ewi)
.addBands(lswi)
.addBands(awei)
.addBands(nbr2)
var classNames = city.merge(water).merge(tree).merge(crop).merge(bare);
var bands = ['B2', 'B3', 'B4', 'B5', 'B6', 'B7','MNDWI','NDBI','NDVI','EWI','NDWI','AWEI','LSWI',"NBR2"];
var training = image.select(bands).sampleRegions({
collection: classNames,
properties: ['landcover'],
scale: 30
});
var withRandom = training.randomColumn('random');
var split = 0.9;
var trainingPartition = withRandom.filter(ee.Filter.lt('random', split));
var testingPartition = withRandom.filter(ee.Filter.gte('random', split));
var classProperty = 'landcover';
var classifier = ee.Classifier.libsvm().train({
features: trainingPartition,
classProperty: 'landcover',
inputProperties: bands
});
var classified = image.select(bands).classify(classifier);
var test = testingPartition.classify(classifier);
var confusionMatrix = test.errorMatrix('landcover', 'classification');
print(year)
print('confusionMatrix',confusionMatrix);
print('overall accuracy', confusionMatrix.accuracy());
print('kappa accuracy', confusionMatrix.kappa());
Map.addLayer(classified,{}, "classified"+year);
Export.image.toDrive({
image: classified,
description: 'YR_cart'+year,
folder: 'YR_cart'+year,
scale: 30,
region: roi,
maxPixels:34e10
});
}
function main() {
var startYear = 2022;
var endYear = 2022;
for (var year=startYear; year<=endYear; year++) {
if (year >2012){l8class(year)}else{l57class(year)}
}
}
main();
I knew the study area was too big which lead to an error: "computed value is too large". Does anyone know how to solve this problem? better to revise based on this code if so.
Really appreciate it in advance!
To be honest I checked too many ideas but one of the effective ways I thought is to "break your study area into a bunch of tiles to calculate first, then combine all the results to get the final. However, It's just initial thinking that I didn't test.
Here is the link(you can ignore the comment in Chinese): https://code.earthengine.google.com/5d362229b959d96b9e4017571ba11a75

Creating calendar syncronised to spreadsheet but all events are created onn 1 Jan 1970 at 03:00. What did I miss?

I am following the conversation and tutorial in post Create Google Calendar Events from Spreadsheet but prevent duplicates
But I cannot get the final solution to work. It fills my calendar but all dates are 1/1/1970 at 3 am.
The code is as follows:
function onOpen() {
var sheet = SpreadsheetApp.getActiveSpreadsheet();
var entries = [{
name: "Export Events",
functionName: "exportEvents"
}];
sheet.addMenu("Calendar Actions", entries);
};
function parseDate(s) {
var months = {
jan: 0, feb: 1, mar: 2, apr: 3, may: 4, jun: 5, jul: 6, aug: 7, sep: 8, oct: 9, nov: 10, dec: 11
};
var p = s.replace(".", "").split('-');
return new Date(p[2], p[1], p[0]);
}
/**
* Export events from spreadsheet to calendar
*/
function exportEvents() {
var sheet = SpreadsheetApp.getActiveSheet();
var headerRows = 1; // Number of rows of header info (to skip)
var range = sheet.getDataRange();
var data = range.getDisplayValues();
var calId = "the calendar"; // PRODUCTION
//var calId = "the calendar; // TEST
var cal = CalendarApp.getCalendarById(calId);
//Logger.log(cal);
//Logger.log(data.length);
for (i = 0; i<data.length; i++) {
if (i<headerRows) continue; // Skip header row(s)
if (data[i][0].length<1) continue; // Skip if no content.
var row = data[i];
Logger.log(row);
var date = parseDate(row[0]); // First column
//Logger.log(date);
var title = row[1]; // Second column
var tstart = new Date();
var s = row[2].split(":");
tstart.setHours(s[0]);
tstart.setMinutes(s[1]);
tstart.setSeconds(s[2]);
tstart.setDate(date.getDate());
tstart.setMonth(date.getMonth());
tstart.setYear(date.getYear());
var tstop = new Date();
var e = row[3].split(":");
tstop.setHours(e[0]);
tstop.setMinutes(e[1]);
tstop.setSeconds(e[2]);
tstop.setDate(date.getDate());
tstop.setMonth(date.getMonth());
tstop.setYear(date.getYear());
var loc = row[4];
var desc = row[5];
var id = row[6]; // Sixth column == eventId
// Check if event already exists, update it if it does
var event = null;
if (id.length > 0) {
try {
event = cal.getEventSeriesById(id);
} catch (e) {
// do nothing - we just want to avoid the exception when event doesn't exist
}
}
if (!event) {
//cal.createEvent(title, new Date("March 3, 2010 08:00:00"), new Date("March 3, 2010 09:00:00"), {description:desc,location:loc});
var newEvent = cal.createEvent(title, tstart, tstop, {
description: desc, location: loc
}).getId();
var r = i + 1;
var cell = sheet.getRange("G" + r);
cell.setValue(newEvent);
} else {
Logger.log(event);
event.setTitle(title);
event.setDescription(desc);
event.setLocation(loc);
// event.setTime(tstart, tstop); // cannot setTime on eventSeries.
// ... but we CAN set recurrence!
var recurrence = CalendarApp.newRecurrence().addDailyRule().times(1);
event.setRecurrence(recurrence, tstart, tstop);
}
debugger;
}
}
I think I must be making an obvious rookie mistake but cannot figure it out. Any chance of some help?
BTW: my dates are formatted: 12/01/2019 and times formatted: 18:00:00.

How do you properly configure an event listener/handler for a CategoryFilter control?

I am trying to plot the following sample data using a LineChart with a CategoryFilter to filter on year.
Data table is defined as:
aggData: [Date: date][Team: string][Score: number]
From the aggData table I dynamically calculate the default hAxis ticks as
var hAxisTicks = [];
var dateRange = aggData.getColumnRange(0);
for (var date = dateRange.min; date <= dateRange.max; date = new Date(date.getFullYear(), date.getMonth() + 1)) {
hAxisTicks.push(date);
}
The year picker and the line chart are configured as:
var yearPicker = new google.visualization.ControlWrapper({
controlType: 'CategoryFilter',
containerId: 'categoryFilter_div',
options: {
filterColumnIndex: 0,
ui: {
allowTyping: false,
allowMultiple: false,
label: 'Year:',
labelStacking: 'vertical'
},
useFormattedValue: true
}
});
var lineChart = new google.visualization.ChartWrapper({
chartType: 'LineChart',
containerId: 'chart_div',
options: {
width: 900,
height: 500,
hAxis: {
format: 'MMM', ticks: hAxisTicks
}
}
});
I added the following event listener
google.visualization.events.addListener(yearPicker, 'statechange', function () {
google.visualization.events.addOneTimeListener(lineChart, 'ready', getTicks);
});
I need to create/recreate the hAxis ticks everytime the yearPicker changes by calling getTicks
function getTicks() {
var ticks = [];
if (yearPicker.getState().selectedValues.length > 0) {
for (var i = 0; i <= hAxisTicks.length; i = i + 1) {
var date = new Date(hAxisTicks[i]);
if (date.getFullYear() == yearPicker.getState().selectedValues[0]) {
ticks.push(date)
}
}
}
else {
for (var i = 0; i <= hAxisTicks.length; i = i + 1) {
var date = new Date(hAxisTicks[i]);
ticks.push(date);
}
lineChart.setOption('hAxis.ticks', ticks);
lineChart.draw();
}
lineChart.setOption('hAxis.ticks', ticks);
lineChart.draw();
}
Here's what happens at different stages
1- When page first loads the graph looks like (the getTicks function is NOT called) which is correct:
2- When the year is changed to 2019, for example, the hAxis ticks get recalculated (the getTicks function is does get called) and the graph appears to be correct
3- Attempting to go back to the default chart to display all years, an a.getTime is not a function error message appears under the CategoryFilter
4- Any subsequent attempts to change the CategoryFilter to any value throws a ```One or more participants failed to draw()
How can I rectify this behavior?
I realized my iteration over the hAxisTics array was incorrect. I should stop at < hAxisTics.length instead of <= hAxisTics.length and I should recalculate inside the event handler
google.visualization.events.addListener(yearPicker, 'statechange', function () {
var ticks = [];
if (yearPicker.getState().selectedValues.length > 0) {
for (var i = 0; i < hAxisTicks.length; i = i + 1) {
var date = new Date(hAxisTicks[i]);
if (date.getFullYear() == yearPicker.getState().selectedValues[0]) {
ticks.push(date)
}
}
}
else {
for (var i = 0; i < hAxisTicks.length; i = i + 1) {
var date = new Date(hAxisTicks[i]);
ticks.push(date);
}
lineChart.setOption('hAxis.ticks', ticks);
lineChart.draw();
}
lineChart.setOption('hAxis.ticks', ticks);
lineChart.draw();
});

Script for Date Stamping on Multiple Sheets

I am very very very new to all this. I need help, I am trying to use script editor to get the date statically stamped in one column when something is entered in a different column. I figured how to do this for one tab but I need this to happen on multiple tabs in the same sheet and I'm struggling to get it to work. Is there one code that will work for this? This is the script I was using for one tab:
/**
* Creates a Date Stamp if a column is edited.
*/
//CORE VARIABLES
// The column you want to check if something is entered.
var COLUMNTOCHECK = 9;
// Where you want the date time stamp offset from the input location. [row, column]
var DATETIMELOCATION = [0,-8];
// Sheet you are working on
var SHEETNAME = 'Sheet 2'
function onEdit(e) {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getActiveSheet();
//checks that we're on the correct sheet.
if( sheet.getSheetName() == SHEETNAME ) {
var selectedCell = ss.getActiveCell();
//checks the column to ensure it is on the one we want to cause the date to appear.
if( selectedCell.getColumn() == COLUMNTOCHECK) {
var dateTimeCell = selectedCell.offset(DATETIMELOCATION[0],DATETIMELOCATION[1]);
dateTimeCell.setValue(new Date());
}
}
}
Thank you for your time in advance.
To proceed with the function on multiple sheets, you can check for the sheet name in an array of acceptable names.
function onEdit() {
var colToCheck = 9;
// Offset from the input [row, column]
var dateOffset = [0, -8];
// Sheets to proceed on
var sheetNames = ['Sheet 2', 'Sheet 3'];
var sheet = SpreadsheetApp.getActive().getActiveSheet();
var name = sheet.getName();
if (sheetNames.indexOf(name) > -1) {
var cell = sheet.getActiveCell();
var col = cell.getColumn();
if (col == colToCheck) {
var dateTimeCell = cell.offset(dateOffset[0], dateOffset[1]);
dateTimeCell.setValue(new Date());
}
}
}
References
Arrays
indexOf()
EDIT ONE
If you want multiple options, you could set them up in arrays. The order of the elements in the arrays must match.
This code assumes that the timestamp is always on the same row.
function onEdit() {
var sheetNames = ['Sheet 2', 'Sheet 3'];
var colsToCheck = [9, 15];
var colOffsets = [-8, -4];
var sheet = SpreadsheetApp.getActive().getActiveSheet();
var name = sheet.getSheetName();
var index = sheetNames.indexOf(name);
if (index > -1) {
var cell = sheet.getActiveCell();
var col = cell.getColumn();
if (col == colsToCheck[index]) {
var dateTimeCell = cell.offset(0, colOffsets[index]);
dateTimeCell.setValue(new Date());
}
}
}
EDIT TWO
For those of you who would prefer objects
function onEdit() {
var sheets = {
'Sheet 2': {
checkCol: 9,
offset: -8
},
'Sheet 3': {
checkCol: 15,
offset: -4
}
};
var sheet = SpreadsheetApp.getActive().getActiveSheet();
var name = sheet.getSheetName();
var settings = sheets[name];
if (settings) {
var cell = sheet.getActiveCell();
var col = cell.getColumn();
if (col == settings.checkCol) {
var dateTimeCell = cell.offset(0, settings.offset);
dateTimeCell.setValue(new Date());
}
}
}

How to automatically delete rows that contain a date with more than 3 days offset to the past from now?

I am trying to get a script going that will automatically delete rows with a date over 3 days old (4 days on)
I found this script that I was hoping to be able to adapt:
function DeleteOldEntries() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
//give your sheet name below instead of Sheet1
var sheet = ss.getSheetByName("Foglio1");
var datarange = sheet.getDataRange();
var lastrow = datarange.getLastRow();
var currentDate = new Date();
var oneweekago = new Date();
oneweekago.setDate(currentDate.getDate() - 7);
for (i = lastrow; i >= 2; i--) {
var tempdate = sheet.getRange(i, 1).getValue();
if (tempdate < oneweekago) {
sheet.deleteRow(i);
}
}
}
But there seems to be an error in the script itself that I need to figure out before adapting it to 4 days instead of 7 (that part is easy)
My sheet has 3 columns with the date in column C if that info is helpful
"date in column C, if that info is helpful"
It is indeed ! instead of trying to get a date in column A as it it done in this line :
var tempdate = sheet.getRange(i, 1).getValue();
you should look at the value in column C like this :
var tempdate = sheet.getRange(i, 3).getValue();
but to be more efficient you should do these comparisons at array level, try it like below and it will run much faster ...
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName("Foglio1");
var datarange = sheet.getDataRange();
var lastrow = datarange.getLastRow();
var values = datarange.getValues();// get all data in a 2D array
var currentDate = new Date();
var oneweekago = new Date();
oneweekago.setDate(currentDate.getDate() - 7);
for (i=lastrow;i>=2;i--) {
var tempdate = values[i-1][2];// arrays are 0 indexed so row1 = values[0] and col3 = [2]
if(tempdate < oneweekago)
{
sheet.deleteRow(i);
}
}
}
It will be much much faster if your rows are in order of date, newest at the top and you delete all the rows at once and not one at a time.
function deleteOldData() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName("CallHub1");
var datarange = sheet.getDataRange();
var lastrow = datarange.getLastRow();
var values = datarange.getValues();// get all data in a 2D array
var currentDate = new Date();
var daysago = new Date().setDate(currentDate.getDate() - 3);
var yearago = new Date().setDate(currentDate.getDate() - 365);
for (i=lastrow;i>=2;i--) {
var tempdate = values[i-1][0];// arrays are 0 indexed so row1 = values[0] and col3 = [2]
if(tempdate < daysago) {
if(tempdate < yearago) {continue;}
sheet.deleteRows(1, i);
break;
}
}
}