Every possible combination of lists in google earth engine - google-earth-engine

I want to get possible combinations of two sets of lists in google earth engine, but my code did not works.
var Per1= ee.Array([[0.1,0.5,0.8],[0.4,0.5,0.2]])
var pre = PercFin1.toList()
var CC=ee.List([1,2,3]);
var ZZ = pre.map(function(hh){
var Per11 = ee.List(pre).get(hh);
var out = CC.zip(Per11);
return out;
});
print (ZZ)
The error I get is:
List.get, argument 'index': Invalid type. Expected: Integer. Actual: List.
Thanks in advance

I don't know if this is what you want, but it looks like you've got the right idea but made an incidental mistake: hh is not an index into pre but an element of it.
I modified and simplified the last part of your code (along with changing PercFin1 to Per1, which I assume was a typo):
var ZZ = pre.map(function(hh){
return CC.zip(hh);
});
print(ZZ);
The result of this is
[
[[1,0.1],[2,0.5],[3,0.8]],
[[1,0.4],[2,0.5],[3,0.2]]
]
which is what I understand you want — each row in Per1 individually zipped with CC.

Related

Only able to access first record in a query

(server side script)
This is a stripped down version of my code but what this should be doing is
find records where the "uniqueid" is equal to matchid
return 0 if there are less than two of these items
print the region of each item if there are two or more items
return the number of items
function copyFile(matchid){
var fileName = getProp('projectName')+" "+row[0];
var query = app.models.Files.newQuery();
query.filters.uniqueid._equals = matchid;
records = query.run();
var len = records.length;
if (len < 2) return 0;
console.log(row[2]+" - "+len);
for (var i=0; i<len;i++){
console.log("Loop "+i);
var r = records[i];
console.log(r.region);
}
return records.length
Strangely, it can only get at the region (or any of the other data for the FIRST record ( records[0]) for the others it says undefined. This is extremely confusing and frustrating. To reiterate it passes the len < 2 check, so there are more records in the set returned from the query, they just seem to be undefined if I try to get them from records[i]
Note: uniqueid is not actually a unique field, the name is from something else, sorry about confusion.
Question: WHY can't I get at records[1] records [2]
This was a ridiculous problem and I don't entirely understand the solution.
Changing "records" to "recs" entirely fixes my problem.
why does records[0] work, records[1] does not
but recs[0] and recs[1] both work.
I believe "records" has a special meaning and points at something regardless of assignment in this context.

Unable to extract List elements as integers using `getInfo`

I'm using reduceRegion to sum the number of water pixels determined by an NDWI. I want to do this on a collection of images to see change in water area over a period time.
The values are returned from the reduceRegion in the console and appear to be integers, but I am unable to extract them as such. This seems to be a common problem, but the solution is typically using getInfo function to bring these values over to client side. Unfortunately getInfo returns a null in this case.
The code below is for a collection of images OR a single image. The single image(image1) returns an image with an extra property(waterArea), and the mapped algorithm blows up(because the function is returning nulls).
I've also tried using getInfo on waterAg to potentially bring that list over to client side, however that returns the same List of objects that I don't want.
var image1 = ee.Image(leastcloud.first()).select(['B11','B8','B3'])
var stackarea = function(image){
var watermask = ee.Image(0)
var MNDWI = image.normalizedDifference(['B3','B11'])
watermask = watermask.where(MNDWI.gt(.31),1);
//sum of water pixels in an area
var sum = ee.Number(watermask.reduceRegion({
reducer: ee.Reducer.sum(),
geometry: geometry,
scale: 20,
maxPixels: 1e9
}));
var clientSide = sum.getInfo()
var setArea = image.set('waterArea', clientSide)
return setArea
};
var single = stackarea(image1)
print(single)
var watermapped = filterSpot.map(stackarea)
var waterAg = watermapped.aggregate_array('waterArea')
print(waterAg)
I'm really not sure how to extract these values as numbers...
I'm hoping to get a list of numbers so that I can concatenate that array to other arrays(date of image, cloud pixel %, etc.)
reduceRegion returns a dictionary object, not a number-like object. Therefore, in your stackarea function, clientSide variable is a dictionary (i.e. an object), not a number.
The number that you're after is stored in the dictionary returned by the reduceRegion function. You can get your hand on that number by using a get function on this dictionary object:
var sum = watermask.reduceRegion({
reducer: ee.Reducer.sum(),
geometry: geometry,
scale: 20,
maxPixels: 1e9
}).get('nd');
In this way, sum will be a server-side number that store the value you're after (There's no need to use ee.Number here as it does not help much).
In case you wonder about why using get('nd') but not get('somethingelse'), well it's the name of the band in your watermask image, and this name is the default band name given to the result of the normalizedDifference function.
And in my opinion, you don't even need to use the getInfo function which takes much more time to execute. Just delete the line var clientSide = sum.getInfo() and modify the next line into var setArea = image.set('waterArea', sum).
Hope this help.

Get word at position in Atom

From a linter provider, I receive a Point compatible array(line, column) where the error occured. Now I would like to hightlight the word surrounding that point, basically the result one would get if that exact point was double-clicked in the editor. Something like
const range = textEditor.getWordAtPosition(point)
Is what I hoped for, but couldn't find in the documentation.
Thanks for your help!
After looking around for a while, there seems to be no API method for the given need. I ended up writing a small helper function based upon this answer:
function getWordAtPosition(line, pos) {
// Perform type conversions.
line = String(line);
pos = Number(pos) >>> 0;
// Search for the word's beginning and end.
const left = Math.max.apply(null, [/\((?=[^(]*$)/,/\)(?=[^)]*$)/, /\,(?=[^,]*$)/, /\[(?=[^[]*$)/, /\](?=[^]]*$)/, /\;(?=[^;]*$)/, /\.(?=[^.]*$)/, /\s(?=[^\s]*$)/].map(x => line.slice(0, pos).search(x))) + 1
let right = line.slice(pos).search(/\s|\(|\)|\,|\.|\[|\]|\;/)
// The last word in the string is a special case.
if (right < 0) {
right = line.length - 1
}
// Return the word, using the located bounds to extract it from the string.
return str.slice(left, right + pos)
}
Here, the beginning of the word is determined by the latest occurance of one of the characters (),.[]; or a blank.
The end of the word is determined by the same characters, however here the first occurance is taken as a delimeter.
Given the original context, the function can the be called using the API method ::lineTextForBufferRow and the desired postion (column) as follows:
const range = getWordAtPosition(textEditor.lineTextForBufferRow(bufferRow), 10)

Reformatting date in google spreadsheet

I'm setting up a spreadsheet for someone else with a form to enter data.
One of the columns is supposed to hold a date. The input date format is like this example: "Jan 26, 2013" (there will be a lot of copy & paste involved to collect data, so changing the format at input step is not a real option).
I need this date column to be sortable, but the spreadsheet doesn't recognize this as a date but simply as a string. (It would recognize "Jan-26-2013", I've tried.)
So I need to reformat the input date.
My question is: how can I do this? I have looked around and google apps script looks like the way to go (though I haven't found a good example of reformatting yet).
Unfortunately my only programming experience is in Python, and of intermediate level. I could do this in Python without a problem, but I don't know any JavaScript.
(My Python approach would be:
splitted = date.split()
newdate = "-".join([splitted[0], splitted[1][:-1], splitted[2]])
return newdate
)
I also don't know how I'd go about linking the script to the spreadsheet - would I attach it to the cell, or the form, or where? And how? Any link to a helpful, understandable tutorial etc. on this point would help greatly.
Any help greatly appreciated!
Edit: Here's the code I ended up with:
//Function to filter unwanted " chars from date entries
function reformatDate() {
var sheet = SpreadsheetApp.getActiveSheet();
var startrow = 2;
var firstcolumn = 6;
var columnspan = 1;
var lastrow = sheet.getLastRow();
var dates = sheet.getRange(startrow, firstcolumn, lastrow, columnspan).getValues();
newdates = []
for(var i in dates){
var mydate = dates[i][0];
try
{
var newdate = mydate.replace(/"/g,'');
}
catch(err)
{
var newdate = mydate
}
newdates.push([newdate]);
}
sheet.getRange(startrow, firstcolumn, lastrow, columnspan).setValues(newdates)
}
For other confused google-script Newbies like me:
attaching the script to the spreadsheet works by creating the script from within the spreadsheet (Tools => Script Editor). Just putting the function in there is enough, you don't seem to need a function call etc.
you select the trigger of the script from the Script Editor (Resources => This Project's Triggers).
Important: the script will only work if there's an empty row at the bottom of the sheet in question!
Just an idea :
If you double click on your date string in the spreadsheet you will see that its real value that makes it a string instead of a date object is this 'Jan 26, 2013 with the ' in front of the string that I didn't add here...(The form does that to allow you to type what you want in the text area, including +322475... for example if it is a phone number, that's a known trick in spreadsheets cells) You could simply make a script that runs on form submit and that removes the ' in the cells, I guess the spreadsheet would do the rest... (I didn't test that so give it a try and consider this as a suggestion).
To remove the ' you can simply use the .replace() method **
var newValue = value.replace(/'/g,'');
here are some links to the relevant documentation : link1 link2
EDIT following your comment :
It could be simpler since the replace doesn't generate an error if no match is found. So you could make it like this :
function reformatDate() {
var sheet = SpreadsheetApp.getActiveSheet();
var dates = sheet.getRange(2, 6, sheet.getLastRow(), 1).getValues();
newdates = []
for(var i in dates){
var mydate = dates[i][0];
var newdate = mydate.replace(/"/g,'');
newdates.push([newdate]);
}
sheet.getRange(2, 6, sheet.getLastRow(), 1).setValues(newdates)
}
Also, you used the " in your code, presumably on purpose... my test showed ' instead. What made you make this choice ?
Solved it, I just had to change the comma to dot and it worked

How do I create variable paths using e4X?

I need to know how I can parse a variable path in Flex 3 & e4X. For example, I have two XML strings where the name of one element is the only difference.
<NameOfRoot>
<NameOfChild1>
<data>1</data>
</NameOfChild1>
</NameOfRoot>
<NameOfRoot>
<NameOfChild2>
<data>2</data>
</NameOfChild2>
</NameOfRoot>
Currently I am accessing variables like this:
var data1:String = NameOfRoot.*::NameOfChild1.*::data;
var data2:String = NameOfRoot.*::NameOfChild2.*::data;
I would rather make this task more abstract so that if "NameOfChild3" is introduced I do not need to update the code. For example:
var data:String = NameOfRoot.*::{variable}.*::data;
Does anyone have insights into how this can be done?
Use the child property (LiveDocs example here):
var tagName:String = "NameOfChild1";
var data:String = NameOfRoot.child(tagName).data;
That's with no namespacing--not sure whether it's necessary in your case, but I assume you'd add some *::'s?
this also works:
var data:String = NameOfRoot..data;
but if you have more than 1 data node you'll have to sort some stuff out.
It looks like the ".*." operation will work. I wonder if this is the easiest way to handle this problem.
var data:String = NameOfRoot.*.*::data;

Resources