From b98c266dc794e01791bfaacbde46520140875b4c Mon Sep 17 00:00:00 2001 From: Google Earth Engine Authors Date: Fri, 15 Sep 2023 17:42:18 +0000 Subject: [PATCH] v0.1.370 PiperOrigin-RevId: 565718645 --- javascript/build/ee_api_js.js | 185 +++++++++--------- javascript/build/ee_api_js_debug.js | 63 +++--- javascript/build/ee_api_js_npm.js | 107 +++++----- javascript/package.json | 2 +- javascript/src/apiclient.js | 2 +- javascript/src/apifunction.js | 2 - javascript/src/batch.js | 1 + javascript/src/collection.js | 1 - javascript/src/computedobject.js | 2 - javascript/src/customfunction.js | 1 - javascript/src/data.js | 1 - javascript/src/date.js | 2 - javascript/src/deserializer.js | 2 - javascript/src/dictionary.js | 1 - javascript/src/ee.js | 1 - javascript/src/element.js | 1 - javascript/src/encodable.js | 1 - javascript/src/feature.js | 1 - javascript/src/featurecollection.js | 5 +- javascript/src/filter.js | 1 - javascript/src/function.js | 1 - javascript/src/geometry.js | 1 - javascript/src/image.js | 4 +- javascript/src/imagecollection.js | 1 - javascript/src/list.js | 1 - javascript/src/number.js | 1 - javascript/src/serializer.js | 2 - javascript/src/string.js | 1 - javascript/src/terrain.js | 1 - javascript/src/types.js | 1 - python/ee/__init__.py | 31 +-- python/ee/apifunction.py | 21 +- python/ee/cli/commands.py | 74 ++++--- python/ee/image.py | 3 +- python/ee/tests/algorithms.json | 33 +++- .../tests/{date_test.py => ee_date_test.py} | 1 + .../tests/{list_test.py => ee_list_test.py} | 0 .../{number_test.py => ee_number_test.py} | 0 .../{string_test.py => ee_string_test.py} | 0 python/ee/tests/table_converter_test.py | 110 +++++++++++ .../Earth_Engine_REST_API_Quickstart.ipynb | 1 - 41 files changed, 409 insertions(+), 261 deletions(-) rename python/ee/tests/{date_test.py => ee_date_test.py} (99%) rename python/ee/tests/{list_test.py => ee_list_test.py} (100%) rename python/ee/tests/{number_test.py => ee_number_test.py} (100%) rename python/ee/tests/{string_test.py => ee_string_test.py} (100%) create mode 100644 python/ee/tests/table_converter_test.py delete mode 100644 python/examples/ipynb/Earth_Engine_REST_API_Quickstart.ipynb diff --git a/javascript/build/ee_api_js.js b/javascript/build/ee_api_js.js index d35e75707..09a87cd80 100644 --- a/javascript/build/ee_api_js.js +++ b/javascript/build/ee_api_js.js @@ -223,12 +223,11 @@ var Af=function(a){a=void 0===a?{}:a;this.h={};this.h.earthEngineDestination=nul Af.prototype.i=function(){return{J:{pyramidingPolicy:re,pyramidingPolicyOverrides:se},keys:["earthEngineDestination","pyramidingPolicy","pyramidingPolicyOverrides","tileSize"],La:{pyramidingPolicyOverrides:{ja:null,oa:!1,pa:!1,qa:!1}},s:{earthEngineDestination:$e}}}; k.Object.defineProperties(Af.prototype,{Ga:{configurable:!0,enumerable:!0,get:function(){return G(this,"earthEngineDestination")?F(this,"earthEngineDestination"):null},set:function(a){this.h.earthEngineDestination=a}},pyramidingPolicy:{configurable:!0,enumerable:!0,get:function(){return G(this,"pyramidingPolicy")?F(this,"pyramidingPolicy"):null},set:function(a){this.h.pyramidingPolicy=a}},Tf:{configurable:!0,enumerable:!0,get:function(){return G(this,"pyramidingPolicyOverrides")?F(this,"pyramidingPolicyOverrides"): null},set:function(a){this.h.pyramidingPolicyOverrides=a}},tileSize:{configurable:!0,enumerable:!0,get:function(){return G(this,"tileSize")?F(this,"tileSize"):null},set:function(a){this.h.tileSize=a}}}); -var qf=function(a){a=void 0===a?{}:a;this.h={};this.h.id=null==a.id?null:a.id;this.h.dataType=null==a.dataType?null:a.dataType;this.h.grid=null==a.grid?null:a.grid;this.h.pyramidingPolicy=null==a.pyramidingPolicy?null:a.pyramidingPolicy;this.h.tilesets=null==a.tilesets?null:a.tilesets;this.h.missingData=null==a.missingData?null:a.missingData;this.h.cloudStorageLocation=null==a.cloudStorageLocation?null:a.cloudStorageLocation};q(qf,E); -qf.prototype.i=function(){return{P:{tilesets:fg},J:{pyramidingPolicy:te},keys:"cloudStorageLocation dataType grid id missingData pyramidingPolicy tilesets".split(" "),s:{cloudStorageLocation:cf,dataType:gg,grid:Cf,missingData:hg}}}; -k.Object.defineProperties(qf.prototype,{cloudStorageLocation:{configurable:!0,enumerable:!0,get:function(){return G(this,"cloudStorageLocation")?F(this,"cloudStorageLocation"):null},set:function(a){this.h.cloudStorageLocation=a}},dataType:{configurable:!0,enumerable:!0,get:function(){return G(this,"dataType")?F(this,"dataType"):null},set:function(a){this.h.dataType=a}},grid:{configurable:!0,enumerable:!0,get:function(){return G(this,"grid")?F(this,"grid"):null},set:function(a){this.h.grid=a}},id:{configurable:!0, -enumerable:!0,get:function(){return G(this,"id")?F(this,"id"):null},set:function(a){this.h.id=a}},missingData:{configurable:!0,enumerable:!0,get:function(){return G(this,"missingData")?F(this,"missingData"):null},set:function(a){this.h.missingData=a}},pyramidingPolicy:{configurable:!0,enumerable:!0,get:function(){return G(this,"pyramidingPolicy")?F(this,"pyramidingPolicy"):null},set:function(a){this.h.pyramidingPolicy=a}},tilesets:{configurable:!0,enumerable:!0,get:function(){return G(this,"tilesets")? -F(this,"tilesets"):null},set:function(a){this.h.tilesets=a}}});var Bf=function(a){a=void 0===a?{}:a;this.h={};this.h.driveDestination=null==a.la?null:a.la;this.h.cloudStorageDestination=null==a.ia?null:a.ia;this.h.geoTiffOptions=null==a.Gd?null:a.Gd;this.h.tfRecordOptions=null==a.ie?null:a.ie;this.h.fileFormat=null==a.F?null:a.F};q(Bf,E); -Bf.prototype.i=function(){return{J:{fileFormat:ue},keys:["cloudStorageDestination","driveDestination","fileFormat","geoTiffOptions","tfRecordOptions"],s:{cloudStorageDestination:bf,driveDestination:of,geoTiffOptions:$f,tfRecordOptions:ig}}}; +var qf=function(a){a=void 0===a?{}:a;this.h={};this.h.id=null==a.id?null:a.id;this.h.dataType=null==a.dataType?null:a.dataType;this.h.grid=null==a.grid?null:a.grid;this.h.pyramidingPolicy=null==a.pyramidingPolicy?null:a.pyramidingPolicy;this.h.tilesets=null==a.tilesets?null:a.tilesets;this.h.missingData=null==a.missingData?null:a.missingData};q(qf,E); +qf.prototype.i=function(){return{P:{tilesets:fg},J:{pyramidingPolicy:te},keys:"dataType grid id missingData pyramidingPolicy tilesets".split(" "),s:{dataType:gg,grid:Cf,missingData:hg}}}; +k.Object.defineProperties(qf.prototype,{dataType:{configurable:!0,enumerable:!0,get:function(){return G(this,"dataType")?F(this,"dataType"):null},set:function(a){this.h.dataType=a}},grid:{configurable:!0,enumerable:!0,get:function(){return G(this,"grid")?F(this,"grid"):null},set:function(a){this.h.grid=a}},id:{configurable:!0,enumerable:!0,get:function(){return G(this,"id")?F(this,"id"):null},set:function(a){this.h.id=a}},missingData:{configurable:!0,enumerable:!0,get:function(){return G(this,"missingData")? +F(this,"missingData"):null},set:function(a){this.h.missingData=a}},pyramidingPolicy:{configurable:!0,enumerable:!0,get:function(){return G(this,"pyramidingPolicy")?F(this,"pyramidingPolicy"):null},set:function(a){this.h.pyramidingPolicy=a}},tilesets:{configurable:!0,enumerable:!0,get:function(){return G(this,"tilesets")?F(this,"tilesets"):null},set:function(a){this.h.tilesets=a}}}); +var Bf=function(a){a=void 0===a?{}:a;this.h={};this.h.driveDestination=null==a.la?null:a.la;this.h.cloudStorageDestination=null==a.ia?null:a.ia;this.h.geoTiffOptions=null==a.Gd?null:a.Gd;this.h.tfRecordOptions=null==a.ie?null:a.ie;this.h.fileFormat=null==a.F?null:a.F};q(Bf,E);Bf.prototype.i=function(){return{J:{fileFormat:ue},keys:["cloudStorageDestination","driveDestination","fileFormat","geoTiffOptions","tfRecordOptions"],s:{cloudStorageDestination:bf,driveDestination:of,geoTiffOptions:$f,tfRecordOptions:ig}}}; k.Object.defineProperties(Bf.prototype,{ia:{configurable:!0,enumerable:!0,get:function(){return G(this,"cloudStorageDestination")?F(this,"cloudStorageDestination"):null},set:function(a){this.h.cloudStorageDestination=a}},la:{configurable:!0,enumerable:!0,get:function(){return G(this,"driveDestination")?F(this,"driveDestination"):null},set:function(a){this.h.driveDestination=a}},F:{configurable:!0,enumerable:!0,get:function(){return G(this,"fileFormat")?F(this,"fileFormat"):null},set:function(a){this.h.fileFormat= a}},Gd:{configurable:!0,enumerable:!0,get:function(){return G(this,"geoTiffOptions")?F(this,"geoTiffOptions"):null},set:function(a){this.h.geoTiffOptions=a}},ie:{configurable:!0,enumerable:!0,get:function(){return G(this,"tfRecordOptions")?F(this,"tfRecordOptions"):null},set:function(a){this.h.tfRecordOptions=a}}}); var jg=function(a){a=void 0===a?{}:a;this.h={};this.h.name=null==a.name?null:a.name;this.h.properties=null==a.properties?null:a.properties;this.h.uriPrefix=null==a.kd?null:a.kd;this.h.tilesets=null==a.tilesets?null:a.tilesets;this.h.bands=null==a.bands?null:a.bands;this.h.maskBands=null==a.If?null:a.If;this.h.footprint=null==a.Ah?null:a.Ah;this.h.missingData=null==a.missingData?null:a.missingData;this.h.pyramidingPolicy=null==a.pyramidingPolicy?null:a.pyramidingPolicy;this.h.startTime=null==a.startTime? @@ -433,14 +432,14 @@ aj.prototype.sb=function(){return this.o?this.o.readyState:0};aj.prototype.getSt var lj=function(a){try{if(!a.o)return null;if("response"in a.o)return a.o.response;switch(a.xc){case "":case "text":return a.o.responseText;case "arraybuffer":if("mozResponseArrayBuffer"in a.o)return a.o.mozResponseArrayBuffer}Si(a.aa,"Response type "+a.xc+" is not supported on this browser");return null}catch(b){return Ti(a.aa,"Can not get response: "+b.message),null}};aj.prototype.getResponseHeader=function(a){if(this.o&&4==this.sb())return a=this.o.getResponseHeader(a),null===a?void 0:a}; aj.prototype.getAllResponseHeaders=function(){return this.o&&2<=this.sb()?this.o.getAllResponseHeaders()||"":""};var mj=function(a){var b={};a=a.getAllResponseHeaders().split("\r\n");for(var c=0;c\r\n\r\n"+m+"\r\n"}).join("")+"--batch_EARTHENGINE_batch--\r\n",g=function(f){var l={};a.forEach(function(m){var p=n(m);m=p.next().value;p=n(p.next().value);p.next();p=p.next().value;null!=f[m]&&(l[m]= -Uc(p,f[m]))});return b?b(l):l};return this.callback?(tj(d,null,function(f,l){return c.callback(l?f:g(f),l)},"multipart/mixed; boundary=batch_EARTHENGINE_batch",e,void 0,this.Pb),null):g(tj(d,null,void 0,"multipart/mixed; boundary=batch_EARTHENGINE_batch",e,void 0,this.Pb))};var vj=function(){};q(vj,kh); -vj.prototype.send=function(a,b){var c=[a.B+" "+a.path+" HTTP/1.1"];c.push("Content-Type: application/json; charset=utf-8");var d=xj();null!=d&&c.push("Authorization: "+d);a=a.body?JSON.stringify(a.body):"";return[c.join("\r\n")+"\r\n\r\n"+a,b]}; +Uc(p,f[m]))});return b?b(l):l};return this.callback?(tj(d,null,function(f,l){return c.callback(l?f:g(f),l)},"multipart/mixed; boundary=batch_EARTHENGINE_batch",e,void 0,this.Pb),null):g(tj(d,null,void 0,"multipart/mixed; boundary=batch_EARTHENGINE_batch",e,void 0,this.Pb))};var uj=function(){};q(uj,kh); +uj.prototype.send=function(a,b){var c=[a.B+" "+a.path+" HTTP/1.1"];c.push("Content-Type: application/json; charset=utf-8");var d=xj();null!=d&&c.push("Authorization: "+d);a=a.body?JSON.stringify(a.body):"";return[c.join("\r\n")+"\r\n\r\n"+a,b]}; var yj=function(a,b,c){a=n(b.split("--"+a.split("; boundary=")[1]));for(b=a.next();!b.done;b=a.next())if(b=b.value.split("\r\n\r\n"),!(3>b.length)){var d=b[0].match(/\r\nContent-ID: ]*)>/)[1],e=Number(b[1].match(/^HTTP\S*\s(\d+)\s/)[1]);c(d,e,b.slice(2).join("\r\n\r\n"))}},rj=function(){var a=zj.replace(/\/api$/,"");return"window"in r&&!a.match(/^https?:\/\/content-/)?a.replace(/^(https?:\/\/)(.*\.googleapis\.com)$/,"$1content-$2"):a},Bj=function(a,b,c){var d=[];a&&(d=d.concat(Aj)); b&&d.push("https://www.googleapis.com/auth/devstorage.read_write");a=d=d.concat(c);c=b=0;for(var e={};cg)break;y++}return Wj(C.status,function(P){try{return C.getResponseHeader(P)}catch(oa){return null}},C.responseText,l,void 0,e,d,f)},Uj=function(a,b,c,d,e,g,f){var l=0,m={url:a,method:c,content:d,headers:e},p=Oj,v=null!=g?g:10; m.callback=function(y){y=y.target;if(429==y.getStatus()&&l"))+"_";for(e=0;e< -d.length;e++){var g=d[e],f=c+e;b[g].T=f;a.args[g].name=f}return a};var ep=function(a,b){if(!(this instanceof ep))return Qm(ep,arguments);if(a instanceof ep)return a;fp();var c=S(ep,arguments);a=c.date;c=c.tz;var d=new O("Date"),e={},g=null;if(Vm(a)){if(e.value=a,c)if(Vm(c))e.timeZone=c;else throw Error("Invalid argument specified for ee.Date(..., opt_tz): "+c);}else if(Um(a))e.value=a;else if(wa(a))e.value=Math.floor(a.getTime());else if(a instanceof N)a.H&&"Date"==a.H.Y().returns?(d=a.H,e=a.args,g=a.T):e.value=a;else throw Error("Invalid argument specified for ee.Date(): "+ -a);N.call(this,d,e,g)};x(ep,N);w("ee.Date",ep);var gp=!1,fp=function(){gp||(ln(ep,"Date","Date"),gp=!0)};ep.prototype.name=function(){return"Date"};w("ee.Deserializer",function(){});var ip=function(a){return hp(JSON.parse(a))};w("ee.Deserializer.fromJSON",ip);var hp=function(a){if("result"in a&&"values"in a)return jp(a);var b={};if(t(a)&&"CompoundValue"===a.type){for(var c=a.scope,d=0;d/,"");c[g]=!0}var f=r.ee,l;for(l in b)l in c&&!(l in f)&&(f[l]=Ep(l),yp.push(l),a[l]?(f[l].signature=a[l],f[l].signature.isConstructor=!0,fn[l]=!0):f[l].signature={});Sm=f;Fp()}catch(m){wp(m);return}sp="ready";for(tp=[];0"))+"_";for(e=0;e< +d.length;e++){var g=d[e],f=c+e;b[g].T=f;a.args[g].name=f}return a};var fp=function(a,b){if(!(this instanceof fp))return Qm(fp,arguments);if(a instanceof fp)return a;gp();var c=S(fp,arguments);a=c.date;c=c.tz;var d=new O("Date"),e={},g=null;if(Vm(a)){if(e.value=a,c)if(Vm(c))e.timeZone=c;else throw Error("Invalid argument specified for ee.Date(..., opt_tz): "+c);}else if(Um(a))e.value=a;else if(wa(a))e.value=Math.floor(a.getTime());else if(a instanceof N)a.H&&"Date"==a.H.Y().returns?(d=a.H,e=a.args,g=a.T):e.value=a;else throw Error("Invalid argument specified for ee.Date(): "+ +a);N.call(this,d,e,g)};x(fp,N);w("ee.Date",fp);var hp=!1,gp=function(){hp||(ln(fp,"Date","Date"),hp=!0)};fp.prototype.name=function(){return"Date"};w("ee.Deserializer",function(){});var jp=function(a){return ip(JSON.parse(a))};w("ee.Deserializer.fromJSON",jp);var ip=function(a){if("result"in a&&"values"in a)return kp(a);var b={};if(t(a)&&"CompoundValue"===a.type){for(var c=a.scope,d=0;d/,"");c[g]=!0}var f=r.ee,l;for(l in b)l in c&&!(l in f)&&(f[l]=Fp(l),zp.push(l),a[l]?(f[l].signature=a[l],f[l].signature.isConstructor=!0,fn[l]=!0):f[l].signature={});Sm=f;Gp()}catch(m){xp(m);return}tp="ready";for(up=[];0a.y||a.y>=d)return c.createElement("div");var e=a.x%d;0>e&&(e+=d);d=new google.maps.Point(e,a.y);a=[a.x,a.y,b,this.wb++].join("-");e=this.tg.getUniqueId();a=[a,e].join("-");b=this.eh(d,b,c,a);b.tileSize=this.tileSize;Tp(b.ka,this.opacity);this.xb.set(a,b);Wp(this,b);this.dispatchEvent(new Xp(this.Lc()));this.tg.Ef(b,(new Date).getTime()/1E3);return b.ka};h.releaseTile=function(a){var b=this.xb.get(a.id);this.xb.remove(a.id);b&&(b.abort(),Fa(b))}; -var Wp=function(a,b){a.ib.Wa(b,"status-changed",function(){switch(b.getStatus()){case "loaded":var c=b.il,d=(new Date).getTime();Kp(this.de,b.zoom).tileLatencies.push(d-c);this.dispatchEvent(new Yp(this.Lc()));break;case "throttled":Kp(this.de,b.zoom).throttleCount++;this.dispatchEvent(new Zp(b.Ba));break;case "failed":Kp(this.de,b.zoom).errorCount++;this.dispatchEvent(new $p(b.Ba,b.Wk));break;case "aborted":this.dispatchEvent(new aq(this.Lc()))}})}; -Up.prototype.I=function(){D.prototype.I.call(this);this.xb.forEach(Fa);this.xb.clear();this.xb=null;Fa(this.ib);this.tg=this.ib=null};var Vp=function(a,b){return Xa(a.xb.Z(),function(c){return c.getStatus()==b})};w("ee.layers.AbstractOverlay",Up);Up.prototype.removeTileCallback=Up.prototype.Zf;Up.prototype.addTileCallback=Up.prototype.Le;var Yp=function(){A.call(this,"tile-load")};q(Yp,A);var Xp=function(){A.call(this,"tile-start")};q(Xp,A);var Zp=function(){A.call(this,"tile-throttle")};q(Zp,A); -var $p=function(a,b){A.call(this,"tile-fail");this.errorMessage=b};q($p,A);var aq=function(){A.call(this,"tile-abort")};q(aq,A);var bq=function(a,b,c,d){D.call(this);this.pb=a;this.zoom=b;this.ka=c.createElement("div");this.ka.id=d;this.ll=5;this.Zd=function(){};this.ge="new";this.xi=0;this.Cf=!1};q(bq,D);bq.prototype.getDiv=function(){return this.ka}; -var dq=function(a){if(!a.Cf&&"loading"==a.getStatus())throw Error("startLoad() can only be invoked once. Use retryLoad() after the first attempt.");cq(a,"loading");a.il=(new Date).getTime();a.Ya=new aj;a.Ya.xc="blob";a.Ya.Wa("complete",function(){var b=lj(a.Ya),c=a.Ya.getStatus();429==c&&cq(a,"throttled");if(Ui(c)){var d={};Db(mj(a.Ya),function(g,f){d[f.toLowerCase()]=g});a.zl=d;a.Ei=b;a.Jc()}else if(b){var e=new Sp;e.Wa("loadend",function(){a.ed(e.ba.result)});e.readAsText(b)}else a.ed("Failed to load tile.")}, -!1);a.Ya.Tc("ready",Da(Fa,a.Ya));a.Ba&&a.Ba.endsWith("&profiling=1")&&(a.Ba=a.Ba.replace("&profiling=1",""),a.Ya.headers.set("X-Earth-Engine-Computation-Profiling","1"));a.Ya.send(a.Ba,"GET")};h=bq.prototype;h.Jc=function(){this.Zd(this);cq(this,"loaded")};h.Fc=function(){Fa(this.Ya)}; -h.ed=function(a){var b=function(c){try{if(c=JSON.parse(c),c.error&&c.error.message)return c.error.message}catch(d){}return c};this.xi>=this.ll?(this.Wk=b(a),cq(this,"failed")):(this.Fc(),setTimeout(u(function(){this.Ra||(this.Cf=!0,dq(this),this.Cf=!1)},this),1E3*Math.pow(2,this.xi++)))};h.abort=function(){this.Fc();"aborted"!=this.getStatus()&&"removed"!=this.getStatus()&&cq(this,this.ge in eq?"removed":"aborted")};h.getStatus=function(){return this.ge};var cq=function(a,b){a.ge=b;a.dispatchEvent("status-changed")}; -bq.prototype.I=function(){D.prototype.I.call(this);this.Fc();this.ka.remove();this.Zd=null};var eq={aborted:!0,failed:!0,loaded:!0,removed:!0};var fq=function(){z.call(this)};q(fq,z);var gq=function(a,b){Up.call(this,a,b);this.Sg=new xc;this.qh=new xc};q(gq,Up);gq.prototype.eh=function(a,b,c,d){var e=new hq(a,b,c,d);this.ib.Wa(e,"status-changed",function(){"loaded"==e.getStatus()&&(this.Sg.set(a,new Float32Array(e.vd)),this.qh.set(a,e.ka))});return e};gq.prototype.I=function(){Up.prototype.I.call(this);this.qh=this.Sg=null};w("ee.layers.BinaryOverlay",gq);var hq=function(a,b,c,d){bq.call(this,a,b,c,d)};q(hq,bq); -hq.prototype.Jc=function(){var a=new Sp;a.Wa("loadend",function(){this.vd=a.ba.result;bq.prototype.Jc.call(this)},void 0,this);a.readAsArrayBuffer(this.Ei)};var iq=function(a){D.call(this);this.Pc={};this.Oc={};this.Rb=new Lp(this);this.W=a;this.Ve=!1};x(iq,D);var jq=["load","abort","error"],kq=function(a,b,c){if(c="string"===typeof c?c:c.src)a.Ve=!1,a.Pc[b]={src:c,dh:null}},lq=function(a,b){delete a.Pc[b];var c=a.Oc[b];c&&(delete a.Oc[b],a.Rb.oe(c,jq,a.di))}; -iq.prototype.start=function(){var a=this.Pc;Ib(a).forEach(function(b){var c=a[b];if(c&&(delete a[b],!this.Ra)){if(this.W){var d=this.W;d=(d?new uh(th(d)):Ha||(Ha=new uh)).Uk("IMG")}else d=new Image;c.dh&&(d.crossOrigin=c.dh);this.Rb.Wa(d,jq,this.di);this.Oc[b]=d;d.id=b;d.src=c.src}},this)}; -iq.prototype.di=function(a){var b=a.currentTarget;if(b){if("readystatechange"==a.type)if("complete"==b.readyState)a.type="load";else return;"undefined"==typeof b.naturalWidth&&("load"==a.type?(b.naturalWidth=b.width,b.naturalHeight=b.height):(b.naturalWidth=0,b.naturalHeight=0));lq(this,b.id);this.dispatchEvent({type:a.type,target:b});!this.Ra&&Nb(this.Oc)&&Nb(this.Pc)&&!this.Ve&&(this.Ve=!0,this.dispatchEvent("complete"))}};iq.prototype.I=function(){delete this.Pc;delete this.Oc;Fa(this.Rb);iq.L.I.call(this)};/* +a:new Y(a);case "ImageCollection":return new Z(a);case "Filter":return new V(a);case "Algorithm":if("string"===typeof a)return new O(a);if("function"===typeof a){b=a.length;c=[];for(var d=0;da.y||a.y>=d)return c.createElement("div");var e=a.x%d;0>e&&(e+=d);d=new google.maps.Point(e,a.y);a=[a.x,a.y,b,this.wb++].join("-");e=this.tg.getUniqueId();a=[a,e].join("-");b=this.eh(d,b,c,a);b.tileSize=this.tileSize;Up(b.ka,this.opacity);this.xb.set(a,b);Xp(this,b);this.dispatchEvent(new Yp(this.Lc()));this.tg.Ef(b,(new Date).getTime()/1E3);return b.ka};h.releaseTile=function(a){var b=this.xb.get(a.id);this.xb.remove(a.id);b&&(b.abort(),Fa(b))}; +var Xp=function(a,b){a.ib.Wa(b,"status-changed",function(){switch(b.getStatus()){case "loaded":var c=b.il,d=(new Date).getTime();Lp(this.de,b.zoom).tileLatencies.push(d-c);this.dispatchEvent(new Zp(this.Lc()));break;case "throttled":Lp(this.de,b.zoom).throttleCount++;this.dispatchEvent(new $p(b.Ba));break;case "failed":Lp(this.de,b.zoom).errorCount++;this.dispatchEvent(new aq(b.Ba,b.Wk));break;case "aborted":this.dispatchEvent(new bq(this.Lc()))}})}; +Vp.prototype.I=function(){D.prototype.I.call(this);this.xb.forEach(Fa);this.xb.clear();this.xb=null;Fa(this.ib);this.tg=this.ib=null};var Wp=function(a,b){return Xa(a.xb.Z(),function(c){return c.getStatus()==b})};w("ee.layers.AbstractOverlay",Vp);Vp.prototype.removeTileCallback=Vp.prototype.Zf;Vp.prototype.addTileCallback=Vp.prototype.Le;var Zp=function(){A.call(this,"tile-load")};q(Zp,A);var Yp=function(){A.call(this,"tile-start")};q(Yp,A);var $p=function(){A.call(this,"tile-throttle")};q($p,A); +var aq=function(a,b){A.call(this,"tile-fail");this.errorMessage=b};q(aq,A);var bq=function(){A.call(this,"tile-abort")};q(bq,A);var cq=function(a,b,c,d){D.call(this);this.pb=a;this.zoom=b;this.ka=c.createElement("div");this.ka.id=d;this.ll=5;this.Zd=function(){};this.ge="new";this.xi=0;this.Cf=!1};q(cq,D);cq.prototype.getDiv=function(){return this.ka}; +var eq=function(a){if(!a.Cf&&"loading"==a.getStatus())throw Error("startLoad() can only be invoked once. Use retryLoad() after the first attempt.");dq(a,"loading");a.il=(new Date).getTime();a.Ya=new aj;a.Ya.xc="blob";a.Ya.Wa("complete",function(){var b=lj(a.Ya),c=a.Ya.getStatus();429==c&&dq(a,"throttled");if(Ui(c)){var d={};Db(mj(a.Ya),function(g,f){d[f.toLowerCase()]=g});a.zl=d;a.Ei=b;a.Jc()}else if(b){var e=new Tp;e.Wa("loadend",function(){a.ed(e.ba.result)});e.readAsText(b)}else a.ed("Failed to load tile.")}, +!1);a.Ya.Tc("ready",Da(Fa,a.Ya));a.Ba&&a.Ba.endsWith("&profiling=1")&&(a.Ba=a.Ba.replace("&profiling=1",""),a.Ya.headers.set("X-Earth-Engine-Computation-Profiling","1"));a.Ya.send(a.Ba,"GET")};h=cq.prototype;h.Jc=function(){this.Zd(this);dq(this,"loaded")};h.Fc=function(){Fa(this.Ya)}; +h.ed=function(a){var b=function(c){try{if(c=JSON.parse(c),c.error&&c.error.message)return c.error.message}catch(d){}return c};this.xi>=this.ll?(this.Wk=b(a),dq(this,"failed")):(this.Fc(),setTimeout(u(function(){this.Ra||(this.Cf=!0,eq(this),this.Cf=!1)},this),1E3*Math.pow(2,this.xi++)))};h.abort=function(){this.Fc();"aborted"!=this.getStatus()&&"removed"!=this.getStatus()&&dq(this,this.ge in fq?"removed":"aborted")};h.getStatus=function(){return this.ge};var dq=function(a,b){a.ge=b;a.dispatchEvent("status-changed")}; +cq.prototype.I=function(){D.prototype.I.call(this);this.Fc();this.ka.remove();this.Zd=null};var fq={aborted:!0,failed:!0,loaded:!0,removed:!0};var gq=function(){z.call(this)};q(gq,z);var hq=function(a,b){Vp.call(this,a,b);this.Sg=new xc;this.qh=new xc};q(hq,Vp);hq.prototype.eh=function(a,b,c,d){var e=new iq(a,b,c,d);this.ib.Wa(e,"status-changed",function(){"loaded"==e.getStatus()&&(this.Sg.set(a,new Float32Array(e.vd)),this.qh.set(a,e.ka))});return e};hq.prototype.I=function(){Vp.prototype.I.call(this);this.qh=this.Sg=null};w("ee.layers.BinaryOverlay",hq);var iq=function(a,b,c,d){cq.call(this,a,b,c,d)};q(iq,cq); +iq.prototype.Jc=function(){var a=new Tp;a.Wa("loadend",function(){this.vd=a.ba.result;cq.prototype.Jc.call(this)},void 0,this);a.readAsArrayBuffer(this.Ei)};var jq=function(a){D.call(this);this.Pc={};this.Oc={};this.Rb=new Mp(this);this.W=a;this.Ve=!1};x(jq,D);var kq=["load","abort","error"],lq=function(a,b,c){if(c="string"===typeof c?c:c.src)a.Ve=!1,a.Pc[b]={src:c,dh:null}},mq=function(a,b){delete a.Pc[b];var c=a.Oc[b];c&&(delete a.Oc[b],a.Rb.oe(c,kq,a.di))}; +jq.prototype.start=function(){var a=this.Pc;Ib(a).forEach(function(b){var c=a[b];if(c&&(delete a[b],!this.Ra)){if(this.W){var d=this.W;d=(d?new uh(th(d)):Ha||(Ha=new uh)).Uk("IMG")}else d=new Image;c.dh&&(d.crossOrigin=c.dh);this.Rb.Wa(d,kq,this.di);this.Oc[b]=d;d.id=b;d.src=c.src}},this)}; +jq.prototype.di=function(a){var b=a.currentTarget;if(b){if("readystatechange"==a.type)if("complete"==b.readyState)a.type="load";else return;"undefined"==typeof b.naturalWidth&&("load"==a.type?(b.naturalWidth=b.width,b.naturalHeight=b.height):(b.naturalWidth=0,b.naturalHeight=0));mq(this,b.id);this.dispatchEvent({type:a.type,target:b});!this.Ra&&Nb(this.Oc)&&Nb(this.Pc)&&!this.Ve&&(this.Ve=!0,this.dispatchEvent("complete"))}};jq.prototype.I=function(){delete this.Pc;delete this.Oc;Fa(this.Rb);jq.L.I.call(this)};/* SPDX-License-Identifier: Apache-2.0 */ -var mq=[],nq=function(a){var b=Pi(Qi(),"safevalues").Sh;b&&Ri(b,Ei,"A URL with content '"+a+"' was sanitized away.")};-1===mq.indexOf(nq)&&mq.push(nq);function oq(a){if("undefined"!==typeof MediaSource&&a instanceof MediaSource)return new pd(URL.createObjectURL(a),od);var b=a.type.match(/^([^;]+)(?:;\w+=(?:\w+|"[\w;,= ]+"))*$/i);if(2!==(null==b?void 0:b.length)||!(/^image\/(?:bmp|gif|jpeg|jpg|png|tiff|webp|x-icon|heic|heif|avif)$/i.test(b[1])||/^video\/(?:mpeg|mp4|ogg|webm|x-matroska|quicktime|x-ms-wmv)$/i.test(b[1])||/^audio\/(?:3gpp2|3gpp|aac|L16|midi|mp3|mp4|mpeg|oga|ogg|opus|x-m4a|x-matroska|x-wav|wav|webm)$/i.test(b[1])))throw Error("unsafe blob MIME type: "+ -a.type);return new pd(URL.createObjectURL(a),od)};var pq=function(a,b){Up.call(this,a,b)};q(pq,Up);pq.prototype.eh=function(a,b,c,d){return new qq(a,b,c,d)};w("ee.layers.ImageOverlay",pq);var qq=function(a,b,c,d){bq.call(this,a,b,c,d);this.Zd=rq;this.Hh=this.fa=this.Nd=null;this.Wc=""};q(qq,bq); -qq.prototype.Jc=function(){try{var a=oq(this.Ei);this.Wc=qd(a);var b=this.Wc!==rd.toString()?this.Wc:this.Ba}catch(c){b=this.Ba}this.fa=new iq;kq(this.fa,this.ka.id+"-image",b);this.Hh=Zb(this.fa,sq,function(c){"load"==c.type?(this.Nd=c.target,bq.prototype.Jc.call(this)):this.ed()},void 0,this);this.fa.start()};qq.prototype.Fc=function(){bq.prototype.Fc.call(this);this.fa&&(hc(this.Hh),Fa(this.fa))};qq.prototype.I=function(){bq.prototype.I.call(this);this.Wc&&URL.revokeObjectURL(this.Wc)}; -var rq=function(a){a.ka.appendChild(a.Nd)},sq=["load","abort","error"];var tq=function(a){for(var b=arguments[0],c=1;cthis.Sd)throw Error("[goog.structs.Pool] Min can not be greater than max");this.Sa=new wq;this.tb=new Gc;this.delay=0;this.Df=null;this.od()};x(xq,z);xq.prototype.Mc=function(){var a=Date.now();if(!(null!=this.Df&&a-this.Dfthis.Sd&&0=this.R()){for(var c=this.za,d=0;d>1,a[d].getKey()>c.getKey())a[b]=a[d],b=d;else break;a[b]=c};h=Aq.prototype; +var nq=[],oq=function(a){var b=Pi(Qi(),"safevalues").Sh;b&&Ri(b,Ei,"A URL with content '"+a+"' was sanitized away.")};-1===nq.indexOf(oq)&&nq.push(oq);function pq(a){if("undefined"!==typeof MediaSource&&a instanceof MediaSource)return new pd(URL.createObjectURL(a),od);var b=a.type.match(/^([^;]+)(?:;\w+=(?:\w+|"[\w;,= ]+"))*$/i);if(2!==(null==b?void 0:b.length)||!(/^image\/(?:bmp|gif|jpeg|jpg|png|tiff|webp|x-icon|heic|heif|avif)$/i.test(b[1])||/^video\/(?:mpeg|mp4|ogg|webm|x-matroska|quicktime|x-ms-wmv)$/i.test(b[1])||/^audio\/(?:3gpp2|3gpp|aac|amr|L16|midi|mp3|mp4|mpeg|oga|ogg|opus|x-m4a|x-matroska|x-wav|wav|webm)$/i.test(b[1])||/^font\/\w+/i.test(b[1])))throw Error("unsafe blob MIME type: "+ +a.type);return new pd(URL.createObjectURL(a),od)};var qq=function(a,b){Vp.call(this,a,b)};q(qq,Vp);qq.prototype.eh=function(a,b,c,d){return new rq(a,b,c,d)};w("ee.layers.ImageOverlay",qq);var rq=function(a,b,c,d){cq.call(this,a,b,c,d);this.Zd=sq;this.Hh=this.fa=this.Nd=null;this.Wc=""};q(rq,cq); +rq.prototype.Jc=function(){try{var a=pq(this.Ei);this.Wc=qd(a);var b=this.Wc!==rd.toString()?this.Wc:this.Ba}catch(c){b=this.Ba}this.fa=new jq;lq(this.fa,this.ka.id+"-image",b);this.Hh=Zb(this.fa,tq,function(c){"load"==c.type?(this.Nd=c.target,cq.prototype.Jc.call(this)):this.ed()},void 0,this);this.fa.start()};rq.prototype.Fc=function(){cq.prototype.Fc.call(this);this.fa&&(hc(this.Hh),Fa(this.fa))};rq.prototype.I=function(){cq.prototype.I.call(this);this.Wc&&URL.revokeObjectURL(this.Wc)}; +var sq=function(a){a.ka.appendChild(a.Nd)},tq=["load","abort","error"];var uq=function(a){for(var b=arguments[0],c=1;cthis.Sd)throw Error("[goog.structs.Pool] Min can not be greater than max");this.Sa=new xq;this.tb=new Gc;this.delay=0;this.Df=null;this.od()};x(yq,z);yq.prototype.Mc=function(){var a=Date.now();if(!(null!=this.Df&&a-this.Dfthis.Sd&&0=this.R()){for(var c=this.za,d=0;d>1,a[d].getKey()>c.getKey())a[b]=a[d],b=d;else break;a[b]=c};h=Bq.prototype; h.remove=function(){var a=this.za,b=a.length,c=a[0];if(!(0>=b)){if(1==b)a.length=0;else{a[0]=a.pop();a=0;b=this.za;for(var d=b.length,e=b[a];a>1;){var g=2*a+1,f=2*a+2;g=fe.getKey())break;b[a]=b[g];a=g}b[a]=e}return c.qe}};h.Z=function(){for(var a=this.za,b=[],c=a.length,d=0;dthis.ml)return!1;this.Jg++;lq(this.fa,this.ea);setTimeout(u(this.Al,this),0);return!0}; -h.Al=function(){if(!this.ic){var a=u(function(d){this.ic||(kq(this.fa,this.ea,d),Zb(this.fa,Mq,u(this.bl,this)),this.fa.start())},this),b=this.getUrl();if(Rd(b).Aa.Nb("profiling")){var c=new aj;c.xc="blob";c.Wa("complete",u(function(){this.oi=c.getResponseHeader("X-Earth-Engine-Computation-Profile")||null;if(200<=c.getStatus()&&300>c.getStatus())try{var d=qd(oq(lj(c)));var e=d!==rd.toString()}catch(g){}a(e?d:b)},this));c.Tc("ready",u(c.Qa,c));c.send(b,"GET")}else a(b)}};h.Jg=0;h.ic=!1;h.fa=null; -h.Qi=null;h.Ia=null;h.oi=null;var Mq=["load","abort","error"],Nq=function(){z.call(this);this.Da=!1};q(Nq,z);Nq.prototype.setActive=function(a){this.Da=a};Nq.prototype.isActive=function(){return this.Da};var Iq=function(a,b){Dq.call(this,a,b)};q(Iq,Dq);Iq.prototype.Ye=function(){return new Nq};Iq.prototype.zd=function(a){a.Qa()};Iq.prototype.Of=function(a){return!a.Ra&&!a.isActive()};var Oq=function(a,b,c,d,e){Lc.call(this,a,b,c,d,e);this.minZoom=d.minZoom||0;this.maxZoom=d.maxZoom||20;if(!window.google||!window.google.maps)throw Error("Google Maps API hasn't been initialized.");this.tileSize=d.tileSize||new google.maps.Size(256,256);this.name=d.name;this.vg=new Gc;this.Pf=1;this.ta=e||null};q(Oq,Lc);h=Oq.prototype;h.Le=function(a){return $b(this,"tileevent",a)};h.Zf=function(a){hc(a)}; -h.getTile=function(a,b,c){if(ba.y||a.y>=1<this.ml)return!1;this.Jg++;mq(this.fa,this.ea);setTimeout(u(this.Al,this),0);return!0}; +h.Al=function(){if(!this.ic){var a=u(function(d){this.ic||(lq(this.fa,this.ea,d),Zb(this.fa,Nq,u(this.bl,this)),this.fa.start())},this),b=this.getUrl();if(Rd(b).Aa.Nb("profiling")){var c=new aj;c.xc="blob";c.Wa("complete",u(function(){this.oi=c.getResponseHeader("X-Earth-Engine-Computation-Profile")||null;if(200<=c.getStatus()&&300>c.getStatus())try{var d=qd(pq(lj(c)));var e=d!==rd.toString()}catch(g){}a(e?d:b)},this));c.Tc("ready",u(c.Qa,c));c.send(b,"GET")}else a(b)}};h.Jg=0;h.ic=!1;h.fa=null; +h.Qi=null;h.Ia=null;h.oi=null;var Nq=["load","abort","error"],Oq=function(){z.call(this);this.Da=!1};q(Oq,z);Oq.prototype.setActive=function(a){this.Da=a};Oq.prototype.isActive=function(){return this.Da};var Jq=function(a,b){Eq.call(this,a,b)};q(Jq,Eq);Jq.prototype.Ye=function(){return new Oq};Jq.prototype.zd=function(a){a.Qa()};Jq.prototype.Of=function(a){return!a.Ra&&!a.isActive()};var Pq=function(a,b,c,d,e){Lc.call(this,a,b,c,d,e);this.minZoom=d.minZoom||0;this.maxZoom=d.maxZoom||20;if(!window.google||!window.google.maps)throw Error("Google Maps API hasn't been initialized.");this.tileSize=d.tileSize||new google.maps.Size(256,256);this.name=d.name;this.vg=new Gc;this.Pf=1;this.ta=e||null};q(Pq,Lc);h=Pq.prototype;h.Le=function(a){return $b(this,"tileevent",a)};h.Zf=function(a){hc(a)}; +h.getTile=function(a,b,c){if(ba.y||a.y>=1<=} opt_selectors * @param {number=} opt_maxVertices * @return {!ExportTask} + * @export */ Export.table.toBigQuery = function( collection, opt_description, opt_table, opt_overwrite, opt_append, diff --git a/javascript/src/collection.js b/javascript/src/collection.js index 51429f4ad..6524f29fd 100644 --- a/javascript/src/collection.js +++ b/javascript/src/collection.js @@ -1,7 +1,6 @@ /** * @fileoverview Base class for ImageCollection and FeatureCollection. * This class is never intended to be instantiated by the user. - * @author gorelick@google.com (Noel Gorelick) */ goog.provide('ee.Collection'); diff --git a/javascript/src/computedobject.js b/javascript/src/computedobject.js index 924c057a8..26c1cbcdd 100644 --- a/javascript/src/computedobject.js +++ b/javascript/src/computedobject.js @@ -1,7 +1,5 @@ /** * @fileoverview A representation of a computed earthengine object. - * - * @author gorelick@google.com (Noel Gorelick) */ goog.provide('ee.ComputedObject'); diff --git a/javascript/src/customfunction.js b/javascript/src/customfunction.js index f985b041e..3446a837d 100644 --- a/javascript/src/customfunction.js +++ b/javascript/src/customfunction.js @@ -1,6 +1,5 @@ /** * @fileoverview An object representing a custom EE Function. - * @author maxus@google.com (Max Shawabkeh) */ goog.provide('ee.CustomFunction'); diff --git a/javascript/src/data.js b/javascript/src/data.js index e00f3bb38..8f3ea4eb0 100644 --- a/javascript/src/data.js +++ b/javascript/src/data.js @@ -1,7 +1,6 @@ /** * @fileoverview Singleton for all of the library's communication * with the Earth Engine API. - * @author gorelick@google.com (Noel Gorelick) * @suppress {missingRequire} TODO(user): this shouldn't be needed * @suppress {useOfGoogProvide} TODO(user): Convert to goog.module. */ diff --git a/javascript/src/date.js b/javascript/src/date.js index 9269658fc..4166365c6 100644 --- a/javascript/src/date.js +++ b/javascript/src/date.js @@ -3,8 +3,6 @@ * * We don't autogenerate this class because we want the constructor * to promote by pushing things through the server-side Date() function. - * - * @author gorelick@google.com (Noel Gorelick) */ goog.provide('ee.Date'); diff --git a/javascript/src/deserializer.js b/javascript/src/deserializer.js index 76d3ed1dd..605158094 100644 --- a/javascript/src/deserializer.js +++ b/javascript/src/deserializer.js @@ -1,7 +1,5 @@ /** * @fileoverview A deserializer that decodes EE object trees from JSON DAGs. - * - * @author maxus@google.com (Max Shawabkeh) */ goog.provide('ee.Deserializer'); diff --git a/javascript/src/dictionary.js b/javascript/src/dictionary.js index 4a0b43613..54702e3d6 100644 --- a/javascript/src/dictionary.js +++ b/javascript/src/dictionary.js @@ -1,6 +1,5 @@ /** * @fileoverview A wrapper for dicts. - * @author gorelick@google.com (Noel Gorelick) */ goog.provide('ee.Dictionary'); diff --git a/javascript/src/ee.js b/javascript/src/ee.js index 386f0312c..28f678157 100644 --- a/javascript/src/ee.js +++ b/javascript/src/ee.js @@ -1,6 +1,5 @@ /** * @fileoverview Initialization and convenience functions for the EE library. - * @author gorelick@google.com (Noel Gorelick) */ goog.provide('ee'); diff --git a/javascript/src/element.js b/javascript/src/element.js index 1728fa8cf..5dd736fe9 100644 --- a/javascript/src/element.js +++ b/javascript/src/element.js @@ -1,7 +1,6 @@ /** * @fileoverview Base class for Image, Feature and Collection. * This class is never intended to be instantiated by the user. - * @author gorelick@google.com (Noel Gorelick) */ goog.provide('ee.Element'); diff --git a/javascript/src/encodable.js b/javascript/src/encodable.js index 5acd85693..04c33c117 100644 --- a/javascript/src/encodable.js +++ b/javascript/src/encodable.js @@ -1,6 +1,5 @@ /** * @fileoverview An interface implemented by serializable objects. - * @author maxus@google.com (Max Shawabkeh) */ goog.provide('ee.Encodable'); diff --git a/javascript/src/feature.js b/javascript/src/feature.js index 0776585fd..4ff3e4c16 100644 --- a/javascript/src/feature.js +++ b/javascript/src/feature.js @@ -1,6 +1,5 @@ /** * @fileoverview An object representing EE Features. - * @author gorelick@google.com (Noel Gorelick) */ goog.provide('ee.Feature'); diff --git a/javascript/src/featurecollection.js b/javascript/src/featurecollection.js index fdb84604e..1bf0c0c4a 100644 --- a/javascript/src/featurecollection.js +++ b/javascript/src/featurecollection.js @@ -1,6 +1,5 @@ /** * @fileoverview Representation of an Earth Engine FeatureCollection. - * @author gorelick@google.com (Noel Gorelick) */ goog.provide('ee.FeatureCollection'); @@ -70,8 +69,8 @@ ee.FeatureCollection = function(args, opt_column) { actualArgs['geometryColumn'] = opt_column; } ee.FeatureCollection.base( - this, - 'constructor', + this, + 'constructor', new ee.ApiFunction('Collection.loadTable'), actualArgs); } else if (Array.isArray(args)) { // A list of features. diff --git a/javascript/src/filter.js b/javascript/src/filter.js index 6aa6ffdb7..be20ddbb6 100644 --- a/javascript/src/filter.js +++ b/javascript/src/filter.js @@ -1,6 +1,5 @@ /** * @fileoverview Collection filters. - * @author gorelick@google.com (Noel Gorelick) * * new Filter('time', low, high) * .bounds(ring) diff --git a/javascript/src/function.js b/javascript/src/function.js index ec163b611..3a91c6bb0 100644 --- a/javascript/src/function.js +++ b/javascript/src/function.js @@ -1,6 +1,5 @@ /** * @fileoverview A base class for EE Functions. - * @author maxus@google.com (Max Shawabkeh) */ goog.provide('ee.Function'); diff --git a/javascript/src/geometry.js b/javascript/src/geometry.js index 932039bd5..4ca66731d 100644 --- a/javascript/src/geometry.js +++ b/javascript/src/geometry.js @@ -1,6 +1,5 @@ /** * @fileoverview An object representing EE Geometries. - * @author maxus@google.com (Max Shawabkeh) */ goog.provide('ee.Geometry'); diff --git a/javascript/src/image.js b/javascript/src/image.js index 7c205d9e6..ab52eab5e 100644 --- a/javascript/src/image.js +++ b/javascript/src/image.js @@ -1,7 +1,7 @@ /** * @fileoverview A representation of an earth engine image. - * See: https://sites.google.com/site/earthengineapidocs for more details. - * @author gorelick@google.com (Noel Gorelick) + * See: https://developers.google.com/earth-engine/apidocs/ee-image for more + * details. */ goog.provide('ee.Image'); diff --git a/javascript/src/imagecollection.js b/javascript/src/imagecollection.js index e39be78ff..5fa6b50bb 100644 --- a/javascript/src/imagecollection.js +++ b/javascript/src/imagecollection.js @@ -1,6 +1,5 @@ /** * @fileoverview Javascript representation for an Earth Engine ImageCollection. - * @author gorelick@google.com (Noel Gorelick) */ goog.provide('ee.ImageCollection'); diff --git a/javascript/src/list.js b/javascript/src/list.js index 080219a17..4fac2d91b 100644 --- a/javascript/src/list.js +++ b/javascript/src/list.js @@ -1,6 +1,5 @@ /** * @fileoverview A wrapper for Lists. - * @author gorelick@google.com (Noel Gorelick) */ goog.provide('ee.List'); diff --git a/javascript/src/number.js b/javascript/src/number.js index a366db87a..d689c1c46 100644 --- a/javascript/src/number.js +++ b/javascript/src/number.js @@ -1,6 +1,5 @@ /** * @fileoverview A wrapper for numbers. - * @author gorelick@google.com (Noel Gorelick) */ goog.provide('ee.Number'); diff --git a/javascript/src/serializer.js b/javascript/src/serializer.js index 4f765a440..b30839ff2 100644 --- a/javascript/src/serializer.js +++ b/javascript/src/serializer.js @@ -1,7 +1,5 @@ /** * @fileoverview A serializer that encodes EE object trees as JSON DAGs. - * - * @author gorelick@google.com (Noel Gorelick) */ goog.provide('ee.Serializer'); diff --git a/javascript/src/string.js b/javascript/src/string.js index c798b1f2b..0fba3bbfe 100644 --- a/javascript/src/string.js +++ b/javascript/src/string.js @@ -1,6 +1,5 @@ /** * @fileoverview A wrapper for strings. - * @author gorelick@google.com (Noel Gorelick) */ goog.provide('ee.String'); diff --git a/javascript/src/terrain.js b/javascript/src/terrain.js index ec64aba70..f0757ca31 100755 --- a/javascript/src/terrain.js +++ b/javascript/src/terrain.js @@ -1,7 +1,6 @@ /** * @fileoverview A class to generate the ee.Terrain namespace. * - * @author gorelick@google.com (Noel Gorelick) * @suppress {useOfGoogProvide} */ diff --git a/javascript/src/types.js b/javascript/src/types.js index ca2b6f84f..7a33d4a05 100644 --- a/javascript/src/types.js +++ b/javascript/src/types.js @@ -1,6 +1,5 @@ /** * @fileoverview A set of utilities to work with EE types. - * @author maxus@google.com (Max Shawabkeh) */ goog.provide('ee.Types'); diff --git a/python/ee/__init__.py b/python/ee/__init__.py index b2d8e88af..c719863bb 100644 --- a/python/ee/__init__.py +++ b/python/ee/__init__.py @@ -1,7 +1,7 @@ #!/usr/bin/env python3 """The EE Python library.""" -__version__ = '0.1.369' +__version__ = '0.1.370' # Using lowercase function naming to match the JavaScript names. # pylint: disable=g-bad-name @@ -128,6 +128,7 @@ def Initialize( """ if credentials == 'persistent': credentials = data.get_persistent_credentials() + data.initialize( credentials=credentials, api_base_url=(opt_url + '/api' if opt_url else None), @@ -136,22 +137,25 @@ def Initialize( cloud_api_key=cloud_api_key, project=project, http_transport=http_transport) + # Initialize the dynamically loaded functions on the objects that want them. ApiFunction.initialize() + Collection.initialize() + Date.initialize() + Dictionary.initialize() Element.initialize() - Image.initialize() Feature.initialize() - Collection.initialize() - ImageCollection.initialize() FeatureCollection.initialize() Filter.initialize() Geometry.initialize() + Image.initialize() + ImageCollection.initialize() List.initialize() Number.initialize() String.initialize() - Date.initialize() - Dictionary.initialize() Terrain.initialize() + + # These must happen last. _InitializeGeneratedClasses() _InitializeUnboundMethods() @@ -159,21 +163,24 @@ def Initialize( def Reset(): """Reset the library. Useful for re-initializing to a different server.""" data.reset() + + # Must call reset on the base class before any of its derived classes. ApiFunction.reset() - Element.reset() - Image.reset() + Element.reset() # Must be before Collection. + Collection.reset() # Must be before FeatureCollection and ImageCollection. + Date.reset() + Dictionary.reset() Feature.reset() - Collection.reset() - ImageCollection.reset() FeatureCollection.reset() Filter.reset() Geometry.reset() + Image.reset() + ImageCollection.reset() List.reset() Number.reset() String.reset() - Date.reset() - Dictionary.reset() Terrain.reset() + _ResetGeneratedClasses() global Algorithms Algorithms = _AlgorithmsContainer() diff --git a/python/ee/apifunction.py b/python/ee/apifunction.py index 1460cc9d1..47e18487c 100644 --- a/python/ee/apifunction.py +++ b/python/ee/apifunction.py @@ -14,10 +14,12 @@ # Using lowercase function naming to match the JavaScript names. # pylint: disable=g-bad-name +from __future__ import annotations + import copy import keyword import re -from typing import Any, Dict, Optional, Type +from typing import Any, Dict, Optional, Set, Type from ee import computedobject from ee import data @@ -32,11 +34,11 @@ class ApiFunction(function.Function): _signature: Dict[str, Any] # A dictionary of functions defined by the API server. - _api = {} + _api: Dict[str, ApiFunction] = {} # A set of algorithm names containing all algorithms that have been bound to # a function so far using importApi(). - _bound_signatures = set() + _bound_signatures: Set[str] = set() def __init__(self, name: str, opt_signature: Optional[Dict[str, Any]] = None): """Creates a function defined by the EE API. @@ -53,7 +55,7 @@ def __init__(self, name: str, opt_signature: Optional[Dict[str, Any]] = None): self._signature = copy.deepcopy(opt_signature) self._signature['name'] = name - def __eq__(self, other): + def __eq__(self, other: Any) -> bool: return (isinstance(other, ApiFunction) and self.getSignature() == other.getSignature()) @@ -94,11 +96,11 @@ def apply_(cls, name: str, named_args: Dict[str, Any]) -> Any: """ return cls.lookup(name).apply(named_args) - def encode_invocation(self, encoder): + def encode_invocation(self, encoder: Any) -> Any: del encoder # Unused. return self._signature['name'] - def encode_cloud_invocation(self, encoder): + def encode_cloud_invocation(self, encoder: Any) -> Dict[str, Any]: del encoder # Unused. return {'functionName': self._signature['name']} @@ -120,7 +122,7 @@ def unboundFunctions(cls) -> Dict[str, Any]: return dict([(name, func) for name, func in cls._api.items() if name not in cls._bound_signatures]) - # TODO(user): Any -> 'ApiFunction' for the return type. + # TODO(user): Any -> ApiFunction for the return type. @classmethod def lookup(cls, name: str) -> Any: """Looks up an API function by name. @@ -139,7 +141,7 @@ def lookup(cls, name: str) -> Any: return result @classmethod - def lookupInternal(cls, name: str) -> Optional['ApiFunction']: + def lookupInternal(cls, name: str) -> Optional[ApiFunction]: """Looks up an API function by name. Args: @@ -212,7 +214,8 @@ def importApi( # Create a new function so we can attach properties to it. def MakeBoundFunction(func): # We need the lambda to capture "func" from the enclosing scope. - return lambda *args, **kwargs: func.call(*args, **kwargs) # pylint: disable=unnecessary-lambda + # pylint: disable-next=unnecessary-lambda + return lambda *args, **kwargs: func.call(*args, **kwargs) bound_function = MakeBoundFunction(api_func) # Add docs. diff --git a/python/ee/cli/commands.py b/python/ee/cli/commands.py index a60523e4f..f1d31dddb 100644 --- a/python/ee/cli/commands.py +++ b/python/ee/cli/commands.py @@ -17,7 +17,7 @@ import shutil import sys import tempfile -from typing import Any, Dict, List, Sequence, Tuple, Union +from typing import Any, Dict, Hashable, List, Optional, Sequence, Tuple, Type, Union import urllib.parse # Prevent TensorFlow from logging anything at the native level. @@ -291,7 +291,7 @@ def _decode_property(string: str) -> Tuple[str, Any]: return (name, value) -def _add_property_flags(parser): +def _add_property_flags(parser: argparse.ArgumentParser) -> None: """Adds command line flags related to metadata properties to a parser.""" parser.add_argument( '--property', '-p', @@ -310,7 +310,7 @@ def _add_property_flags(parser): type=_decode_date) -def _decode_property_flags(args): +def _decode_property_flags(args: argparse.Namespace) -> Dict[str, Any]: """Decodes metadata properties from args as a name->value dict.""" property_list = list(args.property or []) names = [name for name, _ in property_list] @@ -328,8 +328,8 @@ def _check_valid_files(filenames: Sequence[str]) -> None: raise ee.EEException('Invalid Cloud Storage URL: ' + filename) -def _pretty_print_json(json_obj): - """Pretty-prints a JSON object to stdandard output.""" +def _pretty_print_json(json_obj: Any) -> None: + """Pretty-prints a JSON object to standard output.""" print(json.dumps(json_obj, sort_keys=True, indent=2, separators=(',', ': '))) @@ -485,7 +485,9 @@ def run( self._apply_permissions(acl, permissions) ee.data.setAssetAcl(args.asset_id, json.dumps(acl)) - def _set_permission(self, permissions, grant, prefix): + def _set_permission( + self, permissions: Dict[str, str], grant: str, prefix: str + ) -> None: """Sets the permission for a given user/group.""" parts = grant.rsplit(':', 1) if len(parts) != 2 or parts[1] not in ['R', 'W']: @@ -500,7 +502,9 @@ def _set_permission(self, permissions, grant, prefix): raise ee.EEException('Cannot grant write permissions to all users.') permissions[prefixed_user] = role - def _remove_permission(self, permissions, user, prefix): + def _remove_permission( + self, permissions: Dict[str, str], user: str, prefix: str + ) -> None: """Removes permissions for a given user/group.""" prefixed_user = user if not self._is_all_users(user): @@ -509,7 +513,7 @@ def _remove_permission(self, permissions, user, prefix): raise ee.EEException('Multiple permission settings for "%s".' % user) permissions[prefixed_user] = 'D' - def _user_account_type(self, user): + def _user_account_type(self, user: str) -> str: """Returns the appropriate account type for a user email.""" # Here 'user' ends with ':R', ':W', or ':D', so we extract @@ -519,7 +523,7 @@ def _user_account_type(self, user): else: return 'user:' - def _parse_permissions(self, args): + def _parse_permissions(self, args: argparse.Namespace) -> Dict[str, str]: """Decodes and sanity-checks the permissions in the arguments.""" # A dictionary mapping from user ids to one of 'R', 'W', or 'D'. permissions = {} @@ -538,26 +542,33 @@ def _parse_permissions(self, args): self._remove_permission(permissions, group, 'group:') return permissions - def _apply_permissions(self, acl, permissions) -> None: + def _apply_permissions( + self, acl: Dict[str, Union[bool, List[str]]], permissions: Dict[str, str] + ) -> None: """Applies the given permission edits to the given acl.""" for user, role in permissions.items(): if self._is_all_users(user): acl[ALL_USERS_CAN_READ] = (role == 'R') - elif role == 'R': - if user not in acl[READERS]: - acl[READERS].append(user) - if user in acl[WRITERS]: - acl[WRITERS].remove(user) - elif role == 'W': - if user in acl[READERS]: - acl[READERS].remove(user) - if user not in acl[WRITERS]: - acl[WRITERS].append(user) - elif role == 'D': - if user in acl[READERS]: - acl[READERS].remove(user) - if user in acl[WRITERS]: - acl[WRITERS].remove(user) + else: + # Make pytype understand the types. + assert isinstance(acl[READERS], list) + assert isinstance(acl[WRITERS], list) + + if role == 'R': + if user not in acl[READERS]: + acl[READERS].append(user) + if user in acl[WRITERS]: + acl[WRITERS].remove(user) + elif role == 'W': + if user in acl[READERS]: + acl[READERS].remove(user) + if user not in acl[WRITERS]: + acl[WRITERS].append(user) + elif role == 'D': + if user in acl[READERS]: + acl[READERS].remove(user) + if user in acl[WRITERS]: + acl[WRITERS].remove(user) def _is_all_users(self, user: str) -> bool: """Determines if a user name represents the special "all users" entity.""" @@ -1305,14 +1316,13 @@ def run( manifest = self.manifest_from_args(args) _upload(args, manifest, ee.data.startIngestion) - def manifest_from_args(self, args): + def manifest_from_args(self, args: argparse.Namespace) -> Dict[str, Any]: """Constructs an upload manifest from the command-line flags.""" - def is_tf_record(path): - if any(path.lower().endswith(extension) - for extension in TF_RECORD_EXTENSIONS): - return True - return False + def is_tf_record(path: str) -> bool: + return any( + path.lower().endswith(extension) for extension in TF_RECORD_EXTENSIONS + ) if args.manifest: with open(args.manifest) as fh: @@ -1516,7 +1526,7 @@ def run( manifest = self.manifest_from_args(args) _upload(args, manifest, ee.data.startTableIngestion) - def manifest_from_args(self, args): + def manifest_from_args(self, args: argparse.Namespace) -> Any: """Constructs an upload manifest from the command-line flags.""" if args.manifest: diff --git a/python/ee/image.py b/python/ee/image.py index bf4d07b19..3303905c4 100644 --- a/python/ee/image.py +++ b/python/ee/image.py @@ -1,7 +1,8 @@ #!/usr/bin/env python3 """A representation of an Earth Engine image. -See: https://sites.google.com/site/earthengineapidocs for more details. +See: https://developers.google.com/earth-engine/apidocs/ee-image for more +details. """ import json diff --git a/python/ee/tests/algorithms.json b/python/ee/tests/algorithms.json index caa40c7ac..64f7d99ff 100644 --- a/python/ee/tests/algorithms.json +++ b/python/ee/tests/algorithms.json @@ -2997,7 +2997,7 @@ "arguments": [{ "argumentName": "metric", "type": "String", - "description": "The distance metric to use. Options are:\n \u0027euclidean\u0027 - euclidean distance from the unnormalized class mean.\n \u0027cosine\u0027 - spectral angle from the unnormalized class mean.\n \u0027mahalanobis\u0027 - Mahalanobis distance from the class mean.", + "description": "The distance metric to use. Options are:\n \u0027euclidean\u0027 - euclidean distance from the unnormalized class mean.\n \u0027cosine\u0027 - spectral angle from the unnormalized class mean.\n \u0027mahalanobis\u0027 - Mahalanobis distance from the class mean.\n \u0027manhattan\u0027 - Manhattan distance from the unnormalized class mean.", "optional": true, "defaultValue": "euclidean" }, { @@ -9134,6 +9134,37 @@ "optional": true, "defaultValue": "extrapolate" }] + }, { + "name": "algorithms/Image.linkCollection", + "description": "Links the source image to a matching image from an image collection.\nAny specified bands or metadata will be added to the source image from the image found in the collection, and if the bands or metadata are already present they will be overwritten. If a matching image is not found, any new or updated bands will be fully masked and any new or updated metadata will be null. The output footprint will be the same as the source image footprint.\nA match is determined if the source image and an image in the collection have a specific equivalent metadata property. If more than one collection image would match, the collection image selected is arbitrary. By default, images are matched on their \u0027system:index\u0027 metadata property.\nThis linking function is a convenience method for adding bands to a target image based on a specified shared metadata property and is intended to support linking collections that apply different processing/product generation to the same source imagery. For more expressive linking known as \u0027joining\u0027, see https://developers.google.com/earth-engine/guides/joins_intro.", + "returnType": "Image\u003cunknown bands\u003e", + "arguments": [{ + "argumentName": "input", + "type": "Image\u003cunknown bands\u003e", + "description": "The source image a matching image in the collection will be linked to." + }, { + "argumentName": "imageCollection", + "type": "ImageCollection", + "description": "The image collection searched to extract an image matching the source." + }, { + "argumentName": "linkedBands", + "type": "Object", + "description": "A band name or list of band names to add or update from the matching image.", + "optional": true, + "defaultValue": null + }, { + "argumentName": "linkedProperties", + "type": "Object", + "description": "A metadata property or list of properties to add or update from the matching image.", + "optional": true, + "defaultValue": null + }, { + "argumentName": "matchPropertyName", + "type": "String", + "description": "The metadata property name to use as a match criteria.", + "optional": true, + "defaultValue": "system:index" + }] }, { "name": "algorithms/Image.load", "description": "Returns the image given its ID.", diff --git a/python/ee/tests/date_test.py b/python/ee/tests/ee_date_test.py similarity index 99% rename from python/ee/tests/date_test.py rename to python/ee/tests/ee_date_test.py index 445483850..532250119 100644 --- a/python/ee/tests/date_test.py +++ b/python/ee/tests/ee_date_test.py @@ -9,6 +9,7 @@ class DateTest(apitestcase.ApiTestCase): + def testDate(self): """Verifies date constructors.""" diff --git a/python/ee/tests/list_test.py b/python/ee/tests/ee_list_test.py similarity index 100% rename from python/ee/tests/list_test.py rename to python/ee/tests/ee_list_test.py diff --git a/python/ee/tests/number_test.py b/python/ee/tests/ee_number_test.py similarity index 100% rename from python/ee/tests/number_test.py rename to python/ee/tests/ee_number_test.py diff --git a/python/ee/tests/string_test.py b/python/ee/tests/ee_string_test.py similarity index 100% rename from python/ee/tests/string_test.py rename to python/ee/tests/ee_string_test.py diff --git a/python/ee/tests/table_converter_test.py b/python/ee/tests/table_converter_test.py new file mode 100644 index 000000000..44ccc9c2f --- /dev/null +++ b/python/ee/tests/table_converter_test.py @@ -0,0 +1,110 @@ +#!/usr/bin/env python3 +"""Tests for the table_converter module.""" + +from typing import Any, Dict, Optional, Type + +import geopandas +from geopandas import testing +import pandas + +from ee import table_converter +import unittest +import parameterized + + +class TableConverterTest(parameterized.TestCase): + + def _make_feature( + self, geometry: Dict[str, Any], properties: Dict[str, Any] + ) -> Dict[str, Any]: + return {'type': 'Feature', 'geometry': geometry, 'properties': properties} + + @parameterized.named_parameters( + ('pandas', 'pandas', table_converter.PandasConverter), + ('geopandas', 'geopandas', table_converter.GeoPandasConverter), + ('mixed case', 'gEOPANdas', table_converter.GeoPandasConverter), + ('invalid', 'UNKNOWN', None), + ) + def test_from_file_format( + self, + data_format: str, + expected: Optional[Type[table_converter.TableConverter]], + ) -> None: + """Verifies `from_file_format` returns the correct converter class.""" + if expected is None: + self.assertIsNone(table_converter.from_file_format(data_format)) + else: + self.assertIsInstance( + table_converter.from_file_format(data_format), expected + ) + + def test_pandas_converter(self) -> None: + """Verifies `PandasConverter` does the correct conversion.""" + converter = table_converter.PandasConverter() + + dataframe = converter.do_conversion( + iter([ + self._make_feature( + geometry={'type': 'Point', 'coordinates': [0, 0]}, + properties={'colname': 'A', 'another-one': '10'}, + ), + self._make_feature( + geometry={'type': 'Point', 'coordinates': [1, 1]}, + properties={'colname': 'B'}, + ), + ]) + ) + pandas.testing.assert_frame_equal( + dataframe, + pandas.DataFrame([ + { + 'geo': {'type': 'Point', 'coordinates': [0, 0]}, + 'colname': 'A', + 'another-one': '10', + }, + { + 'geo': {'type': 'Point', 'coordinates': [1, 1]}, + 'colname': 'B', + }, + ]), + ) + + def test_geopandas_converter(self) -> None: + """Verifies `GeoPandasConverter` does the correct conversion.""" + converter = table_converter.GeoPandasConverter() + + dataframe = converter.do_conversion( + iter([ + self._make_feature( + geometry={'type': 'Point', 'coordinates': [0, 0]}, + properties={'colname': 'A', 'another-one': '10'}, + ), + self._make_feature( + geometry={'type': 'Point', 'coordinates': [1, 1]}, + properties={'colname': 'B'}, + ), + ]) + ) + + feature_coll = { + 'type': 'FeatureCollection', + 'features': [ + self._make_feature( + geometry={'type': 'Point', 'coordinates': [0, 0]}, + properties={'colname': 'A', 'another-one': '10'}, + ), + self._make_feature( + geometry={'type': 'Point', 'coordinates': [1, 1]}, + properties={'colname': 'B'}, + ), + ], + 'bbox': (1.0, 1.0, 2.0, 2.0), + } + testing.assert_geodataframe_equal( + dataframe, + geopandas.GeoDataFrame.from_features(feature_coll), + ) + + +if __name__ == '__main__': + unittest.main() diff --git a/python/examples/ipynb/Earth_Engine_REST_API_Quickstart.ipynb b/python/examples/ipynb/Earth_Engine_REST_API_Quickstart.ipynb deleted file mode 100644 index 77bb29f49..000000000 --- a/python/examples/ipynb/Earth_Engine_REST_API_Quickstart.ipynb +++ /dev/null @@ -1 +0,0 @@ -{"nbformat":4,"nbformat_minor":0,"metadata":{"colab":{"name":"Earth_Engine_REST_API_Quickstart.ipynb","provenance":[]},"kernelspec":{"name":"python3","display_name":"Python 3"}},"cells":[{"cell_type":"markdown","metadata":{"id":"pr1eEWIUjiBc","colab_type":"text"},"source":["# Earth Engine REST API Quickstart\n","\n","This is a demonstration notebook for using the Earth Engine REST API. See the complete guide for more information: https://developers.google.com/earth-engine/reference/Quickstart.\n"]},{"cell_type":"markdown","metadata":{"id":"OfMAA6YhPuFl","colab_type":"text"},"source":["## Authentication\n","\n","The first step is to choose a project and login to Google Cloud."]},{"cell_type":"code","metadata":{"id":"FRm2HczTIlKe","colab_type":"code","colab":{}},"source":["# INSERT YOUR PROJECT HERE\n","PROJECT = 'your-project'\n","!gcloud auth login --project {PROJECT}"],"execution_count":0,"outputs":[]},{"cell_type":"markdown","metadata":{"id":"hnufOtSfP0jX","colab_type":"text"},"source":["## Define service account credentials"]},{"cell_type":"code","metadata":{"id":"tLxOnKL2Nk5p","colab_type":"code","colab":{}},"source":["# INSERT YOUR SERVICE ACCOUNT HERE\n","SERVICE_ACCOUNT='your-service-account@your-project.iam.gserviceaccount.com'\n","KEY = 'private-key.json'\n","\n","!gcloud iam service-accounts keys create {KEY} --iam-account {SERVICE_ACCOUNT}"],"execution_count":0,"outputs":[]},{"cell_type":"markdown","metadata":{"id":"6QksNfvaY5em","colab_type":"text"},"source":["## Create an authorized session to make HTTP requests"]},{"cell_type":"code","metadata":{"id":"h2MHcyeqLufx","colab_type":"code","colab":{}},"source":["from google.auth.transport.requests import AuthorizedSession\n","from google.oauth2 import service_account\n","\n","credentials = service_account.Credentials.from_service_account_file(KEY)\n","scoped_credentials = credentials.with_scopes(\n"," ['https://www.googleapis.com/auth/cloud-platform'])\n","\n","session = AuthorizedSession(scoped_credentials)\n","\n","url = 'https://earthengine.googleapis.com/v1alpha/projects/earthengine-public/assets/LANDSAT'\n","\n","response = session.get(url)\n","\n","from pprint import pprint\n","import json\n","pprint(json.loads(response.content))\n"],"execution_count":0,"outputs":[]},{"cell_type":"markdown","metadata":{"id":"_KjWa7KJY_7m","colab_type":"text"},"source":["## Get a list of images at a point"]},{"cell_type":"markdown","metadata":{"id":"5kKbIDctpZeH","colab_type":"text"},"source":["Query for Sentinel-2 images at a specific location, in a specific time range and with estimated cloud cover less than 10%."]},{"cell_type":"code","metadata":{"id":"0bENTPjMQr5h","colab_type":"code","colab":{}},"source":["import urllib\n","\n","coords = [-122.085, 37.422]\n","\n","project = 'projects/earthengine-public'\n","asset_id = 'COPERNICUS/S2'\n","name = '{}/assets/{}'.format(project, asset_id)\n","url = 'https://earthengine.googleapis.com/v1alpha/{}:listImages?{}'.format(\n"," name, urllib.parse.urlencode({\n"," 'startTime': '2017-04-01T00:00:00.000Z',\n"," 'endTime': '2017-05-01T00:00:00.000Z',\n"," 'region': '{\"type\":\"Point\", \"coordinates\":' + str(coords) + '}',\n"," 'filter': 'CLOUDY_PIXEL_PERCENTAGE < 10',\n","}))\n","\n","response = session.get(url)\n","content = response.content\n","\n","for asset in json.loads(content)['images']:\n"," id = asset['id']\n"," cloud_cover = asset['properties']['CLOUDY_PIXEL_PERCENTAGE']\n"," print('%s : %s' % (id, cloud_cover))"],"execution_count":0,"outputs":[]},{"cell_type":"markdown","metadata":{"id":"DY0MfkjiAAW_","colab_type":"text"},"source":["## Inspect an image\n","\n","Get the asset name from the previous output and request its metadata."]},{"cell_type":"code","metadata":{"id":"ddzrXIl4ADLk","colab_type":"code","colab":{}},"source":["asset_id = 'COPERNICUS/S2/20170430T190351_20170430T190351_T10SEG'\n","name = '{}/assets/{}'.format(project, asset_id)\n","url = 'https://earthengine.googleapis.com/v1alpha/{}'.format(name)\n","\n","response = session.get(url)\n","content = response.content\n","\n","asset = json.loads(content)\n","print('Band Names: %s' % ','.join(band['id'] for band in asset['bands']))\n","print('First Band: %s' % json.dumps(asset['bands'][0], indent=2, sort_keys=True))"],"execution_count":0,"outputs":[]},{"cell_type":"markdown","metadata":{"id":"O5I63cC6ZDQn","colab_type":"text"},"source":["## Get pixels from one of the images"]},{"cell_type":"code","metadata":{"id":"xJhv6bfEZHa2","colab_type":"code","colab":{}},"source":["import numpy\n","import io\n","\n","name = '{}/assets/{}'.format(project, asset_id)\n","url = 'https://earthengine.googleapis.com/v1alpha/{}:getPixels'.format(name)\n","body = json.dumps({\n"," 'fileFormat': 'NPY',\n"," 'bandIds': ['B2', 'B3', 'B4', 'B8'],\n"," 'grid': {\n"," 'affineTransform': {\n"," 'scaleX': 10,\n"," 'scaleY': -10,\n"," 'translateX': 499980,\n"," 'translateY': 4200000,\n"," },\n"," 'dimensions': {'width': 256, 'height': 256},\n"," },\n","})\n","\n","pixels_response = session.post(url, body)\n","pixels_content = pixels_response.content\n","\n","array = numpy.load(io.BytesIO(pixels_content))\n","print('Shape: %s' % (array.shape,))\n","print('Data:')\n","print(array)"],"execution_count":0,"outputs":[]},{"cell_type":"markdown","metadata":{"id":"jcwE2W8kFojo","colab_type":"text"},"source":["## Get a thumbnail of an image\n","\n","Note that `name` and `asset` are already defined from the request to get the asset metadata. "]},{"cell_type":"code","metadata":{"id":"xs0ZHHKmFovV","colab_type":"code","colab":{}},"source":["url = 'https://earthengine.googleapis.com/v1alpha/{}:getPixels'.format(name)\n","body = json.dumps({\n"," 'fileFormat': 'PNG',\n"," 'bandIds': ['B4', 'B3', 'B2'],\n"," 'region': asset['geometry'],\n"," 'grid': {\n"," 'dimensions': {'width': 256, 'height': 256},\n"," },\n"," 'visualizationOptions': {\n"," 'ranges': [{'min': 0, 'max': 3000}],\n"," },\n","})\n","\n","image_response = session.post(url, body)\n","image_content = image_response.content\n","\n","# Import the Image function from the IPython.display module. \n","from IPython.display import Image\n","Image(image_content)"],"execution_count":0,"outputs":[]}]} \ No newline at end of file