5.1. Create model#

In this example, we show how to run a complete Tradesman model for Nauru, an insular country in Oceania.

Imports

from tradesman.model import Tradesman
from tempfile import gettempdir
from uuid import uuid4
from os.path import join

We create a temporary folder to store our data

folder = join(gettempdir(), uuid4().hex)

Let’s initialize our model

model = Tradesman(network_path=folder, model_place="Nauru")

If we want to run a model with Tradesman default configurations, we can go for model.create() and wait for it. But we can customize the model we want to create. So let’s check out how to change some of the configurations.

First step is to add the model area and other geographical subdivisions to our model

model.import_model_area()
model.add_country_borders()
model.import_subdivisions()

We can now import the network to our model. We’ll download our network from OpenStreetMaps (OSM).

model.import_network()

Later we import population data into our model. We use WorldPop as our source, but you can also try Meta.

model.import_population()
pop_Nauru.tif: 0.00B [00:00, ?B/s]
pop_Nauru.tif:  62%|######2   | 8.00k/12.9k [00:00<00:00, 17.9kB/s]
pop_Nauru.tif: 100%|##########| 16.0k/16.0k [00:00<00:00, 35.7kB/s]

Now that we have network and population information, we can build our Traffic Analysis Zones (TAZs). Nauru has a small population, so we will set our zones to range between 100 and 500 inhabitants.

model.build_zoning(min_zone_pop=100, max_zone_pop=500)
Expect 868 total hexbins for this bounding box

  0%|          | 0/31 [00:00<?, ?it/s]
100%|##########| 31/31 [00:00<00:00, 1345.51it/s]
/home/runner/work/tradesman/tradesman/tradesman/model_creation/zoning/zones_with_location.py:23: UserWarning: Geometry is in a geographic CRS. Results from 'centroid' are likely incorrect. Use 'GeoSeries.to_crs()' to re-project geometries to a projected CRS before this operation.

  centroids = gpd.GeoDataFrame(hexb[["hex_id"]], geometry=hexb.centroid, crs="EPSG:4326")
