Channel Models from Datasets

In this notebook, you will learn how to create a channel model from agenerator. This can be used, e.g., to import datasets of channel impulse responses.

GPU Configuration and Imports

[1]:
importosifos.getenv("CUDA_VISIBLE_DEVICES")isNone:gpu_num=0# Use "" to use the CPUos.environ["CUDA_VISIBLE_DEVICES"]=f"{gpu_num}"os.environ['TF_CPP_MIN_LOG_LEVEL']='3'# Import Sionnatry:importsionna.phyexceptImportErrorase:importsysif'google.colab'insys.modules:# Install Sionna in Google Colabprint("Installing Sionna and restarting the runtime. Please run the cell again.")os.system("pip install sionna")os.kill(os.getpid(),5)else:raisee# Configure the notebook to use only a single GPU and allocate only as much memory as needed# For more details, see https://www.tensorflow.org/guide/gpuimporttensorflowastfgpus=tf.config.list_physical_devices('GPU')ifgpus:try:tf.config.experimental.set_memory_growth(gpus[0],True)exceptRuntimeErrorase:print(e)# Avoid warnings from TensorFlowtf.get_logger().setLevel('ERROR')importnumpyasnpimporth5pyconfig=sionna.phy.configconfig.seed=42# Set seed for reproducible random number generation

Simulation Parameters

[2]:
num_rx=2num_rx_ant=2num_tx=1num_tx_ant=8num_time_steps=100num_paths=10

Creating a Simple Dataset

To illustrate how to load dataset, we will first create one.

The next cell creates a very small HDF5 file storing Gaussian distributed i.i.d. path coefficients and uniformly distributed i.i.d. path delays.

[3]:
# Number of examples in the datasetdataset_size=1000# Random path coefficientsa_shape=[dataset_size,num_rx,num_rx_ant,num_tx,num_tx_ant,num_paths,num_time_steps]a=(config.np_rng.normal(size=a_shape)+1j*config.np_rng.normal(size=a_shape))/np.sqrt(2)# Random path delaystau=config.np_rng.uniform(size=[dataset_size,num_rx,num_tx,num_paths])
[4]:
filename='my_dataset.h5'hf=h5py.File(filename,'w')hf.create_dataset('a',data=a)hf.create_dataset('tau',data=tau)hf.close()

Generators

The first step to load a dataset is to create agenerator. A generator is a callable object, i.e., a function or a class that implements the__call__() method, and that behaves like an iterator.

The next cell shows how to create a generator that parses an HDF5 file storing path coefficients and delays. Note that how the HDF5 file is parsed depends on its structure. The following generator is specific to the dataset previously created.

If you have another dataset, you will need to change the way it is parsed in the generator. The generator can also carry out any type of desired pre-processing of your data, e.g., normalization.

[5]:
classHD5CIRGen:def__init__(self,filename):self.filename=filenamedef__call__(self):withh5py.File(self.filename,'r')ashf:foriminzip(hf["a"],hf["tau"]):a=im[0]tau=im[1]# One could do some preprocessing on the dataset here# ...yieldim
[6]:
generator=HD5CIRGen(filename)

We can use the generator to sample the first 5 items of the dataset:

[7]:
i=0for(a,tau)ingenerator():print(a.shape)print(tau.shape)i=i+1ifi==5:break
(2, 2, 1, 8, 10, 100)(2, 1, 10)(2, 2, 1, 8, 10, 100)(2, 1, 10)(2, 2, 1, 8, 10, 100)(2, 1, 10)(2, 2, 1, 8, 10, 100)(2, 1, 10)(2, 2, 1, 8, 10, 100)(2, 1, 10)

Let us create a channel model from this dataset:

[8]:
fromsionna.phy.channelimportCIRDatasetbatch_size=64# The batch_size cannot be changed after the creation of the channel modelchannel_model=CIRDataset(generator,batch_size,num_rx,num_rx_ant,num_tx,num_tx_ant,num_paths,num_time_steps)

We can now sample from this dataset in the same way as we would from a stochastic channel model:

[9]:
# Note that the arguments batch_size, num_time_steps, and smapling_frequency# of the __call__ function are ignored as they are already specified by the dataset.a,tau=channel_model()
[10]:
print(a.shape)print(a.dtype)print(tau.shape)print(tau.dtype)
(64, 2, 2, 1, 8, 10, 100)<dtype: 'complex64'>(64, 2, 1, 10)<dtype: 'float32'>

Use the Channel Model for OFDM Transmissions

The following code demonstrates how you can use the channel model to generate channel frequency responses that can be used for the simulation of communication system based on OFDM.

[11]:
# Create an OFDM resource grid# Each time step is assumed to correspond to one OFDM symbol over which it is constant.resource_grid=sionna.phy.ofdm.ResourceGrid(num_ofdm_symbols=num_time_steps,fft_size=76,subcarrier_spacing=15e3,num_tx=num_tx,num_streams_per_tx=num_tx_ant)
[12]:
ofdm_channel=sionna.phy.channel.GenerateOFDMChannel(channel_model,resource_grid)
[13]:
# Generate a batch of frequency responses# Shape: [batch size, num_rx, num_rx_ant, num_tx, num_tx_ant, num_ofdm_symbols, num_subcarriers]h_freq=ofdm_channel()print(h_freq.shape)
(64, 2, 2, 1, 8, 100, 76)
[14]:
# Delete dataset%rm my_dataset.h5