Vai al contenuto

Modulo GeoData

Il modulo Geodata fornisce strumenti per la gestione e il preprocessing dei dati geografici, inclusi confini amministrativi e dati censuari. Le funzioni di questo modulo facilitano la lettura, il filtraggio e la conversione dei dati in formati utilizzabili per l'analisi geografica, come GeoDataFrame e GeoPackage.

Il codice nuovo dovrebbe importare da istat_census_data. Il riferimento qui sotto è generato dal modulo di implementazione per mantenere visibile la documentazione completa delle funzioni.

Stime censuarie H3

Usa estimate_h3_census_indexes() dopo aver creato il file finale census_data.gpkg con finalize_census_data(). Per impostazione predefinita la funzione legge il layer census<year>, usa il catalogo censuario incluso nel pacchetto per selezionare gli indicatori additivi presenti nel layer, genera le celle H3 di livello 11 per l'AOI e distribuisce i valori delle sezioni censuarie sorgenti con interpolazione pesata per area.

from pathlib import Path

import geopandas as gpd
from shapely.geometry import box

from istat_census_data import estimate_h3_census_indexes, generate_h3_grid

aoi = gpd.GeoDataFrame(
    geometry=[box(12.0, 41.0, 12.2, 41.2)],
    crs="EPSG:4326",
)

h3_estimates = estimate_h3_census_indexes(
    census_data_path=Path("census_data.gpkg"),
    year=2021,
    aoi=aoi,
    h3_resolution=11,
    indexes=["P1", "P2"],
    workers=4,
    chunk_size=5000,
    max_in_flight_chunks=4,
    output_path=Path("h3_census_2021.gpkg"),
)

Lo stimatore usa obbligatoriamente la risoluzione H3 11. L'argomento h3_resolution puo essere omesso perché il livello 11 e il valore predefinito, ma qualsiasi altro valore viene rifiutato. Le celle H3 di bordo vengono espanse per impostazione predefinita con tre anelli di vicinato tramite boundary_ring_size=3, cosi da non perdere celle che intersecano bordi AOI complessi.

generate_h3_grid() salva metadata di riuso e un fingerprint negli attributi del GeoDataFrame restituito. Il fingerprint include CRS normalizzato dell'AOI, risoluzione H3, boundary_ring_size, area_crs, CRS della griglia, bounds dell'AOI, area dell'AOI e hash della geometria AOI validata e unificata. I caller avanzati possono passare quella griglia a h3_grid per evitare di rigenerare celle identiche:

h3_grid = generate_h3_grid(
    aoi=aoi,
    h3_resolution=11,
    boundary_ring_size=3,
)

h3_estimates = estimate_h3_census_indexes(
    census_data_path=Path("census_data.gpkg"),
    year=2021,
    aoi=aoi,
    indexes=["P1", "P2"],
    h3_grid=h3_grid,
)

Lo stimatore valida il fingerprint prima del riuso. Una geometria AOI diversa, anche con lo stesso bounding box, o un parametro che definisce la griglia diverso produce un errore chiaro invece di riusare celle non valide.

Le colonne degli indicatori additivi nella tabella H3 restituita e nel GeoPackage scritto sono salvate come conteggi interi. Lo stimatore valida prima il calcolo continuo pesato per area in total_validation, poi distribuisce i valori interi con un passaggio a resto maggiore e registra i controlli post-allocazione in integer_total_validation. Le colonne di densita restano float.

Lo stesso workflow e disponibile come script di esempio modificabile in scripts/estimate_h3_census.py. Imposta i valori di modulo come census_data_path, aoi_path, selected_year, selected_indexes, boundary_ring_size, workers e chunk_size, poi esegui lo script. Usa selected_indexes = [] per stimare tutti gli indicatori additivi del catalogo presenti nel layer sorgente.

Storage intermedio H3

La stima H3 usa per impostazione predefinita uno storage intermedio basato su Parquet/GeoParquet. pyarrow e una dipendenza obbligatoria del pacchetto, quindi non serve installare extra per questa modalita. Lo stimatore scrive sezioni censuarie preparate, chunk preparati della griglia H3 e risultati compatti dei chunk in una workspace temporanea, poi rilegge i risultati dei chunk per costruire l'output finale GeoPackage.

Questo riduce il picco di RAM perché i worker non devono restituire grandi GeoDataFrame al processo principale. Inoltre evita di costruire molte colonne una per volta quando selected_indexes = [] si espande a tutti gli indicatori additivi.

