Getting Started with DeepMIMO.¶
Tutorial Overview:
- Part 1: Hello World - Load a simple scenario, generate channels
- Part 2: Deep Dive - Explore complex scenarios with multiple base stations
- Part 3: Discovery - Learn how to discover more using
dm.info(), aliases, and implicit computations
Related Video: Getting Started Video
Part 1: Hello World¶
Let's start with the absolute basics: installing DeepMIMO, loading a simple scenario, and generating channels.
# Install DeepMIMO (if not already installed)
%pip install --pre deepmimo
Requirement already satisfied: deepmimo in /Users/namhyunk/miniforge3/lib/python3.12/site-packages (4.0.0b11) Requirement already satisfied: matplotlib>=3.8.2 in /Users/namhyunk/miniforge3/lib/python3.12/site-packages (from deepmimo) (3.10.8) Requirement already satisfied: numpy<2.3,>=1.19.5 in /Users/namhyunk/miniforge3/lib/python3.12/site-packages (from deepmimo) (2.2.6) Requirement already satisfied: scipy>=1.6.2 in /Users/namhyunk/miniforge3/lib/python3.12/site-packages (from deepmimo) (1.16.1) Requirement already satisfied: tqdm>=4.59.0 in /Users/namhyunk/miniforge3/lib/python3.12/site-packages (from deepmimo) (4.67.1) Requirement already satisfied: requests in /Users/namhyunk/miniforge3/lib/python3.12/site-packages (from deepmimo) (2.32.4) Requirement already satisfied: contourpy>=1.0.1 in /Users/namhyunk/miniforge3/lib/python3.12/site-packages (from matplotlib>=3.8.2->deepmimo) (1.3.3) Requirement already satisfied: cycler>=0.10 in /Users/namhyunk/miniforge3/lib/python3.12/site-packages (from matplotlib>=3.8.2->deepmimo) (0.12.1) Requirement already satisfied: fonttools>=4.22.0 in /Users/namhyunk/miniforge3/lib/python3.12/site-packages (from matplotlib>=3.8.2->deepmimo) (4.62.1) Requirement already satisfied: kiwisolver>=1.3.1 in /Users/namhyunk/miniforge3/lib/python3.12/site-packages (from matplotlib>=3.8.2->deepmimo) (1.5.0) Requirement already satisfied: packaging>=20.0 in /Users/namhyunk/miniforge3/lib/python3.12/site-packages (from matplotlib>=3.8.2->deepmimo) (25.0) Requirement already satisfied: pillow>=8 in /Users/namhyunk/miniforge3/lib/python3.12/site-packages (from matplotlib>=3.8.2->deepmimo) (11.3.0) Requirement already satisfied: pyparsing>=3 in /Users/namhyunk/miniforge3/lib/python3.12/site-packages (from matplotlib>=3.8.2->deepmimo) (3.3.2) Requirement already satisfied: python-dateutil>=2.7 in /Users/namhyunk/miniforge3/lib/python3.12/site-packages (from matplotlib>=3.8.2->deepmimo) (2.9.0.post0) Requirement already satisfied: six>=1.5 in /Users/namhyunk/miniforge3/lib/python3.12/site-packages (from python-dateutil>=2.7->matplotlib>=3.8.2->deepmimo) (1.17.0) Requirement already satisfied: charset_normalizer<4,>=2 in /Users/namhyunk/miniforge3/lib/python3.12/site-packages (from requests->deepmimo) (3.4.2) Requirement already satisfied: idna<4,>=2.5 in /Users/namhyunk/miniforge3/lib/python3.12/site-packages (from requests->deepmimo) (3.10) Requirement already satisfied: urllib3<3,>=1.21.1 in /Users/namhyunk/miniforge3/lib/python3.12/site-packages (from requests->deepmimo) (2.5.0) Requirement already satisfied: certifi>=2017.4.17 in /Users/namhyunk/miniforge3/lib/python3.12/site-packages (from requests->deepmimo) (2025.7.14)
Note: you may need to restart the kernel to use updated packages.
# Import necessary libraries
import numpy as np
import deepmimo as dm
Warning: AODT features require pandas/pyarrow. Install with: pip install 'deepmimo[aodt]'
Load a Simple Scenario¶
We'll use the ASU Campus scenario, which is a simple outdoor scenario.
# Download and load a scenario
scen_name = "asu_campus_3p5"
dm.download(scen_name)
dataset = dm.load(scen_name)
Scenario "asu_campus_3p5" already exists in /Users/namhyunk/Documents/GitHub/DeepMIMO/deepmimo_scenarios Loading TXRX PAIR: TXset 1 (tx_idx 0) & RXset 0 (rx_idxs 131931)
# Check what we loaded
print(f"Loaded scenario: {scen_name}")
print(f"Dataset type: {type(dataset)}")
print(dataset)
Loaded scenario: asu_campus_3p5
Dataset type: <class 'deepmimo.datasets.dataset.Dataset'>
{'aoa_az': array([[nan, nan, nan, ..., nan, nan, nan],
[nan, nan, nan, ..., nan, nan, nan],
[nan, nan, nan, ..., nan, nan, nan],
...,
[nan, nan, nan, ..., nan, nan, nan],
[nan, nan, nan, ..., nan, nan, nan],
[nan, nan, nan, ..., nan, nan, nan]],
shape=(131931, 10), dtype=float32),
'aoa_el': array([[nan, nan, nan, ..., nan, nan, nan],
[nan, nan, nan, ..., nan, nan, nan],
[nan, nan, nan, ..., nan, nan, nan],
...,
[nan, nan, nan, ..., nan, nan, nan],
[nan, nan, nan, ..., nan, nan, nan],
[nan, nan, nan, ..., nan, nan, nan]],
shape=(131931, 10), dtype=float32),
'aod_az': array([[nan, nan, nan, ..., nan, nan, nan],
[nan, nan, nan, ..., nan, nan, nan],
[nan, nan, nan, ..., nan, nan, nan],
...,
[nan, nan, nan, ..., nan, nan, nan],
[nan, nan, nan, ..., nan, nan, nan],
[nan, nan, nan, ..., nan, nan, nan]],
shape=(131931, 10), dtype=float32),
'aod_el': array([[nan, nan, nan, ..., nan, nan, nan],
[nan, nan, nan, ..., nan, nan, nan],
[nan, nan, nan, ..., nan, nan, nan],
...,
[nan, nan, nan, ..., nan, nan, nan],
[nan, nan, nan, ..., nan, nan, nan],
[nan, nan, nan, ..., nan, nan, nan]],
shape=(131931, 10), dtype=float32),
'delay': array([[nan, nan, nan, ..., nan, nan, nan],
[nan, nan, nan, ..., nan, nan, nan],
[nan, nan, nan, ..., nan, nan, nan],
...,
[nan, nan, nan, ..., nan, nan, nan],
[nan, nan, nan, ..., nan, nan, nan],
[nan, nan, nan, ..., nan, nan, nan]],
shape=(131931, 10), dtype=float32),
'inter': array([[nan, nan, nan, ..., nan, nan, nan],
[nan, nan, nan, ..., nan, nan, nan],
[nan, nan, nan, ..., nan, nan, nan],
...,
[nan, nan, nan, ..., nan, nan, nan],
[nan, nan, nan, ..., nan, nan, nan],
[nan, nan, nan, ..., nan, nan, nan]],
shape=(131931, 10), dtype=float32),
'inter_pos': array([[[[nan, nan, nan],
[nan, nan, nan],
[nan, nan, nan],
[nan, nan, nan],
[nan, nan, nan],
[nan, nan, nan]],
[[nan, nan, nan],
[nan, nan, nan],
[nan, nan, nan],
[nan, nan, nan],
[nan, nan, nan],
[nan, nan, nan]],
[[nan, nan, nan],
[nan, nan, nan],
[nan, nan, nan],
[nan, nan, nan],
[nan, nan, nan],
[nan, nan, nan]],
...,
[[nan, nan, nan],
[nan, nan, nan],
[nan, nan, nan],
[nan, nan, nan],
[nan, nan, nan],
[nan, nan, nan]],
[[nan, nan, nan],
[nan, nan, nan],
[nan, nan, nan],
[nan, nan, nan],
[nan, nan, nan],
[nan, nan, nan]],
[[nan, nan, nan],
[nan, nan, nan],
[nan, nan, nan],
[nan, nan, nan],
[nan, nan, nan],
[nan, nan, nan]]],
[[[nan, nan, nan],
[nan, nan, nan],
[nan, nan, nan],
[nan, nan, nan],
[nan, nan, nan],
[nan, nan, nan]],
[[nan, nan, nan],
[nan, nan, nan],
[nan, nan, nan],
[nan, nan, nan],
[nan, nan, nan],
[nan, nan, nan]],
[[nan, nan, nan],
[nan, nan, nan],
[nan, nan, nan],
[nan, nan, nan],
[nan, nan, nan],
[nan, nan, nan]],
...,
[[nan, nan, nan],
[nan, nan, nan],
[nan, nan, nan],
[nan, nan, nan],
[nan, nan, nan],
[nan, nan, nan]],
[[nan, nan, nan],
[nan, nan, nan],
[nan, nan, nan],
[nan, nan, nan],
[nan, nan, nan],
[nan, nan, nan]],
[[nan, nan, nan],
[nan, nan, nan],
[nan, nan, nan],
[nan, nan, nan],
[nan, nan, nan],
[nan, nan, nan]]],
[[[nan, nan, nan],
[nan, nan, nan],
[nan, nan, nan],
[nan, nan, nan],
[nan, nan, nan],
[nan, nan, nan]],
[[nan, nan, nan],
[nan, nan, nan],
[nan, nan, nan],
[nan, nan, nan],
[nan, nan, nan],
[nan, nan, nan]],
[[nan, nan, nan],
[nan, nan, nan],
[nan, nan, nan],
[nan, nan, nan],
[nan, nan, nan],
[nan, nan, nan]],
...,
[[nan, nan, nan],
[nan, nan, nan],
[nan, nan, nan],
[nan, nan, nan],
[nan, nan, nan],
[nan, nan, nan]],
[[nan, nan, nan],
[nan, nan, nan],
[nan, nan, nan],
[nan, nan, nan],
[nan, nan, nan],
[nan, nan, nan]],
[[nan, nan, nan],
[nan, nan, nan],
[nan, nan, nan],
[nan, nan, nan],
[nan, nan, nan],
[nan, nan, nan]]],
...,
[[[nan, nan, nan],
[nan, nan, nan],
[nan, nan, nan],
[nan, nan, nan],
[nan, nan, nan],
[nan, nan, nan]],
[[nan, nan, nan],
[nan, nan, nan],
[nan, nan, nan],
[nan, nan, nan],
[nan, nan, nan],
[nan, nan, nan]],
[[nan, nan, nan],
[nan, nan, nan],
[nan, nan, nan],
[nan, nan, nan],
[nan, nan, nan],
[nan, nan, nan]],
...,
[[nan, nan, nan],
[nan, nan, nan],
[nan, nan, nan],
[nan, nan, nan],
[nan, nan, nan],
[nan, nan, nan]],
[[nan, nan, nan],
[nan, nan, nan],
[nan, nan, nan],
[nan, nan, nan],
[nan, nan, nan],
[nan, nan, nan]],
[[nan, nan, nan],
[nan, nan, nan],
[nan, nan, nan],
[nan, nan, nan],
[nan, nan, nan],
[nan, nan, nan]]],
[[[nan, nan, nan],
[nan, nan, nan],
[nan, nan, nan],
[nan, nan, nan],
[nan, nan, nan],
[nan, nan, nan]],
[[nan, nan, nan],
[nan, nan, nan],
[nan, nan, nan],
[nan, nan, nan],
[nan, nan, nan],
[nan, nan, nan]],
[[nan, nan, nan],
[nan, nan, nan],
[nan, nan, nan],
[nan, nan, nan],
[nan, nan, nan],
[nan, nan, nan]],
...,
[[nan, nan, nan],
[nan, nan, nan],
[nan, nan, nan],
[nan, nan, nan],
[nan, nan, nan],
[nan, nan, nan]],
[[nan, nan, nan],
[nan, nan, nan],
[nan, nan, nan],
[nan, nan, nan],
[nan, nan, nan],
[nan, nan, nan]],
[[nan, nan, nan],
[nan, nan, nan],
[nan, nan, nan],
[nan, nan, nan],
[nan, nan, nan],
[nan, nan, nan]]],
[[[nan, nan, nan],
[nan, nan, nan],
[nan, nan, nan],
[nan, nan, nan],
[nan, nan, nan],
[nan, nan, nan]],
[[nan, nan, nan],
[nan, nan, nan],
[nan, nan, nan],
[nan, nan, nan],
[nan, nan, nan],
[nan, nan, nan]],
[[nan, nan, nan],
[nan, nan, nan],
[nan, nan, nan],
[nan, nan, nan],
[nan, nan, nan],
[nan, nan, nan]],
...,
[[nan, nan, nan],
[nan, nan, nan],
[nan, nan, nan],
[nan, nan, nan],
[nan, nan, nan],
[nan, nan, nan]],
[[nan, nan, nan],
[nan, nan, nan],
[nan, nan, nan],
[nan, nan, nan],
[nan, nan, nan],
[nan, nan, nan]],
[[nan, nan, nan],
[nan, nan, nan],
[nan, nan, nan],
[nan, nan, nan],
[nan, nan, nan],
[nan, nan, nan]]]], shape=(131931, 10, 6, 3), dtype=float32),
'load_params': {'matrices': 'all',
'max_paths': 25,
'rx_sets': {0: array([ 0, 1, 2, ..., 131928, 131929, 131930],
shape=(131931,))},
'tx_sets': {1: array([0])}},
'materials': MaterialList(1 materials, names=['ITU Concrete 3.5 GHz']),
'name': 'asu_campus_3p5',
'phase': array([[nan, nan, nan, ..., nan, nan, nan],
[nan, nan, nan, ..., nan, nan, nan],
[nan, nan, nan, ..., nan, nan, nan],
...,
[nan, nan, nan, ..., nan, nan, nan],
[nan, nan, nan, ..., nan, nan, nan],
[nan, nan, nan, ..., nan, nan, nan]],
shape=(131931, 10), dtype=float32),
'power': array([[nan, nan, nan, ..., nan, nan, nan],
[nan, nan, nan, ..., nan, nan, nan],
[nan, nan, nan, ..., nan, nan, nan],
...,
[nan, nan, nan, ..., nan, nan, nan],
[nan, nan, nan, ..., nan, nan, nan],
[nan, nan, nan, ..., nan, nan, nan]],
shape=(131931, 10), dtype=float32),
'rt_params': {'diffuse_diffractions': 1,
'diffuse_final_interaction_only': True,
'diffuse_random_phases': False,
'diffuse_reflections': 2,
'diffuse_transmissions': 0,
'frequency': 3500000000.0,
'max_diffractions': 1,
'max_path_depth': 7,
'max_reflections': 6,
'max_scattering': 1,
'max_transmissions': 0,
'num_rays': 259200,
'raw_params': {'antenna': {'VSWR': 1,
'antenna': 1,
'cable_loss': 0,
'component': 'TotalGain',
'gain_range': 40,
'is_sphere': False,
'polarization': 'vertical',
'power_threshold': -250,
'show_arrow': False,
'type': 'isotropic',
'waveform': 0},
'apg_acceleration': {'adjacency_distance': 10,
'binary_output_mode': 'per_path_utm',
'binary_rate': [0, 'active'],
'database_mode': 'write',
'enabled': True,
'path_depth': 10,
'workflow_mode': 'full'},
'diffuse_scattering': {'diffuse_diffractions': 1,
'diffuse_reflections': 2,
'diffuse_transmissions': 0,
'enabled': True,
'final_interaction_only': True},
'model': {'OutputRequests': {'data': [],
'kind': '',
'labels': [],
'name': '',
'values': {'CEF': False,
'ComplexImpulseResponse': True,
'DelaySpread': False,
'DirectionOfArrival': True,
'DirectionOfDeparture': True,
'ElectroMagneticFields': False,
'FSPathloss': False,
'FSPower': False,
'MeanDirectionOfArrival': False,
'MeanDirectionOfDeparture': False,
'MeanTimeOfArrival': False,
'Pathloss': True,
'Paths': True,
'Power': False,
'TimeOfArrival': True,
'XPathloss': False}},
'foliage_attenuation_hor': 1,
'foliage_attenuation_vert': 1,
'foliage_model': 0,
'initial_ray_mode': 'uniform_sweep',
'max_reflections': 6,
'max_transmissions': 0,
'max_wedge_diffractions': 1,
'num_threads': 20,
'plane_wave_phase_reference': 'automatic',
'ray_spacing': 0.25,
'terrain_diffractions': 'No'},
'studyarea': {'MPE': {'data': [],
'kind': '',
'labels': [],
'name': '',
'values': {'mpe_averaging_time': 300,
'mpe_averaging_time_short': 0.1,
'mpe_is_active': 'inactive',
'mpe_user_efield_peak': 100000,
'mpe_user_efield_rms': 61.4,
'mpe_user_hfield_rms': 0.163,
'mpe_user_power': 2,
'mpe_user_power_short': 10,
'mpestandard': 'controlled'}},
'MonteCarlo': {'data': [],
'kind': '',
'labels': [],
'name': '',
'values': {'monte_carlo_active': False,
'monte_carlo_iterations': 10,
'monte_carlo_max': False,
'monte_carlo_mean': True,
'monte_carlo_median': False,
'monte_carlo_min': False,
'monte_carlo_sdev': False,
'monte_carlo_seed': 1,
'monte_carlo_updated': False}},
'StudyAreaNumber': 2,
'apg_acceleration': {'data': [],
'kind': '',
'labels': [],
'name': '',
'values': {'adjacency_distance': 10,
'binary_output_mode': 'per_path_utm',
'binary_rate': [0, 'active'],
'database_mode': 'write',
'enabled': True,
'path_depth': 10,
'workflow_mode': 'full'}},
'autoboundary': 1,
'boundary': {'data': [[-323.9248046875, -285.705810546875, 0],
[358.074584960938, -285.705810546875, 0],
[358.074584960938, 240.25, 0],
[-323.9248046875, 240.25, 0]],
'kind': '',
'labels': [],
'name': '',
'values': {'nVertices': 4,
'reference': {'data': [],
'kind': '',
'labels': ['cartesian', 'terrain'],
'name': '',
'values': {'latitude': 0, 'longitude': 0, 'visible': False}},
'zmax': 27.4909896850586,
'zmin': -0.25}},
'diffuse_scattering': {'data': [],
'kind': '',
'labels': [],
'name': '',
'values': {'diffuse_diffractions': 1,
'diffuse_reflections': 2,
'diffuse_transmissions': 0,
'enabled': True,
'final_interaction_only': True}},
'model': {'data': [[17.0749, -22.7279, 13.6205]],
'kind': '',
'labels': ['x3d'],
'name': '',
'values': {'OutputRequests': {'data': [],
'kind': '',
'labels': [],
'name': '',
'values': {'CEF': False,
'ComplexImpulseResponse': True,
'DelaySpread': False,
'DirectionOfArrival': True,
'DirectionOfDeparture': True,
'ElectroMagneticFields': False,
'FSPathloss': False,
'FSPower': False,
'MeanDirectionOfArrival': False,
'MeanDirectionOfDeparture': False,
'MeanTimeOfArrival': False,
'Pathloss': True,
'Paths': True,
'Power': False,
'TimeOfArrival': True,
'XPathloss': False}},
'foliage_attenuation_hor': 1,
'foliage_attenuation_vert': 1,
'foliage_model': 0,
'initial_ray_mode': 'uniform_sweep',
'max_reflections': 6,
'max_transmissions': 0,
'max_wedge_diffractions': 1,
'num_threads': 20,
'plane_wave_phase_reference': 'automatic',
'ray_spacing': 0.25,
'terrain_diffractions': 'No'}},
'partitioning': {'data': [],
'kind': '',
'labels': [],
'name': '',
'values': {'max_threads': 0,
'num_partitions': 2,
'partitioning_type': 'disabled',
'queuing_type': 'disabled'}}},
'waveform': {'CarrierFrequency': 3500000000.0,
'bandwidth': 100000000.0,
'frequencyDistribution': ['Uniform', 500.0, 1500.0, 'inactive', False, 10],
'phase': 0.0,
'waveform': 0}},
'ray_casting_method': 'uniform',
'ray_casting_range_az': 360.0,
'ray_casting_range_el': 180.0,
'raytracer_name': 'Remcom Wireless Insite',
'raytracer_version': '3.3',
'synthetic_array': True,
'terrain_diffraction': False,
'terrain_reflection': True,
'terrain_scattering': False},
'rx_pos': array([[-225.551, -160.169, 1.5 ],
[-224.551, -160.169, 1.5 ],
[-223.551, -160.169, 1.5 ],
...,
[ 182.449, 159.831, 1.5 ],
[ 183.449, 159.831, 1.5 ],
[ 184.449, 159.831, 1.5 ]], shape=(131931, 3), dtype=float32),
'scene': Scene(36 objects [buildings: 35, terrain: 1], dims = 681.5 x 525.5 x 27.2 m),
'tx_pos': array([[166., 104., 22.]], dtype=float32),
'txrx': {'rx_set_id': 0, 'tx_idx': 0, 'tx_set_id': 1}}
Generate Channels¶
Now let's generate some basic channel matrices.
# Generate time-domain channels
ch_params = dm.ChannelParameters()
ch_params.freq_domain = False
dataset.compute_channels(ch_params)
channels = dataset.channel
print(f"Channel shape: {channels.shape}")
print(f"Channel type: {type(channels)}")
Channel shape: (131931, 1, 8, 10) Channel type: <class 'deepmimo.datasets.array_wrapper.DeepMIMOArray'>
Basic Inspection¶
Let's check some basic properties of our dataset.
# Check line-of-sight status
print(f"LOS status shape: {dataset.los.shape}")
print(f"Number of users with LOS: {np.sum(dataset.los == 1)}")
print(f"Number of users with NLOS: {np.sum(dataset.los == 0)}")
print(f"Number of users with no paths: {np.sum(dataset.los == -1)}")
LOS status shape: (131931,) Number of users with LOS: 25998 Number of users with NLOS: 59159 Number of users with no paths: 46774
# Check pathloss
pathloss = dataset.pathloss
print(f"Pathloss shape: {pathloss.shape}")
print(f"Average pathloss: {np.mean(pathloss[pathloss > -np.inf]):.2f} dB")
Pathloss shape: (131931,) Average pathloss: 109.23 dB
Part 2: Deep Dive with Complex Scenarios¶
Now let's explore a more complex scenario with multiple base stations and dive deeper into the dataset structure.
# Load a city scenario with multiple base stations
city_scen = "city_18_denver_3p5"
dm.download(city_scen)
# Load specific TX/RX sets to get a single dataset
city_dataset = dm.load(city_scen, tx_sets=[1], rx_sets=[0])
Scenario "city_18_denver_3p5" already exists in /Users/namhyunk/Documents/GitHub/DeepMIMO/deepmimo_scenarios Loading TXRX PAIR: TXset 1 (tx_idx 0) & RXset 0 (rx_idxs 43248)
Explore TX/RX Pairs and Sets¶
# Get information about transmitter and receiver sets
txrx_sets = dm.get_txrx_sets(city_scen)
print("Available TX-RX sets:")
for txrx_set in txrx_sets:
print(f" {txrx_set}")
Available TX-RX sets: RXSet(name='UE_grid', id=0, points=43248) TXRXSet(name='BS3', id=1, points=1) TXRXSet(name='BS2', id=2, points=1) TXRXSet(name='BS1', id=3, points=1)
# Get TX/RX pair information
pairs = dm.get_txrx_pairs(txrx_sets)
print(f"Number of TX/RX pairs: {len(pairs)}")
print("First few pairs:")
for pair in pairs[:5]:
print(f" {pair}")
Number of TX/RX pairs: 12 First few pairs: TxRxPair(tx=BS3[0], rx=UE_grid) TxRxPair(tx=BS3[0], rx=BS3) TxRxPair(tx=BS3[0], rx=BS2) TxRxPair(tx=BS3[0], rx=BS1) TxRxPair(tx=BS2[0], rx=UE_grid)
Explore Available Matrices¶
Let's see what matrices/parameters are available in the dataset.
# List available fundamental matrices
print("Available dataset attributes:")
for attr in dir(city_dataset):
if not attr.startswith("_") and not callable(getattr(city_dataset, attr)):
print(f" - {attr}")
Available dataset attributes: - WRAPPABLE_ARRAYS - aoa_az - aoa_el - aoa_phi - aoa_theta - aod_az - aod_el - aod_phi - aod_theta
- array_response_product - bounce_pos - bounce_type - bs_ori - bs_pos
- ch - ch_params - channel - channel_params - channels - chs - delay - dist - distance - dists
- doppler - grid_size - grid_spacing - inter - inter_int
- inter_obj - inter_obj_ids - inter_object_ids - inter_objects - inter_objs - inter_pos
- inter_str
- inter_vec - interaction_locations - interaction_positions - interactions - lin_pwr - linear_power - load_params - los - los_status - materials - max_inter - max_interactions - max_paths
- mplm_hash - multipath_hash - n_paths - n_ue - name - num_inter - num_interactions - num_paths - path_hash - path_ids - path_loss - pathloss - phase - pl - power - power_linear - powers - pwr - pwr_ant_gain - pwr_lin - rt_params - rx_loc - rx_locations - rx_ori - rx_pos - rx_position - rx_vel - scene - time_of_arrival - toa - tx_loc - tx_locations - tx_ori - tx_pos - tx_position - tx_rx - tx_vel - txrx - txrx_sets - ue_ori - ue_pos
# Explore some key matrices
print(f"Power matrix shape: {city_dataset.power.shape}")
print(f"Phase matrix shape: {city_dataset.phase.shape}")
print(f"Delay matrix shape: {city_dataset.delay.shape}")
print(f"AOA (azimuth) matrix shape: {city_dataset.aoa_az.shape}")
print(f"AOD (azimuth) matrix shape: {city_dataset.aod_az.shape}")
Power matrix shape: (43248, 25) Phase matrix shape: (43248, 25) Delay matrix shape: (43248, 25) AOA (azimuth) matrix shape: (43248, 25) AOD (azimuth) matrix shape: (43248, 25)
Scenario Summary¶
Get a high-level overview of the scenario.
# Get scenario summary
print("Scenario Summary:")
dm.summary(city_scen)
Scenario Summary: ================================================== DeepMIMO city_18_denver_3p5 Scenario Summary ================================================== [Ray-Tracing Configuration] - Ray-tracer: Remcom Wireless Insite v3.3 - Frequency: 3.5 GHz [Ray-tracing parameters] Main interaction limits - Max path depth: 4 - Max reflections: 3 - Max diffractions: 1 - Max scatterings: 1 - Max transmissions: 0 Diffuse Scattering - Diffuse scattering: Enabled - Diffuse reflections: 2 - Diffuse diffractions: 1 - Diffuse transmissions: 0 - Final interaction only: True - Random phases: False Terrain - Terrain reflection: True - Terrain diffraction: False - Terrain scattering: False Ray Casting Settings - Number of rays: 259,200 - Casting method: uniform - Casting range (az): 360.0° - Casting range (el): 180.0° - Synthetic array: True [Scene] - Number of scenes: 1 - Total objects: 547 - Vertices: 1,911 - Faces: 3,928 - Triangular faces: 547 [Materials] Total materials: 3 ITU Concrete 3.5 GHz: - Permittivity: 5.31 - Conductivity: 0.09 S/m - Scattering model: directive - Scattering coefficient: 0.20 - Cross-polarization coefficient: 0.40 Asphalt_1GHz: - Permittivity: 5.72 - Conductivity: 0.00 S/m - Scattering model: none - Scattering coefficient: 0.40 - Cross-polarization coefficient: 0.40 ITU Wet earth 3.5 GHz: - Permittivity: 18.18 - Conductivity: 0.76 S/m - Scattering model: directive - Scattering coefficient: 0.40 - Cross-polarization coefficient: 0.40 [TX/RX Configuration] Total number of receivers: 28992 Total number of transmitters: 3 txrx_set_0 (UE_grid): - Role: RX - Total points: 43,248 - Active points: 28,989 - Antennas per point: 1 - Dual polarization: False txrx_set_1 (BS3): - Role: TX & RX - Total points: 1 - Active points: 1 - Antennas per point: 1 - Dual polarization: False txrx_set_2 (BS2): - Role: TX & RX - Total points: 1 - Active points: 1 - Antennas per point: 1 - Dual polarization: False txrx_set_3 (BS1): - Role: TX & RX - Total points: 1 - Active points: 1 - Antennas per point: 1 - Dual polarization: False
Part 3: Discovery - Learning More¶
DeepMIMO provides powerful tools to help you discover and understand the available functions and parameters.
Using dm.info() for Parameter Documentation¶
# Get information about all available parameters
dm.info("all")
Fundamental Matrices: ============================== power: Tap power. Received power in dBW for each path, assuming 0 dBW transmitted power. 10*log10(|a|²), where a is the complex channel amplitude [num_rx, num_paths] phase: Tap phase. Phase of received signal for each path in degrees. ∠a (angle of a), where a is the complex channel amplitude [num_rx, num_paths] delay: Tap delay. Propagation delay for each path in seconds [num_rx, num_paths] aoa_az: Angle of arrival (azimuth) for each path in degrees [num_rx, num_paths] aoa_el: Angle of arrival (elevation) for each path in degrees [num_rx, num_paths] aod_az: Angle of departure (azimuth) for each path in degrees [num_rx, num_paths] aod_el: Angle of departure (elevation) for each path in degrees [num_rx, num_paths] inter: Type of interactions along each path Codes: 0: LOS, 1: Reflection, 2: Diffraction, 3: Scattering, 4: Transmission Code meaning: 121 -> Tx-R-D-R-Rx [num_rx, num_paths] inter_pos: 3D coordinates in meters of each interaction point along paths [num_rx, num_paths, max_interactions, 3] rx_pos: Receiver positions in 3D coordinates in meters [num_rx, 3] tx_pos: Transmitter positions in 3D coordinates in meters [num_tx, 3] Computed/Derived Matrices: ============================== los: Line of sight status for each path. 1: Direct path between TX and RX. 0: Indirect path (reflection, diffraction, scattering, or transmission). -1: No paths between TX and RX. [num_rx, ] channel: Channel matrix between TX and RX antennas [num_rx, num_rx_ant, num_tx_ant, X], with X = number of paths in time domain or X = number of subcarriers in frequency domain power_linear: Linear power for each path (W) [num_rx, num_paths] pathloss: Pathloss for each path (dB) [num_rx, num_paths] distance: Distance between TX and RX for each path (m) [num_rx, num_paths] num_paths: Number of paths for each user [num_rx] inter_str: Interaction string for each path. Interaction codes: 0 -> "", 1 -> "R", 2 -> "D", 3 -> "S", 4 -> "T" Example interaction integer to string: 121 -> "RDR" [num_rx, num_paths] doppler: Doppler frequency shifts [Hz] for each user and path [num_rx, num_paths] inter_obj: Object ids at each interaction point [num_rx, num_paths, max_interactions] Additional Dataset Fields: ============================== scene: Scene parameters materials: List of available materials and their electromagnetic properties txrx_sets: Transmitter/receiver parameters rt_params: Ray-tracing parameters
# Get information about a specific parameter
dm.info("power")
power: Tap power. Received power in dBW for each path, assuming 0 dBW transmitted power. 10*log10(|a|²), where a is the complex channel amplitude [num_rx, num_paths]
# Get information about channel parameters
dm.info("ch_params")
Channel Generation Parameters: ============================== bs_antenna: Base station antenna array configuration parameters. ue_antenna: User equipment antenna array configuration parameters. bs_antenna.shape: Antenna array dimensions [X, Y] or [X, Y, Z] elements Default: [1, 1] | Type: list[int] | Units: number of elements bs_antenna.spacing: Spacing between antenna elements Default: 0.5 | Type: float | Units: wavelengths bs_antenna.rotation: Rotation angles [azimuth, elevation, polarization] Default: [0, 0, 0] | Type: list[float] | Units: degrees bs_antenna.radiation_pattern: Antenna element radiation pattern Default: "isotropic" | Type: str | Options: "isotropic", "halfwave-dipole" doppler: Enable/disable Doppler effect simulation Default: False | Type: bool num_paths: Maximum number of paths to consider per user Default: 10 | Type: int | Units: number of paths freq_domain: Channel domain Default: 0 | Type: int | Options: 0 (time domain), 1 (frequency domain/OFDM) ofdm: OFDM channel configuration parameters. Used (and needed!) only if freq_domain=1. Default: None | Type: dict ofdm.bandwidth: System bandwidth Default: 10e6 | Type: float | Units: Hz ofdm.subcarriers: Total number of OFDM subcarriers Default: 512 | Type: int | Units: number of subcarriers ofdm.selected_subcarriers: Indices of subcarriers to generate Default: None (all subcarriers) | Type: list[int] | Units: subcarrier indices ofdm.rx_filter: Enable/disable receive low-pass filter / ADC filter Default: False | Type: bool
Inspecting Function Docstrings¶
You can use dm.info() to inspect the docstrings of any function or object!
# Inspect the docstring of a function
# dm.info(dm.load) # Uncomment to view docstring
print("Use dm.info(dm.load) to view the docstring of dm.load()")
Use dm.info(dm.load) to view the docstring of dm.load()
# Inspect the docstring of a method
# dm.info(dataset.compute_channels) # Uncomment to view docstring
print("Use dm.info(dataset.compute_channels) to view the docstring")
Use dm.info(dataset.compute_channels) to view the docstring
Understanding Aliases¶
DeepMIMO provides convenient aliases for common parameters.
# Check if an alias resolves to a parameter
dm.info("rx_pos") # This is an alias
rx_pos: Receiver positions in 3D coordinates in meters [num_rx, 3]
# Common aliases
print("Using aliases:")
print(" dataset.user_pos (alias) -> dataset.rx_pos (actual)")
print(" dataset.bs_pos (alias) -> dataset.tx_pos (actual)")
print(f" RX positions shape: {dataset.rx_pos.shape}")
Using aliases: dataset.user_pos (alias) -> dataset.rx_pos (actual) dataset.bs_pos (alias) -> dataset.tx_pos (actual) RX positions shape: (131931, 3)
Implicit Computations¶
Some dataset attributes are computed on-the-fly when you access them.
# These are computed implicitly:
print(f"Number of paths per user: {dataset.num_paths[:10]}") # Computed from power/delay
print(f"Pathloss (dB) for first 5 users: {dataset.pathloss[:5]}") # Computed from power
print(f"Distance (m) for first 5 users: {dataset.dist[:5]}") # Computed from delay
Number of paths per user: [ 0 0 0 0 0 0 0 0 0 10] Pathloss (dB) for first 5 users: [nan nan nan nan nan] Distance (m) for first 5 users: [472.77658 471.94873 471.12152 470.295 469.46918]
Discovering More Functions¶
Explore the available functions in the DeepMIMO module.
# List key functions in the dm module
print("Key DeepMIMO functions:")
key_functions = [f for f in dir(dm) if not f.startswith("_") and callable(getattr(dm, f))]
for func in sorted(key_functions)[:20]: # Show first 20
print(f" - dm.{func}()")
Key DeepMIMO functions: - dm.BoundingBox() - dm.ChannelParameters() - dm.Dataset() - dm.DelegatingList() - dm.DotDict() - dm.DynamicDataset() - dm.Face() - dm.MacroDataset() - dm.Material() - dm.MaterialList() - dm.PhysicalElement() - dm.PhysicalElementGroup() - dm.RayTracingParameters() - dm.Scene() - dm.TxRxPair() - dm.TxRxSet() - dm.config() - dm.convert() - dm.dbw2watt() - dm.download()
# Get help for any function
# dm.info(dm.download) # Uncomment to view docstring
print("Use dm.info(dm.download) to view the docstring of any function")
Use dm.info(dm.download) to view the docstring of any function
Next Steps¶
Now that you understand the basics, explore these tutorials:
- Tutorial 2: Visualization and Scene - Learn how to visualize coverage maps, rays, and 3D scenes
- Tutorial 3: Detailed Channel Generation - Deep dive into channel generation parameters
- Tutorial 4: User Selection and Dataset Manipulation - Learn how to filter and sample users
- Tutorial 5: Doppler and Mobility - Add time-varying effects to your channels
- Tutorial 6: Beamforming - Implement beamforming and spatial processing
- Tutorial 7: Convert & Upload Ray-tracing dataset - Work with external ray tracers
- Tutorial 8: Migration Guide - Migrating from DeepMIMO v3 to v4