File size: 3,335 Bytes
5fd7795
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
"""
CropAI SporeCast™ GIS Airborne Disease Outbreak & Epidemic Spread Prediction Engine
Simulates fungal spore cloud transport using wind velocity vectors, relative humidity,
and farm cluster density to provide 36-hour early warning alerts to adjacent farming communities.
"""

import math
from typing import Dict, Any, List


class SporeCastEngine:
    """GIS Vector Dispersion & Airborne Spore Epidemic Forecaster."""

    @staticmethod
    def simulate_dispersion(
        source_lat: float,
        source_lng: float,
        disease_name: str,
        wind_speed_kmh: float,
        wind_direction_deg: float,  # 0=North, 90=East, 180=South, 270=West
        humidity_pct: float,
        source_severity_pct: float
    ) -> Dict[str, Any]:
        """
        Simulates downwind spore cloud propagation trajectory over 24h and 48h intervals.
        """
        # Convert wind direction to radians (meteorological: direction wind is coming from)
        rad = math.radians(wind_direction_deg)
        # Vector displacement per 24 hours in km
        disp_24h_km = wind_speed_kmh * 18.0  # effective advection
        disp_48h_km = wind_speed_kmh * 36.0

        # Approximate degrees per km (at equator/tropics ~ 1 deg lat = 111 km)
        d_lat_24h = (disp_24h_km * math.cos(rad)) / 111.0
        d_lng_24h = (disp_24h_km * math.sin(rad)) / (111.0 * math.cos(math.radians(source_lat)))

        d_lat_48h = (disp_48h_km * math.cos(rad)) / 111.0
        d_lng_48h = (disp_48h_km * math.sin(rad)) / (111.0 * math.cos(math.radians(source_lat)))

        pred_lat_24h = round(source_lat + d_lat_24h, 5)
        pred_lng_24h = round(source_lng + d_lng_24h, 5)
        pred_lat_48h = round(source_lat + d_lat_48h, 5)
        pred_lng_48h = round(source_lng + d_lng_48h, 5)

        # Spore Viability Index (high humidity + moderate temp increases survival)
        viability_score = min(0.98, max(0.20, (humidity_pct / 100.0) * 0.95))

        # Risk zone radius in kilometers
        dispersion_radius_km = round(disp_24h_km * 0.45, 1)

        return {
            "disease": disease_name,
            "origin_coordinates": {"lat": source_lat, "lng": source_lng},
            "spore_dispersion_speed_kmh": wind_speed_kmh,
            "effective_wind_direction_degrees": wind_direction_deg,
            "spore_viability_index": round(viability_score, 2),
            "trajectory_forecast_24h": {
                "projected_center_lat": pred_lat_24h,
                "projected_center_lng": pred_lng_24h,
                "threat_radius_km": dispersion_radius_km,
                "estimated_arrival_hours": 18
            },
            "trajectory_forecast_48h": {
                "projected_center_lat": pred_lat_48h,
                "projected_center_lng": pred_lng_48h,
                "threat_radius_km": round(dispersion_radius_km * 1.8, 1),
                "estimated_arrival_hours": 36
            },
            "early_warning_advisory": (
                f"High-risk airborne spore cloud of {disease_name} detected. "
                f"Wind is carrying viable spores at {wind_speed_kmh} km/h toward bearing {int(wind_direction_deg)}°. "
                f"Farms within {dispersion_radius_km} km downwind must apply prophylactic bio-fungicide within 24 hours."
            )
        }


sporecast_engine = SporeCastEngine()