Welcome to Plotly forum!
Theoretically we can plot a heatmap like that displayed at the link you posted, on a spherical earth map, but practically not.
That heatmap is an image of resolution at least 26 x 26.
To map it within the boundary of a country (on the sphere) that can contain a rectangular/square region with sides of, let us say, 10 lon units x 10 lat units, we have to transform it to a rectangular region measured in radians.
This means that in radians we have the sides of length 10\pi/180 \approx 0.1745. It is so small that you cannot see on the map.
Below I illustrate this drawback:
import numpy as np
from numpy import pi, sin, cos
import plotly.graph_objects as go
x = y = np.arange(26)
X, Y = np.meshgrid(x,y)
Z = np.cos(X*Y/4)
m, n = Z.shape
fig = go.Figure(go.Heatmap(x=x, y=y, z=Z, colorscale='RdBu', zsmooth='best'))
Define a function that transforms into radians the lon in [-180, 180, and lat in [-90, 90], and a function that maps points within the rectangle
[-pi, pi] x [-pi/2, pi/2] to a sphere of radius 1.
#convert degrees to radians
def mapping_map_to_sphere(lon, lat, radius=1):
# lon in [-pi, pi), lat in [-pi/2,pi/2]
#this function maps the points of coords (lon, lat) to points onto the sphere of radius=1
lon = np.array(lon, dtype=np.float64)
lat = np.array(lat, dtype=np.float64)
lon = degree2radians(lon)
lat = degree2radians(lat)
xs = radius*cos(lon)*cos(lat)
ys = radius*sin(lon)*cos(lat)
zs = radius*sin(lat)
return xs, ys, zs
When I plotted a global heatmap on the spherical map, here https://plot.ly/~empet/14813/heatmap-plot-on-a-spherical-map/#/,
I saved in this file https://github.com/empet/Datasets/blob/master/map_sphere.npy
the coordinates of country boundaries and coastlines, to be plotted as a go.Scatter3d chart on the sphere.
spherical_earth_map = np.load('map_sphere.npy')
xm, ym, zm = spherical_earth_map.T
fig = go.Figure(go.Scatter3d(x=xm, y=ym, z=zm, mode='lines'))
Let us say that we want to plot the above heatmap on the spherical map into the region coresponding to lon in the interval londeg, and lat in the interval latdeg:
londeg = [30, 40]
latdeg = [50, 60]
#convert londeg, latdeg to radians:
lonrad = [degree2radians(londeg), degree2radians(londeg)]
latrad = [degree2radians(latdeg), degree2radians(latdeg)]
print(lonrad, '\n', latrad)
# Define a meshgrid from lonrad, latrad of the same size like Z in our heatmap:
lon = np.linspace(lonrad, lonrad, n)
lat = np.linspace(latrad, latrad, m)
lon, lat = np.meshgrid(lon, lat)
Xs, Ys, Zs = mapping_map_to_sphere(lon, lat)
#add the heatmap on sphere as a surface
fig.add_surface(x=Xs, y=Ys, z=Zs, surfacecolor=Z, colorscale='RdBu');
As you can notice, the heatmap is invisible.
But let us plot it in an independent figure:
figg =go.Figure(go.Surface(x=Xs, y=Ys, z=Zs, surfacecolor=Z, colorscale='RdBu'))
Looking at the xaxis, yaxis, zaxis tick labels we see that the heatmap on sphere is concentrated in a very, very small region. That’s why it was invisible in the previous plot.