| """ |
| Weather Data Analyzer |
| Statistical analysis of weather data |
| """ |
|
|
| import statistics |
| from globals import ( |
| TEMP_COLD_THRESHOLD, TEMP_HOT_THRESHOLD, |
| WIND_CALM, WIND_MODERATE, WIND_STRONG, |
| PRECIP_LIGHT, PRECIP_MODERATE, PRECIP_HEAVY, |
| DECIMAL_PLACES |
| ) |
|
|
| class WeatherAnalyzer: |
| def __init__(self): |
| self.data_points = [] |
| |
| def add_data(self, weather_data): |
| """ |
| Add weather data for analysis |
| """ |
| self.data_points.append(weather_data) |
| |
| def get_temperature_stats(self): |
| """ |
| Calculate temperature statistics |
| """ |
| temps = [d.temperature for d in self.data_points if d.temperature is not None] |
| |
| if not temps: |
| return None |
| |
| stats = { |
| 'count': len(temps), |
| 'mean': round(statistics.mean(temps), DECIMAL_PLACES), |
| 'median': round(statistics.median(temps), DECIMAL_PLACES), |
| 'min': round(min(temps), DECIMAL_PLACES), |
| 'max': round(max(temps), DECIMAL_PLACES) |
| } |
| |
| if len(temps) > 1: |
| stats['stdev'] = round(statistics.stdev(temps), DECIMAL_PLACES) |
| |
| return stats |
| |
| def get_humidity_stats(self): |
| """ |
| Calculate humidity statistics |
| """ |
| humidity = [d.humidity for d in self.data_points if d.humidity is not None] |
| |
| if not humidity: |
| return None |
| |
| return { |
| 'mean': round(statistics.mean(humidity), DECIMAL_PLACES), |
| 'median': round(statistics.median(humidity), DECIMAL_PLACES), |
| 'min': round(min(humidity), DECIMAL_PLACES), |
| 'max': round(max(humidity), DECIMAL_PLACES) |
| } |
| |
| def classify_temperature(self, temp): |
| """ |
| Classify temperature as cold, mild, or hot |
| """ |
| if temp < TEMP_COLD_THRESHOLD: |
| return "Cold" |
| elif temp > TEMP_HOT_THRESHOLD: |
| return "Hot" |
| else: |
| return "Mild" |
| |
| def classify_wind(self, speed): |
| """ |
| Classify wind speed |
| """ |
| if speed < WIND_CALM: |
| return "Calm" |
| elif speed < WIND_MODERATE: |
| return "Moderate" |
| elif speed < WIND_STRONG: |
| return "Strong" |
| else: |
| return "Severe" |
| |
| def classify_precipitation(self, precip): |
| """ |
| Classify precipitation intensity |
| """ |
| if precip < PRECIP_LIGHT: |
| return "Light" |
| elif precip < PRECIP_MODERATE: |
| return "Moderate" |
| elif precip < PRECIP_HEAVY: |
| return "Heavy" |
| else: |
| return "Very Heavy" |
| |
| def get_weather_distribution(self): |
| """ |
| Get distribution of weather conditions |
| """ |
| distribution = { |
| 'Cold': 0, |
| 'Mild': 0, |
| 'Hot': 0 |
| } |
| |
| for data in self.data_points: |
| if data.temperature is not None: |
| classification = self.classify_temperature(data.temperature) |
| distribution[classification] += 1 |
| |
| return distribution |
| |
| def find_extreme_days(self): |
| """ |
| Find days with extreme weather |
| """ |
| extreme_days = [] |
| |
| for data in self.data_points: |
| if data.is_extreme_weather(): |
| extreme_days.append(data) |
| |
| return extreme_days |
| |
| def calculate_comfort_index(self, temp, humidity): |
| """ |
| Calculate simple comfort index |
| """ |
| if temp is None or humidity is None: |
| return None |
| |
| |
| if temp > 27: |
| heat_index = temp + (0.5 * (humidity - 50)) |
| if heat_index > 32: |
| return "Uncomfortable" |
| |
| if temp < 10: |
| return "Cold" |
| |
| if humidity > 80: |
| return "Humid" |
| |
| return "Comfortable" |
| |
| def get_average_by_location(self): |
| """ |
| Calculate average temperature by location |
| """ |
| location_temps = {} |
| |
| for data in self.data_points: |
| if data.temperature is None: |
| continue |
| |
| if data.location not in location_temps: |
| location_temps[data.location] = [] |
| |
| location_temps[data.location].append(data.temperature) |
| |
| averages = {} |
| for location, temps in location_temps.items(): |
| averages[location] = round(statistics.mean(temps), DECIMAL_PLACES) |
| |
| return averages |
| |
| def detect_trend(self): |
| """ |
| Detect if temperature is trending up or down |
| """ |
| if len(self.data_points) < 3: |
| return "Insufficient data" |
| |
| temps = [d.temperature for d in self.data_points if d.temperature is not None] |
| |
| if len(temps) < 3: |
| return "Insufficient data" |
| |
| |
| first_half = temps[:len(temps)//2] |
| second_half = temps[len(temps)//2:] |
| |
| avg_first = statistics.mean(first_half) |
| avg_second = statistics.mean(second_half) |
| |
| diff = avg_second - avg_first |
| |
| if abs(diff) < 1: |
| return "Stable" |
| elif diff > 0: |
| return "Warming" |
| else: |
| return "Cooling" |
|
|