how to generate a heatmap in ipyleaflet - leaflet

I have multiple coordinates (latitude and longitude) and I would like to create a heatmap. I have checked all the documentation online and examples and cannot find anything which helps my to create a heatmap on an ipyleaflet map.
Please could someone advise how I generate and add a heatmap layer onto an ipyleaflet map.
I am working inside a jupyter notebook.
Thanks

Since the last version of ipyleaflet it is now possible to create a HeatMap:
from ipyleaflet import Map, Heatmap
from random import uniform
m = Map(center=[0, 0], zoom=2)
locations = [
[uniform(-80, 80), uniform(-180, 180), uniform(0, 1000)] # lat, lng, intensity
for i in range(1000)
]
heat = Heatmap(locations=locations, radius=20, blur=10)
m.add_layer(heat)
# Change some attributes of the heatmap
heat.radius = 30
heat.blur = 50
heat.max = 0.5
heat.gradient = {0.4: 'red', 0.6: 'yellow', 0.7: 'lime', 0.8: 'cyan', 1.0: 'blue'}
m

Related

How can I fit a circle (ideally an ellipse) to latitude/longitude scatter points in Cartopy?

I simply want a best-fitting ellipse or circle for scatter data I have. I have been able to fit a circle to the data using numerous packages, but then the results are clearly nonsense. Maybe I need to do something weird to get results that work (a) for lat/lon data and (b) with Cartopy projections?
I have the following array of longitude/latitude values:
coords = np.array([-153.1906979 , 62.01707771],
[ 13.05660412, 63.15537447],
[-175.82610203, 67.11698477],
[ -10.31730643, 61.74562855],
[ 168.02402748, 79.60818152],
[ -34.46162907, 65.10894426],
[ -57.20962503, 59.49626998],
[ 113.70202771, 68.22239091],
[ -80.43411993, 55.6654176 ],
[ 93.77252509, 76.19392633],
[-104.10892084, 56.68264351],
[ 66.36158188, 67.59664968],
[-127.75176924, 57.31577071],
[-151.83057714, 61.64142205],
[ 17.44848859, 56.02194986],
[-176.30087703, 66.5955554 ],
[ -5.48747931, 61.95844561],
[ 160.22917767, 66.07650153],
[ -27.93440014, 67.82152994],
[ 137.09393573, 63.71148003],
[ -53.3290508 , 55.79699915],
[ 109.42329666, 75.43090294],
[ -76.59105583, 59.18143738],
[ 89.94733587, 63.50658353],
[-100.54585734, 55.16704225],
[ 66.15810397, 64.64851675],
[-123.65415058, 60.14507524],
[ 41.00262656, 70.67714209],
[-145.66917977, 68.55315102],
[ 18.34306395, 67.62222778])
I plot them on a map as following:
fig = plt.figure(figsize=(20,20))
ax = fig.add_subplot(121,projection=ccrs.NearsidePerspective(central_longitude=0, central_latitude=90,
satellite_height=30785831))
ax.add_feature(cfeature.NaturalEarthFeature('physical', 'ocean', '50m', facecolor='#daf7f7', alpha=0.7, zorder=0))
ax.add_feature(cfeature.NaturalEarthFeature('physical', 'land', '50m', facecolor='#ebc7a4', edgecolor='black', alpha=0.7,zorder=0))
ax.set_global()
grid = ax.gridlines(draw_labels=True)
grid.xlabel_style = {'size': 20, 'color': 'black'}
grid.ylabel_style = {'size': 20, 'color': 'black'}
ax.scatter(coords[0:,0], coords[0:,1], c='red', s=40, zorder=1, transform=PlateCarree())
I get this plot
All I now want to do is fit an ellipse or a circle to this scatter data. Using the solution here: https://stackoverflow.com/a/52877062/17583970, I cannot even try plot anything because the b axis of the ellipse is just a nan. Using skg.nsphere_fit() gave a radius of 433, which is obviously wrong or needs transforming in some way.
Any help would be greatly appreciated.
The coordinates you use really matter in this case. Any fitting will use some sort of distance metric that's being minimized, and the distance in lat/lon coordinates doesn't reflect something in meters or miles at all:
https://en.wikipedia.org/wiki/Geodesics_on_an_ellipsoid
If you're willing to assume that your map projection is a reasonable distance metric you can simply transform the coordinates, and perform the fit on those. I suspect that in this case the fit will be slightly biassed towards the pole (center of the map), making the ellipse a little smaller than it would be when fitted using the actual distance on the earths surface.
Using Cartopy to define the projections of your data and map:
data_proj = ccrs.PlateCarree()
map_proj = ccrs.NearsidePerspective(central_longitude=0, central_latitude=90, satellite_height=30785831)
Those can then be used to convert the coordinates to the map projection:
coords_map = map_proj.transform_points(data_proj, coords[:,0], coords[:,1])[:, :-1]
Fitting (and predicting) an ellipse using Scikit-Image:
from skimage.measure import EllipseModel
model = EllipseModel()
model.estimate(coords_map)
ellipse_coords = model.predict_xy(np.linspace(0, 2*np.pi, 100))
That gives the vertices of the ellipse in the map projection. You could consider converting them back to lat/lon, which would allow you to use ccrs.Geodetic and have Cartopy plot the segments as great circles. But sampling the predicted ellipse in map coordinates might already be fine.
This results in:
fig, ax = plt.subplots(figsize=(6,6), subplot_kw=dict(projection=map_proj), dpi=86, facecolor="w")
ax.add_feature(cfeature.NaturalEarthFeature('physical', 'ocean', '110m', facecolor='#C6EEFF', alpha=1, zorder=0))
ax.add_feature(cfeature.NaturalEarthFeature('physical', 'land', '110m', facecolor='#A2BAA4', edgecolor='none', alpha=1,zorder=0))
ax.set_global()
grid = ax.gridlines(draw_labels=True, lw=0.5, color="k", alpha=0.2)
ax.plot(coords_map[0:,0], coords_map[0:,1], "o", mfc="none", mec='#A70000', mew=1, ms=5, zorder=1, transform=map_proj)
ax.plot(ellipse_coords[:, 0], ellipse_coords[:,1], "-", color="#A70000", transform=map_proj)