Il percorso Parquet predefinito ritaglia anche la griglia H3 sulla AOI un chunk alla volta prima dell'inizio della stima. Le AOI grandi producono quindi file osservabili in grid_chunks/ invece di attendere la fine di una griglia H3 ritagliata completamente in memoria. Le directory di intermedi conservate non includono piu un file completo h3_grid.parquet.

La pianificazione parallela dei chunk e limitata da max_in_flight_chunks. Quando il valore e omesso, lo stimatore pianifica al massimo il numero di worker attivi. Questo default evita che Dask, thread e process mettano in coda tutti i chunk dell'AOI in memoria nello stesso momento.

Usa intermediate_dir quando vuoi una posizione prevedibile per gli intermedi. Usa keep_intermediates=True per ispezionare i file conservati e reuse_intermediates=True per riusare risultati chunk compatibili dalla stessa directory.

h3_estimates = estimate_h3_census_indexes(
    census_data_path=Path("census_data.gpkg"),
    year=2021,
    aoi=aoi,
    indexes=[],
    workers=4,
    chunk_size=5000,
    max_in_flight_chunks=4,
    intermediate_dir=Path("h3_intermediates"),
    keep_intermediates=True,
)

Imposta intermediate_storage="memory" solo quando vuoi esplicitamente il percorso in memoria legacy per AOI piccole o debug. L'output utente finale resta GeoPackage, a meno che tu ometta output_path e lavori direttamente con il GeoDataFrame restituito.

Esecuzione parallela e benchmark

La stima H3 e seriale per impostazione predefinita: workers=1. Per AOI piu grandi puoi impostare workers a un valore maggiore di 1 e scegliere un chunk_size per dividere la griglia H3 in chunk deterministici. Ogni cella H3 e elaborata da un solo chunk, quindi i risultati paralleli contengono le stesse celle del percorso seriale e devono corrispondere ai totali seriali entro la tolleranza dello stimatore.

h3_estimates = estimate_h3_census_indexes(
    census_data_path=Path("census_data.gpkg"),
    year=2021,
    aoi=aoi,
    indexes=["P1", "P2"],
    workers=4,
    chunk_size=5000,
    max_in_flight_chunks=4,
)

Con lo storage intermedio Parquet/GeoParquet predefinito, i worker thread, process e Dask scrivono un file risultato per ogni chunk e restituiscono path al processo principale. Per impostazione predefinita, il processo principale esegue la merge finale dopo il completamento dei chunk. Quando usi stream_output=True insieme a output_path, la finalizzazione scrive quei chunk direttamente nel GeoPackage, crea lo spatial index del layer e un indice tabellare unico su h3_index, e restituisce un GeoDataFrame solo di metadati con row_count e tabelle di validazione negli attrs. Usa parallel_backend="process" solo dopo un benchmark sulla tua macchina: puo aiutare negli overlay dominati dalla CPU, ma aggiunge overhead di avvio worker e I/O su disco.

Usa il backend opzionale Dask quando vuoi che Dask pianifichi localmente gli stessi chunk H3 deterministici:

pip install "istat-census-data[dask]"
h3_estimates = estimate_h3_census_indexes(
    census_data_path=Path("census_data.gpkg"),
    year=2021,
    aoi=aoi,
    indexes=["P1", "P2"],
    workers=4,
    chunk_size=5000,
    parallel_backend="dask",
    max_in_flight_chunks=4,
)

Il backend Dask usa attualmente lo scheduler locale a thread di Dask e lo stesso contratto a chunk Parquet dei backend standard. E un percorso runtime opzionale, non una dipendenza richiesta per le installazioni normali del pacchetto.

Inizia con workers non superiore ai core fisici disponibili per il processo. Per H3 livello 11, valori di chunk_size tra 2.000 e 10.000 celle sono un primo intervallo pratico. Chunk piu piccoli danno aggiornamenti di avanzamento piu frequenti ma aumentano l'overhead; chunk piu grandi riducono l'overhead ma possono lasciare worker inattivi verso la fine dell'elaborazione.

Mantieni max_in_flight_chunks uguale a workers per la prima elaborazione grande. Aumentalo solo dopo un benchmark che mostri che l'overhead di pianificazione pesa piu della pressione sulla memoria. Per AOI grandi come una regione intera, preferisci intermediate_storage="parquet" ed evita impostazioni Dask che mettano in coda piu chunk di quelli che la macchina puo gestire. In modalita Parquet, chunk_size controlla anche quante celle H3 vengono proiettate e ritagliate sulla AOI in ogni batch di preparazione della griglia.

