cetk 0.0.4.dev0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (60) hide show
  1. cetk/__init__.py +87 -0
  2. cetk/db.py +41 -0
  3. cetk/edb/__init__.py +0 -0
  4. cetk/edb/apps.py +9 -0
  5. cetk/edb/cache.py +249 -0
  6. cetk/edb/const.py +26 -0
  7. cetk/edb/copy.py +18 -0
  8. cetk/edb/exporters.py +551 -0
  9. cetk/edb/importers/__init__.py +36 -0
  10. cetk/edb/importers/activity_import.py +279 -0
  11. cetk/edb/importers/codeset_import.py +124 -0
  12. cetk/edb/importers/gridsource_import.py +256 -0
  13. cetk/edb/importers/roadsource_import.py +1602 -0
  14. cetk/edb/importers/source_import.py +958 -0
  15. cetk/edb/importers/timevar_import.py +115 -0
  16. cetk/edb/importers/utils.py +92 -0
  17. cetk/edb/importers/validation.py +207 -0
  18. cetk/edb/ltreefield.py +76 -0
  19. cetk/edb/migrations/0001_initial.py +1731 -0
  20. cetk/edb/migrations/0002_data.py +156 -0
  21. cetk/edb/migrations/0003_create_gpkg_tables.py +14 -0
  22. cetk/edb/migrations/__init__.py +0 -0
  23. cetk/edb/models/__init__.py +49 -0
  24. cetk/edb/models/base.py +52 -0
  25. cetk/edb/models/common_models.py +144 -0
  26. cetk/edb/models/fleets.py +160 -0
  27. cetk/edb/models/gridsource_models.py +163 -0
  28. cetk/edb/models/road_classes.py +197 -0
  29. cetk/edb/models/road_models.py +413 -0
  30. cetk/edb/models/source_models.py +399 -0
  31. cetk/edb/models/timevar_models.py +111 -0
  32. cetk/edb/rasterize/__init__.py +1 -0
  33. cetk/edb/rasterize/rasterizer.py +1544 -0
  34. cetk/edb/signals.py +43 -0
  35. cetk/edb/traffic.py +75 -0
  36. cetk/edb/units.py +160 -0
  37. cetk/emissions/__init__.py +0 -0
  38. cetk/emissions/aggregate_emissions.sql +303 -0
  39. cetk/emissions/areasource_emissions.sql +53 -0
  40. cetk/emissions/calc.py +148 -0
  41. cetk/emissions/filters.py +179 -0
  42. cetk/emissions/gridsource_emissions.sql +52 -0
  43. cetk/emissions/pointsource_emissions.sql +53 -0
  44. cetk/emissions/queries.py +221 -0
  45. cetk/emissions/roadsource_emissions.sql +211 -0
  46. cetk/emissions/used_substances.sql +56 -0
  47. cetk/emissions/views.py +89 -0
  48. cetk/logging.py +68 -0
  49. cetk/settings.py +85 -0
  50. cetk/tools/__init__.py +1 -0
  51. cetk/tools/cetk_command.py +599 -0
  52. cetk/tools/manage.py +24 -0
  53. cetk/tools/utils.py +334 -0
  54. cetk/utils.py +62 -0
  55. cetk-0.0.4.dev0.dist-info/LICENSE +201 -0
  56. cetk-0.0.4.dev0.dist-info/METADATA +297 -0
  57. cetk-0.0.4.dev0.dist-info/RECORD +60 -0
  58. cetk-0.0.4.dev0.dist-info/WHEEL +5 -0
  59. cetk-0.0.4.dev0.dist-info/entry_points.txt +3 -0
  60. cetk-0.0.4.dev0.dist-info/top_level.txt +1 -0