Blender 2.77: How to I create a path for an object to follow with latitude, longitude, & altitude (in feet) coordinates in csv format?

I have a csv of lat., long., and altitude data from flight 24.
I want to make a path for an object to follow in blender, but the path has to be generated from the above data.
I also want to import a 3D-model of the place where the aircraft flew over.
The problem is I need to use blender 2.77 because the another add-on I want to use only supports v. 2.77. Add-ons like blender-osm and blender-gis only supports the most up to date version of blender.
Lets say you have x y z coordinates for each point of a path then you can easily able to create a path curve using bpy. Here is an example:
import bpy
def create_curve(coords_list):
crv = bpy.data.curves.new('crv', 'CURVE')
crv.dimensions = '3D'
spline = crv.splines.new(type='NURBS')
spline.points.add(len(coords_list) - 1)
for p, new_co in zip(spline.points, coords_list):
p.co = (new_co + [1.0])
obj = bpy.data.objects.new('object_name', crv)
bpy.data.scenes[0].collection.objects.link(obj)
cords_list = [
[0,0,0],
[1, 0, 1],
[2, 0, -1],
[0, 0, 2]
]
create_curve(cords_list)
Output:

GeoTIFF raster mirrored on Python basemap

I am trying to plot a .tif raster on my map with basemap. With QGIS I see the raster layer as it is supposed to be:
QGIS image
However, when then plotting with python basemap the colours are off, and the projection is somehow both rotated 180 degrees and mirrored, with a random blue line projected on the left side of the chart:
Some information about the .tif file (acquired with the rasterio and earthpy packages):
<osgeo.gdal.Dataset; proxy of <Swig Object of type 'GDALDatasetShadow *' at 0x7fcf9bdbef90> >
{'driver': 'GTiff', 'dtype': 'float32', 'nodata': -3.4028234663852886e+38, 'width': 2760, 'height': 1350, 'count': 1, 'crs': CRS.from_epsg(4326), 'transform': Affine(0.01, 0.0, 3.7,
0.0, -0.01, 71.2)}
EPSG:4326
BoundingBox(left=3.7, bottom=57.7, right=31.3, top=71.2)
+proj=longlat +datum=WGS84 +no_defs
The original raster data was downloaded here (forest restoration potential) and cropped to the right latitude and longitude with QGIS.
What am I doing wrong?
import gdal
from numpy import linspace
from numpy import meshgrid
import matplotlib.pyplot as plt
from mpl_toolkits.basemap import Basemap
lowlong = 3.7 #lower left corner of longitude
lowlat = 57.7 #lower left corner of latitude
upplong = 31.3 #upper right corner of longitude
upplat = 71.2 #upper right corner of latitude
pathToRaster = r'~/Data/Shapefile/NorwayPotential.tif'
raster = gdal.Open(pathToRaster,1)
print(raster)
geo = raster.GetGeoTransform()
geo = raster.ReadAsArray()
mp = Basemap(projection='merc',
llcrnrlon=lowlong,
llcrnrlat=lowlat,
urcrnrlon=upplong,
urcrnrlat=upplat,
resolution='i')
mp.drawcoastlines()
mp.drawcountries()
x = linspace(0,mp.urcrnrx,geo.shape[1])
y = linspace(0,mp.urcrnry,geo.shape[0])
xx,yy = meshgrid(x,y)
mp.pcolormesh(xx,yy,geo)
plt.show()
After the line of code:
geo = raster.ReadAsArray()
you can flip the data array by
geo = geo[::-1,:]
and should get the correct result.

