Improve relay maps with proper world map backgrounds using cartopy

This commit is contained in:
lollerfirst
2025-11-01 19:57:44 +01:00
parent bd4a666b99
commit da302d5aba
4 changed files with 44 additions and 51 deletions
+4
View File
@@ -32,6 +32,10 @@ jobs:
run: |
python -m pip install --upgrade pip
pip install matplotlib pandas numpy folium scipy
# Install cartopy and its dependencies
sudo apt-get update
sudo apt-get install -y libproj-dev proj-bin proj-data libgeos-dev
pip install cartopy
- name: Generate relay maps
run: |
Binary file not shown.

Before

Width:  |  Height:  |  Size: 192 KiB

After

Width:  |  Height:  |  Size: 988 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 251 KiB

After

Width:  |  Height:  |  Size: 1.1 MiB

+40 -51
View File
@@ -48,38 +48,47 @@ def create_interactive_map(df, output_path):
def create_static_map(df, output_path):
"""
Create a static PNG map showing relay locations on a simple world map.
Create a static PNG map showing relay locations on a proper world map.
Args:
df: DataFrame containing relay data with Latitude and Longitude columns
output_path: Path to save the PNG map
"""
import cartopy.crs as ccrs
import cartopy.feature as cfeature
plt.figure(figsize=(15, 10))
# Create a simple base map
ax = plt.axes()
ax.set_facecolor('#DDEEFF') # Light blue background for oceans
# Create a map with a proper projection
ax = plt.axes(projection=ccrs.PlateCarree())
# Draw a simple grid
for i in range(-180, 181, 30):
plt.axvline(x=i, color='#CCCCCC', linestyle='--', alpha=0.5)
# Add map features
ax.add_feature(cfeature.LAND, facecolor='#E5E5E5')
ax.add_feature(cfeature.OCEAN, facecolor='#DDEEFF')
ax.add_feature(cfeature.COASTLINE, linewidth=0.5, edgecolor='#999999')
ax.add_feature(cfeature.BORDERS, linewidth=0.3, edgecolor='#AAAAAA')
ax.add_feature(cfeature.LAKES, facecolor='#DDEEFF', edgecolor='#999999', linewidth=0.5)
ax.add_feature(cfeature.RIVERS, edgecolor='#99CCFF', linewidth=0.5)
for i in range(-90, 91, 30):
plt.axhline(y=i, color='#CCCCCC', linestyle='--', alpha=0.5)
# Add grid
gl = ax.gridlines(crs=ccrs.PlateCarree(), draw_labels=True,
linewidth=0.5, color='gray', alpha=0.5, linestyle='--')
gl.top_labels = False
gl.right_labels = False
# Set map limits
plt.xlim(-180, 180)
plt.ylim(-90, 90)
ax.set_extent([-180, 180, -90, 90], crs=ccrs.PlateCarree())
# Plot relay locations
plt.scatter(
df['Longitude'],
df['Latitude'],
alpha=0.7,
alpha=0.8,
c='blue',
s=30,
edgecolor='white',
linewidth=0.5
linewidth=0.5,
transform=ccrs.PlateCarree()
)
# Add title and labels
@@ -95,19 +104,6 @@ def create_static_map(df, output_path):
bbox=dict(boxstyle="round,pad=0.3", fc="white", alpha=0.8)
)
# Add labels for equator and prime meridian
plt.text(0, -5, "0° (Prime Meridian)", ha='center', fontsize=8, alpha=0.7)
plt.text(5, 0, "0° (Equator)", va='center', rotation=90, fontsize=8, alpha=0.7)
# Remove axes ticks but keep latitude/longitude labels at 30-degree intervals
plt.xticks([-180, -150, -120, -90, -60, -30, 0, 30, 60, 90, 120, 150, 180],
["180°W", "150°W", "120°W", "90°W", "60°W", "30°W", "",
"30°E", "60°E", "90°E", "120°E", "150°E", "180°E"],
fontsize=8)
plt.yticks([-90, -60, -30, 0, 30, 60, 90],
["90°S", "60°S", "30°S", "", "30°N", "60°N", "90°N"],
fontsize=8)
# Adjust layout and save
plt.tight_layout()
plt.savefig(output_path, dpi=300, bbox_inches='tight')
@@ -123,22 +119,29 @@ def create_heatmap(df, output_path):
df: DataFrame containing relay data with Latitude and Longitude columns
output_path: Path to save the PNG heatmap
"""
import cartopy.crs as ccrs
import cartopy.feature as cfeature
from scipy.ndimage import gaussian_filter
plt.figure(figsize=(15, 10))
# Create a simple base map
ax = plt.axes()
ax.set_facecolor('#DDEEFF') # Light blue background for oceans
# Create a map with a proper projection
ax = plt.axes(projection=ccrs.PlateCarree())
# Draw a simple grid
for i in range(-180, 181, 30):
plt.axvline(x=i, color='#CCCCCC', linestyle='--', alpha=0.5)
# Add map features
ax.add_feature(cfeature.LAND, facecolor='#E5E5E5')
ax.add_feature(cfeature.OCEAN, facecolor='#DDEEFF')
ax.add_feature(cfeature.COASTLINE, linewidth=0.5, edgecolor='#999999')
ax.add_feature(cfeature.BORDERS, linewidth=0.3, edgecolor='#AAAAAA')
for i in range(-90, 91, 30):
plt.axhline(y=i, color='#CCCCCC', linestyle='--', alpha=0.5)
# Add grid
gl = ax.gridlines(crs=ccrs.PlateCarree(), draw_labels=True,
linewidth=0.5, color='gray', alpha=0.5, linestyle='--')
gl.top_labels = False
gl.right_labels = False
# Set map limits
plt.xlim(-180, 180)
plt.ylim(-90, 90)
ax.set_extent([-180, 180, -90, 90], crs=ccrs.PlateCarree())
# Create grid for heatmap
x = np.linspace(-180, 180, 360)
@@ -155,7 +158,6 @@ def create_heatmap(df, output_path):
heatmap[lat_idx, lon_idx] += 1
# Apply Gaussian smoothing to heatmap
from scipy.ndimage import gaussian_filter
heatmap = gaussian_filter(heatmap, sigma=3)
# Create custom colormap (blue to white)
@@ -163,7 +165,7 @@ def create_heatmap(df, output_path):
cmap = LinearSegmentedColormap.from_list('custom_blue', colors)
# Plot heatmap
plt.pcolormesh(x, y, heatmap, cmap=cmap, alpha=0.7)
plt.pcolormesh(x, y, heatmap, cmap=cmap, alpha=0.7, transform=ccrs.PlateCarree())
# Add title
plt.title('Global Heatmap of BitChat-Compatible Nostr Relays', fontsize=16)
@@ -178,19 +180,6 @@ def create_heatmap(df, output_path):
bbox=dict(boxstyle="round,pad=0.3", fc="white", alpha=0.8)
)
# Add labels for equator and prime meridian
plt.text(0, -5, "0° (Prime Meridian)", ha='center', fontsize=8, alpha=0.7)
plt.text(5, 0, "0° (Equator)", va='center', rotation=90, fontsize=8, alpha=0.7)
# Add longitude/latitude labels
plt.xticks([-180, -150, -120, -90, -60, -30, 0, 30, 60, 90, 120, 150, 180],
["180°W", "150°W", "120°W", "90°W", "60°W", "30°W", "",
"30°E", "60°E", "90°E", "120°E", "150°E", "180°E"],
fontsize=8)
plt.yticks([-90, -60, -30, 0, 30, 60, 90],
["90°S", "60°S", "30°S", "", "30°N", "60°N", "90°N"],
fontsize=8)
# Adjust layout and save
plt.tight_layout()
plt.savefig(output_path, dpi=300, bbox_inches='tight')