cetk 0.0.6.dev0__tar.gz → 0.0.8.dev0__tar.gz
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-0.0.6.dev0 → cetk-0.0.8.dev0}/CONTRIBUTING.md +4 -4
- {cetk-0.0.6.dev0 → cetk-0.0.8.dev0}/PKG-INFO +10 -9
- {cetk-0.0.6.dev0 → cetk-0.0.8.dev0}/constraints-lowest.txt +29 -27
- {cetk-0.0.6.dev0 → cetk-0.0.8.dev0}/noxfile.py +2 -2
- {cetk-0.0.6.dev0 → cetk-0.0.8.dev0}/pyproject.toml +9 -8
- {cetk-0.0.6.dev0 → cetk-0.0.8.dev0}/requirements-dev.in +1 -1
- {cetk-0.0.6.dev0 → cetk-0.0.8.dev0}/requirements-dev.txt +1 -1
- {cetk-0.0.6.dev0 → cetk-0.0.8.dev0}/src/cetk/__init__.py +1 -1
- {cetk-0.0.6.dev0 → cetk-0.0.8.dev0}/src/cetk/edb/const.py +1 -1
- {cetk-0.0.6.dev0 → cetk-0.0.8.dev0}/src/cetk/edb/importers/activity_import.py +7 -0
- {cetk-0.0.6.dev0 → cetk-0.0.8.dev0}/src/cetk/edb/importers/codeset_import.py +3 -1
- {cetk-0.0.6.dev0 → cetk-0.0.8.dev0}/src/cetk/edb/importers/gridsource_import.py +5 -5
- {cetk-0.0.6.dev0 → cetk-0.0.8.dev0}/src/cetk/edb/importers/source_import.py +10 -5
- {cetk-0.0.6.dev0 → cetk-0.0.8.dev0}/src/cetk/edb/importers/utils.py +6 -1
- {cetk-0.0.6.dev0 → cetk-0.0.8.dev0}/src/cetk/edb/importers/validation.py +2 -2
- {cetk-0.0.6.dev0 → cetk-0.0.8.dev0}/src/cetk/edb/migrations/0001_initial.py +6 -6
- {cetk-0.0.6.dev0 → cetk-0.0.8.dev0}/src/cetk/edb/models/fleets.py +1 -2
- {cetk-0.0.6.dev0 → cetk-0.0.8.dev0}/src/cetk/edb/models/road_models.py +9 -5
- {cetk-0.0.6.dev0 → cetk-0.0.8.dev0}/src/cetk/edb/rasterize/rasterizer.py +17 -13
- {cetk-0.0.6.dev0 → cetk-0.0.8.dev0}/src/cetk/emissions/calc.py +1 -1
- {cetk-0.0.6.dev0 → cetk-0.0.8.dev0}/src/cetk/emissions/filters.py +0 -2
- {cetk-0.0.6.dev0 → cetk-0.0.8.dev0}/src/cetk/emissions/queries.py +23 -8
- {cetk-0.0.6.dev0 → cetk-0.0.8.dev0}/src/cetk/emissions/roadsource_emissions.sql +4 -2
- {cetk-0.0.6.dev0 → cetk-0.0.8.dev0}/src/cetk/emissions/views.py +1 -1
- {cetk-0.0.6.dev0 → cetk-0.0.8.dev0}/src/cetk/tools/cetk_command.py +2 -7
- {cetk-0.0.6.dev0 → cetk-0.0.8.dev0}/src/cetk.egg-info/PKG-INFO +10 -9
- cetk-0.0.8.dev0/src/cetk.egg-info/requires.txt +12 -0
- {cetk-0.0.6.dev0 → cetk-0.0.8.dev0}/tests/edb/test_common_models.py +0 -1
- {cetk-0.0.6.dev0 → cetk-0.0.8.dev0}/tests/edb/test_rasterize.py +0 -1
- {cetk-0.0.6.dev0 → cetk-0.0.8.dev0}/tests/emissions/test_aggregate_emissions.py +1 -1
- {cetk-0.0.6.dev0 → cetk-0.0.8.dev0}/tests/tools/test_calculate.py +6 -2
- cetk-0.0.6.dev0/src/cetk.egg-info/requires.txt +0 -11
- {cetk-0.0.6.dev0 → cetk-0.0.8.dev0}/.pre-commit-config.yaml +0 -0
- {cetk-0.0.6.dev0 → cetk-0.0.8.dev0}/LICENSE +0 -0
- {cetk-0.0.6.dev0 → cetk-0.0.8.dev0}/MANIFEST.in +0 -0
- {cetk-0.0.6.dev0 → cetk-0.0.8.dev0}/README.md +0 -0
- {cetk-0.0.6.dev0 → cetk-0.0.8.dev0}/flatpak_install.sh +0 -0
- {cetk-0.0.6.dev0 → cetk-0.0.8.dev0}/manage.py +0 -0
- {cetk-0.0.6.dev0 → cetk-0.0.8.dev0}/setup.cfg +0 -0
- {cetk-0.0.6.dev0 → cetk-0.0.8.dev0}/src/cetk/db.py +0 -0
- {cetk-0.0.6.dev0 → cetk-0.0.8.dev0}/src/cetk/edb/__init__.py +0 -0
- {cetk-0.0.6.dev0 → cetk-0.0.8.dev0}/src/cetk/edb/apps.py +0 -0
- {cetk-0.0.6.dev0 → cetk-0.0.8.dev0}/src/cetk/edb/cache.py +0 -0
- {cetk-0.0.6.dev0 → cetk-0.0.8.dev0}/src/cetk/edb/copy.py +0 -0
- {cetk-0.0.6.dev0 → cetk-0.0.8.dev0}/src/cetk/edb/exporters.py +0 -0
- {cetk-0.0.6.dev0 → cetk-0.0.8.dev0}/src/cetk/edb/fixtures/edb-ref.json +0 -0
- {cetk-0.0.6.dev0 → cetk-0.0.8.dev0}/src/cetk/edb/importers/__init__.py +0 -0
- {cetk-0.0.6.dev0 → cetk-0.0.8.dev0}/src/cetk/edb/importers/roadsource_import.py +0 -0
- {cetk-0.0.6.dev0 → cetk-0.0.8.dev0}/src/cetk/edb/importers/timevar_import.py +0 -0
- {cetk-0.0.6.dev0 → cetk-0.0.8.dev0}/src/cetk/edb/ltreefield.py +0 -0
- {cetk-0.0.6.dev0 → cetk-0.0.8.dev0}/src/cetk/edb/migrations/0002_data.py +0 -0
- {cetk-0.0.6.dev0 → cetk-0.0.8.dev0}/src/cetk/edb/migrations/0003_create_gpkg_tables.py +0 -0
- {cetk-0.0.6.dev0 → cetk-0.0.8.dev0}/src/cetk/edb/migrations/__init__.py +0 -0
- {cetk-0.0.6.dev0 → cetk-0.0.8.dev0}/src/cetk/edb/models/__init__.py +0 -0
- {cetk-0.0.6.dev0 → cetk-0.0.8.dev0}/src/cetk/edb/models/base.py +0 -0
- {cetk-0.0.6.dev0 → cetk-0.0.8.dev0}/src/cetk/edb/models/common_models.py +0 -0
- {cetk-0.0.6.dev0 → cetk-0.0.8.dev0}/src/cetk/edb/models/gridsource_models.py +0 -0
- {cetk-0.0.6.dev0 → cetk-0.0.8.dev0}/src/cetk/edb/models/road_classes.py +0 -0
- {cetk-0.0.6.dev0 → cetk-0.0.8.dev0}/src/cetk/edb/models/source_models.py +0 -0
- {cetk-0.0.6.dev0 → cetk-0.0.8.dev0}/src/cetk/edb/models/timevar_models.py +0 -0
- {cetk-0.0.6.dev0 → cetk-0.0.8.dev0}/src/cetk/edb/rasterize/__init__.py +0 -0
- {cetk-0.0.6.dev0 → cetk-0.0.8.dev0}/src/cetk/edb/signals.py +0 -0
- {cetk-0.0.6.dev0 → cetk-0.0.8.dev0}/src/cetk/edb/traffic.py +0 -0
- {cetk-0.0.6.dev0 → cetk-0.0.8.dev0}/src/cetk/edb/units.py +0 -0
- {cetk-0.0.6.dev0 → cetk-0.0.8.dev0}/src/cetk/edb/utils.py +0 -0
- {cetk-0.0.6.dev0 → cetk-0.0.8.dev0}/src/cetk/emissions/__init__.py +0 -0
- {cetk-0.0.6.dev0 → cetk-0.0.8.dev0}/src/cetk/emissions/aggregate_emissions.sql +0 -0
- {cetk-0.0.6.dev0 → cetk-0.0.8.dev0}/src/cetk/emissions/areasource_emissions.sql +0 -0
- {cetk-0.0.6.dev0 → cetk-0.0.8.dev0}/src/cetk/emissions/gridsource_emissions.sql +0 -0
- {cetk-0.0.6.dev0 → cetk-0.0.8.dev0}/src/cetk/emissions/pointsource_emissions.sql +0 -0
- {cetk-0.0.6.dev0 → cetk-0.0.8.dev0}/src/cetk/emissions/used_substances.sql +0 -0
- {cetk-0.0.6.dev0 → cetk-0.0.8.dev0}/src/cetk/logging.py +0 -0
- {cetk-0.0.6.dev0 → cetk-0.0.8.dev0}/src/cetk/settings.py +0 -0
- {cetk-0.0.6.dev0 → cetk-0.0.8.dev0}/src/cetk/tools/__init__.py +0 -0
- {cetk-0.0.6.dev0 → cetk-0.0.8.dev0}/src/cetk/tools/manage.py +0 -0
- {cetk-0.0.6.dev0 → cetk-0.0.8.dev0}/src/cetk/tools/utils.py +0 -0
- {cetk-0.0.6.dev0 → cetk-0.0.8.dev0}/src/cetk/utils.py +0 -0
- {cetk-0.0.6.dev0 → cetk-0.0.8.dev0}/src/cetk.egg-info/SOURCES.txt +0 -0
- {cetk-0.0.6.dev0 → cetk-0.0.8.dev0}/src/cetk.egg-info/dependency_links.txt +0 -0
- {cetk-0.0.6.dev0 → cetk-0.0.8.dev0}/src/cetk.egg-info/entry_points.txt +0 -0
- {cetk-0.0.6.dev0 → cetk-0.0.8.dev0}/src/cetk.egg-info/top_level.txt +0 -0
- {cetk-0.0.6.dev0 → cetk-0.0.8.dev0}/tests/conftest.py +0 -0
- {cetk-0.0.6.dev0 → cetk-0.0.8.dev0}/tests/edb/data/TrafficImportFormat.xlsx +0 -0
- {cetk-0.0.6.dev0 → cetk-0.0.8.dev0}/tests/edb/data/__init__.py +0 -0
- {cetk-0.0.6.dev0 → cetk-0.0.8.dev0}/tests/edb/data/all_sources.xlsx +0 -0
- {cetk-0.0.6.dev0 → cetk-0.0.8.dev0}/tests/edb/data/areasourceactivities.xlsx +0 -0
- {cetk-0.0.6.dev0 → cetk-0.0.8.dev0}/tests/edb/data/areasources.xlsx +0 -0
- {cetk-0.0.6.dev0 → cetk-0.0.8.dev0}/tests/edb/data/congestion_profiles.json +0 -0
- {cetk-0.0.6.dev0 → cetk-0.0.8.dev0}/tests/edb/data/fleets.json +0 -0
- {cetk-0.0.6.dev0 → cetk-0.0.8.dev0}/tests/edb/data/fleets.xlsx +0 -0
- {cetk-0.0.6.dev0 → cetk-0.0.8.dev0}/tests/edb/data/gridsource_rasters/vasterbotten_conc_NOx_1990010100_1991010100.tif +0 -0
- {cetk-0.0.6.dev0 → cetk-0.0.8.dev0}/tests/edb/data/gridsource_rasters/vasterbotten_conc_PM25_1990010100_1991010100.tif +0 -0
- {cetk-0.0.6.dev0 → cetk-0.0.8.dev0}/tests/edb/data/gridsource_rasters/vasterbotten_conc_PM25_2000010100_2001010100.tif +0 -0
- {cetk-0.0.6.dev0 → cetk-0.0.8.dev0}/tests/edb/data/gridsource_rasters/vasterbotten_conc_PM25_2011010100_2012010100.tif +0 -0
- {cetk-0.0.6.dev0 → cetk-0.0.8.dev0}/tests/edb/data/gridsources.xlsx +0 -0
- {cetk-0.0.6.dev0 → cetk-0.0.8.dev0}/tests/edb/data/gridsources_tmp.xlsx +0 -0
- {cetk-0.0.6.dev0 → cetk-0.0.8.dev0}/tests/edb/data/pointsourceactivities.xlsx +0 -0
- {cetk-0.0.6.dev0 → cetk-0.0.8.dev0}/tests/edb/data/pointsources.csv +0 -0
- {cetk-0.0.6.dev0 → cetk-0.0.8.dev0}/tests/edb/data/pointsources.xlsx +0 -0
- {cetk-0.0.6.dev0 → cetk-0.0.8.dev0}/tests/edb/data/roadclass_settings.xlsx +0 -0
- {cetk-0.0.6.dev0 → cetk-0.0.8.dev0}/tests/edb/data/roadclasses.csv +0 -0
- {cetk-0.0.6.dev0 → cetk-0.0.8.dev0}/tests/edb/data/roadclasses.json +0 -0
- {cetk-0.0.6.dev0 → cetk-0.0.8.dev0}/tests/edb/data/roadclasses_1attr.csv +0 -0
- {cetk-0.0.6.dev0 → cetk-0.0.8.dev0}/tests/edb/data/roadclasses_1attr.json +0 -0
- {cetk-0.0.6.dev0 → cetk-0.0.8.dev0}/tests/edb/data/roaddata.gpkg +0 -0
- {cetk-0.0.6.dev0 → cetk-0.0.8.dev0}/tests/edb/data/roads.json +0 -0
- {cetk-0.0.6.dev0 → cetk-0.0.8.dev0}/tests/edb/data/roads.xlsx +0 -0
- {cetk-0.0.6.dev0 → cetk-0.0.8.dev0}/tests/edb/data/sinuous_road.geojson +0 -0
- {cetk-0.0.6.dev0 → cetk-0.0.8.dev0}/tests/edb/data/timevars.json +0 -0
- {cetk-0.0.6.dev0 → cetk-0.0.8.dev0}/tests/edb/data/vehicle_settings.xlsx +0 -0
- {cetk-0.0.6.dev0 → cetk-0.0.8.dev0}/tests/edb/data/vehicles.csv +0 -0
- {cetk-0.0.6.dev0 → cetk-0.0.8.dev0}/tests/edb/data/vehicles.json +0 -0
- {cetk-0.0.6.dev0 → cetk-0.0.8.dev0}/tests/edb/data/vehicles.xlsx +0 -0
- {cetk-0.0.6.dev0 → cetk-0.0.8.dev0}/tests/edb/test_fleets.py +0 -0
- {cetk-0.0.6.dev0 → cetk-0.0.8.dev0}/tests/edb/test_gridsource_models.py +0 -0
- {cetk-0.0.6.dev0 → cetk-0.0.8.dev0}/tests/edb/test_importers.py +0 -0
- {cetk-0.0.6.dev0 → cetk-0.0.8.dev0}/tests/edb/test_ltreefield.py +0 -0
- {cetk-0.0.6.dev0 → cetk-0.0.8.dev0}/tests/edb/test_road_classes.py +0 -0
- {cetk-0.0.6.dev0 → cetk-0.0.8.dev0}/tests/edb/test_road_importers.py +0 -0
- {cetk-0.0.6.dev0 → cetk-0.0.8.dev0}/tests/edb/test_road_models.py +0 -0
- {cetk-0.0.6.dev0 → cetk-0.0.8.dev0}/tests/emissions/__init__.py +0 -0
- {cetk-0.0.6.dev0 → cetk-0.0.8.dev0}/tests/emissions/test_areasource_emissions.py +0 -0
- {cetk-0.0.6.dev0 → cetk-0.0.8.dev0}/tests/emissions/test_custom_sqlite_functions.py +0 -0
- {cetk-0.0.6.dev0 → cetk-0.0.8.dev0}/tests/emissions/test_gridsource_emissions.py +0 -0
- {cetk-0.0.6.dev0 → cetk-0.0.8.dev0}/tests/emissions/test_pointsource_emissions.py +0 -0
- {cetk-0.0.6.dev0 → cetk-0.0.8.dev0}/tests/emissions/test_roadsource_emissions.py +0 -0
- {cetk-0.0.6.dev0 → cetk-0.0.8.dev0}/tests/emissions/test_utils.py +0 -0
- {cetk-0.0.6.dev0 → cetk-0.0.8.dev0}/tests/test_db.py +0 -0
- {cetk-0.0.6.dev0 → cetk-0.0.8.dev0}/tests/tools/conftest.py +0 -0
- {cetk-0.0.6.dev0 → cetk-0.0.8.dev0}/tests/tools/data/__init__.py +0 -0
- {cetk-0.0.6.dev0 → cetk-0.0.8.dev0}/tests/tools/data/inventory.xlsx +0 -0
- {cetk-0.0.6.dev0 → cetk-0.0.8.dev0}/tests/tools/data/validation.xlsx +0 -0
- {cetk-0.0.6.dev0 → cetk-0.0.8.dev0}/tests/tools/test_create.py +0 -0
- {cetk-0.0.6.dev0 → cetk-0.0.8.dev0}/tests/tools/test_delete.py +0 -0
- {cetk-0.0.6.dev0 → cetk-0.0.8.dev0}/tests/tools/test_exports.py +0 -0
- {cetk-0.0.6.dev0 → cetk-0.0.8.dev0}/tests/tools/test_imports.py +0 -0
- {cetk-0.0.6.dev0 → cetk-0.0.8.dev0}/tests/tools/test_info.py +0 -0
- {cetk-0.0.6.dev0 → cetk-0.0.8.dev0}/windows_find_gdal.py +0 -0
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
``` console
|
|
12
12
|
$ git clone https://git.smhi.se/foclair/cetk.git
|
|
13
13
|
$ cd cetk
|
|
14
|
-
$ python3.
|
|
14
|
+
$ python3.11 -m venv --prompt cetk .venv
|
|
15
15
|
$ . .venv/bin/activate
|
|
16
16
|
$ pip install -U pip setuptools wheel
|
|
17
17
|
$ pip install -r requirements.txt
|
|
@@ -23,7 +23,7 @@ $ pip install -e .
|
|
|
23
23
|
``` console
|
|
24
24
|
$ git clone https://git.smhi.se/foclair/cetk.git
|
|
25
25
|
$ cd cetk
|
|
26
|
-
$ python3.
|
|
26
|
+
$ python3.11 -m venv --prompt cetk .venv
|
|
27
27
|
$ . .venv/Scripts/activate
|
|
28
28
|
$ pip install pre-commit
|
|
29
29
|
$ pip install -e .
|
|
@@ -41,5 +41,5 @@ Dependencies are organized in the following files:
|
|
|
41
41
|
| Filename | Contents |
|
|
42
42
|
| ---------------------------------- | ------------------------------------------------------------------------- |
|
|
43
43
|
| constraints.txt | Version constraints for pinned requirements |
|
|
44
|
-
| requirements.txt | Pinned requirements for _using_ cetk (don't edit)
|
|
45
|
-
| setup.py | Loose requirements for _using_ cetk
|
|
44
|
+
| requirements.txt | Pinned requirements for _using_ cetk (don't edit) |
|
|
45
|
+
| setup.py | Loose requirements for _using_ cetk |
|
|
@@ -1,25 +1,26 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: cetk
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.8.dev0
|
|
4
4
|
Summary: CLAIRs Emission ToolKit cetk
|
|
5
5
|
Author: Christian Asker, Mattias Jakobsson, David Segersson, Eef van Dongen
|
|
6
6
|
Maintainer-email: FO Luft <foluftadmin@smhi.se>
|
|
7
7
|
License-Expression: Apache-2.0
|
|
8
8
|
Classifier: Programming Language :: Python :: 3
|
|
9
9
|
Classifier: Topic :: Scientific/Engineering :: Atmospheric Science
|
|
10
|
-
Requires-Python: >=3.
|
|
10
|
+
Requires-Python: >=3.11
|
|
11
11
|
Description-Content-Type: text/markdown
|
|
12
12
|
License-File: LICENSE
|
|
13
|
-
Requires-Dist:
|
|
14
|
-
Requires-Dist:
|
|
13
|
+
Requires-Dist: affine<3.0.1
|
|
14
|
+
Requires-Dist: django<6,>=5.2.16
|
|
15
|
+
Requires-Dist: fiona>=1.8.22
|
|
15
16
|
Requires-Dist: geopandas>=0.12
|
|
16
|
-
Requires-Dist: netCDF4>=1.
|
|
17
|
-
Requires-Dist: numpy
|
|
17
|
+
Requires-Dist: netCDF4>=1.6.1
|
|
18
|
+
Requires-Dist: numpy<2.5,>=1.20.3
|
|
18
19
|
Requires-Dist: openpyxl>=3.0.7
|
|
19
20
|
Requires-Dist: pandas>=2.0
|
|
20
|
-
Requires-Dist: pyogrio>=0.
|
|
21
|
-
Requires-Dist:
|
|
22
|
-
Requires-Dist: rasterio>=1.3
|
|
21
|
+
Requires-Dist: pyogrio>=0.5.0
|
|
22
|
+
Requires-Dist: rastafari2>=0.4
|
|
23
|
+
Requires-Dist: rasterio>=1.3.3
|
|
23
24
|
Requires-Dist: shapely>=2.0
|
|
24
25
|
Dynamic: license-file
|
|
25
26
|
|
|
@@ -1,28 +1,30 @@
|
|
|
1
1
|
# This file was autogenerated by uv via the following command:
|
|
2
2
|
# nox -s constraints-lowest
|
|
3
|
-
affine==
|
|
4
|
-
# via
|
|
5
|
-
|
|
3
|
+
affine==1.0
|
|
4
|
+
# via
|
|
5
|
+
# cetk (pyproject.toml)
|
|
6
|
+
# rasterio
|
|
7
|
+
asgiref==3.12.1
|
|
6
8
|
# via django
|
|
7
|
-
attrs==
|
|
9
|
+
attrs==26.1.0
|
|
8
10
|
# via
|
|
9
11
|
# fiona
|
|
10
12
|
# rasterio
|
|
11
|
-
certifi==
|
|
13
|
+
certifi==2026.7.22
|
|
12
14
|
# via
|
|
13
15
|
# fiona
|
|
14
16
|
# pyogrio
|
|
15
17
|
# pyproj
|
|
16
18
|
# rasterio
|
|
17
|
-
cftime==1.6.
|
|
19
|
+
cftime==1.6.5
|
|
18
20
|
# via netcdf4
|
|
19
|
-
click==
|
|
21
|
+
click==8.5.0
|
|
20
22
|
# via
|
|
21
23
|
# click-plugins
|
|
22
24
|
# cligj
|
|
23
25
|
# fiona
|
|
24
26
|
# rasterio
|
|
25
|
-
click-plugins==1.1.1
|
|
27
|
+
click-plugins==1.1.1.2
|
|
26
28
|
# via
|
|
27
29
|
# fiona
|
|
28
30
|
# rasterio
|
|
@@ -30,11 +32,11 @@ cligj==0.7.2
|
|
|
30
32
|
# via
|
|
31
33
|
# fiona
|
|
32
34
|
# rasterio
|
|
33
|
-
django==
|
|
35
|
+
django==5.2.16
|
|
34
36
|
# via cetk (pyproject.toml)
|
|
35
37
|
et-xmlfile==2.0.0
|
|
36
38
|
# via openpyxl
|
|
37
|
-
fiona==1.8.
|
|
39
|
+
fiona==1.8.22
|
|
38
40
|
# via
|
|
39
41
|
# cetk (pyproject.toml)
|
|
40
42
|
# geopandas
|
|
@@ -42,45 +44,47 @@ geopandas==0.12.1
|
|
|
42
44
|
# via cetk (pyproject.toml)
|
|
43
45
|
munch==4.0.0
|
|
44
46
|
# via fiona
|
|
45
|
-
netcdf4==1.
|
|
47
|
+
netcdf4==1.6.1
|
|
46
48
|
# via cetk (pyproject.toml)
|
|
47
|
-
numpy==1.
|
|
49
|
+
numpy==1.23.2
|
|
48
50
|
# via
|
|
49
51
|
# cetk (pyproject.toml)
|
|
50
52
|
# cftime
|
|
51
53
|
# netcdf4
|
|
52
54
|
# pandas
|
|
53
55
|
# pyogrio
|
|
54
|
-
#
|
|
56
|
+
# rastafari2
|
|
55
57
|
# rasterio
|
|
56
58
|
# shapely
|
|
57
59
|
# snuggs
|
|
58
60
|
openpyxl==3.0.7
|
|
59
61
|
# via cetk (pyproject.toml)
|
|
60
|
-
packaging==
|
|
62
|
+
packaging==26.3
|
|
61
63
|
# via geopandas
|
|
62
64
|
pandas==2.0.0
|
|
63
65
|
# via
|
|
64
66
|
# cetk (pyproject.toml)
|
|
65
67
|
# geopandas
|
|
66
|
-
pyogrio==0.
|
|
68
|
+
pyogrio==0.5.0
|
|
67
69
|
# via cetk (pyproject.toml)
|
|
68
|
-
pyparsing==3.2
|
|
70
|
+
pyparsing==3.3.2
|
|
69
71
|
# via snuggs
|
|
70
|
-
pyproj==3.
|
|
72
|
+
pyproj==3.7.2
|
|
71
73
|
# via
|
|
72
74
|
# geopandas
|
|
73
|
-
#
|
|
75
|
+
# rastafari2
|
|
74
76
|
python-dateutil==2.9.0.post0
|
|
75
77
|
# via pandas
|
|
76
|
-
pytz==
|
|
78
|
+
pytz==2026.3.post1
|
|
77
79
|
# via pandas
|
|
78
|
-
|
|
80
|
+
rastafari2==0.4.1.2
|
|
79
81
|
# via cetk (pyproject.toml)
|
|
80
|
-
rasterio==1.3.
|
|
82
|
+
rasterio==1.3.3
|
|
81
83
|
# via cetk (pyproject.toml)
|
|
82
|
-
setuptools==
|
|
83
|
-
# via
|
|
84
|
+
setuptools==84.0.0
|
|
85
|
+
# via
|
|
86
|
+
# fiona
|
|
87
|
+
# rasterio
|
|
84
88
|
shapely==2.0.0
|
|
85
89
|
# via
|
|
86
90
|
# cetk (pyproject.toml)
|
|
@@ -91,9 +95,7 @@ six==1.17.0
|
|
|
91
95
|
# python-dateutil
|
|
92
96
|
snuggs==1.4.7
|
|
93
97
|
# via rasterio
|
|
94
|
-
sqlparse==0.
|
|
98
|
+
sqlparse==0.6.0
|
|
95
99
|
# via django
|
|
96
|
-
|
|
97
|
-
# via asgiref
|
|
98
|
-
tzdata==2025.2
|
|
100
|
+
tzdata==2026.4
|
|
99
101
|
# via pandas
|
|
@@ -19,7 +19,7 @@ def requirements_dev(session):
|
|
|
19
19
|
pip_compile(session, "requirements-dev.txt", "requirements-dev.in")
|
|
20
20
|
|
|
21
21
|
|
|
22
|
-
@nox.session(name="constraints-lowest", python="3.
|
|
22
|
+
@nox.session(name="constraints-lowest", python="3.11")
|
|
23
23
|
def constraints_lowest(session):
|
|
24
24
|
"""Re-compile the constraints for the lowest allowed dependency versions"""
|
|
25
25
|
session.install("-c", "requirements-dev.txt", "uv")
|
|
@@ -58,7 +58,7 @@ def test(session):
|
|
|
58
58
|
session.run("pytest", *session.posargs)
|
|
59
59
|
|
|
60
60
|
|
|
61
|
-
@nox.session(name="test-lowest", python="3.
|
|
61
|
+
@nox.session(name="test-lowest", python="3.11")
|
|
62
62
|
def test_lowest(session):
|
|
63
63
|
"""Run the unit and regression tests with the lowest allowed versions."""
|
|
64
64
|
session.install("-c", "requirements-dev.txt", *TEST_REQUIREMENTS)
|
|
@@ -15,7 +15,7 @@ maintainers = [
|
|
|
15
15
|
]
|
|
16
16
|
description = "CLAIRs Emission ToolKit cetk"
|
|
17
17
|
readme = "README.md"
|
|
18
|
-
requires-python = ">=3.
|
|
18
|
+
requires-python = ">=3.11"
|
|
19
19
|
license = "Apache-2.0"
|
|
20
20
|
license-files = ["LICENSE"]
|
|
21
21
|
classifiers = [
|
|
@@ -23,16 +23,17 @@ classifiers = [
|
|
|
23
23
|
"Topic :: Scientific/Engineering :: Atmospheric Science",
|
|
24
24
|
]
|
|
25
25
|
dependencies = [ # Release date Comment
|
|
26
|
-
"
|
|
27
|
-
"
|
|
26
|
+
"affine<3.0.1", # 2026-08-28 required by rasterio - support for 3.0.1+ pending
|
|
27
|
+
"django >=5.2.16,<6",# 2026-07-07 due to dependabot alerts
|
|
28
|
+
"fiona >=1.8.22", # 2022-10-17 first version with cp311 wheel
|
|
28
29
|
"geopandas >=0.12", # 2022-10-24 first version with shapely 2 support
|
|
29
|
-
"netCDF4 >=1.
|
|
30
|
-
"numpy >=1.20.3", # 2021-05-10 required by pandas 2.0.0
|
|
30
|
+
"netCDF4 >=1.6.1", # 2022-09-15 first version with cp311 wheel
|
|
31
|
+
"numpy >=1.20.3, <2.5", # 2021-05-10 required by pandas 2.0.0, numpy 2.5 not compatible with NetCDF4
|
|
31
32
|
"openpyxl >=3.0.7", # 2021-03-09 required by pandas 2.0.0
|
|
32
33
|
"pandas >=2.0", # 2023-04-03 cetk import test fails with earlier versions
|
|
33
|
-
"pyogrio >=0.
|
|
34
|
-
"
|
|
35
|
-
"rasterio >=1.3",
|
|
34
|
+
"pyogrio >=0.5.0", # 2023-01-16 first version with cp311 wheel
|
|
35
|
+
"rastafari2 >=0.4",
|
|
36
|
+
"rasterio >=1.3.3", # 2022-10-19 first version with cp311 wheel
|
|
36
37
|
"shapely >=2.0", # 2022-12-12 cetk calc --rasterize fails with earlier versions
|
|
37
38
|
]
|
|
38
39
|
dynamic = ["version"]
|
|
@@ -248,6 +248,13 @@ def import_emissionfactorsheet(workbook, validation):
|
|
|
248
248
|
validation=validation,
|
|
249
249
|
)
|
|
250
250
|
)
|
|
251
|
+
except Exception:
|
|
252
|
+
return_message.append(
|
|
253
|
+
import_error(
|
|
254
|
+
f"Failed to import sheet 'EmissionFactor'. Check row {row_nr + 2} for errors.",
|
|
255
|
+
validation=validation,
|
|
256
|
+
)
|
|
257
|
+
)
|
|
251
258
|
except KeyError:
|
|
252
259
|
return_message.append(
|
|
253
260
|
import_error(
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import pandas as pd
|
|
2
|
+
|
|
1
3
|
from cetk.edb.models import ActivityCode, CodeSet, VerticalDist
|
|
2
4
|
|
|
3
5
|
from .utils import import_error, worksheet_to_dataframe
|
|
@@ -76,7 +78,7 @@ def import_activitycodesheet(workbook, validation):
|
|
|
76
78
|
try:
|
|
77
79
|
codeset = CodeSet.objects.get(slug=row_dict["codeset_slug"])
|
|
78
80
|
if "vertical_distribution_slug" in row_dict:
|
|
79
|
-
if row_dict["vertical_distribution_slug"]
|
|
81
|
+
if not pd.isna(row_dict["vertical_distribution_slug"]):
|
|
80
82
|
try:
|
|
81
83
|
vdist = VerticalDist.objects.get(
|
|
82
84
|
slug=row_dict["vertical_distribution_slug"]
|
|
@@ -105,7 +105,7 @@ def validate_gridsources(df, timevars, code_sets, raster_names, datadir):
|
|
|
105
105
|
messages += validate_activitycodes(row_dict, code_sets, row_nr=row_nr)
|
|
106
106
|
messages += validate_timevar(row_dict, timevars, row_nr=row_nr)
|
|
107
107
|
messages += validate_unit(row_dict, row_nr)
|
|
108
|
-
for col in filter(lambda x: row_dict[x]
|
|
108
|
+
for col in filter(lambda x: not pd.isna(row_dict[x]), subst_cols):
|
|
109
109
|
subst_slug = col[6:]
|
|
110
110
|
messages += validate_raster(
|
|
111
111
|
row_dict, raster_names, datadir, rasters, row_nr, subst_slug
|
|
@@ -121,7 +121,7 @@ def validate_gridsources(df, timevars, code_sets, raster_names, datadir):
|
|
|
121
121
|
subst_slug,
|
|
122
122
|
)
|
|
123
123
|
)
|
|
124
|
-
for col in filter(lambda x: row_dict[x]
|
|
124
|
+
for col in filter(lambda x: not pd.isna(row_dict[x]), act_cols):
|
|
125
125
|
act_name = col[4:].strip()
|
|
126
126
|
messages += validate_raster(
|
|
127
127
|
row_dict, raster_names, datadir, rasters, row_nr, subst_slug
|
|
@@ -205,7 +205,7 @@ def import_gridsources(filepath, encoding=None):
|
|
|
205
205
|
# set tags
|
|
206
206
|
tag_keys = [key for key in row_dict.keys() if key.startswith("tag:")]
|
|
207
207
|
src.tags = {
|
|
208
|
-
key[4:]: row_dict[key] for key in tag_keys if row_dict[key]
|
|
208
|
+
key[4:]: row_dict[key] for key in tag_keys if not pd.isna(row_dict[key])
|
|
209
209
|
}
|
|
210
210
|
validate_activitycodes(row_dict, code_sets, row_nr, src)
|
|
211
211
|
validate_timevar(row_dict, timevars, row_nr, src)
|
|
@@ -216,7 +216,7 @@ def import_gridsources(filepath, encoding=None):
|
|
|
216
216
|
src.substances.all().delete()
|
|
217
217
|
src.activities.all().delete()
|
|
218
218
|
|
|
219
|
-
for col in filter(lambda x: row_dict[x]
|
|
219
|
+
for col in filter(lambda x: not pd.isna(row_dict[x]), subst_cols):
|
|
220
220
|
subst = col[6:]
|
|
221
221
|
# if sum is specified instead of an emission total,
|
|
222
222
|
# the emission value is calculated as the sum of the raster
|
|
@@ -232,7 +232,7 @@ def import_gridsources(filepath, encoding=None):
|
|
|
232
232
|
emis["value"] = emission_unit_to_si(float(emis_value), unit)
|
|
233
233
|
src.substances.create(**emis)
|
|
234
234
|
|
|
235
|
-
for col in filter(lambda x: row_dict[x]
|
|
235
|
+
for col in filter(lambda x: not pd.isna(row_dict[x]), act_cols):
|
|
236
236
|
activity_name = col[4:]
|
|
237
237
|
rname, rpath = data_to_raster(
|
|
238
238
|
row_dict["rastername"], row_dict["path"], datadir, subst
|
|
@@ -261,9 +261,7 @@ def create_or_update_sources(
|
|
|
261
261
|
|
|
262
262
|
# set dataframe index
|
|
263
263
|
try:
|
|
264
|
-
df.set_index(
|
|
265
|
-
["facility_id", "source_name"], verify_integrity=True, inplace=True
|
|
266
|
-
)
|
|
264
|
+
df.set_index(["facility_id", "source_name"], inplace=True)
|
|
267
265
|
except ValueError as err:
|
|
268
266
|
return_message.append(
|
|
269
267
|
import_error(
|
|
@@ -601,7 +599,7 @@ def create_or_update_sources(
|
|
|
601
599
|
else:
|
|
602
600
|
return_message.append(
|
|
603
601
|
import_error(
|
|
604
|
-
f"
|
|
602
|
+
f"Multiple rows have the same source_name '{source_name}' in the PointSource sheet. Correct duplicates under facility_id or source_name before import.",
|
|
605
603
|
validation=validation,
|
|
606
604
|
)
|
|
607
605
|
)
|
|
@@ -812,7 +810,14 @@ def import_sourceactivities(
|
|
|
812
810
|
log.debug("validating/importing sheet PointSource")
|
|
813
811
|
data = workbook["PointSource"].values
|
|
814
812
|
df_pointsource = worksheet_to_dataframe(data)
|
|
815
|
-
|
|
813
|
+
|
|
814
|
+
try:
|
|
815
|
+
df_pointsource = set_datatypes(df_pointsource, "point")
|
|
816
|
+
except ValueError as exc:
|
|
817
|
+
return_message.append(
|
|
818
|
+
import_error(str(exc) + " in spreadsheet 'PointSource'", validation)
|
|
819
|
+
)
|
|
820
|
+
|
|
816
821
|
# import pointsources and pointsourcesubstances
|
|
817
822
|
caching_sources = len(df_pointsource) > PointSource.objects.count()
|
|
818
823
|
ps, msgs = create_or_update_sources(
|
|
@@ -68,10 +68,15 @@ def cache_codesets():
|
|
|
68
68
|
|
|
69
69
|
|
|
70
70
|
def worksheet_to_dataframe(data):
|
|
71
|
+
# breakpoint()
|
|
71
72
|
data = list(data)
|
|
72
73
|
if not data:
|
|
73
74
|
raise EmptySheet("Sheet is empty")
|
|
74
|
-
df = pd.DataFrame(data)
|
|
75
|
+
# df = pd.DataFrame(data)
|
|
76
|
+
df = pd.DataFrame(data, dtype=object)
|
|
77
|
+
# Convert all NaN to None
|
|
78
|
+
df = df.where(pd.notna(df), None)
|
|
79
|
+
|
|
75
80
|
# Set the first row as the header
|
|
76
81
|
df.columns = df.iloc[0]
|
|
77
82
|
df = df[1:].reset_index(drop=True)
|
|
@@ -99,9 +99,9 @@ def validate_timevar(values, timevars, row_nr, src=None):
|
|
|
99
99
|
|
|
100
100
|
|
|
101
101
|
def data_to_raster(raster_name, raster_path, datadir, substance):
|
|
102
|
-
if
|
|
102
|
+
if not pd.isna(raster_path):
|
|
103
103
|
# generate raster name form path
|
|
104
|
-
if raster_name
|
|
104
|
+
if pd.isna(raster_name):
|
|
105
105
|
raster_name = splitext(basename(raster_path))[0]
|
|
106
106
|
# if placeholder is used for substance in path
|
|
107
107
|
# the raster-name will be given a suffix
|
|
@@ -1445,7 +1445,7 @@ class Migration(migrations.Migration):
|
|
|
1445
1445
|
migrations.AddConstraint(
|
|
1446
1446
|
model_name="fleet",
|
|
1447
1447
|
constraint=models.CheckConstraint(
|
|
1448
|
-
|
|
1448
|
+
condition=models.Q(("default_heavy_vehicle_share__range", (0, 1))),
|
|
1449
1449
|
name="fleet_default_heavy_vehicle_share_between_0_and_1",
|
|
1450
1450
|
),
|
|
1451
1451
|
),
|
|
@@ -1594,25 +1594,25 @@ class Migration(migrations.Migration):
|
|
|
1594
1594
|
migrations.AddConstraint(
|
|
1595
1595
|
model_name="roadsource",
|
|
1596
1596
|
constraint=models.CheckConstraint(
|
|
1597
|
-
|
|
1597
|
+
condition=models.Q(("aadt__gte", 0)), name="road_source_aadt_gte_0"
|
|
1598
1598
|
),
|
|
1599
1599
|
),
|
|
1600
1600
|
migrations.AddConstraint(
|
|
1601
1601
|
model_name="roadsource",
|
|
1602
1602
|
constraint=models.CheckConstraint(
|
|
1603
|
-
|
|
1603
|
+
condition=models.Q(("nolanes__gt", 0)), name="road_source_nolanes_gt_0"
|
|
1604
1604
|
),
|
|
1605
1605
|
),
|
|
1606
1606
|
migrations.AddConstraint(
|
|
1607
1607
|
model_name="roadsource",
|
|
1608
1608
|
constraint=models.CheckConstraint(
|
|
1609
|
-
|
|
1609
|
+
condition=models.Q(("width__gt", 0)), name="road_source_width_gt_0"
|
|
1610
1610
|
),
|
|
1611
1611
|
),
|
|
1612
1612
|
migrations.AddConstraint(
|
|
1613
1613
|
model_name="roadsource",
|
|
1614
1614
|
constraint=models.CheckConstraint(
|
|
1615
|
-
|
|
1615
|
+
condition=models.Q(
|
|
1616
1616
|
("median_strip_width__gte", 0),
|
|
1617
1617
|
("median_strip_width__lt", models.F("width")),
|
|
1618
1618
|
),
|
|
@@ -1622,7 +1622,7 @@ class Migration(migrations.Migration):
|
|
|
1622
1622
|
migrations.AddConstraint(
|
|
1623
1623
|
model_name="roadsource",
|
|
1624
1624
|
constraint=models.CheckConstraint(
|
|
1625
|
-
|
|
1625
|
+
condition=models.Q(("heavy_vehicle_share__range", (0, 1))),
|
|
1626
1626
|
name="road_source_heavy_vehicle_share_between_0_and_1",
|
|
1627
1627
|
),
|
|
1628
1628
|
),
|
|
@@ -25,7 +25,6 @@ class FleetManager(models.Manager):
|
|
|
25
25
|
for f in data:
|
|
26
26
|
for m in f["members"]:
|
|
27
27
|
for fu in m["fuels"]:
|
|
28
|
-
# breakpoint()
|
|
29
28
|
if (m["vehicle"], fu["fuel"]) not in validcombinations:
|
|
30
29
|
raise ValueError(
|
|
31
30
|
f"{m['vehicle']}/{fu['fuel']} is not a valid vehicle/fuel"
|
|
@@ -87,7 +86,7 @@ class Fleet(models.Model):
|
|
|
87
86
|
default_related_name = "fleets"
|
|
88
87
|
constraints = [
|
|
89
88
|
models.CheckConstraint(
|
|
90
|
-
|
|
89
|
+
condition=Q(default_heavy_vehicle_share__range=(0, 1)),
|
|
91
90
|
name="fleet_default_heavy_vehicle_share_between_0_and_1",
|
|
92
91
|
),
|
|
93
92
|
]
|
|
@@ -228,19 +228,23 @@ class RoadSource(SourceBase):
|
|
|
228
228
|
class Meta:
|
|
229
229
|
default_related_name = "roadsources"
|
|
230
230
|
constraints = [
|
|
231
|
-
models.CheckConstraint(check=Q(aadt__gte=0), name="road_source_aadt_gte_0"),
|
|
232
231
|
models.CheckConstraint(
|
|
233
|
-
|
|
232
|
+
condition=Q(aadt__gte=0), name="road_source_aadt_gte_0"
|
|
234
233
|
),
|
|
235
|
-
models.CheckConstraint(check=Q(width__gt=0), name="road_source_width_gt_0"),
|
|
236
234
|
models.CheckConstraint(
|
|
237
|
-
|
|
235
|
+
condition=Q(nolanes__gt=0), name="road_source_nolanes_gt_0"
|
|
236
|
+
),
|
|
237
|
+
models.CheckConstraint(
|
|
238
|
+
condition=Q(width__gt=0), name="road_source_width_gt_0"
|
|
239
|
+
),
|
|
240
|
+
models.CheckConstraint(
|
|
241
|
+
condition=(
|
|
238
242
|
Q(median_strip_width__gte=0) & Q(median_strip_width__lt=F("width"))
|
|
239
243
|
),
|
|
240
244
|
name="road_source_median_strip_width_between_0_and_width",
|
|
241
245
|
),
|
|
242
246
|
models.CheckConstraint(
|
|
243
|
-
|
|
247
|
+
condition=Q(heavy_vehicle_share__range=(0, 1)),
|
|
244
248
|
name="road_source_heavy_vehicle_share_between_0_and_1",
|
|
245
249
|
),
|
|
246
250
|
]
|
|
@@ -318,15 +318,7 @@ class EmissionRasterizer:
|
|
|
318
318
|
"""Get querysets for emissions."""
|
|
319
319
|
|
|
320
320
|
sourcetypes = sourcetypes or SOURCETYPES
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
# if ac1 is not None or ac2 is not None or ac3 is not None:
|
|
324
|
-
# breakpoint()
|
|
325
|
-
# # raise ValueError(
|
|
326
|
-
# # "filtering for ac not implemented in source_emissions_query yet!"
|
|
327
|
-
# # )
|
|
328
|
-
# if activity codes are given as strings, get the corresponding
|
|
329
|
-
# activity code instances
|
|
321
|
+
|
|
330
322
|
if ac1 is not None and len(ac1) > 0 and isinstance(ac1[0], str):
|
|
331
323
|
# TODO why code__in= not code= ?
|
|
332
324
|
codeset1 = Settings.get_current().codeset1
|
|
@@ -708,10 +700,12 @@ class EmissionRasterizer:
|
|
|
708
700
|
name=var_name,
|
|
709
701
|
unit=self.unit,
|
|
710
702
|
instance=self.instance,
|
|
703
|
+
substance=substance.slug,
|
|
711
704
|
cell_methods=cell_methods,
|
|
712
705
|
parameter=param.name,
|
|
713
706
|
time=time,
|
|
714
707
|
chunksizes=chunking,
|
|
708
|
+
quantity="emission",
|
|
715
709
|
)
|
|
716
710
|
subst_vars["field2d"] = {"emission": var_name}
|
|
717
711
|
else:
|
|
@@ -890,6 +884,7 @@ class EmissionRasterizer:
|
|
|
890
884
|
# rasterizing chunks and writing to dataset
|
|
891
885
|
chunk_begin = begin
|
|
892
886
|
chunk_end = begin
|
|
887
|
+
chunk_time_ind = 0
|
|
893
888
|
while chunk_end < end:
|
|
894
889
|
if min_time_chunksize == 1e9:
|
|
895
890
|
# means no result_files exist
|
|
@@ -934,13 +929,19 @@ class EmissionRasterizer:
|
|
|
934
929
|
substance,
|
|
935
930
|
emis_chunk,
|
|
936
931
|
timestamps=[chunk_begin, chunk_end],
|
|
932
|
+
chunk_time_ind=chunk_time_ind,
|
|
937
933
|
)
|
|
938
934
|
# update time-span of variable and dataset
|
|
939
935
|
|
|
940
936
|
# update chunk time interval
|
|
937
|
+
chunk_time_ind = (
|
|
938
|
+
chunk_time_ind
|
|
939
|
+
+ int((chunk_end - chunk_begin).total_seconds() / 3600)
|
|
940
|
+
+ 1
|
|
941
|
+
)
|
|
941
942
|
chunk_begin = chunk_end + datetime.timedelta(hours=1)
|
|
942
943
|
|
|
943
|
-
def set_data(self, dset, substance, data, timestamps=None):
|
|
944
|
+
def set_data(self, dset, substance, data, timestamps=None, chunk_time_ind=0):
|
|
944
945
|
"""Add chunk of data to variable."""
|
|
945
946
|
|
|
946
947
|
var = dset[f"emission_{substance.slug}"]
|
|
@@ -951,12 +952,12 @@ class EmissionRasterizer:
|
|
|
951
952
|
else:
|
|
952
953
|
time_var = dset["time"]
|
|
953
954
|
# map_oriented, np.fliplr flips 3d data along second dimension
|
|
954
|
-
var[:, :, :] = np.fliplr(data)
|
|
955
|
+
var[chunk_time_ind:, :, :] = np.fliplr(data)
|
|
955
956
|
times = pd.date_range(timestamps[0], timestamps[1], freq=self.time_step)
|
|
956
957
|
hours_since_1970 = (
|
|
957
958
|
times - pd.to_datetime("1970-01-01").tz_localize(self.timezone)
|
|
958
959
|
).total_seconds() / 3600
|
|
959
|
-
time_var[:] = hours_since_1970
|
|
960
|
+
time_var[chunk_time_ind:] = hours_since_1970
|
|
960
961
|
|
|
961
962
|
def _timeseries_emis(self, substance, begin, end, sourcetype):
|
|
962
963
|
"""Get emission timeseries data chunk for sources.
|
|
@@ -1398,7 +1399,7 @@ class EmissionRasterizer:
|
|
|
1398
1399
|
self.log.info(
|
|
1399
1400
|
f"No exact match for EPSG and spatial ref, using best guess: {epsg}"
|
|
1400
1401
|
)
|
|
1401
|
-
|
|
1402
|
+
grid_mapping.srid = epsg
|
|
1402
1403
|
grid_mapping.crs_wkt = crs.to_wkt() # for CF Conventions 1.7
|
|
1403
1404
|
return grid_mapping
|
|
1404
1405
|
|
|
@@ -1409,6 +1410,7 @@ def create_variable(
|
|
|
1409
1410
|
name: str,
|
|
1410
1411
|
unit: Optional[str] = None,
|
|
1411
1412
|
quantity: Optional[str] = None,
|
|
1413
|
+
substance: Optional[str] = None,
|
|
1412
1414
|
instance: Optional[str] = None,
|
|
1413
1415
|
cell_methods: Optional[str] = None,
|
|
1414
1416
|
parameter: Optional[str] = None,
|
|
@@ -1437,6 +1439,8 @@ def create_variable(
|
|
|
1437
1439
|
var.parameter = parameter
|
|
1438
1440
|
if quantity is not None:
|
|
1439
1441
|
var.quantity = quantity
|
|
1442
|
+
if substance is not None:
|
|
1443
|
+
var.substance = substance
|
|
1440
1444
|
if instance is not None:
|
|
1441
1445
|
var.instance = instance
|
|
1442
1446
|
if cell_methods is not None:
|
|
@@ -125,7 +125,7 @@ def aggregate_emissions(
|
|
|
125
125
|
code_labels = dict(codeset.codes.values_list("code", "label"))
|
|
126
126
|
for ind in df.index:
|
|
127
127
|
code = df.loc[ind, "activitycode"]
|
|
128
|
-
if
|
|
128
|
+
if not pd.isna(code):
|
|
129
129
|
df.loc[ind, "activity"] = code_labels[code]
|
|
130
130
|
# add to index (to remain also after pivoting)
|
|
131
131
|
df.set_index(["activitycode", "activity"], inplace=True)
|