city_gen
- class nomad.city_gen.City(dimensions: tuple = (0, 0), manual_streets: bool = False, name: str = 'Garden City', block_side_length: float = 15.0, web_mercator_origin_x: float = -4265699.0, web_mercator_origin_y: float = 4392976.0, rotation_deg: float = 0.0, offset_x: int = 0, offset_y: int = 0)[source]
Bases:
objectClass for representing a city containing buildings, streets, and methods for city management.
- buildings
A dictionary of Building objects with their IDs as keys.
- Type:
dict
- streets
A dictionary of Street objects with their coordinates as keys.
- Type:
dict
- buildings_outline
A polygon representing the combined geometry of all buildings in the city.
- Type:
shapely.geometry.polygon.Polygon
- city_boundary
A polygon representing the boundary of the city.
- Type:
shapely.geometry.polygon.Polygon
- dimensions
A tuple representing the dimensions of the city (width, height).
- Type:
tuple
- street_graph
A dictionary representing the graph of streets with their neighbors.
- Type:
dict
- shortest_paths
A dictionary containing the shortest paths between all pairs of streets.
- Type:
dict
- gravity
A DataFrame containing the gravity values between all pairs of streets.
- Type:
pandas.DataFrame
- add_building(building_type, door, geom=None, blocks=None, gdf_row=None)[source]
Adds a building to the city with the specified type, door location, and geometry.
- Parameters:
building_type (str) – The type of the building (‘home’, ‘workplace’, ‘retail’, ‘park’).
door (tuple) – A tuple representing the (x, y) coordinates of the door of the building.
geom (shapely.geometry.polygon.Polygon, optional) – The geometry of the building (can be a box or MultiPolygon).
blocks (list of tuples, optional) – A list of (x, y) coordinates representing the blocks occupied by the building.
gdf_row (geopandas.GeoDataFrame or pandas.Series, optional) – A single row GeoDataFrame or Series containing building information.
- Raises:
ValueError – If the door is not on an existing street, if the building overlaps with existing buildings, or if the geometry/blocks do not align with the grid.
- add_buildings_from_gdf(buildings_gdf)[source]
Initialize or add multiple buildings from a GeoDataFrame.
- Parameters:
buildings_gdf (geopandas.GeoDataFrame) – A GeoDataFrame containing building information with columns for type, door coordinates, and geometry.
- Raises:
ValueError – If the GeoDataFrame lacks required columns or contains invalid data.
- property buildings_df
- check_adjacent(geom1, geom2, graph=None)[source]
Adjacency on a grid of 1x1 blocks. Returns list[bool].
- compute_gravity(exponent=2.0, callable_only=False, n_chunks=10, use_proxy_hub_distance=True)[source]
Precompute building-to-building gravity from door-to-door distances.
- Parameters:
exponent (float) – The gravity decay exponent (default 2.0)
callable_only (bool) – If True, store callable function instead of dense matrix (default False)
n_chunks (int) – Number of chunks for computing nearby doors in hub mode (default 10)
use_proxy_hub_distance (bool) – If True, use hub-based distance approximation (fast, scales to large cities). If False, compute true graph distances between all door pairs (slow but exact, suitable for small cities with <200 buildings). Default True.
Notes
Hub mode approximates
dist(i, j)as the distance fromdoor_itohub_i, plus the graph distance fromhub_itohub_j, plus the distance fromhub_jtodoor_j. True mode computesshortest_path_length(door_i, door_j)on the street graph.Stores result in self.grav as DataFrame (callable_only=False) or callable (callable_only=True)
Persistence:
Hub mode (use_proxy_hub_distance=True): Gravity infrastructure is saved by save_geopackage() and restored by from_geopackage(load_gravity=True). The city.grav callable works immediately after loading.
True distance mode (use_proxy_hub_distance=False): Not persisted. Must call compute_gravity(…, use_proxy_hub_distance=False) after loading. This is fast for small cities (<200 buildings) where this mode is intended.
- compute_shortest_paths(callable_only=False)[source]
Compute shortest paths between street blocks.
- Parameters:
callable_only (bool, default False) – If False, precompute all-pairs shortest paths (only for small cities) If True, store on-demand callable (placeholder for hub-based routing)
Notes
Callable mode currently uses nx.shortest_path() on demand—this is a PLACEHOLDER. Production use with _sample_step requires hub-based routing for scalability (billions of calls). Current implementation too slow for large-scale trajectory generation.
Stores result in self.shortest_paths as dict or callable
- classmethod from_geodataframes(buildings_gdf, streets_gdf, blocks_gdf=None, edges_df=None, city_boundary=None)[source]
Construct a City from buildings and streets GeoDataFrames.
- from_mercator(data)[source]
Convert Web Mercator coordinates back to city block coordinates using city’s parameters.
- Parameters:
data (pd.DataFrame) – DataFrame with ‘x’, ‘y’ columns in Web Mercator coordinates
- Returns:
DataFrame with ‘x’, ‘y’ columns updated to city block coordinates. If ‘ha’ column exists, it is also scaled back.
- Return type:
pd.DataFrame
- get_block(coordinates)[source]
Returns information about the block at the given coordinates.
- Parameters:
coordinates (tuple) – A tuple representing the (x, y) coordinates of the block.
- Returns:
A dictionary containing the kind of block (‘street’ or ‘building’), the ID of the building if applicable, the type of building if applicable, and the geometry of the block.
- Return type:
dict
- get_building(identifier=None, door_coords=None, any_coords=None)[source]
Retrieve a building by string ID, door coordinates, or any coordinates within the city’s bounds.
Parameters:
- identifierstr, optional
The string ID of the building (e.g., ‘h-x8-y8’).
- door_coordstuple, optional
The (x, y) coordinates of the building’s door.
- any_coordstuple, optional
Any (x, y) coordinates within the city’s bounds to find a building that contains this point.
Returns:
- geopandas.GeoDataFrame or None
A GeoDataFrame with a single row containing building details if found, None otherwise.
- get_building_coordinates()[source]
Get building coordinates as a DataFrame with building_id, x, y, building_type, size columns.
- Returns:
DataFrame with columns: building_id, x, y, building_type, size
- Return type:
pd.DataFrame
- get_distance_fast(start_coord: tuple, end_coord: tuple)[source]
Return shortest path distance (number of edges) between two street cells.
- Parameters:
start_coord (tuple[int, int]) – Starting street block (x, y).
end_coord (tuple[int, int]) – Ending street block (x, y).
- Returns:
Number of edges in the shortest path from start to end.
- Return type:
int
Notes
Uses the same shortest_paths mechanism as get_shortest_path(), but returns only the distance (len(path) - 1) for efficiency.
- get_paths_fast(start_coord: tuple, end_coord: tuple)[source]
DEPRECATED: Return shortest path with LRU-style caching.
This method wraps get_shortest_path() with a simple cache. May be useful for future optimizations but currently not sufficient for large-scale trajectory generation needs.
- Parameters:
start_coord (tuple[int, int]) – Starting street block (x, y).
end_coord (tuple[int, int]) – Ending street block (x, y).
- Returns:
Sequence of street blocks from start to end, or empty list if no path.
- Return type:
list[tuple[int, int]]
- get_shortest_path(start_coord: tuple, end_coord: tuple, plot: bool = False, ax=None)[source]
Return a block path between two street cells.
- Parameters:
start_coord (tuple[int, int]) – Starting street block (x, y).
end_coord (tuple[int, int]) – Ending street block (x, y).
plot (bool, optional) – Plot the resulting path on the city map when True.
ax (matplotlib.axes.Axes, optional) – Target axis used when plot=True.
- Returns:
Sequence of street blocks from start to end.
- Return type:
list[tuple[int, int]]
- Raises:
ValueError – If either coordinate is not a valid street block or if shortest_paths has not been computed.
Notes
Requires compute_shortest_paths() to be called first. Uses precomputed paths (dict) or on-demand callable depending on mode.
- plot_city(ax, doors=True, address=True, zorder=1, heatmap_agent=None, colors=None, alpha=1, legend=False)[source]
Plots the city on a given matplotlib axis.
- Parameters:
ax (matplotlib.axes.Axes) – The axis on which to plot the city.
doors (bool) – Whether to plot doors of buildings.
address (bool) – Whether to plot the address of buildings.
zorder (int) – The z-order of the plot.
heatmap_agent (Agent) – The agent for which to plot a heatmap of time spent in each building.
colors (dict) – A dictionary mapping building types to colors for plotting.
legend (bool) – Whether to display a legend for building types.
- save(filename)[source]
Saves the city object to a file.
- Parameters:
filename (str) – The name of the file to save the city object to.
- save_geopackage(gpkg_path, persist_blocks=True, persist_city_properties=True, persist_gravity_data=True, reverse_affine=False, edges_path=None, street_graphml_path=None)[source]
Save city to GeoPackage with all spatial objects for simulation continuity.
- Parameters:
gpkg_path (str) – Path to GeoPackage (.gpkg) for buildings, streets, and auxiliary layers
persist_blocks (bool, default False) – If True, save blocks_gdf layer
persist_city_properties (bool, default True) – If True, save city properties (name, block_side_length, origins, etc.)
persist_gravity_data (bool, default True) – If True, save gravity infrastructure (hubs, distances, nearby doors)
reverse_affine (bool, default False) – If True, transform geometries from garden city units to Web Mercator meters
edges_path (str, optional) – Path to save edges parquet (ox, oy, dx, dy, distance, gravity)
street_graphml_path (str, optional) – Path to save street graph as GraphML
Notes
This method saves everything needed to reload and continue a simulation. Use from_geopackage() to reload.
- property streets_df
- to_file(buildings_path=None, streets_path=None, street_graphml_path=None, driver='GeoJSON', to_crs=None, reverse_affine=False)[source]
Export city layers to file with optional coordinate transformations.
- Parameters:
buildings_path (str, optional) – Path to save buildings layer
streets_path (str, optional) – Path to save streets layer
street_graphml_path (str, optional) – Path to save street graph as GraphML
driver (str, default 'GeoJSON') – Output format: ‘GeoJSON’, ‘GPKG’, ‘Parquet’, ‘ESRI Shapefile’
to_crs (str or CRS, optional) – Target CRS for reprojection (e.g., ‘EPSG:4326’)
reverse_affine (bool, default False) – If True, transform from garden city units to Web Mercator meters using self.block_side_length, offset_x, offset_y, rotation_deg
Notes
For GeoJSON output, to_crs=’EPSG:4326’ is required if reverse_affine=True.
- to_mercator(data)[source]
Convert city block coordinates to Web Mercator coordinates using city’s parameters.
- Parameters:
data (pd.DataFrame) – DataFrame with ‘x’, ‘y’ columns in city block coordinates
- Returns:
DataFrame with ‘x’, ‘y’ columns updated to Web Mercator coordinates. If ‘ha’ column exists, it is also scaled.
- Return type:
pd.DataFrame
- class nomad.city_gen.RandomCityGenerator(width, height, street_spacing=5, park_ratio=0.1, home_ratio=0.4, work_ratio=0.3, retail_ratio=0.2, seed=42, verbose=False)[source]
Bases:
object- fill_block(block_x, block_y, block_type)[source]
Fills a block with multiple buildings of the specified type.
- generate_city()[source]
Generates a systematically structured city where blocks are fully occupied with buildings.
- class nomad.city_gen.RasterCity(boundary_polygon, streets_gdf, buildings_gdf, block_side_length=15.0, crs='EPSG:3857', building_type_col='building_type', name='Rasterized City', resolve_overlaps=False, other_building_behavior='keep', rotation_deg=0.0, rotation_origin=None, verbose=True)[source]
Bases:
City
- class nomad.city_gen.Street(coordinates: tuple = None, geometry: Polygon = None)[source]
Bases:
objectClass for street block in the city through which individuals move from building to building.
- coordinates
A tuple representing the (x, y) coordinates of the street block.
- Type:
tuple
- geometry
A polygon representing the geometry of the street block.
- Type:
shapely.geometry.polygon.Polygon
- id
A unique identifier for the street block, formatted as ‘s-x{coordinates[0]}-y{coordinates[1]}’.
- Type:
str
- (none)
- nomad.city_gen.assign_door_to_building(building_blocks, available_blocks, graph=None)[source]
Find adjacent block that can serve as door (not occupied by buildings).
- nomad.city_gen.find_connected_components(block_coords: List[Tuple[int, int]], connectivity: str = '4-connected') List[Set[Tuple[int, int]]][source]
- nomad.city_gen.find_intersecting_blocks(geometries_gdf: GeoDataFrame, blocks_gdf: GeoDataFrame, predicate: str = 'intersects') DataFrame[source]