Pipelines¶
DeepMIMO pipelines are end-to-end workflows that take a geographic location (GPS bounding box) all the way through ray tracing to a finished DeepMIMO dataset — with no manual steps and no proprietary GUI tools required.
deepmimo/pipelines/
├── osm_to_mitsuba.py ← OSM → Mitsuba scene (core of the no-Blender pipeline)
├── txrx_placement.py ← TX / RX grid generation
├── sionna_rt/ ← Sionna RT pipeline driver
│ ├── sionna_raytracer.py
│ └── sionna_utils.py
└── utils/
├── geo_utils.py ← Coordinate conversion, satellite imagery
├── osm_utils.py ← Building queries and placement validation
└── pipeline_utils.py ← BS positioning, scenario management
What are pipelines?¶
A pipeline chains together several independent steps so a single function call can produce a complete ray tracing dataset from nothing but a set of GPS coordinates:
- Scene generation — download building footprints from OpenStreetMap and extrude them into 3D meshes (PLY + Mitsuba XML), or use an existing scene from Blender/Wireless InSite.
- TX / RX placement — convert GPS BS coordinates and UE grids into the local Cartesian system expected by the ray tracer.
- Ray tracing — run Sionna RT (or Wireless InSite) on the scene with the configured antennas.
- Export & convert — serialize the path data and convert it to the standardized DeepMIMO format.
The OSM pipeline (documented below) is the primary no-dependency workflow: it requires only pip install 'deepmimo[sionna]' and an internet connection.
OSM → Mitsuba Scene¶
The osm_to_mitsuba module converts a GPS bounding box into a Mitsuba 2 scene that Sionna RT can load directly. It queries the Overpass API for building footprints, extrudes each polygon into a closed 3D mesh, and writes the result as a scene.xml + PLY mesh collection.
Typical usage¶
from deepmimo.pipelines.osm_to_mitsuba import generate_scene
scene_folder = generate_scene(
minlat=48.1355, minlon=11.5735,
maxlat=48.1395, maxlon=11.5795,
scene_folder="my_munich_scene",
)
# scene_folder/
# scene.xml — Mitsuba scene description
# meshes/ground.ply — flat ground plane
# meshes/building_N.ply — one PLY mesh per OSM building
# osm_gps_origin.txt — origin lat/lon for coordinate recovery
import sionna.rt as sionna_rt
scene = sionna_rt.load_scene(scene_folder + "/scene.xml", merge_shapes=False)
How it works¶
GPS bbox
│
▼
Overpass API → list of (footprint_xy, height) per building
│
▼
_extrude_footprint() → 3D vertices + triangle indices per building
│ (bottom ring + top ring + side walls + roof fan)
▼
_write_ply() → building_N.ply (ASCII PLY, one file per building)
│
▼
_write_mitsuba_xml() → scene.xml (ITU concrete material + shape refs)
Heights come from OSM tags in order of priority:
| Tag | Behaviour |
|---|---|
height |
Parse float, strip " m" suffix |
building:height |
Same |
building:levels |
Multiply by 3 m per floor |
| (none) | Default 10 m |
The coordinate origin is the centre of the GPS bounding box, converted to UTM via utm.from_latlon. All PLY vertices are in local metres relative to this origin. The origin is saved to osm_gps_origin.txt so downstream code can recover GPS coordinates.
API reference¶
Generate a Mitsuba scene from OpenStreetMap building data.
Downloads building footprints for the given GPS bounding box, extrudes them into 3D meshes, creates a ground plane, and writes a Mitsuba XML scene file that Sionna RT can load directly.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
minlat
|
float
|
South boundary latitude. |
required |
minlon
|
float
|
West boundary longitude. |
required |
maxlat
|
float
|
North boundary latitude. |
required |
maxlon
|
float
|
East boundary longitude. |
required |
scene_folder
|
str
|
Output directory. Created if it does not exist. |
required |
ground_padding
|
float
|
Ground plane extends this many metres beyond the bounding box on each side (default 30 m). |
GROUND_PADDING
|
verbose
|
bool
|
Print progress messages. |
True
|
Returns:
| Type | Description |
|---|---|
str
|
Path to the generated scene folder (not the XML file), matching |
str
|
the convention of |
Download building footprints from OpenStreetMap for a GPS bounding box.
Tries Overpass API mirrors first; falls back to the OSM main API if all mirrors are unavailable. Each returned dict has:
coords: list of (lon, lat) tuples forming the closed polygonheight: estimated building height in metres
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
minlat
|
float
|
South boundary latitude. |
required |
minlon
|
float
|
West boundary longitude. |
required |
maxlat
|
float
|
North boundary latitude. |
required |
maxlon
|
float
|
East boundary longitude. |
required |
Returns:
| Type | Description |
|---|---|
list[dict[str, Any]]
|
List of building dicts, each with |
TX / RX Placement¶
txrx_placement converts pipeline configuration dicts into numpy position arrays.
Typical usage¶
from deepmimo.pipelines.txrx_placement import gen_plane_grid
# Generate a UE grid covering the scene
rx_pos = gen_plane_grid(
min_coord1=xmin + 10, max_coord1=xmax - 10,
min_coord2=ymin + 10, max_coord2=ymax - 10,
spacing=30.0,
fixed_coord=1.5, # UE height in metres
normal="z", # grid lies in XY plane
)
# rx_pos: (N, 3) array of [x, y, z] positions
API reference¶
Generate a grid of points on a plane perpendicular to a major axis.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
min_coord1
|
float
|
Minimum value for first planar coordinate |
required |
max_coord1
|
float
|
Maximum value for first planar coordinate |
required |
min_coord2
|
float
|
Minimum value for second planar coordinate |
required |
max_coord2
|
float
|
Maximum value for second planar coordinate |
required |
spacing
|
float
|
Grid spacing in meters |
required |
fixed_coord
|
float
|
Value for the coordinate along the normal axis |
required |
normal
|
str
|
Normal axis of the plane ('x', 'y', or 'z'). Defaults to 'z' |
'z'
|
Returns:
| Type | Description |
|---|---|
ndarray
|
np.ndarray: Grid points with shape (N, 3) where N is the number of points |
Generate user grid in Cartesian coordinates.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
rt_params
|
dict[str, Any]
|
Ray tracing parameters Required Parameters: - min_lat, min_lon, max_lat, max_lon (float): GPS coordinates of the area - origin_lat, origin_lon (float): Origin GPS coordinates - grid_spacing (float): Grid spacing in meters - ue_height (float): UE height in meters |
required |
Returns:
| Type | Description |
|---|---|
ndarray
|
np.ndarray: User grid positions in Cartesian coordinates |
Generate transmitter positions from GPS coordinates.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
rt_params
|
dict[str, Any]
|
Ray tracing parameters dict with keys
|
required |
Returns:
| Type | Description |
|---|---|
ndarray
|
list[list[float]]: Transmitter positions in Cartesian coordinates |
Geographic Utilities¶
geo_utils handles all coordinate system conversions between GPS (lat/lon), UTM
metres, and the local Cartesian system used inside the pipeline.
Coordinate systems¶
| System | Unit | Used for |
|---|---|---|
| GPS (WGS 84) | degrees | Overpass API queries, scenario naming |
| UTM | metres (absolute) | intermediate conversion via utm package |
| Local Cartesian | metres (relative) | scene XML, Sionna positions, DeepMIMO dataset |
The local Cartesian origin is always the centre of the GPS bounding box.
Satellite imagery¶
If you have a Google Maps Static API key, fetch_satellite_view downloads a
640 × 640 satellite image of the scene area:
from deepmimo.pipelines.utils.geo_utils import fetch_satellite_view
img_path = fetch_satellite_view(
minlat=48.1355, minlon=11.5735,
maxlat=48.1395, maxlon=11.5795,
api_key="YOUR_GOOGLE_MAPS_API_KEY",
save_dir="./satellite/",
)
API reference¶
Convert latitude and longitude to UTM coordinates.
Transforms GPS coordinates to Universal Transverse Mercator (UTM) coordinates, which provide a flat representation of the Earth's surface in meters.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
lat
|
float | ndarray
|
Latitude in degrees |
required |
long
|
float | ndarray
|
Longitude in degrees |
required |
Returns:
| Type | Description |
|---|---|
tuple[float | ndarray, float | ndarray]
|
tuple[float | np.ndarray, float | np.ndarray]: Tuple containing: - x (easting): Distance in meters east from zone origin - y (northing): Distance in meters north from equator |
Note
UTM zones and hemisphere information are discarded. For high-precision applications where zone transitions matter, additional handling may be needed.
Convert a GPS bounding box to a Cartesian bounding box.
Transforms a geographic bounding box defined by min/max latitude and longitude into a local Cartesian coordinate system centered at the specified origin.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
minlat
|
float
|
Minimum latitude in degrees |
required |
minlon
|
float
|
Minimum longitude in degrees |
required |
maxlat
|
float
|
Maximum latitude in degrees |
required |
maxlon
|
float
|
Maximum longitude in degrees |
required |
origin_lat
|
float
|
Origin latitude in degrees |
required |
origin_lon
|
float
|
Origin longitude in degrees |
required |
pad
|
float
|
Padding to add to the bounding box in meters |
0
|
Returns:
| Type | Description |
|---|---|
tuple[float, float, float, float]
|
tuple[float, float, float, float]: Tuple containing: - xmin: Minimum x coordinate in meters from origin - ymin: Minimum y coordinate in meters from origin - xmax: Maximum x coordinate in meters from origin - ymax: Maximum y coordinate in meters from origin |
Note
The resulting coordinates are in meters relative to the origin point, making them suitable for local area calculations and visualizations.
Convert GPS coordinates to relative Cartesian coordinates.
Transforms GPS coordinates into a local Cartesian coordinate system centered at the specified origin point. Useful for local area calculations where a flat Earth approximation is acceptable.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
lat
|
float | ndarray
|
Latitude in degrees |
required |
lon
|
float | ndarray
|
Longitude in degrees |
required |
origin_lat
|
float
|
Origin latitude in degrees |
required |
origin_lon
|
float
|
Origin longitude in degrees |
required |
Returns:
| Type | Description |
|---|---|
tuple[float | ndarray, float | ndarray]
|
tuple[float | np.ndarray, float | np.ndarray]: Tuple containing: - x: Distance in meters east from origin - y: Distance in meters north from origin |
Note
For areas spanning more than a few kilometers, consider using a proper projection system to account for Earth's curvature.
Calculate distance between two points in meters using Haversine formula.
The Haversine formula determines the great-circle distance between two points on a sphere given their latitudes and longitudes. This implementation assumes a spherical Earth with radius EARTH_RADIUS.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
lat1
|
float
|
First point latitude in degrees |
required |
lon1
|
float
|
First point longitude in degrees |
required |
lat2
|
float
|
Second point latitude in degrees |
required |
lon2
|
float
|
Second point longitude in degrees |
required |
Returns:
| Name | Type | Description |
|---|---|---|
float |
float
|
Distance between points in meters |
Example
dist = haversine_distance(40.7128, -74.0060, 34.0522, -118.2437) print(f"Distance between NY and LA: {dist/1000:.1f} km")
Fetch a satellite view image of a bounding box using Google Maps Static API.
Downloads and saves a satellite image for the specified geographic area. The image is centered on the bounding box with a fixed zoom level.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
minlat
|
float
|
Minimum latitude in degrees |
required |
minlon
|
float
|
Minimum longitude in degrees |
required |
maxlat
|
float
|
Maximum latitude in degrees |
required |
maxlon
|
float
|
Maximum longitude in degrees |
required |
api_key
|
str
|
Google Maps API key for authentication |
required |
save_dir
|
str
|
Directory to save the satellite view image |
required |
Returns:
| Type | Description |
|---|---|
str | None
|
Optional[str]: Path to the saved image file, or None if the request fails |
Note
- Image size is fixed at 640x640 pixels (maximum for free tier)
- Zoom level is fixed at 18 (detailed view)
- Requires a valid Google Maps API key with Static Maps API enabled
- API calls may incur charges depending on your Google Maps API plan
Pipeline Utilities¶
pipeline_utils provides helpers for reading pipeline outputs and placing
base stations.
Typical usage¶
from deepmimo.pipelines.utils.pipeline_utils import get_origin_coords
# After generate_scene(), recover the coordinate origin
origin_lat, origin_lon = get_origin_coords(osm_scene_folder)
API reference¶
Read the origin coordinates from the OSM folder.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
osm_folder
|
str
|
Path to the OSM folder |
required |
Returns:
| Type | Description |
|---|---|
tuple[float, float]
|
tuple[float, float]: Origin coordinates (latitude, longitude) |
OSM Building Utilities¶
osm_utils provides helpers for querying and validating building data — useful
when you need to place a base station at a specific GPS location and ensure it
does not overlap with any building.
Typical usage¶
from deepmimo.pipelines.utils.osm_utils import get_buildings, find_nearest_clear_location
# Find a clear outdoor BS location near a given GPS point
buildings = get_buildings(lat=48.137, lon=11.576)
clear_lat, clear_lon = find_nearest_clear_location(
original_lat=48.137, original_lon=11.576, buildings=buildings
)
API reference¶
Get all significant buildings in the area as Building instances.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
lat
|
float
|
Latitude of the center point |
required |
lon
|
float
|
Longitude of the center point |
required |
radius
|
float
|
Search radius in meters, defaults to SEARCH_RADIUS |
SEARCH_RADIUS
|
Returns:
| Type | Description |
|---|---|
list[Building]
|
list[Building]: List of Building instances |
Find nearest location that maintains minimum distance from all buildings.
Uses multiple strategies to find a suitable location: 1. Checks if original point is already clear of buildings 2. Moves away from nearest building edge 3. Uses spiral search pattern 4. Uses random walk with increasing distance 5. Falls back to moving north if all else fails
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
original_lat
|
float
|
Original latitude |
required |
original_lon
|
float
|
Original longitude |
required |
buildings
|
list[Building]
|
List of Building instances |
required |
Returns:
| Type | Description |
|---|---|
tuple[float, float]
|
tuple[float, float]: Tuple of (latitude, longitude) for location clear of buildings |
Check if point maintains minimum distance from all building footprints.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
point
|
Point
|
Point to check |
required |
buildings
|
list[Building]
|
List of Building instances |
required |
Returns:
| Name | Type | Description |
|---|---|---|
bool |
bool
|
True if point maintains minimum distance from all buildings |