cetk/edb/signals.py ADDED
@@ -0,0 +1,43 @@
1
+ """signals issued by edb."""
2
+
3
+ from typing import Union
4
+
5
+ from django.db.backends.signals import connection_created
6
+ from django.dispatch import receiver
7
+
8
+ DEFAULT_TRAFFIC_CONDITIONS = str(24 * [7 * [1.0]])
9
+ DEFAULT_TRAFFIC_FLOW = str(24 * [7 * [100.0]])
10
+
11
+
12
+ def condition_weight(
13
+ cond_str: Union[str, None],
14
+ typeday_str: Union[str, None],
15
+ typeday_sum: Union[float, None],
16
+ cond: int,
17
+ ):
18
+ """
19
+ calculate fraction of week with a given traffic condition (level of service).
20
+ """
21
+
22
+ # CongestionProfile.traffic condition and FlowTimevar.typeday
23
+ # are arrays formatted as strings to alow storing in sqlite
24
+
25
+ # They are converted to sequences of floats
26
+ cond_str = cond_str or DEFAULT_TRAFFIC_CONDITIONS
27
+ typeday_str = typeday_str or DEFAULT_TRAFFIC_FLOW
28
+
29
+ hourly_conditions = map(
30
+ float, cond_str.replace("[", "").replace("]", "").split(",")
31
+ )
32
+ hourly_flow = map(float, typeday_str.replace("[", "").replace("]", "").split(","))
33
+
34
+ # filter hours with a given level of service, and sum flow during those hours
35
+ veh_hours_with_cond = sum(
36
+ flow for level, flow in zip(hourly_conditions, hourly_flow) if level == cond
37
+ )
38
+ return veh_hours_with_cond / typeday_sum
39
+
40
+
41
+ @receiver(connection_created)
42
+ def extend_sqlite(connection=None, **kwargs):
43
+ connection.connection.create_function("condition_weight", 4, condition_weight)
cetk/edb/traffic.py ADDED
@@ -0,0 +1,75 @@
1
+ import pandas as pd
2
+
3
+ from cetk.edb.models import CongestionProfile
4
+
5
+ LoS = CongestionProfile.LevelOfService
6
+ # We express the adjustments as differences to be able to vectorize
7
+ # the operations in get_traffic_velocity().
8
+ VELOCITY_ADJUSTMENTS = {
9
+ 20: {
10
+ "light": {LoS.FREEFLOW: +10, LoS.HEAVY: +10, LoS.SATURATED: -5},
11
+ "heavy": {LoS.FREEFLOW: +10, LoS.HEAVY: +10, LoS.SATURATED: -5},
12
+ },
13
+ 30: {
14
+ "light": {LoS.FREEFLOW: +10, LoS.HEAVY: +10, LoS.SATURATED: -5},
15
+ "heavy": {LoS.FREEFLOW: +10, LoS.HEAVY: +10, LoS.SATURATED: -5},
16
+ },
17
+ 40: {
18
+ "light": {LoS.FREEFLOW: +10, LoS.HEAVY: 0, LoS.SATURATED: -10},
19
+ "heavy": {LoS.FREEFLOW: +5, LoS.HEAVY: 0, LoS.SATURATED: -10},
20
+ },
21
+ 50: {
22
+ "light": {LoS.FREEFLOW: +10, LoS.HEAVY: 0, LoS.SATURATED: -10},
23
+ "heavy": {LoS.FREEFLOW: +5, LoS.HEAVY: 0, LoS.SATURATED: -10},
24
+ },
25
+ 60: {
26
+ "light": {LoS.FREEFLOW: +10, LoS.HEAVY: 0, LoS.SATURATED: -10},
27
+ "heavy": {LoS.FREEFLOW: +5, LoS.HEAVY: 0, LoS.SATURATED: -10},
28
+ },
29
+ 70: {
30
+ "light": {LoS.FREEFLOW: +10, LoS.HEAVY: 0, LoS.SATURATED: -10},
31
+ "heavy": {LoS.FREEFLOW: 0, LoS.HEAVY: 0, LoS.SATURATED: -10},
32
+ },
33
+ 80: {
34
+ "light": {LoS.FREEFLOW: +10, LoS.HEAVY: 0, LoS.SATURATED: -10},
35
+ "heavy": {LoS.FREEFLOW: 0, LoS.HEAVY: 0, LoS.SATURATED: -10},
36
+ },
37
+ 90: {
38
+ "light": {LoS.FREEFLOW: +10, LoS.HEAVY: 0, LoS.SATURATED: -15},
39
+ "heavy": {LoS.FREEFLOW: 0, LoS.HEAVY: 0, LoS.SATURATED: -15},
40
+ },
41
+ 100: {
42
+ "light": {LoS.FREEFLOW: +10, LoS.HEAVY: 0, LoS.SATURATED: -20},
43
+ "heavy": {LoS.FREEFLOW: -10, LoS.HEAVY: -10, LoS.SATURATED: -20},
44
+ },
45
+ 110: {
46
+ "light": {LoS.FREEFLOW: +10, LoS.HEAVY: -10, LoS.SATURATED: -25},
47
+ "heavy": {LoS.FREEFLOW: -20, LoS.HEAVY: -20, LoS.SATURATED: -25},
48
+ },
49
+ 120: {
50
+ "light": {LoS.FREEFLOW: +10, LoS.HEAVY: -10, LoS.SATURATED: -30},
51
+ "heavy": {LoS.FREEFLOW: -30, LoS.HEAVY: -30, LoS.SATURATED: -30},
52
+ },
53
+ 130: {
54
+ "light": {LoS.FREEFLOW: +10, LoS.HEAVY: -10, LoS.SATURATED: -40},
55
+ "heavy": {LoS.FREEFLOW: -40, LoS.HEAVY: -40, LoS.SATURATED: -40},
56
+ },
57
+ 140: {
58
+ "light": {LoS.FREEFLOW: +10, LoS.HEAVY: -10, LoS.SATURATED: -40},
59
+ "heavy": {LoS.FREEFLOW: -50, LoS.HEAVY: -50, LoS.SATURATED: -50},
60
+ },
61
+ }
62
+
63
+
64
+ def los_to_velocity(los_series, posted_speed):
65
+ """derive dynamic vehicle speed from level of service and posted speed."""
66
+ adjustments = VELOCITY_ADJUSTMENTS[posted_speed]
67
+ v_li = pd.Series(posted_speed, index=los_series.index, name="V(li)")
68
+ for los, delta in adjustments["light"].items():
69
+ v_li[los_series == los] += delta
70
+ v_li[los_series == LoS.STOPNGO] = 10 if posted_speed < 70 else 20
71
+ v_he = pd.Series(posted_speed, index=los_series.index, name="V(he)")
72
+ for los, delta in adjustments["heavy"].items():
73
+ v_he[los_series == los] += delta
74
+ v_he[los_series == LoS.STOPNGO] = 10 if posted_speed < 70 else 20
75
+ return v_li, v_he
cetk/edb/units.py ADDED
@@ -0,0 +1,160 @@
1
+ """Utility functions for managing emission units."""
2
+
3
+
4
+ MASS_UNIT_TO_KILOGRAMS = {
5
+ "ng": 1.0e-12,
6
+ "µg": 1.0e-9, # support both micro letter and small greek letter mu
7
+ "μg": 1.0e-9,
8
+ "microg": 1.0e-9,
9
+ "mg": 1.0e-6,
10
+ "g": 0.001,
11
+ "hg": 0.1,
12
+ "kg": 1.0,
13
+ "ton": 1000,
14
+ "tonne": 1000,
15
+ "t": 1000,
16
+ "Mg": 1000,
17
+ "kt": 1.0e6,
18
+ "Gg": 1.0e6,
19
+ "Tg": 1.0e9,
20
+ }
21
+
22
+ TIME_UNIT_TO_SECONDS = {
23
+ "ms": 1.0e-3,
24
+ "s": 1.0,
25
+ "min": 60,
26
+ "h": 3600,
27
+ "hour": 3600,
28
+ "day": 3600 * 24,
29
+ "year": 3600 * 24 * 365.25,
30
+ "yr": 3600 * 24 * 365.25,
31
+ }
32
+
33
+ ENERGY_UNIT_TO_GIGAJOULES = {
34
+ "J": 1.0e-39,
35
+ "kWh": 3.6e-3,
36
+ "MWh": 3.6,
37
+ "GJ": 1.0,
38
+ }
39
+
40
+ LENGTH_UNIT_TO_METERS = {"km": 1000, "m": 1.0}
41
+
42
+
43
+ def emission_unit_to_si(value, unit):
44
+ """convert value to si-units (kg/s)."""
45
+
46
+ try:
47
+ mass_unit, time_unit = unit.split("/")
48
+ except ValueError:
49
+ raise ValueError(f"conversion of emission unit {unit} is not supported")
50
+
51
+ try:
52
+ return (
53
+ value * MASS_UNIT_TO_KILOGRAMS[mass_unit] / TIME_UNIT_TO_SECONDS[time_unit]
54
+ )
55
+ except KeyError:
56
+ if mass_unit not in MASS_UNIT_TO_KILOGRAMS:
57
+ raise KeyError(f"no conversion factor defined for mass-unit {mass_unit}")
58
+ else:
59
+ raise KeyError(f"no conversion factor defined for time-unit {time_unit}")
60
+
61
+
62
+ def emis_conversion_factor_from_si(unit):
63
+ try:
64
+ mass_unit, time_unit = unit.split("/")
65
+ except ValueError:
66
+ raise ValueError(f"conversion of emission unit {unit} is not supported")
67
+
68
+ try:
69
+ return TIME_UNIT_TO_SECONDS[time_unit] / MASS_UNIT_TO_KILOGRAMS[mass_unit]
70
+ except KeyError:
71
+ if mass_unit not in MASS_UNIT_TO_KILOGRAMS:
72
+ raise KeyError(f"no conversion factor defined for mass-unit {mass_unit}")
73
+ else:
74
+ raise KeyError(f"no conversion factor defined for time-unit {time_unit}")
75
+
76
+
77
+ def vehicle_ef_unit_to_si(value, mass_unit, length_unit):
78
+ """convert mass/(veh*length) to si-units kg/(veh*m)."""
79
+
80
+ try:
81
+ return (
82
+ value
83
+ * MASS_UNIT_TO_KILOGRAMS[mass_unit]
84
+ / LENGTH_UNIT_TO_METERS[length_unit]
85
+ )
86
+ except KeyError:
87
+ if mass_unit not in MASS_UNIT_TO_KILOGRAMS:
88
+ raise KeyError(f"no conversion factor defined for mass-unit {mass_unit}")
89
+ else:
90
+ raise KeyError(
91
+ f"no conversion factor defined for length-unit {length_unit}"
92
+ )
93
+
94
+
95
+ def activity_rate_unit_to_si(value, unit):
96
+ """convert activity rate unit to si-units [s⁻¹]."""
97
+
98
+ activity_unit, time_unit = unit.split("/")
99
+ try:
100
+ return value / TIME_UNIT_TO_SECONDS[time_unit]
101
+ except KeyError:
102
+ raise KeyError(f"no conversion factor defined for time-unit {time_unit}")
103
+
104
+
105
+ def activity_rate_unit_from_si(value, unit):
106
+ """convert activity rate from si-units [s⁻¹]."""
107
+
108
+ activity_unit, time_unit = unit.split("/")
109
+ try:
110
+ return value * TIME_UNIT_TO_SECONDS[time_unit]
111
+ except KeyError:
112
+ raise KeyError(f"no conversion factor defined for time-unit {time_unit}")
113
+
114
+
115
+ def activity_ef_unit_to_si(value, unit):
116
+ """convert activity emission factor unit to si-units [kg]."""
117
+
118
+ mass_unit, activity_unit = unit.split("/")
119
+ try:
120
+ return value * MASS_UNIT_TO_KILOGRAMS[mass_unit]
121
+ except KeyError:
122
+ raise KeyError(f"no conversion factor defined for mass-unit {mass_unit}")
123
+
124
+
125
+ def heating_demand_unit_to_si(value, unit):
126
+ """convert heating demand unit to (almost) si-units [GJ s⁻¹]."""
127
+
128
+ energy_unit, time_unit = unit.split("/")
129
+ try:
130
+ return (
131
+ value
132
+ * ENERGY_UNIT_TO_GIGAJOULES[energy_unit]
133
+ / TIME_UNIT_TO_SECONDS[time_unit]
134
+ )
135
+ except KeyError:
136
+ if time_unit not in TIME_UNIT_TO_SECONDS:
137
+ raise KeyError(f"no conversion factor defined for time-unit {time_unit}")
138
+ else:
139
+ raise KeyError(
140
+ f"no conversion factor defined for energy-unit {energy_unit}"
141
+ )
142
+
143
+
144
+ def heating_ef_unit_to_si(value, unit):
145
+ """convert heating emission factor unit to (almost) si-units [kg/GJ]."""
146
+
147
+ mass_unit, energy_unit = unit.split("/")
148
+ try:
149
+ return (
150
+ value
151
+ * MASS_UNIT_TO_KILOGRAMS[mass_unit]
152
+ / ENERGY_UNIT_TO_GIGAJOULES[energy_unit]
153
+ )
154
+ except KeyError:
155
+ if mass_unit not in MASS_UNIT_TO_KILOGRAMS:
156
+ raise KeyError(f"no conversion factor defined for mass-unit {mass_unit}")
157
+ else:
158
+ raise KeyError(
159
+ f"no conversion factor defined for energy-unit {energy_unit}"
160
+ )
File without changes
@@ -0,0 +1,303 @@
1
+ WITH
2
+ point_source as (
3
+ SELECT sources.id as source_id, timevar_id,
4
+ ST_Transform(geom, {srid}) as geom,
5
+ ac1.code as ac1, ac2.code as ac2, ac3.code as ac3
6
+ FROM edb_pointsource as sources
7
+ LEFT JOIN edb_activitycode as ac1 ON ac1.id = sources.activitycode1_id
8
+ LEFT JOIN edb_activitycode as ac2 ON ac2.id = sources.activitycode2_id
9
+ LEFT JOIN edb_activitycode as ac3 ON ac3.id = sources.activitycode3_id
10
+ {point_source_filter}
11
+ ),
12
+ area_source as (
13
+ SELECT sources.id as source_id, timevar_id,
14
+ ST_Transform(geom, {srid}) as geom,
15
+ ac1.code as ac1, ac2.code as ac2, ac3.code as ac3
16
+ FROM edb_areasource as sources
17
+ LEFT JOIN edb_activitycode as ac1 ON ac1.id = sources.activitycode1_id
18
+ LEFT JOIN edb_activitycode as ac2 ON ac2.id = sources.activitycode2_id
19
+ LEFT JOIN edb_activitycode as ac3 ON ac3.id = sources.activitycode3_id
20
+ {area_source_filter}
21
+ ),
22
+ grid_source as (
23
+ SELECT sources.id as source_id, timevar_id,
24
+ ac1.code as ac1, ac2.code as ac2, ac3.code as ac3
25
+ FROM edb_gridsource as sources
26
+ LEFT JOIN edb_activitycode as ac1 ON ac1.id = sources.activitycode1_id
27
+ LEFT JOIN edb_activitycode as ac2 ON ac2.id = sources.activitycode2_id
28
+ LEFT JOIN edb_activitycode as ac3 ON ac3.id = sources.activitycode3_id
29
+ {grid_source_filter}
30
+ ),
31
+ road_source as (
32
+ SELECT sources.id as source_id, name as source_name, tags,
33
+ ST_Transform(geom, {srid}) as geom, aadt, heavy_vehicle_share,
34
+ congestion_profile_id,nolanes,speed,width,slope,roadclass_id,fleet_id
35
+ FROM edb_roadsource as sources
36
+ {road_source_filter}
37
+ ),
38
+ fleet_veh as (
39
+ SELECT
40
+ fm.fleet_id,
41
+ rc.id as roadclass_id,
42
+ fm.vehicle_id as vehicle_id,
43
+ veh.isheavy,
44
+ timevar_id,
45
+ coldstart_timevar_id,
46
+ fm.fraction as fraction,
47
+ fm.coldstart_fraction,
48
+ fleet.default_heavy_vehicle_share,
49
+ substance_id,
50
+ freeflow_ef,
51
+ heavy_ef,
52
+ saturated_ef,
53
+ stopngo_ef,
54
+ coldstart_ef,
55
+ ef.ac1,
56
+ ef.ac2,
57
+ ef.ac3
58
+ FROM
59
+ (
60
+ SELECT
61
+ fleet_id,
62
+ fm.id as fleetmember_id,
63
+ veh_ef.traffic_situation_id as traffic_situation,
64
+ fm.vehicle_id,
65
+ veh_ef.substance_id,
66
+ ac1.code as ac1,
67
+ ac2.code as ac2,
68
+ ac3.code as ac3,
69
+ sum(fmf.fraction * veh_ef.freeflow) as freeflow_ef,
70
+ sum(fmf.fraction * veh_ef.heavy) as heavy_ef,
71
+ sum(fmf.fraction * veh_ef.saturated) as saturated_ef,
72
+ sum(fmf.fraction * veh_ef.stopngo) as stopngo_ef,
73
+ sum(fmf.fraction * veh_ef.coldstart) as coldstart_ef
74
+ FROM edb_fleetmember fm
75
+ JOIN edb_fleetmemberfuel as fmf ON fm.id=fmf.fleet_member_id
76
+ JOIN edb_vehicleef as veh_ef
77
+ ON fm.vehicle_id = veh_ef.vehicle_id
78
+ AND fmf.fuel_id = veh_ef.fuel_id
79
+ JOIN edb_fleet as fleet ON fm.fleet_id = fleet.id
80
+ JOIN edb_vehiclefuelcomb as vfc
81
+ ON fm.vehicle_id = vfc.vehicle_id
82
+ AND fmf.fuel_id = vfc.fuel_id
83
+ LEFT JOIN edb_activitycode as ac1 ON vfc.activitycode1_id=ac1.id
84
+ LEFT JOIN edb_activitycode as ac2 ON vfc.activitycode2_id=ac2.id
85
+ LEFT JOIN edb_activitycode as ac3 ON vfc.activitycode3_id=ac3.id
86
+ WHERE veh_ef.substance_id != {traffic_work_subst_id}
87
+ GROUP BY fm.fleet_id, fm.id, veh_ef.traffic_situation_id,
88
+ fm.vehicle_id, veh_ef.substance_id, ac1.code, ac2.code, ac3.code
89
+ UNION
90
+ SELECT
91
+ fleet_id,
92
+ fm.id as fleetmember_id,
93
+ ts.id as traffic_situation,
94
+ fm.vehicle_id,
95
+ {traffic_work_subst_id} as substance_id,
96
+ ac1.code as ac1,
97
+ ac2.code as ac2,
98
+ ac3.code as ac3,
99
+ 1.0 as freeflow_ef,
100
+ 1.0 as saturated_ef,
101
+ 1.0 as congested_ef,
102
+ 1.0 as stopngo_ef,
103
+ 0.0 as coldstart_ef
104
+ FROM edb_fleetmember fm
105
+ JOIN edb_fleetmemberfuel as fmf ON fm.id=fmf.fleet_member_id
106
+ CROSS JOIN edb_trafficsituation as ts
107
+ JOIN edb_fleet as fleet ON fm.fleet_id = fleet.id
108
+ JOIN edb_vehiclefuelcomb as vfc on fm.vehicle_id = vfc.vehicle_id
109
+ AND fmf.fuel_id = vfc.fuel_id
110
+ LEFT JOIN edb_activitycode as ac1 ON vfc.activitycode1_id=ac1.id
111
+ LEFT JOIN edb_activitycode as ac2 ON vfc.activitycode2_id=ac2.id
112
+ LEFT JOIN edb_activitycode as ac3 ON vfc.activitycode3_id=ac3.id
113
+ ) as ef
114
+ JOIN edb_fleetmember fm ON ef.fleetmember_id = fm.id
115
+ JOIN edb_vehicle veh ON ef.vehicle_id=veh.id
116
+ LEFT JOIN edb_roadclass rc
117
+ ON ef.traffic_situation=rc.traffic_situation_id
118
+ JOIN edb_fleet as fleet ON fm.fleet_id = fleet.id
119
+ WHERE (
120
+ ef.freeflow_ef != 0 OR ef.coldstart_ef != 0 OR
121
+ ef.stopngo_ef != 0 OR ef.heavy_ef != 0 OR ef.saturated_ef != 0
122
+ ) {ef_substance_filter}
123
+ ),
124
+ /*
125
+ Calculate weight of each LOS (Level Of Service) for all valid combinations
126
+ of congestion profile and timevar. A custom sqlite function in python called
127
+ condition_weight is used (see cetk.edb.signals).
128
+ */
129
+ congestion as (
130
+ SELECT c.id as congestion_profile_id, t.id as timevar_id,
131
+ condition_weight(c.traffic_condition, t.typeday, t.typeday_sum, 1) as freeflow_share,
132
+ condition_weight(c.traffic_condition, t.typeday, t.typeday_sum, 2) as heavy_share,
133
+ condition_weight(c.traffic_condition, t.typeday, t.typeday_sum, 3) as saturated_share,
134
+ condition_weight(c.traffic_condition, t.typeday, t.typeday_sum, 4) as stopngo_share
135
+ FROM (
136
+ SELECT DISTINCT congestion_profile_id, timevar_id
137
+ FROM road_source as src
138
+ JOIN edb_fleetmember AS fm ON src.fleet_id = fm.fleet_id
139
+ ) as ct
140
+ JOIN edb_flowtimevar as t ON ct.congestion_profile_id = c.id
141
+ JOIN edb_congestionprofile as c ON ct.timevar_id = t.id
142
+ ),
143
+ road_emis as (
144
+ SELECT substance_id, ac1, ac2, ac3,
145
+ road_veh_ef.veh_m_per_sec * (
146
+ freeflow_ef * COALESCE(freeflow_share, 1.0) +
147
+ heavy_ef * COALESCE(heavy_share, 0.0) +
148
+ saturated_ef * COALESCE(saturated_share, 0.0) +
149
+ stopngo_ef * COALESCE(stopngo_share, 0.0) +
150
+ coldstart_ef * coldstart_fraction
151
+ ) as emis
152
+ FROM
153
+ (
154
+ SELECT
155
+ fleet_veh.coldstart_fraction,
156
+ congestion.freeflow_share,
157
+ congestion.heavy_share,
158
+ congestion.saturated_share,
159
+ congestion.stopngo_share,
160
+ fleet_veh.substance_id,
161
+ fleet_veh.freeflow_ef,
162
+ fleet_veh.heavy_ef,
163
+ fleet_veh.saturated_ef,
164
+ fleet_veh.stopngo_ef,
165
+ fleet_veh.coldstart_ef,
166
+ fleet_veh.ac1,
167
+ fleet_veh.ac2,
168
+ fleet_veh.ac3,
169
+ (
170
+ CASE
171
+ WHEN fleet_veh.isheavy=TRUE THEN
172
+ COALESCE(
173
+ road_source.heavy_vehicle_share,
174
+ fleet_veh.default_heavy_vehicle_share
175
+ )
176
+ ELSE
177
+ 1 - COALESCE(
178
+ road_source.heavy_vehicle_share,
179
+ fleet_veh.default_heavy_vehicle_share
180
+ )
181
+ END
182
+ * fleet_veh.fraction * road_source.aadt / (3600.0 * 24) * ST_Length(road_source.geom)
183
+ ) as veh_m_per_sec
184
+ FROM road_source
185
+ JOIN fleet_veh
186
+ ON road_source.roadclass_id=fleet_veh.roadclass_id
187
+ AND road_source.fleet_id=fleet_veh.fleet_id
188
+ LEFT JOIN congestion
189
+ ON congestion.congestion_profile_id=road_source.congestion_profile_id
190
+ AND congestion.timevar_id=fleet_veh.timevar_id
191
+ ) as road_veh_ef
192
+ ),
193
+ ef_subst as (
194
+ SELECT * FROM edb_emissionfactor as ef
195
+ JOIN edb_activity ON edb_activity.id=ef.activity_id
196
+ WHERE ef.factor > 0
197
+ {ef_substance_filter}
198
+ ),
199
+ point_emis as (
200
+ SELECT aggr_emis.substance_id, ac1, ac2, ac3, aggr_emis.emis
201
+ FROM
202
+ (
203
+ SELECT substance_id, source_id, sum(emis) as emis
204
+ FROM
205
+ (
206
+ SELECT
207
+ point_source.source_id,
208
+ emis.substance_id as substance_id,
209
+ emis.value as emis
210
+ FROM edb_pointsourcesubstance as emis
211
+ JOIN point_source ON point_source.source_id=emis.source_id
212
+ WHERE emis.value > 0
213
+ {emis_substance_filter}
214
+ UNION ALL
215
+ SELECT
216
+ point_source.source_id,
217
+ ef_subst.substance_id as substance_id,
218
+ act.rate * ef_subst.factor as emis
219
+ FROM edb_pointsourceactivity as act
220
+ JOIN point_source ON act.source_id=point_source.source_id
221
+ JOIN ef_subst ON act.activity_id=ef_subst.activity_id
222
+ WHERE act.rate > 0
223
+ ) all_emis
224
+ GROUP BY substance_id, source_id
225
+ ) aggr_emis
226
+ JOIN point_source ON aggr_emis.source_id = point_source.source_id
227
+ ),
228
+ area_emis as (
229
+ SELECT aggr_emis.substance_id, ac1, ac2, ac3, aggr_emis.emis
230
+ FROM
231
+ (
232
+ SELECT substance_id, source_id, sum(emis) as emis
233
+ FROM
234
+ (
235
+ SELECT
236
+ area_source.source_id,
237
+ emis.substance_id as substance_id,
238
+ emis.value as emis
239
+ FROM edb_areasourcesubstance as emis
240
+ JOIN area_source ON area_source.source_id=emis.source_id
241
+ WHERE emis.value > 0
242
+ {emis_substance_filter}
243
+ UNION ALL
244
+ SELECT
245
+ area_source.source_id,
246
+ ef_subst.substance_id as substance_id,
247
+ act.rate * ef_subst.factor as emis
248
+ FROM edb_areasourceactivity as act
249
+ JOIN area_source ON act.source_id=area_source.source_id
250
+ JOIN ef_subst ON act.activity_id=ef_subst.activity_id
251
+ WHERE act.rate > 0
252
+ ) all_emis
253
+ GROUP BY substance_id, source_id
254
+ ) aggr_emis
255
+ JOIN area_source ON aggr_emis.source_id = area_source.source_id
256
+ ),
257
+ grid_emis as (
258
+ SELECT aggr_emis.substance_id, ac1, ac2, ac3, aggr_emis.emis
259
+ FROM
260
+ (
261
+ SELECT substance_id, source_id, raster_name, sum(emis * raster.total) as emis
262
+ FROM
263
+ (
264
+ SELECT
265
+ grid_source.source_id,
266
+ emis.substance_id as substance_id,
267
+ emis.value as emis,
268
+ emis.raster as raster_name
269
+ FROM edb_gridsourcesubstance as emis
270
+ JOIN grid_source ON grid_source.source_id=emis.source_id
271
+ WHERE emis.value > 0
272
+ {emis_substance_filter}
273
+ UNION ALL
274
+ SELECT
275
+ grid_source.source_id,
276
+ ef_subst.substance_id as substance_id,
277
+ emis.rate * ef_subst.factor as emis,
278
+ emis.raster as raster_name
279
+ FROM edb_gridsourceactivity as emis
280
+ JOIN grid_source ON emis.source_id=grid_source.source_id
281
+ JOIN ef_subst ON emis.activity_id=ef_subst.activity_id
282
+ WHERE emis.rate > 0
283
+ ) all_emis
284
+ JOIN (
285
+ {raster_share_sql}
286
+ ) as raster ON all_emis.raster_name = raster.name
287
+ GROUP BY substance_id, source_id, raster_name
288
+ ) aggr_emis
289
+ JOIN grid_source ON aggr_emis.source_id = grid_source.source_id
290
+ )
291
+ SELECT {ac_column} substances.slug as substance, sum(emis) as emission
292
+ FROM
293
+ (
294
+ SELECT * FROM area_emis
295
+ UNION ALL
296
+ SELECT * FROM point_emis
297
+ UNION ALL
298
+ SELECT * FROM grid_emis
299
+ UNION ALL
300
+ SELECT * FROM road_emis
301
+ ) as all_emis
302
+ JOIN substances ON substance_id = substances.id
303
+ GROUP BY {ac_groupby} substances.slug
@@ -0,0 +1,53 @@
1
+ /*
2
+ Calculate emissions, optionally filtered by a polygon.
3
+ Substance emissions and activity emissions are calculated separately and
4
+ are then aggregated by source, raster and substance.
5
+ */
6
+ WITH sources as (
7
+ SELECT sources.id as source_id, name as source_name, tags, timevar_id,
8
+ ac1.code as ac1, ac2.code as ac2, ac3.code as ac3,
9
+ ST_Transform(geom, {srid}) as geom
10
+ FROM edb_areasource as sources
11
+ LEFT JOIN edb_activitycode as ac1 ON ac1.id = sources.activitycode1_id
12
+ LEFT JOIN edb_activitycode as ac2 ON ac2.id = sources.activitycode2_id
13
+ LEFT JOIN edb_activitycode as ac3 ON ac3.id = sources.activitycode3_id
14
+ {source_filters}
15
+ )
16
+ SELECT sources.source_id, aggr_emis.substance_id, source_name, ac1, ac2, ac3,
17
+ sources.geom as geom,
18
+ ST_AsText(sources.geom) as wkt,
19
+ sources.timevar_id, substances.slug as substance, aggr_emis.emis
20
+ FROM
21
+ (
22
+ SELECT substance_id, source_id, SUM(emis) as emis
23
+ FROM
24
+ (
25
+ SELECT
26
+ sources.source_id,
27
+ emis.substance_id as substance_id,
28
+ emis.value as emis
29
+ FROM edb_areasourcesubstance as emis
30
+ JOIN sources ON sources.source_id = emis.source_id
31
+ WHERE emis.value > 0
32
+ {emis_substance_filter}
33
+ UNION ALL
34
+ SELECT
35
+ sources.source_id,
36
+ ef_subst.substance_id as substance_id,
37
+ act.rate * ef_subst.factor as emis
38
+ FROM edb_areasourceactivity as act
39
+ JOIN sources ON act.source_id=sources.source_id
40
+ JOIN (
41
+ SELECT *
42
+ FROM edb_emissionfactor as ef
43
+ JOIN edb_activity ON edb_activity.id=ef.activity_id
44
+ WHERE ef.factor > 0
45
+ {ef_substance_filter}
46
+ ) as ef_subst ON act.activity_id=ef_subst.activity_id
47
+ WHERE act.rate > 0
48
+ ) all_emis
49
+ GROUP BY substance_id, source_id
50
+ ) aggr_emis
51
+ JOIN sources ON aggr_emis.source_id = sources.source_id
52
+ JOIN substances ON aggr_emis.substance_id = substances.id
53
+ ORDER BY sources.source_id