-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathcore.py
More file actions
109 lines (98 loc) · 4 KB
/
Copy pathcore.py
File metadata and controls
109 lines (98 loc) · 4 KB
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
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
"""
core.py
Implement get_location_properties(lat, lon) that:
- loads Survey of India shapefiles from `data/` (lazy loaded)
- performs point-in-polygon lookups (GeoPandas + Shapely)
- returns a small dict with required fields
NOTE: This is a minimal starter skeleton. Update attribute names depending on your SoI shapefile schemas.
"""
import geopandas as gpd
from shapely.geometry import Point
import os
# Update these to match your SoI filenames (place under data/)
SEISMIC_SHP = os.path.join("data", "soi_seismic_zones.shp")
WIND_SHP = os.path.join("data", "soi_wind_regions.shp")
# Lazy-loaded caches
_seismic_gdf = None
_wind_gdf = None
def _load_gdfs():
global _seismic_gdf, _wind_gdf
if _seismic_gdf is None:
if not os.path.exists(SEISMIC_SHP):
raise FileNotFoundError(
f"Missing Survey-of-India seismic shapefile: {SEISMIC_SHP}\n"
"Place SoI shapefile(s) in data/ or update core.py"
)
_seismic_gdf = gpd.read_file(SEISMIC_SHP)
if _wind_gdf is None:
if not os.path.exists(WIND_SHP):
raise FileNotFoundError(
f"Missing Survey-of-India wind shapefile: {WIND_SHP}\n"
"Place SoI shapefile(s) in data/ or update core.py"
)
_wind_gdf = gpd.read_file(WIND_SHP)
def get_location_properties(lat: float, lon: float) -> dict:
"""
Return properties for a given lat, lon.
Output (minimum):
{
'lat': float,
'lon': float,
'seismic_zone': 'II'|'III'|'IV'|'V'|None,
'basic_wind_speed': float|None,
'notes': str
}
"""
_load_gdfs()
pt = Point(lon, lat) # (x=lon, y=lat)
res = {"lat": lat, "lon": lon, "seismic_zone": None, "basic_wind_speed": None, "notes": ""}
# seismic lookup
try:
if hasattr(_seismic_gdf, "sindex") and _seismic_gdf.sindex:
candidate_idx = list(_seismic_gdf.sindex.query(pt))
candidate = _seismic_gdf.iloc[candidate_idx] if candidate_idx else _seismic_gdf
else:
candidate = _seismic_gdf
containing = candidate[candidate.contains(pt)]
if not containing.empty:
# Common field names: 'ZONE', 'zone', 'SeismicZ' etc. Adapt per file.
for key in ("ZONE", "zone", "SeismicZone", "SeisZone", "SEIZONE"):
if key in containing.columns:
res["seismic_zone"] = str(containing.iloc[0][key])
break
# fallback: find string like II/III/IV/V
if res["seismic_zone"] is None:
for c in containing.columns:
val = containing.iloc[0][c]
if isinstance(val, str) and val.strip().upper() in {"II", "III", "IV", "V"}:
res["seismic_zone"] = val.strip().upper()
break
except Exception as e:
res["notes"] += f"Seismic lookup error: {e}. "
# wind lookup
try:
if hasattr(_wind_gdf, "sindex") and _wind_gdf.sindex:
candidate_idx = list(_wind_gdf.sindex.query(pt))
candidate = _wind_gdf.iloc[candidate_idx] if candidate_idx else _wind_gdf
else:
candidate = _wind_gdf
containing = candidate[candidate.contains(pt)]
if not containing.empty:
for key in ("Vb", "vb", "WIND_SPEED", "wind_speed", "BasicWind"):
if key in containing.columns:
try:
res["basic_wind_speed"] = float(containing.iloc[0][key])
break
except Exception:
continue
# fallback: try to coerce first numeric column
if res["basic_wind_speed"] is None:
for c in containing.columns:
try:
res["basic_wind_speed"] = float(containing.iloc[0][c])
break
except Exception:
continue
except Exception as e:
res["notes"] += f"Wind lookup error: {e}. "
return res