@@ -58,7 +58,8 @@ def link_performance(link_model, SNRs, send_max, err_min, send_chunk=None, code_
58
58
BERs : 1d ndarray
59
59
Estimated Bit Error Ratio corresponding to each SNRs
60
60
"""
61
-
61
+ if not send_chunk :
62
+ send_chunk = err_min
62
63
return link_model .link_performance (SNRs , send_max , err_min , send_chunk , code_rate )
63
64
64
65
@@ -133,7 +134,7 @@ class LinkModel:
133
134
*Default* is 1.
134
135
"""
135
136
136
- def __init__ (self , modulate , channel , receive , num_bits_symbol , constellation , Es = 1 , decoder = None , rate = 1 ):
137
+ def __init__ (self , modulate , channel , receive , num_bits_symbol , constellation , Es = 1 , decoder = None , rate = 1. ):
137
138
self .modulate = modulate
138
139
self .channel = channel
139
140
self .receive = receive
@@ -146,8 +147,10 @@ def __init__(self, modulate, channel, receive, num_bits_symbol, constellation, E
146
147
self .decoder = lambda msg : msg
147
148
else :
148
149
self .decoder = decoder
150
+ self .full_simulation_results = None
149
151
150
- def link_performance (self , SNRs , send_max , err_min , send_chunk = None , code_rate = 1 ):
152
+ def link_performance_full_metrics (self , SNRs , tx_max , err_min , send_chunk = None , code_rate : float = 1. ,
153
+ number_chunks_per_send = 1 , stop_on_surpass_error = True ):
151
154
"""
152
155
Estimate the BER performance of a link model with Monte Carlo simulation.
153
156
@@ -157,8 +160,8 @@ def link_performance(self, SNRs, send_max, err_min, send_chunk=None, code_rate=1
157
160
Signal to Noise ratio in dB defined as :math:`SNR_{dB} = (E_b/N_0)_{dB} + 10 \log_{10}(R_cM_c)`
158
161
where :math:`Rc` is the code rate and :math:`Mc` the modulation rate.
159
162
160
- send_max : int
161
- Maximum number of bits send for each SNR.
163
+ tx_max : int
164
+ Maximum number of transmissions for each SNR.
162
165
163
166
err_min : int
164
167
link_performance send bits until it reach err_min errors (see also send_max).
@@ -172,6 +175,110 @@ def link_performance(self, SNRs, send_max, err_min, send_chunk=None, code_rate=1
172
175
Rate of the used code.
173
176
*Default*: 1 i.e. no code.
174
177
178
+ number_chunks_per_send : int
179
+ Number of chunks per transmission
180
+
181
+ stop_on_surpass_error : bool
182
+ Controls if during simulation of a SNR it should break and move to the next SNR when
183
+ the bit error is above the err_min parameter
184
+
185
+ Returns
186
+ -------
187
+ List[BERs, BEs, CEs, NCs]
188
+ BERs : 1d ndarray
189
+ Estimated Bit Error Ratio corresponding to each SNRs
190
+ BEs : 2d ndarray
191
+ Number of Estimated Bits with Error per transmission corresponding to each SNRs
192
+ CEs : 2d ndarray
193
+ Number of Estimated Chunks with Errors per transmission corresponding to each SNRs
194
+ NCs : 2d ndarray
195
+ Number of Chunks transmitted per transmission corresponding to each SNRs
196
+ """
197
+
198
+ # Initialization
199
+ BERs = np .zeros_like (SNRs , dtype = float )
200
+ BEs = np .zeros ((len (SNRs ), tx_max ), dtype = int ) # Bit errors per tx
201
+ CEs = np .zeros ((len (SNRs ), tx_max ), dtype = int ) # Chunk Errors per tx
202
+ NCs = np .zeros ((len (SNRs ), tx_max ), dtype = int ) # Number of Chunks per tx
203
+ # Set chunk size and round it to be a multiple of num_bits_symbol*nb_tx to avoid padding
204
+ if send_chunk is None :
205
+ send_chunk = err_min
206
+ divider = self .num_bits_symbol * self .channel .nb_tx
207
+ send_chunk = max (divider , send_chunk // divider * divider )
208
+
209
+ receive_size = self .channel .nb_tx * self .num_bits_symbol
210
+ full_args_decoder = len (getfullargspec (self .decoder ).args ) > 1
211
+
212
+ # Computations
213
+ for id_SNR in range (len (SNRs )):
214
+ self .channel .set_SNR_dB (SNRs [id_SNR ], code_rate , self .Es )
215
+ total_tx_send = 0
216
+ bit_err = np .zeros (tx_max , dtype = int )
217
+ chunk_loss = np .zeros (tx_max , dtype = int )
218
+ chunk_count = np .zeros (tx_max , dtype = int )
219
+ for id_tx in range (tx_max ):
220
+ if stop_on_surpass_error and bit_err .sum () > err_min :
221
+ break
222
+ # Propagate some bits
223
+ msg = np .random .choice ((0 , 1 ), send_chunk * number_chunks_per_send )
224
+ symbs = self .modulate (msg )
225
+ channel_output = self .channel .propagate (symbs )
226
+
227
+ # Deals with MIMO channel
228
+ if isinstance (self .channel , MIMOFlatChannel ):
229
+ nb_symb_vector = len (channel_output )
230
+ received_msg = np .empty (int (math .ceil (len (msg ) / self .rate )), dtype = np .int8 )
231
+ for i in range (nb_symb_vector ):
232
+ received_msg [receive_size * i :receive_size * (i + 1 )] = \
233
+ self .receive (channel_output [i ], self .channel .channel_gains [i ],
234
+ self .constellation , self .channel .noise_std ** 2 )
235
+ else :
236
+ received_msg = self .receive (channel_output , self .channel .channel_gains ,
237
+ self .constellation , self .channel .noise_std ** 2 )
238
+ # Count errors
239
+ if full_args_decoder :
240
+ decoded_bits = self .decoder (channel_output , self .channel .channel_gains ,
241
+ self .constellation , self .channel .noise_std ** 2 ,
242
+ received_msg , self .channel .nb_tx * self .num_bits_symbol )
243
+ else :
244
+ decoded_bits = self .decoder (received_msg )
245
+ # calculate number of error frames
246
+ for i in range (number_chunks_per_send ):
247
+ errors = np .bitwise_xor (msg [send_chunk * i :send_chunk * (i + 1 )],
248
+ decoded_bits [send_chunk * i :send_chunk * (i + 1 )]).sum ()
249
+ bit_err [id_tx ] += errors
250
+ chunk_loss [id_tx ] += 1 if errors > 0 else 0
251
+
252
+ chunk_count [id_tx ] += number_chunks_per_send
253
+ total_tx_send += 1
254
+ BERs [id_SNR ] = bit_err .sum () / (total_tx_send * send_chunk )
255
+ BEs [id_SNR ] = bit_err
256
+ CEs [id_SNR ] = np .where (bit_err > 0 , 1 , 0 )
257
+ NCs [id_SNR ] = chunk_count
258
+ if BEs [id_SNR ].sum () < err_min :
259
+ break
260
+ self .full_simulation_results = BERs , BEs , CEs , NCs
261
+ return BERs , BEs , CEs , NCs
262
+
263
+ def link_performance (self , SNRs , send_max , err_min , send_chunk = None , code_rate = 1 ):
264
+ """
265
+ Estimate the BER performance of a link model with Monte Carlo simulation.
266
+ Parameters
267
+ ----------
268
+ SNRs : 1D arraylike
269
+ Signal to Noise ratio in dB defined as :math:`SNR_{dB} = (E_b/N_0)_{dB} + 10 \log_{10}(R_cM_c)`
270
+ where :math:`Rc` is the code rate and :math:`Mc` the modulation rate.
271
+ send_max : int
272
+ Maximum number of bits send for each SNR.
273
+ err_min : int
274
+ link_performance send bits until it reach err_min errors (see also send_max).
275
+ send_chunk : int
276
+ Number of bits to be send at each iteration. This is also the frame length of the decoder if available
277
+ so it should be large enough regarding the code type.
278
+ *Default*: send_chunck = err_min
279
+ code_rate : float in (0,1]
280
+ Rate of the used code.
281
+ *Default*: 1 i.e. no code.
175
282
Returns
176
283
-------
177
284
BERs : 1d ndarray
0 commit comments