Basemap plus 3d graph

Hello Stackoverflow forks,
I'm a enthusiastic python learner.
I have studied python to visualiza my personal project about population density.
I have gone through tutorials about matplotlib and basemap in python.
I came across with the idea about
mapping my 3dimensional graph on top of the basemap which allows me to use geographycal coordinate information.
Can anyone let me know how I could use basemap as a base plane for the 3dimensional graph?
Please let me know which tutorial or references I could go with for developing this.
Best,
Thank you always Stackoverflow forks.
The basemap documentation has a small section on 3D plotting. Here's a simple script to get you started:
import matplotlib.pyplot as plt
from mpl_toolkits.basemap import Basemap
plt.close('all')
fig = plt.figure()
ax = fig.gca(projection='3d')
extent = [-127, -65, 25, 51]
# make the map and axis.
m = Basemap(llcrnrlon=extent[0], llcrnrlat=extent[2],
urcrnrlon=extent[1], urcrnrlat=extent[3],
projection='cyl', resolution='l', fix_aspect=False, ax=ax)
ax.add_collection3d(m.drawcoastlines(linewidth=0.25))
ax.add_collection3d(m.drawcountries(linewidth=0.25))
ax.add_collection3d(m.drawstates(linewidth=0.25))
ax.view_init(azim = 230, elev = 15)
ax.set_xlabel(u'Longitude (°E)', labelpad=10)
ax.set_ylabel(u'Latitude (°N)', labelpad=10)
ax.set_zlabel(u'Altitude (ft)', labelpad=20)
# values to plot - change as needed. Plots 2 dots, one at elevation 0 and another 100.
# also draws a line between the two.
x, y = m(-85.4808, 32.6099)
ax.plot3D([x, x], [y, y], [0, 100], color = 'green', lw = 0.5)
ax.scatter3D(x, y, 100, s = 5, c = 'k', zorder = 4)
ax.scatter3D(x, y, 0, s = 2, c = 'k', zorder = 4)
ax.set_zlim(0., 400.)
plt.show()

How can I align the y-axis (latitudes) of a map plot and a plot in python

