RadarRedo / tile_interceptor.py
nakas's picture
Implement clean radar reclassification with perfect colors
2b279ea
Raw
History Blame Contribute Delete
4.85 kB
"""
Alternative approach: Create a custom Folium layer that processes tiles on-the-fly
This ensures we get the exact same clean tiles that Tab 1 displays
"""
import folium
import numpy as np
from PIL import Image
import io
import base64
from radar_processor import RadarImageProcessor
class ProcessingWmsTileLayer(folium.raster_layers.WmsTileLayer):
"""Custom WMS layer that processes tiles with American colors on-the-fly."""
def __init__(self, *args, **kwargs):
# Extract our custom processor
self.processor = kwargs.pop('processor', None)
super().__init__(*args, **kwargs)
def render(self, **kwargs):
# Get the standard WMS layer HTML
standard_html = super().render(**kwargs)
# Add JavaScript to intercept and process tiles
processing_js = """
<script>
// Intercept tile loading and process them
function processRadarTile(img) {
try {
var canvas = document.createElement('canvas');
var ctx = canvas.getContext('2d');
canvas.width = img.width;
canvas.height = img.height;
ctx.drawImage(img, 0, 0);
var imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
var data = imageData.data;
// Process pixels to American colors
for (var i = 0; i < data.length; i += 4) {
var r = data[i];
var g = data[i + 1];
var b = data[i + 2];
var a = data[i + 3];
if (a > 0) { // Non-transparent pixel
// Simple Canadian to American color mapping
var newColor = mapCanadianToAmerican(r, g, b);
data[i] = newColor[0]; // R
data[i + 1] = newColor[1]; // G
data[i + 2] = newColor[2]; // B
}
}
ctx.putImageData(imageData, 0, 0);
img.src = canvas.toDataURL();
} catch (e) {
console.log('Tile processing failed:', e);
}
}
function mapCanadianToAmerican(r, g, b) {
// Canadian cyan (0,255,255) -> American blue (30,144,255)
if (r < 50 && g > 200 && b > 200) return [30, 144, 255];
// Canadian bright green (0,200,0) -> American lime (0,255,0)
if (r < 50 && g > 150 && g < 250 && b < 50) return [0, 255, 0];
// Canadian yellow (255,255,0) -> American yellow (255,255,0) [same]
if (r > 200 && g > 200 && b < 100) return [255, 255, 0];
// Canadian orange (255,150,0) -> American dark orange (255,140,0)
if (r > 200 && g > 100 && g < 200 && b < 50) return [255, 140, 0];
// Canadian red (255,0,0) -> American red (255,0,0) [same]
if (r > 200 && g < 100 && b < 100) return [255, 0, 0];
// Canadian magenta (200,0,200) -> American magenta (255,0,255)
if (r > 150 && g < 100 && b > 150) return [255, 0, 255];
// Default: return original color
return [r, g, b];
}
// Hook into tile loading
setTimeout(function() {
var images = document.querySelectorAll('img[src*="geo.weather.gc.ca"]');
images.forEach(function(img) {
if (img.complete) {
processRadarTile(img);
} else {
img.onload = function() { processRadarTile(img); };
}
});
}, 1000);
</script>
"""
return standard_html + processing_js
def create_processing_radar_map(wms_url, layer_name, opacity=0.7):
"""Create a map with processing WMS layer that converts colors on-the-fly."""
# Create base map
m = folium.Map(
location=[56.1304, -106.3468], # Canada center
zoom_start=4,
tiles="OpenStreetMap"
)
# Add the processing WMS layer
processor = RadarImageProcessor()
processing_layer = ProcessingWmsTileLayer(
url=wms_url,
layers=layer_name,
version="1.3.0",
transparent=True,
format="image/png",
name="Processed Canadian Radar (American Colors)",
overlay=True,
control=True,
opacity=opacity,
processor=processor,
attr='<a href="https://eccc-msc.github.io/open-data/licence/readme_en/">ECCC</a> (Recolored)'
)
processing_layer.add_to(m)
# Add layer control
folium.LayerControl().add_to(m)
return m