diff --git a/Project.toml b/Project.toml index 9aeaf39..f4696da 100644 --- a/Project.toml +++ b/Project.toml @@ -15,6 +15,7 @@ DelimitedFiles = "8bb1440f-4735-579b-a4ab-409b98df4dab" DigitalComm = "a7b11256-881b-11e9-3aff-ff4a76f1bfae" Distributed = "8ba89e20-285c-5b6f-9357-94700520ee1b" FFTW = "7a1cc6ca-52ef-59f5-83cd-3a7055c09341" +Flatten = "4c728ea3-d9ee-5c9a-9642-b6f7d7dc04fa" Flux = "587475ba-b771-5e3f-ad9e-33799f191a9c" Infiltrator = "5903a43b-9cc3-4c30-8d17-598619ec4e9b" InteractiveUtils = "b77e0a4c-d291-57a0-90e8-8db25a27a240" diff --git a/README.md b/README.md index c23e07d..3a82da9 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# RiFyFi +# RiFyFi.jl [![Build Status](https://github.com/achilletIrisa/RiFyFi.jl/actions/workflows/CI.yml/badge.svg?branch=main)](https://github.com/achilletIrisa/RiFyFi.jl/actions/workflows/CI.yml?query=branch%3Amain) @@ -6,15 +6,26 @@ RiFyFi is a framework for Radio Frequency Fingerprint Identification. RFF is a unique signature created in the emitter transmission chain by the hardware impairments. These impairments may be used as a secure identifier as they cannot be easily replicated for spoofing purposes. In recent years, the RFF identification relies mainly on Deep Learning (DL), and large databases are consequently needed to improve identification in different environmental conditions. RiFyFi is introduced to propose a framework combine with a virtual database to explore the RFF identification. Different transmission scenarios are modeled such as the data type (being a preamble or a payload) and the data size. +RiFyFi is composed of different subpackage +- RiFyFi_VDG : The Virtual Database Generator +- RiFyFi_IdF : Package for training and testing network +- Augmentation : Package used for data augmentation +- Results : Package to create some confusion matrix or F1 score evolution in function of time. +## Protocol to use RiFyFi with Julia +Insatall Julia (here develop with 1.8.5) Create a folders -Download or clone the project with git clone -Going in Rifyfi.jl -Open Julia terminal +Download or clone the project with: git clone https://github.com/JuliaTelecom/Rifyfi.jl +Going in Rifyfi.jl folders +Open a Julia terminal Activate the project ] activate . Instantiate the project with ] instantiate +Then you can you the script script_example.jl, in the Julia Terminal : +include("src/script_exemple.jl") + + Then you can use RiFyFi in two manners: - Creating random parameter values for impairments - Define the value of the impairments parameters with scenario file diff --git a/src/Results/src/Prod_ConfusionMatrix.jl b/src/Results/src/Prod_ConfusionMatrix.jl index a805ecc..9b869a2 100644 --- a/src/Results/src/Prod_ConfusionMatrix.jl +++ b/src/Results/src/Prod_ConfusionMatrix.jl @@ -53,14 +53,15 @@ end """ Fonction qui plot la matrice de confusion en format csv \n - filename = .pkl file + filename = .pkl + file txs,rxs,days,equalized = param for test with 2 for equalized rxsnn,daysnn = param to choose to CNN ChunSize = 256 dataAug = "sans" or "OfflineV1" """ -function Confusion_Matrix_CSV(Param_Data,Param_Network,savepathbson="") +function Confusion_Matrix_CSV(Param_Data,Param_Network,savepathbson="",Param_Data_test=Param_Data) if Param_Network.Train_args.use_cuda ==true hardware1 = "GPU" else @@ -68,22 +69,23 @@ function Confusion_Matrix_CSV(Param_Data,Param_Network,savepathbson="") end if savepathbson == "" if Param_Data.Augmentation_Value.augmentationType == "No_channel" - savepathbson = "run/Synth/$(Param_Data.Augmentation_Value.augmentationType)_$(Param_Data.nbTx)_$(Param_Data.Chunksize)_$(Param_Network.Networkname)/$(Param_Data.E)_$(Param_Data.S)/$(Param_Data.E)_$(Param_Data.S)_$(Param_Data.C)_$(Param_Data.RFF)_$(Param_Data.nbSignals)_$(Param_Data.nameModel)/$(hardware1)" + savepath_model = "run/Synth/$(Param_Data.Modulation)/$(Param_Data.Augmentation_Value.augmentationType)_$(Param_Data.nbTx)_$(Param_Data.Chunksize)_$(Param_Network.Networkname)/$(Param_Data.E)_$(Param_Data.S)/$(Param_Data.E)_$(Param_Data.S)_$(Param_Data.C)_$(Param_Data.RFF)_$(Param_Data.nbSignals)_$(Param_Data.nameModel)/$(hardware1)" else - savepathbson = "run/Synth/$(Param_Data.Augmentation_Value.augmentationType)_$(Param_Data.nbTx)_$(Param_Data.Chunksize)_$(Param_Network.Networkname)/$(Param_Data.E)_$(Param_Data.S)/$(Param_Data.E)_$(Param_Data.S)_$(Param_Data.C)_$(Param_Data.RFF)_$(Param_Data.nbSignals)_$(Param_Data.nameModel)_$(Param_Data.Augmentation_Value.Channel)_$(Param_Data.Augmentation_Value.Channel_Test)_nbAugment_$(Param_Data.Augmentation_Value.nb_Augment)/$(hardware1)" + savepath_model = "run/Synth/$(Param_Data.Modulation)/$(Param_Data.Augmentation_Value.augmentationType)_$(Param_Data.nbTx)_$(Param_Data.Chunksize)_$(Param_Network.Networkname)/$(Param_Data.E)_$(Param_Data.S)/$(Param_Data.E)_$(Param_Data.S)_$(Param_Data.C)_$(Param_Data.RFF)_$(Param_Data.nbSignals)_$(Param_Data.nameModel)_$(Param_Data.Augmentation_Value.Channel)_$(Param_Data.Augmentation_Value.Channel_Test)_nbAugment_$(Param_Data.Augmentation_Value.nb_Augment)/$(hardware1)" end end allAcc = Float64[] - res =RiFyFi_IdF.loadCNN("$(savepathbson)/model_seed_$(Param_Network.Seed_Network)_dr$(Param_Network.Train_args.dr).bson") + res = RiFyFi_IdF.loadCNN("$(savepath_model)/model_seed_$(Param_Network.Seed_Network)_dr$(Param_Network.Train_args.dr)_$(Param_Data.Modulation).bson") + #res =RiFyFi_IdF.loadCNN("$(savepath_model)/model_new.bson") model = res.model testmode!(model, true) # We are in test mode, with no dropout (moy,std_val) = (nothing,nothing) allAccuracy = Float64[] - (_,_,X_test,Y_test) =loadCSV_Synthetic(Param_Data) + (_,_,X_test,Y_test) =loadCSV_Synthetic(Param_Data_test) if Param_Network.Train_args.use_cuda @@ -98,13 +100,13 @@ function Confusion_Matrix_CSV(Param_Data,Param_Network,savepathbson="") confMatrix = confusionMatrix(l̂,l,Param_Data.nbTx) plt = plotConfusionMatrix(confMatrix ) - savepath ="Results/$(Param_Data.Augmentation_Value.augmentationType)_$(Param_Data.nbTx)_$(Param_Data.Chunksize)_$(Param_Network.Networkname)/$(Param_Data.E)_$(Param_Data.S)" - !ispath(savepath) && mkpath(savepath) + savepath_result ="Results/$(Param_Data.Modulation)/$(Param_Data.Augmentation_Value.augmentationType)_$(Param_Data.nbTx)_$(Param_Data.Chunksize)_$(Param_Network.Networkname)/$(Param_Data.E)_$(Param_Data.S)" + !ispath(savepath_result) && mkpath(savepath_result) Temp=zeros(1,Param_Data.nbTx) if Param_Data.Augmentation_Value.augmentationType == "No_channel" - file="$(savepath)/confMatrix_$(Param_Data.E)_$(Param_Data.S)_$(Param_Data.C)_$(Param_Data.RFF)_$(Param_Data.nbSignals)_$(Param_Data.name)_seed_$(Param_Network.Seed_Network).csv" + file="$(savepath_result)/confMatrix_$(Param_Data.E)_$(Param_Data.S)_$(Param_Data.C)_$(Param_Data.RFF)_$(Param_Data.nbSignals)_$(Param_Data.name)_seed_$(Param_Network.Seed_Network).csv" else - file="$(savepath)/confMatrix_$(Param_Data.E)_$(Param_Data.S)_$(Param_Data.C)_$(Param_Data.RFF)_$(Param_Data.nbSignals)_$(Param_Data.name)_$(Param_Data.Augmentation_Value.Channel)_$(Param_Data.Augmentation_Value.Channel_Test)_nbAugment_$(Param_Data.Augmentation_Value.nb_Augment)_seed_$(Param_Network.Seed_Network).csv" + file="$(savepath_result)/confMatrix_$(Param_Data.E)_$(Param_Data.S)_$(Param_Data.C)_$(Param_Data.RFF)_$(Param_Data.nbSignals)_$(Param_Data.name)_$(Param_Data.Augmentation_Value.Channel)_$(Param_Data.Augmentation_Value.Channel_Test)_nbAugment_$(Param_Data.Augmentation_Value.nb_Augment)_seed_$(Param_Network.Seed_Network).csv" end open(file,"w") do io for i in 0:size(confMatrix,1)-1 diff --git a/src/Results/src/Results.jl b/src/Results/src/Results.jl index ed1b60c..7bfc708 100644 --- a/src/Results/src/Results.jl +++ b/src/Results/src/Results.jl @@ -30,7 +30,7 @@ using .RiFyFi_VDG include("../../RiFyFi_IdF/src/RiFyFi_IdF.jl") using .RiFyFi_IdF -function main(Param_Data,Param_Network,Type_Resuts,Table_Seed_Network,savepathbson) +function main(Param_Data,Param_Network,Type_Resuts,Table_Seed_Network,savepathbson,Param_Data_test) if Type_Resuts == "F1_score" F1_score_Synth(Param_Data,Param_Network,Table_Seed_Network,savepathbson) @@ -39,7 +39,7 @@ function main(Param_Data,Param_Network,Type_Resuts,Table_Seed_Network,savepathbs Compute_mean(Param_Data,Param_Network,nameSituation,Table_Seed_Network) elseif Type_Resuts == "Confusion_Matrix" - Confusion_Matrix_CSV(Param_Data,Param_Network,savepathbson ) + Confusion_Matrix_CSV(Param_Data,Param_Network,savepathbson,Param_Data_test ) end @@ -55,9 +55,9 @@ function F1_score_Synth(Param_Data,Param_Network,Table_Seed_Network,savepathbson end if savepathbson == "" if Param_Data.Augmentation_Value.augmentationType == "No_channel" - savepathbson = "run/Synth/$(Param_Data.Augmentation_Value.augmentationType)_$(Param_Data.nbTx)_$(Param_Data.Chunksize)_$(Param_Network.Networkname)/$(Param_Data.E)_$(Param_Data.S)/$(Param_Data.E)_$(Param_Data.S)_$(Param_Data.C)_$(Param_Data.RFF)_$(Param_Data.nbSignals)_$(Param_Data.nameModel)/$(hardware1)" + savepathbson = "run/Synth/$(Param_Data.Modulation)/$(Param_Data.Augmentation_Value.augmentationType)_$(Param_Data.nbTx)_$(Param_Data.Chunksize)_$(Param_Network.Networkname)/$(Param_Data.E)_$(Param_Data.S)/$(Param_Data.E)_$(Param_Data.S)_$(Param_Data.C)_$(Param_Data.RFF)_$(Param_Data.nbSignals)_$(Param_Data.nameModel)/$(hardware1)" else - savepathbson = "run/Synth/$(Param_Data.Augmentation_Value.augmentationType)_$(Param_Data.nbTx)_$(Param_Data.Chunksize)_$(Param_Network.Networkname)/$(Param_Data.E)_$(Param_Data.S)/$(Param_Data.E)_$(Param_Data.S)_$(Param_Data.C)_$(Param_Data.RFF)_$(Param_Data.nbSignals)_$(Param_Data.nameModel)_$(Param_Data.Augmentation_Value.Channel)_$(Param_Data.Augmentation_Value.Channel_Test)_nbAugment_$(Param_Data.Augmentation_Value.nb_Augment)/$(hardware1)" + savepathbson = "run/Synth/$(Param_Data.Modulation)/$(Param_Data.Augmentation_Value.augmentationType)_$(Param_Data.nbTx)_$(Param_Data.Chunksize)_$(Param_Network.Networkname)/$(Param_Data.E)_$(Param_Data.S)/$(Param_Data.E)_$(Param_Data.S)_$(Param_Data.C)_$(Param_Data.RFF)_$(Param_Data.nbSignals)_$(Param_Data.nameModel)_$(Param_Data.Augmentation_Value.Channel)_$(Param_Data.Augmentation_Value.Channel_Test)_nbAugment_$(Param_Data.Augmentation_Value.nb_Augment)/$(hardware1)" end end if Param_Data.Augmentation_Value.augmentationType == "No_channel" @@ -85,7 +85,7 @@ function F1_score_Synth(Param_Data,Param_Network,Table_Seed_Network,savepathbson for i =1 :1: size(Table_Seed_Network,1) Param_Network.Seed_Network= Table_Seed_Network[i] name = savename - Scenario ="$(savepathbson)/F1_Score_$(hardware1)_seed_$(Param_Network.Seed_Network)_dr$(Param_Network.Train_args.dr).csv" + Scenario ="$(savepathbson)/F1_Score_$(hardware1)_seed_$(Param_Network.Seed_Network)_dr$(Param_Network.Train_args.dr)_$(Param_Data.Modulation).csv" delim=';' nameBase = split(Scenario,".")[1] # ---------------------------------------------------- @@ -104,7 +104,7 @@ function F1_score_Synth(Param_Data,Param_Network,Table_Seed_Network,savepathbson @pgf push!(a, LegendEntry("Seed $(i)")) # Train) end - pgfsave("$(savepathbson)/F1_Score_$(savename).tex",a) + pgfsave("$(savepathbson)/F1_Score_$(savename)_$(Param_Data.Modulation).tex",a) end @@ -113,7 +113,7 @@ end function Compute_mean(Param_Data,Param_Network,nameSituation,Table_Seed_Network) - savepath = "../My_RFFI_Syst/run/$(Param_Data.Augmentation_Value.augmentationType)_$(Param_Data.nbTx)_$(Param_Data.Chunksize)_$(Param_Network.Networkname)/$(Param_Data.E)_$(Param_Data.S)" + savepath = "run/$(Param_Data.Modulation)/$(Param_Data.Augmentation_Value.augmentationType)_$(Param_Data.nbTx)_$(Param_Data.Chunksize)_$(Param_Network.Networkname)/$(Param_Data.E)_$(Param_Data.S)" if Param_Network.Train_args.use_cuda ==true hardware1 = "GPU" else diff --git a/src/RiFyFi.jl b/src/RiFyFi.jl index c7c916b..d2a27a5 100644 --- a/src/RiFyFi.jl +++ b/src/RiFyFi.jl @@ -30,6 +30,13 @@ using .RiFyFi_VDG include("RiFyFi_IdF/src/RiFyFi_IdF.jl") using .RiFyFi_IdF +include("Augmentation/src/Augmentation.jl") +using .Augmentation + +include("Results/src/Results.jl") +using .Results + + # ---------------------------------------------------- # --- Loading utility functions # ---------------------------------------------------- @@ -60,22 +67,22 @@ function main(Param_Data,Param_Network) (dataTrain,dataTest) = init(Param_Data,Param_Network) if Param_Data.Augmentation_Value.augmentationType == "No_channel" - savepath = "run/Synth/$(Param_Data.Augmentation_Value.augmentationType)_$(Param_Data.nbTx)_$(Param_Data.Chunksize)_$(Param_Network.Networkname)/$(Param_Data.E)_$(Param_Data.S)/$(Param_Data.E)_$(Param_Data.S)_$(Param_Data.C)_$(Param_Data.RFF)_$(Param_Data.nbSignals)_$(Param_Data.nameModel)/$(hardware)" + savepath_model = "run/Synth/$(Param_Data.Modulation)/$(Param_Data.Augmentation_Value.augmentationType)_$(Param_Data.nbTx)_$(Param_Data.Chunksize)_$(Param_Network.Networkname)/$(Param_Data.E)_$(Param_Data.S)/$(Param_Data.E)_$(Param_Data.S)_$(Param_Data.C)_$(Param_Data.RFF)_$(Param_Data.nbSignals)_$(Param_Data.nameModel)/$(hardware)" else - savepath = "run/Synth/$(Param_Data.Augmentation_Value.augmentationType)_$(Param_Data.nbTx)_$(Param_Data.Chunksize)_$(Param_Network.Networkname)/$(Param_Data.E)_$(Param_Data.S)/$(Param_Data.E)_$(Param_Data.S)_$(Param_Data.C)_$(Param_Data.RFF)_$(Param_Data.nbSignals)_$(Param_Data.nameModel)_$(Param_Data.Augmentation_Value.Channel)_$(Param_Data.Augmentation_Value.Channel_Test)_nbAugment_$(Param_Data.Augmentation_Value.nb_Augment)/$(hardware)" + savepath_model = "run/Synth/$(Param_Data.Modulation)/$(Param_Data.Augmentation_Value.augmentationType)_$(Param_Data.nbTx)_$(Param_Data.Chunksize)_$(Param_Network.Networkname)/$(Param_Data.E)_$(Param_Data.S)/$(Param_Data.E)_$(Param_Data.S)_$(Param_Data.C)_$(Param_Data.RFF)_$(Param_Data.nbSignals)_$(Param_Data.nameModel)_$(Param_Data.Augmentation_Value.Channel)_$(Param_Data.Augmentation_Value.Channel_Test)_nbAugment_$(Param_Data.Augmentation_Value.nb_Augment)/$(hardware)" end - !ispath(savepath) && mkpath(savepath) - @infiltrate - (model,trainLoss,trainAcc,testLoss,testAcc,args) = customTrain!(dataTrain,dataTest,savepath,Param_Network) + !ispath(savepath_model) && mkpath(savepath_model) + + (model,trainLoss,trainAcc,testLoss,testAcc,args) = customTrain!(dataTrain,dataTest,savepath_model,Param_Network,Param_Data.Modulation) # ---------------------------------------------------- # --- Saving model # ---------------------------------------------------- - modelpath = joinpath(savepath, "model_seed_$(Param_Network.Seed_Network)_dr$(Param_Network.Train_args.dr).bson") + modelpath = joinpath(savepath_model, "model_seed_$(Param_Network.Seed_Network)_dr$(Param_Network.Train_args.dr)_$(Param_Data.Modulation).bson") nbEpochs = args.epochs BSON.@save modelpath model nbEpochs trainLoss trainAcc testLoss testAcc args testAugmented_acc =0 testAugmented_loss=0 - return (savepath,model,trainLoss,trainAcc,testLoss,testAcc,testAugmented_loss,testAugmented_acc) + return (savepath_model,model,trainLoss,trainAcc,testLoss,testAcc,testAugmented_loss,testAugmented_acc) end diff --git a/src/RiFyFi_IdF/src/RiFyFi_IdF.jl b/src/RiFyFi_IdF/src/RiFyFi_IdF.jl index d30146f..82127be 100644 --- a/src/RiFyFi_IdF/src/RiFyFi_IdF.jl +++ b/src/RiFyFi_IdF/src/RiFyFi_IdF.jl @@ -266,6 +266,8 @@ end function loadCNN(cnnPath) # --- Loading data + # dict = BSON.parse(cnnPath) + dict = BSON.load(cnnPath,@__MODULE__) # --- Exporting variables model = dict[:model] @@ -273,6 +275,7 @@ function loadCNN(cnnPath) trainAcc = dict[:trainAcc] testLoss = dict[:testLoss] trainLoss = dict[:trainLoss] + #=moy = 0 std = 1 try @@ -318,6 +321,8 @@ export Network_struct export Args export Args_construct + + end diff --git a/src/RiFyFi_IdF/src/customTrain.jl b/src/RiFyFi_IdF/src/customTrain.jl index 2a5e506..b4b1fcd 100644 --- a/src/RiFyFi_IdF/src/customTrain.jl +++ b/src/RiFyFi_IdF/src/customTrain.jl @@ -69,7 +69,7 @@ end -function customTrain!(dataTrain,dataTest,savepath,Param_Network) +function customTrain!(dataTrain,dataTest,savepath_model,Param_Network,Modulation) # ---------------------------------------------------- # --- CPU or GPU # ---------------------------------------------------- @@ -151,7 +151,7 @@ function customTrain!(dataTrain,dataTest,savepath,Param_Network) # Timings are calculated per eopch, we want complete time Param_Network.Train_args.timings = cumsum(Param_Network.Train_args.timings;dims=1) # Write timings and accuracy in a file - open("$(savepath)/F1_Score_$(DeviceName)_seed_$(Param_Network.Seed_Network)_dr$(Param_Network.Train_args.dr).csv","w") do io + open("$(savepath_model)/F1_Score_$(DeviceName)_seed_$(Param_Network.Seed_Network)_dr$(Param_Network.Train_args.dr)_$(Modulation).csv","w") do io arr = [Param_Network.Train_args.timings[1:epoch] trainf1 testf1 trainLoss testLoss] writedlm(io,round.(arr;digits=4),';') end diff --git a/src/RiFyFi_VDG/PA_memory_models.mat b/src/RiFyFi_VDG/PA_memory_models.mat new file mode 100644 index 0000000..b73baa9 Binary files /dev/null and b/src/RiFyFi_VDG/PA_memory_models.mat differ diff --git a/src/RiFyFi_VDG/src/RiFyFi_VDG.jl b/src/RiFyFi_VDG/src/RiFyFi_VDG.jl index 6c3557d..ed2a89d 100644 --- a/src/RiFyFi_VDG/src/RiFyFi_VDG.jl +++ b/src/RiFyFi_VDG/src/RiFyFi_VDG.jl @@ -17,7 +17,12 @@ using CSV using DelimitedFiles using DataFrames using Infiltrator -include("../../Augmentation/src/Augmentation.jl") +using DSP +using Plots + + +# Augmentation Module, add channel model on data +include("../../Augmentation/src/Augmentation.jl") using .Augmentation # ---------------------------------------------------- # --- Export @@ -33,10 +38,14 @@ include("utils_dict.jl") # ---------------------------------------------------- # --- Modulator & Demodulator # ---------------------------------------------------- -include("tx.jl") -include("rx.jl") -include("pa_memory.jl") -#include("plotAMAM.jl") +include("tx_OFDM.jl") # Tx for OFDM modulation +include("tx_singleCarrier.jl") # Tx for single Carrier Modulation +include("tx_LoRa.jl") # Tx for LoRa modulation +include("rx.jl") # Receiver (non use) +include("pa_memory.jl") # functions for PA impairments with memory model +include("dynamic_CFO.jl") # functions to simulate a dynamic CFO + + # ---------------------------------------------------- # --- Setup Impairments # ---------------------------------------------------- @@ -50,43 +59,46 @@ export Data_Synth_construct # ---------------------------------------------------- """ Function that create 4 csv files based - - on a fixed scenario RFF parameter + - on a fixed scenario RFF parameter define by RiFyFi_VDG.Data_Synth structure. - on a configuration (define RFF parameters randomly) CSV files: - Training Data - Test Data - Training Labels - - Test Labels """ + - Test Labels + """ function setSynthetiquecsv(Param_Data) (bigMatTrain,bigLabel_Train,bigMatTest,bigLabel_Test,X) = create_virtual_Database(Param_Data) bigLabels_Train = create_bigMat_Labels_Tx(bigLabel_Train) bigLabels_Test = create_bigMat_Labels_Tx(bigLabel_Test) -@infiltrate + if Param_Data.Augmentation_Value.augmentationType == "No_channel" - savepath = "./CSV_Files/$(Param_Data.Augmentation_Value.augmentationType)_$(Param_Data.nbTx)_$(Param_Data.Chunksize)/$(Param_Data.E)_$(Param_Data.S)/$(Param_Data.E)_$(Param_Data.S)_$(Param_Data.C)_$(Param_Data.RFF)_$(Param_Data.nbSignals)_$(Param_Data.nameModel)" + savepath_CSVfiles = "./CSV_Files/$(Param_Data.Modulation)/$(Param_Data.Augmentation_Value.augmentationType)_$(Param_Data.nbTx)_$(Param_Data.Chunksize)/$(Param_Data.E)_$(Param_Data.S)/$(Param_Data.E)_$(Param_Data.S)_$(Param_Data.C)_$(Param_Data.RFF)_$(Param_Data.nbSignals)_$(Param_Data.nameModel)" else - savepath = "./CSV_Files/$(Param_Data.Augmentation_Value.augmentationType)_$(Param_Data.nbTx)_$(Param_Data.Chunksize)/$(Param_Data.E)_$(Param_Data.S)/$(Param_Data.E)_$(Param_Data.S)_$(Param_Data.C)_$(Param_Data.RFF)_$(Param_Data.nbSignals)_$(Param_Data.nameModel)_$(Param_Data.Augmentation_Value.Channel)_$(Param_Data.Augmentation_Value.Channel_Test)_nbAugment_$(Param_Data.Augmentation_Value.nb_Augment)" + savepath_CSVfiles = "./CSV_Files/$(Param_Data.Modulation)/$(Param_Data.Augmentation_Value.augmentationType)_$(Param_Data.nbTx)_$(Param_Data.Chunksize)/$(Param_Data.E)_$(Param_Data.S)/$(Param_Data.E)_$(Param_Data.S)_$(Param_Data.C)_$(Param_Data.RFF)_$(Param_Data.nbSignals)_$(Param_Data.nameModel)_$(Param_Data.Augmentation_Value.Channel)_$(Param_Data.Augmentation_Value.Channel_Test)_nbAugment_$(Param_Data.Augmentation_Value.nb_Augment)" end - !ispath(savepath) && mkpath(savepath) - open("$(savepath)/bigMatTrain.csv","w") do io + !ispath(savepath_CSVfiles) && mkpath(savepath_CSVfiles) + + # Save in CSV files + open("$(savepath_CSVfiles)/bigMatTrain.csv","w") do io for i in 1:size(bigMatTrain)[3] writedlm(io,[vcat(bigMatTrain[:,:,i][:,1],bigMatTrain[:,:,i][:,2])]) end end - open("$(savepath)/bigMatTest.csv","w") do io + open("$(savepath_CSVfiles)/bigMatTest.csv","w") do io for i in 1:size(bigMatTest)[3] writedlm(io,[vcat(bigMatTest[:,:,i][:,1],bigMatTest[:,:,i][:,2])]) end end - open("$(savepath)/bigLabelsTrain.csv","w") do io + open("$(savepath_CSVfiles)/bigLabelsTrain.csv","w") do io for i in 1:size(bigLabels_Train)[1] writedlm(io,[bigLabels_Train[i]]) end end - open("$(savepath)/bigLabelsTest.csv","w") do io + open("$(savepath_CSVfiles)/bigLabelsTest.csv","w") do io for i in 1:size(bigLabels_Test)[1] writedlm(io,[bigLabels_Test[i]]) end @@ -99,83 +111,67 @@ end """ -Create train and test dataset (here matrixes and not dataloader) for a given distance in feet. If the keyword "all" is used the train and test sets uses all distances. -(X_train,Y_train,X_test,Y_test) = create_X_and_Y(distance) +Create train and test dataset (here matrixes and not dataloader) for a configuration decribed by RiFyFi_VDG.Data_Synth structure. +(X_train,Y_train,X_test,Y_test,tupTrain.X) = create_X_and_Y(Param_Data::RiFyFi_VDG.Data_Synth) """ function create_virtual_Database(Param_Data) - shuffle =true - @info "Create Tx" - # --- Def parameters - augmentationType = Param_Data.Augmentation_Value.augmentationType - ChunkSize = Param_Data.Chunksize - nbRadioTx = Param_Data.nbTx - E = Param_Data.E - S = Param_Data.S - C = Param_Data.C - RFF = Param_Data.RFF - name = Param_Data.name - nbSignaux = Param_Data.nbSignals - pourcentTrain = Param_Data.pourcentTrain - seed_data = Param_Data.seed_data - seed_dataTest = Param_Data.seed_dataTest - seed_model = Param_Data.seed_model - seed_modelTest = Param_Data.seed_modelTest + shuffle = true + @info "Create virtual Tx" # ---------------------------------------------------------------- # --- Create configuration with parameters and random impairments # ---------------------------------------------------------------- if Param_Data.configuration == "nothing" @info "Create Tx with random impairments" - savePath="Configurations/$(augmentationType)_$(nbRadioTx)_$(ChunkSize)/$(E)_$(RFF)_$(name)" - !ispath(savePath) && mkpath(savePath) + savePath_config="Configurations/$(Param_Data.Augmentation_Value.augmentationType)_$(Param_Data.nbTx)_$(Param_Data.Chunksize)/$(Param_Data.E)_$(Param_Data.RFF)_$(Param_Data.name)" + !ispath(savePath_config) && mkpath(savePath_config) # --- Create configuration based on mean value and interval parameter - configurationTrain = "$(savePath)/ConfigTrain.json" - configurationTest = "$(savePath)/ConfigTest_$(S).json" - createConfiguration(configurationTrain,ChunkSize,nbRadioTx,nbSignaux,C,seed_model,seed_data) - createConfiguration(configurationTest,ChunkSize,nbRadioTx,nbSignaux,C,seed_modelTest,seed_dataTest) + configurationTrain = "$(savePath_config)/ConfigTrain.json" + configurationTest = "$(savePath_config)/ConfigTest_$(Param_Data.S).json" + createConfiguration(configurationTrain,Param_Data.Chunksize,Param_Data.nbTx,Param_Data.nbSignals,Param_Data.C,Param_Data.seed_model,Param_Data.seed_data) + createConfiguration(configurationTest,Param_Data.Chunksize,Param_Data.nbTx,Param_Data.nbSignals,Param_Data.C,Param_Data.seed_modelTest,Param_Data.seed_dataTest) # --- Generate Database random database correspond to the parameters and configuration - tupTrain = generateDatabase(configurationTrain,E,S,C,RFF,name,Int(nbSignaux*pourcentTrain)) - tupTest = generateDatabase(configurationTest,E,S,C,RFF,name,nbSignaux-Int(nbSignaux*pourcentTrain)) - # Saving configuration of the Database with value of impairments - saveScenario("$(savePath)/scenario.json",tupTrain.dict_out) + tupTrain = generateDatabase(configurationTrain,Param_Data.E,Param_Data.S,Param_Data.C,Param_Data.RFF,Param_Data.name,Param_Data.Modulation,Int(Param_Data.nbSignals*Param_Data.pourcentTrain)) + tupTest = generateDatabase(configurationTest,Param_Data.E,Param_Data.S,Param_Data.C,Param_Data.RFF,Param_Data.name,Param_Data.Modulation,Param_Data.nbSignals-Int(Param_Data.nbSignals*Param_Data.pourcentTrain)) + # --- Save configuration of the Database with value of impairments + saveScenario("$(savePath_config)/scenario.json",tupTrain.dict_out) # --------------------------------------------------------------------------- # --- Create configuration with fixe RFF impairments define in scenario file # --------------------------------------------------------------------------- elseif Param_Data.configuration == "scenario" # --- Generate Database with fixe impairments scenario - @info "Create Tx based on scenario $(E) $(RFF) $(name)" - savePath="Configurations/$(augmentationType)_$(nbRadioTx)_$(ChunkSize)/$(E)_$(RFF)_$(name)" - !ispath(savePath) && mkpath(savePath) + @info "Create Tx based on scenario $(Param_Data.E) $(Param_Data.RFF) $(Param_Data.name)" + savePath_config="Configurations/$(Param_Data.Augmentation_Value.augmentationType)_$(Param_Data.nbTx)_$(Param_Data.Chunksize)/$(Param_Data.E)_$(Param_Data.RFF)_$(Param_Data.name)" + !ispath(savePath_config) && mkpath(savePath_config) # --- Create configuration based on parameter - configurationTrain = "$(savePath)/ConfigTrain.json" - configurationTest = "$(savePath)/ConfigTest_$(S).json" - createConfiguration(configurationTrain,ChunkSize,nbRadioTx,nbSignaux,C,seed_model,seed_data) - createConfiguration(configurationTest,ChunkSize,nbRadioTx,nbSignaux,C,seed_modelTest,seed_dataTest) + configurationTrain = "$(savePath_config)/ConfigTrain.json" + configurationTest = "$(savePath_config)/ConfigTest_$(Param_Data.S).json" + createConfiguration(configurationTrain,Param_Data.Chunksize,Param_Data.nbTx,Param_Data.nbSignals,Param_Data.C,Param_Data.seed_model,Param_Data.seed_data) + createConfiguration(configurationTest,Param_Data.Chunksize,Param_Data.nbTx,Param_Data.nbSignals,Param_Data.C,Param_Data.seed_modelTest,Param_Data.seed_dataTest) # --- Create database based on scenarios impairments previously defined - s_d_mismatch,s_d_cfo,s_d_phaseNoise,s_d_nonLinearPA = reloadScenario("$(savePath)/scenario.json",RFF) - tupTrain = generateDatabase(configurationTrain,E,S,C,RFF,name,Int(nbSignaux*pourcentTrain);s_d_mismatch, s_d_cfo, s_d_phaseNoise, s_d_nonLinearPA) - tupTest = generateDatabase(configurationTest,E,S,C,RFF,name,nbSignaux-Int(nbSignaux*pourcentTrain);s_d_mismatch, s_d_cfo, s_d_phaseNoise, s_d_nonLinearPA) + s_d_mismatch,s_d_cfo,s_d_phaseNoise,s_d_nonLinearPA = reloadScenario("$(savePath_config)/scenario.json",RFF) + tupTrain = generateDatabase(configurationTrain,Param_Data.E,Param_Data.S,Param_Data.C,Param_Data.RFF,Param_Data.name,Param_Data.Modulation,Int(Param_Data.nbSignals*Param_Data.pourcentTrain);s_d_mismatch, s_d_cfo, s_d_phaseNoise, s_d_nonLinearPA) + tupTest = generateDatabase(configurationTest,Param_Data.E,Param_Data.S,Param_Data.C,Param_Data.RFF,Param_Data.name,Param_Data.Modulation,Param_Data.nbSignals-Int(Param_Data.nbSignals*Param_Data.pourcentTrain);s_d_mismatch, s_d_cfo, s_d_phaseNoise, s_d_nonLinearPA) end # --- Compute dimension of Matrices - nbChunks = nbSignaux *nbRadioTx # size(tupTrain.bigMat,3) + size(tupTest.bigMat,3) - nbTrain = Int(round(pourcentTrain*nbChunks)) # size(tupTrain.bigMat,3) - nbTest = nbChunks - nbTrain # size(tupTest.bigMat,3) - nbTrain_per_radio =Int(nbTrain/nbRadioTx) - nbTest_per_radio =Int(nbTest/nbRadioTx) + nbChunks = Param_Data.nbSignals * Param_Data.nbTx + nbTrain = Int(round(Param_Data.pourcentTrain * nbChunks)) + nbTest = nbChunks - nbTrain + nbTrain_per_radio =Int(nbTrain/Param_Data.nbTx) + nbTest_per_radio =Int(nbTest/Param_Data.nbTx) X_trainTemp = tupTrain.bigMat X_testTemp = tupTest.bigMat - - # --- Pour chaque radio TX on complète les matrices de labels - if name =="1VsAll" + # --- Creation of label for each transmitter + if Param_Data.name =="1VsAll" Y_trainTemp = zeros(2,nbTrain) Y_testTemp = zeros(2,nbTest) for iR =1 :1:2 - Y_trainTemp[iR,(nbRadioTx-1)*((iR-1)*nbTrain_per_radio)+1:(nbRadioTx-2+iR)*nbTrain_per_radio] .= 1 - Y_testTemp[iR,(nbRadioTx-1)*((iR-1)*nbTest_per_radio)+1:(nbRadioTx-2+iR)*nbTest_per_radio] .= 1 + Y_trainTemp[iR,(Param_Data.nbTx-1)*((iR-1)*nbTrain_per_radio)+1:(Param_Data.nbTx-2+iR)*nbTrain_per_radio] .= 1 + Y_testTemp[iR,(Param_Data.nbTx-1)*((iR-1)*nbTest_per_radio)+1:(Param_Data.nbTx-2+iR)*nbTest_per_radio] .= 1 end else - Y_trainTemp = zeros(nbRadioTx,nbTrain) - Y_testTemp = zeros(nbRadioTx,nbTest) - for iR =1 :1:nbRadioTx + Y_trainTemp = zeros(Param_Data.nbTx,nbTrain) + Y_testTemp = zeros(Param_Data.nbTx,nbTest) + for iR =1 :1:Param_Data.nbTx Y_trainTemp[iR,(iR-1)*nbTrain_per_radio+1:iR*nbTrain_per_radio] .= 1 Y_testTemp[iR,(iR-1)*nbTest_per_radio+1:iR*nbTest_per_radio] .= 1 end @@ -183,47 +179,42 @@ function create_virtual_Database(Param_Data) # -------------------------------------------------- # --- Add Channel / Augmented Data # -------------------------------------------------- - if augmentationType=="augment" || augmentationType=="same_channel" || augmentationType=="1channelTest" - nbAugment = Param_Data.Augmentation_Value.nb_Augment - @info nbAugment - channel =Param_Data.Augmentation_Value.Channel - channel_Test =Param_Data.Augmentation_Value.Channel_Test - seed_channel = Param_Data.Augmentation_Value.seed_channel - seed_channel_test = Param_Data.Augmentation_Value.seed_channel_test - burstSize = Param_Data.Augmentation_Value.burstSize - if augmentationType=="augment" - N = Int(nbSignaux * pourcentTrain) # on génère toujours nbSignaux par canal - ( X_train,Y_train)=Augmentation.Add_diff_Channel_train_test(X_trainTemp,Y_trainTemp,N,channel,ChunkSize,nbAugment,nbRadioTx,seed_channel,burstSize) + if (Param_Data.Augmentation_Value.augmentationType=="augment" || + Param_Data.Augmentation_Value.augmentationType=="same_channel" || + Param_Data.Augmentation_Value.augmentationType=="1channelTest") + @info "Augmentation * " Param_Data.Augmentation_Value.nb_Augment + if Param_Data.Augmentation_Value.augmentationType=="augment" + N = Int(Param_Data.nbSignals * Param_Data.pourcentTrain) # on génère toujours nbSignaux par canal + ( X_train,Y_train)=Augmentation.Add_diff_Channel_train_test(X_trainTemp,Y_trainTemp,N,Param_Data.Augmentation_Value.Channel,Param_Data.Chunksize,Param_Data.Augmentation_Value.nb_Augment,Param_Data.nbTx,Param_Data.Augmentation_Value.seed_channel,Param_Data.Augmentation_Value.burstSize) @info size(X_train) # TEST - N = nbSignaux - N + N = Param_Data.nbSignals - N nbAugment_Test = 100 - (X_test,Y_test)=Augmentation.Add_diff_Channel_train_test(X_testTemp,Y_testTemp,N,channel_Test,ChunkSize,nbAugment_Test,nbRadioTx,seed_channel_test,burstSize) - elseif augmentationType=="same_channel" - N = Int(nbSignaux * pourcentTrain) # on génère toujours nbSignaux par canal - ( X_train,Y_train)=Augmentation.Add_diff_Channel_train_test(X_trainTemp,Y_trainTemp,N,channel,ChunkSize,nbAugment,nbRadioTx,seed_channel,burstSize) + (X_test,Y_test)=Augmentation.Add_diff_Channel_train_test(X_testTemp,Y_testTemp,N,Param_Data.Augmentation_Value.Channel_Test,Param_Data.Chunksize,nbAugment_Test,Param_Data.nbTx,Param_Data.Augmentation_Value.seed_channel_test,Param_Data.Augmentation_Value.burstSize) + elseif Param_Data.Augmentation_Value.augmentationType=="same_channel" + N = Int(Param_Data.nbSignals * Param_Data.pourcentTrain) # on génère toujours nbSignaux par canal + ( X_train,Y_train)=Augmentation.Add_diff_Channel_train_test(X_trainTemp,Y_trainTemp,N,Param_Data.Augmentation_Value.Channel,Param_Data.Chunksize,Param_Data.Augmentation_Value.nb_Augment,Param_Data.nbTx,Param_Data.Augmentation_Value.seed_channel,Param_Data.Augmentation_Value.burstSize) # TEST - N = nbSignaux - N - nbAugment_Test = nbAugment - seed_channel_test = seed_channel - (X_test,Y_test)=Augmentation.Add_diff_Channel_train_test(X_testTemp,Y_testTemp,N,channel,ChunkSize,nbAugment_Test,nbRadioTx,seed_channel_test,burstSize) + N = Param_Data.nbSignals - N + nbAugment_Test = Param_Data.Augmentation_Value.nb_Augment + (X_test,Y_test)=Augmentation.Add_diff_Channel_train_test(X_testTemp,Y_testTemp,N,Param_Data.Augmentation_Value.Channel,Param_Data.Chunksize,nbAugment_Test,Param_Data.nbTx,Param_Data.Augmentation_Value.seed_channel,Param_Data.Augmentation_Value.burstSize) end else - nbAugment = 1 + Param_Data.Augmentation_Value.nb_Augment = 1 + nbAugment_Test =1 X_train =X_trainTemp X_test=X_testTemp Y_train=Y_trainTemp Y_test=Y_testTemp - nbAugment_Test =1 end # ---------------------------------------- # --- Shuffle signals with labels # ---------------------------------------- if shuffle - X_trainS = zeros(Float32,ChunkSize,2,nbTrain*nbAugment) - Y_trainS = zeros(Float32,nbRadioTx,nbTrain*nbAugment) - X_testS = zeros(Float32,ChunkSize,2,nbTest*nbAugment_Test) - Y_testS = zeros(Float32,nbRadioTx,nbTest*nbAugment_Test) + X_trainS = zeros(Float32,Param_Data.Chunksize,2,nbTrain*Param_Data.Augmentation_Value.nb_Augment) + Y_trainS = zeros(Float32,Param_Data.nbTx,nbTrain*Param_Data.Augmentation_Value.nb_Augment) + X_testS = zeros(Float32,Param_Data.Chunksize,2,nbTest*nbAugment_Test) + Y_testS = zeros(Float32,Param_Data.nbTx,nbTest*nbAugment_Test) indexes = randperm(Int(size(X_train,3))) for i =1 :1 :size(X_train,3) X_trainS[:,:,(i)] = X_train[:,:,(indexes[i])] @@ -250,61 +241,49 @@ function create_virtual_Database(Param_Data) return (X_train,Y_train,X_test,Y_test,tupTrain.X) end -""" Function that load data from the CSV file for Synthetic database +""" Function that load data from the CSV file for Synthetic database based on configuration described by +RiFyFi_VDG.Data_Synth struct """ function loadCSV_Synthetic(Param_Data) - augmentationType = Param_Data.Augmentation_Value.augmentationType - ChunkSize = Param_Data.Chunksize - nbRadioTx = Param_Data.nbTx - E = Param_Data.E - S = Param_Data.S - C = Param_Data.C - RFF = Param_Data.RFF - name = Param_Data.name - nbSignaux = Param_Data.nbSignals - pourcentTrain = Param_Data.pourcentTrain - - nbChunks=Int(nbRadioTx*nbSignaux) - nbTrain = Int(round(pourcentTrain*nbChunks)) + + nbChunks=Int(Param_Data.nbTx*Param_Data.nbSignals) + nbTrain = Int(round(Param_Data.pourcentTrain*nbChunks)) nbTest = nbChunks - nbTrain - if augmentationType == "No_channel" - savepath = "./CSV_Files/$(augmentationType)_$(nbRadioTx)_$(ChunkSize)/$(E)_$(S)/$(E)_$(S)_$(C)_$(RFF)_$(nbSignaux)_$(name)" + if Param_Data.Augmentation_Value.augmentationType == "No_channel" + savepath_CSVfiles = "./CSV_Files/$(Param_Data.Modulation)/$(Param_Data.Augmentation_Value.augmentationType)_$(Param_Data.nbTx)_$(Param_Data.Chunksize)/$(Param_Data.E)_$(Param_Data.S)/$(Param_Data.E)_$(Param_Data.S)_$(Param_Data.C)_$(Param_Data.RFF)_$(Param_Data.nbSignals)_$(Param_Data.name)" else - channel = Param_Data.Augmentation_Value.Channel - channel_Test = Param_Data.Augmentation_Value.Channel_Test - nbAugment = Param_Data.Augmentation_Value.nb_Augment - savepath = "./CSV_Files/$(Param_Data.Augmentation_Value.augmentationType)_$(Param_Data.nbTx)_$(Param_Data.Chunksize)/$(Param_Data.E)_$(Param_Data.S)/$(Param_Data.E)_$(Param_Data.S)_$(Param_Data.C)_$(Param_Data.RFF)_$(Param_Data.nbSignals)_$(Param_Data.nameModel)_$(Param_Data.Augmentation_Value.Channel)_$(Param_Data.Augmentation_Value.Channel_Test)_nbAugment_$(Param_Data.Augmentation_Value.nb_Augment)" - nbTrain = nbTrain * nbAugment - if augmentationType == "1channelTest" + savepath_CSVfiles = "./CSV_Files/$(Param_Data.Modulation)/$(Param_Data.Augmentation_Value.augmentationType)_$(Param_Data.nbTx)_$(Param_Data.Chunksize)/$(Param_Data.E)_$(Param_Data.S)/$(Param_Data.E)_$(Param_Data.S)_$(Param_Data.C)_$(Param_Data.RFF)_$(Param_Data.nbSignals)_$(Param_Data.nameModel)_$(Param_Data.Augmentation_Value.Channel)_$(Param_Data.Augmentation_Value.Channel_Test)_nbAugment_$(Param_Data.Augmentation_Value.nb_Augment)" + nbTrain = nbTrain * Param_Data.Augmentation_Value.nb_Augment + if Param_Data.Augmentation_Value.augmentationType == "1channelTest" nbTest = nbTest * 1 - elseif augmentationType == "same_channel" + elseif Param_Data.Augmentation_Value.augmentationType == "same_channel" nbTest = nbTest * 1 - else augmentationType == "augment" + else Param_Data.Augmentation_Value.augmentationType == "augment" nbTest = nbTest * 100 end end # Labels - fileLabelTest= "$(savepath)/bigLabelsTest.csv" + fileLabelTest= "$(savepath_CSVfiles)/bigLabelsTest.csv" Y_testTemp = Matrix(DataFrame(CSV.File(fileLabelTest;types=Int64,header=false))) - fileLabelTrain= "$(savepath)/bigLabelsTrain.csv" + fileLabelTrain= "$(savepath_CSVfiles)/bigLabelsTrain.csv" Y_trainTemp = Matrix(DataFrame(CSV.File(fileLabelTrain;types=Int64,header=false))) # Data - fileDataTest= "$(savepath)/bigMatTest.csv" + fileDataTest= "$(savepath_CSVfiles)/bigMatTest.csv" X_testTemp = Matrix(DataFrame(CSV.File(fileDataTest;types=Float32,header=false))) - fileDataTrain= "$(savepath)/bigMatTrain.csv" + fileDataTrain= "$(savepath_CSVfiles)/bigMatTrain.csv" X_trainTemp = Matrix(DataFrame(CSV.File(fileDataTrain;types=Float32,header=false))) - X_train = zeros(Float32, ChunkSize,2,nbTrain) - X_test = zeros(Float32, ChunkSize,2,nbTest) - Y_train = zeros(nbRadioTx,nbTrain) - Y_test = zeros(nbRadioTx,nbTest) + X_train = zeros(Float32, Param_Data.Chunksize,2,nbTrain) + X_test = zeros(Float32, Param_Data.Chunksize,2,nbTest) + Y_train = zeros(Param_Data.nbTx,nbTrain) + Y_test = zeros(Param_Data.nbTx,nbTest) for i in 1:size(X_trainTemp)[1] - X_train[:,1,i]=X_trainTemp[i,1:ChunkSize] - X_train[:,2,i]=X_trainTemp[i,ChunkSize+1:ChunkSize+ChunkSize] + X_train[:,1,i]=X_trainTemp[i,1:Param_Data.Chunksize] + X_train[:,2,i]=X_trainTemp[i,Param_Data.Chunksize+1:Param_Data.Chunksize+Param_Data.Chunksize] end for i in 1:size(X_testTemp)[1] - X_test[:,1,i]=X_testTemp[i,1:ChunkSize] - X_test[:,2,i]=X_testTemp[i,ChunkSize+1:ChunkSize+ChunkSize] + X_test[:,1,i]=X_testTemp[i,1:Param_Data.Chunksize] + X_test[:,2,i]=X_testTemp[i,Param_Data.Chunksize+1:Param_Data.Chunksize+Param_Data.Chunksize] end for i in 1:size(Y_trainTemp)[1] Y_train[Y_trainTemp[i]+1,i]=1 @@ -320,9 +299,9 @@ end """ Generates a datbase based on the configuration stored in the JSON file `filename` """ -function generateDatabase(filename::String,E::String,S::String,C::String,RFF::String,name::String,nbSignaux::Int;kw...) +function generateDatabase(filename::String,E::String,S::String,C::String,RFF::String,name::String,Modulation::String,nbSignaux::Int;kw...) dict = loadConfiguration(filename) - return generateDatabase(dict,E,S,C,RFF,name,nbSignaux;kw...) + return generateDatabase(dict,E,S,C,RFF,name,Modulation,nbSignaux;kw...) end """ Create a default constructor if no input structure is given. Otherwise, returns the structure @@ -340,9 +319,9 @@ end """ Dispatch when dict is composed with symbols """ -function generateDatabase(dict::AbstractDict{Symbol,Any},E,S,C,RFF,name,nbSignaux;kw...) +function generateDatabase(dict::AbstractDict{Symbol,Any},E,S,C,RFF,name,Modulation,nbSignaux;kw...) ds = string_dict(dict) - generateDatabase(ds,E,S,C,RFF,name,nbSignaux;kw...) + generateDatabase(ds,E,S,C,RFF,name,Modulation,nbSignaux;kw...) end """ Generate a vector of RF impairments structure, based on the filename. The output can be used as input of generateDatabase. The file used as input should habe been generated from saveScenario, whose output is from generateDatabase @@ -391,7 +370,7 @@ end """ Core signal generation, using a Dict for configuration. Each impairment config can be overwritted by custom config """ -function generateDatabase(dict::AbstractDict{String,Any},E,S,C,RFF,name,nbSignaux; +function generateDatabase(dict::AbstractDict{String,Any},E,S,C,RFF,name,Modulation,nbSignaux; s_d_mismatch::Union{Vector{RFImpairmentsModels.IQMismatch},Nothing} = nothing, # Force config for IQ Mismatch s_d_cfo::Union{Vector{RFImpairmentsModels.CFO},Nothing} = nothing , # Force config for CFO s_d_phaseNoise::Union{Vector{RFImpairmentsModels.PhaseNoiseModel},Nothing}= nothing , # Force config for PN @@ -412,7 +391,21 @@ function generateDatabase(dict::AbstractDict{String,Any},E,S,C,RFF,name,nbSignau # --- Fill matrix with data # ---------------------------------------------------- # --- First associate OFDM symbols with number of IQ samples - tmp,_,_ = tx(1) + if Modulation == "OFDM" + tmp,_,_ = tx(1) + @info "OFDM" + elseif Modulation == "SC" + tmp = singleCarrierTx(1) + @info " Single Carrier Modulation " + elseif Modulation == "LoRa" + SF = 7 + BW =1 + Fs = 1 + (tmp,_,_,_,_) = Gen_symb_SF(SF,1,BW,Fs,1) + @info " LoRa Modulation " + else + @info "ERREUR" + end size_symb = length(tmp) # We split in independent burst of duration max_burst_size nb_bursts = nb_chunks ÷ max_burst_size +1 @@ -423,23 +416,16 @@ function generateDatabase(dict::AbstractDict{String,Any},E,S,C,RFF,name,nbSignau bigMat = zeros(Float32,chunk_size,2,nb_chunks*nb_radios) bigLabels = zeros(nb_radios,nb_chunks*nb_radios) dict_out = Dict() - X=zeros(ComplexF32,548*nb_symb_per_bursts*nb_bursts,nb_radios) + X=zeros(ComplexF32,size_symb*nb_symb_per_bursts*nb_bursts,nb_radios) # --- Iterative generation #= X_brut = zeros(Float32,4,263040,2) savepath = "CSV_Files/sans_4_256/E1_S2/E1_S2_C1_all_impairments_1000_" brut1= "$(savepath)/X_brut1.csv" X_brut[1,:,:] = Matrix(DataFrame(CSV.File(brut1;types=Float64,header=false))) - brut2= "$(savepath)/X_brut2.csv" - X_brut[2,:,:] = Matrix(DataFrame(CSV.File(brut2;types=Float64,header=false))) - brut3= "$(savepath)/X_brut3.csv" - X_brut[3,:,:] = Matrix(DataFrame(CSV.File(brut3;types=Float64,header=false))) - brut4= "$(savepath)/X_brut4.csv" - X_brut[4,:,:] = Matrix(DataFrame(CSV.File(brut4;types=Float64,header=false))) - nbIQ= 16440 =# for r ∈ 1 : nb_radios - #= + #= ## Used To permut the transmitter impairment if r==1 permut=3 r=permut @@ -506,19 +492,15 @@ function generateDatabase(dict::AbstractDict{String,Any},E,S,C,RFF,name,nbSignau Random.seed!(seed_models + (r-1)* nb_bursts + r + k ) end end - # We instantiate a new channel model - s_channel = setup_channel(dict,r,k) - # We should start to random phase for PN + # We should start to random phase for PN randomize_phaseNoise!(s_phaseNoise) - # @info k , s_phaseNoise - # ajout de bruit + # Random Phase Noise Random.seed!(seed_models + (r-1)* nb_bursts + r + k ) - s_noise = setup_awgn(dict,r,k) # We calculate a new fading factor FIXME => Related to SNR ? - s_power = setup_rx_power(dict,r,s_noise,k) + # s_power = setup_rx_power(dict,r,s_noise,k) # ---------------------------------------------------- # --- Create the pure tx signal @@ -532,9 +514,20 @@ function generateDatabase(dict::AbstractDict{String,Any},E,S,C,RFF,name,nbSignau Random.seed!(seed_data + (r-1)* nb_bursts + r + k ) end end - (x,_,_) = tx(nb_symb_per_bursts) - x=x.*10 - nbIQperBurst =548*nb_symb_per_bursts + if Modulation == "OFDM" + (x,_,_) = tx(nb_symb_per_bursts) + x=x.*10 + elseif Modulation == "SC" + x = singleCarrierTx(nb_symb_per_bursts) + elseif Modulation == "LoRa" + SF = 7 + BW =1 + Fs = 1 + (x,_,_,_,_) = Gen_symb_SF(SF,nb_symb_per_bursts,BW,Fs,1) + else + @info "ERREUR" + end + nbIQperBurst =size_symb*nb_symb_per_bursts X[(k-1)*nbIQperBurst+1:k*nbIQperBurst,r] = x # ------------------------------------------- # -- Tx impairments avec seed Fingerprint @@ -548,6 +541,9 @@ function generateDatabase(dict::AbstractDict{String,Any},E,S,C,RFF,name,nbSignau Random.seed!(seed_models + (r-1)* nb_bursts + r + k ) end end + # ------------------------------------------- + # --- To study the individual impact of impairments + # ------------------------------------------- if RFF == "imbalance" # IQ Mismatch addIQMismatch!(x,s_mismatch) @@ -557,6 +553,8 @@ function generateDatabase(dict::AbstractDict{String,Any},E,S,C,RFF,name,nbSignau elseif RFF == "cfo" # Add CFO RFImpairmentsModels.addCFO!(x,s_cfo) + elseif RFF == "dynamic_cfo" + add_dynamic_CFO!(x,s_cfo) elseif RFF == "PA_memory" # Non linear PA memory if E == "E1" @@ -575,23 +573,35 @@ function generateDatabase(dict::AbstractDict{String,Any},E,S,C,RFF,name,nbSignau # PlotingAMAM_Saleh(x[1:2000],y[1:2000],RFF,r,E,S,C,name) x = y end - else + # ------------------------------------------- + # --- To study the Conglomerate impact of impairments + # ------------------------------------------- + elseif RFF == "all_impairments_dynamic_cfo" # All Impairments addIQMismatch!(x,s_mismatch) addPhaseNoise!(x,s_phaseNoise) # Imperfection Dynamique - RFImpairmentsModels.addCFO!(x,s_cfo) + add_dynamic_CFO!(x,s_cfo) if RFF=="all_impairments_memory" x=addNonLinearPA_memory(x,s_nonLinearPA,r) else x=addNonLinearPA(x,s_nonLinearPA) end + else # All Impairments + addIQMismatch!(x,s_mismatch) + addPhaseNoise!(x,s_phaseNoise) # Imperfection Dynamique + RFImpairmentsModels.addCFO!(x,s_cfo) + if RFF=="all_impairments_memory" + x=addNonLinearPA_memory(x,s_nonLinearPA,r) + else + x=addNonLinearPA(x,s_nonLinearPA) + end end # ---------------------------------------------------- - # -- Multipath channel model + # -- Noise model # ---------------------------------------------------- - if C=="C1" + if C=="C1" # No noise out=x - elseif C=="C3" + elseif C=="C3" # Add random noise between 10dB and 30dB Random.seed!(seed_models + (r-1)* nb_bursts + r + k ) s_noise = Int(rand(1:3)*10) out,_ = addNoise(x,s_noise) @@ -600,10 +610,7 @@ function generateDatabase(dict::AbstractDict{String,Any},E,S,C,RFF,name,nbSignau out,_ = addNoise(x,s_noise) end - # ---------------------------------------------------- - # Rx impairments - A completer ailleur - # ---------------------------------------------------- - + if k== nb_bursts rest= nb_chunks-(nb_bursts-1)*max_burst_size out=x[1:rest*chunk_size] diff --git a/src/RiFyFi_VDG/src/Struct_data.jl b/src/RiFyFi_VDG/src/Struct_data.jl index e0299a1..52f9d8f 100644 --- a/src/RiFyFi_VDG/src/Struct_data.jl +++ b/src/RiFyFi_VDG/src/Struct_data.jl @@ -1,21 +1,22 @@ Base.@kwdef mutable struct Data_Synth - name::String = "" - nameModel::String = "" - nbTx::Int = 4 - nbSignals::Int = 12000 - Chunksize::Int = 256 - features::String= "IQsamples" - S::String = "S1" - E::String = "E2" - C::String = "C2_20dB" - RFF::String = "all_impairments" - Normalisation::Bool = true - pourcentTrain::Float64 =0.9 - configuration::String = "non" - seed_data::Int = 1234 + name::String = "" # Name use to save the configuration + nameModel::String = "" # Name use to save the configuration + nbTx::Int = 4 # Nb transmitters in the database + nbSignals::Int = 12000 # Nb signals per transmitter for Train + test + Chunksize::Int = 256 # Size of packet + features::String= "IQsamples" # In this version always use "IQsamples" + S::String = "S1" # S described the type of signal trame use in database (S1 preamble, S2 MAC address, S3 Payload) + E::String = "E3" # E3 always to have a dynamic Phase noise impairments and different impairments for each transmitter + C::String = "C2_20dB" # C described the level of noise + RFF::String = "all_impairments" # define the impairments which are activate + Normalisation::Bool = true # Normalise dataset + pourcentTrain::Float64 =0.9 # Define the proportion of the Train /Test sets + configuration::String = "nothing" # use "scenario" to reload a predefined scenario or "nothing" to let the generator create a random scenario + seed_data::Int = 1234 # Define the seed to ensure random and reproductible result seed_model::Int = 2345 seed_dataTest::Int = 1234 seed_modelTest::Int = 2345 + Modulation::String = "OFDM" # define the Modulation Augmentation_Value = Data_Augmented_construct() end @@ -122,10 +123,16 @@ function Data_Synth_construct(; kwargs...) seed_modelTest = 15987654321 end + if haskey(kwargs, :Modulation) + Modulation = kwargs[:Modulation] + else + Modulation = "" + end + if haskey(kwargs, :Augmentation_Value) Augmentation_Value = kwargs[:Augmentation_Value] else Augmentation_Value = Data_Augmented_construct() end -return Data_Synth(name,nameModel,nbTx,nbSignals,Chunksize,features,S,E,C,RFF,Normalisation,pourcentTrain,configuration,seed_data,seed_model,seed_dataTest,seed_modelTest,Augmentation_Value) +return Data_Synth(name,nameModel,nbTx,nbSignals,Chunksize,features,S,E,C,RFF,Normalisation,pourcentTrain,configuration,seed_data,seed_model,seed_dataTest,seed_modelTest,Modulation,Augmentation_Value) end diff --git a/src/RiFyFi_VDG/src/dynamic_CFO.jl b/src/RiFyFi_VDG/src/dynamic_CFO.jl new file mode 100644 index 0000000..d597478 --- /dev/null +++ b/src/RiFyFi_VDG/src/dynamic_CFO.jl @@ -0,0 +1,18 @@ +"function to add a dynamic CFO " +function add_dynamic_CFO!(y::AbstractVector{Complex{T}},x::AbstractVector,δ::Number,fs::Number,ϕ=0) where {T<:Real} + # --- Basic array check + @assert length(x) == length(y) "Input and output should have same length (here input x is $(length(x)) and pre-allocated output has size $(length(y))" + # --- CFO pulsation + + dynamic = rand(9500:10500)/10000 + ω = δ / fs * dynamic + # --- Adding CFO + @inbounds @simd for n ∈ eachindex(x) + y[n] = x[n] * Complex{T}(exp(2im*π*ω*( (n-1) + ϕ))) + end +end + + +function add_dynamic_CFO!(x::AbstractVector,cfo::RFImpairmentsModels.CFO) + add_dynamic_CFO!(x,x,cfo.f,cfo.fs,cfo.ϕ) +end diff --git a/src/RiFyFi_VDG/src/pa_memory.jl b/src/RiFyFi_VDG/src/pa_memory.jl index b6472e6..43072a7 100644 --- a/src/RiFyFi_VDG/src/pa_memory.jl +++ b/src/RiFyFi_VDG/src/pa_memory.jl @@ -25,7 +25,7 @@ end function setup_nonLinearPA_memory(dict,indexRadio) with_nonLinearPA = @loadKey dict "with_nonLinearPA" false if with_nonLinearPA - file= matopen("../My_Signal_Synthesis/PA_memory_models.mat") + file= matopen("./src/RiFyFi_VDG/PA_memory_models.mat") parameters=read(file)["parameters"] param = parameters[indexRadio]; order = Int(param["pa"]["P"]); # nonlinearity order of the PA @@ -45,7 +45,6 @@ end #pa = parameters[r]["pa"] # on réccupère les paramètres du PA de la radio numéro r - #memory = [1,2,2,2,2] #order = 9 @@ -53,8 +52,6 @@ end #bandwidth = 120e6 #pa_coefficients = zeros(ComplexF64,sum(memory)) # To be changed with correct coefficients - - # Init the structure #pa = Memory_PowerAmplifier(pa_coefficients,order,memory,backoff,bandwidth) @@ -74,17 +71,13 @@ end function memoryPA(input,pa::Memory_PowerAmplifier,r) - - # A changer pour réccupére les donner la la structure pa # Memory polynomial PA model L_in = length(input); M = pa.memory; # memory order of the PA P = pa.order; # nonlinearity order of the PA backoff =pa.backoff - ###### - # A conserver - ##### + # Scale input power according to the specified back-off Pin = mean(abs.(input).^2); # store the input power, and scale back to it after the TX model scale_input = 1/sqrt(10^(backoff/10)*Pin); # 0 dB back-off corresponds to input power=1 diff --git a/src/RiFyFi_VDG/src/setup_impairments.jl b/src/RiFyFi_VDG/src/setup_impairments.jl index a3d3256..a64a7db 100644 --- a/src/RiFyFi_VDG/src/setup_impairments.jl +++ b/src/RiFyFi_VDG/src/setup_impairments.jl @@ -2,9 +2,6 @@ """ Create a configuration for IQ mismatch for a given radio based on configuation in dict """ function setup_IQMismatch(dict,r) - # Seed - # seed_models = @loadKey dict "seed_models" 12345 - # Random.seed!(seed_models + r + 10) # --- Loading config with_iq_mismatch = @loadKey dict "with_iq_mismatch" false if !with_iq_mismatch @@ -26,9 +23,6 @@ end """ Create a configuration for CFO for a given radio based on configuation in dict """ function setup_CFO(dict,r) - # Seed - # seed_models = @loadKey dict "seed_models" 12345 - # Random.seed!(seed_models + r + 100) with_cfo = @loadKey dict "with_cfo" false sampling_rate = @loadKey dict "sampling_rate" 1 @@ -43,6 +37,10 @@ function setup_CFO(dict,r) end end + + + + """ Create a configuration for phase noise for a given radio based on configuation in dict """ function setup_phaseNoise(dict::Dict{String},r) @@ -66,9 +64,6 @@ end """ Create a configuration for AWGN for a given radio based on configuation in dict """ function setup_awgn(dict,r,k) - # Seed - # seed_models = @loadKey dict "seed_models" 12345 - # Random.seed!(seed_models + r + k + 2000) with_noise = @loadKey dict "with_awgn" false if with_noise awgn_snr_base = @loadKey dict "awgn_snr_base" 80 @@ -81,9 +76,6 @@ function setup_awgn(dict,r,k) end function setup_nonLinearPA(dict,indexRadio) - # Seed - # seed_models = @loadKey dict "seed_models" 12345 - # Random.seed!(seed_models + indexRadio + 3000) with_nonLinearPA = @loadKey dict "with_nonLinearPA" false if with_nonLinearPA # pa_models = @loadKey dict "nonLinearPA_models" :Linear @@ -113,9 +105,6 @@ end function setup_nonLinearPA_control(dict,indexRadio) pourcentage =0.1 - # Seed - # seed_models = @loadKey dict "seed_models" 12345 - # Random.seed!(seed_models + indexRadio + 3000) with_nonLinearPA = @loadKey dict "with_nonLinearPA" false if with_nonLinearPA # pa_models = @loadKey dict "nonLinearPA_models" :Linear @@ -159,9 +148,7 @@ end """ Apply power reduction to signal to emulate distance. Returns a scaling factor to multiply with the rx signal """ function setup_rx_power(dict,r,snr,k) - # Seed - # seed_models = @loadKey dict "seed_models" 12345 - # Random.seed!(seed_models + r + k + 5000) + with_rx_power = @loadKey dict "with_rx_power" false if !with_rx_power scale = 1 diff --git a/src/RiFyFi_VDG/src/tx_LoRa.jl b/src/RiFyFi_VDG/src/tx_LoRa.jl new file mode 100644 index 0000000..533d26a --- /dev/null +++ b/src/RiFyFi_VDG/src/tx_LoRa.jl @@ -0,0 +1,196 @@ +# module Tx + +""" +Generate LoRa symbols +signal, bitstsream_preFEC, symbols_preFEC, bitstsream_postFEC, symbols_postFEC = Gen_symb_SF(SF,N,BW,Fs,inverse) +# Input +- SF: Spreading factor of the CSS modulation +- N: Number of block to transmit, a block correspond to SF LoRa symbols +- BW: Bandwidth used for transmission +- Fs: sampling frequency +- inverse: 0 to send upchirp, 1 for downchirp +# Output +- signal: Baseband signal emitted from the transmitter +- bitstsream_preFEC: randomly generated binary data, it is the data that need to be sent +- symbols_preFEC: Conversion of bitstsream_preFEC into symbols, each symbols correspond to 4 bits +- bitstsream_postFEC: Results of the application of Hamming code and interleaving +- symbols_postFEC: Conversion of bitstsream_postFEC into symbols, each symbols correspond to SF bits + +""" +function Gen_symb_SF(SF,N,BW,Fs,inverse) + total_sym = N*SF; # Number of LoRa Symbols + A=rand(4,total_sym); + A=(A.<1/2); # Binary elements + bitstsream_preFEC = A; + + InputH = zeros(7,total_sym) + # Hamming coding (7,4) + for i ∈ 1:total_sym + InputH[:,i] = hamming74Encode(A[:,i]) + end + OutputFEC = floor.(Int, InputH); + + OutputInter = zeros(Int,N*7,SF); + for k ∈ 1:N # interleaver + OutputInter[(k-1)*7 + 1 : 7*k,:] = OutputFEC[:,SF*(k-1) + 1 : SF*k] + end + + # Symb=gray2dec(OutputInter); # Gray coding + LoRa_symbols = grayencode.(bin2dec(OutputInter)) + LoRa_symbols_mat=LoRa_symbols'; + signal=[]; + num_samples = Int64(floor(Fs*(2^SF)/BW)); # Number of samples + for i = 1:(N*7) + out_sym = LoRa_Modulation(SF,BW,Fs,num_samples,LoRa_symbols_mat[i],inverse); + signal = append!(signal, out_sym); + end + symbols_preFEC = bin2dec(bitstsream_preFEC') + symbols_postFEC = bin2dec(OutputInter) + return Complex.(signal),bitstsream_preFEC, symbols_preFEC, OutputInter, symbols_postFEC +end + +""" +Do the CSS modulation +""" +function LoRa_Modulation(SF,BW,Fs,num_samples,symbol,inverse) + + #initialization + phase = 0; + Frequency_Offset = (Fs/2) - (BW/2); + + shift = symbol; + out_preamble = zeros(ComplexF64,num_samples); + + for k = 1:num_samples + + # output the complex signal + out_preamble[k] = cos(phase) + 1im*sin(phase); + + # Frequency from cyclic shift + f = BW*shift/(2^SF); + if(inverse == 1) + f = BW - f; + end + + # apply Frequency offset away from DC + f = f + Frequency_Offset; + + # Increase the phase according to frequency + phase = phase + 2*pi*f/Fs; + if phase > pi + phase = phase - 2*pi; + end + + # update cyclic shift + shift = shift + BW/Fs; + if shift >= (2^SF) + shift = shift - 2^SF; + end + end + return out_preamble +end + + +""" +""" +function hamming_mat(total_sym, A) + InputH = zeros(7,total_sym) + for i ∈ 1:total_sym #encodage de hamming (ajout des bits de parités: mots de 4 bits --> mots de 7 bits) + InputH[:,i] = hamming74Encode(A[:,i]) + end + InputH = floor.(Int, InputH); + return InputH +end + +""" +""" +function hamming74Encode(x) + # --- Matrix encoder + # --- Matrix encoder + A = UInt8.([ 0 1 1;1 0 1;1 1 0;1 1 1 ]); + G = [ Matrix{UInt8}([1 0 0 0 ; 0 1 0 0;0 0 1 0;0 0 0 1]) A ] + # --- Init output + nL = length(x)÷4; + out = zeros(UInt8,7); + y = zeros(UInt8,nL*7); + # --- + for iN = 1 : 1 : nL + # --- Get 4 bits + subM = x[(iN-1)*4 .+ (1:4)]; + # --- Apply encoder + out .= mod.((subM' * G)[:],2); + # --- Additionnal parity bit + parity = mod(sum(out),2); + y[(iN-1)*7 .+ (1:7)] .= out; + end + return y; +end + +""" +""" +function interleaver(N, SF, InputH) + InputInter = zeros(Int,N*7,SF); + for k ∈ 1:N #interleaver + InputInter[(k-1)*7 + 1 : 7*k,:] = InputH[:,SF*(k-1) + 1 : SF*k] + end + return InputInter +end + +# end # module + + + +"""" +g = grayencode(n)\\ +Convert the integer `n` as its value with Gray encoding \\ +Inputs : +- n : Input integer +Outputs : +- g : Gray-coded integer +Example: grayencode(2) = 3 +""" +grayencode(n::Integer) = n ⊻ (n >> 1) + + +""" +n = graydecode(n) +Convert the gray encoded word `n` back +Inputs : +- g : Gray-coded integer +Outputs : +- n : Input integer +""" +function graydecode(n::Integer) + r = n + while (n >>= 1) != 0 + r ⊻= n + end + return r +end + +""" +n = bin2dec(data) +Convert a binary vector into its integer representation. The input should be a vector with the first element the MSB and the last element the LSB. \\ +Example : bin2dec([0;0;1]) = 1; bin2dec([1;0;1;0])=10 \\ +If the input is a matrix, the conversion is down per line (e.g bin2dec([1 0 1 0 ; 1 1 1 0]) = [10;14] +""" +function bin2dec(data::AbstractMatrix) + pow2 = [2^(k-1) for k in (size(data,2)):-1:1] + dataout = [sum(data[k,:] .* pow2) for k ∈ 1:size(data,1)] + return dataout +end +bin2dec(data::AbstractVector) = bin2dec(data') + +""" +Binary representation of Int on a given number of bits. MSB in pos 1 and LSB at end +""" +function dec2bin(input::Vector{Int},n::Int) + Output_bin = zeros(Int, length(input), n) + for i ∈ eachindex(input) + c = bitstring(input[i]) + data = [Int(c[j]-48) for j ∈ length(c)-(n-1):length(c)] + Output_bin[i,:] = data + end + return Output_bin +end + diff --git a/src/RiFyFi_VDG/src/tx.jl b/src/RiFyFi_VDG/src/tx_OFDM.jl similarity index 100% rename from src/RiFyFi_VDG/src/tx.jl rename to src/RiFyFi_VDG/src/tx_OFDM.jl diff --git a/src/RiFyFi_VDG/src/tx_singleCarrier.jl b/src/RiFyFi_VDG/src/tx_singleCarrier.jl new file mode 100644 index 0000000..28a3059 --- /dev/null +++ b/src/RiFyFi_VDG/src/tx_singleCarrier.jl @@ -0,0 +1,92 @@ + + +""" +sqrtRaisedCosine(N,β,ovS)\\ +Returns the Finite Impulse Response of a Square Root Raised Cosine (SRRC) filter. +The filter is defined by its span (evaluated in number of symbol N), its Roll-Off factor and its oversampling factor. The span corresponds to the number of symbol affected by filter before and after the center point. \\ +Output is a Complex{Float64} array of size L= 2KN+1 \\ +SRRC definition is based on [1]\\ +[1] 3GPP TS 25.104 V6.8.0 (2004-12). http://www.3gpp.org/ftp/Specs/archive/25_series/25.104/25104-680.zip\\ +Parameters +- N : Symbol span +- β : Roll-off factor (Float64) +- ovS : Oversampling rate +""" +function sqrtRaisedCosine(N,β,ovS) + # --- Final size of filter + nbTaps = 2 * N * ovS + 1; + # --- Init output + h = zeros(Float64,nbTaps); + counter = 0; + # --- Iterative SRRC definition + for k = -N*ovS : 1 : N*ovS + counter = counter + 1; + if k == 0 + ## First singular point at t=0 + h[counter] = (1-β) + 4*β/pi; + elseif abs(k) == ovS / (4*β); + ## Second possible singular point + h[counter] = β/sqrt(2)*( (1+2/pi)sin(pi/(4β))+(1-2/pi)cos(pi/(4β))); + else + ## Classic SRRC formulation (see [1]) + h[counter] = ( sin(pi*k/ovS*(1-β)) + 4β*k/ovS*cos(pi*k/ovS*(1+β))) / (pi*k/ovS*(1- (4β*k/ovS)^2) ); + end + end + # --- Normalize power of filter + #return h / maximum(abs.(h)) + return h / sqrt(sum(abs2.(h))) +end + +""" Create a transmitted signal with `nbSymb` symbols with constellation with `mcs` constellation size (with log2(mcs) bits per symbol i.e 4 for QPSK and 16 for QAM-16), filtered by a square root raised cosine with oversampling factor `ovs` and Roll-off factor `β` span on `2N+1` symbols +Return the generated bit sequence and the complex signal +""" +function singleCarrierTx(nbSymb; mcs = 4,ovS = 4, β=0.3, N=6) + # Number of bits per symbol + bps = Int(log2(mcs)) + # Generate bit sequence + bitSeq = genBitSequence(bps * nbSymb) + # Modulate + qamSeq = bitMappingQAM(mcs,bitSeq) + # Generate filter + h = sqrtRaisedCosine(N,β,ovS) + # Oversample and filter + support = zeros(ComplexF64, nbSymb * ovS) + support[1:ovS:end] .= qamSeq + # Filter data + dataFiltered = DSP.conv(h,support) + return (bitSeq,dataFiltered) +end + + +function singleCarrierTx(nbSymb) + mcs = 4 + ovS = 4 + β=0.3 + N=6 + (bitSeq,dataFiltered) = singleCarrierTx(nbSymb; mcs ,ovS, β, N) + alpha = N * ovS + # size_h = 2 * N * ovS + 1 + x= dataFiltered[1+alpha: end- alpha] + return x +end + +""" Demodulate the transmitted signal with a synchronisation delay `delay` +Returns the Rx QAm sequence and the decoded bit sequence """ +function singleCarrierRx(y; delay=0,mcs = 4,ovS = 8, β=0.3, N=6) + # Filter in Rx + h = sqrtRaisedCosine(N,β,ovS) + dataFiltered = DSP.conv(h,y) + # Decision + # assuming match filter + tails = length(h)-1 + constRx = dataFiltered[1+delay+tails:ovS:end-tails] + # Demodulation + bitDec = bitDemappingQAM(mcs,constRx) + return (bitDec,constRx) +end + + +# Minimal Chain +# b,signal = RiFyFi.RiFyFi_VDG.singleCarrierTx(120) +# b̄,qamRx = RiFyFi.RiFyFi_VDG.singleCarrierRx(signal); +# ber = sum(xor.(b̄,b)) / length(b) diff --git a/src/script_example.jl b/src/script_example.jl index 23f1421..b1f8260 100644 --- a/src/script_example.jl +++ b/src/script_example.jl @@ -3,17 +3,10 @@ using RiFyFi using Infiltrator using RFImpairmentsModels -include("Augmentation/src/Augmentation.jl") -using .Augmentation - -include("RiFyFi_VDG/src/RiFyFi_VDG.jl") -using .RiFyFi_VDG - -include("RiFyFi_IdF/src/RiFyFi_IdF.jl") -using .RiFyFi_IdF - -include("Results/src/Results.jl") -using .Results +using RiFyFi.Augmentation +using RiFyFi.RiFyFi_IdF +using RiFyFi.RiFyFi_VDG +using RiFyFi.Results # Parameters DataBase Synth name= "Example_Database" @@ -42,12 +35,13 @@ if S == "S1" || S == "S2" else seed_dataTest = 9999246912 * 100000000 end +Modulation = "SC" # SC for single carrier modulation or OFDM or LoRa # Parameters for Data Augmentation nb_Augment= 1 # Define the number of channel for each transmitter augmentationType="No_channel" # use No_channel, augment or same_channel Channel="etu" -Channel_Test="eva" +Channel_Test="etu" # Network Parameters @@ -55,33 +49,30 @@ Networkname="AlexNet" # Name of the Network NbClass =nbRadioTx #Chunksize #NbSignals -Seed_Network= 11 - +Table_Seed_Network= [11] +Seed_Network =11 # Train Args η = 1e-5 # learning rate dr = 0.25 # dropout batchsize = 64 -epochs = 2000 +epochs = 20 use_cuda = true savepathbson="" Augmentation_Value = Augmentation.Data_Augmented_construct(augmentationType=augmentationType,nb_Augment=nb_Augment,Channel=Channel,Channel_Test=Channel_Test) -Param_Data = RiFyFi_VDG.Data_Synth(name,nameModel,nbRadioTx, NbSignals, Chunksize,features,S,E,C,RFF,Normalisation,pourcentTrain,configuration,seed_data,seed_model,seed_dataTest,seed_modelTest,Augmentation_Value) -setSynthetiquecsv(Param_Data) - +Param_Data = RiFyFi.RiFyFi_VDG.Data_Synth(name,nameModel,nbRadioTx, NbSignals, Chunksize,features,S,E,C,RFF,Normalisation,pourcentTrain,configuration,seed_data,seed_model,seed_dataTest,seed_modelTest,Modulation,Augmentation_Value) +RiFyFi_VDG.setSynthetiquecsv(Param_Data) +@infiltrate Train_args = RiFyFi_IdF.Args(η = η, dr=dr, epochs= epochs, batchsize=batchsize) Param_Network = RiFyFi_IdF.Network_struct(;Networkname,NbClass,Chunksize,NbSignals,Seed_Network,Train_args) RiFyFi.main(Param_Data,Param_Network) -nameTable = [name] -Seed_Network= Table_Seed_Network[1] -Train_args = RiFyFi_IdF.Args(η = η ,dr=dr, epochs= epochs,batchsize=batchsize) -Param_Network = RiFyFi_IdF.Network_struct(;Networkname,NbClass,Chunksize,NbSignals,Seed_Network,Train_args) -Results.main(Param_Data,Param_Network,"F1_score",Table_Seed_Network,savepathbson) -Results.main(Param_Data,Param_Network,"Confusion_Matrix",Table_Seed_Network,savepathbson) + +Results.main(Param_Data,Param_Network,"F1_score",Table_Seed_Network,savepathbson,Param_Data) +Results.main(Param_Data,Param_Network,"Confusion_Matrix",Table_Seed_Network,savepathbson,Param_Data)