Is there a limit to plotting markers with folium? - python

I'm plotting the missions ran by the USAF on North Korea during the Korean War.
The following is the map with 2800 plots.
I have a total of about 7500 plots, but whenever I try to plot above 2800 a blank map renders. I'm rendering on a pc laptop. Would it render if I use a desktop? Or is this a limit with folium?
I'm not speculating that it's an issue with the data. I'll share the coordinates data in case someone would like to explore it: link to public excel sheet.

As #Bob Haffner suggested you can use FastMarkerCluster from Folium library.
Here is my code, in my file there is ~500K points.
import pandas as pd
import json
from folium.plugins import FastMarkerCluster
rome_lat, rome_lng = 41.9028, 12.4964
with open("file_name.json", 'r') as f:
# create a new DataFrame
samples = pd.DataFrame(json.loads(f.read()))
# init the folium map object
my_map = folium.Map(location=[rome_lat, rome_lng], zoom_start=5)
# add all the point from the file to the map object using FastMarkerCluster
my_map.add_child(FastMarkerCluster(samples[['latitude', 'longitude']].values.tolist()))
# save the map
my_map.save("save_file.html")
This code takes ~10ms to render the map.
For more details example please follow this link:
FastMarkerCluster example
Hope this is helpful.

Another option is that we can add a specific number of markers(let's say 3000 markers) on a layer, using folium.map.FeatureGroup() function that will add 3000 markers on a single layer, and we can add that layer to the map using add_child() function, which reduces the number of layers on the map. I got the result for 20,000 Markers and 3000 line string. And is able to load within 40-45 seconds.

Related

How to extract a profile of value from a raster along a given line?

How to extract a profile of values from a raster along a given shapefile line in Python?
I am struggling finding a method to extract a profile of values (e.g. topographic profile) from a raster (geotiff). The library Rasterio has a method to clip/extract value from a raster based on a polygon, but I cannot find an equivalent method for a line shapefile.
There is a basic method with scipy, but it does not inherently conserve geographic information like a method based on higher level toolbox like rasterio could provide.
In other words, I am looking for an equivalent in Python of what the tool Terrain Profile in QGIS offers.
Thanks
This is a bit different than extracting for a polygon, as you want to sample every pixel touched by the line, in the order they are touched (the polygon approaches don't care about pixel order).
It looks like it would be possible to adapt this approach to use rasterio instead. Given a line read from a shapefile using geopandas or fiona as a shapely object, you use the endpoints to derive a new equidistant projection that you use as dst_crs in a WarpedVRT and read pixel values from that. It looks like you would need to calculate the length of your line in terms of the number of pixels you want sampled, this is the width parameter of the WarpedVRT.
This approach may need to be adapted further if your line is not an approximately straight line between the endpoints.
If you want to just get the raw pixel values under the line, you should be able to use a mask in rasterio or rasterize directly, for each line. You may want to use the all_touched=True in the case of lines.
I had a similar problem and found a solution which works for me. The solution uses shapely to sample points on a line/lines and then accesses respective values from the GeoTiff, therefore the extracted profile follows the direction of the line. Here is the method that I ended up with:
def extract_along_line(xarr, line, n_samples=256):
profile = []
for i in range(n_samples):
# get next point on the line
point = line.interpolate(i / n_samples - 1., normalized=True)
# access the nearest pixel in the xarray
value = xarr.sel(x=point.x, y=point.y, method="nearest").data
profile.append(value)
return profile
Here is a working example with data from the copernicus-dem database and the line is the diagonal of the received tile:
import rioxarray
import shapely.geometry
import matplotlib.pyplot as plt
sample_tif = ('https://elevationeuwest.blob.core.windows.net/copernicus-dem/'
'COP30_hh/Copernicus_DSM_COG_10_N35_00_E138_00_DEM.tif')
# Load xarray
tile = rioxarray.open_rasterio(sample_tif).squeeze()
# create a line (here its the diagonal of tile)
line = shapely.geometry.MultiLineString([[
[tile.x[-1],tile.y[-1]],
[tile.x[0], tile.y[0]]]])
# use the method from above to extract the profile
profile = extract_along_line(tile, line)
plt.plot(profile)
plt.show()

How to load GeoJson file properly?

I have a geojson file of Moscow districts that is avaliable at
http://gis-lab.info/data/mos-adm/mo.geojson
So, I can't load it properly.
These ideas does not help:
GeoJSON data not displaying in Python folium map
GeoJson usage in folium
I tried to create a map and then add a layer on it.
import folium
m = folium.Map(location = [55.7522200,37.6156000], zoom_start_13)
folium.GeoJson(open('mo.geojson')).add_to(m)'
this does not work
Try folium.GeoJson(open('mo.geojson').read()).add_to(m)
This reads the contents of the file and passes the string to folium.

Embedding Google Earth with Python

Is there a way to embed Google Earth or Google Earth Engine in a Python desktop application?
As of now, I've created a kml file with longitude/latitude data that can be manually dropped into Google Earth Pro to trace the path of the GPS.
I've seen a lot of forum posts where Google Earth was embedded in webpages but not desktop applications so I was wondering if it could be done.
Any suggestions would be appreciated
Yes, you can add Google Earth Engine results to a desktop application as long as it supports WMS tile layers, images, or graphs.
Here are some examples assuming your have already gone through these preprocesing steps:
import ee
ee.Initialize() # note: may have initialize with a service account within an application
# ee Image object of the Global SRTM data
img = ee.Image("USGS/SRTMGL1_003")
Get WMS tiles:
# get map tile id and token with specific color palette
# arguments into "getMapId" are the same as the JavaScript API "Map.addLayer"
result = img.getMapId({'min': 0, 'max': 3000})
url = "https://earthengine.googleapis.com/map/{mapid}/{{z}}/{{x}}/{{y}}?token={token}"
tiles = url.format(**result)
print(tiles)
# visualize in your favorite application that supports WMS
Get static Image:
# Generate a URL that displays a static Image from Global DEM
url = img.getThumbUrl({'min':0, 'max':3000})
# create a file-like object from the url
import urllib2
f = urllib2.ulropen(url)
# Display the image using matplotlib
import matplotlib.pyplot as plt
result = plt.imread(f)
plt.imshow(result)
plt.show()
Displaying a time series graph may be a little more involved:
# get a collection with time series
collection = ee.ImageCollection('MODIS/006/MOD11A2')\
.filterDate('2016-01-01','2018-01-01')
# create a geometry of area to show time series
atl = ee.Geometry.Point([-84.3880,33.7490])
# get a time series over the point
result = collection.select('LST_Day_1km').getRegion(atl,1000).getInfo()
# turn the result into a pandas dataframe and manipulate results for plotting
import pandas as pd
df = pd.DataFrame(result[1:])
df.columns = result[0]
# convert epoch time to a format for pandas
dates = [pd.Timestamp(t*1000000) for t in df.time]
# make new pandas series object with scaled LST values
ts = pd.Series(np.array(df.LST_Day_1km)*0.02-273.15,index=dates,name='lst')
ts.index.name = 'Date'
# finally display results
ts.plot()
There are probably more efficient ways to get the results and display in an application, however, this may be a way to get you started.
Two second google search found this! So in answer to your question, yes you can use Google Earth in Python
https://developers.google.com/earth-engine/python_install

Python SAC plot w/ grid

I'm required to use the information from a .sac file and plot it against a grid. I know that using various ObsPy functions one is able to plot the Seismograms using st.plot() but I can't seem to get it against a grid. I've also tried following the example given here "How do I draw a grid onto a plot in Python?" but have trouble when trying to configure my x axis to use UTCDatetime. I'm new to python and programming of this sort so any advice / help would be greatly appreciated.
Various resources used:
"http://docs.obspy.org/tutorial/code_snippets/reading_seismograms.html"
"http://docs.obspy.org/packages/autogen/obspy.core.stream.Stream.plot.html#obspy.core.stream.Stream.plot"
The Stream's plot() method actually automatically generates a grid, e.g. if you take the default example and plot it via:
from obspy.core import read
st = read() # without filename an example file is loaded
tr = st[0] # we will use only the first channel
tr.plot()
You may want to play with the number_of_ticks, tick_format and tick_rotationparameters as pointed out in http://docs.obspy.org/packages/autogen/obspy.core.stream.Stream.plot.html.
However if you want more control you can pass a matplotlib figure as input parameter to the plot() method:
from obspy.core import read
import matplotlib.pyplot as plt
fig = plt.figure()
st = read('/path/to/file.sac')
st.plot(fig=fig)
# at this point do whatever you want with your figure, e.g.
fig.gca().set_axis_off()
# finally display your figure
fig.show()
Hope it helps.

How to draw a png-osm-map with coordinates

I want to create a map with several given points in Python. For this I want to use Basemap from matplotlib. It works well, but I don't know how to get a proper background map.
How can I import an OSM map? Or should I use a different mapping package? I just want to create a raster map and save it as png.
This not my solution; I have pasted it from the question because the asker doesn't have enough reputation to answer his own question.
I found a solution:
Using imshow within Basemap includes an png into the plot as
background image. To obtain the right background image, I used the
export feature of OSM with boundaries taken from the Basemap
constructor:
m = Basemap(llcrnrlon=7.4319, urcrnrlat=52.0632, urcrnrlon=7.848, llcrnrlat=51.8495,
resolution='h', projection='merc')
im = plt.imread('background.png')
m.imshow(im, interpolation='lanczos', origin='upper')
I found some accessible basemap imagery from NASA GIBS tileserver. You might be able to use the same method for other tileservers.
http://earthdata.nasa.gov/wiki/main/index.php/GIBS_Supported_Clients#Script-level_access_to_imagery
Thi Uses GDAL's gdal_translate in a python subshell:
import subprocess
import matplotlib.pyplot
import mpl_toolkits.basemap
l,u,r,d=(7.4319,52.0632,7.848,51.8495)
subprocess.call ('gdal_translate -of GTiff -outsize 400 400 -projwin {l} {u} {r} {d} TERRA.xml Background.tif'.format(l=l,u=u,r=r,d=d),shell=True )
im=matplotlib.pyplot.imread('Background.tif')
m = mpl_toolkits.basemap.Basemap(llcrnrlon=l, urcrnrlat=u, urcrnrlon=r, llcrnrlat=d,
resolution='h', projection='merc')
m.imshow(im, interpolation='lanczos', origin='upper')
matplotlib.pyplot.show()
This needs the TERRA.xml file from the above link, though you can inline the XML as well.

Categories