DeepMIMO v3 - Python

DeepMIMO v3 Features

    • Includes all features of DeepMIMO v1 and v2
    • Optimized memory requirements and generation speed

    • Antenna panel orientation and field of view

    • Dual polar antenna (when available in the scenario)
    • Doppler shift for dynamic scenarios

    • Faster and more efficient data structure

    • Available in Matlab & Python

Table of Contents

How Does it Work?

DeepMIMO v3 dataset generator processes the input ray-tracing file based on the parameters’ values specified in the DeepMIMO parameters file to generate the output dataset

 

Check the detailed documentation below for more information about the DeepMIMO v3 parameters and outputs

Download and Installation

Step 1: (Generator Package)

  • Install DeepMIMOv3 package from pip by
				
					pip install DeepMIMOv3
				
			

Step 2: (Scenario)

  • Select and download a scenario from the scenarios page.
  • Extract scenario folder into a dataset folder.

Step 3: (Parameter Configuration and Dataset Generation)

  • Start a new python script as follows
				
					import DeepMIMOv3

# Load the default parameters
parameters = DeepMIMOv3.default_params() 

# Set scenario name
parameters['scenario'] = 'O1_60' 

# Set the main folder containing extracted scenarios
parameters['dataset_folder'] = r'C:\Users\xxx\Desktop\scenarios'

# Generate data
dataset = DeepMIMOv3.generate_data(parameters)
				
			
  • Configure the parameters (For details, please refer to the input/output parameters and examples below)
  • Run the code to generate the dataset!

Input Parameters

dataset_folder string


Folder of the unzipped scenarios. Inside the dataset folder, each scenario should have their own folder with the dataset files inside.

				
					# If the O1_60 scenario is extracted in "C:/dataset/" folder, set
parameters['dataset_folder'] = r'C:/dataset/'

# The default value is set as './Raytracing_scenarios/'
				
			

scenario string


Name of the scenario to be loaded. To check and download available scenarios, please check the scenarios page.

				
					# To load scenario O1_60, set the dictionary variable by
parameters['scenario'] = 'O1_60'
				
			

Dynamic scenario settings – dynamic_scenario_scenes numpy array

 

[For dynamic scenarios] Determines the dynamic scenario scenes to be loaded. 
				
					# To load the first five scenes, set
parameters['dynamic_scenario_scenes'] = np.arange(5)
				
			

num_paths integer in [1, 25]

 

Maximum number of paths to be considered (a value between 1 and 25), e.g., choose 1 if you are only interested in the strongest path 

				
					# To only include 10 strongest paths in the channel computation, set
parameters['num_paths'] = 10
				
			

active_BS integer numpy array

 

The ID of the basestations to be included in the dataset. The basestation IDs can be selected from the scenario description. In the final dataset, the activated basestations IDs are renumbered in the same order starting from 1 to the number of active basestations.

				
					# To activate only the first basestation, set
parameters['active_BS'] = np.array([1])
				
			
				
					# To activate the basestations 1, 5, and 8, set
parameters['active_BS'] = np.array([1, 5, 8])
				
			

user_rows numpy array

 

The rows of users to be generated. 

Specifically, the row of users in the given array are selected.

				
					# To activate the user rows 1-5, set
parameters['user_rows'] = np.arange(5)
				
			

user_subsampling float in the range (0,1)

 

This parameter determines the ratio of the users to be activated within the active rows determined by the parameters row_subsampling, user_row_first and user_row_last. In each row, it allows random sampling of round(user_subsampling*number_of_users_in_row) users for activation.

The value 1 activates all the users within the active rows.

				
					# To activate the half of the users in each selected row randomly, set
parameters['user_subsampling'] = 0.5
				
			

User antenna – shape integer numpy array, spacing floatrotation float numpy array, FoV float numpy array, radiation_pattern string

 

The user antenna parameters. shape is a 2-dimensional array of number of antenna elements in horizontal-vertical dimensions. The antenna spacing between array elements is determined as (spacing x wavelength).

 

An antenna array (UPA) of (shape[0] x shape[1]) elements is adopted for each active UE. With no rotation ([0, 0, 0]), the antenna array is directed towards +x lying on the y axis.

 

