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.
- cetk/__init__.py +87 -0
- cetk/db.py +41 -0
- cetk/edb/__init__.py +0 -0
- cetk/edb/apps.py +9 -0
- cetk/edb/cache.py +249 -0
- cetk/edb/const.py +26 -0
- cetk/edb/copy.py +18 -0
- cetk/edb/exporters.py +551 -0
- cetk/edb/importers/__init__.py +36 -0
- cetk/edb/importers/activity_import.py +279 -0
- cetk/edb/importers/codeset_import.py +124 -0
- cetk/edb/importers/gridsource_import.py +256 -0
- cetk/edb/importers/roadsource_import.py +1602 -0
- cetk/edb/importers/source_import.py +958 -0
- cetk/edb/importers/timevar_import.py +115 -0
- cetk/edb/importers/utils.py +92 -0
- cetk/edb/importers/validation.py +207 -0
- cetk/edb/ltreefield.py +76 -0
- cetk/edb/migrations/0001_initial.py +1731 -0
- cetk/edb/migrations/0002_data.py +156 -0
- cetk/edb/migrations/0003_create_gpkg_tables.py +14 -0
- cetk/edb/migrations/__init__.py +0 -0
- cetk/edb/models/__init__.py +49 -0
- cetk/edb/models/base.py +52 -0
- cetk/edb/models/common_models.py +144 -0
- cetk/edb/models/fleets.py +160 -0
- cetk/edb/models/gridsource_models.py +163 -0
- cetk/edb/models/road_classes.py +197 -0
- cetk/edb/models/road_models.py +413 -0
- cetk/edb/models/source_models.py +399 -0
- cetk/edb/models/timevar_models.py +111 -0
- cetk/edb/rasterize/__init__.py +1 -0
- cetk/edb/rasterize/rasterizer.py +1544 -0
- cetk/edb/signals.py +43 -0
- cetk/edb/traffic.py +75 -0
- cetk/edb/units.py +160 -0
- cetk/emissions/__init__.py +0 -0
- cetk/emissions/aggregate_emissions.sql +303 -0
- cetk/emissions/areasource_emissions.sql +53 -0
- cetk/emissions/calc.py +148 -0
- cetk/emissions/filters.py +179 -0
- cetk/emissions/gridsource_emissions.sql +52 -0
- cetk/emissions/pointsource_emissions.sql +53 -0
- cetk/emissions/queries.py +221 -0
- cetk/emissions/roadsource_emissions.sql +211 -0
- cetk/emissions/used_substances.sql +56 -0
- cetk/emissions/views.py +89 -0
- cetk/logging.py +68 -0
- cetk/settings.py +85 -0
- cetk/tools/__init__.py +1 -0
- cetk/tools/cetk_command.py +599 -0
- cetk/tools/manage.py +24 -0
- cetk/tools/utils.py +334 -0
- cetk/utils.py +62 -0
- cetk-0.0.4.dev0.dist-info/LICENSE +201 -0
- cetk-0.0.4.dev0.dist-info/METADATA +297 -0
- cetk-0.0.4.dev0.dist-info/RECORD +60 -0
- cetk-0.0.4.dev0.dist-info/WHEEL +5 -0
- cetk-0.0.4.dev0.dist-info/entry_points.txt +3 -0
- 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
|