How do I map the count of images in a ImageCollection in GEE? - gis

I want to replicate the following image, which pixel-wise tells (look at the legend) how many images are available in a ee.ImageCollection.
https://i.stack.imgur.com/BgoMR.png [1]
I thank you for any help in advance!
References:
[1] Masoud Mahdianpari, Bahram Salehi, Fariba Mohammadimanesh,
Brian Brisco, Saeid Homayouni, Eric Gill, Evan R. DeLancey & Laura Bourgeau-Chavez
(2020) Big Data for a Big Country: The First Generation of Canadian Wetland Inventory Map
at a Spatial Resolution of 10-m Using Sentinel-1 and Sentinel-2 Data on the Google Earth
Engine Cloud Computing Platform, Canadian Journal of Remote Sensing, 46:1, 15-33, DOI:
10.1080/07038992.2019.1711366[enter image description here]

If you use geemap Python package you can use geemap.image_count function and Map.add_colorbar method to add a colorbar. If you use JavaScript code editor you could use the code below which is derived and modified from geemap repo and you could check this out for adding a colorbar:
// Acquire Sentinel-2 Image Collection
var collection = ee.ImageCollection('COPERNICUS/S2_SR_HARMONIZED')
// Get one band's name
var band = collection.first().bandNames().get(0)
// Generate desired image where each pixel value represents the number of Images in the Image Collection
var image = collection.filterBounds(geometry)
.filterDate('2017-01-01', '2020-04-15')
.filter(ee.Filter.listContains("system:band_names", band))
.select([band])
.reduce(ee.Reducer.count())
.clip(geometry)
var vis = {"min":0,"max":900,"palette":["00FFFF","0000FF"]}
Map.addLayer(image, vis, 'NDWI')

Related

Temporal Analysis using SoilGrids -GEE

SoilGrids provides the mapping of different properties of soil. I have executed their sample code on Google Earth Engine and it's working fine:
var sand_mean = ee.Image('projects/soilgrids-isric/sand_mean')
//print example image metadata and description
print(sand_mean)
//Add all layer to Map
Map.addLayer(sand_mean.select('sand_0-5cm_mean'),{min: 50, max: 1000,palette: ['5d5851','635a4b','6a5b44','715c3d','785e36','7e5f30','856129','8c6222','92641c','996515','a0660e','a66808','ad6901']},'SoilGrids250m 2.0 - Sand content ISRIC_0_5cm')
//Set basemap to Hybrid view
Map.setOptions('HYBRID')
But my question is can we do temporal analysis using soilGrids? I can't find filterDate property. So, is it possible to see the change in the subsequent years (temporal analysis)?

Prepping geodata for interactive geo viz using Bokeh - slow to JSON

