How to mask out shadows from LANDSAT/LE07/C01/T1_TOA? - shadow

I want to use the LANDSAT/LE07/C01/T1_TOA collection in google earth engine and I am struggling to understand how the bits work in order to mask out areas with clouds and shadows. I managed to write the following, but I am not very confident and do not know how to mask out shadows.
var dataset = ee.ImageCollection('LANDSAT/LE07/C01/T1_TOA')
.filterBounds(geometry)
.map(function(image){return image.clip(geometry)})
.filter(ee.Filter.calendarRange(6,8,'month'))
.filterDate('1999-05-01','2017-09-30');
var qas = function(image) {
var qa = image.select('BQA');
var mask = qa.eq(672);
return image.updateMask(mask).copyProperties(image);
}
var merged = dataset.map(qas);
var addNDVI = function(image) {
var ndvi = image.normalizedDifference(['B4', 'B3']).rename('NDVI');
return image.addBands(ndvi);
};
var ndvi = merged.map(addNDVI);
How to properly do quality masking with bits?

Try It
var cloudMaskL7 = function(image) {
var qa = image.select('BQA');
var cloud = qa.bitwiseAnd(1 << 4)
.and(qa.bitwiseAnd(1 << 6))
.or(qa.bitwiseAnd(1 << 8));
var mask2 = image.mask().reduce(ee.Reducer.min());
return image
.select(['B3', 'B4'], ['Red', 'NIR'])
.updateMask(cloud.not()).updateMask(mask2)
.set('system:time_start', image.get('system:time_start'));
};
var dataset = ee.ImageCollection("LANDSAT/LE07/C01/T1_TOA")
.filterBounds(geometry)
.filterDate('2012-05-01','2017-09-30')
.map(cloudMaskL7)
var NDVIofLANDSAT = function(image) {
var ndvi = image.normalizedDifference(['NIR', 'Red']).rename('NDVI');
return image.addBands(ndvi);
};
var ndviCollection = dataset
.map(NDVIofLANDSAT)
.select("NDVI");
print("Total no of LANDSAT Images ", ndviCollection);
Map.addLayer (ndviCollection.first().select('NDVI').clip(geometry), {min:0, max:1, 'palette': ['red','yellow', 'green']}, 'NDVI')

Related

Replace Text with Images in Google Slides for 200 slides?

