"""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( pyproj.transform, pyproj.Proj(init="epsg:27700"), pyproj.Proj(init="epsg:4326") ) def main(base_url, api_key, process, source_file): """Read from file, update buildings""" with fiona.open(source_file, "r") as source: for feature in source: props = feature["properties"] if process == "camden": toid, data = process_camden(props) else: toid, data = process_fitzrovia(props) if data is None: continue building_id = find_building(toid, feature["geometry"], base_url) if not building_id: print("no_match", toid, "-") continue save_data(building_id, data, api_key, base_url) def process_camden(props): toid = osgb_toid(props["TOID"]) data = {"date_year": props["Year_C"], "date_source_detail": props["Date_sou_1"]} return toid, data def process_fitzrovia(props): toid = osgb_toid(props["TOID"]) storeys = props["Storeys"] if storeys is None: return toid, None if props["Basement"] == "Yes": data = {"size_storeys_core": int(storeys) - 1, "size_storeys_basement": 1} else: data = {"size_storeys_core": int(storeys), "size_storeys_basement": 0} 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): """Save data to a building""" requests.post( "{}/buildings/{}.json?api_key={}".format(base_url, building_id, api_key), json=data, ) def find_building(toid, geom, base_url): """Find building_id by TOID or location""" r = requests.get( base_url + "/buildings/reference", params={"key": "toid", "id": toid} ) buildings = r.json() if buildings and len(buildings) == 1: bid = buildings[0]["building_id"] 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) r = requests.get( base_url + "/buildings/locate", params={"lng": point_ll.x, "lat": point_ll.y} ) buildings = r.json() if buildings and len(buildings) == 1: bid = buildings[0]["building_id"] print("match_by_location", toid, bid) return bid return None if __name__ == "__main__": try: url, api_key, process, filename = ( sys.argv[1], sys.argv[2], sys.argv[3], sys.argv[4], ) except IndexError: print( "Usage: {} ./path/to/camden.shp".format( os.path.basename(__file__) ) ) exit() main(url, api_key, process, filename)