help@rskworld.in +91 93305 39277
RSK World
  • Home
  • Development
    • Web Development
    • Mobile Apps
    • Software
    • Games
    • Project
  • Technologies
    • Data Science
    • AI Development
    • Cloud Development
    • Blockchain
    • Cyber Security
    • Dev Tools
    • Testing Tools
  • About
  • Contact

Theme Settings

Color Scheme
Display Options
Font Size
100%
Back to Project
RSK World
weather-chatbot
/
utils
RSK World
weather-chatbot
Weather Chatbot - Python + Flask + OpenWeatherMap + OpenAI + Weather Forecast + Weather Alerts + Natural Language Processing
utils
  • __pycache__
  • __init__.py3.9 KB
  • advanced_nlp.py28.4 KB
  • analytics.py22 KB
  • auth.py17.8 KB
  • comparison.py24.2 KB
  • database.py24.6 KB
  • geolocation.py20.1 KB
  • multilang.py22 KB
  • notifications.py34.1 KB
  • rate_limiting.py24.3 KB
  • weather_maps.py29.6 KB
  • weather_utils.py12.9 KB
weather_maps.py
utils/weather_maps.py
Raw Download
Find: Go to:
#!/usr/bin/env python3
"""
Weather Chatbot Maps & Radar Module
===================================

Author: RSK World (https://rskworld.in)
Founded by: Molla Samser
Designer & Tester: Rima Khatun
Contact: +91 93305 39277, hello@rskworld.in, support@rskworld.in
Location: Nutanhat, Mongolkote, Purba Burdwan, West Bengal, India, 713147
Year: 2026

Description: Weather maps and radar integration services
"""

import requests
import json
import base64
from typing import Dict, List, Optional, Tuple
from datetime import datetime, timedelta
import io

# Optional dependencies for weather maps - handle gracefully if not installed
try:
    import matplotlib
    matplotlib.use('Agg')  # Use non-interactive backend (must be before pyplot import)
    import matplotlib.pyplot as plt
    import matplotlib.patches as patches
    from matplotlib.backends.backend_agg import FigureCanvasAgg
    from matplotlib.patches import Patch as MplPatch
    MATPLOTLIB_AVAILABLE = True
except (ImportError, AttributeError) as e:
    matplotlib = None
    plt = None
    patches = None
    FigureCanvasAgg = None
    MplPatch = None
    MATPLOTLIB_AVAILABLE = False
    print(f"Warning: Matplotlib not available. Weather map image generation will be disabled. Error: {e}")

try:
    import numpy as np
    NUMPY_AVAILABLE = True
except ImportError:
    np = None
    NUMPY_AVAILABLE = False
    print("Warning: NumPy not available. Some map calculations will be limited.")

