-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmake_maps.py
149 lines (125 loc) · 5.65 KB
/
make_maps.py
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
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
import re
import json
import copy
from datetime import timedelta, datetime
# Data is downloaded from https://maps.massgis.digital.mass.gov/MassMapper/MassMapper.html
# Using layer: Massachusetts Municipalities Multipar Polygons
# and exported as lat/lon as shapefile in WGS84
# Downloaded data is passed to https://mapshaper.org/
# and simplified to > 5 % of the original file size, fixing any line crossings.
# The resulting data is saved as MA_towns.json into this repository.
# Date a which the timeline ends. Needs to be later than the last date in the data
# but it's eaiser to update here by hand than to search through the data to find it.
enddate = "01/02/2026"
with open('MA_towns.json') as f:
data = json.load(f)
for i, f in enumerate(data['features']):
f['id'] = f['properties']['town']
# Parse input data in three files
fossil_fuel_free_table = re.compile("(?P<name>[a-zA-Z\ ]+)\ (?P<date>[0-9/]+)")
stretch_code_table = re.compile("(?P<name>[a-zA-Z\ ]+)\ [0-9\,]+ (?P<date>[0-9/]+)")
specialized_code_table = re.compile("(?P<name>[a-zA-Z\ ]+)\ [0-9\,]+ (?P<date>[0-9/]+) (?P<specialdate>[0-9/]*)")
# Stretch code
stretch_code = {}
specialized_opt_in = {}
with open('code_dates.dat') as f:
for line in f:
out = stretch_code_table.search(line)
if out is not None:
stretch_code[out.group('name')] = out.group('date')
out = specialized_code_table.search(line)
if out is not None:
specialized_opt_in[out.group('name')] = out.group('specialdate')
# Approved list of fossil-fuel free pilot towns
fossil_fuel_free = {}
with open('fossil_fuel_free.dat') as f:
for line in f:
out = fossil_fuel_free_table.search(line)
if out is None:
# Just the name of the town, no date
fossil_fuel_free[line.strip()] = "draft"
else:
# Name and date
fossil_fuel_free[out.group("name")] = out.group("date")
print(fossil_fuel_free)
print(f'Number of municipalities in geojson file: {len(data["features"])}')
print(f'Number of municipalities with base code: {len(data["features"]) - len(stretch_code)}')
print(f'Number of municipalities with stretch code (incl. those with opt-in stretch code): {len(stretch_code) - len(specialized_opt_in)}')
print(f'Number of municipalities with specialized opt-in stretch code: {len(specialized_opt_in)}')
print(f'Number of municipalities with fossil-fuel free: {len(fossil_fuel_free)}')
def USdate_to_ISO(datestr, subtractdays=0):
return (datetime.strptime(datestr, '%m/%d/%Y') -
timedelta(days=subtractdays)).isoformat()
# Now we build up the geojson files with the data we want to display
featurelist = [] # for timeline
featurelist_future = [] # for plain version, capture last known date
for town in data['features']:
name = town['properties']['town'].title()
feature = {'type': 'Feature',
'geometry': town['geometry'],
'properties': town['properties']}
feature['properties']['stretchcode'] = stretch_code.get(name, 'not yet')
feature['properties']['optinstretchcode'] = specialized_opt_in.get(name, 'not yet')
if name in fossil_fuel_free:
feature["properties"][
"fossilfuel"
] = f"Fossil Fuel Free prioritized community: {fossil_fuel_free[name]}"
else:
feature["properties"]["fossilfuel"] = ""
# Special case for towns that left the stretch code program
if name == 'Essex':
feature['properties']['stretchcode'] = '1/1/2015 - 5/8/2023'
dates = [
("01/01/2009", 0),
("01/01/2015", 1),
("05/08/2023", -1),
(enddate, None),
]
elif name == 'Rochester':
feature['properties']['stretchcode'] = '1/1/2019 - 5/22/2023'
dates = [
("01/01/2009", 0),
("01/01/2019", 1),
("05/22/2023", -1),
(enddate, None),
]
else:
dates = [("01/01/2009", 0), (enddate, None)]
if name in stretch_code:
dates.append((stretch_code.get(name), 1))
if name in specialized_opt_in:
dates.append((specialized_opt_in.get(name), 1))
if name in fossil_fuel_free:
if fossil_fuel_free[name] == "draft":
dates.append(("07/01/2024", 10))
else:
dates.append((fossil_fuel_free[name], 10))
dates.sort(key=lambda x: datetime.strptime(x[0], '%m/%d/%Y'))
codecolor = 0
for i, d in enumerate(dates[:-1]):
codecolor = codecolor + d[1]
code = copy.deepcopy(feature)
code['properties']['code_color'] = codecolor
code['properties']['start'] = USdate_to_ISO(d[0])
code['properties']['end'] = USdate_to_ISO(dates[i + 1][0], subtractdays=1)
featurelist.append(code)
# Add last known data point - the one most in the future
# i.e. the last thing the town has adopted so far
featurelist_future.append(code)
# And write it into docs/MA_energy_codes_town.js such that it's read directly as a javascript file
# That way, we get a file very similar to https://leafletjs.com/examples/choropleth/
outdata = {'type': 'FeatureCollection', 'features': featurelist}
with open('docs/MA_energy_codes_town.js', 'w') as f:
f.write('var townsData = ' + json.dumps(outdata) + ';')
outdata = {'type': 'FeatureCollection', 'features': featurelist_future}
with open('docs/MA_energy_codes_town_future.js', 'w') as f:
f.write('var townsData = ' + json.dumps(outdata) + ';')
base_code = []
for town in data['features']:
name = town['properties']['town'].title()
if name not in stretch_code:
base_code.append(name)
base_code.sort()
for name in base_code:
print(name)
print(len(base_code))