5.1. Create model#
In this example, we show how to run a complete Tradesman model for Nauru, an insular country in Oceania.
Imports
[1]:
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
[2]:
folder = join(gettempdir(), uuid4().hex)
Let’s initialize our model
[3]:
model = Tradesman(network_path=folder, model_place="Nauru")
No pre-existing parameter file exists for this project. Will use default
No pre-existing parameter file exists for this project. Will use default
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
[4]:
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).
[5]:
model.import_network()
Later we import population data into our model. We use WorldPop as our source, but you can also try Meta.
[6]:
model.import_population()
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.
[7]:
model.build_zoning(min_zone_pop=100, max_zone_pop=500)
Expect 868 total hexbins for this bounding box
100%|██████████| 31/31 [00:00<00:00, 1175.13it/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.12.11/x64/lib/python3.12/site-packages/geopandas/array.py:408: 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/zones_with_pop.py:21: FutureWarning: A value is trying to be set on a copy of a DataFrame or Series through chained assignment using an inplace method.
The behavior will change in pandas 3.0. This inplace method will never work because the intermediate object on which we are setting values always behaves as a copy.
For example, when doing 'df[col].method(value, inplace=True)', try using 'df.method({col: value}, inplace=True)' or df[col] = df[col].method(value) instead, to perform the operation inplace on the original object.
pop_to_zone.population.fillna(0, inplace=True)
/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
14it [00:00, 151.93it/s]
/home/runner/work/tradesman/tradesman/tradesman/model_creation/zoning/create_clusters.py:95: FutureWarning: `use_index` defaults to False but will default to True in future. Set True/False directly to control this behavior and silence this warning
adj_mtx = libpysal.weights.Queen.from_dataframe(zone_df)
/opt/hostedtoolcache/Python/3.12.11/x64/lib/python3.12/site-packages/libpysal/weights/contiguity.py:347: UserWarning: The weights matrix is not fully connected:
There are 2 disconnected components.
W.__init__(self, neighbors, ids=ids, **kw)
/opt/hostedtoolcache/Python/3.12.11/x64/lib/python3.12/site-packages/geopandas/geodataframe.py:1896: UserWarning: Boolean Series key will be reindexed to match DataFrame index.
result = super().__getitem__(key)
/home/runner/work/tradesman/tradesman/tradesman/model_creation/zoning/create_clusters.py:95: FutureWarning: `use_index` defaults to False but will default to True in future. Set True/False directly to control this behavior and silence this warning
adj_mtx = libpysal.weights.Queen.from_dataframe(zone_df)
/opt/hostedtoolcache/Python/3.12.11/x64/lib/python3.12/site-packages/libpysal/weights/contiguity.py:347: UserWarning: The weights matrix is not fully connected:
There are 3 disconnected components.
There is 1 island with id: 28.
W.__init__(self, neighbors, ids=ids, **kw)
/opt/hostedtoolcache/Python/3.12.11/x64/lib/python3.12/site-packages/geopandas/geodataframe.py:1896: UserWarning: Boolean Series key will be reindexed to match DataFrame index.
result = super().__getitem__(key)
/opt/hostedtoolcache/Python/3.12.11/x64/lib/python3.12/site-packages/geopandas/geodataframe.py:1896: UserWarning: Boolean Series key will be reindexed to match DataFrame index.
result = super().__getitem__(key)
/home/runner/work/tradesman/tradesman/tradesman/model_creation/zoning/create_clusters.py:95: FutureWarning: `use_index` defaults to False but will default to True in future. Set True/False directly to control this behavior and silence this warning
adj_mtx = libpysal.weights.Queen.from_dataframe(zone_df)
/opt/hostedtoolcache/Python/3.12.11/x64/lib/python3.12/site-packages/libpysal/weights/contiguity.py:347: UserWarning: The weights matrix is not fully connected:
There are 2 disconnected components.
W.__init__(self, neighbors, ids=ids, **kw)
/opt/hostedtoolcache/Python/3.12.11/x64/lib/python3.12/site-packages/geopandas/geodataframe.py:1896: UserWarning: Boolean Series key will be reindexed to match DataFrame index.
result = super().__getitem__(key)
/home/runner/work/tradesman/tradesman/tradesman/model_creation/zoning/create_clusters.py:95: FutureWarning: `use_index` defaults to False but will default to True in future. Set True/False directly to control this behavior and silence this warning
adj_mtx = libpysal.weights.Queen.from_dataframe(zone_df)
/opt/hostedtoolcache/Python/3.12.11/x64/lib/python3.12/site-packages/libpysal/weights/contiguity.py:347: UserWarning: The weights matrix is not fully connected:
There are 2 disconnected components.
W.__init__(self, neighbors, ids=ids, **kw)
/opt/hostedtoolcache/Python/3.12.11/x64/lib/python3.12/site-packages/geopandas/geodataframe.py:1896: UserWarning: Boolean Series key will be reindexed to match DataFrame index.
result = super().__getitem__(key)
Done 0/14 states
Let’s import more population data to our model! Now we’ll gather information about total inhabitants by sex and age.
[8]:
model.import_pop_by_sex_and_age()
We can also import amenity and building information from OSM.
[9]:
model.import_amenities()
model.import_buildings(False)
/home/runner/work/tradesman/tradesman/tradesman/data_retrieval/osm_tags/import_osm_data.py:75: FutureWarning: A value is trying to be set on a copy of a DataFrame or Series through chained assignment using an inplace method.
The behavior will change in pandas 3.0. This inplace method will never work because the intermediate object on which we are setting values always behaves as a copy.
For example, when doing 'df[col].method(value, inplace=True)', try using 'df.method({col: value}, inplace=True)' or df[col] = df[col].method(value) instead, to perform the operation inplace on the original object.
df.update_tags.fillna("undetermined", inplace=True)
/home/runner/work/tradesman/tradesman/tradesman/data_retrieval/osm_tags/import_osm_data.py:75: FutureWarning: A value is trying to be set on a copy of a DataFrame or Series through chained assignment using an inplace method.
The behavior will change in pandas 3.0. This inplace method will never work because the intermediate object on which we are setting values always behaves as a copy.
For example, when doing 'df[col].method(value, inplace=True)', try using 'df.method({col: value}, inplace=True)' or df[col] = df[col].method(value) instead, to perform the operation inplace on the original object.
df.update_tags.fillna("undetermined", inplace=True)
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.
[10]:
# model.build_population_synthesizer_data(sample_size=0.02)
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.
[11]:
# model.synthesize_population(thread_number=1)