Visualization and Scene.¶
Tutorial Overview:
- Coverage Maps - Visualizing signal coverage
- Rays - Ray propagation visualization
- Path Plots - Visualization of different path components
- Scene & Materials - 3D scene and material visualization
- Plot Overlays - Combining different visualizations
Related Video: Visualization Video
In [1]:
Copied!
# Import libraries
import matplotlib.pyplot as plt
import numpy as np
import deepmimo as dm
# Import libraries
import matplotlib.pyplot as plt
import numpy as np
import deepmimo as dm
Warning: AODT features require pandas/pyarrow. Install with: pip install 'deepmimo[aodt]'
In [2]:
Copied!
# Load dataset
scen_name = "asu_campus_3p5"
dm.download(scen_name)
dataset = dm.load(scen_name)
# Load dataset
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)
Coverage Maps¶
Visualize signal coverage across the scenario.
In [3]:
Copied!
# Plot power coverage
dataset.power.plot()
plt.title("Power Coverage Map")
plt.show()
# Plot power coverage
dataset.power.plot()
plt.title("Power Coverage Map")
plt.show()
In [4]:
Copied!
# Plot pathloss coverage
dataset.pathloss.plot()
plt.title("Pathloss Coverage Map")
plt.show()
# Plot pathloss coverage
dataset.pathloss.plot()
plt.title("Pathloss Coverage Map")
plt.show()
Rays¶
Visualize ray propagation paths.
In [5]:
Copied!
# Plot rays for a user with line-of-sight
u_idx = np.where(dataset.los == 1)[0][100]
dataset.plot_rays(u_idx, proj_3D=False, dpi=100)
plt.title("Ray Propagation Paths")
plt.show()
# Plot rays for a user with line-of-sight
u_idx = np.where(dataset.los == 1)[0][100]
dataset.plot_rays(u_idx, proj_3D=False, dpi=100)
plt.title("Ray Propagation Paths")
plt.show()
Path Plots¶
Visualize different path components and characteristics.
Percentage of Power¶
In [6]:
Copied!
# Plot power percentage per path
if hasattr(dataset, "power"):
# Calculate power percentage
linear_power = 10 ** (dataset.power / 10)
total_power = np.sum(linear_power, axis=1, keepdims=True)
power_pct = (linear_power / (total_power + 1e-20)) * 100
plt.figure(figsize=(10, 6))
plt.hist(power_pct[power_pct > 0].flatten(), bins=50)
plt.xlabel("Power Percentage (%)")
plt.ylabel("Count")
plt.title("Distribution of Power Percentage per Path")
plt.show()
# Plot power percentage per path
if hasattr(dataset, "power"):
# Calculate power percentage
linear_power = 10 ** (dataset.power / 10)
total_power = np.sum(linear_power, axis=1, keepdims=True)
power_pct = (linear_power / (total_power + 1e-20)) * 100
plt.figure(figsize=(10, 6))
plt.hist(power_pct[power_pct > 0].flatten(), bins=50)
plt.xlabel("Power Percentage (%)")
plt.ylabel("Count")
plt.title("Distribution of Power Percentage per Path")
plt.show()
Number of Interactions¶
In [7]:
Copied!
# Visualize number of interactions per path
if hasattr(dataset, "interactions"):
interactions = dataset.interactions
# Count digits in interaction codes
num_interactions = np.array(
[[len(str(int(x))) if x > 0 else 0 for x in row] for row in interactions]
)
plt.figure(figsize=(10, 6))
plt.hist(num_interactions.flatten(), bins=range(10))
plt.xlabel("Number of Interactions")
plt.ylabel("Count")
plt.title("Distribution of Interaction Counts")
plt.show()
# Visualize number of interactions per path
if hasattr(dataset, "interactions"):
interactions = dataset.interactions
# Count digits in interaction codes
num_interactions = np.array(
[[len(str(int(x))) if x > 0 else 0 for x in row] for row in interactions]
)
plt.figure(figsize=(10, 6))
plt.hist(num_interactions.flatten(), bins=range(10))
plt.xlabel("Number of Interactions")
plt.ylabel("Count")
plt.title("Distribution of Interaction Counts")
plt.show()
Scene & Materials¶
Explore the 3D scene and materials.
Scene Visualization¶
In [8]:
Copied!
# Plot the 3D scene
if hasattr(dataset, "scene"):
dataset.scene.plot()
plt.title("3D Scene")
plt.show()
else:
print("Scene data not available for this scenario")
# Plot the 3D scene
if hasattr(dataset, "scene"):
dataset.scene.plot()
plt.title("3D Scene")
plt.show()
else:
print("Scene data not available for this scenario")
Materials¶
In [9]:
Copied!
# Display material properties
if hasattr(dataset, "materials"):
print("Available Materials:")
print(dataset.materials)
else:
print("Material data not available for this scenario")
# Display material properties
if hasattr(dataset, "materials"):
print("Available Materials:")
print(dataset.materials)
else:
print("Material data not available for this scenario")
Available Materials: MaterialList(1 materials, names=['ITU Concrete 3.5 GHz'])
Plot Overlays¶
Combine different visualizations for comprehensive analysis.
2D Scene, Coverage & Rays Overlay¶
In [10]:
Copied!
# Overlay coverage map with rays
fig, ax = plt.subplots(figsize=(12, 8))
# Plot coverage as background
dataset.power.plot(ax=ax)
# Overlay rays for a selected user
los_users = np.where(dataset.los == 1)[0]
if len(los_users) > 0:
dataset.plot_rays(los_users[50], ax=ax, proj_3D=False)
plt.title("Coverage Map with Ray Overlay")
plt.show()
# Overlay coverage map with rays
fig, ax = plt.subplots(figsize=(12, 8))
# Plot coverage as background
dataset.power.plot(ax=ax)
# Overlay rays for a selected user
los_users = np.where(dataset.los == 1)[0]
if len(los_users) > 0:
dataset.plot_rays(los_users[50], ax=ax, proj_3D=False)
plt.title("Coverage Map with Ray Overlay")
plt.show()
3D Scene & Rays Overlay¶
In [11]:
Copied!
# 3D visualization with scene and rays
if hasattr(dataset, "scene"):
# Plot rays first, then overlay the scene
ax = dataset.plot_rays(los_users[50])
dataset.scene.plot(ax=ax)
ax.legend().set_visible(False)
plt.title("3D Scene with Rays")
plt.show()
else:
print("3D scene not available for this scenario")
# 3D visualization with scene and rays
if hasattr(dataset, "scene"):
# Plot rays first, then overlay the scene
ax = dataset.plot_rays(los_users[50])
dataset.scene.plot(ax=ax)
ax.legend().set_visible(False)
plt.title("3D Scene with Rays")
plt.show()
else:
print("3D scene not available for this scenario")
Multipath Lifetime Map (MPLM)¶
Visualize spatial regions with similar multipath characteristics. The MPLM colors each receiver location based on its unique multipath signature. Receivers with the same combination of propagation paths will have the same color.
Basic MPLM Visualization¶
In [12]:
Copied!
# Plot the Multipath Lifetime Map
dataset.plot_mplm(dpi=150)
plt.show()
# Plot the Multipath Lifetime Map
dataset.plot_mplm(dpi=150)
plt.show()
The MPLM computation involves three lazy-evaluated properties:
dataset.inter_vec: Vectorized interaction codesdataset.path_ids: Unique IDs for each path signaturedataset.path_hash: Hash for each user's multipath mix
In [13]:
Copied!
# Access the underlying data (computed lazily on first access)
path_hash = dataset.path_hash
path_ids = dataset.path_ids
# Statistics
print(f"Total users: {dataset.n_ue}")
print(f"Active users (with paths): {(path_hash != -1).sum()}")
print(f"Unique multipath signatures: {len(np.unique(path_hash[path_hash != -1]))}")
# Access the underlying data (computed lazily on first access)
path_hash = dataset.path_hash
path_ids = dataset.path_ids
# Statistics
print(f"Total users: {dataset.n_ue}")
print(f"Active users (with paths): {(path_hash != -1).sum()}")
print(f"Unique multipath signatures: {len(np.unique(path_hash[path_hash != -1]))}")
Total users: 131931 Active users (with paths): 85157 Unique multipath signatures: 15201
Analyzing Multipath Zones¶
In [14]:
Copied!
# Find the most common multipath signatures
active_hashes = path_hash[path_hash != -1]
unique_hashes, counts = np.unique(active_hashes, return_counts=True)
top_5_idx = np.argsort(counts)[-5:]
print("Top 5 most common multipath signatures:")
for idx in reversed(top_5_idx):
hash_val = unique_hashes[idx]
count = counts[idx]
print(f" Hash {hash_val}: {count} users ({count / len(active_hashes) * 100:.1f}%)")
# Find the most common multipath signatures
active_hashes = path_hash[path_hash != -1]
unique_hashes, counts = np.unique(active_hashes, return_counts=True)
top_5_idx = np.argsort(counts)[-5:]
print("Top 5 most common multipath signatures:")
for idx in reversed(top_5_idx):
hash_val = unique_hashes[idx]
count = counts[idx]
print(f" Hash {hash_val}: {count} users ({count / len(active_hashes) * 100:.1f}%)")
Top 5 most common multipath signatures: Hash 2613: 360 users (0.4%) Hash 11224: 201 users (0.2%) Hash 402: 185 users (0.2%) Hash 11557: 163 users (0.2%) Hash 12133: 154 users (0.2%)
Next Steps¶
Continue with:
- 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