We applied the propagation simulation from the paper A Comparison of Geographical Propagation Visualizations (https://dl.acm.org/doi/10.1145/3313831.3376350) to the administrative regions of Germany used in Visual Boosting Techniques for Spatiotemporal Dense Pixel Visualizations (https://arxiv.org/abs/2604.25298). The original code can be found at: https://ilda.saclay.inria.fr/propagvis/
Uniform-per-region version, current preferred one:
python datasets_generation/generate_germany_nuts3_propagation_uniform_regions.py
python datasets_generation/plot_germany_small_multiples.pyPopulation-proportional version:
python datasets_generation/generate_germany_nuts3_propagation_population_scaled.py
python datasets_generation/plot_germany_small_multiples.pyImportant: both variants write to the same output folders and filenames: visualizations_and_datasets/datasets/locations/ visualizations_and_datasets/datasets/propagation/ visualizations_and_datasets/intro/german_*.png So if you want to keep both generated outputs, run one variant, copy/rename its output folder, then run the other. The outputs currently generated here are from uniform_regions: 400 regions, exactly 30 synthetic inhabitants per region.
![]() Direction |
![]() Global |
![]() Hop |
![]() Local |
![]() Peak Fast |
|
The Visual Boosting paper uses COVID-19 incidence data over German districts. These districts correspond to Germany's Kreis-level administrative units: Landkreise and kreisfreie Stadte / urban districts. This is also approximately the NUTS-3 level for Germany.
The useful part for this project is that this level has about 400 spatial regions, which is much higher than the propagation visualization datasets currently bundled here:
- Ica: 43 regions
- Biobio: 51 regions
- Zacatecas: 56 regions
- German districts: about 400 regions
That still is not the same as a dense 128x128 scalar field, but it is a much better starting point for region-level experiments.
Reuse the propagation visualization simulator, but replace the original Ica/Biobio/Zacatecas maps with German district polygons.
The expected output would be a synthetic propagation dataset with one infection value per German district per timestep.
You need a German district boundary file, preferably as GeoJSON.
The file should contain one feature per district and include:
- district geometry as
PolygonorMultiPolygon - a stable district ID, preferably AGS / Landkreis ID
- district name
- area field, or enough geometry information to compute area
- optional population field
Good candidate data sources:
- BKG / GeoBasis-DE administrative boundaries, especially VG5000 or NUTS datasets
- RKI / Destatis COVID-19 datasets for matching district IDs and population/incidence data
Use the district level:
Landkreise + kreisfreie Stadte
In German administrative hierarchy this is the Kreise level. In many statistical datasets it maps to NUTS-3.
Avoid using:
- Bundeslander: too coarse, only 16 regions
- Regierungsbezirke: too coarse and incomplete as a standard reporting level
- Gemeinden: much higher resolution, but probably too expensive for the current simulator
Place the German district GeoJSON somewhere under the propagation data folder, for example:
propagation_data/datasets_generation/data/germany_districts.geojson
or:
propagation_data/visualizations_and_datasets/datasets/locations/germany_districts.geojson
The propagation code expects fields like:
- geometry
- population or area
- centroid coordinates
The existing code in:
propagation_data/datasets_generation/lib/location.py
uses either:
population = int(row['POPULATION'] / 1000)or, with equal_density=True:
population = int(row[area_name] * density)For German districts, the easiest first pass is probably:
location = Location(
'germany_districts.geojson',
'<area_field>',
equal_density=True,
density=<chosen_density>,
plot=True
)If the GeoJSON includes population, a better version is to adapt n_habitants_subloc so it reads the German population field and scales it down.
Each district becomes a sublocation. The simulator randomly places synthetic inhabitants inside each district polygon.
With roughly 400 districts, the density should be tuned carefully. If density is too high, the graph and SIR simulation may become expensive.
Useful target sizes for first tests:
- small: 5,000 inhabitants
- medium: 10,000 inhabitants
- large: 25,000+ inhabitants
The existing simulator uses NetworkX's geographical threshold graph:
nx.geographical_threshold_graph(...)This connects inhabitants based on spatial proximity. You will probably need to retune the threshold parameter in setup_default_network, because Germany's coordinate scale and district extents will differ from the existing maps.
Start with a sparse graph. If infection does not spread far enough, increase:
- graph threshold
- infection probability
- number of seed regions
- ratio of seeded inhabitants
Use create_seeds_config to select initial infected districts:
location.create_seeds_config([district_index], ratio=0.2, plot=False)For more controlled experiments, choose:
- one seed district for local spread
- several seed districts for multi-origin propagation
- border/non-adjacent districts for jump patterns
Use:
sim = PropagationSimulator(location)
sim.set_params(p_infect, p_remove, p_infected)
sim.run()Typical values from the existing notebooks include:
sim.set_params(0.3, 0.1, 0.2)
sim.set_params(0.5, 0.1, 0.3)
sim.set_params(0.1, 0.1, 0.3)The simulator writes raw history and processed history files.
The current processed output will still be region-level:
timestep -> district_id -> infected_count
With about 400 districts and 35 timesteps, this gives:
400 * 35 = 14,000 scalar values
This is much better than Ica/Biobio/Zacatecas, but still only 400 spatial samples per timestep.




