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/exporters.py
ADDED
|
@@ -0,0 +1,551 @@
|
|
|
1
|
+
import ast
|
|
2
|
+
import os
|
|
3
|
+
|
|
4
|
+
# need to import fiona before geopandas due to gpd bug causing circular imports.
|
|
5
|
+
import fiona # noqa
|
|
6
|
+
import geopandas as gpd
|
|
7
|
+
import numpy as np
|
|
8
|
+
import pandas as pd
|
|
9
|
+
import pyogrio
|
|
10
|
+
import rasterio as rio
|
|
11
|
+
from django.db import connection
|
|
12
|
+
from openpyxl import Workbook
|
|
13
|
+
from shapely import wkt
|
|
14
|
+
|
|
15
|
+
from cetk.edb.const import DEFAULT_EMISSION_UNIT, WGS84_SRID
|
|
16
|
+
from cetk.edb.importers.source_import import (
|
|
17
|
+
OPTIONAL_COLUMNS_POINT,
|
|
18
|
+
REQUIRED_COLUMNS_AREA,
|
|
19
|
+
REQUIRED_COLUMNS_POINT,
|
|
20
|
+
)
|
|
21
|
+
from cetk.edb.models import (
|
|
22
|
+
Activity,
|
|
23
|
+
ActivityCode,
|
|
24
|
+
AreaSource,
|
|
25
|
+
AreaSourceSubstance,
|
|
26
|
+
CodeSet,
|
|
27
|
+
ColdstartTimevar,
|
|
28
|
+
CongestionProfile,
|
|
29
|
+
EmissionFactor,
|
|
30
|
+
Facility,
|
|
31
|
+
Fleet,
|
|
32
|
+
FleetMemberFuel,
|
|
33
|
+
FlowTimevar,
|
|
34
|
+
GridSource,
|
|
35
|
+
GridSourceSubstance,
|
|
36
|
+
PointSource,
|
|
37
|
+
PointSourceSubstance,
|
|
38
|
+
RoadAttribute,
|
|
39
|
+
RoadClass,
|
|
40
|
+
RoadSource,
|
|
41
|
+
Substance,
|
|
42
|
+
TrafficSituation,
|
|
43
|
+
VehicleEF,
|
|
44
|
+
VehicleFuel,
|
|
45
|
+
VehicleFuelComb,
|
|
46
|
+
)
|
|
47
|
+
from cetk.edb.models.timevar_models import Timevar
|
|
48
|
+
from cetk.edb.units import activity_rate_unit_from_si, emis_conversion_factor_from_si
|
|
49
|
+
from cetk.tools.utils import get_db
|
|
50
|
+
|
|
51
|
+
REQUIRED_COLUMNS_GRID = {
|
|
52
|
+
"name": np.str_,
|
|
53
|
+
"rastername": np.str_,
|
|
54
|
+
"timevar": np.str_,
|
|
55
|
+
"path": np.str_,
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
days_header = [
|
|
59
|
+
"ID",
|
|
60
|
+
"typeday",
|
|
61
|
+
"monday",
|
|
62
|
+
"tuesday",
|
|
63
|
+
"wednesday",
|
|
64
|
+
"thursday",
|
|
65
|
+
"friday",
|
|
66
|
+
"saturday",
|
|
67
|
+
"sunday",
|
|
68
|
+
]
|
|
69
|
+
months_header = [
|
|
70
|
+
" ",
|
|
71
|
+
"month",
|
|
72
|
+
"January",
|
|
73
|
+
"February",
|
|
74
|
+
"March",
|
|
75
|
+
"April",
|
|
76
|
+
"May",
|
|
77
|
+
"June",
|
|
78
|
+
"July",
|
|
79
|
+
"August",
|
|
80
|
+
"September",
|
|
81
|
+
"October",
|
|
82
|
+
"November",
|
|
83
|
+
"December",
|
|
84
|
+
]
|
|
85
|
+
time_intervals = [
|
|
86
|
+
"00-01",
|
|
87
|
+
"01-02",
|
|
88
|
+
"02-03",
|
|
89
|
+
"03-04",
|
|
90
|
+
"04-05",
|
|
91
|
+
"05-06",
|
|
92
|
+
"06-07",
|
|
93
|
+
"07-08",
|
|
94
|
+
"08-09",
|
|
95
|
+
"09-10",
|
|
96
|
+
"10-11",
|
|
97
|
+
"11-12",
|
|
98
|
+
"12-13",
|
|
99
|
+
"13-14",
|
|
100
|
+
"14-15",
|
|
101
|
+
"15-16",
|
|
102
|
+
"16-17",
|
|
103
|
+
"17-18",
|
|
104
|
+
"18-19",
|
|
105
|
+
"19-20",
|
|
106
|
+
"20-21",
|
|
107
|
+
"21-22",
|
|
108
|
+
"22-23",
|
|
109
|
+
"23-24",
|
|
110
|
+
]
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
def export_sources(export_filepath, srid=WGS84_SRID, unit=DEFAULT_EMISSION_UNIT):
|
|
114
|
+
# Create a new Excel workbook and remove standard first Sheet
|
|
115
|
+
workbook = Workbook()
|
|
116
|
+
del workbook["Sheet"]
|
|
117
|
+
if PointSource.objects.count() > 0:
|
|
118
|
+
point_columns = REQUIRED_COLUMNS_POINT | OPTIONAL_COLUMNS_POINT
|
|
119
|
+
worksheet = workbook.create_sheet(title="PointSource")
|
|
120
|
+
create_source_sheet(
|
|
121
|
+
worksheet, PointSource, point_columns, PointSourceSubstance, unit
|
|
122
|
+
)
|
|
123
|
+
workbook.save(export_filepath)
|
|
124
|
+
|
|
125
|
+
if AreaSource.objects.count() > 0:
|
|
126
|
+
worksheet = workbook.create_sheet(title="AreaSource")
|
|
127
|
+
create_source_sheet(
|
|
128
|
+
worksheet, AreaSource, REQUIRED_COLUMNS_AREA, AreaSourceSubstance, unit
|
|
129
|
+
)
|
|
130
|
+
workbook.save(export_filepath)
|
|
131
|
+
|
|
132
|
+
if GridSource.objects.count() > 0:
|
|
133
|
+
worksheet = workbook.create_sheet(title="GridSource")
|
|
134
|
+
create_source_sheet(
|
|
135
|
+
worksheet, GridSource, REQUIRED_COLUMNS_GRID, GridSourceSubstance, unit
|
|
136
|
+
)
|
|
137
|
+
workbook.save(export_filepath)
|
|
138
|
+
|
|
139
|
+
if EmissionFactor.objects.count() > 0:
|
|
140
|
+
worksheet = workbook.create_sheet(title="EmissionFactor")
|
|
141
|
+
header = [
|
|
142
|
+
"activity_name",
|
|
143
|
+
"substance",
|
|
144
|
+
"factor",
|
|
145
|
+
"emissionfactor_unit",
|
|
146
|
+
"activity_unit",
|
|
147
|
+
]
|
|
148
|
+
worksheet.append(header)
|
|
149
|
+
for emfac in EmissionFactor.objects.all():
|
|
150
|
+
# all factors stored in SI, original factor unit at import not stored in db.
|
|
151
|
+
factor_unit = "kg/" + emfac.activity.unit.split("/")[0]
|
|
152
|
+
row_data = [
|
|
153
|
+
emfac.activity.name,
|
|
154
|
+
emfac.substance.slug,
|
|
155
|
+
emfac.factor,
|
|
156
|
+
factor_unit,
|
|
157
|
+
emfac.activity.unit,
|
|
158
|
+
]
|
|
159
|
+
worksheet.append(row_data)
|
|
160
|
+
workbook.save(export_filepath)
|
|
161
|
+
|
|
162
|
+
if CodeSet.objects.count() > 0:
|
|
163
|
+
worksheet = workbook.create_sheet(title="CodeSet")
|
|
164
|
+
header = ["name", "slug", "description"]
|
|
165
|
+
worksheet.append(header)
|
|
166
|
+
for cs in CodeSet.objects.all():
|
|
167
|
+
worksheet.append([cs.name, cs.slug, cs.description])
|
|
168
|
+
workbook.save(export_filepath)
|
|
169
|
+
|
|
170
|
+
if ActivityCode.objects.count() > 0:
|
|
171
|
+
worksheet = workbook.create_sheet(title="ActivityCode")
|
|
172
|
+
header = ["codeset_slug", "activitycode", "label", "vertical_distribution_slug"]
|
|
173
|
+
worksheet.append(header)
|
|
174
|
+
for ac in ActivityCode.objects.all():
|
|
175
|
+
if ac.vertical_dist is not None:
|
|
176
|
+
worksheet.append(
|
|
177
|
+
[ac.code_set.slug, ac.code, ac.label, ac.vertical_dist.slug]
|
|
178
|
+
)
|
|
179
|
+
else:
|
|
180
|
+
worksheet.append([ac.code_set.slug, ac.code, ac.label, ""])
|
|
181
|
+
workbook.save(export_filepath)
|
|
182
|
+
|
|
183
|
+
if Timevar.objects.count() > 0:
|
|
184
|
+
worksheet = workbook.create_sheet(title="Timevar")
|
|
185
|
+
create_timevar_sheet(worksheet, Timevar)
|
|
186
|
+
workbook.save(export_filepath)
|
|
187
|
+
|
|
188
|
+
if FlowTimevar.objects.count() > 0:
|
|
189
|
+
worksheet = workbook.create_sheet(title="FlowTimevar")
|
|
190
|
+
create_timevar_sheet(worksheet, FlowTimevar)
|
|
191
|
+
workbook.save(export_filepath)
|
|
192
|
+
|
|
193
|
+
if ColdstartTimevar.objects.count() > 0:
|
|
194
|
+
worksheet = workbook.create_sheet(title="ColdstartTimevar")
|
|
195
|
+
create_timevar_sheet(worksheet, ColdstartTimevar)
|
|
196
|
+
workbook.save(export_filepath)
|
|
197
|
+
|
|
198
|
+
if CongestionProfile.objects.count() > 0:
|
|
199
|
+
worksheet = workbook.create_sheet(title="CongestionProfile")
|
|
200
|
+
create_timevar_sheet(worksheet, CongestionProfile)
|
|
201
|
+
workbook.save(export_filepath)
|
|
202
|
+
|
|
203
|
+
if RoadSource.objects.count() > 0:
|
|
204
|
+
create_roadsource_sheet(workbook)
|
|
205
|
+
workbook.save(export_filepath)
|
|
206
|
+
|
|
207
|
+
# RoadAttributes could be defined before importing any roads
|
|
208
|
+
if RoadAttribute.objects.count() > 0:
|
|
209
|
+
worksheet = workbook.create_sheet(title="RoadAttribute")
|
|
210
|
+
header = ["name", "slug"]
|
|
211
|
+
worksheet.append(header)
|
|
212
|
+
for ra in RoadAttribute.objects.all():
|
|
213
|
+
worksheet.append([ra.name, ra.slug])
|
|
214
|
+
workbook.save(export_filepath)
|
|
215
|
+
|
|
216
|
+
if VehicleFuelComb.objects.count() > 0:
|
|
217
|
+
create_vehiclefuel_sheet(workbook)
|
|
218
|
+
workbook.save(export_filepath)
|
|
219
|
+
|
|
220
|
+
if Fleet.objects.count() > 0:
|
|
221
|
+
create_fleet_sheet(workbook)
|
|
222
|
+
workbook.save(export_filepath)
|
|
223
|
+
|
|
224
|
+
if TrafficSituation.objects.count() > 0:
|
|
225
|
+
create_traffic_sheet(workbook)
|
|
226
|
+
workbook.save(export_filepath)
|
|
227
|
+
|
|
228
|
+
if VehicleEF.objects.count() > 0:
|
|
229
|
+
create_vehicle_ef_sheet(workbook)
|
|
230
|
+
workbook.save(export_filepath)
|
|
231
|
+
|
|
232
|
+
|
|
233
|
+
def create_vehicle_ef_sheet(workbook):
|
|
234
|
+
worksheet = workbook.create_sheet(title="VehicleEmissionFactor")
|
|
235
|
+
header = [
|
|
236
|
+
"traffic_situation",
|
|
237
|
+
"vehicle",
|
|
238
|
+
"fuel",
|
|
239
|
+
"substance",
|
|
240
|
+
"freeflow",
|
|
241
|
+
"heavy",
|
|
242
|
+
"saturated",
|
|
243
|
+
"stopngo",
|
|
244
|
+
"coldstart",
|
|
245
|
+
"unit",
|
|
246
|
+
]
|
|
247
|
+
worksheet.append(header)
|
|
248
|
+
for vef in VehicleEF.objects.all():
|
|
249
|
+
# TODO could convert to more human readable values with for example unit mg/km.
|
|
250
|
+
row = [
|
|
251
|
+
vef.traffic_situation.ts_id,
|
|
252
|
+
vef.vehicle.name,
|
|
253
|
+
vef.fuel.name,
|
|
254
|
+
vef.substance.slug,
|
|
255
|
+
vef.freeflow,
|
|
256
|
+
vef.heavy,
|
|
257
|
+
vef.saturated,
|
|
258
|
+
vef.stopngo,
|
|
259
|
+
vef.coldstart,
|
|
260
|
+
"kg/m",
|
|
261
|
+
]
|
|
262
|
+
worksheet.append(row)
|
|
263
|
+
|
|
264
|
+
|
|
265
|
+
def create_traffic_sheet(workbook):
|
|
266
|
+
worksheet = workbook.create_sheet(title="TrafficSituation")
|
|
267
|
+
header = ["traffic_situation"]
|
|
268
|
+
attributes = []
|
|
269
|
+
for attribute in RoadAttribute.objects.all():
|
|
270
|
+
header.append("attr:" + attribute.slug)
|
|
271
|
+
attributes.append(attribute.slug)
|
|
272
|
+
attributes = np.array(attributes)
|
|
273
|
+
worksheet.append(header)
|
|
274
|
+
for i, rc in enumerate(RoadClass.objects.all()):
|
|
275
|
+
row = [""] * len(header)
|
|
276
|
+
row[0] = rc.traffic_situation.ts_id
|
|
277
|
+
for av in rc.attribute_values.all():
|
|
278
|
+
ind = np.where(attributes == av.attribute.slug)[0][0]
|
|
279
|
+
row[ind + 1] = av.value
|
|
280
|
+
worksheet.append(row)
|
|
281
|
+
|
|
282
|
+
|
|
283
|
+
def create_fleet_sheet(workbook):
|
|
284
|
+
worksheet = workbook.create_sheet(title="Fleet")
|
|
285
|
+
header = [
|
|
286
|
+
"name",
|
|
287
|
+
"default_heavy_vehicle_share",
|
|
288
|
+
"vehicle",
|
|
289
|
+
"vehicle_fraction",
|
|
290
|
+
"coldstart_fraction",
|
|
291
|
+
"flow_timevar",
|
|
292
|
+
"coldstart_timevar",
|
|
293
|
+
]
|
|
294
|
+
fuel_ids = []
|
|
295
|
+
for fuel in VehicleFuel.objects.all():
|
|
296
|
+
fuel_ids.append(fuel.id)
|
|
297
|
+
header.append(f"fuel:{fuel.name}")
|
|
298
|
+
worksheet.append(header)
|
|
299
|
+
for fleet in Fleet.objects.all():
|
|
300
|
+
for fleetmember in fleet.vehicles.all():
|
|
301
|
+
veh = fleetmember.vehicle
|
|
302
|
+
row = [
|
|
303
|
+
fleet.name,
|
|
304
|
+
fleet.default_heavy_vehicle_share,
|
|
305
|
+
veh.name,
|
|
306
|
+
fleetmember.fraction,
|
|
307
|
+
fleetmember.coldstart_fraction,
|
|
308
|
+
]
|
|
309
|
+
if fleetmember.timevar is None:
|
|
310
|
+
row.append("")
|
|
311
|
+
else:
|
|
312
|
+
row.append(fleetmember.timevar.name)
|
|
313
|
+
if fleetmember.coldstart_timevar is None:
|
|
314
|
+
row.append("")
|
|
315
|
+
else:
|
|
316
|
+
row.append(fleetmember.coldstart_timevar.name)
|
|
317
|
+
for fuel_id in fuel_ids:
|
|
318
|
+
try:
|
|
319
|
+
row.append(fleetmember.fuels.get(fuel_id=fuel_id).fraction)
|
|
320
|
+
except FleetMemberFuel.DoesNotExist:
|
|
321
|
+
row.append("")
|
|
322
|
+
worksheet.append(row)
|
|
323
|
+
|
|
324
|
+
|
|
325
|
+
def create_vehiclefuel_sheet(workbook):
|
|
326
|
+
worksheet = workbook.create_sheet(title="VehicleFuel")
|
|
327
|
+
header = ["name", "isheavy", "info", "fuel"]
|
|
328
|
+
codeset_slugs = [code.slug for code in CodeSet.objects.all()]
|
|
329
|
+
codeset_ids = [CodeSet.objects.get(slug=slug).id for slug in codeset_slugs]
|
|
330
|
+
codeset_columns = [f"activitycode_{slug}" for slug in codeset_slugs]
|
|
331
|
+
header = header + codeset_columns
|
|
332
|
+
worksheet.append(header)
|
|
333
|
+
for vf in VehicleFuelComb.objects.all():
|
|
334
|
+
row = [vf.vehicle.name, str(vf.vehicle.isheavy), vf.vehicle.info, vf.fuel.name]
|
|
335
|
+
for i in codeset_ids:
|
|
336
|
+
try:
|
|
337
|
+
row.append(
|
|
338
|
+
ActivityCode.objects.get(id=getattr(vf, f"activitycode{i}_id")).code
|
|
339
|
+
)
|
|
340
|
+
except ActivityCode.DoesNotExist:
|
|
341
|
+
row.append("")
|
|
342
|
+
worksheet.append(row)
|
|
343
|
+
|
|
344
|
+
|
|
345
|
+
def create_roadsource_sheet(workbook):
|
|
346
|
+
worksheet = workbook.create_sheet(title="RoadSource")
|
|
347
|
+
header = [
|
|
348
|
+
"filepath",
|
|
349
|
+
"name",
|
|
350
|
+
"nlanes",
|
|
351
|
+
"width",
|
|
352
|
+
"median_strip_width",
|
|
353
|
+
"aadt",
|
|
354
|
+
"heavy_vehicle_share",
|
|
355
|
+
"fleet",
|
|
356
|
+
"congestion_profile",
|
|
357
|
+
"speed",
|
|
358
|
+
"slope",
|
|
359
|
+
]
|
|
360
|
+
# add attributes, always at least 1 to define which emission factors to use
|
|
361
|
+
road_attributes = ""
|
|
362
|
+
for attribute in RoadAttribute.objects.all():
|
|
363
|
+
header.append("attr:" + attribute.slug)
|
|
364
|
+
road_attributes += f", rc.{attribute.slug} AS {attribute.slug} "
|
|
365
|
+
worksheet.append(header)
|
|
366
|
+
# slight adaptions to header to form actual content
|
|
367
|
+
db_name = os.path.basename(get_db()).split(".")[0]
|
|
368
|
+
roadpath = os.path.join(os.path.dirname(get_db()), db_name + "-roadsource.gpkg")
|
|
369
|
+
header[0] = roadpath
|
|
370
|
+
header = [attr.replace("attr:", "") for attr in header]
|
|
371
|
+
worksheet.append(header)
|
|
372
|
+
|
|
373
|
+
sql = (
|
|
374
|
+
"SELECT rs.name, rs.nolanes, rs.width, rs.median_strip_width, rs.aadt, "
|
|
375
|
+
"rs.heavy_vehicle_share, f.name AS fleet, cp.name AS congestion_profile, "
|
|
376
|
+
"rs.speed, rs.slope, rs.roadclass_id, ST_AsText(geom) AS geometry "
|
|
377
|
+
"FROM edb_roadsource AS rs "
|
|
378
|
+
"LEFT JOIN edb_fleet AS F ON rs.fleet_id = f.id "
|
|
379
|
+
"LEFT JOIN edb_congestionprofile AS cp ON rs.congestion_profile_id = cp.id "
|
|
380
|
+
)
|
|
381
|
+
cur = connection.cursor()
|
|
382
|
+
cur.execute(sql)
|
|
383
|
+
|
|
384
|
+
df = pd.DataFrame(cur.fetchall(), columns=[col[0] for col in cur.description])
|
|
385
|
+
roadclass_mapping = {}
|
|
386
|
+
for rc in RoadClass.objects.all():
|
|
387
|
+
roadclass_mapping[rc.id] = rc.attributes
|
|
388
|
+
for col in roadclass_mapping[1].keys():
|
|
389
|
+
df[col] = df["roadclass_id"].map(
|
|
390
|
+
lambda x: roadclass_mapping[x][col] if x in roadclass_mapping else None
|
|
391
|
+
)
|
|
392
|
+
df = df.drop(columns=["roadclass_id"])
|
|
393
|
+
df["geometry"] = df["geometry"].apply(wkt.loads)
|
|
394
|
+
gdf = gpd.GeoDataFrame(df, geometry="geometry")
|
|
395
|
+
crs = "EPSG:4326"
|
|
396
|
+
gdf.crs = crs
|
|
397
|
+
# does not work from QGIS gdf.to_file(roadpath, driver="GPKG")
|
|
398
|
+
pyogrio.write_dataframe(gdf, roadpath, layer="roads")
|
|
399
|
+
|
|
400
|
+
|
|
401
|
+
def create_timevar_sheet(worksheet, tvar_type):
|
|
402
|
+
for tvar in tvar_type.objects.all():
|
|
403
|
+
worksheet.append(days_header)
|
|
404
|
+
if tvar_type is CongestionProfile:
|
|
405
|
+
typeday_list = ast.literal_eval(tvar.traffic_condition)
|
|
406
|
+
else:
|
|
407
|
+
typeday_list = ast.literal_eval(tvar.typeday)
|
|
408
|
+
for i in range(len(typeday_list)):
|
|
409
|
+
if i == 0:
|
|
410
|
+
row_data = [tvar.name] + [time_intervals[i]] + typeday_list[i]
|
|
411
|
+
else:
|
|
412
|
+
row_data = [""] + [time_intervals[i]] + typeday_list[i]
|
|
413
|
+
worksheet.append(row_data)
|
|
414
|
+
if tvar_type is not CongestionProfile:
|
|
415
|
+
month_list = ast.literal_eval(tvar.month)
|
|
416
|
+
worksheet.append(months_header)
|
|
417
|
+
worksheet.append(["", ""] + month_list)
|
|
418
|
+
|
|
419
|
+
|
|
420
|
+
def create_source_sheet(
|
|
421
|
+
worksheet, model_type, REQUIRED_COLUMNS, SourceSubstanceModel, unit
|
|
422
|
+
):
|
|
423
|
+
"""create source sheet for Point, Area or GridSource"""
|
|
424
|
+
emis_conversion_factor = emis_conversion_factor_from_si(unit)
|
|
425
|
+
header = list(REQUIRED_COLUMNS.keys())
|
|
426
|
+
codeset_slugs = [code.slug for code in CodeSet.objects.all()]
|
|
427
|
+
codeset_ids = [CodeSet.objects.get(slug=slug).id for slug in codeset_slugs]
|
|
428
|
+
codeset_columns = [f"activitycode_{slug}" for slug in codeset_slugs]
|
|
429
|
+
substance_slugs = list(
|
|
430
|
+
set([ss.substance.slug for ss in SourceSubstanceModel.objects.all()])
|
|
431
|
+
)
|
|
432
|
+
substance_columns = [f"subst:{subst}" for subst in substance_slugs]
|
|
433
|
+
header = header + codeset_columns + substance_columns + ["emission_unit"]
|
|
434
|
+
activities = Activity.objects.all()
|
|
435
|
+
if len(activities) > 0:
|
|
436
|
+
activity_names = [activity.name for activity in activities]
|
|
437
|
+
activity_columns = [f"act:{name}" for name in activity_names]
|
|
438
|
+
header = header + activity_columns
|
|
439
|
+
|
|
440
|
+
worksheet.append(header)
|
|
441
|
+
for source in model_type.objects.all():
|
|
442
|
+
if source.timevar_id is not None:
|
|
443
|
+
timevar_name = Timevar.objects.get(id=source.timevar_id).name
|
|
444
|
+
else:
|
|
445
|
+
timevar_name = ""
|
|
446
|
+
|
|
447
|
+
activitycodes = {}
|
|
448
|
+
for i in codeset_ids:
|
|
449
|
+
activitycode = getattr(source, f"activitycode{i}")
|
|
450
|
+
activitycodes[i] = activitycode.code if activitycode is not None else ""
|
|
451
|
+
source_substances = [ss.substance.slug for ss in source.substances.all()]
|
|
452
|
+
if model_type == GridSource:
|
|
453
|
+
if len(source_substances) > 0:
|
|
454
|
+
rasternames = set(
|
|
455
|
+
[substance.raster for substance in source.substances.all()]
|
|
456
|
+
)
|
|
457
|
+
if len(rasternames) == 1:
|
|
458
|
+
rastername = source.substances.first().raster
|
|
459
|
+
else:
|
|
460
|
+
try:
|
|
461
|
+
rastername = (
|
|
462
|
+
os.path.commonprefix(list(rasternames))
|
|
463
|
+
+ "{subst}"
|
|
464
|
+
+ common_suffix(list(rasternames))
|
|
465
|
+
)
|
|
466
|
+
except Exception:
|
|
467
|
+
raise ValueError(
|
|
468
|
+
"Could not find a generic raster name "
|
|
469
|
+
+ f"for GridSource {source.name}"
|
|
470
|
+
)
|
|
471
|
+
elif source.activities.count() > 0:
|
|
472
|
+
rastername = source.activities.first().raster
|
|
473
|
+
rasternames = [rastername]
|
|
474
|
+
else:
|
|
475
|
+
rastername = ""
|
|
476
|
+
if rastername != "":
|
|
477
|
+
rasterpath = os.path.join(
|
|
478
|
+
os.path.dirname(get_db()), rastername + ".tif"
|
|
479
|
+
)
|
|
480
|
+
for name in rasternames:
|
|
481
|
+
# storing each raster, not generic name
|
|
482
|
+
tif_path = os.path.join(os.path.dirname(get_db()), name + ".tif")
|
|
483
|
+
with rio.open(f"GPKG:{get_db()}:raster_{name}") as src:
|
|
484
|
+
meta = src.meta
|
|
485
|
+
meta.update(driver="GTiff")
|
|
486
|
+
with rio.open(tif_path, "w", **meta) as dst:
|
|
487
|
+
# always only 1 band
|
|
488
|
+
dst.write(src.read(1), 1)
|
|
489
|
+
else:
|
|
490
|
+
rasterpath = ""
|
|
491
|
+
row_data = [source.name, rastername, timevar_name, rasterpath]
|
|
492
|
+
else:
|
|
493
|
+
row_data = [
|
|
494
|
+
str(source.facility),
|
|
495
|
+
Facility.objects.get(id=source.facility_id).name,
|
|
496
|
+
source.name,
|
|
497
|
+
source.geom.coords[1] if model_type == PointSource else source.geom.wkt,
|
|
498
|
+
]
|
|
499
|
+
if model_type == PointSource:
|
|
500
|
+
row_data.append(source.geom.coords[0])
|
|
501
|
+
row_data.append(timevar_name)
|
|
502
|
+
|
|
503
|
+
if hasattr(source, "chimney_height"):
|
|
504
|
+
row_data.extend(
|
|
505
|
+
[
|
|
506
|
+
source.chimney_height,
|
|
507
|
+
source.chimney_outer_diameter,
|
|
508
|
+
source.chimney_inner_diameter,
|
|
509
|
+
source.chimney_gas_speed,
|
|
510
|
+
source.chimney_gas_temperature,
|
|
511
|
+
source.house_width,
|
|
512
|
+
source.house_height,
|
|
513
|
+
]
|
|
514
|
+
)
|
|
515
|
+
|
|
516
|
+
for i in codeset_ids:
|
|
517
|
+
row_data.append(activitycodes[i])
|
|
518
|
+
|
|
519
|
+
emis_row = [
|
|
520
|
+
source.substances.get(substance=Substance.objects.get(slug=slug).id).value
|
|
521
|
+
if slug in source_substances
|
|
522
|
+
else 0
|
|
523
|
+
for slug in substance_slugs
|
|
524
|
+
]
|
|
525
|
+
emis_row = [emis * emis_conversion_factor for emis in emis_row]
|
|
526
|
+
row_data = row_data + emis_row + [unit]
|
|
527
|
+
|
|
528
|
+
if len(activities) > 0:
|
|
529
|
+
source_activities = [
|
|
530
|
+
Activity.objects.get(id=sa.activity_id).name
|
|
531
|
+
for sa in source.activities.all()
|
|
532
|
+
]
|
|
533
|
+
source_activity_rates = dict()
|
|
534
|
+
for act in source.activities.all():
|
|
535
|
+
activity_unit = Activity.objects.get(id=act.activity_id).unit
|
|
536
|
+
activity_rate = activity_rate_unit_from_si(act.rate, activity_unit)
|
|
537
|
+
source_activity_rates[
|
|
538
|
+
Activity.objects.get(id=act.activity_id).name
|
|
539
|
+
] = activity_rate
|
|
540
|
+
act_row = [
|
|
541
|
+
source_activity_rates[name] if name in source_activities else 0
|
|
542
|
+
for name in activity_names
|
|
543
|
+
]
|
|
544
|
+
row_data = row_data + act_row
|
|
545
|
+
worksheet.append(row_data)
|
|
546
|
+
|
|
547
|
+
|
|
548
|
+
def common_suffix(strings):
|
|
549
|
+
reversed_strings = [s[::-1] for s in strings]
|
|
550
|
+
common_suffix_reversed = os.path.commonprefix(reversed_strings)
|
|
551
|
+
return common_suffix_reversed[::-1]
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
from .codeset_import import import_activitycodesheet, import_codesetsheet # noqa
|
|
2
|
+
from .gridsource_import import import_gridsources # noqa
|
|
3
|
+
from .roadsource_import import ( # noqa
|
|
4
|
+
fleet_excel_to_dict,
|
|
5
|
+
import_congestion_profiles,
|
|
6
|
+
import_fleets,
|
|
7
|
+
import_roadclasses,
|
|
8
|
+
import_roads,
|
|
9
|
+
import_traffic,
|
|
10
|
+
import_vehicles,
|
|
11
|
+
roadclass_excel_to_dict,
|
|
12
|
+
roadsource_excel_to_dict,
|
|
13
|
+
vehicles_excel_to_dict,
|
|
14
|
+
)
|
|
15
|
+
from .source_import import import_sourceactivities, import_sources # noqa
|
|
16
|
+
from .timevar_import import import_timevars, import_timevarsheet # noqa
|
|
17
|
+
|
|
18
|
+
SHEETS = (
|
|
19
|
+
"CodeSet",
|
|
20
|
+
"ActivityCode",
|
|
21
|
+
"Timevar",
|
|
22
|
+
"Activity",
|
|
23
|
+
"EmissionFactor",
|
|
24
|
+
"PointSource",
|
|
25
|
+
"AreaSource",
|
|
26
|
+
"GridSource",
|
|
27
|
+
"RoadSource",
|
|
28
|
+
"VehicleFuel",
|
|
29
|
+
"Fleet",
|
|
30
|
+
"CongestionProfile",
|
|
31
|
+
"FlowTimevar",
|
|
32
|
+
"ColdstartTimevar",
|
|
33
|
+
"RoadAttriute",
|
|
34
|
+
"TrafficSituation",
|
|
35
|
+
"VehicleEmissionFactor",
|
|
36
|
+
)
|