I'm trying plot two panels in a plot.
The first one (left) is a data with latitude values in its y-axis. The second panel is a map.
I wanna that the latitude values of both panels coinciding, but I don't know how get it.
I have a code like this:
fig_mapa= plt.figure()
'''Mapa'''
ax1=fig_mapa.add_subplot(122)
map = Basemap(llcrnrlon=-90,llcrnrlat=-58.1,urcrnrlon=-32,urcrnrlat=12.6,
resolution='f',projection='merc',lon_0=-58,lat_0=-25, ax=ax1)
map.drawparallels(np.arange(-90,90.,5), labels=[0,1,0,0], linewidth=0.5)
map.drawmeridians(np.arange(-180.,180.,5), labels=[0,0,0,1], linewidth=0.5)
map.readshapefile("./Fases_tectonicas/Shapefiles/Unidades_Fi", 'Unidades_Fi', linewidth=0.1)
#map.warpimage(image='./Geotiffs/NE1_HR_LC_SR_W_DR/NE1_HR_LC_SR_W_DR.tif', zorder=1)
map.drawcoastlines(linewidth=0.5, color='k')
Nombre_Unidad= []
for elemento in map.Unidades_Fi_info:
Nombre_Unidad.append(elemento['NAME'])
for i in range(len(Nombre_Unidad)):
draw=map.Unidades_Fi[i]
poly=Polygon(draw, facecolor=color[Nombre_Unidad[i]],edgecolor='k', alpha=0.5,linewidth=0.1, zorder=2)
plt.gca().add_patch(poly)
'''Gráfico Eventos Compresivos'''
ax2= fig_mapa.add_subplot(121)
ax2.set_ylim(-58.1,12.6)
ax2.set_xlim(120,0)
ax2.set_xlabel('Tiempo [Ma]')
ax2.set_ylabel('Latitud[°]')
ax2.grid()
The simplest way to align two axes is with the sharex or sharey keyword for plt.subplots. However, the coordinates that Basemap shows and the coordinates that it uses for the Axes instance are two different things, so you will have to convert between the two if you want to have understandable ytick labels and some meaningful graph in your second Axes instance. Below I show how you can align the two y-axes, set the yticks properly and transform your data to the data coordinates of your Basemap. I left the creation of the Basemap untouched.
from matplotlib import pyplot as plt
from mpl_toolkits.basemap import Basemap
import numpy as np
##figure with two subplots and shared y-axis
fig,(ax2,ax1) = plt.subplots(nrows=1, ncols=2, sharey='row')
m1 = Basemap(llcrnrlon=-90,llcrnrlat=-58.1,urcrnrlon=-32,urcrnrlat=12.6,
#resolution='f',
projection='merc',lon_0=-58,lat_0=-25, ax=ax1)
m1.drawparallels(np.arange(-90,90.,5), labels=[0,1,0,0], linewidth=0.5)
m1.drawmeridians(np.arange(-180.,180.,5), labels=[0,0,0,1], linewidth=0.5)
m1.drawcoastlines(linewidth=0.5, color='k')
##turning off yticks at basemap
ax1.yaxis.set_ticks_position('none')
##setting yticks:
yticks = np.arange(-55,12.6,5)
##transform yticks:
_,yticks_data = m1(0*yticks,yticks)
ax2.set_yticks(yticks_data)
ax2.set_yticklabels(['{: >3}$^\circ${}'.format(
abs(int(y)), 'N' if y>0 else 'S' if y<0 else ' '
) for y in yticks])
ax2.set_xlim(120,0)
ax2.set_xlabel('Tiempo [Ma]')
ax2.set_ylabel('Latitud[$^\circ$]')
ax2.grid()
#some fake data for testing plotting
yrange = np.linspace(-60,20,100)
temp = (np.sin(10*np.deg2rad(yrange))+1)*50
##transform yrange
_,yrange_data = m1(0*yrange, yrange)
ax2.plot(temp,yrange_data)
plt.show()
The result of the above code looks like this:
Hope this helps.