I would like to replace some text box text in Google slides with corresponding images. I have tried to following method: How to replace Text with Image on Google Slide using Google Script
It only works on small amounts of data, but I have over 500 object to loop through. I cannot use the Slides API only apps script.
Are there any efficient ways to go about it?
Here is my code so far:
function addFruits() {
//adding search texts
var apple = "Apple";
var orange = "Orange";
var cherry = "Cherry";
var bamboo = "Bamboo";
//addding file ids
var appleID = 'XXXXXXX';
var orangeID = 'XXXXXXXXXXX';
var cherryID = 'XXXXXXXXX';
var bambooID = 'XXXXXXXXXX';
//getting images
var appleIMG = DriveApp.getFileById(appleID).getBlob();
var orangeIMG = DriveApp.getFileById(orangeID).getBlob();
var cherryIMG = DriveApp.getFileById(cherryID).getBlob();
var bambooIMG = DriveApp.getFileById(bambooID).getBlob();
//Logger.log(appleIMG)
//Logger.log(orangeIMG)
//Logger.log(cherryIMG)
//Logger.log(bambooIMG)
// retreive all slides.
var presentation = SlidesApp.openById(slideID);
var slides = presentation.getSlides();
//Logger.log(slides)
//get all shapes and reduce them to a 1d array
var shapesArrays = [];
slides.forEach(slide => {
let shape = slide.getShapes();
shapesArrays.push(shape)
})
var shapes = [].concat.apply([], shapesArrays);
//Logger.log(shapes)
shapes.forEach(s => {
if (s.getText().asString().includes(apple)) {
s.replaceWithImage(appleIMG);
}
else if (s.getText().asString().includes(orange)) {
s.replaceWithImage(orangeIMG);
}
else if (s.getText().asString().includes(cherry)) {
s.replaceWithImage(cherryIMG);
}
else if (s.getText().asString().includes(bamboo)) {
s.replaceWithImage(bambooIMG);
}
});
}
Try this:
function addFruits() {
const ids = [{ id: "id1", name: "name1",{ id: "id2", name: "name2" }];
var presentation = SlidesApp.openById(slideID);
var slides = presentation.getSlides();
slides.forEach(slide => {
let shapes = slide.getShapes();
shapes.forEach(shape => {
let text = shape.getText().asString();
ids.forEach(e => {
if (text.includes(id.name)) {
shape.replaceWithImage(DriveApp.getFileById(e.id).getBlob());
}
});
});
});
}
You can limit the number of slides you attempt by limiting the size of ids

Read binary file with extendscript

Limited to using Extendscript in Photoshop I'm trying to write and then read in the same binary file.
I can write the file okay, but I'm not sure where I'm going wrong with the read part.
The data will be RGB colours in hex, so I'll either want to return the data from the read function as array or a string. Only I can't even get it to tell me the file just written exists. And I'm not sure if I should be using seek() or read(). Confused.
var f = new File("D:\\temp\\bin.act");
var w = write_binary(f);
var r = read_binary(w);
alert(r);
function write_binary(afile)
{
afile.encoding = "BINARY";
afile.open ("w");
for(i = 0; i < 256; i++)
{
afile.write(String.fromCharCode (i));
}
afile.close();
}
function read_binary(afile)
{
var f = new File(afile);
f.open("r");
f.encoding = "BINARY";
//var data = f.read();
//if(f.exists) alert(afile);
//alert (data);
var arr = [];
for (var i = 0; i < f.length; i+=4)
{
f.seek(i, 0);
var hex = f.readch().charCodeAt(0).toString(16);
if(hex.length === 1) hex = "0" + hex;
arr.push(hex);
}
return arr;
}
You can read it like this:
// Open binary file
var afile = "/Users/mark/StackOverflow/data.bin"
var f = new File(afile);
f.open("r");
f.encoding = "BINARY";
alert('OK');
var hexstring=""
while (true){
var b = f.readch().charCodeAt(0);
if(f.eof){break;}
var hex = b.toString(16);
if(hex.length === 1) hex = "0" + hex;
hexstring += hex;
}
alert(hexstring);
The corresponding writing part of this answer is here.

Is a unicode code point can be displayed normally?

I want to know whether a unicode code point can be displayed in chrome, and check it in golang, so I can escape some parts of a string before i send it to chrome.
I have found that there is three types of unicode code point can not be displayed normally in chrome :
Space . like code point 0x20(32). ' '
Font not exist. There is a question mark in the square box. (occupy two English letters width) like code point 0x378(888) "͸"
Invaild code point value. A diamond-shaped black box with a question mark inside (occupy one English letter width) like code point 0xd800(55296) "�"
I found that I can use js and OffscreenCanvas to render all of the unicode code point and check if them looks like above three types.
Then I got a function that can tell you whether a rune/character can be displayed normally by the operating system. https://github.com/fastslothlab/fslRune
js code:
(function(){
var start = 0;
var end = 1114111;
const imageSize = 20;
var tufoCiList = [32,888,55296];
var num = end-start+1;
var startTime = performance.now()
var hasDataCiList = [];
var c = new OffscreenCanvas(imageSize,imageSize);
var ctx = c.getContext("2d");
function getImageDataByCi(ci){
var s = String.fromCodePoint(ci);
ctx.clearRect(0,0,imageSize,imageSize);
ctx.fillText(s, 5, 15);
var imgD = ctx.getImageData(0,0,imageSize,imageSize);
var hasNoneZero = false;
var buf = imgD.data;
return buf;
}
var tofuBufList = [];
for (var i in tufoCiList){
tofuBufList.push(getImageDataByCi(tufoCiList[i]));
}
function debugImage(){
c.convertToBlob({
type: "image/png",
}).then(function(blob) {
var url = URL.createObjectURL(blob);
var imgObj = document.createElement("img");
imgObj.src = url;
document.body.appendChild(imgObj);
console.log(url);
});
}
function bufEqual(buf1, buf2){
if (buf1.byteLength != buf2.byteLength) return false;
for (var i = 0 ; i != buf1.byteLength ; i++){
if (buf1[i] != buf2[i]) return false;
}
return true;
}
for (var ci =start;ci<=end;ci++){
var buf = getImageDataByCi(ci);
var hasFound = false;
for (var i in tofuBufList){
if (bufEqual(buf,tofuBufList[i])){
hasFound = true;
break;
}
}
if (hasFound){
continue;
}
hasDataCiList.push(ci);
}
console.log((performance.now()-startTime)/num);
console.log(JSON.stringify(hasDataCiList));
})();

mapserver with WMS call with openlayers

I scenario is below :
map is shown under from TiledWMS layer from mapserver. It has 2 layers.
TiledWMS layer for OSM world map.
TiledWMS layer for layers defined in kml file placed in mapserver through .map file. This map file contains many layers.
Now , when user click on map : it got 2 layers as above.
But since 2nd layer is made up of different layers as given in .map file , i am not able to uniquely identify these layers. I want that since 2 nd layer is made up of different layers in kml file i should be able to uniquely identify them on mouse click or hower.
Thanks
Satpal
I am able to get it : below is samaple code for others.
var coord = evt.coordinate;
var pixel = $scope.map.getPixelFromCoordinate(coord);
var viewProjection = $scope.map.getView().getProjection();
var viewResolution = $scope.map.getView().getResolution();
var numberOfLayersOnMap = $scope.map.getLayers();
var feature = $scope.map.forEachFeatureAtPixel(pixel, function(feature, layer){return feature;}, null, function(layer) {return true;});
if(feature === undefined)
{
$scope.map.forEachLayerAtPixel(pixel, function (layer)
{
if(!layer)
{
return ;
}
var urlWMSGetFeatureInfo = layer.getSource().getGetFeatureInfoUrl(coord, viewResolution, viewProjection, {
'INFO_FORMAT': 'application/vnd.ogc.gml'
});
if(urlWMSGetFeatureInfo.indexOf("osm-google.map")<0)
{
$http({
method: 'GET',
url: urlWMSGetFeatureInfo,
}).success(function(data){
var parser = new ol.format.WMSGetFeatureInfo();
var features = parser.readFeatures(data);
if(features.length>0)
{
var featureName = features[0].n.Name;
topOverlayElement.innerHTML = featureName;
$scope.highlightOverlay.setFeatures(new ol.Collection());
if($scope.flagLinkage == true)
{
var xmlObj = utility.StringToXML(data);
var xmlDocumnet = xmlObj.childNodes[0];
var layerNode = xmlDocumnet.children[0];
var gmlLayerNode = layerNode.children[0];
var layerName = gmlLayerNode.textContent;
var layerInfoObject = {};
layerInfoObject.layerName = layerName;
//layerInfoObject.placemarkName = featureName;
$scope.placemarksSelectedObject.push(layerInfoObject);
$scope.placemarksSelectedFeatureObject.push(features[0]);
}
else
{
$scope.placemarksSelectedFeatureObject.length = 0;
$scope.placemarksSelectedFeatureObject.push(features[0]);
}
$scope.highlightOverlay.setFeatures(new ol.Collection($scope.placemarksSelectedFeatureObject));
var featureDescription = features[0].n.description;
middleOverlayElement.innerHTML = (featureDescription === undefined) ? '' : featureDescription;
$scope.showOverlay(coord);
}
}).error(function (data) {
console.log("Not able to get capabilty data.");
});
}
else
{
$scope.closeOverlay(evt);
}
});

GAS - Sort a flexTable by column

I understand that cellTable in GWT performs this (Sort FlexTable Inquiry) and I was wondering if anyone knew a way to emulate some of the column sorting behaviour using a flexTable in UiApp.
In my case it is only necessary for the app to sort the column once at creation, not have it sortable by the user on click. I have included my flexTable creation code below:
var flexTable = app.createFlexTable()
.setStyleAttribute('marginTop', '10px')
.setCellPadding(5)
.setCellSpacing(2);
for(var i = 0;i<(size-1);i++){
var class = "class" + (i+1);
var classCode = classObjectsIndex[loggedInUser][class];
var text10 = statusObjectsIndex[classCode].classname;
var text11 = statusObjectsIndex[classCode].homeworkstatus;
var text12 = statusObjectsIndex[classCode].classcalendarlink;
var anchor = app.createAnchor('Calendar', text12)
.setTarget('_blank');
var calPanel = app.createAbsolutePanel()
.add(anchor);
flexTable.setText(i, 0, text10);
flexTable.setText(i, 1, text11);
flexTable.setWidget(i, 2, calPanel);
if(text11 == "No homework set for this class"){
flexTable.setRowStyleAttribute(i, "backgroundColor", "#96bcfd")
flexTable.setRowStyleAttribute(i, "color", "#000000");
}else{
flexTable.setRowStyleAttribute(i, "backgroundColor", "#eca8a3");
flexTable.setRowStyleAttribute(i, "color", "#FFFFFF");
};
}
app.add(flexTable);
Due to the way in which the table is populated sorting the array the values are pulled from will not help.
This the first question I have posted here, please be gentle. If I could ask it in a better way, I have overlooked an obvious resource to get my answer or if there is more information I need to provide please let me know!
EDIT//////////////////////////////////
I was having trouble sorting using the code provided, very helpfully, by Serge and so I approached it slightly differently and created individual objects for each row of data. The advice given by both Serge and Zig helped me end up with this working solution, many thanks!
//create flexTable
var flexTable = app.createFlexTable();
flexTable.setStyleAttribute('marginTop', '10px')
flexTable.setCellPadding(5);
flexTable.setCellSpacing(2);
//create empty table array to store rowObjects
var tableArray =[];
//create rowObjects
for(var i = 0; i<(size-1); i++){
var rowObject = {};
var class = 'class' + (i+1);
var classCode = classObjectsIndex[loggedInUser][class];
rowObject.className = statusObjectsIndex[classCode].classname;
rowObject.homeworkStatus = statusObjectsIndex[classCode].homeworkstatus;
rowObject.link = app.createAbsolutePanel().add(app.createAnchor('Calendar',statusObjectsIndex[classCode].classcalendarlink));
if(statusObjectsIndex[classCode].homeworkstatus == "No homework set for this class"){
rowObject.BGColor = "#96bcfd";
rowObject.color = "#000000";
}else{
rowObject.BGColor = "#eca8a3";
rowObject.color = "#FFFFFF";
}
tableArray.push(rowObject);
}
//sort objects in array by homework status
tableArray.sort(function (a, b) {
if (a.homeworkStatus > b.homeworkStatus)
return 1;
if (a.homeworkStatus < b.homeworkStatus)
return -1;
return 0;
});
//populate flextable
for(var i = 0;i<(size-1);i++){
flexTable.setText(i,0, tableArray[i].className);
flexTable.setText(i,1, tableArray[i].homeworkStatus);
flexTable.setWidget(i,2, tableArray[i].link);
flexTable.setRowStyleAttribute(i, 'color', tableArray[i].color);
flexTable.setRowStyleAttribute(i, 'backgroundColor', tableArray[i].BGColor);
};
app.add(flexTable);
Theres nothing that prevents you from sorting the source array first. Just store each 5 columns (3 data columns plus background/foreground colors) as rows in another array and sort that other array. After sort populate the table.
I fully agre with Zig on this, here is an example of such an implementation to help you figure out how to approach it. (code not tested but should be right)
var flexTable = app.createFlexTable()
.setStyleAttribute('marginTop', '10px')
.setCellPadding(5)
.setCellSpacing(2);
var array = [];
var t0 = [];
var t1 = [];
var t2 = [];
var color = [];
var BGcolor = [];
for(var i = 0;i<(size-1);i++){
var class = "class" + (i+1);
var classCode = classObjectsIndex[loggedInUser][class];
t0.push(statusObjectsIndex[classCode].classname);
t1.push(statusObjectsIndex[classCode].homeworkstatus);
t2.push(app.createAbsolutePanel().add(app.createAnchor('Calendar',statusObjectsIndex[classCode].classcalendarlink)));
if(statusObjectsIndex[classCode].homeworkstatus == "No homework set for this class"){
color.push("#000000")
BGcolor.push("#96bcfd")
}else{
color.push("#FFFFFF")
BGcolor.push("#eca8a3")
};
array.push(t0,t1,t2,color,BGcolor);
}
// sort the array here
array.sort();// use other sort parameter if you want, search SO for examples
for(var n in array){
flexTable.setText(i, 0, array[n][0]);
flexTable.setText(i, 1, array[n][1]);
flexTable.setWidget(i, 2, array[n][2]);
flexTable.setRowStyleAttribute(i, array[n][3])
flexTable.setRowStyleAttribute(i, array[n][4]);
}
app.add(flexTable);