Fix logging to matlab/bin file
Add Python script to plot logged buffers. Modified write_file_matlab() to add .bin extension if binary format is selected.
This commit is contained in:
@@ -150,14 +150,19 @@ int write_file_matlab(const char *fname, const char *vname, void *data, int leng
|
||||
|
||||
//printf("Writing %d elements of type %d to %s\n",length,format,fname);
|
||||
|
||||
const int fname_len = strlen(fname);
|
||||
char write_file_name[fname_len + 10];
|
||||
const char *fn_format = (format & MATLAB_RAW) ? "%s.bin" : "%s";
|
||||
snprintf(write_file_name, sizeof(write_file_name), fn_format, fname);
|
||||
|
||||
if (format == 10 || format ==11 || format == 12 || format == 13 || format == 14 || multiVec) {
|
||||
fp = fopen(fname,"a+");
|
||||
fp = fopen(write_file_name, "a+");
|
||||
} else if (format != 10 && format !=11 && format != 12 && format != 13 && format != 14) {
|
||||
fp = fopen(fname,"w+");
|
||||
fp = fopen(write_file_name, "w+");
|
||||
}
|
||||
|
||||
if (fp== NULL) {
|
||||
printf("[OPENAIR][FILE OUTPUT] Cannot open file %s\n",fname);
|
||||
printf("[OPENAIR][FILE OUTPUT] Cannot open file %s\n", write_file_name);
|
||||
return(-1);
|
||||
}
|
||||
|
||||
|
||||
@@ -766,10 +766,12 @@ int nr_rx_pdsch(PHY_VARS_NR_UE *ue,
|
||||
for (int a = 0; a < nbRx; a++) {
|
||||
int offset = (void *)rxdataF_comp[0][a] - (void *)rxdataF_comp[0] + symbol * rx_size_symbol * sizeof(c16_t);
|
||||
memcpy(ue->phy_sim_pdsch_rxdataF_comp + offset, rxdataF_comp[0][a] + symbol * rx_size_symbol, sizeof(c16_t) * rx_size_symbol);
|
||||
memcpy(ue->phy_sim_pdsch_dl_ch_estimates + offset, dl_ch_estimates, pdsch_est_size * sizeof(c16_t));
|
||||
memcpy((c16_t *)ue->phy_sim_pdsch_dl_ch_estimates + pdsch_est_size * a, dl_ch_estimates, pdsch_est_size * sizeof(c16_t));
|
||||
}
|
||||
if (ue->phy_sim_pdsch_dl_ch_estimates_ext)
|
||||
memcpy(ue->phy_sim_pdsch_dl_ch_estimates_ext + symbol * rx_size_symbol, dl_ch_estimates_ext, sizeof(dl_ch_estimates_ext));
|
||||
memcpy((c16_t *)ue->phy_sim_pdsch_dl_ch_estimates_ext + symbol * rx_size_symbol,
|
||||
dl_ch_estimates_ext,
|
||||
sizeof(dl_ch_estimates_ext));
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
||||
@@ -989,6 +989,9 @@ printf("%d\n", slot);
|
||||
n_false_positive = 0;
|
||||
if (n_trials== 1) num_rounds = 1;
|
||||
|
||||
NR_gNB_DLSCH_t *gNB_dlsch = &msgDataTx->dlsch[0][0];
|
||||
nfapi_nr_dl_tti_pdsch_pdu_rel15_t *rel15 = &gNB_dlsch->harq_process.pdsch_pdu.pdsch_pdu_rel15;
|
||||
|
||||
for (trial = 0; trial < n_trials && !stop; trial++) {
|
||||
|
||||
errors_bit = 0;
|
||||
@@ -1004,9 +1007,6 @@ printf("%d\n", slot);
|
||||
int harq_pid = slot;
|
||||
NR_DL_UE_HARQ_t *UE_harq_process = &UE->dl_harq_processes[0][harq_pid];
|
||||
|
||||
NR_gNB_DLSCH_t *gNB_dlsch = &msgDataTx->dlsch[0][0];
|
||||
nfapi_nr_dl_tti_pdsch_pdu_rel15_t *rel15 = &gNB_dlsch->harq_process.pdsch_pdu.pdsch_pdu_rel15;
|
||||
|
||||
UE_harq_process->decodeResult = false;
|
||||
round = 0;
|
||||
UE_harq_process->DLround = round;
|
||||
@@ -1105,10 +1105,10 @@ printf("%d\n", slot);
|
||||
sprintf(filename,"txsig%d.m", aa);//LOG_M
|
||||
LOG_M(filename,"txs", &txdata[aa][slot_offset +frame_parms->ofdm_symbol_size+frame_parms->nb_prefix_samples0],6*(frame_parms->ofdm_symbol_size+frame_parms->nb_prefix_samples),1,1);
|
||||
}
|
||||
}
|
||||
if (output_fd) {
|
||||
printf("writing txdata to binary file\n");
|
||||
fwrite(txdata[0],sizeof(int32_t),frame_length_complex_samples,output_fd);
|
||||
if (output_fd) {
|
||||
printf("writing txdata to binary file\n");
|
||||
fwrite(txdata[0], sizeof(int32_t), frame_length_complex_samples, output_fd);
|
||||
}
|
||||
}
|
||||
|
||||
int txlev[n_tx];
|
||||
@@ -1292,15 +1292,38 @@ printf("%d\n", slot);
|
||||
}
|
||||
|
||||
if (n_trials == 1) {
|
||||
unsigned int op_format = 1;
|
||||
unsigned int dec = 1;
|
||||
if (output_fd) { // Write in bin format
|
||||
op_format |= MATLAB_RAW;
|
||||
}
|
||||
|
||||
LOG_M("rxsig0.m","rxs0", UE->common_vars.rxdata[0], frame_length_complex_samples, 1, 1);
|
||||
LOG_M("rxsig0.m", "rxs0", UE->common_vars.rxdata[0], frame_length_complex_samples, dec, op_format);
|
||||
if (UE->frame_parms.nb_antennas_rx>1)
|
||||
LOG_M("rxsig1.m","rxs1", UE->common_vars.rxdata[1], frame_length_complex_samples, 1, 1);
|
||||
LOG_M("rxF0.m","rxF0", UE->phy_sim_rxdataF, frame_parms->samples_per_slot_wCP, 1, 1);
|
||||
LOG_M("rxF_ext.m","rxFe",UE->phy_sim_pdsch_rxdataF_ext,g_rbSize*12*14,1,1);
|
||||
LOG_M("chestF0.m","chF0",UE->phy_sim_pdsch_dl_ch_estimates_ext,g_rbSize*12*14,1,1);
|
||||
write_output("rxF_comp.m","rxFc",UE->phy_sim_pdsch_rxdataF_comp,N_RB_DL*12*14,1,1);
|
||||
LOG_M("rxF_llr.m","rxFllr",UE->phy_sim_pdsch_llr,available_bits,1,0);
|
||||
LOG_M("rxsig1.m", "rxs1", UE->common_vars.rxdata[1], frame_length_complex_samples, dec, op_format);
|
||||
LOG_M("rxF0.m", "rxF0", UE->phy_sim_rxdataF, frame_parms->samples_per_slot_wCP, dec, op_format);
|
||||
LOG_M("rxF_ext.m", "rxFe", UE->phy_sim_pdsch_rxdataF_ext, g_rbSize * 12 * 14, dec, op_format);
|
||||
const uint32_t numReSym = (g_rbSize * 12 + 15) & (~15);
|
||||
const uint32_t numValidReSym = g_rbSize * 12;
|
||||
{
|
||||
const int s = rel15->StartSymbolIndex;
|
||||
const int n = rel15->NrOfSymbols;
|
||||
for (int i = s; i < s + n; i++) {
|
||||
char fName[50];
|
||||
snprintf(fName, sizeof(fName), "chestF0_ext_s%d.m", i);
|
||||
LOG_M(fName,
|
||||
"chF0_ext",
|
||||
((c16_t *)UE->phy_sim_pdsch_dl_ch_estimates_ext) + (i * numReSym),
|
||||
numValidReSym,
|
||||
dec,
|
||||
op_format);
|
||||
snprintf(fName, sizeof(fName), "rxF_comp_s%d.m", i);
|
||||
LOG_M(fName, "rxFc", ((c16_t *)UE->phy_sim_pdsch_rxdataF_comp) + (i * numReSym), numValidReSym, dec, op_format);
|
||||
}
|
||||
}
|
||||
LOG_M("chestF0.m", "chF0", UE->phy_sim_pdsch_dl_ch_estimates, frame_parms->ofdm_symbol_size * 14, dec, op_format);
|
||||
op_format = (op_format & (~1));
|
||||
LOG_M("rxF_llr.m", "rxFllr", UE->phy_sim_pdsch_llr, available_bits, dec, op_format);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
@@ -240,6 +240,7 @@ int main(int argc, char *argv[])
|
||||
int threadCnt=0;
|
||||
int max_ldpc_iterations = 5;
|
||||
int num_antennas_per_thread = 1;
|
||||
uint32_t log_format = 0;
|
||||
if ((uniqCfg = load_configmodule(argc, argv, CONFIG_ENABLECMDLINEONLY)) == 0) {
|
||||
exit_fun("[NR_ULSIM] Error, configuration module init failed\n");
|
||||
}
|
||||
@@ -251,8 +252,7 @@ int main(int argc, char *argv[])
|
||||
InitSinLUT();
|
||||
|
||||
int c;
|
||||
while ((c = getopt(argc, argv, "--:O:a:b:c:d:ef:g:h:i:k:m:n:p:q:r:s:t:u:v:w:y:z:A:C:F:G:H:I:M:N:PR:S:T:U:L:ZW:E:X:")) != -1) {
|
||||
|
||||
while ((c = getopt(argc, argv, "--:O:a:b:c:d:ef:g:h:i:jk:m:n:p:q:r:s:t:u:v:w:y:z:A:C:F:G:H:I:M:N:PR:S:T:U:L:ZW:E:X:")) != -1) {
|
||||
/* ignore long options starting with '--', option '-O' and their arguments that are handled by configmodule */
|
||||
/* with this opstring getopt returns 1 for non-option arguments, refer to 'man 3 getopt' */
|
||||
if (c == 1 || c == '-' || c == 'O')
|
||||
@@ -346,7 +346,11 @@ int main(int argc, char *argv[])
|
||||
i+=2;
|
||||
} while (optarg[i-1] == ',');
|
||||
break;
|
||||
|
||||
|
||||
case 'j':
|
||||
log_format |= MATLAB_RAW;
|
||||
break;
|
||||
|
||||
case 'k':
|
||||
printf("Setting threequarter_fs_flag\n");
|
||||
openair0_cfg[0].threequarter_fs= 1;
|
||||
@@ -524,6 +528,7 @@ int main(int argc, char *argv[])
|
||||
printf("-g Channel model configuration. Arguments list: Number of arguments = 3, {Channel model: [A] TDLA30, [B] TDLB100, [C] TDLC300}, {Correlation: [l] Low, [m] Medium, [h] High}, {Maximum Doppler shift} e.g. -g A,l,10\n");
|
||||
printf("-h This message\n");
|
||||
printf("-i Change channel estimation technique. Arguments list: Number of arguments=2, Frequency domain {0:Linear interpolation, 1:PRB based averaging}, Time domain {0:Estimates of last DMRS symbol, 1:Average of DMRS symbols}. e.g. -i 1,0\n");
|
||||
printf("-j Save signal buffers in binary format.");
|
||||
printf("-k 3/4 sampling\n");
|
||||
printf("-m MCS value\n");
|
||||
printf("-n Number of trials to simulate\n");
|
||||
@@ -560,7 +565,7 @@ int main(int argc, char *argv[])
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
logInit();
|
||||
set_glog(loglvl);
|
||||
|
||||
@@ -1215,12 +1220,12 @@ int main(int argc, char *argv[])
|
||||
phy_procedures_nrUE_TX(UE, &UE_proc, &phy_data);
|
||||
|
||||
if (n_trials == 1) {
|
||||
LOG_M("txsig0.m", "txs0", &UE->common_vars.txData[0][slot_offset], slot_length, 1, 1);
|
||||
LOG_M("txsig0.m", "txs0", &UE->common_vars.txData[0][slot_offset], slot_length, 1, 1 | log_format);
|
||||
if (precod_nbr_layers > 1) {
|
||||
LOG_M("txsig1.m", "txs1", &UE->common_vars.txData[1][slot_offset], slot_length, 1, 1);
|
||||
if (precod_nbr_layers == 4) {
|
||||
LOG_M("txsig2.m", "txs2", &UE->common_vars.txData[2][slot_offset], slot_length, 1, 1);
|
||||
LOG_M("txsig3.m", "txs3", &UE->common_vars.txData[3][slot_offset], slot_length, 1, 1);
|
||||
LOG_M("txsig1.m", "txs1", &UE->common_vars.txData[1][slot_offset], slot_length, 1, 1 | log_format);
|
||||
if (precod_nbr_layers == 4) {
|
||||
LOG_M("txsig2.m", "txs2", &UE->common_vars.txData[2][slot_offset], slot_length, 1, 1 | log_format);
|
||||
LOG_M("txsig3.m", "txs3", &UE->common_vars.txData[3][slot_offset], slot_length, 1, 1 | log_format);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1294,16 +1299,16 @@ int main(int argc, char *argv[])
|
||||
ul_proc_error = phy_procedures_gNB_uespec_RX(gNB, frame, slot, &UL_INFO);
|
||||
|
||||
if (n_trials == 1 && round == 0) {
|
||||
LOG_M("rxsig0.m", "rx0", &rxdata[0][slot_offset], slot_length, 1, 1);
|
||||
LOG_M("rxsigF0.m", "rxsF0", gNB->common_vars.rxdataF[0][0], 14 * frame_parms->ofdm_symbol_size, 1, 1);
|
||||
LOG_M("rxsig0.m", "rx0", &rxdata[0][slot_offset], slot_length, 1, 1 | log_format);
|
||||
LOG_M("rxsigF0.m", "rxsF0", gNB->common_vars.rxdataF[0][0], 14 * frame_parms->ofdm_symbol_size, 1, 1 | log_format);
|
||||
if (precod_nbr_layers > 1) {
|
||||
LOG_M("rxsig1.m", "rx1", &rxdata[1][slot_offset], slot_length, 1, 1);
|
||||
LOG_M("rxsigF1.m", "rxsF1", gNB->common_vars.rxdataF[0][1], 14 * frame_parms->ofdm_symbol_size, 1, 1);
|
||||
LOG_M("rxsigF1.m", "rxsF1", gNB->common_vars.rxdataF[0][1], 14 * frame_parms->ofdm_symbol_size, 1, 1 | log_format);
|
||||
if (precod_nbr_layers == 4) {
|
||||
LOG_M("rxsig2.m", "rx2", &rxdata[2][slot_offset], slot_length, 1, 1);
|
||||
LOG_M("rxsig3.m", "rx3", &rxdata[3][slot_offset], slot_length, 1, 1);
|
||||
LOG_M("rxsigF2.m", "rxsF2", gNB->common_vars.rxdataF[0][2], 14 * frame_parms->ofdm_symbol_size, 1, 1);
|
||||
LOG_M("rxsigF3.m", "rxsF3", gNB->common_vars.rxdataF[0][3], 14 * frame_parms->ofdm_symbol_size, 1, 1);
|
||||
LOG_M("rxsigF2.m", "rxsF2", gNB->common_vars.rxdataF[0][2], 14 * frame_parms->ofdm_symbol_size, 1, 1 | log_format);
|
||||
LOG_M("rxsigF3.m", "rxsF3", gNB->common_vars.rxdataF[0][3], 14 * frame_parms->ofdm_symbol_size, 1, 1 | log_format);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1317,71 +1322,69 @@ int main(int argc, char *argv[])
|
||||
&pusch_vars->ul_ch_estimates[0][start_symbol * frame_parms->ofdm_symbol_size],
|
||||
frame_parms->ofdm_symbol_size,
|
||||
1,
|
||||
1);
|
||||
1 | log_format);
|
||||
|
||||
LOG_M("rxsigF0_comp.m",
|
||||
"rxsF0_comp",
|
||||
&pusch_vars->rxdataF_comp[0][start_symbol * (off + (NR_NB_SC_PER_RB * pusch_pdu->rb_size))],
|
||||
nb_symb_sch * (off + (NR_NB_SC_PER_RB * pusch_pdu->rb_size)),
|
||||
1,
|
||||
1);
|
||||
1 | log_format);
|
||||
|
||||
if (precod_nbr_layers == 2) {
|
||||
|
||||
LOG_M("chestF3.m",
|
||||
"chF3",
|
||||
&pusch_vars->ul_ch_estimates[3][start_symbol * frame_parms->ofdm_symbol_size],
|
||||
frame_parms->ofdm_symbol_size,
|
||||
1,
|
||||
1);
|
||||
1 | log_format);
|
||||
|
||||
LOG_M("rxsigF2_comp.m",
|
||||
"rxsF2_comp",
|
||||
&pusch_vars->rxdataF_comp[2][start_symbol * (off + (NR_NB_SC_PER_RB * pusch_pdu->rb_size))],
|
||||
nb_symb_sch * (off + (NR_NB_SC_PER_RB * pusch_pdu->rb_size)),
|
||||
1,
|
||||
1);
|
||||
1 | log_format);
|
||||
}
|
||||
|
||||
if (precod_nbr_layers == 4) {
|
||||
|
||||
LOG_M("chestF5.m",
|
||||
"chF5",
|
||||
&pusch_vars->ul_ch_estimates[5][start_symbol * frame_parms->ofdm_symbol_size],
|
||||
frame_parms->ofdm_symbol_size,
|
||||
1,
|
||||
1);
|
||||
1 | log_format);
|
||||
LOG_M("chestF10.m",
|
||||
"chF10",
|
||||
&pusch_vars->ul_ch_estimates[10][start_symbol * frame_parms->ofdm_symbol_size],
|
||||
frame_parms->ofdm_symbol_size,
|
||||
1,
|
||||
1);
|
||||
1 | log_format);
|
||||
LOG_M("chestF15.m",
|
||||
"chF15",
|
||||
&pusch_vars->ul_ch_estimates[15][start_symbol * frame_parms->ofdm_symbol_size],
|
||||
frame_parms->ofdm_symbol_size,
|
||||
1,
|
||||
1);
|
||||
1 | log_format);
|
||||
|
||||
LOG_M("rxsigF4_comp.m",
|
||||
"rxsF4_comp",
|
||||
&pusch_vars->rxdataF_comp[4][start_symbol * (off + (NR_NB_SC_PER_RB * pusch_pdu->rb_size))],
|
||||
nb_symb_sch * (off + (NR_NB_SC_PER_RB * pusch_pdu->rb_size)),
|
||||
1,
|
||||
1);
|
||||
1 | log_format);
|
||||
LOG_M("rxsigF8_comp.m",
|
||||
"rxsF8_comp",
|
||||
&pusch_vars->rxdataF_comp[8][start_symbol * (off + (NR_NB_SC_PER_RB * pusch_pdu->rb_size))],
|
||||
nb_symb_sch * (off + (NR_NB_SC_PER_RB * pusch_pdu->rb_size)),
|
||||
1,
|
||||
1);
|
||||
1 | log_format);
|
||||
LOG_M("rxsigF12_comp.m",
|
||||
"rxsF12_comp",
|
||||
&pusch_vars->rxdataF_comp[12][start_symbol * (off + (NR_NB_SC_PER_RB * pusch_pdu->rb_size))],
|
||||
nb_symb_sch * (off + (NR_NB_SC_PER_RB * pusch_pdu->rb_size)),
|
||||
1,
|
||||
1);
|
||||
1 | log_format);
|
||||
}
|
||||
|
||||
LOG_M("rxsigF0_llr.m",
|
||||
@@ -1389,7 +1392,7 @@ int main(int argc, char *argv[])
|
||||
&pusch_vars->llr[0],
|
||||
precod_nbr_layers * (nb_symb_sch - 1) * NR_NB_SC_PER_RB * pusch_pdu->rb_size * mod_order,
|
||||
1,
|
||||
0);
|
||||
0 | log_format);
|
||||
}
|
||||
|
||||
if ((ulsch_gNB->last_iteration_cnt >= ulsch_gNB->max_ldpc_iterations) || ul_proc_error == 1) {
|
||||
|
||||
@@ -19,3 +19,16 @@ Same goes for any software modifications of `nr_ulsim` - the cache is not aware
|
||||
the data - remember to clear your cache manually if you are comparing different `nr_ulsim` versions.
|
||||
|
||||
The script also allows to skip usage of the cache with `--rerun` option.
|
||||
|
||||
## `dl_graph.py`
|
||||
|
||||
This generates plots from data saved from nr_dlsim. It takes data in two formats:
|
||||
|
||||
1. Plots frequency domain channel estimates, constellation diagram and LLRs from data read in binary format. The data is generated from `nr_dlsim -w`
|
||||
2. Plots BER (other also possible) from CSV data generated by `nr_dlsim -Z`.
|
||||
|
||||
The plots are saved in three formats: `.png`, `.pdf` and `.svg`.
|
||||
|
||||
### Example graphs:
|
||||
#### BER
|
||||

|
||||
|
||||
File diff suppressed because it is too large
Load Diff
|
After Width: | Height: | Size: 39 KiB |
@@ -0,0 +1,68 @@
|
||||
#!/usr/bin/env python
|
||||
# coding: utf-8
|
||||
import numpy as np
|
||||
import matplotlib.pyplot as plt
|
||||
import argparse
|
||||
import pandas
|
||||
|
||||
def save_fig(fig:plt.figure, figName:str):
|
||||
fig.savefig(figName + '.pdf')
|
||||
fig.savefig(figName + '.png')
|
||||
fig.savefig(figName + '.svg')
|
||||
|
||||
# Channel Frequency Response
|
||||
def channel_est(dataPath):
|
||||
binfile = dataPath + 'chestF0_ext_s1.m.bin'
|
||||
data = np.fromfile(binfile,dtype=np.int16)
|
||||
dataCmp = data[0::2] + 1j*data[1::2]
|
||||
fig = plt.gcf()
|
||||
plt.plot(np.abs(dataCmp))
|
||||
save_fig(fig, 'channel_est')
|
||||
plt.close(fig)
|
||||
|
||||
# Constellation
|
||||
def constellation(dataPath):
|
||||
binfile = dataPath + 'rxF_comp_s1.m.bin'
|
||||
data = np.fromfile(binfile,dtype=np.int16)
|
||||
dataCmp = data[0::2] + 1j*data[1::2]
|
||||
fig = plt.gcf()
|
||||
plt.scatter(np.real(dataCmp),np.imag(dataCmp))
|
||||
save_fig(fig, 'constellation')
|
||||
plt.close(fig)
|
||||
|
||||
# LLR
|
||||
def llr(dataPath):
|
||||
binfile = dataPath + 'rxF_llr.m.bin'
|
||||
data = np.fromfile(binfile,dtype=np.int16)
|
||||
fig = plt.gcf()
|
||||
plt.plot(data,'*')
|
||||
save_fig(fig, 'llr')
|
||||
plt.close(fig)
|
||||
|
||||
# BER from data in CSV files generated by nr_dlsim
|
||||
def ber(dataPath, csvFiles):
|
||||
d0 = pandas.read_csv(dataPath + csvFiles[0] + '.csv')
|
||||
ax = d0.plot(x='SNR',y='channel_ber_0',logy=True,label=csvFiles[0])
|
||||
plt.ylabel('BER')
|
||||
for i in range(1,len(csvFiles)):
|
||||
d = pandas.read_csv(dataPath + csvFiles[i] + '.csv')
|
||||
d.plot(ax=ax,x='SNR',y='channel_ber_0',logy=True,label=csvFiles[i],grid=True)
|
||||
|
||||
fig = ax.figure
|
||||
save_fig(fig, 'ber_compare')
|
||||
plt.close(fig)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
parser = argparse.ArgumentParser(description="DL plot generator")
|
||||
parser.add_argument('--data-path', help='Path to directory containing data', default='../../cmake_targets/ran_build/build/')
|
||||
parser.add_argument('--csv-data', nargs='+' ,help='CSV file name without extension (generated from nr_dlsim with -Z option)')
|
||||
parser.add_argument('--ber-compare', help='Compare BER from multiple CSV files', action='store_true')
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
channel_est(args.data_path)
|
||||
constellation(args.data_path)
|
||||
llr(args.data_path)
|
||||
if args.ber_compare:
|
||||
ber(args.data_path, args.csv_data)
|
||||
Reference in New Issue
Block a user