/opt/hostedtoolcache/Python/3.9.16/x64/lib/python3.9/site-packages/geopandas/array.py:364: UserWarning: Geometry is in a geographic CRS. Results from 'sjoin_nearest' are likely incorrect. Use 'GeoSeries.to_crs()' to re-project geometries to a projected CRS before this operation.

  warnings.warn(
/home/runner/work/tradesman/tradesman/tradesman/model_creation/zoning/create_clusters.py:33: UserWarning: Geometry is in a geographic CRS. Results from 'centroid' are likely incorrect. Use 'GeoSeries.to_crs()' to re-project geometries to a projected CRS before this operation.

  centroids = hexbins.geometry.centroid

0it [00:00, ?it/s]Done 0/14 states

3it [00:00, 25.03it/s]
14it [00:00, 70.36it/s]
/opt/hostedtoolcache/Python/3.9.16/x64/lib/python3.9/site-packages/libpysal/weights/weights.py:172: UserWarning: The weights matrix is not fully connected:
 There are 2 disconnected components.
  warnings.warn(message)
/opt/hostedtoolcache/Python/3.9.16/x64/lib/python3.9/site-packages/geopandas/geodataframe.py:1475: UserWarning: Boolean Series key will be reindexed to match DataFrame index.
  result = super().__getitem__(key)
/opt/hostedtoolcache/Python/3.9.16/x64/lib/python3.9/site-packages/libpysal/weights/weights.py:172: UserWarning: The weights matrix is not fully connected:
 There are 2 disconnected components.
 There is 1 island with id: 39.
  warnings.warn(message)
/opt/hostedtoolcache/Python/3.9.16/x64/lib/python3.9/site-packages/geopandas/geodataframe.py:1475: UserWarning: Boolean Series key will be reindexed to match DataFrame index.
  result = super().__getitem__(key)
/opt/hostedtoolcache/Python/3.9.16/x64/lib/python3.9/site-packages/libpysal/weights/weights.py:172: UserWarning: The weights matrix is not fully connected:
 There are 2 disconnected components.
  warnings.warn(message)
/opt/hostedtoolcache/Python/3.9.16/x64/lib/python3.9/site-packages/geopandas/geodataframe.py:1475: UserWarning: Boolean Series key will be reindexed to match DataFrame index.
  result = super().__getitem__(key)

Let’s import more population data to our model! Now we’ll gather information about total inhabitants by sex and age.

model.import_pop_by_sex_and_age()
NRU_POPF1.tif: 0.00B [00:00, ?B/s]
NRU_POPF1.tif:  52%|#####2    | 8.00k/15.4k [00:00<00:00, 30.9kB/s]
NRU_POPF1.tif: 100%|##########| 16.0k/16.0k [00:00<00:00, 61.7kB/s]

NRU_POPF2.tif: 0.00B [00:00, ?B/s]
NRU_POPF2.tif:  52%|#####2    | 8.00k/15.3k [00:00<00:00, 31.2kB/s]
NRU_POPF2.tif: 100%|##########| 16.0k/16.0k [00:00<00:00, 62.2kB/s]

NRU_POPF3.tif: 0.00B [00:00, ?B/s]
NRU_POPF3.tif:  52%|#####2    | 8.00k/15.4k [00:00<00:00, 30.9kB/s]
NRU_POPF3.tif: 100%|##########| 16.0k/16.0k [00:00<00:00, 61.7kB/s]

NRU_POPF4.tif: 0.00B [00:00, ?B/s]
NRU_POPF4.tif:  52%|#####2    | 8.00k/15.4k [00:00<00:00, 31.1kB/s]
NRU_POPF4.tif: 100%|##########| 16.0k/16.0k [00:00<00:00, 62.2kB/s]

NRU_POPF5.tif: 0.00B [00:00, ?B/s]
NRU_POPF5.tif:  52%|#####2    | 8.00k/15.4k [00:00<00:00, 31.1kB/s]
NRU_POPF5.tif: 100%|##########| 16.0k/16.0k [00:00<00:00, 62.0kB/s]

NRU_POPF6.tif: 0.00B [00:00, ?B/s]
NRU_POPF6.tif:  52%|#####1    | 8.00k/15.4k [00:00<00:00, 29.3kB/s]
NRU_POPF6.tif: 100%|##########| 16.0k/16.0k [00:00<00:00, 58.5kB/s]

NRU_POPF7.tif: 0.00B [00:00, ?B/s]
NRU_POPF7.tif:  52%|#####2    | 8.00k/15.3k [00:00<00:00, 31.2kB/s]
NRU_POPF7.tif: 100%|##########| 16.0k/16.0k [00:00<00:00, 62.3kB/s]

NRU_POPF8.tif: 0.00B [00:00, ?B/s]
NRU_POPF8.tif:  52%|#####2    | 8.00k/15.3k [00:00<00:00, 31.1kB/s]
NRU_POPF8.tif: 100%|##########| 16.0k/16.0k [00:00<00:00, 62.1kB/s]

NRU_POPF9.tif: 0.00B [00:00, ?B/s]
NRU_POPF9.tif:  52%|#####1    | 8.00k/15.4k [00:00<00:00, 31.2kB/s]
NRU_POPF9.tif: 100%|##########| 16.0k/16.0k [00:00<00:00, 62.2kB/s]

NRU_POPF10.tif: 0.00B [00:00, ?B/s]
NRU_POPF10.tif:  52%|#####1    | 8.00k/15.4k [00:00<00:00, 31.0kB/s]
NRU_POPF10.tif: 100%|##########| 16.0k/16.0k [00:00<00:00, 62.0kB/s]

NRU_POPF11.tif: 0.00B [00:00, ?B/s]
NRU_POPF11.tif:  52%|#####1    | 8.00k/15.4k [00:00<00:00, 31.1kB/s]
NRU_POPF11.tif: 100%|##########| 16.0k/16.0k [00:00<00:00, 62.1kB/s]

NRU_POPF12.tif: 0.00B [00:00, ?B/s]
NRU_POPF12.tif:  52%|#####2    | 8.00k/15.4k [00:00<00:00, 30.6kB/s]
NRU_POPF12.tif: 100%|##########| 16.0k/16.0k [00:00<00:00, 61.2kB/s]

NRU_POPF13.tif: 0.00B [00:00, ?B/s]
NRU_POPF13.tif:  52%|#####2    | 8.00k/15.3k [00:00<00:00, 30.9kB/s]
NRU_POPF13.tif: 100%|##########| 16.0k/16.0k [00:00<00:00, 61.7kB/s]

NRU_POPF14.tif: 0.00B [00:00, ?B/s]
NRU_POPF14.tif:  52%|#####1    | 8.00k/15.4k [00:00<00:00, 31.0kB/s]
NRU_POPF14.tif: 100%|##########| 16.0k/16.0k [00:00<00:00, 62.0kB/s]

NRU_POPF15.tif: 0.00B [00:00, ?B/s]
NRU_POPF15.tif:  52%|#####2    | 8.00k/15.4k [00:00<00:00, 31.1kB/s]
NRU_POPF15.tif: 100%|##########| 16.0k/16.0k [00:00<00:00, 62.1kB/s]

NRU_POPF16.tif: 0.00B [00:00, ?B/s]
NRU_POPF16.tif:  52%|#####2    | 8.00k/15.4k [00:00<00:00, 29.2kB/s]
NRU_POPF16.tif: 100%|##########| 16.0k/16.0k [00:00<00:00, 58.4kB/s]

NRU_POPF17.tif: 0.00B [00:00, ?B/s]
NRU_POPF17.tif:  52%|#####2    | 8.00k/15.3k [00:00<00:00, 31.0kB/s]
NRU_POPF17.tif: 100%|##########| 16.0k/16.0k [00:00<00:00, 61.9kB/s]

NRU_POPF18.tif: 0.00B [00:00, ?B/s]
NRU_POPF18.tif:  52%|#####2    | 8.00k/15.4k [00:00<00:00, 29.2kB/s]
NRU_POPF18.tif: 100%|##########| 16.0k/16.0k [00:00<00:00, 58.2kB/s]

NRU_POPM1.tif: 0.00B [00:00, ?B/s]
NRU_POPM1.tif:  52%|#####1    | 8.00k/15.4k [00:00<00:00, 30.9kB/s]
NRU_POPM1.tif: 100%|##########| 16.0k/16.0k [00:00<00:00, 61.7kB/s]

NRU_POPM2.tif: 0.00B [00:00, ?B/s]
NRU_POPM2.tif:  52%|#####1    | 8.00k/15.4k [00:00<00:00, 31.2kB/s]
NRU_POPM2.tif: 100%|##########| 16.0k/16.0k [00:00<00:00, 62.2kB/s]

NRU_POPM3.tif: 0.00B [00:00, ?B/s]
NRU_POPM3.tif:  52%|#####2    | 8.00k/15.3k [00:00<00:00, 30.7kB/s]
NRU_POPM3.tif: 100%|##########| 16.0k/16.0k [00:00<00:00, 61.2kB/s]

NRU_POPM4.tif: 0.00B [00:00, ?B/s]
NRU_POPM4.tif:  52%|#####2    | 8.00k/15.4k [00:00<00:00, 31.0kB/s]
NRU_POPM4.tif: 100%|##########| 16.0k/16.0k [00:00<00:00, 62.0kB/s]

NRU_POPM5.tif: 0.00B [00:00, ?B/s]
NRU_POPM5.tif:  52%|#####1    | 8.00k/15.4k [00:00<00:00, 31.1kB/s]
NRU_POPM5.tif: 100%|##########| 16.0k/16.0k [00:00<00:00, 62.1kB/s]

NRU_POPM6.tif: 0.00B [00:00, ?B/s]
NRU_POPM6.tif:  52%|#####1    | 8.00k/15.4k [00:00<00:00, 31.1kB/s]
NRU_POPM6.tif: 100%|##########| 16.0k/16.0k [00:00<00:00, 62.1kB/s]

NRU_POPM7.tif: 0.00B [00:00, ?B/s]
NRU_POPM7.tif:  52%|#####2    | 8.00k/15.4k [00:00<00:00, 30.9kB/s]
NRU_POPM7.tif: 100%|##########| 16.0k/16.0k [00:00<00:00, 61.7kB/s]

NRU_POPM8.tif: 0.00B [00:00, ?B/s]
NRU_POPM8.tif:  52%|#####2    | 8.00k/15.4k [00:00<00:00, 30.8kB/s]
NRU_POPM8.tif: 100%|##########| 16.0k/16.0k [00:00<00:00, 61.4kB/s]

NRU_POPM9.tif: 0.00B [00:00, ?B/s]
NRU_POPM9.tif:  52%|#####2    | 8.00k/15.4k [00:00<00:00, 30.7kB/s]
NRU_POPM9.tif: 100%|##########| 16.0k/16.0k [00:00<00:00, 61.3kB/s]

NRU_POPM10.tif: 0.00B [00:00, ?B/s]
NRU_POPM10.tif:  52%|#####1    | 8.00k/15.4k [00:00<00:00, 31.2kB/s]
NRU_POPM10.tif: 100%|##########| 16.0k/16.0k [00:00<00:00, 62.2kB/s]

NRU_POPM11.tif: 0.00B [00:00, ?B/s]
NRU_POPM11.tif:  52%|#####2    | 8.00k/15.4k [00:00<00:00, 30.6kB/s]
NRU_POPM11.tif: 100%|##########| 16.0k/16.0k [00:00<00:00, 61.1kB/s]

NRU_POPM12.tif: 0.00B [00:00, ?B/s]
NRU_POPM12.tif:  52%|#####2    | 8.00k/15.4k [00:00<00:00, 30.1kB/s]
NRU_POPM12.tif: 100%|##########| 16.0k/16.0k [00:00<00:00, 60.2kB/s]

NRU_POPM13.tif: 0.00B [00:00, ?B/s]
NRU_POPM13.tif:  52%|#####1    | 8.00k/15.4k [00:00<00:00, 31.1kB/s]
NRU_POPM13.tif: 100%|##########| 16.0k/16.0k [00:00<00:00, 62.1kB/s]

NRU_POPM14.tif: 0.00B [00:00, ?B/s]
NRU_POPM14.tif:  52%|#####1    | 8.00k/15.4k [00:00<00:00, 28.7kB/s]
NRU_POPM14.tif: 100%|##########| 16.0k/16.0k [00:00<00:00, 57.3kB/s]

NRU_POPM15.tif: 0.00B [00:00, ?B/s]
NRU_POPM15.tif:  52%|#####2    | 8.00k/15.4k [00:00<00:00, 31.2kB/s]
NRU_POPM15.tif: 100%|##########| 16.0k/16.0k [00:00<00:00, 62.2kB/s]

NRU_POPM16.tif: 0.00B [00:00, ?B/s]
NRU_POPM16.tif:  52%|#####2    | 8.00k/15.4k [00:00<00:00, 29.6kB/s]
NRU_POPM16.tif: 100%|##########| 16.0k/16.0k [00:00<00:00, 59.0kB/s]

NRU_POPM17.tif: 0.00B [00:00, ?B/s]
NRU_POPM17.tif:  52%|#####2    | 8.00k/15.4k [00:00<00:00, 31.1kB/s]
NRU_POPM17.tif: 100%|##########| 16.0k/16.0k [00:00<00:00, 62.0kB/s]

NRU_POPM18.tif: 0.00B [00:00, ?B/s]
NRU_POPM18.tif:  52%|#####2    | 8.00k/15.3k [00:00<00:00, 31.1kB/s]
NRU_POPM18.tif: 100%|##########| 16.0k/16.0k [00:00<00:00, 62.1kB/s]

We can also import amenity and building information from OSM.

model.import_amenities()
model.import_buildings(False)

With Tradesman, we can also create a synthetic population for our model. First, we build our seed sample. At the end of this step, it is possible to see the overall characteristics of our population sample.

model.build_population_synthesizer_data(sample_size=0.02)
Calculated vs Expected percentage of households per size in the sample

# Person      Calculated    Expected
----------  ------------  ----------
1 person           27.54       22.84
2-3 person         43.48       50.52
4-5 person         23.19       22.09
6+ person           5.8         4.55

Difference in calculated vs expected percentage of households in the sample

# Person      Diff.
----------  -------
1 person       4.7
2-3 person    -7.04
4-5 person     1.1
6+ person      1.25

Than we synthesize our data. As our population is not that large, we don’t need to set multiple threads to run the synthesizer. But as the size of the population increases, it is worth using multiple threads to reduce the processing time. At the end of the process, we will receive two outputs related to the validation of our synthetic population.

model.synthesize_population(thread_number=1)
/home/runner/work/tradesman/tradesman/tradesman/model_creation/synthetic_population/create_synthetic_population.py:108: UserWarning: Synthetic population was not generated. Please increase your sample size or change the number of threads.
  warnings.warn(

Total running time of the script: ( 5 minutes 50.963 seconds)

Gallery generated by Sphinx-Gallery