From abe409ad1365a9ad10416f672a57ffb307cc810d Mon Sep 17 00:00:00 2001 From: Bobby Xiong Date: Mon, 13 Apr 2026 14:10:05 +0200 Subject: [PATCH 1/5] Allow allow subregional NUTS selection. --- scripts/base_network.py | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/scripts/base_network.py b/scripts/base_network.py index 327a14df21..69b2df3341 100644 --- a/scripts/base_network.py +++ b/scripts/base_network.py @@ -1492,6 +1492,20 @@ def build_admin_shapes( .map(country_level) .map(level_map) ) + + # Overwrite if more specified subregions are available + subregion_level = { + k: v for k, v in admin_levels.items() if (k != "level") and (k[:2] in countries) and len(k)>2 + } + if subregion_level: + subregion_level_list = "\n".join( + [f"- {k}: level {v}" for k, v in subregion_level.items()] + ) + logger.info( + f"Setting individual administrative levels for subregions:\n{subregion_level_list}" + ) + for k, v in subregion_level.items(): + nuts3_regions.loc[nuts3_regions.index.str.startswith(k), "column"] = level_map[v] # If GB is in the countries, set the level, aggregate London area to level 1 due to converging issues if "GB" in countries and level != "bz": From abfd30b1a7136f86eb96abbd598aa36f13aa2fa4 Mon Sep 17 00:00:00 2001 From: Bobby Xiong Date: Mon, 13 Apr 2026 14:15:59 +0200 Subject: [PATCH 2/5] Updated schema. --- config/schema.default.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/schema.default.json b/config/schema.default.json index 0468c33193..def0421779 100644 --- a/config/schema.default.json +++ b/config/schema.default.json @@ -488,7 +488,7 @@ "additionalProperties": { "type": "integer" }, - "description": "Optionally include dictionary of individual country codes and their individual NUTS levels. Overwrites country-specific `level`. For example: `{'DE': 1, 'FR': 2}`. Only applies when mode is set to `administrative`.", + "description": "Optionally include dictionary of individual country or NUTS codes and their individual resolution. Overwrites country-specific `level`. For example: `{'DE': 1, 'FR': 2, 'DEA': 3}`. Only applies when mode is set to `administrative`.", "type": "object" } } From 2c737b2e967799cd2078b2c2f35f0f11332f2f1a Mon Sep 17 00:00:00 2001 From: Bobby Xiong Date: Mon, 13 Apr 2026 14:27:18 +0200 Subject: [PATCH 3/5] Schema update. --- config/schema.default.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/schema.default.json b/config/schema.default.json index def0421779..0468c33193 100644 --- a/config/schema.default.json +++ b/config/schema.default.json @@ -488,7 +488,7 @@ "additionalProperties": { "type": "integer" }, - "description": "Optionally include dictionary of individual country or NUTS codes and their individual resolution. Overwrites country-specific `level`. For example: `{'DE': 1, 'FR': 2, 'DEA': 3}`. Only applies when mode is set to `administrative`.", + "description": "Optionally include dictionary of individual country codes and their individual NUTS levels. Overwrites country-specific `level`. For example: `{'DE': 1, 'FR': 2}`. Only applies when mode is set to `administrative`.", "type": "object" } } From 80395344689064bc8ff8e5ad0a6a2979fd6f94b4 Mon Sep 17 00:00:00 2001 From: Bobby Xiong Date: Mon, 13 Apr 2026 14:43:30 +0200 Subject: [PATCH 4/5] Refactored code. --- scripts/base_network.py | 37 +++++++++---------------------------- 1 file changed, 9 insertions(+), 28 deletions(-) diff --git a/scripts/base_network.py b/scripts/base_network.py index 69b2df3341..a30e391a09 100644 --- a/scripts/base_network.py +++ b/scripts/base_network.py @@ -1469,41 +1469,22 @@ def build_admin_shapes( if clustering == "administrative": logger.info(f"Building bus regions at administrative level {level}") - nuts3_regions["column"] = level_map[level] - # Only keep the values whose keys are in countries - country_level = { - k: v for k, v in admin_levels.items() if (k != "level") and (k in countries) - } + countries_config = admin_levels.get("countries", {}) + country_level = {k: v for k, v in countries_config.items() if len(k) == 2 and k in countries} + subregion_level = {k: v for k, v in countries_config.items() if len(k) > 2 and k[:2] in countries} + if country_level: - country_level_list = "\n".join( - [f"- {k}: level {v}" for k, v in country_level.items()] - ) - logger.info( - f"Setting individual administrative levels for:\n{country_level_list}" - ) - nuts3_regions.loc[ - nuts3_regions["country"].isin(country_level.keys()), "column" - ] = ( - nuts3_regions.loc[ - nuts3_regions["country"].isin(country_level.keys()), "country" - ] + logger.info("Setting individual administrative levels for:\n" + "\n".join(f"- {k}: level {v}" for k, v in country_level.items())) + nuts3_regions.loc[nuts3_regions["country"].isin(country_level), "column"] = ( + nuts3_regions.loc[nuts3_regions["country"].isin(country_level), "country"] .map(country_level) .map(level_map) ) - - # Overwrite if more specified subregions are available - subregion_level = { - k: v for k, v in admin_levels.items() if (k != "level") and (k[:2] in countries) and len(k)>2 - } + if subregion_level: - subregion_level_list = "\n".join( - [f"- {k}: level {v}" for k, v in subregion_level.items()] - ) - logger.info( - f"Setting individual administrative levels for subregions:\n{subregion_level_list}" - ) + logger.info("Setting individual administrative levels for subregions:\n" + "\n".join(f"- {k}: level {v}" for k, v in subregion_level.items())) for k, v in subregion_level.items(): nuts3_regions.loc[nuts3_regions.index.str.startswith(k), "column"] = level_map[v] From c8f5a4afce0d7bd84b33b1d85ac69b99687ec17a Mon Sep 17 00:00:00 2001 From: Bobby Xiong Date: Mon, 13 Apr 2026 14:45:57 +0200 Subject: [PATCH 5/5] Ruff formatted. --- scripts/base_network.py | 32 +++++++++++++++++++++++++------- 1 file changed, 25 insertions(+), 7 deletions(-) diff --git a/scripts/base_network.py b/scripts/base_network.py index a30e391a09..ed0c551e43 100644 --- a/scripts/base_network.py +++ b/scripts/base_network.py @@ -1472,21 +1472,39 @@ def build_admin_shapes( nuts3_regions["column"] = level_map[level] countries_config = admin_levels.get("countries", {}) - country_level = {k: v for k, v in countries_config.items() if len(k) == 2 and k in countries} - subregion_level = {k: v for k, v in countries_config.items() if len(k) > 2 and k[:2] in countries} + country_level = { + k: v for k, v in countries_config.items() if len(k) == 2 and k in countries + } + subregion_level = { + k: v + for k, v in countries_config.items() + if len(k) > 2 and k[:2] in countries + } if country_level: - logger.info("Setting individual administrative levels for:\n" + "\n".join(f"- {k}: level {v}" for k, v in country_level.items())) - nuts3_regions.loc[nuts3_regions["country"].isin(country_level), "column"] = ( - nuts3_regions.loc[nuts3_regions["country"].isin(country_level), "country"] + logger.info( + "Setting individual administrative levels for:\n" + + "\n".join(f"- {k}: level {v}" for k, v in country_level.items()) + ) + nuts3_regions.loc[ + nuts3_regions["country"].isin(country_level), "column" + ] = ( + nuts3_regions.loc[ + nuts3_regions["country"].isin(country_level), "country" + ] .map(country_level) .map(level_map) ) if subregion_level: - logger.info("Setting individual administrative levels for subregions:\n" + "\n".join(f"- {k}: level {v}" for k, v in subregion_level.items())) + logger.info( + "Setting individual administrative levels for subregions:\n" + + "\n".join(f"- {k}: level {v}" for k, v in subregion_level.items()) + ) for k, v in subregion_level.items(): - nuts3_regions.loc[nuts3_regions.index.str.startswith(k), "column"] = level_map[v] + nuts3_regions.loc[nuts3_regions.index.str.startswith(k), "column"] = ( + level_map[v] + ) # If GB is in the countries, set the level, aggregate London area to level 1 due to converging issues if "GB" in countries and level != "bz":