If the rotation is defined, the antennas are rotated with the angles defined by rotation[0], rotation[1] and rotation[2] around the x-y-z axes from the initial orientation. For a uniformly random user rotation, define rotation by a 3×2 numpy matrix in the form of [[x_min, x_max], [y_min, y_max], [z_min, z_max]]. 

 

 

The FoV parameter allows to adjust field of view of in horizontal and vertical directions. Specifically, the antenna’s horizontal and vertical field of views are limited to FoV[0] and FoV[1] degrees.

 

There are two available radiation pattern options:

  • ‘isotropic’ – This option does not apply any extra radiation gain to the ray-tracing scenario.
  • ‘halfwave-dipole’ – This option applies halfwave dipole antenna radiation pattern. To generate the same results with DeepMIMOv1 scenarios, use this option.

If the antenna pattern is not defined, it is set as ‘isotropic’.

				
					# To adopt a 4 element ULA in y direction with 120 degrees horizontal 180 degrees vertical FoV, set
parameters['ue_antenna']['shape'] = np.array([4, 1])
parameters['ue_antenna']['rotation'] = np.array([0, 0, 30]) # Rotate array 30 degrees around z-axis
parameters['ue_antenna']['FoV'] = np.array([120, 180])
				
			
				
					# To adopt a 4x2 UPA in y-z directions with spacing 0.5*wavelength, set
parameters['ue_antenna']['shape'] = np.array([4, 2])
parameters['ue_antenna']['spacing'] = 0.5
				
			
				
					# To rotate UEs 30 degrees around z-axis, set
parameters['ue_antenna']['rotation'] = np.array([0, 0, 30]) # Rotate array 30 degrees in z-axis
				
			
				
					# To (uniformly) randomly rotate each UE 0-30, 30-60 and 60-90 degrees around x-y-z axes, set
