Commit 5634c975a7d59096bfc18d75005f43f2a0cc1bdd
1 parent
1ae3ccd1
Exists in
master
Expose travel distance as output.
/spend 22h
Showing
3 changed files
with
53 additions
and
48 deletions
Show diff stats
flaskr/controllers/main_controller.py
... | ... | @@ -262,7 +262,8 @@ def compute(): # process the queue of estimation requests |
262 | 262 | |
263 | 263 | destinations_by_city_key = {} |
264 | 264 | |
265 | - cities_sum = {} | |
265 | + cities_sum_foot = {} | |
266 | + cities_sum_dist = {} | |
266 | 267 | for model in emission_models: |
267 | 268 | cities_dict = {} |
268 | 269 | for _destination in _destinations: |
... | ... | @@ -282,11 +283,16 @@ def compute(): # process the queue of estimation requests |
282 | 283 | 'city': city_key, |
283 | 284 | 'address': _destination.address, |
284 | 285 | 'footprint': 0.0, |
286 | + 'distance': 0.0, | |
285 | 287 | } |
286 | - cities_dict[city_key]['footprint'] += footprint | |
287 | - if city_key not in cities_sum: | |
288 | - cities_sum[city_key] = 0.0 | |
289 | - cities_sum[city_key] += footprint | |
288 | + cities_dict[city_key]['footprint'] += footprint['co2eq_kg'] | |
289 | + cities_dict[city_key]['distance'] += footprint['distance'] | |
290 | + if city_key not in cities_sum_foot: | |
291 | + cities_sum_foot[city_key] = 0.0 | |
292 | + cities_sum_foot[city_key] += footprint['co2eq_kg'] | |
293 | + if city_key not in cities_sum_dist: | |
294 | + cities_sum_dist[city_key] = 0.0 | |
295 | + cities_sum_dist[city_key] += footprint['distance'] | |
290 | 296 | |
291 | 297 | cities = [cities_dict[k] for k in cities_dict.keys()] |
292 | 298 | cities = sorted(cities, key=lambda c: c['footprint']) |
... | ... | @@ -297,17 +303,21 @@ def compute(): # process the queue of estimation requests |
297 | 303 | |
298 | 304 | _results['footprints'] = footprints |
299 | 305 | |
300 | - total = 0.0 | |
306 | + total_foot = 0.0 | |
307 | + total_dist = 0.0 | |
301 | 308 | |
302 | 309 | cities_mean_dict = {} |
303 | - for city in cities_sum.keys(): | |
304 | - city_mean = 1.0 * cities_sum[city] / len(emission_models) | |
310 | + for city in cities_sum_foot.keys(): | |
311 | + city_mean_foot = 1.0 * cities_sum_foot[city] / len(emission_models) | |
312 | + city_mean_dist = 1.0 * cities_sum_dist[city] / len(emission_models) | |
305 | 313 | cities_mean_dict[city] = { |
306 | 314 | 'address': destinations_by_city_key[city].address, |
307 | 315 | 'city': city, |
308 | - 'footprint': city_mean, | |
316 | + 'footprint': city_mean_foot, | |
317 | + 'distance': city_mean_dist, | |
309 | 318 | } |
310 | - total += city_mean | |
319 | + total_foot += city_mean_foot | |
320 | + total_dist += city_mean_dist | |
311 | 321 | |
312 | 322 | cities_mean = [cities_mean_dict[k] for k in cities_mean_dict.keys()] |
313 | 323 | cities_mean = sorted(cities_mean, key=lambda c: c['footprint']) |
... | ... | @@ -317,8 +327,10 @@ def compute(): # process the queue of estimation requests |
317 | 327 | } |
318 | 328 | _results['cities'] = cities_mean |
319 | 329 | |
320 | - _results['total'] = total # DEPRECATED | |
321 | - _results['footprint'] = total | |
330 | + _results['total'] = total_foot # DEPRECATED | |
331 | + _results['footprint'] = total_foot | |
332 | + | |
333 | + _results['distance'] = total_dist | |
322 | 334 | |
323 | 335 | return _results |
324 | 336 | |
... | ... | @@ -433,25 +445,17 @@ def consult_estimation(public_id, extension): |
433 | 445 | |
434 | 446 | si = StringIO() |
435 | 447 | cw = csv.writer(si, quoting=csv.QUOTE_ALL) |
436 | - cw.writerow([u"city", u"address", u"co2 (g)"]) | |
448 | + cw.writerow([u"city", u"address", u"co2 (kg)", u"distance (km)"]) | |
437 | 449 | |
438 | 450 | results = estimation.get_output_dict() |
439 | - if 'mean_footprint' in results: | |
440 | - for city in results['mean_footprint']['cities']: | |
441 | - cw.writerow([ | |
442 | - city['city'].encode(OUT_ENCODING), | |
443 | - city['address'].encode(OUT_ENCODING), | |
444 | - city['footprint'] | |
445 | - ]) | |
446 | - elif 'cities' in results: | |
447 | - for city in results['cities']: | |
448 | - cw.writerow([ | |
449 | - city['city'].encode(OUT_ENCODING), | |
450 | - city['address'].encode(OUT_ENCODING), | |
451 | - city['total'] | |
452 | - ]) | |
453 | - | |
454 | - # HTTP headers? | |
451 | + for city in results['cities']: | |
452 | + cw.writerow([ | |
453 | + city['city'].encode(OUT_ENCODING), | |
454 | + city['address'].encode(OUT_ENCODING), | |
455 | + round(city['footprint'], 3), | |
456 | + round(city['distance'], 3), | |
457 | + ]) | |
458 | + | |
455 | 459 | # return si.getvalue().strip('\r\n') |
456 | 460 | return Response( |
457 | 461 | response=si.getvalue().strip('\r\n'), | ... | ... |
flaskr/laws/travel_emission_linear_fit.py
... | ... | @@ -2,6 +2,7 @@ import numpy as np |
2 | 2 | from geopy.distance import great_circle |
3 | 3 | |
4 | 4 | |
5 | +# @abc | |
5 | 6 | class BaseEmissionModel(): |
6 | 7 | def __init__(self, config): # Constructor |
7 | 8 | self.name = config.name |
... | ... | @@ -29,9 +30,10 @@ class EmissionModel(BaseEmissionModel): |
29 | 30 | prefer_train_under_distance=0, # meters |
30 | 31 | ): |
31 | 32 | footprint = 0.0 |
33 | + distance = 0.0 | |
32 | 34 | |
33 | 35 | ############################################# |
34 | - # TODO: find closest airport(s) and pick one | |
36 | + # TODO: find closest airport(s) and pick one? | |
35 | 37 | # We're going to need caching here as well. |
36 | 38 | from collections import namedtuple |
37 | 39 | origin_airport = namedtuple('Position', [ |
... | ... | @@ -55,34 +57,33 @@ class EmissionModel(BaseEmissionModel): |
55 | 57 | # ... TODO |
56 | 58 | |
57 | 59 | # I.b Airplane travel footprint |
58 | - footprint += self.compute_airplane_footprint( | |
60 | + great_circle_distance = self.get_distance_between( | |
59 | 61 | origin_latitude=origin_airport.latitude, |
60 | 62 | origin_longitude=origin_airport.longitude, |
61 | 63 | destination_latitude=destination_airport.latitude, |
62 | 64 | destination_longitude=destination_airport.longitude, |
63 | 65 | ) |
66 | + footprint += self.compute_airplane_footprint( | |
67 | + distance=great_circle_distance | |
68 | + ) | |
69 | + distance += great_circle_distance | |
64 | 70 | |
65 | - # II.a Double the footprint if it's a round-trip | |
71 | + # II.a Double it up since it's a round-trip | |
66 | 72 | footprint *= 2.0 |
73 | + distance *= 2.0 | |
67 | 74 | |
68 | - return footprint | |
75 | + return { | |
76 | + 'distance': distance, | |
77 | + 'co2eq_kg': footprint, | |
78 | + } | |
79 | + # return footprint | |
69 | 80 | |
70 | 81 | def compute_airplane_footprint( |
71 | 82 | self, |
72 | - origin_latitude, | |
73 | - origin_longitude, | |
74 | - destination_latitude, | |
75 | - destination_longitude | |
83 | + distance | |
76 | 84 | ): |
77 | 85 | config = self.config.plane_emission_linear_fit |
78 | 86 | |
79 | - great_circle_distance = self.get_distance_between( | |
80 | - origin_latitude, origin_longitude, | |
81 | - destination_latitude, destination_longitude | |
82 | - ) | |
83 | - | |
84 | - distance = great_circle_distance | |
85 | - | |
86 | 87 | distance = config.connecting_flights_scale * distance |
87 | 88 | |
88 | 89 | footprint = self.compute_airplane_distance_footprint(distance, config) |
... | ... | @@ -111,7 +112,7 @@ class EmissionModel(BaseEmissionModel): |
111 | 112 | """ |
112 | 113 | :param distance: in km |
113 | 114 | :param config: |
114 | - :return: | |
115 | + :return: float | |
115 | 116 | """ |
116 | 117 | footprint = distance |
117 | 118 | for interval in config.intervals: | ... | ... |
flaskr/templates/estimation.html
... | ... | @@ -193,7 +193,7 @@ jQuery(document).ready(function($){ |
193 | 193 | var vizid = "#cities_footprints_d3viz"; |
194 | 194 | var csvUrl = "/estimation/{{ estimation.public_id }}.csv"; |
195 | 195 | var x_key = 'city'; |
196 | - var y_key = 'co2 (g)'; | |
196 | + var y_key = 'co2 (kg)'; | |
197 | 197 | |
198 | 198 | // Set the dimensions and margins of the graph |
199 | 199 | var margin = {top: 10, right: 30, bottom: 150, left: 150}, |
... | ... | @@ -214,7 +214,7 @@ jQuery(document).ready(function($){ |
214 | 214 | d3.csv(csvUrl, function(data) { |
215 | 215 | |
216 | 216 | // Extrema |
217 | - var data_y_max = d3.max(data, function(d) { return parseFloat(d['co2 (g)']); }); | |
217 | + var data_y_max = d3.max(data, function(d) { return parseFloat(d[y_key]); }); | |
218 | 218 | var axis_y_max = ceil_value_to_magnitude(data_y_max); |
219 | 219 | |
220 | 220 | // X axis |
... | ... | @@ -266,7 +266,7 @@ jQuery(document).ready(function($){ |
266 | 266 | var vizid = "#cities_footprints_d3viz_lollipop"; |
267 | 267 | var csvUrl = "/estimation/{{ estimation.public_id }}.csv"; |
268 | 268 | var y_key = 'city'; |
269 | - var x_key = 'co2 (g)'; | |
269 | + var x_key = 'co2 (kg)'; | |
270 | 270 | |
271 | 271 | var margin = {top: 10, right: 30, bottom: 150, left: 150}, |
272 | 272 | height = Math.max(300, 100+16*plots_config['cities_count']) - margin.top - margin.bottom; | ... | ... |