anomaly-detection-material-parameters-calibration

Sionna param calibration (research proj)
git clone https://git.ea.contact/anomaly-detection-material-parameters-calibration
Log | Files | Refs | README

carrier_config.py (8408B)


      1 #
      2 # SPDX-FileCopyrightText: Copyright (c) 2021-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
      3 # SPDX-License-Identifier: Apache-2.0
      4 #
      5 """Carrier configuration for the nr (5G) sub-package of the Sionna library.
      6 """
      7 # pylint: disable=line-too-long
      8 
      9 from .config import Config
     10 
     11 class CarrierConfig(Config):
     12     """
     13     The CarrierConfig objects sets parameters for a specific OFDM numerology,
     14     as described in Section 4 [3GPP38211]_.
     15 
     16     All configurable properties can be provided as keyword arguments during the
     17     initialization or changed later.
     18 
     19     Example
     20     -------
     21     >>> carrier_config = CarrierConfig(n_cell_id=41)
     22     >>> carrier_config.subcarrier_spacing = 30
     23     """
     24     def __init__(self, **kwargs):
     25         self._name = "Carrier Configuration"
     26         super().__init__(**kwargs)
     27         self.check_config()
     28 
     29     #-----------------------------#
     30     #---Configurable parameters---#
     31     #-----------------------------#
     32 
     33     #---n_cell_id---#
     34     @property
     35     def n_cell_id(self):
     36         r"""
     37         int, 1 (default) | [0,...,1007] : Physical layer cell identity
     38             :math:`N_\text{ID}^\text{cell}`
     39         """
     40         self._ifndef("n_cell_id", 1)
     41         return self._n_cell_id
     42 
     43     @n_cell_id.setter
     44     def n_cell_id(self, value):
     45         assert value in range(1008), \
     46         "n_cell_id must be in the range from 0 to 1007"
     47         self._n_cell_id = value
     48 
     49     #---cyclic_prefix---#
     50     @property
     51     def cyclic_prefix(self):
     52         """
     53         str, "normal" (default) | "extended" : Cyclic prefix length
     54 
     55             The option "normal" corresponds to 14 OFDM symbols per slot, while
     56             "extended" corresponds to 12 OFDM symbols. The latter option is
     57             only possible with a `subcarrier_spacing` of 60 kHz.
     58         """
     59         self._ifndef("cyclic_prefix", "normal")
     60         return self._cyclic_prefix
     61 
     62     @cyclic_prefix.setter
     63     def cyclic_prefix(self, value):
     64         assert value in ["normal", "extended"], "Invalid cyclic prefix"
     65         self._cyclic_prefix = value
     66 
     67     #---subcarrier_spacing---#
     68     @property
     69     def subcarrier_spacing(self):
     70         r"""
     71         float, 15 (default) | 30 | 60 | 120 | 240 | 480 | 960 : Subcarrier
     72             spacing :math:`\Delta f` [kHz]
     73         """
     74         self._ifndef("subcarrier_spacing", 15)
     75         return self._subcarrier_spacing
     76 
     77     @subcarrier_spacing.setter
     78     def subcarrier_spacing(self, value):
     79         assert value in [15, 30, 60, 120, 240, 480, 960], \
     80             "Invalid subcarrier spacing"
     81         self._subcarrier_spacing = value
     82 
     83     #---n_size_grid---#
     84     @property
     85     def n_size_grid(self):
     86         r"""
     87         int, 4 (default) | [1,...,275] : Number of resource blocks in the
     88             carrier resource grid :math:`N^{\text{size},\mu}_{\text{grid},x}`
     89         """
     90         self._ifndef("n_size_grid", 4)
     91         return self._n_size_grid
     92 
     93     @n_size_grid.setter
     94     def n_size_grid(self, value):
     95         assert value in range(1,276), \
     96             "n_size_grid must be in the range from 1 to 275"
     97         self._n_size_grid = value
     98 
     99     #---n_start_grid---#
    100     @property
    101     def n_start_grid(self):
    102         r"""
    103         int, 0 (default) | [0,...,2199] : Start of resource grid relative to
    104             common resource block (CRB) 0
    105             :math:`N^{\text{start},\mu}_{\text{grid},x}`
    106         """
    107         self._ifndef("n_start_grid", 0)
    108         return self._n_start_grid
    109 
    110     @n_start_grid.setter
    111     def n_start_grid(self, value):
    112         assert value in range(0,2200), \
    113             "n_start_grid must be in the range from 0 to 2199"
    114         self._n_start_grid = value
    115 
    116     #---slot_number---#
    117     @property
    118     def slot_number(self):
    119         r"""
    120         int, 0 (default), [0,...,num_slots_per_frame] : Slot number within a frame
    121             :math:`n^\mu_{s,f}`
    122         """
    123         self._ifndef("slot_number", 0)
    124         return self._slot_number
    125 
    126     @slot_number.setter
    127     def slot_number(self, value):
    128         assert 0<=value<self.num_slots_per_frame, \
    129             "slot_number cannot exceed the number of slots per frame-1"
    130         self._slot_number = value
    131 
    132     #---frame_number---#
    133     @property
    134     def frame_number(self):
    135         r"""
    136         int, 0 (default), [0,...,1023] : System frame number :math:`n_\text{f}`
    137         """
    138         self._ifndef("frame_number", 0)
    139         return self._frame_number
    140 
    141     @frame_number.setter
    142     def frame_number(self, value):
    143         assert value in range(0,1024), "frame_number must be in [0, 1023]"
    144         self._frame_number = value
    145 
    146     #--------------------------#
    147     #---Read-only parameters---#
    148     #--------------------------#
    149 
    150     @property
    151     def num_symbols_per_slot(self):
    152         r"""
    153         int, 14 (default) | 12, read-only : Number of OFDM symbols per slot
    154             :math:`N_\text{symb}^\text{slot}`
    155 
    156             Configured through the `cyclic_prefix`.
    157         """
    158         if self.cyclic_prefix=="normal":
    159             return 14
    160         else:
    161             return 12
    162 
    163     @property
    164     def num_slots_per_subframe(self):
    165         r"""
    166         int, 1 (default) | 2 | 4 | 8 | 16 | 32 | 64, read-only : Number of
    167             slots per subframe :math:`N_\text{slot}^{\text{subframe},\mu}`
    168 
    169             Depends on the `subcarrier_spacing`.
    170         """
    171         if self.subcarrier_spacing==15:
    172             return 1
    173         elif self.subcarrier_spacing==30:
    174             return 2
    175         elif self.subcarrier_spacing==60:
    176             return 4
    177         elif self.subcarrier_spacing==120:
    178             return 8
    179         elif self.subcarrier_spacing==240:
    180             return 16
    181         elif self.subcarrier_spacing==480:
    182             return 32
    183         elif self.subcarrier_spacing==960:
    184             return 64
    185 
    186     @property
    187     def num_slots_per_frame(self):
    188         r"""
    189         int, 10 (default) | 20 | 40 | 80 | 160 | 320 | 640, read-only : Number
    190             of slots per frame :math:`N_\text{slot}^{\text{frame},\mu}`
    191 
    192             Depends on the `subcarrier_spacing`.
    193         """
    194         return 10*self.num_slots_per_subframe
    195 
    196     @property
    197     def mu(self):
    198         r"""
    199         int, 0 (default) | 1 | 2 | 3 | 4 | 5 | 6, read-only : Subcarrier
    200             spacing configuration, :math:`\Delta f = 2^\mu 15` kHz
    201         """
    202         return [15, 30, 60, 120, 240, 480, 960].index(self.subcarrier_spacing)
    203 
    204     @property
    205     def frame_duration(self):
    206         r"""
    207         float, 10e-3 (default), read-only : Duration of a frame
    208             :math:`T_\text{f}` [s]
    209         """
    210         return 10e-3
    211 
    212     @property
    213     def sub_frame_duration(self):
    214         r"""
    215         float, 1e-3 (default), read-only : Duration of a subframe
    216             :math:`T_\text{sf}` [s]
    217         """
    218         return 1e-3
    219 
    220     @property
    221     def t_c(self):
    222         r"""
    223         float, 0.509e-9 [s], read-only : Sampling time :math:`T_\text{c}` for
    224             subcarrier spacing 480kHz.
    225         """
    226         return 1/(480e3*4096)
    227 
    228     @property
    229     def t_s(self):
    230         r"""
    231         float, 32.552e-9 [s], read-only : Sampling time :math:`T_\text{s}` for
    232             subcarrier spacing 15kHz.
    233         """
    234         return 1/(15e3*2048)
    235 
    236     @property
    237     def kappa(self):
    238         r"""
    239         float, 64, read-only : The constant
    240             :math:`\kappa = T_\text{s}/T_\text{c}`
    241         """
    242         return 64.
    243 
    244     @property
    245     def cyclic_prefix_length(self):
    246         r"""
    247         float, read-only : Cyclic prefix length
    248             :math:`N_{\text{CP},l}^{\mu} \cdot T_{\text{c}}` [s]
    249         """
    250         if self.cyclic_prefix=="extended":
    251             cp =  512*self.kappa*2**(-self.mu)
    252         else:
    253             cp = 144*self.kappa*2**(-self.mu)
    254             if self.slot_number in [0, 7*2**self.mu]:
    255                 cp += 16*self.kappa
    256         return cp*self.t_c
    257 
    258     #-------------------#
    259     #---Class methods---#
    260     #-------------------#
    261 
    262     def check_config(self):
    263         """Test if configuration is valid"""
    264 
    265         if self.cyclic_prefix=="extended":
    266             assert self.subcarrier_spacing==60, \
    267             "Extended cyclic prefix only valid for 60kHz subcarrier spacing"
    268 
    269         attr_list = ["n_cell_id",
    270                      "cyclic_prefix",
    271                      "subcarrier_spacing",
    272                      "n_size_grid",
    273                      "slot_number",
    274                      "frame_number"
    275                     ]
    276         for attr in attr_list:
    277             value = getattr(self, attr)
    278             setattr(self, attr, value)