Usa scripts/benchmark_h3_estimation.py su dati gia finalizzati per confrontare le impostazioni prima di eseguire una grande AOI di produzione. Modifica worker_counts, chunk_sizes, parallel_backend, max_in_flight_chunks, boundary_ring_size, intermediate_storage, keep_intermediates, reuse_intermediates e runs nello script. Mantieni selected_indexes = [] quando vuoi stimare tutti gli indicatori additivi presenti nel layer sorgente.

L'output del benchmark riporta secondi trascorsi, numero di celle H3 e stato della validazione dei totali per ogni combinazione worker/chunk. I record vengono loggati e scritti in JSON dopo ogni run completata, quindi le esecuzioni lunghe hanno avanzamento osservabile. Usa i tempi di AOI piccole come controllo di correttezza e overhead; AOI medie o grandi sono piu utili per decidere se l'esecuzione parallela conviene davvero.

Configurare lo script di benchmark

scripts/benchmark_h3_estimation.py si configura modificando le variabili di modulo dentro il file. Non e pensato per essere usato tramite argomenti CLI.

main_path = Path("/home/max/Desktop/census_test")
census_data_path = main_path / "census_data.gpkg"
aoi_path = main_path / "aoi.gpkg"
benchmark_output_path = main_path / "h3_benchmark.json"

selected_year = 2021
selected_indexes: list[str] = []
boundary_ring_size = DEFAULT_BOUNDARY_RING_SIZE

worker_counts = [1, 2, 4]
chunk_sizes = [DEFAULT_H3_CHUNK_SIZE]
parallel_backend = "thread"
max_in_flight_chunks = None

intermediate_storage = "parquet"
intermediate_dir = main_path / "h3_intermediates"
keep_intermediates = True
reuse_intermediates = False

runs = 1

Usa worker_counts = [1] per eseguire solo il percorso seriale. Inserisci valori maggiori di 1 per confrontare l'esecuzione parallela. Parti con parallel_backend = "thread"; prova parallel_backend = "process" o parallel_backend = "dask" solo dopo un benchmark di riferimento. Il backend Dask richiede l'installazione opzionale di Dask. Lascia max_in_flight_chunks = None per pianificare al massimo il numero di worker attivi, oppure imposta un intero positivo quando vuoi una dimensione batch ripetibile.

Mantieni boundary_ring_size = DEFAULT_BOUNDARY_RING_SIZE a meno che tu stia studiando un caso specifico di bordo AOI. Il default attuale e 3 ed e incluso nei record JSON del benchmark, cosi le run con copertura di bordo diversa restano confrontabili.

Imposta reuse_intermediates = False per una run cold che ricrea i file intermedi. Impostalo a True solo per una successiva run warm che deve riusare chunk compatibili mantenuti su disco. Mantieni keep_intermediates = True quando vuoi ispezionare o riusare i file Parquet/GeoParquet; impostalo a False per rimuoverli dopo la run.

Workflow H3 end-to-end

Usa run_h3_census_workflow() o scripts/run_h3_census_analysis.py quando vuoi che gli anni censuari scelti guidino l'intera pipeline. Il workflow scarica solo gli anni richiesti, li preprocessa, finalizza census_data.gpkg e poi scrive un layer H3 di livello 11 per ogni anno.

Per run multi-anno sulla stessa AOI, il workflow genera la griglia H3 una sola volta prima del ciclo sugli anni e la passa a ogni stima annuale. Preparazione delle sorgenti censuarie, overlay, validazione e scrittura layer restano comunque indipendenti per ogni anno.

Lo script di esempio modificabile scripts/run_h3_census_analysis.py espone lo stesso workflow con valori di modulo. Imposta list_year, main_path, aoi_path, list_region, municipalities_code e i controlli di performance nello script. Usa selected_indexes = [] per stimare tutti gli indicatori additivi disponibili in ogni anno selezionato. Il livello H3 e fisso a 11 e la policy sulle sezioni speciali/fittizie ha valore predefinito exclude.

Il workflow end-to-end espone gli stessi controlli di performance di PRP-012 disponibili nello stimatore su dati finalizzati. Modifica workers, chunk_size, parallel_backend e max_in_flight_chunks nello script per tarare elaborazioni grandi. Dopo aver installato istat-census-data[dask], imposta parallel_backend = "dask" per usare il backend Dask locale opzionale.

Per run regionali multi-anno, imposta retain_results=False. Con lo storage intermedio Parquet predefinito, il workflow scrive allora ogni layer annuale nel GeoPackage facendo streaming da result_chunks/, senza materializzare il GeoDataFrame annuale completo. Il risultato del workflow conserva comunque row_counts, total_validations e integer_total_validations per ogni anno.