class WeatherMapsService:
    """Weather maps and radar integration service"""
    
    def __init__(self, openweather_api_key: str = None, mapbox_api_key: str = None):
        self.openweather_api_key = openweather_api_key
        self.mapbox_api_key = mapbox_api_key
        self.openweather_layers_url = "https://maps.openweathermap.org/maps/2.0"
        self.mapbox_static_url = "https://api.mapbox.com/styles/v1"
        self.radar_url = "https://api.openweathermap.org/data/2.5"
    
    def get_weather_map_layers(self) -> Dict:
        """
        Get available weather map layers.
        
        Returns:
            Available map layers information
        """
        layers = {
            'precipitation': {
                'name': 'Precipitation',
                'description': 'Current precipitation radar',
                'url': f"{self.openweather_layers_url}/precipitation/0/{datetime.now().strftime('%Y-%m-%d')}",
                'opacity_range': [0.1, 1.0],
                'default_opacity': 0.8
            },
            'precipitation_new': {
                'name': 'Precipitation (New)',
                'description': 'Enhanced precipitation radar',
                'url': f"{self.openweather_layers_url}/precipitation_new/0/{datetime.now().strftime('%Y-%m-%d')}",
                'opacity_range': [0.1, 1.0],
                'default_opacity': 0.8
            },
            'clouds': {
                'name': 'Clouds',
                'description': 'Cloud cover satellite imagery',
                'url': f"{self.openweather_layers_url}/clouds/0/{datetime.now().strftime('%Y-%m-%d')}",
                'opacity_range': [0.1, 1.0],
                'default_opacity': 0.7
            },
            'pressure': {
                'name': 'Pressure',
                'description': 'Atmospheric pressure contours',
                'url': f"{self.openweather_layers_url}/pressure/0/{datetime.now().strftime('%Y-%m-%d')}",
                'opacity_range': [0.1, 1.0],
                'default_opacity': 0.6
            },
            'wind': {
                'name': 'Wind Speed',
                'description': 'Wind speed and direction',
                'url': f"{self.openweather_layers_url}/wind/0/{datetime.now().strftime('%Y-%m-%d')}",
                'opacity_range': [0.1, 1.0],
                'default_opacity': 0.7
            },
            'temperature': {
                'name': 'Temperature',
                'description': 'Surface temperature',
                'url': f"{self.openweather_layers_url}/temp/0/{datetime.now().strftime('%Y-%m-%d')}",
                'opacity_range': [0.1, 1.0],
                'default_opacity': 0.6
            }
        }
        
        return {
            'available_layers': layers,
            'base_url': self.openweather_layers_url,
            'api_key_required': bool(self.openweather_api_key)
        }
    
    def generate_weather_map_url(self, layer: str, bounds: List[float], 
                               zoom: int = 5, opacity: float = 0.8) -> Dict:
        """
        Generate weather map URL for specific layer and bounds.
        
        Args:
            layer: Weather layer type
            bounds: Map bounds [lat_min, lon_min, lat_max, lon_max]
            zoom: Zoom level
            opacity: Layer opacity
            
        Returns:
            Map URL and metadata
        """
        try:
            if not self.openweather_api_key:
                return {'error': 'OpenWeatherMap API key required'}
            
            # Validate bounds
            if len(bounds) != 4:
                return {'error': 'Invalid bounds format. Use [lat_min, lon_min, lat_max, lon_max]'}
            
            lat_min, lon_min, lat_max, lon_max = bounds
            
            # Validate coordinates
            if not (-90 <= lat_min <= 90 and -90 <= lat_max <= 90):
                return {'error': 'Invalid latitude bounds'}
            if not (-180 <= lon_min <= 180 and -180 <= lon_max <= 180):
                return {'error': 'Invalid longitude bounds'}
            
            # Calculate center point
            center_lat = (lat_min + lat_max) / 2
            center_lon = (lon_min + lon_max) / 2
            
            # Generate map URL
            map_url = f"{self.openweather_layers_url}/{layer}/{zoom}/{center_lat:.4f}/{center_lon:.4f}"
            
            params = {
                'appid': self.openweather_api_key,
                'opacity': opacity,
                'bbox': f"{lon_min},{lat_min},{lon_max},{lat_max}"
            }
            
            # Build full URL with parameters
            param_string = '&'.join([f"{k}={v}" for k, v in params.items()])
            full_url = f"{map_url}?{param_string}"
            
            return {
                'success': True,
                'map_url': full_url,
                'layer': layer,
                'bounds': bounds,
                'center': [center_lat, center_lon],
                'zoom': zoom,
                'opacity': opacity,
                'generated_at': datetime.now().isoformat()
            }
            
        except Exception as e:
            return {'error': f'Failed to generate map URL: {str(e)}'}
    
    def get_radar_data(self, lat: float, lon: float, radius: int = 50) -> Dict:
        """
        Get radar data for a specific location.
        
        Args:
            lat: Latitude
            lon: Longitude
            radius: Search radius in kilometers
            
        Returns:
            Radar data and imagery
        """
        try:
            if not self.openweather_api_key:
                return {'error': 'OpenWeatherMap API key required'}
            
            # Get current weather with radar information
            url = f"{self.radar_url}/weather"
            params = {
                'lat': lat,
                'lon': lon,
                'appid': self.openweather_api_key,
                'units': 'metric'
            }
            
            response = requests.get(url, params=params, timeout=10)
            response.raise_for_status()
            
            weather_data = response.json()
            
            # Extract radar-relevant information
            radar_info = {
                'location': {
                    'lat': lat,
                    'lon': lon,
                    'city': weather_data.get('name', 'Unknown'),
                    'country': weather_data.get('sys', {}).get('country', '')
                },
                'current_conditions': {
                    'temperature': weather_data.get('main', {}).get('temp', 0),
                    'humidity': weather_data.get('main', {}).get('humidity', 0),
                    'pressure': weather_data.get('main', {}).get('pressure', 0),
                    'visibility': weather_data.get('visibility', 0) / 1000,  # Convert to km
                    'description': weather_data.get('weather', [{}])[0].get('description', ''),
                    'icon': weather_data.get('weather', [{}])[0].get('icon', '')
                },
                'wind': {
                    'speed': weather_data.get('wind', {}).get('speed', 0),
                    'direction': weather_data.get('wind', {}).get('deg', 0),
                    'gust': weather_data.get('wind', {}).get('gust', 0)
                },
                'precipitation': {
                    'rain_1h': weather_data.get('rain', {}).get('1h', 0),
                    'rain_3h': weather_data.get('rain', {}).get('3h', 0),
                    'snow_1h': weather_data.get('snow', {}).get('1h', 0),
                    'snow_3h': weather_data.get('snow', {}).get('3h', 0)
                },
                'clouds': {
                    'coverage': weather_data.get('clouds', {}).get('all', 0)
                },
                'radar_url': self._generate_radar_url(lat, lon, radius),
                'timestamp': datetime.now().isoformat()
            }
            
            return radar_info
            
        except requests.exceptions.RequestException as e:
            return {'error': f'Failed to get radar data: {str(e)}'}
        except Exception as e:
            return {'error': f'Error processing radar data: {str(e)}'}
    
    def _generate_radar_url(self, lat: float, lon: float, radius: int) -> str:
        """Generate radar URL for the location"""
        if not self.openweather_api_key:
            return ""
        
        # Calculate bounds based on radius
        # Rough approximation: 1 degree latitude ≈ 111 km
        import math
        lat_delta = radius / 111
        lon_delta = radius / (111 * math.cos(math.radians(lat)))
        
        lat_min = lat - lat_delta
        lat_max = lat + lat_delta
        lon_min = lon - lon_delta
        lon_max = lon + lon_delta
        
        # Generate precipitation radar URL
        radar_url = f"{self.openweather_layers_url}/precipitation_new/6/{lat:.4f}/{lon:.4f}"
        params = f"appid={self.openweather_api_key}&opacity=0.8&bbox={lon_min},{lat_min},{lon_max},{lat_max}"
        
        return f"{radar_url}?{params}"
    
    def create_weather_map_image(self, cities_data: Dict[str, Dict], 
                               map_type: str = 'temperature', 
                               width: int = 800, height: int = 600) -> Dict:
        """
        Create a custom weather map image with city data.
        
        Args:
            cities_data: Dictionary of city weather data
            map_type: Type of weather map (temperature, precipitation, pressure, wind)
            width: Image width
            height: Image height
            
        Returns:
            Base64 encoded image and metadata
        """
        try:
            if not MATPLOTLIB_AVAILABLE or plt is None:
                return {'error': 'Matplotlib is required for map image generation. Please install matplotlib.'}
            
            # Create matplotlib figure
            fig, ax = plt.subplots(figsize=(width/100, height/100), dpi=100)
            
            # Set up the map
            ax.set_xlim(-180, 180)
            ax.set_ylim(-90, 90)
            ax.set_aspect('equal')
            
            # Add world map background (simplified)
            self._add_world_map_background(ax)
            
            # Plot cities with weather data
            for city, data in cities_data.items():
                if 'error' in data:
                    continue
                
                lat = data.get('latitude', 0)
                lon = data.get('longitude', 0)
                
                if lat == 0 and lon == 0:
                    # Try to get coordinates from city name
                    coords = self._get_city_coordinates(city)
                    if coords:
                        lat, lon = coords
                    else:
                        continue
                
                # Get weather value based on map type
                value = self._get_weather_value(data, map_type)
                color = self._get_weather_color(value, map_type)
                
                # Plot city marker
                ax.scatter(lon, lat, c=color, s=100, alpha=0.8, edgecolors='black', linewidth=1)
                
                # Add city label
                ax.annotate(city, (lon, lat), xytext=(5, 5), 
                           textcoords='offset points', fontsize=8, alpha=0.8)
                
                # Add value label
                value_text = self._format_value_text(value, map_type)
                ax.annotate(value_text, (lon, lat), xytext=(5, -15), 
                           textcoords='offset points', fontsize=7, alpha=0.7)
            
            # Set title and labels
            ax.set_title(f'Weather Map - {map_type.title()}', fontsize=16, fontweight='bold')
            ax.set_xlabel('Longitude', fontsize=12)
            ax.set_ylabel('Latitude', fontsize=12)
            
            # Add grid
            ax.grid(True, alpha=0.3)
            
            # Add colorbar if applicable
            if map_type in ['temperature', 'pressure', 'wind']:
                self._add_colorbar(ax, map_type)
            
            # Add legend
            self._add_map_legend(ax, map_type)
            
            # Add attribution
            ax.text(0.02, 0.02, 'Weather Chatbot - RSK World (https://rskworld.in)', 
                   transform=ax.transAxes, fontsize=8, alpha=0.7)
            
            # Save figure to buffer
            buffer = io.BytesIO()
            plt.savefig(buffer, format='png', dpi=100, bbox_inches='tight')
            buffer.seek(0)
            
            # Convert to base64
            image_base64 = base64.b64encode(buffer.getvalue()).decode()
            
            plt.close()
            
            return {
                'success': True,
                'image_base64': image_base64,
                'map_type': map_type,
                'cities_count': len(cities_data),
                'dimensions': {'width': width, 'height': height},
                'generated_at': datetime.now().isoformat()
            }
            
        except Exception as e:
            return {'error': f'Failed to create weather map image: {str(e)}'}
    
    def _add_world_map_background(self, ax):
        """Add simplified world map background"""
        if not MATPLOTLIB_AVAILABLE or patches is None:
            return
        
        # Create a simple world map outline
        world_coords = [
            # Simplified continent outlines (very basic)
            [-100, 40, -80, 50],  # North America (simplified)
            [-10, 35, 40, 70],   # Europe/Africa (simplified)
            [70, 10, 140, 50],   # Asia (simplified)
            [110, -45, 155, -10], # Australia (simplified)
            [-80, -55, -35, -15], # South America (simplified)
        ]
        
        for coords in world_coords:
            rect = patches.Rectangle((coords[0], coords[2]), 
                                   coords[1] - coords[0], 
                                   coords[3] - coords[2],
                                   linewidth=0.5, edgecolor='gray', 
                                   facecolor='lightgray', alpha=0.3)
            ax.add_patch(rect)
    
    def _get_city_coordinates(self, city: str) -> Optional[Tuple[float, float]]:
        """Get city coordinates (simplified - would use geocoding API in production)"""
        # This is a very simplified version - in production, use a proper geocoding service
        city_coords = {
            'london': (51.5074, -0.1278),
            'new york': (40.7128, -74.0060),
            'paris': (48.8566, 2.3522),
            'tokyo': (35.6762, 139.6503),
            'delhi': (28.7041, 77.1025),
            'mumbai': (19.0760, 72.8777),
            'kolkata': (22.5726, 88.3639),
            'sydney': (-33.8688, 151.2093),
            'moscow': (55.7558, 37.6173),
            'beijing': (39.9042, 116.4074),
            'dubai': (25.2048, 55.2708),
            'singapore': (1.3521, 103.8198)
        }
        
        return city_coords.get(city.lower())
    
    def _get_weather_value(self, data: Dict, map_type: str) -> float:
        """Get weather value based on map type"""
        if map_type == 'temperature':
            return data.get('temperature', 0)
        elif map_type == 'precipitation':
            return data.get('rain_1h', 0) + data.get('snow_1h', 0)
        elif map_type == 'pressure':
            return data.get('pressure', 1013)
        elif map_type == 'wind':
            return data.get('wind_speed', 0)
        elif map_type == 'humidity':
            return data.get('humidity', 0)
        else:
            return 0
    
    def _get_weather_color(self, value: float, map_type: str) -> str:
        """Get color based on weather value and type"""
        if map_type == 'temperature':
            if value < -10:
                return 'darkblue'
            elif value < 0:
                return 'blue'
            elif value < 10:
                return 'lightblue'
            elif value < 20:
                return 'green'
            elif value < 30:
                return 'yellow'
            elif value < 40:
                return 'orange'
            else:
                return 'red'
        
        elif map_type == 'precipitation':
            if value == 0:
                return 'white'
            elif value < 2.5:
                return 'lightblue'
            elif value < 10:
                return 'blue'
            else:
                return 'darkblue'
        
        elif map_type == 'pressure':
            if value < 1000:
                return 'red'
            elif value < 1010:
                return 'orange'
            elif value < 1020:
                return 'green'
            else:
                return 'blue'
        
        elif map_type == 'wind':
            if value < 5:
                return 'green'
            elif value < 15:
                return 'yellow'
            elif value < 25:
                return 'orange'
            else:
                return 'red'
        
        elif map_type == 'humidity':
            if value < 30:
                return 'brown'
            elif value < 60:
                return 'green'
            else:
                return 'blue'
        
        else:
            return 'gray'
    
    def _format_value_text(self, value: float, map_type: str) -> str:
        """Format value text for display"""
        if map_type == 'temperature':
            return f"{value:.1f}°C"
        elif map_type == 'precipitation':
            return f"{value:.1f}mm"
        elif map_type == 'pressure':
            return f"{value:.0f}hPa"
        elif map_type == 'wind':
            return f"{value:.1f}m/s"
        elif map_type == 'humidity':
            return f"{value:.0f}%"
        else:
            return f"{value:.1f}"
    
    def _add_colorbar(self, ax, map_type: str):
        """Add colorbar to the map"""
        if not MATPLOTLIB_AVAILABLE or plt is None:
            return
        # This is a simplified colorbar implementation
        # In production, use proper matplotlib colorbar
        # For now, we skip colorbar as it requires additional matplotlib configuration
        pass
    
    def _add_map_legend(self, ax, map_type: str):
        """Add legend to the map"""
        if not MATPLOTLIB_AVAILABLE or patches is None:
            return
        
        legend_elements = []
        
        if map_type == 'temperature':
            legend_elements = [
                ('< -10°C', 'darkblue'),
                ('-10°C to 0°C', 'blue'),
                ('0°C to 10°C', 'lightblue'),
                ('10°C to 20°C', 'green'),
                ('20°C to 30°C', 'yellow'),
                ('30°C to 40°C', 'orange'),
                ('> 40°C', 'red')
            ]
        elif map_type == 'precipitation':
            legend_elements = [
                ('No precipitation', 'white'),
                ('Light (< 2.5mm)', 'lightblue'),
                ('Moderate (2.5-10mm)', 'blue'),
                ('Heavy (> 10mm)', 'darkblue')
            ]
        elif map_type == 'wind':
            legend_elements = [
                ('Calm (< 5m/s)', 'green'),
                ('Moderate (5-15m/s)', 'yellow'),
                ('Strong (15-25m/s)', 'orange'),
                ('Severe (> 25m/s)', 'red')
            ]
        
        # Add legend to plot
        if legend_elements and MATPLOTLIB_AVAILABLE and MplPatch is not None:
            try:
                legend_patches = [MplPatch(facecolor=color, label=label) 
                                for label, color in legend_elements]
                
                ax.legend(handles=legend_patches, loc='upper right', fontsize=8)
            except Exception as e:
                # Fallback if legend creation fails
                print(f"Warning: Could not create legend: {e}")
    
    def get_weather_animation_frames(self, city: str, hours: int = 24) -> Dict:
        """
        Get weather animation frames for a city.
        
        Args:
            city: City name
            hours: Number of hours for animation
            
        Returns:
            Animation frame URLs
        """
        try:
            if not self.openweather_api_key:
                return {'error': 'OpenWeatherMap API key required'}
            
            # Get forecast data
            forecast_url = f"{self.radar_url}/forecast"
            params = {
                'q': city,
                'appid': self.openweather_api_key,
                'units': 'metric',
                'cnt': hours // 3  # 3-hour intervals
            }
            
            response = requests.get(forecast_url, params=params, timeout=10)
            response.raise_for_status()
            
            forecast_data = response.json()
            
            # Generate animation frames
            frames = []
            for i, item in enumerate(forecast_data['list'][:hours // 3]):
                frame_data = {
                    'timestamp': item['dt_txt'],
                    'temperature': item['main']['temp'],
                    'description': item['weather'][0]['description'],
                    'icon': item['weather'][0]['icon'],
                    'humidity': item['main']['humidity'],
                    'pressure': item['main']['pressure'],
                    'wind_speed': item['wind']['speed'],
                    'frame_number': i + 1
                }
                
                # Generate map URL for this frame
                city_coords = self._get_city_coordinates(city)
                if city_coords:
                    lat, lon = city_coords
                    map_url = self._generate_radar_url(lat, lon, 100)
                    frame_data['map_url'] = map_url
                
                frames.append(frame_data)
            
            return {
                'success': True,
                'city': city,
                'total_frames': len(frames),
                'hours_covered': hours,
                'frames': frames,
                'generated_at': datetime.now().isoformat()
            }
            
        except requests.exceptions.RequestException as e:
            return {'error': f'Failed to get animation frames: {str(e)}'}
        except Exception as e:
            return {'error': f'Error processing animation: {str(e)}'}
    
    def create_weather_comparison_map(self, cities_comparison: Dict) -> Dict:
        """
        Create a weather comparison map between multiple cities.
        
        Args:
            cities_comparison: Comparison data from analytics module
            
        Returns:
            Comparison map image
        """
        try:
            if 'error' in cities_comparison:
                return cities_comparison
            
            # Extract cities and their data
            cities_data = {}
            for city in cities_comparison.get('cities_compared', []):
                # Get current weather for each city (simplified)
                cities_data[city] = {
                    'temperature': cities_comparison.get('metrics', {}).get('temperature', {}).get(city, 20),
                    'humidity': cities_comparison.get('metrics', {}).get('humidity', {}).get(city, 50),
                    'wind_speed': cities_comparison.get('metrics', {}).get('wind_speed', {}).get(city, 5),
                    'pressure': cities_comparison.get('metrics', {}).get('pressure', {}).get(city, 1013)
                }
            
            # Create comparison map
            return self.create_weather_map_image(cities_data, map_type='temperature')
            
        except Exception as e:
            return {'error': f'Failed to create comparison map: {str(e)}'}
    
    def get_map_tile_url(self, lat: float, lon: float, zoom: int, 
                        layer: str = 'precipitation') -> Dict:
        """
        Get map tile URL for specific coordinates.
        
        Args:
            lat: Latitude
            lon: Longitude
            zoom: Zoom level
            layer: Map layer
            
        Returns:
            Tile URL
        """
        try:
            if not self.openweather_api_key:
                return {'error': 'OpenWeatherMap API key required'}
            
            # Convert lat/lon to tile coordinates
            import math
            x = int((lon + 180) / 360 * (2 ** zoom))
            y = int((1 - math.log(math.tan(math.radians(lat)) + 1 / math.cos(math.radians(lat))) / math.pi) / 2 * (2 ** zoom))
            
            # Generate tile URL
            tile_url = f"{self.openweather_layers_url}/{layer}/{zoom}/{x}/{y}"
            params = f"appid={self.openweather_api_key}&opacity=0.8"
            
            return {
                'success': True,
                'tile_url': f"{tile_url}?{params}",
                'tile_coords': {'x': x, 'y': y, 'z': zoom},
                'lat_lon': {'lat': lat, 'lon': lon},
                'layer': layer
            }
            
        except Exception as e:
            return {'error': f'Failed to generate tile URL: {str(e)}'}
    
    def export_map_data(self, map_data: Dict, format_type: str = 'json') -> str:
        """
        Export map data in different formats.
        
        Args:
            map_data: Map data dictionary
            format_type: Export format (json, csv, geojson)
            
        Returns:
            Exported data string
        """
        if format_type == 'json':
            return json.dumps(map_data, indent=2, default=str)
        elif format_type == 'csv':
            return self._export_to_csv(map_data)
        elif format_type == 'geojson':
            return self._export_to_geojson(map_data)
        else:
            return json.dumps(map_data, indent=2, default=str)
    
    def _export_to_csv(self, map_data: Dict) -> str:
        """Export map data to CSV format"""
        import csv
        import io
        
        output = io.StringIO()
        writer = csv.writer(output)
        
        # Write header
        writer.writerow(['City', 'Latitude', 'Longitude', 'Temperature', 'Humidity', 'Wind Speed', 'Pressure'])
        
        # Write data (simplified - would need actual city data)
        if 'cities_data' in map_data:
            for city, data in map_data['cities_data'].items():
                writer.writerow([
                    city,
                    data.get('latitude', ''),
                    data.get('longitude', ''),
                    data.get('temperature', ''),
                    data.get('humidity', ''),
                    data.get('wind_speed', ''),
                    data.get('pressure', '')
                ])
        
        return output.getvalue()
    
    def _export_to_geojson(self, map_data: Dict) -> str:
        """Export map data to GeoJSON format"""
        features = []
        
        if 'cities_data' in map_data:
            for city, data in map_data['cities_data'].items():
                if 'latitude' in data and 'longitude' in data:
                    feature = {
                        "type": "Feature",
                        "geometry": {
                            "type": "Point",
                            "coordinates": [data['longitude'], data['latitude']]
                        },
                        "properties": {
                            "city": city,
                            "temperature": data.get('temperature', 0),
                            "humidity": data.get('humidity', 0),
                            "wind_speed": data.get('wind_speed', 0),
                            "pressure": data.get('pressure', 0)
                        }
                    }
                    features.append(feature)
        
        geojson = {
            "type": "FeatureCollection",
            "features": features
        }
        
        return json.dumps(geojson, indent=2)
768 lines•29.6 KB
python

About RSK World

Founded by Molla Samser, with Designer & Tester Rima Khatun, RSK World is your one-stop destination for free programming resources, source code, and development tools.

Founder: Molla Samser
Designer & Tester: Rima Khatun

Development

  • Game Development
  • Web Development
  • Mobile Development
  • AI Development
  • Development Tools

Legal

  • Terms & Conditions
  • Privacy Policy
  • Disclaimer

Contact Info

Nutanhat, Mongolkote
Purba Burdwan, West Bengal
India, 713147

+91 93305 39277

hello@rskworld.in
support@rskworld.in

© 2026 RSK World. All rights reserved.

Content used for educational purposes only. View Disclaimer