Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Polarplot as image on a map

I have this codeblock to plot a gyro calibration as a compass rose, via a matplotlib polarplot, see the image below. Now I would like to plot the compass on a folium map so at that the observer can see that the Gyro heading does align with the quayside of the port where the ship was moored during the calibration.

How can I plot the polarplot as a transparent (white background is transparent) .png or a .svg @ the position co-ordinates on a folium map?

from pvlib import solarposition
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt

# Polarplot

# user input _____________________________________________________________________________
tz = 'Europe/Amsterdam'
lat = 52+(57/60)+(26.9/3600)
lon =  4+(46/60)+(37.5/3600)
lat_dms, lon_dms ="52°57′26.9″","004°46′37.5″"  # position strings

loc_descr = "Den Helder - Nieuwe Diep"

# Corrected gyro heading
gyro_corrected = 154.92
st_dev_gyro = 0.03

# First fix Zn
first_fix = 138.873

# Last fix Zn
last_fix = 144.915
#user input ______________________________________________________________________________

# Function to convert degrees to radians
def degrees_to_radians(degrees):
    return degrees * np.pi / 180.0

# Convert angles to radians
gyro_corrected_rad = degrees_to_radians(gyro_corrected)
first_fix_rad = degrees_to_radians(first_fix)
last_fix_rad = degrees_to_radians(last_fix)

# */ solar trajectory plot ------------------------------------------------------------------------------------------------------
# set times for solar trajectory
times = pd.date_range('2019-12-31 00:00:00', '2020-01-01', freq='H', tz=tz)
solpos = solarposition.get_solarposition(times, lat, lon)
# remove nighttime
solpos = solpos.loc[solpos['apparent_elevation'] > 0, :]

#make polarplot
ax = plt.subplot(1, 1, 1, projection='polar')

# /* solar  plot ------------------------------------------------------------------------------------------------------

# Plot the corrected gyro heading vector
ax.quiver(0, 0, gyro_corrected_rad, 90, angles='xy', scale_units='xy', scale=1, color='darkgreen', label=f'Gyro Heading True: ({gyro_corrected} ± {st_dev_gyro})°')


# /* solar  plot ------------------------------------------------------------------------------------------------------
# draw hour labels
for hour in np.unique(solpos.index.hour):
    # choose label position by the smallest radius for each hour
    subset = solpos.loc[solpos.index.hour == hour, :]
    r = subset.apparent_zenith
    pos = solpos.loc[r.idxmin(), :]
    ax.text(np.radians(pos['azimuth']), pos['apparent_zenith'], str(hour))

# draw individual days
for date in pd.to_datetime(['2019-12-31']):
    times = pd.date_range(date, date+pd.Timedelta('24h'), freq='5min', tz=tz)
    solpos = solarposition.get_solarposition(times, lat, lon)
    solpos = solpos.loc[solpos['apparent_elevation'] > 0, :]
    label =  f"☀️ @ {date.strftime('%Y-%m-%d')} -localtime: UTC+1"
    ax.plot(np.radians(solpos.azimuth), solpos.apparent_zenith, label=label, color='darkorange', linewidth=2)
# /* solar trajectory plot ------------------------------------------------------------------------------------------------------

# Plot the line for the first fix
ax.plot([0, first_fix_rad], [0, 90], color= 'orange', linestyle='--', label=f'{first_fix}° -fix 1 ☀️')

# Plot the line for the last fix
ax.plot([0, last_fix_rad], [0, 90], color='gold', linestyle='--', label=f'{last_fix}° -last fix ☀️')

# change coordinates to be like a compass
data = pd.DataFrame({'value': [0, 20, 30, 20, 0, 10, 15, 10],
                     'bearing': range(0, 360, 45),
                     'compass': ['000°\nN', 'NE', '090°\n E', 'SE', '180°\nS', 'SW', '270°\nW', 'NW']})

data.index = data['bearing'] * 2*np.pi / 360

ax.set_title(f"Sunshot Gyro Calibration @ {lat_dms}N, {lon_dms}E\n{loc_descr}\n")

# Place the legend below the plot
ax.legend(loc='upper center', bbox_to_anchor=(0.5, -0.18), fancybox=True, shadow=True, ncol=2) # 1.  

ax.set_theta_zero_location('N') # North-up
ax.set_theta_direction(-1)
ax.set_xticklabels(data.compass)
#ax.set_yticklabels()

ax.set_rgrids([])
ax.set_rmax(90)

plt.show()

the plot

like image 245
mR.bLuEsKy Avatar asked Mar 13 '26 09:03

mR.bLuEsKy


1 Answers

IIUC, you can savefig with a transparent background, then use it as a FloatImage :

plt.figure(figsize=(4, 2)) # <<< add this
ax = plt.subplot(1, 1, 1, projection='polar')

# rest of the code..

# plt.show() # <<< comment this

import io
import base64
import folium
from folium.plugins import FloatImage

buff = io.BytesIO()
plt.savefig(buff, transparent=True)
img = base64.b64encode(buff.getvalue()).decode()

m = folium.Map([lat, lon], zoom_start=10)

FloatImage(
    f"data:image/png;base64,{img}", bottom=30, left=-5
).add_to(m)

Output (m) :

enter image description here

like image 115
Timeless Avatar answered Mar 16 '26 00:03

Timeless