2018-03-16 21:38:57 -07:00
|
|
|
import fiona
|
|
|
|
from shapely.geometry import shape, mapping
|
|
|
|
|
|
|
|
import requests
|
|
|
|
import logging
|
|
|
|
import json
|
2021-05-12 23:57:07 -07:00
|
|
|
import sys
|
2018-03-16 21:38:57 -07:00
|
|
|
|
|
|
|
import argparse
|
|
|
|
|
2018-05-15 07:24:17 -07:00
|
|
|
parser = argparse.ArgumentParser(description='Add unique ne_id to Natural Earth theme features based on Brooklyn Ints.')
|
2018-03-16 21:38:57 -07:00
|
|
|
parser.add_argument("--input", "-i", type=str, required=True)
|
|
|
|
parser.add_argument("--output", "-o", type=str, required=True)
|
|
|
|
args = parser.parse_args()
|
|
|
|
|
|
|
|
def generate_id():
|
|
|
|
|
2021-05-12 23:57:07 -07:00
|
|
|
url = 'https://api.brooklynintegers.com/rest/'
|
2018-03-16 21:38:57 -07:00
|
|
|
params = {'method':'brooklyn.integers.create'}
|
|
|
|
|
|
|
|
try :
|
|
|
|
rsp = requests.post(url, params=params)
|
|
|
|
data = rsp.content
|
|
|
|
except Exception, e:
|
|
|
|
logging.error(e)
|
|
|
|
return 0
|
|
|
|
|
|
|
|
try:
|
|
|
|
data = json.loads(data)
|
|
|
|
except Exception, e:
|
|
|
|
logging.error(e)
|
|
|
|
return 0
|
|
|
|
|
|
|
|
return data.get('integer', 0)
|
|
|
|
|
|
|
|
|
|
|
|
with fiona.open( args.input, 'r', encoding='utf-8' ) as source:
|
|
|
|
|
|
|
|
# Copy the source schema and add two new properties.
|
|
|
|
sink_schema = source.schema.copy()
|
|
|
|
|
|
|
|
# add ne_id property if not present in the schema add it
|
|
|
|
if not hasattr( sink_schema['properties'], 'ne_id'):
|
2021-05-12 23:57:07 -07:00
|
|
|
sink_schema['properties']['ne_id'] = 'int'
|
2018-03-16 21:38:57 -07:00
|
|
|
|
|
|
|
# Create a sink for processed features with the same format and
|
|
|
|
# coordinate reference system as the source.
|
|
|
|
with fiona.open(
|
|
|
|
args.output, 'w',
|
|
|
|
crs=source.crs,
|
|
|
|
driver=source.driver,
|
|
|
|
encoding='utf-8',
|
|
|
|
schema=sink_schema,
|
|
|
|
) as sink:
|
|
|
|
|
2021-05-12 23:57:07 -07:00
|
|
|
# setup counter to track which feature we're on
|
|
|
|
f_counter = 1
|
|
|
|
total_features = len(list(source))
|
|
|
|
|
2018-03-16 21:38:57 -07:00
|
|
|
for feature in source:
|
2021-05-12 23:57:07 -07:00
|
|
|
# report which feature we're processing
|
|
|
|
sys.stdout.write("\r " + str(f_counter) + " of " + str(total_features))
|
|
|
|
# but don't spam with new lines
|
|
|
|
sys.stdout.flush()
|
2018-03-16 21:38:57 -07:00
|
|
|
|
|
|
|
try:
|
|
|
|
|
2021-05-12 23:57:07 -07:00
|
|
|
# when a feature's ne_id property is null or 0 then request a new Brooklyn Int and store that to the feature's ne_id property
|
|
|
|
if not hasattr( sink_schema['properties'], 'ne_id'):
|
2018-03-16 21:38:57 -07:00
|
|
|
|
2021-05-12 23:57:07 -07:00
|
|
|
# Add the signed area of the polygon and a timestamp
|
|
|
|
# to the feature properties map.
|
|
|
|
feature['properties'].update(
|
|
|
|
ne_id = generate_id() )
|
2018-03-16 21:38:57 -07:00
|
|
|
|
2021-05-12 23:57:07 -07:00
|
|
|
sink.write(feature)
|
2018-03-16 21:38:57 -07:00
|
|
|
|
2021-05-12 23:57:07 -07:00
|
|
|
else:
|
|
|
|
if feature['properties']['ne_id'] is null or feature['properties']['ne_id'] == 0:
|
2018-03-16 21:38:57 -07:00
|
|
|
|
2021-05-12 23:57:07 -07:00
|
|
|
# Add the signed area of the polygon and a timestamp
|
|
|
|
# to the feature properties map.
|
|
|
|
feature['properties'].update(
|
|
|
|
ne_id = generate_id() )
|
2018-03-16 21:38:57 -07:00
|
|
|
|
2021-05-12 23:57:07 -07:00
|
|
|
sink.write(feature)
|
2018-03-16 21:38:57 -07:00
|
|
|
|
|
|
|
except Exception, e:
|
|
|
|
logging.exception("Error processing feature %s:", feature['id'])
|
2021-05-12 23:57:07 -07:00
|
|
|
|
|
|
|
# increment counter
|
|
|
|
f_counter += 1
|
2018-03-16 21:38:57 -07:00
|
|
|
|
|
|
|
# The sink file is written to disk and closed when its block ends.
|