I'm trying to create a geo viz using this data which maps out all of the zip codes in NYC: https://data.cityofnewyork.us/Health/Modified-Zip-Code-Tabulation-Areas-MODZCTA-Map/5fzm-kpwv. I've used geopandas to read the data as a geodataframe, used shapely.wkt - loads on the multipoloygon, & set the appropriate column as the geometry.
I then uploaded this tree census data (https://data.cityofnewyork.us/Environment/2015-Street-Tree-Census-Tree-Data/uvpi-gqnh) into a df and merged the two on the zipcode column (I renamed cols myself as datasets used different terms).
My goal is to create an interactive geo viz using Bokeh, which I understand uses GEOJson. I've used the following code to achieve: JNB screenshot of code
However, it is taking an exceedingly long time to run the code:
nyc_trees = json.loads(nyc_trees.to_json())
I've tried ujson as well, but it hasn't helped with the timing. Is there a way to speed this up or another work around?

Latitude/Longitude Generation to be used as sample data

I am writing a demo web application that tracks multiple devices through my companies platform. I have the app working, but need a csv file that will simulate devices moving on a map as if they were a tracker attached to a car. The simulator works by reading 1 row of data every second (1 lat/lng point). Here is an example of the first few lines of a file that would work if the points weren't scattered across the US (the SclId is the device name).
SclId Latitude Longitude
HAT-0 44.968046 -94.420307
HAT-1 44.33328 -89.132008
HAT-2 33.755787 -116.359998
HAT-3 33.844843 -116.54911
HAT-4 44.92057 -93.44786
HAT-5 44.240309 -91.493619
HAT-0 44.968041 -94.419696
HAT-1 44.333304 -89.132027
HAT-2 33.755783 -116.360066
HAT-3 33.844847 -116.549069
HAT-4 44.920474 -93.447851
HAT-5 44.240304 -91.493768
If I had something that could create simulation data with mouse clicks it would save me a lot of time creating another program requiring me to drive around with a device and record the data to a CSV. Any help/recommendations would be greatly appreciated. If you don't understand the question please ask for clarification!
There is a website that I use to draw waypoint and download it as any format e.g., GPX, KML, JSON, CSV, etc.
https://www.alltrails.com/explore/map/map-e727fa5--12

Google maps web services/JavaScript API - problems with the bounding boxes

I need to get a decent bounding box for any given city. As of now, I know of no way to do it, but through the google maps API geocode function. However, there are problems.
For instance, consider Abu Dhabi.
Here is the code (using python googlemaps package):
>>> d = gmaps.geocode('Abu Dhabi, AE')
>>> pp.pprint(d)
{ u'Placemark': [ { u'AddressDetails': { u'Accuracy': 4,
u'Country': { u'AdministrativeArea': { u'AdministrativeAreaName': u'Abu Dhabi',
u'Locality': { u'LocalityName': u'Abu Dhabi'}},
u'CountryName': u'United Arab Emirates',
u'CountryNameCode': u'AE'}},
u'ExtendedData': { u'LatLonBox': { u'east': 54.8789043,
u'north': 24.7912388,
u'south': 24.1412558,
u'west': 53.8544291}},
u'Point': { u'coordinates': [54.3666667, 24.4666667, 0]},
u'address': u'Abu Dhabi - United Arab Emirates',
u'id': u'p1'}],
u'Status': { u'code': 200, u'request': u'geocode'},
u'name': u'Abu Dhabi, AE'}
The problem is that the returned LatLonBox is way too large - its diagonal is more than 126km long. With all due respect to Abu Dhabi, I do not think the city is that big.
Interestingly enough, the JavaScript API returns two boxes. Assuming results is the result of invoking google.maps.Geocoder.geocode on 'Abu Dhabi', we have two boxes:
results[0].geometry.bounds = ((24.1776, 54.30012), (24.5413, 54.7751))
results[0].geometry.viewport = ((24.1413, 53.8544), (24.7912, 54.8789))
Where the viewport is exactly the LatLonBox returned by the web services API. The bounds, on the other hand, looks much better both in terms of the size and the location - the below image depicts both boxes:
At first, I have suspected the python package to omit the bounds from the final result, but examining the json returned by the google maps web service reveals that no bounds box is returned by the web service - the python dictionary describing the result is an exact mirror of the returned json.
So, my question is how can I get a decent bounding box when using the web services API? Or is there an alternative API altogether? Does anyone have any experience with a non google maps API to get this kind of information?
Thanks.
EDIT
Another interesting twist. While some cities have huge bounding (or viewport) boxes, some have tiny ones. For instance, the diameter of one bounding Adelaide, AU is only 7km, which is, of course, too small:
You can use MySQL in the back-end and its Extensions for Spatial Data.
Envelope(g)
Returns the minimum bounding rectangle (MBR) for the geometry value g.
The result is returned as a Polygon value.
We used MySQL5.6 in a Geo search project and never looked back. Just make sure that you use MySQL 5.6 or higher for full Geo support.

How To Find Quad/Name/Scale From USGS Terra Server

I'm currently working on developing a Google Maps API implementation that overlays topographic data from USGS Terra Server. I think I have it pretty much under hand except that I can't figure out how to determine the name of the quad, name, & scale for the current tile being served from Terra Server. If you check out this site and zoom into the map that information is being displayed so it must be possible:
http://www.trails.com/topomap.aspx?trailid=fgu003-087
Here are links to some articles which explains more how the images are named by Terra Server:
About MSR Maps
STANDARDIZED DATA SET NAMES FOR DRG PRODUCTS
I'm hoping that some geoloc expert out there has already done this and can point me in the right direction. I'd appreciate if you could give me any clues how I might determine this information from the current map view when overlaying the USGS topo data over Google Maps to produce a user experience much like that of the example map about.
Thanks in advance for your help!
You can use the OGC Style Web Map Server Microsoft also hosts. These have a relatively simple lat/lon/scale structure for fetching data, rather than leaving you guessing about the numbers. Here is a url for Aerial. The Scale variable s ranges from 11-21. The t variable lets you choose between Aerial and Topos. Set t=2 for Topos - here is Topo URL.
To get the quad name and map reference etc. You will have to index the topos and build a database. If you have the Topos on a CD and they are in Tiff format you can use GDALTindex to build this index. Beyond this your queries reduce to Point-in-Polygon type, which you can perform using Net Topology Suite.
Since there is no simple intuitive mapping for all the different map-sets and scales, a precomputed index will be the best way to go.
Gdaltindex can index tif files and produce an index in Shapefile format. This can be mapped into MySQL Geometries using Ogr MySQL support.
In the example, the trails.com server is delivering the custom tile images through their own CDN and displaying those tiles over top of Google Maps using a .NET WebHandler.
Since you need the data to come from MSRMaps.com and not [Trails.com][3], you will point the MSRMaps.com WebHandler instead.
Below is how trails is doing it. Replace the getTileUrl function with something that makes a call to the msrmaps.com server instead, such as MSR Tile Link
var layer = new GTileLayer(new GCopyrightCollection(''), 1, 21);
layer.getTileUrl = function(a, b)
{
var ll = G_NORMAL_MAP.getProjection().fromPixelToLatLng(new GPoint(a.x * 256, (a.y + 1) * 256), b);
var ur = G_NORMAL_MAP.getProjection().fromPixelToLatLng(new GPoint((a.x + 1) * 256, a.y * 256), b);
return "http://cdn-www.trails.com/services/TopoGetGoogleMapTile.ashx?z=" + b + "&style=drgsr&ll=" + ll.y + "," + ll.x + "&ur=" + ur.y + "," + ur.x;
}
var map = new GMap2(document.getElementById("map"));
map.setCenter(new GLatLng(37.4419, -122.1419), 13);
map.setUIToDefault();
var mapType = new GMapType([layer], G_NORMAL_MAP.getProjection(), 'Trails', { errorMessage: google.mapError, textColor: "white", linkColor: "white" });
map.addMapType(mapType);
map.setMapType(mapType);