Se i dati esistono gia, salta gli stadi completati impostando run_download, run_preprocess o run_finalize a False nello script.

Quando usi --skip-finalize, <data-dir>/census_data.gpkg deve gia esistere.

Lo stesso processo e disponibile da Python:

from pathlib import Path

import geopandas as gpd

from istat_census_data import run_h3_census_workflow

aoi = gpd.read_file("aoi.gpkg", layer="aoi")

result = run_h3_census_workflow(
    years=[2021],
    data_folder=Path("./census"),
    aoi=aoi,
    indexes=["P1", "P2"],
    municipality_codes=[58091],
    workers=4,
    chunk_size=5000,
    parallel_backend="thread",
    max_in_flight_chunks=4,
    retain_results=False,
)

print(result.output_path)
print(result.layers)

Il metodo assume densita uniforme dentro ogni sezione censuaria sorgente. Questa scelta e trasparente e conserva i totali additivi rispetto al totale delle celle sorgenti tagliate sull'AOI, ma non e un modello dasimetrico e non va interpretata come localizzazione esatta a livello di edificio o famiglia.

Sezioni censuarie speciali e fittizie

estimate_h3_census_indexes() segnala le sezioni censuarie sorgenti il cui codice contiene uno di questi marker:

Marker Significato Dati consegnati in quelle righe Interpretazione H3
888888 Sezioni fittizie per persone senza alloggio o senza fissa dimora iscritte in anagrafe. ISTAT documenta anche l'uso per persone iscritte tramite associazioni o strutture di accoglienza. Le righe possono contenere le stesse variabili dei file censuari a livello di sezione. Per queste sezioni gli indicatori di popolazione e persona/famiglia possono essere significativi, mentre gli indicatori su abitazioni o edifici non vanno letti come condizioni fisiche del poligono disegnato. La geometria e convenzionale. ISTAT indica che queste sezioni sono disegnate in aree disabitate, preferibilmente vicino alla casa comunale. Le densita H3 su quel poligono sono quindi un meccanismo di allocazione, non una stima della localizzazione residenziale.
999999 Sezioni fittizie collegate a zone in contestazione rivendicate da due o piu comuni. Le righe possono contenere individui residenti nel comune a cui la zona contestata non e assegnata ai fini censuari. Quando presenti nel layer finale, passano comunque attraverso il normale tracciato delle variabili a sezione. Tratta il risultato come allocazione amministrativa. Non interpretare la cella H3 come localizzazione precisa della residenza se la geometria della zona contestata non e appropriata per l'analisi.
7777777 Sezioni fittizie presenti solo nei dati 2011 dell'Abruzzo per comuni colpiti dal sisma dell'aprile 2009. ISTAT documenta queste sezioni per collocare le famiglie che alla data del censimento erano temporaneamente domiciliate in un comune diverso da quello di iscrizione anagrafica. Gli indicatori additivi di popolazione/famiglia possono quindi essere presenti, ma la geometria non e una normale geografia di residenza. Usa cautela in mappe di densita e overlay locali: le righe conservano la contabilita censuaria, ma la geometria codifica una convenzione amministrativa post-sisma.

Questi marker non sono trattati come dati mancanti, ma la stima H3 li esclude per impostazione predefinita perché le loro geometrie convenzionali possono produrre densita locali fuorvianti. Con special_section_policy="exclude", lo stimatore rimuove queste righe sorgenti prima dell'overlay pesato per area; i totali del risultato quindi escludono quei record.

Usa special_section_policy="include" solo quando devi conservare l'intera contabilita censuaria dentro l'AOI e accetti che poligoni convenzionali possano ricevere persone che non sono fisicamente distribuite in quel luogo. In questa modalita, lo stimatore include i loro valori nell'overlay pesato per area e imposta intersects_special_section=True per ogni cella H3 che riceve area da una di queste sezioni.

Usa una policy piu restrittiva quando questa convenzione non e accettabile:

h3_estimates = estimate_h3_census_indexes(
    census_data_path=Path("census_data.gpkg"),
    year=2021,
    aoi=aoi,
    indexes=["P1"],
    special_section_policy="raise",
)
  • exclude: valore predefinito per i processi H3; rimuove queste righe sorgenti prima della stima, quindi i totali le escludono.
  • include: mantiene le righe e segnala le celle H3 interessate.
  • raise: interrompe l'elaborazione con errore se una sezione speciale o fittizia interseca l'AOI.

Puoi ispezionare le celle H3 segnalate con:

flagged_cells = h3_estimates[h3_estimates["intersects_special_section"]]

Lo script di esempio espone la stessa policy tramite l'argomento special_section_policy passato a run().

