|
|
|
""" |
|
Created on Fri Sep 13 16:13:29 2024 |
|
|
|
This script generates preprocessed data from wireless communication scenarios, |
|
including channel generation, patch generation, masking, and preparing raw |
|
channels for the Transformer-based LWM model. |
|
|
|
@author: Sadjad Alikhani |
|
""" |
|
import numpy as np |
|
import os |
|
from tqdm import tqdm |
|
import time |
|
import pickle |
|
import DeepMIMOv3 |
|
import torch |
|
from collections import defaultdict |
|
from utils import generate_gaussian_noise, plot_coverage |
|
|
|
def scenarios_list(): |
|
scen_list = np.array([ |
|
'city_0_newyork', |
|
'city_1_losangeles', |
|
'city_2_chicago', |
|
'city_3_houston', |
|
'city_4_phoenix', |
|
'city_5_philadelphia', |
|
'city_6_miami', |
|
'city_7_sandiego', |
|
'city_8_dallas', |
|
'city_9_sanfrancisco', |
|
'city_10_austin', |
|
'city_11_santaclara', |
|
'city_12_fortworth', |
|
'city_13_columbus', |
|
'city_14_charlotte', |
|
'city_15_indianapolis', |
|
'city_16_sanfrancisco', |
|
'city_17_seattle', |
|
'city_18_denver', |
|
'city_19_oklahoma', |
|
'asu_campus1_v1', |
|
'asu_campus1_v2', |
|
'asu_campus1_v3', |
|
'asu_campus1_v4', |
|
'asu_campus1_v5', |
|
'asu_campus1_v6', |
|
'asu_campus1_v7', |
|
'asu_campus1_v8', |
|
'asu_campus1_v9', |
|
'asu_campus1_v10', |
|
'asu_campus1_v11', |
|
'asu_campus1_v12', |
|
'asu_campus1_v13', |
|
'asu_campus1_v14', |
|
'asu_campus1_v15', |
|
'asu_campus1_v16', |
|
'asu_campus1_v17', |
|
'asu_campus1_v18', |
|
'asu_campus1_v19', |
|
'asu_campus1_v20', |
|
'Boston5G_3p5_v1', |
|
'Boston5G_3p5_v2', |
|
'Boston5G_3p5_v3', |
|
'Boston5G_3p5_v4', |
|
'Boston5G_3p5_v5', |
|
'Boston5G_3p5_v6', |
|
'Boston5G_3p5_v7', |
|
'Boston5G_3p5_v8', |
|
'Boston5G_3p5_v9', |
|
'Boston5G_3p5_v10', |
|
'Boston5G_3p5_v11', |
|
'Boston5G_3p5_v12', |
|
'Boston5G_3p5_v13', |
|
'Boston5G_3p5_v14', |
|
'Boston5G_3p5_v15', |
|
'Boston5G_3p5_v16', |
|
'Boston5G_3p5_v17', |
|
'Boston5G_3p5_v18', |
|
'Boston5G_3p5_v19', |
|
'Boston5G_3p5_v20', |
|
'O1_3p5_v1', |
|
'O1_3p5_v2', |
|
'O1_3p5_v3', |
|
'O1_3p5_v4', |
|
'O1_3p5_v5', |
|
'O1_3p5_v6', |
|
'O1_3p5_v7', |
|
'O1_3p5_v8', |
|
'O1_3p5_v9', |
|
'O1_3p5_v10', |
|
'O1_3p5_v11', |
|
'O1_3p5_v12', |
|
'O1_3p5_v13', |
|
'O1_3p5_v14', |
|
'O1_3p5_v15', |
|
'O1_3p5_v16', |
|
'O1_3p5_v17', |
|
'O1_3p5_v18', |
|
'O1_3p5_v19', |
|
'O1_3p5_v20', |
|
'asu_campus1', |
|
'O1_3p5', |
|
'Boston5G_3p5', |
|
'city_0_newyork_v16x64', |
|
'city_1_losangeles_v16x64', |
|
'city_2_chicago_v16x64', |
|
'city_3_houston_v16x64', |
|
'city_4_phoenix_v16x64', |
|
'city_5_philadelphia_v16x64', |
|
'city_6_miami_v16x64', |
|
'city_7_sandiego_v16x64', |
|
'city_8_dallas_v16x64', |
|
'city_9_sanfrancisco_v16x64' |
|
]) |
|
return scen_list |
|
|
|
def patch_gen(N_ROWS=4, N_COLUMNS=4, selected_scenario_names=None, |
|
manual_data=None, bs_idxs=[1,2,3], load_data=False, |
|
save_dir="data", task="LoS/NLoS Classification", |
|
n_beams=64, o1_bs_idx=[4]): |
|
|
|
os.makedirs(save_dir, exist_ok=True) |
|
|
|
if manual_data is not None: |
|
patches = patch_maker(np.expand_dims(np.array(manual_data), axis=1)) |
|
else: |
|
deepmimo_data = [] |
|
for scenario_name in selected_scenario_names: |
|
if "O1" in scenario_name: |
|
if o1_bs_idx is None: |
|
bs_idxs = [4, 15] |
|
else: |
|
bs_idxs = o1_bs_idx |
|
for bs_idx in bs_idxs: |
|
if has_version_suffix(scenario_name) and bs_idx in [2,3]: |
|
continue |
|
if not load_data: |
|
print(f"\nGenerating data for scenario: {scenario_name}, BS #{bs_idx}") |
|
data, n_ant_bs, n_subcarriers = DeepMIMO_data_gen(scenario_name, bs_idx) |
|
file_name = f"{save_dir}/{scenario_name}_ant{n_ant_bs}_sub{n_subcarriers}_bs{bs_idx}.npy" |
|
np.save(file_name, data) |
|
print(f"Data saved to {file_name}") |
|
deepmimo_data.append(data) |
|
else: |
|
n_ant_bs, n_subcarriers = parametersv2(scenario_name, bs_idx) |
|
print(f"\nLoading data for scenario: {scenario_name}, BS #{bs_idx}") |
|
file_name = f"{save_dir}/{scenario_name}_ant{n_ant_bs}_sub{n_subcarriers}_bs{bs_idx}.npy" |
|
data = np.load(file_name, allow_pickle=True).item() |
|
print(f"Data loaded from {file_name}") |
|
deepmimo_data.append(data) |
|
|
|
cleaned_deepmimo_data = [deepmimo_data_cleaning(deepmimo_data[scenario_idx]) for scenario_idx in range(len(deepmimo_data))] |
|
patches = [patch_maker(cleaned_deepmimo_data[scenario_idx], N_ROWS, N_COLUMNS) for scenario_idx in range(len(deepmimo_data))] |
|
raw_chs = torch.tensor(cleaned_deepmimo_data[0]).squeeze(1) |
|
raw_chs = raw_chs.view(raw_chs.size(0), -1) |
|
raw_chs = torch.hstack((raw_chs.real, raw_chs.imag)) |
|
|
|
if task: |
|
labels = [label_gen(task, deepmimo_data[scenario_idx], selected_scenario_names[scenario_idx], n_beams=n_beams) for scenario_idx in range(len(deepmimo_data))] |
|
return patches, torch.tensor(labels[0]), raw_chs.view(raw_chs.size(0), -1) |
|
else: |
|
return patches, raw_chs.view(raw_chs.size(0), -1) |
|
|
|
def tokenizer(selected_scenario_names, |
|
bs_idxs=[1,2,3], |
|
load_data=False, |
|
task="LoS/NLoS Classification", |
|
n_beams=64, |
|
MAX_LEN=513, |
|
masking_percent=.40, |
|
mask=False, |
|
manual_data=None, |
|
seed=42, |
|
snr=None): |
|
|
|
patches, labels, raw_chs = patch_gen( |
|
selected_scenario_names=selected_scenario_names, |
|
manual_data=manual_data, |
|
bs_idxs=bs_idxs, |
|
load_data=load_data, |
|
task=task, |
|
n_beams=n_beams |
|
) |
|
|
|
patches = [patch for patch_list in patches for patch in patch_list] |
|
print("Total number of samples:", len(patches)) |
|
|
|
grouped_data = defaultdict(list) |
|
grouped_data_2 = [] |
|
|
|
for user_idx in tqdm(range(len(patches)), desc="Processing items"): |
|
patch_size = patches[user_idx].shape[1] |
|
n_patches = patches[user_idx].shape[0] |
|
n_masks_half = int(masking_percent * n_patches) |
|
|
|
word2id = { |
|
'[CLS]': 0.2 * np.ones((patch_size)), |
|
'[MASK]': 0.1 * np.ones((patch_size)) |
|
} |
|
|
|
sample = make_sample( |
|
user_idx, patches, word2id, n_patches, n_masks_half, patch_size, MAX_LEN, mask=mask, seed=seed |
|
) |
|
|
|
if mask: |
|
seq_length = len(sample[0]) |
|
grouped_data[seq_length].append(sample) |
|
else: |
|
grouped_data_2.append(sample) |
|
|
|
if mask: |
|
|
|
normalized_grouped_data = {i: grouped_data[key] for i, key in enumerate(sorted(grouped_data.keys()))} |
|
else: |
|
normalized_grouped_data = torch.stack(grouped_data_2, dim=0) |
|
|
|
if snr is not None: |
|
normalized_grouped_data += generate_gaussian_noise(normalized_grouped_data, snr) |
|
|
|
|
|
return normalized_grouped_data, labels, raw_chs |
|
|
|
def deepmimo_data_cleaning(deepmimo_data): |
|
idxs = np.where(deepmimo_data['user']['LoS'] != -1)[0] |
|
cleaned_deepmimo_data = deepmimo_data['user']['channel'][idxs] |
|
return np.array(cleaned_deepmimo_data) * 1e6 |
|
|
|
def make_sample(user_idx, patch, word2id, n_patches, n_masks, patch_size, MAX_LEN, mask=True, seed=None): |
|
|
|
if seed is not None: |
|
np.random.seed(seed) |
|
|
|
|
|
tokens = patch[user_idx] |
|
input_ids = np.vstack((word2id['[CLS]'], tokens)) |
|
|
|
|
|
tokens_size = int(n_patches) |
|
masked_pos = np.random.choice(range(1, tokens_size), size=n_masks, replace=False) |
|
|
|
masked_tokens = [] |
|
for pos in masked_pos: |
|
original_masked_tokens = input_ids[pos].copy() |
|
masked_tokens.append(original_masked_tokens) |
|
if mask: |
|
rnd_num = np.random.rand() |
|
if rnd_num < 0.1: |
|
input_ids[pos] = np.random.rand(patch_size) |
|
elif rnd_num < 0.9: |
|
input_ids[pos] = word2id['[MASK]'] |
|
|
|
if not mask: |
|
return torch.tensor(input_ids) |
|
else: |
|
return [input_ids, masked_tokens, masked_pos] |
|
|
|
def patch_maker(original_ch, patch_rows, patch_cols): |
|
|
|
n_samples, _, n_rows, n_cols = original_ch.shape |
|
original_ch = original_ch[:, 0] |
|
|
|
|
|
flat_real = original_ch.real |
|
flat_imag = original_ch.imag |
|
|
|
|
|
interleaved = np.empty((n_samples, n_rows, n_cols * 2), dtype=np.float32) |
|
interleaved[:, :, 0::2] = flat_real |
|
interleaved[:, :, 1::2] = flat_imag |
|
|
|
|
|
n_patches_rows = int(np.ceil(n_rows / patch_rows)) |
|
n_patches_cols = int(np.ceil(n_cols / patch_cols)) |
|
|
|
|
|
padded_rows = n_patches_rows * patch_rows - n_rows |
|
padded_cols = n_patches_cols * patch_cols - n_cols |
|
if padded_rows > 0 or padded_cols > 0: |
|
interleaved = np.pad( |
|
interleaved, |
|
((0, 0), (0, padded_rows), (0, padded_cols * 2)), |
|
mode='constant', |
|
constant_values=0, |
|
) |
|
|
|
|
|
n_samples, padded_rows, padded_cols = interleaved.shape |
|
padded_cols //= 2 |
|
patches = [] |
|
|
|
for i in range(0, padded_rows, patch_rows): |
|
for j in range(0, padded_cols, patch_cols): |
|
patch = interleaved[:, i:i + patch_rows, j * 2:(j + patch_cols) * 2] |
|
patches.append(patch.reshape(n_samples, -1)) |
|
|
|
|
|
patches = np.stack(patches, axis=1) |
|
|
|
return patches |
|
|
|
def DeepMIMO_data_gen(scenario, bs_idx): |
|
import DeepMIMOv3 |
|
parameters, row_column_users = get_parameters(scenario, bs_idx) |
|
deepMIMO_dataset = DeepMIMOv3.generate_data(parameters) |
|
|
|
if "O1" in scenario: |
|
hops = [2, 2] |
|
else: |
|
hops = [1, 1] |
|
|
|
uniform_idxs = uniform_sampling(deepMIMO_dataset, hops, len(parameters['user_rows']), |
|
users_per_row=row_column_users[scenario]['n_per_row']) |
|
data = select_by_idx(deepMIMO_dataset, uniform_idxs)[0] |
|
|
|
n_ant_bs = parameters['bs_antenna']['shape'][0] |
|
n_subcarriers = parameters['OFDM']['subcarriers'] |
|
|
|
return data, n_ant_bs, n_subcarriers |
|
|
|
def parametersv2(scenario, bs_idx): |
|
parameters, _ = get_parameters(scenario, bs_idx) |
|
n_ant_bs = parameters['bs_antenna']['shape'][0] |
|
n_subcarriers = parameters['OFDM']['subcarriers'] |
|
return n_ant_bs, n_subcarriers |
|
|
|
def get_parameters(scenario, bs_idx=1): |
|
|
|
n_ant_ue = 1 |
|
scs = 30e3 |
|
|
|
row_column_users = scenario_prop() |
|
|
|
parameters = DeepMIMOv3.default_params() |
|
parameters['dataset_folder'] = './scenarios' |
|
parameters['scenario'] = scenario.split("_v")[0] |
|
|
|
n_ant_bs = row_column_users[scenario]['n_ant_bs'] |
|
n_subcarriers = row_column_users[scenario]['n_subcarriers'] |
|
parameters['active_BS'] = np.array([bs_idx]) |
|
|
|
if isinstance(row_column_users[scenario]['n_rows'], int): |
|
parameters['user_rows'] = np.arange(row_column_users[scenario]['n_rows']) |
|
else: |
|
parameters['user_rows'] = np.arange(row_column_users[scenario]['n_rows'][0], |
|
row_column_users[scenario]['n_rows'][1]) |
|
|
|
parameters['bs_antenna']['shape'] = np.array([n_ant_bs, 1]) |
|
parameters['bs_antenna']['rotation'] = np.array([0,0,-135]) |
|
parameters['ue_antenna']['shape'] = np.array([n_ant_ue, 1]) |
|
parameters['enable_BS2BS'] = False |
|
parameters['OFDM']['subcarriers'] = n_subcarriers |
|
parameters['OFDM']['selected_subcarriers'] = np.arange(n_subcarriers) |
|
|
|
parameters['OFDM']['bandwidth'] = scs * n_subcarriers / 1e9 |
|
parameters['num_paths'] = 20 |
|
|
|
return parameters, row_column_users |
|
|
|
def uniform_sampling(dataset, sampling_div, n_rows, users_per_row): |
|
cols = np.arange(users_per_row, step=sampling_div[0]) |
|
rows = np.arange(n_rows, step=sampling_div[1]) |
|
uniform_idxs = np.array([j + i * users_per_row for i in rows for j in cols]) |
|
return uniform_idxs |
|
|
|
def select_by_idx(dataset, idxs): |
|
dataset_t = [] |
|
for bs_idx in range(len(dataset)): |
|
dataset_t.append({}) |
|
for key in dataset[bs_idx].keys(): |
|
dataset_t[bs_idx]['location'] = dataset[bs_idx]['location'] |
|
dataset_t[bs_idx]['user'] = {k: dataset[bs_idx]['user'][k][idxs] for k in dataset[bs_idx]['user']} |
|
return dataset_t |
|
|
|
def inverse_patch_maker(patches, original_shape, patch_rows, patch_cols): |
|
""" |
|
Reconstructs the original channel matrix from patches. |
|
|
|
Args: |
|
patches (numpy array): Patches of shape (num_samples, n_patches, patch_rows * patch_cols * 2). |
|
original_shape (tuple): Original shape of the channel matrix (num_samples, 1, n_rows, n_cols). |
|
patch_rows (int): Number of rows in each patch. |
|
patch_cols (int): Number of columns in each patch. |
|
|
|
Returns: |
|
numpy array: Reconstructed complex-valued channel matrix of shape (num_samples, 1, n_rows, n_cols). |
|
""" |
|
n_samples, n_patches, patch_size = patches.shape |
|
_, _, n_rows, n_cols = original_shape |
|
|
|
|
|
assert patch_rows * patch_cols * 2 == patch_size, "Patch size mismatch with provided dimensions." |
|
|
|
|
|
n_patches_rows = int(np.ceil(n_rows / patch_rows)) |
|
n_patches_cols = int(np.ceil(n_cols / patch_cols)) |
|
|
|
|
|
interleaved = np.zeros((n_samples, n_patches_rows * patch_rows, n_patches_cols * patch_cols * 2), dtype=np.float32) |
|
patch_idx = 0 |
|
|
|
for i in range(n_patches_rows): |
|
for j in range(n_patches_cols): |
|
patch = patches[:, patch_idx, :].reshape(n_samples, patch_rows, patch_cols * 2) |
|
interleaved[:, i * patch_rows:(i + 1) * patch_rows, j * patch_cols * 2:(j + 1) * patch_cols * 2] = patch |
|
patch_idx += 1 |
|
|
|
|
|
interleaved = interleaved[:, :n_rows, :n_cols * 2] |
|
|
|
|
|
flat_real = interleaved[:, :, 0::2] |
|
flat_imag = interleaved[:, :, 1::2] |
|
|
|
|
|
reconstructed = flat_real + 1j * flat_imag |
|
|
|
|
|
reconstructed = reconstructed[:, np.newaxis, :, :] |
|
|
|
return reconstructed |
|
|
|
def label_gen(task, data, scenario, n_beams=64): |
|
|
|
idxs = np.where(data['user']['LoS'] != -1)[0] |
|
|
|
if task == 'LoS/NLoS Classification': |
|
label = data['user']['LoS'][idxs] |
|
|
|
losChs = np.where(data['user']['LoS'] == -1, np.nan, data['user']['LoS']) |
|
plot_coverage(data['user']['location'], losChs, cbar_title='LoS status') |
|
|
|
elif task == 'Beam Prediction': |
|
parameters, row_column_users = get_parameters(scenario, bs_idx=1) |
|
n_users = len(data['user']['channel']) |
|
n_subbands = 1 |
|
fov = 180 |
|
|
|
|
|
beam_angles = np.around(np.arange(-fov/2, fov/2+.1, fov/(n_beams-1)), 2) |
|
|
|
F1 = np.array([steering_vec(parameters['bs_antenna']['shape'], |
|
phi=azi*np.pi/180, |
|
kd=2*np.pi*parameters['bs_antenna']['spacing']).squeeze() |
|
for azi in beam_angles]) |
|
|
|
full_dbm = np.zeros((n_beams, n_subbands, n_users), dtype=float) |
|
for ue_idx in tqdm(range(n_users), desc='Computing the channel for each user'): |
|
if data['user']['LoS'][ue_idx] == -1: |
|
full_dbm[:,:,ue_idx] = np.nan |
|
else: |
|
chs = F1 @ data['user']['channel'][ue_idx] |
|
full_linear = np.abs(np.mean(chs.squeeze().reshape((n_beams, n_subbands, -1)), axis=-1)) |
|
full_dbm[:,:,ue_idx] = np.around(20*np.log10(full_linear) + 30, 1) |
|
|
|
best_beams = np.argmax(np.mean(full_dbm,axis=1), axis=0) |
|
best_beams = best_beams.astype(float) |
|
best_beams[np.isnan(full_dbm[0,0,:])] = np.nan |
|
|
|
|
|
plot_coverage(data['user']['location'], best_beams, tx_pos=data['location'], |
|
tx_ori=parameters['bs_antenna']['rotation']*np.pi/180, |
|
cbar_title='Best beam index') |
|
|
|
label = best_beams[idxs] |
|
|
|
return label.astype(int) |
|
|
|
def steering_vec(array, phi=0, theta=0, kd=np.pi): |
|
idxs = DeepMIMOv3.ant_indices(array) |
|
resp = DeepMIMOv3.array_response(idxs, phi, theta+np.pi/2, kd) |
|
return resp / np.linalg.norm(resp) |
|
|
|
import re |
|
def has_version_suffix(s): |
|
pattern = r"_v([1-9]|1[0-9]|20)$" |
|
return bool(re.search(pattern, s)) |
|
|
|
def scenario_prop(): |
|
row_column_users = { |
|
'city_0_newyork': { |
|
'n_rows': 109, |
|
'n_per_row': 291, |
|
'n_ant_bs': 8, |
|
'n_subcarriers': 32 |
|
}, |
|
'city_1_losangeles': { |
|
'n_rows': 142, |
|
'n_per_row': 201, |
|
'n_ant_bs': 8, |
|
'n_subcarriers': 64 |
|
}, |
|
'city_2_chicago': { |
|
'n_rows': 139, |
|
'n_per_row': 200, |
|
'n_ant_bs': 8, |
|
'n_subcarriers': 128 |
|
}, |
|
'city_3_houston': { |
|
'n_rows': 154, |
|
'n_per_row': 202, |
|
'n_ant_bs': 8, |
|
'n_subcarriers': 256 |
|
}, |
|
'city_4_phoenix': { |
|
'n_rows': 198, |
|
'n_per_row': 214, |
|
'n_ant_bs': 8, |
|
'n_subcarriers': 512 |
|
}, |
|
'city_5_philadelphia': { |
|
'n_rows': 239, |
|
'n_per_row': 164, |
|
'n_ant_bs': 8, |
|
'n_subcarriers': 1024 |
|
}, |
|
'city_6_miami': { |
|
'n_rows': 199, |
|
'n_per_row': 216 , |
|
'n_ant_bs': 16, |
|
'n_subcarriers': 32 |
|
}, |
|
'city_7_sandiego': { |
|
'n_rows': 207, |
|
'n_per_row': 176, |
|
'n_ant_bs': 16, |
|
'n_subcarriers': 64 |
|
}, |
|
'city_8_dallas': { |
|
'n_rows': 207, |
|
'n_per_row': 190, |
|
'n_ant_bs': 16, |
|
'n_subcarriers': 128 |
|
}, |
|
'city_9_sanfrancisco': { |
|
'n_rows': 196, |
|
'n_per_row': 206, |
|
'n_ant_bs': 16, |
|
'n_subcarriers': 256 |
|
}, |
|
'city_10_austin': { |
|
'n_rows': 255, |
|
'n_per_row': 137, |
|
'n_ant_bs': 16, |
|
'n_subcarriers': 512 |
|
}, |
|
'city_11_santaclara': { |
|
'n_rows': 117, |
|
'n_per_row': 285, |
|
'n_ant_bs': 32, |
|
'n_subcarriers': 32 |
|
}, |
|
'city_12_fortworth': { |
|
'n_rows': 214, |
|
'n_per_row': 179, |
|
'n_ant_bs': 32, |
|
'n_subcarriers': 64 |
|
}, |
|
'city_13_columbus': { |
|
'n_rows': 178, |
|
'n_per_row': 240, |
|
'n_ant_bs': 32, |
|
'n_subcarriers': 128 |
|
}, |
|
'city_14_charlotte': { |
|
'n_rows': 216, |
|
'n_per_row': 177, |
|
'n_ant_bs': 32, |
|
'n_subcarriers': 256 |
|
}, |
|
'city_15_indianapolis': { |
|
'n_rows': 200, |
|
'n_per_row': 196, |
|
'n_ant_bs': 64, |
|
'n_subcarriers': 32 |
|
}, |
|
'city_16_sanfrancisco': { |
|
'n_rows': 201, |
|
'n_per_row': 208, |
|
'n_ant_bs': 64, |
|
'n_subcarriers': 64 |
|
}, |
|
'city_17_seattle': { |
|
'n_rows': 185, |
|
'n_per_row': 205, |
|
'n_ant_bs': 64, |
|
'n_subcarriers': 128 |
|
}, |
|
'city_18_denver': { |
|
'n_rows': 212, |
|
'n_per_row': 204, |
|
'n_ant_bs': 128, |
|
'n_subcarriers': 32 |
|
}, |
|
'city_19_oklahoma': { |
|
'n_rows': 204, |
|
'n_per_row': 188, |
|
'n_ant_bs': 128, |
|
'n_subcarriers': 64 |
|
}, |
|
'asu_campus1_v1': { |
|
'n_rows': [0, 1*int(321/20)], |
|
'n_per_row': 411, |
|
'n_ant_bs': 8, |
|
'n_subcarriers': 32 |
|
}, |
|
'asu_campus1_v2': { |
|
'n_rows': [1*int(321/20), 2*int(321/20)], |
|
'n_per_row': 411, |
|
'n_ant_bs': 8, |
|
'n_subcarriers': 64 |
|
}, |
|
'asu_campus1_v3': { |
|
'n_rows': [2*int(321/20), 3*int(321/20)], |
|
'n_per_row': 411, |
|
'n_ant_bs': 8, |
|
'n_subcarriers': 128 |
|
}, |
|
'asu_campus1_v4': { |
|
'n_rows': [3*int(321/20), 4*int(321/20)], |
|
'n_per_row': 411, |
|
'n_ant_bs': 8, |
|
'n_subcarriers': 256 |
|
}, |
|
'asu_campus1_v5': { |
|
'n_rows': [4*int(321/20), 5*int(321/20)], |
|
'n_per_row': 411, |
|
'n_ant_bs': 8, |
|
'n_subcarriers': 512 |
|
}, |
|
'asu_campus1_v6': { |
|
'n_rows': [5*int(321/20), 6*int(321/20)], |
|
'n_per_row': 411, |
|
'n_ant_bs': 8, |
|
'n_subcarriers': 1024 |
|
}, |
|
'asu_campus1_v7': { |
|
'n_rows': [6*int(321/20), 7*int(321/20)], |
|
'n_per_row': 411, |
|
'n_ant_bs': 16, |
|
'n_subcarriers': 32 |
|
}, |
|
'asu_campus1_v8': { |
|
'n_rows': [7*int(321/20), 8*int(321/20)], |
|
'n_per_row': 411, |
|
'n_ant_bs':16, |
|
'n_subcarriers': 64 |
|
}, |
|
'asu_campus1_v9': { |
|
'n_rows': [8*int(321/20), 9*int(321/20)], |
|
'n_per_row': 411, |
|
'n_ant_bs': 16, |
|
'n_subcarriers': 128 |
|
}, |
|
'asu_campus1_v10': { |
|
'n_rows': [9*int(321/20), 10*int(321/20)], |
|
'n_per_row': 411, |
|
'n_ant_bs': 16, |
|
'n_subcarriers': 256 |
|
}, |
|
'asu_campus1_v11': { |
|
'n_rows': [10*int(321/20), 11*int(321/20)], |
|
'n_per_row': 411, |
|
'n_ant_bs': 16, |
|
'n_subcarriers': 512 |
|
}, |
|
'asu_campus1_v12': { |
|
'n_rows': [11*int(321/20), 12*int(321/20)], |
|
'n_per_row': 411, |
|
'n_ant_bs': 32, |
|
'n_subcarriers': 32 |
|
}, |
|
'asu_campus1_v13': { |
|
'n_rows': [12*int(321/20), 13*int(321/20)], |
|
'n_per_row': 411, |
|
'n_ant_bs': 32, |
|
'n_subcarriers': 64 |
|
}, |
|
'asu_campus1_v14': { |
|
'n_rows': [13*int(321/20), 14*int(321/20)], |
|
'n_per_row': 411, |
|
'n_ant_bs': 32, |
|
'n_subcarriers': 128 |
|
}, |
|
'asu_campus1_v15': { |
|
'n_rows': [14*int(321/20), 15*int(321/20)], |
|
'n_per_row': 411, |
|
'n_ant_bs': 32, |
|
'n_subcarriers': 256 |
|
}, |
|
'asu_campus1_v16': { |
|
'n_rows': [15*int(321/20), 16*int(321/20)], |
|
'n_per_row': 411, |
|
'n_ant_bs': 64, |
|
'n_subcarriers': 32 |
|
}, |
|
'asu_campus1_v17': { |
|
'n_rows': [16*int(321/20), 17*int(321/20)], |
|
'n_per_row': 411, |
|
'n_ant_bs': 64, |
|
'n_subcarriers': 64 |
|
}, |
|
'asu_campus1_v18': { |
|
'n_rows': [17*int(321/20), 18*int(321/20)], |
|
'n_per_row': 411, |
|
'n_ant_bs': 64, |
|
'n_subcarriers': 128 |
|
}, |
|
'asu_campus1_v19': { |
|
'n_rows': [18*int(321/20), 19*int(321/20)], |
|
'n_per_row': 411, |
|
'n_ant_bs': 128, |
|
'n_subcarriers': 32 |
|
}, |
|
'asu_campus1_v20': { |
|
'n_rows': [19*int(321/20), 20*int(321/20)], |
|
'n_per_row': 411, |
|
'n_ant_bs': 128, |
|
'n_subcarriers': 64 |
|
}, |
|
'Boston5G_3p5_v1': { |
|
'n_rows': [812, 812 + 1*int((1622-812)/20)], |
|
'n_per_row': 595, |
|
'n_ant_bs': 8, |
|
'n_subcarriers': 32 |
|
}, |
|
'Boston5G_3p5_v2': { |
|
'n_rows': [812 + 1*int((1622-812)/20), 812 + 2*int((1622-812)/20)], |
|
'n_per_row': 595, |
|
'n_ant_bs': 8, |
|
'n_subcarriers': 64 |
|
}, |
|
'Boston5G_3p5_v3': { |
|
'n_rows': [812 + 2*int((1622-812)/20), 812 + 3*int((1622-812)/20)], |
|
'n_per_row': 595, |
|
'n_ant_bs': 8, |
|
'n_subcarriers': 128 |
|
}, |
|
'Boston5G_3p5_v4': { |
|
'n_rows': [812 + 3*int((1622-812)/20), 812 + 4*int((1622-812)/20)], |
|
'n_per_row': 595, |
|
'n_ant_bs': 8, |
|
'n_subcarriers': 256 |
|
}, |
|
'Boston5G_3p5_v5': { |
|
'n_rows': [812 + 4*int((1622-812)/20), 812 + 5*int((1622-812)/20)], |
|
'n_per_row': 595, |
|
'n_ant_bs': 8, |
|
'n_subcarriers': 512 |
|
}, |
|
'Boston5G_3p5_v6': { |
|
'n_rows': [812 + 5*int((1622-812)/20), 812 + 6*int((1622-812)/20)], |
|
'n_per_row': 595, |
|
'n_ant_bs': 8, |
|
'n_subcarriers': 1024 |
|
}, |
|
'Boston5G_3p5_v7': { |
|
'n_rows': [812 + 6*int((1622-812)/20), 812 + 7*int((1622-812)/20)], |
|
'n_per_row': 595, |
|
'n_ant_bs': 16, |
|
'n_subcarriers': 32 |
|
}, |
|
'Boston5G_3p5_v8': { |
|
'n_rows': [812 + 7*int((1622-812)/20), 812 + 8*int((1622-812)/20)], |
|
'n_per_row': 595, |
|
'n_ant_bs':16, |
|
'n_subcarriers': 64 |
|
}, |
|
'Boston5G_3p5_v9': { |
|
'n_rows': [812 + 8*int((1622-812)/20), 812 + 9*int((1622-812)/20)], |
|
'n_per_row': 595, |
|
'n_ant_bs': 16, |
|
'n_subcarriers': 128 |
|
}, |
|
'Boston5G_3p5_v10': { |
|
'n_rows': [812 + 9*int((1622-812)/20), 812 + 10*int((1622-812)/20)], |
|
'n_per_row': 595, |
|
'n_ant_bs': 16, |
|
'n_subcarriers': 256 |
|
}, |
|
'Boston5G_3p5_v11': { |
|
'n_rows': [812 + 10*int((1622-812)/20), 812 + 11*int((1622-812)/20)], |
|
'n_per_row': 595, |
|
'n_ant_bs': 16, |
|
'n_subcarriers': 512 |
|
}, |
|
'Boston5G_3p5_v12': { |
|
'n_rows': [812 + 11*int((1622-812)/20), 812 + 12*int((1622-812)/20)], |
|
'n_per_row': 595, |
|
'n_ant_bs': 32, |
|
'n_subcarriers': 32 |
|
}, |
|
'Boston5G_3p5_v13': { |
|
'n_rows': [812 + 12*int((1622-812)/20), 812 + 13*int((1622-812)/20)], |
|
'n_per_row': 595, |
|
'n_ant_bs': 32, |
|
'n_subcarriers': 64 |
|
}, |
|
'Boston5G_3p5_v14': { |
|
'n_rows': [812 + 13*int((1622-812)/20), 812 + 14*int((1622-812)/20)], |
|
'n_per_row': 595, |
|
'n_ant_bs': 32, |
|
'n_subcarriers': 128 |
|
}, |
|
'Boston5G_3p5_v15': { |
|
'n_rows': [812 + 14*int((1622-812)/20), 812 + 15*int((1622-812)/20)], |
|
'n_per_row': 595, |
|
'n_ant_bs': 32, |
|
'n_subcarriers': 256 |
|
}, |
|
'Boston5G_3p5_v16': { |
|
'n_rows': [812 + 15*int((1622-812)/20), 812 + 16*int((1622-812)/20)], |
|
'n_per_row': 595, |
|
'n_ant_bs': 64, |
|
'n_subcarriers': 32 |
|
}, |
|
'Boston5G_3p5_v17': { |
|
'n_rows': [812 + 16*int((1622-812)/20), 812 + 17*int((1622-812)/20)], |
|
'n_per_row': 595, |
|
'n_ant_bs': 64, |
|
'n_subcarriers': 64 |
|
}, |
|
'Boston5G_3p5_v18': { |
|
'n_rows': [812 + 17*int((1622-812)/20), 812 + 18*int((1622-812)/20)], |
|
'n_per_row': 595, |
|
'n_ant_bs': 64, |
|
'n_subcarriers': 128 |
|
}, |
|
'Boston5G_3p5_v19': { |
|
'n_rows': [812 + 18*int((1622-812)/20), 812 + 19*int((1622-812)/20)], |
|
'n_per_row': 595, |
|
'n_ant_bs': 128, |
|
'n_subcarriers': 32 |
|
}, |
|
'Boston5G_3p5_v20': { |
|
'n_rows': [812 + 19*int((1622-812)/20), 812 + 20*int((1622-812)/20)], |
|
'n_per_row': 595, |
|
'n_ant_bs': 128, |
|
'n_subcarriers': 64 |
|
}, |
|
'O1_3p5_v1': { |
|
'n_rows': [0*int(3852/12), 1*int(3852/12)], |
|
'n_per_row': 181, |
|
'n_ant_bs': 8, |
|
'n_subcarriers': 32 |
|
}, |
|
'O1_3p5_v2': { |
|
'n_rows': [1*int(3852/12), 2*int(3852/12)], |
|
'n_per_row': 181, |
|
'n_ant_bs': 8, |
|
'n_subcarriers': 64 |
|
}, |
|
'O1_3p5_v3': { |
|
'n_rows': [2*int(3852/12), 3*int(3852/12)], |
|
'n_per_row': 181, |
|
'n_ant_bs': 8, |
|
'n_subcarriers': 128 |
|
}, |
|
'O1_3p5_v4': { |
|
'n_rows': [3*int(3852/12), 4*int(3852/12)], |
|
'n_per_row': 181, |
|
'n_ant_bs': 8, |
|
'n_subcarriers': 256 |
|
}, |
|
'O1_3p5_v5': { |
|
'n_rows': [4*int(3852/12), 5*int(3852/12)], |
|
'n_per_row': 181, |
|
'n_ant_bs': 8, |
|
'n_subcarriers': 512 |
|
}, |
|
'O1_3p5_v6': { |
|
'n_rows': [5*int(3852/12), 6*int(3852/12)], |
|
'n_per_row': 181, |
|
'n_ant_bs': 8, |
|
'n_subcarriers': 1024 |
|
}, |
|
'O1_3p5_v7': { |
|
'n_rows': [6*int(3852/12), 7*int(3852/12)], |
|
'n_per_row': 181, |
|
'n_ant_bs': 16, |
|
'n_subcarriers': 32 |
|
}, |
|
'O1_3p5_v8': { |
|
'n_rows': [7*int(3852/12), 8*int(3852/12)], |
|
'n_per_row': 181, |
|
'n_ant_bs': 16, |
|
'n_subcarriers': 64 |
|
}, |
|
'O1_3p5_v9': { |
|
'n_rows': [8*int(3852/12), 9*int(3852/12)], |
|
'n_per_row': 181, |
|
'n_ant_bs': 16, |
|
'n_subcarriers': 128 |
|
}, |
|
'O1_3p5_v10': { |
|
'n_rows': [9*int(3852/12), 10*int(3852/12)], |
|
'n_per_row': 181, |
|
'n_ant_bs': 16, |
|
'n_subcarriers': 256 |
|
}, |
|
'O1_3p5_v11': { |
|
'n_rows': [10*int(3852/12), 11*int(3852/12)], |
|
'n_per_row': 181, |
|
'n_ant_bs': 16, |
|
'n_subcarriers': 512 |
|
}, |
|
'O1_3p5_v12': { |
|
'n_rows': [11*int(3852/12), 12*int(3852/12)], |
|
'n_per_row': 181, |
|
'n_ant_bs': 32, |
|
'n_subcarriers': 32 |
|
}, |
|
'O1_3p5_v13': { |
|
'n_rows': [12*int(3852/12)+0*int(1351/10), 12*int(3852/12)+1*int(1351/10)], |
|
'n_per_row': 361, |
|
'n_ant_bs': 32, |
|
'n_subcarriers': 64 |
|
}, |
|
'O1_3p5_v14': { |
|
'n_rows': [12*int(3852/12)+1*int(1351/10), 12*int(3852/12)+2*int(1351/10)], |
|
'n_per_row': 181, |
|
'n_ant_bs': 32, |
|
'n_subcarriers': 128 |
|
}, |
|
'O1_3p5_v15': { |
|
'n_rows': [12*int(3852/12)+2*int(1351/10), 12*int(3852/12)+3*int(1351/10)], |
|
'n_per_row': 181, |
|
'n_ant_bs': 32, |
|
'n_subcarriers': 256 |
|
}, |
|
'O1_3p5_v16': { |
|
'n_rows': [12*int(3852/12)+3*int(1351/10), 12*int(3852/12)+4*int(1351/10)], |
|
'n_per_row': 181, |
|
'n_ant_bs': 64, |
|
'n_subcarriers': 32 |
|
}, |
|
'O1_3p5_v17': { |
|
'n_rows': [12*int(3852/12)+4*int(1351/10), 12*int(3852/12)+5*int(1351/10)], |
|
'n_per_row': 181, |
|
'n_ant_bs': 64, |
|
'n_subcarriers': 64 |
|
}, |
|
'O1_3p5_v18': { |
|
'n_rows': [12*int(3852/12)+5*int(1351/10), 12*int(3852/12)+6*int(1351/10)], |
|
'n_per_row': 181, |
|
'n_ant_bs': 64, |
|
'n_subcarriers': 128 |
|
}, |
|
'O1_3p5_v19': { |
|
'n_rows': [12*int(3852/12)+6*int(1351/10), 12*int(3852/12)+7*int(1351/10)], |
|
'n_per_row': 181, |
|
'n_ant_bs': 128, |
|
'n_subcarriers': 32 |
|
}, |
|
'O1_3p5_v20': { |
|
'n_rows': [12*int(3852/12)+7*int(1351/10), 12*int(3852/12)+8*int(1351/10)], |
|
'n_per_row': 181, |
|
'n_ant_bs': 128, |
|
'n_subcarriers': 64 |
|
}, |
|
'city_0_newyork_v16x64': { |
|
'n_rows': 109, |
|
'n_per_row': 291, |
|
'n_ant_bs': 16, |
|
'n_subcarriers': 64 |
|
}, |
|
'city_1_losangeles_v16x64': { |
|
'n_rows': 142, |
|
'n_per_row': 201, |
|
'n_ant_bs': 16, |
|
'n_subcarriers': 64 |
|
}, |
|
'city_2_chicago_v16x64': { |
|
'n_rows': 139, |
|
'n_per_row': 200, |
|
'n_ant_bs': 16, |
|
'n_subcarriers': 64 |
|
}, |
|
'city_3_houston_v16x64': { |
|
'n_rows': 154, |
|
'n_per_row': 202, |
|
'n_ant_bs': 16, |
|
'n_subcarriers': 64 |
|
}, |
|
'city_4_phoenix_v16x64': { |
|
'n_rows': 198, |
|
'n_per_row': 214, |
|
'n_ant_bs': 16, |
|
'n_subcarriers': 64 |
|
}, |
|
'city_5_philadelphia_v16x64': { |
|
'n_rows': 239, |
|
'n_per_row': 164, |
|
'n_ant_bs': 16, |
|
'n_subcarriers': 64 |
|
}, |
|
'city_6_miami_v16x64': { |
|
'n_rows': 199, |
|
'n_per_row': 216, |
|
'n_ant_bs': 16, |
|
'n_subcarriers': 64 |
|
}, |
|
'city_7_sandiego_v16x64': { |
|
'n_rows': 207, |
|
'n_per_row': 176, |
|
'n_ant_bs': 16, |
|
'n_subcarriers': 64 |
|
}, |
|
'city_8_dallas_v16x64': { |
|
'n_rows': 207, |
|
'n_per_row': 190, |
|
'n_ant_bs': 16, |
|
'n_subcarriers': 64 |
|
}, |
|
'city_9_sanfrancisco_v16x64': { |
|
'n_rows': 196, |
|
'n_per_row': 206, |
|
'n_ant_bs': 16, |
|
'n_subcarriers': 64 |
|
}} |
|
return row_column_users |