colouring-montreal/etl/join_building_data/load_shapefile.py

130 lines
3.4 KiB
Python
Raw Normal View History

2018-10-20 13:37:02 -04:00
"""Join shapefile data to buildings
This is effectively an example script using the HTTP API, tailored to particular collected
datasets for Camden (age data) and Fitzrovia (number of storeys).
- read through shapes
- locate building by toid
- else locate building by representative point
- update building with data
"""
import os
import sys
from functools import partial
import fiona
import pyproj
import requests
from shapely.geometry import shape
from shapely.ops import transform
osgb_to_ll = partial(
2023-08-15 09:10:19 -04:00
pyproj.transform, pyproj.Proj(init="epsg:27700"), pyproj.Proj(init="epsg:4326")
2018-10-20 13:37:02 -04:00
)
def main(base_url, api_key, process, source_file):
2023-08-15 09:10:19 -04:00
"""Read from file, update buildings"""
with fiona.open(source_file, "r") as source:
2018-10-20 13:37:02 -04:00
for feature in source:
2023-08-15 09:10:19 -04:00
props = feature["properties"]
2018-10-20 13:37:02 -04:00
if process == "camden":
toid, data = process_camden(props)
else:
toid, data = process_fitzrovia(props)
if data is None:
continue
2023-08-15 09:10:19 -04:00
building_id = find_building(toid, feature["geometry"], base_url)
2018-10-20 13:37:02 -04:00
if not building_id:
print("no_match", toid, "-")
continue
save_data(building_id, data, api_key, base_url)
def process_camden(props):
2023-08-15 09:10:19 -04:00
toid = osgb_toid(props["TOID"])
data = {"date_year": props["Year_C"], "date_source_detail": props["Date_sou_1"]}
2018-10-20 13:37:02 -04:00
return toid, data
def process_fitzrovia(props):
2023-08-15 09:10:19 -04:00
toid = osgb_toid(props["TOID"])
storeys = props["Storeys"]
2018-10-20 13:37:02 -04:00
if storeys is None:
return toid, None
2023-08-15 09:10:19 -04:00
if props["Basement"] == "Yes":
data = {"size_storeys_core": int(storeys) - 1, "size_storeys_basement": 1}
2018-10-20 13:37:02 -04:00
else:
2023-08-15 09:10:19 -04:00
data = {"size_storeys_core": int(storeys), "size_storeys_basement": 0}
2018-10-20 13:37:02 -04:00
return toid, data
def osgb_toid(toid):
if toid is None:
toid = ""
return "osgb" + toid.lstrip("0")
def save_data(building_id, data, api_key, base_url):
2023-08-15 09:10:19 -04:00
"""Save data to a building"""
requests.post(
2019-08-14 09:05:49 -04:00
"{}/buildings/{}.json?api_key={}".format(base_url, building_id, api_key),
2023-08-15 09:10:19 -04:00
json=data,
2018-10-20 13:37:02 -04:00
)
def find_building(toid, geom, base_url):
2023-08-15 09:10:19 -04:00
"""Find building_id by TOID or location"""
r = requests.get(
base_url + "/buildings/reference", params={"key": "toid", "id": toid}
)
2018-10-20 13:37:02 -04:00
buildings = r.json()
if buildings and len(buildings) == 1:
2023-08-15 09:10:19 -04:00
bid = buildings[0]["building_id"]
2018-10-20 13:37:02 -04:00
print("match_by_toid", toid, bid)
return bid
# try location
poly = shape(geom)
point_osgb = poly.centroid
if not poly.contains(point_osgb):
point_osgb = poly.representative_point()
point_ll = transform(osgb_to_ll, point_osgb)
2023-08-15 09:10:19 -04:00
r = requests.get(
base_url + "/buildings/locate", params={"lng": point_ll.x, "lat": point_ll.y}
)
2018-10-20 13:37:02 -04:00
buildings = r.json()
if buildings and len(buildings) == 1:
2023-08-15 09:10:19 -04:00
bid = buildings[0]["building_id"]
2018-10-20 13:37:02 -04:00
print("match_by_location", toid, bid)
return bid
return None
2023-08-15 09:10:19 -04:00
if __name__ == "__main__":
2018-10-20 13:37:02 -04:00
try:
2023-08-15 09:10:19 -04:00
url, api_key, process, filename = (
sys.argv[1],
sys.argv[2],
sys.argv[3],
sys.argv[4],
)
2018-10-20 13:37:02 -04:00
except IndexError:
print(
"Usage: {} <URL> <api_key> <camden|fitzrovia> ./path/to/camden.shp".format(
2023-08-15 09:10:19 -04:00
os.path.basename(__file__)
)
)
2018-10-20 13:37:02 -04:00
exit()
main(url, api_key, process, filename)