parameters['ue_antenna']['rotation'] = np.array([[0, 30], [30, 60], [60, 90])
# After the dataset is generated, the rotation of UE i can be accessed at
parameters['ue_antenna']['rotation'][i]
				
			
				
					# To adopt an halfwave Dipole antenna pattern, set
parameters['ue_antenna']['radiation_pattern'] = 'halfwave-dipole' 
				
			

Basestation antenna – shape integer numpy array, spacing float, rotation float numpy array,  FoV float numpy array, radiation_pattern string

 

The basestation antenna parameters. shape is a 2-dimensional array of number of antenna elements in horizontal-vertical dimensions. The antenna spacing between array elements is determined as (spacing x wavelength).

 

An antenna array (UPA) of (shape[0] x shape[1]) elements is adopted for each active BS. An antenna array (UPA) of (shape[0] x shape[1]) elements is adopted for each active UE. With no rotation ([0, 0, 0]), the antenna array is directed towards +x lying on the y axis.

 

If the rotation is defined, the antennas are rotated with the angles defined by rotation[0], rotation[1] and rotation[2] around the x-y-z axes from the initial orientation.

 

The FoV parameter allows to adjust field of view of in horizontal and vertical directions. Specifically, the antenna’s horizontal and vertical field of views are limited to FoV[0] and FoV[1] degrees.

 

 

There are two available radiation pattern options:

  • ‘isotropic’ – This option does not apply any extra radiation gain to the ray-tracing scenario.
  • ‘halfwave-dipole’ – This option applies halfwave dipole antenna radiation pattern. To generate the same results with DeepMIMOv1 scenarios, apply this option.

If the antenna pattern is not defined, it is set as ‘isotropic’.2horizontal-vertical

				
					# To adopt a 4 element ULA in y direction, set
parameters['bs_antenna']['shape'] = np.array([4, 1])
				
			
				
					# To adopt a 4x2 UPA in y-z directions with spacing 0.5*wavelength, set
parameters['bs_antenna']['shape'] = np.array([4, 2])
parameters['bs_antenna']['spacing'] = 0.5
				
			
				
					# To rotate BSs 30 degrees around z-axis, set
parameters['bs_antenna']['rotation'] = np.array([0, 0, 30]) # Rotate array 30 degrees in z-axis
				
			
				
					# To adopt an halfwave Dipole antenna pattern, set
parameters['ue_antenna']['radiation_pattern'] = 'halfwave-dipole' 
				
			

If there are multiple active basestations, different antennas can be assigned to those by giving a list of antenna dictionaries as the input. For instance, the following example can be utilized with 3 BSs:

				
					# Consider 3 active basestations
parameters['active_BS'] = np.array([1, 5, 8])

# Define 3 different antennas:
antenna1 = {'shape': np.array([1, 1]),
            'spacing': 0.5,
            'rotation': np.array([0, 30, 0])}
antenna2 = {'shape': np.array([2, 2]),
            'spacing': 0.5,
            'rotation': np.array([-15, 0, 30])}
antenna3 = {'shape': np.array([3, 4]),
            'spacing': 0.5,
            'rotation': np.array([-15, 0, 0])}
# Assign the defined antennas to the active basestations:
parameters['bs_antenna'] = [antenna1, antenna2, antenna3]
				
			

enable_BS2BS boolean

 

Enable (1) or disable (0) generation of the channels between basestations

				
					# To generate basestation to basestation output variables, set
parameters['enable_BS2BS'] = True
				
			

enable_doppler boolean

 

Enable (1) or disable (0) generation of the channels with the Doppler shift (if available in the scenario)

				
					# To generate channels with Doppler shift (when available), set 
parameters['enable_doppler '] = True
				
			

enable_dual_polar boolean

 

Enable (1) or disable (0) generation of the dual polar antennas (if available in the scenario)

Note: The number of antennas will be doubled if this option is enabled and available since each antenna position will have two antennas with V and H cross polarization.

				
					# To generate dual polar channels (when available), set
parameters['enable_dual_polar'] = True
				
			

OFDM_channels boolean

 

(0) activate time domain (TD) channel impulse response generation for non-OFDM systems

(1) activate frequency domain (FD) channel generation for OFDM systems

				
					# For OFDM channels, set
parameters['activate_OFDM'] = 1
				
			
				
					# For time-domain channels, set
parameters['activate_OFDM'] = 0
				
			

OFDM – bandwidth float

Total bandwidth of the channel in GHz. 

				
					# To generate channels at 50 MHz bandwidth, set
parameters['OFDM']['bandwidth'] = 0.05
				
			

OFDM – subcarriers integer

 

Number of OFDM subcarriers

				
					# To generate OFDM channels with 256 subcarriers, set
parameters['OFDM']['subcarriers'] = 256
				
			

OFDM – selected_subcarriers numpy array of integers

 

The constructed channels will be calculated only at the sampled subcarriers to reduce the size of the dataset. Only the subcarriers corresponding to the indices in selected_subcarriers will be generated. 

For selected_subcarriers=np.array([0, 8, 16, 24, 32]) , the subcarriers {0, 8, 16, 24, 32} are subsampled from the available subcarriers {1, 2, …, num_OFDM}.

				
					# To sample first 64 subcarriers by 8 spacing between each, set
parameters['OFDM']['selected_subcarriers'] = np.arange(0, 64, 8)
				
			

OFDM – RX_filter boolean

 

The boolean options do the following:

(0) Applies no receive filter

(1) Activates ideal receive LPF: This option convolves channel paths with sinc at the time domain before taking FFT for the frequency domain conversion.

				
					# For an ideal LPF (rectangular in frequency domain and sinc in time domain), set
parameters['OFDM']['RX_filter'] = 1
				
			

Default Input Parameters

The default input parameters can be loaded in three different ways:

Load the default parameter dictionary using the python package:

				
					parameters = DeepMIMOv3.default_params()
				
			

Directly defining a dictionary of all the parameters:

Adding elements to a dictionary:

				
					parameters = { 'dataset_folder': './Raytracing_scenarios',
                'scenario': 'O1_60',
                'dynamic_scenario_scenes': np.array([1]),
                'num_paths': 5,
                'active_BS': np.array([1]),
                'user_rows': np.array([1]),
                'user_subsampling': 1,
                'bs_antenna':
                    {
                     'shape': np.array([8, 4]),
                     'spacing': 0.5,
                     'rotation': np.array([0, 0, 0]),
                     'FoV': np.array([360, 180]),
                     'radiation_pattern': 'isotropic'
                     },
                'ue_antenna':
                    {
                     'shape': np.array([4, 2]),
                     'spacing': 0.5,
                     'rotation': np.array([0, 0, 0]),
                     'FoV': np.array([360, 180]),
                     'radiation_pattern': 'isotropic'
                    },
                'enable_doppler': 0,
                'enable_dual_polar': 0,
                'enable_BS2BS': 1,
                'OFDM_channels': 1,
                'OFDM': 
                    {
                     'subcarriers': 512,
                     'selected_subcarriers': np.array([0]),
                     'bandwidth': 0.05,
                     'RX_filter': 0
                    }
            }
				
			
				
					parameters = {}

parameters['dataset_folder'] = './Raytracing_scenarios'
parameters['scenario'] = 'O1_60'
parameters['dynamic_scenario_scenes'] = np.array([1])
parameters['num_paths'] = 5
parameters['active_BS'] = np.array([1])
parameters['user_rows'] = np.array([1])
parameters['user_subsampling'] = 1

parameters['bs_antenna']['shape'] = np.array([8, 4])
parameters['bs_antenna']['spacing'] = 0.5
# parameters['bs_antenna']['rotation'] = np.array([0, 0, 0])
parameters['bs_antenna']['FoV'] = np.array([360, 180])
parameters['bs_antenna']['radiation_pattern'] = 'isotropic'

parameters['ue_antenna']['shape'] = np.array([8, 4])
parameters['ue_antenna']['spacing'] = 0.5
# parameters['ue_antenna']['rotation'] = np.array([0, 0, 0])
parameters['ue_antenna']['FoV'] = np.array([360, 180])
parameters['ue_antenna']['radiation_pattern'] = 'isotropic'

parameters['enable_doppler'] = 0
parameters['enable_dual_polar'] = 0
parameters['enable_BS2BS'] = 1

parameters['OFDM_channels'] = 1 # Frequency (OFDM) or time domain channels
parameters['OFDM']['subcarriers'] = 512
parameters['OFDM']['selected_subcarriers'] = np.array([0])
parameters['OFDM']['bandwidth'] = 0.05
parameters['OFDM']['RX_filter'] = 0

				
			

Output Parameters

Visualization Functions

				
					from DeepMIMOv3.visualization import plot_LoS_status, plot_coverage
				
			

plot_LoS_status(bs_location, user_locations, user_LoS, scat_size=’auto’)

Description

Scatters the users and one basestation and colors the users based on their line-of-sight status.

Arguments

  • bs_location – numpy array
    1-D array with the xy position of the basestation.
  • user_locations –  numpy array
    Matrix containing user locations across rows and xy positions across columns. Expected shape: <n_users> by 2
  • user_LoSnumpy array
    1-D array with the LoS status of each user. The length should match the number of users in user_locations.
  • scat_sizefloat, optional
    Size of the scatter points.  If set to ‘auto’, the scatter marker size is set based on the point density following the sz = 1 / (100 * point_density), with point_density = n_users / area. The default is ‘auto’.

Returns: None

				
					# Plotting LoS status for all users
bs_idx = 0
bs_location = dataset[bs_idx]['location']
LoS_status = dataset[bs_idx]['user']['LoS']
user_location = dataset[bs_idx]['user']['location']
plot_LoS_status(bs_location, user_location, LoS_status)
				
			

plot_coverage(rxs, cov_map, dpi=300, figsize=(6,4), cbar_title=None, title=False, scat_sz=.5, bs_pos=None, bs_ori=None,
                           legend=False, lims=None, proj_3D=False, equal_aspect=False, tight=True, cmap=’viridis’)

Description

This function scatters user positions <rxs> and colors them based on the <cov_map>.

Arguments

  • rxsnumpy array
    User position array. Dimensions: [n_users, 3].

  • cov_maptuple, list or numpy array
    1-D feature map based on which to color the user positions. The length should match the first dimension of rxs.

  • dpiint, optional
    Density per pixel (i.e., resolution). The default is 300.

  • figsizetuple, optional
    Figure (horizontal size, vertical size) in inches. The default is (6,4).

  • cbar_titlestring, optional
    Title/text for the colorbar. Hide title if None, empty string or False. The default is None.

  • titlestring, optional
    Title of the plot. Hide title if None, empty string or False. The default is False.

  • scat_szfloat, optional
    Scatter marker size. The default is .5.

  • bs_pos tuple, list, or numpy array, optional
    Basestation xyz coordinates for the position. If valid (not None), it puts an ‘x’ marker in that [x,y (,z)] position. Requires 3 values in case of 3D plot (proj_3D argument). The default is None.

  • bs_orituple, list, or numpy array, optional
    Basestation orientation. If valid (not None), it draws a line from the BS position in this direction.
    Orientation/Rotation is around [x,y,z] following the right-hand rule.
    [0,0,0] = Antenna pointing towards +x
    [0,0,90] = Antenna pointing towards +y
    [0,90,0] = Antenna pointing towards -z
    Another way of interpreting (when x rotation is 0):
    z-rotation is azimuth (where 0 is +x)
    y-rotation is elevation/tilt (where 0 is the horizon)
    The default is None.

  • legendbool, optional
    Whether to include a plot legend. The default is False.

  • limstuple, list, or numpy array, optional
    Coverage color limits. Helps setting the limits of the colormap and colorbar.
    The default is None.

  • proj_3Dbool, optional
    Whether to make a 3D or 2D plot. Set to True for 3D and False for 2D. The default is False.

  • equal_aspectbool, optional
    Whether to set axis with equal scale. Note: Complicated in 3D visualizations. The default is False.

  • tightbool, optional
    Whether to set the plot xy(z) limits automatically based on the values so that the axis is maximally used, and no data is omitted. The default is True.

  • cmap – string, optional
    Colormap string identifier for matplotlib. See available colormaps in matplotlib colormaps. The default is ‘viridis’.

Returns

  • figmatplotlib figure
    fig as obtained from fig, ax = plt.subplots()
    The motivation behind returning these elements is allowing editing and saving, before displaying. For this reason, plt.show() is not used inside this function.
  • axmatplotlib axes
    ax as in fig, ax = plt.subplots()
  • cbarmatplotlib colorbar
    The colorbar that is associated with the coverage map.
				
					# Automatic 2D/3D plot
var_names = ['LoS', 'pathloss', 'distance']
for var_name in var_names:
    plot_coverage(dataset[0]['user']['location'], dataset[0]['user'][var_name], 
                  bs_pos=dataset[0]['location'], cbar_title=var_name, proj_3D=False)
				
			
				
					# Plot all path parameters
var_names = ['DoD_phi', 'DoD_theta', 'DoA_phi', 'DoA_theta', 'ToA', 'phase', 'power']
n_users = dataset[0]['user']['paths'].shape[0]
plt_map = np.zeros(n_users) * np.nan # set NaN to users with no paths 
for var_name in var_names:
    plt_map = [dataset[0]['user']['paths'][i][var_name][0] 
               if dataset[0]['user']['paths'][i]['num_paths'] else np.nan for i in range(n_users)]
    plot_coverage(dataset[0]['user']['location'], plt_map, bs_pos=data['location'], 
                  bs_ori=parameters['bs_antenna']['rotation']*np.pi/180,
                  proj_3D=False, title=var_name, cbar_title=var_name)
				
			

Utility Functions

				
					from DeepMIMOv3.utils import steering_vec, uniform_sampling, trim_by_idx, \
                             LinearPath, get_idxs_in_xy_box
				
			

steering_vec(array, phi=0, theta=0, spacing=0.5)

Description

Creates the array steering vector for uniform (linear and rectangular) arrays.

Arguments

  • arraytuple, list, or numpy array
    Number of [elements along the horizontal, elements along the vertical]
  • phifloat, optional
    Azimuth angle in degrees. 0 azimuth is normal to the array. Positive azimuth points beams to the right. The default is 0.
  • thetafloat, optional
    Elevation angle in degrees. 0 elevation is the horizon (normal to the array). Positive elevation tilts the beam downwards. The default is 0.
  • spacingfloat, optional
    Antenna spacing in wavelengths. The default is 0.5.

Returns

  • steering_vectornumpy.ndarray
    The normalized array response vector.
				
					# Make a codebook matrix with 25 beam steering vectors from -60º to 60º azimuth
n_beams = 25
beam_angles = np.around(np.linspace(-60, 60, n_beams), 2)
F1 = np.array([steering_vec(parameters['bs_antenna']['shape'], phi=azi, 
                            spacing=parameters['bs_antenna']['spacing']).squeeze()
               for azi in beam_angles])
# F1 is n_beams x n_ant
				
			

uniform_sampling(sampling_div, n_rows, users_per_row)

Description

Returns indices of users at uniform steps/intervals. Note: Commonly used with  trim_by_idx().

Arguments

  • stepslist
    Step size along x and y dimensions. The list should have 2 elements only. Examples:
    [1,1] = indices of all users
    [1,2] = same number of users across x, one every two users along y. Results: half the users.
    [2,2] = takes one user every 2 users (step=2), along x and y. Results: 1/4 the total users
  • n_rowsint
    Number of rows in the generated dataset.  Necessary for indexing users.
  • users_per_rowint
    Number of users per row in the generated dataset.
    Necessary for indexing users.

Returns

  • data_indices – list
    List of undersampled indices.
				
					# Select one every four indices across x and y directions. Result 16x less indices
uniform_idxs = uniform_sampling([4,4], n_rows=len(parameters['user_rows']), users_per_row=411)
# The values <n_rows> and  <users_per_row> should be acquired from the scenario page.
				
			

trim_by_idx(dataset, idxs)
Description

Returns a DeepMIMO dataset (dictionary) with only the selected user indices.

Arguments

  • datasetDeepMIMO dataset (dictionary)
    A dataset as the output of DeepMIMO.generate_data()
  • idxslist or array
    List of selected indices.

Returns

  • dataset_tDeepMIMO dataset (dictionary)
    Trimmed dataset.
				
					# Trim dataset without regenerating. 
dataset_t = trim_by_idx(dataset, uniform_idxs) # uniform_idxs obtained from uniform_sampling(.)
				
			

get_idxs_in_xy_box(data_pos, x_min, x_max, y_min, y_max):
Description
Obtains the indices of <data_pos> that lie between the xy limits.

Arguments

  • data_posnumpy array
    Array with all positions to choose from – often all the positions in the dataset. Dimensions: [n_positions, 2]
  • x_minfloat
    Minimum x limit. Only positions where x > x_min have their indices returned.
  • x_maxfloat
    Maximum x limit. Only positions where x < x_max have their indices returned.
  • y_minfloat
    Minimum y limit. Only positions where y > y_min have their indices returned.
  • y_maxfloat
    Maximum y limit. Only positions where y < y_max have their indices returned.

Returns

  • idxs_in_boxnumpy array
    Indices of the positions in <data_pos> that are within the defined min-max box.
				
					# obtain the indices of the users in the zone
idxs_in_box = get_idxs_in_xy_box(data['user']['location'], 
                                 x_min=-100, x_max=-60, y_min=0, y_max=40)

# show map
plot_coverage(data['user']['location'], data['user']['LoS'],
              title='LoS status with selected users', cbar_title='LoS status')

# show selected users in the map
plt.scatter(data['user']['location'][idxs_in_box,0], 
            data['user']['location'][idxs_in_box,1], 
            label='box A', s=2, lw=.1, alpha=.1)
				
			

class LinearPath()

Description
Defines a linear path of features and positions.

Arguments

  • deepmimo_datasetDeepMIMO dataset
    A dataset generated from  DeepMIMO.generate_data(.)
  • first_posnumpy array
    [x, y, (z)] position of the start of the linear path.
  • last_posnumpy array
    [x, y, (z)] position of the end of the linear path.
    resfloat, optional
    Resolution [in meters]. The same as providing n_steps. The default is 1.
  • n_stepsint, optional
    Number of positions / samples between first and last position (including these positions). If False, use the resolution parameter <res>. The default is False.
  • filter_repeatedbool, optional
    Whether to eliminate repeated positions.
    Repeated positions happen when a path is oversampled or the closest
    position in the dataset repeats for a set of path positions. If True, the repeated positions are removed. If n_steps is larger than the number of unique positions and this is set to True, then n_steps is set to the number of unique positions. The default is True.

For more information, see the class definition here.

				
					# Create a linear path
linpath = LinearPath(dataset[0], first_pos=[100, 90], last_pos=[-50, 90], n_steps=75)

# Show it on the map
plot_coverage(dataset[0]['user']['location'], dataset[0]['user']['LoS'], 
              title='LoS status with Linear Path', cbar_title='LoS status')
plt.scatter(linpath.pos[:,0], linpath.pos[:,1], c='blue', label='linear path')

# Plot features along the path
for var_name in linpath.get_feature_names():
    plt.plot(getattr(linpath, var_name), ls='-',  c='blue', marker='*', markersize=7)
    plt.xlabel('position index along the path')
    plt.ylabel(f'{var_name}')
    plt.grid()
    plt.show()

				
			

Examples