Fonti: ISTAT documenta 888888x e 999999x in Dati per sezioni di censimento. ISTAT documenta zone in contestazione, sezioni per persone senza dimora e la convenzione 7777777 del 2011 in Abruzzo in Basi territoriali: anni 1991, 2001, 2011 e 2021.

preprocess_geodata(census_shp_folder, census_target_columns, census_tipo_loc_mapping, output_folder, census_layer_name, census_column_remapping=None, regions_file_path=None, regions_target_columns=None, regions_index_column=None, regions_column_remapping=None, provinces_file_path=None, provinces_target_columns=None, provinces_index_column=None, provinces_column_remapping=None, municipalities_file_path=None, municipalities_target_columns=None, municipalities_index_column=None, municipalities_column_remapping=None, municipalities_code=None)

Preprocess census geodata and administrative boundaries and save to GeoPackage.

This function executes the complete workflow for preparing geographic data for a census year, combining:

  1. Reading and normalizing administrative boundaries (regions, provinces, municipalities).
  2. Optionally correcting missing fields (e.g., COD_PROV for 2021).
  3. Reading and preparing census data (sections) from shapefiles.
  4. Joining sections with municipalities, provinces, and regions.
  5. Optionally filtering for a subset of municipalities (municipalities_code).
  6. Saving the final result to a GeoPackage.
PARAMETER DESCRIPTION
census_shp_folder

Folder containing census shapefiles (sections).

TYPE: Path

census_target_columns

Columns to select from census data (sections).

TYPE: list

census_tipo_loc_mapping

Mapping for the TIPO_LOC field to derive the locality type description.

TYPE: dict

output_folder

Folder where the resulting GeoPackage will be saved.

TYPE: Path

census_layer_name

Name of the census layer (e.g., census2011), also used to derive the year from the suffix.

TYPE: str

census_column_remapping

Optional mapping to rename census data columns.

TYPE: dict | None DEFAULT: None

regions_file_path

Optional path to the regional boundaries vector file.

TYPE: Path | None DEFAULT: None

regions_target_columns

Optional columns to select from regional data.

TYPE: list | None DEFAULT: None

regions_index_column

Optional column to use as index for regional data.

TYPE: str | None DEFAULT: None

regions_column_remapping

Optional mapping to rename regional data columns.

TYPE: dict | None DEFAULT: None

provinces_file_path

Optional path to the provincial boundaries vector file.

TYPE: Path | None DEFAULT: None

provinces_target_columns

Optional columns to select from provincial data.

TYPE: list | None DEFAULT: None

provinces_index_column

Optional column to use as index for provincial data.

TYPE: str | None DEFAULT: None

provinces_column_remapping

Optional mapping to rename provincial data columns.

TYPE: dict | None DEFAULT: None

municipalities_file_path

Optional path to the municipal boundaries vector file.

TYPE: Path | None DEFAULT: None

municipalities_target_columns

Optional columns to select from municipal data.

TYPE: list | None DEFAULT: None

municipalities_index_column

Optional column to use as index for municipal data.

TYPE: str | None DEFAULT: None

municipalities_column_remapping

Optional mapping to rename municipal data columns.

TYPE: dict | None DEFAULT: None

municipalities_code

Optional list of ISTAT municipality codes (PRO_COM field) to extract. If empty, all municipalities are kept.

TYPE: list[int] | None DEFAULT: None

RETURNS DESCRIPTION
Path

Path to the generated GeoPackage containing the census layer enriched

Path

with administrative information.

Note

The census year is derived from the layer name census_layer_name[6:] (e.g., census20112011). For 2021, the COD_PROV column is manually reconstructed from PRO_COM_T (see repository issue #47). The GeoPackage is saved as {YEAR_GEODATA_NAME}.gpkg and the layer as {YEAR_GEODATA_NAME}{census_year}.

read_administrative_boundaries(file_path, target_columns, index_column, column_remapping=None, output_folder=None, layer_name=None)

Read administrative boundaries and return a DataFrame or GeoPackage.

This function reads an administrative boundary file (typically a shapefile), selects a subset of columns, and sets a column as the index. Depending on the provided parameters, it can:

  • Return a DataFrame without geometry, sorted and indexed; or
  • Save the data as a layer in a GeoPackage, preserving the geometry.

The encoding is derived from the .dbf file associated with the shapefile to avoid issues with accented characters or special symbols.

PARAMETER DESCRIPTION
file_path

Path to the vector file (e.g., shapefile) containing administrative boundaries.

TYPE: Path

target_columns

List of columns to select from the source dataset. The geometry column is added automatically.

TYPE: list

index_column

Name of the column to use as the DataFrame index (e.g., ISTAT code).

TYPE: str

column_remapping

Optional dictionary to rename columns (e.g., {"DEN_REG": "REGIONE"}). If None, original names are kept.

TYPE: dict | None DEFAULT: None

output_folder

Optional output folder where the GeoPackage will be saved. If None, the function returns a DataFrame (without geometry) instead of writing to disk.

TYPE: Path | None DEFAULT: None

layer_name

Optional name of the layer to use within the GeoPackage. Must be specified if output_folder is provided, to properly distinguish layers.

TYPE: str | None DEFAULT: None

RETURNS DESCRIPTION
DataFrame | Path

Either an indexed and sorted DataFrame without geometry column if

DataFrame | Path

output_folder is None, or the path to the created GeoPackage if

DataFrame | Path

output_folder is provided.

Note

The geometry column is automatically added to target_columns via the GEOMETRY_COLUMN_NAME constant. The GeoPackage is saved with a name based on the YEAR_GEODATA_NAME constant and contains the layer specified by layer_name.

read_census(shp_folder, target_columns, tipo_loc_mapping, column_remapping=None, output_folder=None, layer_name=None)

Read census data from shapefiles and return a GeoDataFrame or GeoPackage.

This function recursively searches for all shapefiles in a folder, reads their data, selects a subset of columns, corrects invalid geometries, adds the locality type description (derived from tipo_loc_mapping), and builds a unified GeoDataFrame with all census sections.

Depending on the parameters, it can:

  • Return the resulting GeoDataFrame directly; or
  • Save the data as a layer in a GeoPackage (YEAR_GEODATA_NAME.gpkg) and return the path to the created file.
PARAMETER DESCRIPTION
shp_folder

Path to the folder containing census shapefiles (recursive reading via rglob("*.shp")).

TYPE: Path

target_columns

List of columns to select from each shapefile (must include or be compatible with the geometry column).

TYPE: list

tipo_loc_mapping

Mapping of locality codes for the TIPO_LOC field (e.g., {1: "Centro abitato", 2: "Nucleo", ...}), used to create the descriptive column DEN_LOC.

TYPE: dict

column_remapping

Optional dictionary to rename selected columns (e.g., {"PRO_COM": "PRO_COMUNE"}). If None, original names are kept.

TYPE: dict | None DEFAULT: None

output_folder

Optional folder where the resulting GeoPackage will be saved. If None, the function does not write to disk and returns the GeoDataFrame directly.

TYPE: Path | None DEFAULT: None

layer_name

Optional name of the layer to use within the GeoPackage. Must be specified if output_folder is provided.

TYPE: str | None DEFAULT: None

RETURNS DESCRIPTION
GeoDataFrame | Path

Either a GeoDataFrame with census data and corrected geometries if

GeoDataFrame | Path

output_folder is None, or the path to the created GeoPackage if

GeoDataFrame | Path

output_folder is provided.

RAISES DESCRIPTION
ValueError

If no shapefile is found in the specified folder.

Note

Geometries are validated with make_valid() to reduce issues caused by invalid polygons. An area_mq column containing the area in square meters is calculated. The GeoDataFrame index is set to the first column in df_columns (typically the census section code).

H3 area-weighted estimation for ISTAT census section indicators.

estimate_h3_census_indexes(census_data_path, year, aoi, h3_resolution=REQUIRED_H3_RESOLUTION, *, indexes='all_additive', aoi_crs=WGS84_CRS, area_crs=DEFAULT_AREA_CRS, layer_name=None, municipality_codes=None, special_section_policy=DEFAULT_SPECIAL_SECTION_POLICY, boundary_ring_size=DEFAULT_BOUNDARY_RING_SIZE, include_density=True, clip_output=False, output_crs=WGS84_CRS, output_path=None, output_layer=None, conservation_tolerance=1e-06, workers=DEFAULT_H3_WORKERS, chunk_size=DEFAULT_H3_CHUNK_SIZE, parallel_backend=DEFAULT_PARALLEL_BACKEND, intermediate_storage=DEFAULT_INTERMEDIATE_STORAGE, intermediate_dir=None, keep_intermediates=False, reuse_intermediates=False, max_in_flight_chunks=None, stream_output=False, h3_grid=None)

Estimate additive census indicators on an H3 grid.

Values are distributed from source census sections to H3 cells using uniform density inside each source section:

contribution = source_value * intersection_area / source_cell_area
PARAMETER DESCRIPTION
census_data_path

Path to the finalized census_data.gpkg file.

TYPE: str | Path

year

Census year to read from layer census<year> unless layer_name is provided.

TYPE: int

aoi

Area of interest as a Shapely geometry, GeoSeries, or GeoDataFrame.

TYPE: GeoInput

h3_resolution

Required H3 resolution. This implementation supports only level 11.

TYPE: int DEFAULT: REQUIRED_H3_RESOLUTION

indexes

Source index codes or canonical catalogue IDs to estimate. The default "all_additive" selects additive source codes present in the layer using the packaged census index catalogue. An empty iterable also selects all available additive indexes.

TYPE: str | Iterable[str] | None DEFAULT: 'all_additive'

aoi_crs

CRS to use when aoi is a plain Shapely geometry or lacks CRS.

TYPE: str | int | None DEFAULT: WGS84_CRS

area_crs

Projected CRS used for area calculations.

TYPE: str | int DEFAULT: DEFAULT_AREA_CRS

layer_name

Optional source layer name. Defaults to census<year>.

TYPE: str | None DEFAULT: None

municipality_codes

Optional municipality codes used to filter source rows through the first available municipality-code column.

TYPE: Iterable[int | str] | None DEFAULT: None

special_section_policy

How to handle special/fictitious sections. The default "exclude" removes them before estimation. Use "include" to keep and flag them, or "raise" to fail if any intersects the AOI.

TYPE: str DEFAULT: DEFAULT_SPECIAL_SECTION_POLICY

boundary_ring_size

H3 neighbour rings added around filled cells before final AOI filtering. Defaults to 3 to avoid missing boundary cells in real administrative AOIs.

TYPE: int DEFAULT: DEFAULT_BOUNDARY_RING_SIZE

include_density

If True, add <index>_density_per_sq_km columns based on the H3/AOI intersection area.

TYPE: bool DEFAULT: True

clip_output

If True, output geometries are clipped to the AOI. Otherwise full H3 cell geometries are returned.

TYPE: bool DEFAULT: False

output_crs

CRS for returned geometries. Defaults to EPSG:4326.

TYPE: str | int DEFAULT: WGS84_CRS

output_path

Optional GeoPackage path to write.

TYPE: str | Path | None DEFAULT: None

output_layer

Optional output layer name. Defaults to h3_census<year>_r<h3_resolution>.

TYPE: str | None DEFAULT: None

conservation_tolerance

Relative tolerance stored in validation metadata.

TYPE: float DEFAULT: 1e-06

workers

Number of parallel workers used for H3-cell chunks. The default 1 uses the serial implementation.

TYPE: int DEFAULT: DEFAULT_H3_WORKERS

chunk_size

Maximum number of H3 cells in each parallel chunk. In the default Parquet mode this also bounds H3 overlay grid preparation.

TYPE: int DEFAULT: DEFAULT_H3_CHUNK_SIZE

parallel_backend

Standard-library executor backend for workers > 1. Use "thread" to avoid copying GeoDataFrames between processes, "process" for process-based execution when serialization overhead is acceptable, or "dask" after installing the optional Dask extra.

TYPE: str DEFAULT: DEFAULT_PARALLEL_BACKEND

intermediate_storage

Intermediate execution mode. Use "parquet" to prepare the H3 overlay grid in bounded chunks, store prepared GeoParquet inputs, and write Parquet chunk outputs on disk. Use "memory" for the legacy in-memory path. Defaults to "parquet".

TYPE: str DEFAULT: DEFAULT_INTERMEDIATE_STORAGE

intermediate_dir

Optional directory used for H3 intermediate files. When omitted, a temporary directory is created automatically.

TYPE: str | Path | None DEFAULT: None

keep_intermediates

If True, keep generated intermediate files after the run. Temporary files are removed by default.

TYPE: bool DEFAULT: False

reuse_intermediates

If True, reuse matching chunk result files in intermediate_dir when they already exist.

TYPE: bool DEFAULT: False

max_in_flight_chunks

Maximum number of chunks submitted or computed at once. Defaults to the active worker count, which bounds queue memory for thread, process, and Dask execution. Increase only after benchmarking if scheduling overhead dominates memory pressure.

TYPE: int | None DEFAULT: None

stream_output

If True, require Parquet intermediate storage and output_path, then stream finalized result chunks directly to the GeoPackage instead of materializing the full output GeoDataFrame. The returned GeoDataFrame is metadata-only; its attrs contain row_count, validation tables, and output information.

TYPE: bool DEFAULT: False

h3_grid

Optional precomputed H3 grid returned by generate_h3_grid() for the same AOI, H3 resolution, boundary_ring_size, area_crs, and internal grid CRS. When supplied, the estimator validates the stored grid fingerprint before reusing it.

TYPE: GeoDataFrame | None DEFAULT: None

RETURNS DESCRIPTION
GeoDataFrame

GeoDataFrame with one row per H3 cell, integer estimated index columns,

GeoDataFrame

density columns when requested, and coverage metadata. When

GeoDataFrame

stream_output=True, returns a metadata-only GeoDataFrame after writing

GeoDataFrame

the GeoPackage layer. The attrs dictionary contains continuous

GeoDataFrame

source_totals, h3_totals, and total_validation, plus

GeoDataFrame

integer_total_validation for the final integer output columns.

RAISES DESCRIPTION
FileNotFoundError

If census_data_path does not exist.

ValueError

If CRS, AOI, requested indexes, parallel options, or source geometry are invalid.

finalize_h3_result_chunks_to_geopackage(intermediate_workspace, output_path, *, output_layer=None, conservation_tolerance=1e-06, index_batch_size=H3_CHUNK_FINALIZATION_INDEX_BATCH_SIZE)

Finalize retained H3 result chunks into a GeoPackage without full concatenation.

This function is intended for retained Parquet/GeoParquet workspaces created by estimate_h3_census_indexes(..., keep_intermediates=True). It streams the result_chunks/ files to the target GeoPackage, rebuilding the same validation and integer additive totals that the in-memory finalization path produces.

PARAMETER DESCRIPTION
intermediate_workspace

Directory containing metadata.json, prepared_source.parquet, and result_chunks/result_chunk_*.parquet.

TYPE: str | Path

output_path

GeoPackage file to create or append to.

TYPE: str | Path

output_layer

GeoPackage layer name. Defaults to h3_census<year>_r<h3_resolution> from the retained metadata.

TYPE: str | None DEFAULT: None

conservation_tolerance

Relative tolerance used for continuous total validation.

TYPE: float DEFAULT: 1e-06

index_batch_size

Number of additive indexes to inspect together while planning integer apportionment. Lower values use less memory.

TYPE: int DEFAULT: H3_CHUNK_FINALIZATION_INDEX_BATCH_SIZE

RETURNS DESCRIPTION
_H3ChunkExportResult

Summary with output path, layer, row count, chunk count, and validation tables.

RAISES DESCRIPTION
FileNotFoundError

If the retained workspace is incomplete.

ValueError

If metadata is invalid, no result chunk exists, or the output layer already exists.

generate_h3_grid(aoi, h3_resolution=REQUIRED_H3_RESOLUTION, *, aoi_crs=WGS84_CRS, area_crs=DEFAULT_AREA_CRS, boundary_ring_size=DEFAULT_BOUNDARY_RING_SIZE, output_crs=WGS84_CRS)

Generate H3 cell polygons intersecting an area of interest.

H3 polygon filling uses cell centres. This function expands the filled cells by neighbour rings and then keeps only cells that intersect the AOI, so boundary cells are retained for area-weighted overlays.

PARAMETER DESCRIPTION
aoi

Area of interest as a Shapely geometry, GeoSeries, or GeoDataFrame.

TYPE: GeoInput

h3_resolution

Required H3 resolution. This implementation supports only level 11.

TYPE: int DEFAULT: REQUIRED_H3_RESOLUTION

aoi_crs

CRS to use when aoi is a plain Shapely geometry or when a GeoSeries/GeoDataFrame has no CRS. Defaults to EPSG:4326.

TYPE: str | int | None DEFAULT: WGS84_CRS

area_crs

Projected CRS used to calculate h3_cell_area_sqm.

TYPE: str | int DEFAULT: DEFAULT_AREA_CRS

boundary_ring_size

Number of H3 neighbour rings added around filled cells before final AOI intersection filtering. Defaults to 3 to retain boundary cells reliably for real administrative AOIs.

TYPE: int DEFAULT: DEFAULT_BOUNDARY_RING_SIZE

output_crs

CRS for returned cell geometries. Defaults to EPSG:4326.

TYPE: str | int DEFAULT: WGS84_CRS

RETURNS DESCRIPTION
GeoDataFrame

GeoDataFrame with h3_index, h3_resolution, h3_cell_area_sqm, and

GeoDataFrame

polygon geometries. The attrs dictionary contains h3_grid_metadata

GeoDataFrame

and h3_grid_fingerprint for safe same-AOI reuse.

RAISES DESCRIPTION
TypeError

If the AOI input type is unsupported.

ValueError

If the AOI is empty, CRS is missing, or the resolution is invalid.