# -*- coding: utf-8 -*-
"""
Created on Wed Jun 16 14:23:20 2021

@author: A752018
"""


def clustering(data, hdb, normalisation, scale, var):
        
    mylist = pd.DataFrame(temp[['DI', 'FN']])
       
    #  --- Energie
    mylist['nrj'] = pd.DataFrame(data['LEVEL'] + (10 * np.log(data['DI'])))
    
    # --- FN / DI unif
    for variable in ('DI', 'FN'):
    
        tab = pd.DataFrame(data[variable])
        
        tab = tab.sort_values(by = variable, ascending = True)
        tab.index = range(0, len(tab))
    
        tab = np.array(tab[variable])
        tab = pd.DataFrame((np.ediff1d(tab, to_begin=0))) 
        
        tab.columns = [variable]
        tab = tab[tab[variable] != 0]
                
        if tab.empty == False:
            pas = min(tab[variable])
        else:
            pas = 0        
            
        # Modification des valeurs
        unif = pd.DataFrame(np.random.uniform(pas, -pas, len(data)))
        mylist[(variable + '_unif')] = pd.to_numeric(data[variable]) + unif[0]
        
        del tab, pas, unif, variable
    
    # Vérification de la positivité de la DI
    mylist['DI_unif'] = mylist['DI_unif'] - np.min(mylist['DI_unif']) + min(data['DI']) 
    
    # mylist['DI'] = data['DI']
    # mylist['FN'] = data['FN']
    if (var == 'Norm'):
        var = ['DI_unif', 'FN_unif']
    else:
        var = ['DI', 'FN']
   
    # --- Clustering : FN_unif / DI_unif
    if (normalisation == True):
        
        if (scale == 'Rs'):
            
            scale = RobustScaler(quantile_range=(5.0, 95.0)).fit(mylist[var])
            
        else:
            scale = StandardScaler().fit(mylist[var])
            
        tab = pd.DataFrame(scale.transform(mylist[var]))
        y_pred = pd.DataFrame(hdb.fit_predict(tab))
        
        del tab

        
    else:
        y_pred = pd.DataFrame(hdb.fit_predict(mylist[var]))
        
    mylist['cluster_unif'] = pd.DataFrame(np.int_(y_pred))
        
    data = pd.merge(data, mylist, left_index = True, right_index = True)
    
    del y_pred, mylist
    
    return data

#  ------------------------------------------------------------------------------------

#       Cas d'application 1

#  ------------------------------------------------------------------------------------
# From FO
# ----------- 1) Création
#  --- Signal A
signal = 13
temp = mise_en_forme(signal, orientation = 'col') 
temp['TOA'] = temp['TOA'] - temp['TOA'].min()

#  Identification de l'émetteur
temp['ID_radar'] = 0



#  --- Signal B
signal = 8
temp2 = mise_en_forme(signal, orientation = 'col') 
temp2['TOA'] = temp2['TOA'] - temp2['TOA'].min()


#  Identification de l'émetteur
temp2['ID_radar'] = 1


# Superposition des signaux
temp2['TOA'] = temp2['TOA'] + 0.0

#  --- Création du nouveau signal
temp = pd.concat([temp, temp2])
temp = temp[temp['TOA'] < 10]
temp.index = range(len(temp))


del temp2
temp = temp.drop(['dTOA', 'nrj', 'DI_unif', 'FN_unif','DI_log', 'cluster_log', 'cluster_unif', 'dTOA_initiale'], axis = 1)

# hdb = hdbscan.HDBSCAN(allow_single_cluster = True, approx_min_span_tree = True, gen_min_span_tree = False, match_reference_implementation=False, 
#                  p = None, prediction_data=False,  core_dist_n_jobs = 4, min_cluster_size = 20, 
#                  min_samples = None, algorithm = 'best', cluster_selection_method = 'eom')

    
temp =  clustering(data = temp, hdb = hdb, normalisation = True, scale = 'St', var = 'Norm')
len(temp['cluster_unif'].unique())
temp = temp.drop(['nrj', 'DI_unif', 'FN_unif','cluster_unif'], axis = 1)

PLOT_simple(temp.T, var_coloration = 'cluster_unif', signal = signal, arg_legend = True, title = True, palette = 'tab20b',
          var1 = 'FN_unif', var2 = 'DI_unif', var3 = 'LEVEL', var4 = 'FN_unif', var5 = 'DI_unif',
                                      label_var1 = 'Frequency (MHz)', label_var2 = 'Pulse width (ns)', 
                                      label_var3 = 'Level (dBm)', label_var4 = 'Frequency (MHz)', label_var5 = 'Pulse width (ns)',
                                      save = mode_save, save_name = 'original_data')



#  Plots
k1_ot_toa, k1_dist_ot_toa = 2, 0.2795
k1_ot_max_toa, k1_dist_ot_max_toa = 5, 0.2372
k1_ot_lvl, k1_dist_ot_lvl = 2, 1.1152460761056208e-06



#  ------------------------------------------------------------------------------------

#       Cas d'application 2

#  ------------------------------------------------------------------------------------
# from ScenarioFO
# Sélection signal
signal = 3
temp = mise_en_forme(signal, orientation = 'col') 

#  Création variable
temp['ID_radar'] = -1


# Boucle
for i in range(len(temp)):
    
    # --- E10
    if(temp.iloc[i, temp.columns.get_loc('DI')] > 18):
        temp.iloc[i, temp.columns.get_loc('ID_radar')] = 0
        
    elif(temp.iloc[i, temp.columns.get_loc('DI')] > 4 and temp.iloc[i, temp.columns.get_loc('DI')] < 6):
        temp.iloc[i, temp.columns.get_loc('ID_radar')] = 0
        
    # --- S5_1
    elif(temp.iloc[i, temp.columns.get_loc('DI')] > 15 and temp.iloc[i, temp.columns.get_loc('DI')] < 17 and temp.iloc[i, temp.columns.get_loc('FN')] > 9362):
        temp.iloc[i, temp.columns.get_loc('ID_radar')] = 1

    # --- P2
    elif(temp.iloc[i, temp.columns.get_loc('DI')] > 15 and temp.iloc[i, temp.columns.get_loc('DI')] < 17 and temp.iloc[i, temp.columns.get_loc('FN')] < 9362):
        temp.iloc[i, temp.columns.get_loc('ID_radar')] = 2
        
    elif(temp.iloc[i, temp.columns.get_loc('DI')] > 7 and temp.iloc[i, temp.columns.get_loc('DI')] < 9):
        temp.iloc[i, temp.columns.get_loc('ID_radar')] = 2

    # --- A5_1
    elif(temp.iloc[i, temp.columns.get_loc('DI')] < 0.4 and temp.iloc[i, temp.columns.get_loc('FN')] < 9300):
        temp.iloc[i, temp.columns.get_loc('ID_radar')] = 3
        
    # --- A1 ?? au lieu de A7
    elif(temp.iloc[i, temp.columns.get_loc('DI')] < 0.4 and temp.iloc[i, temp.columns.get_loc('FN')] > 9380):
        temp.iloc[i, temp.columns.get_loc('ID_radar')] = 4

#  Check
pd.DataFrame(temp['ID_radar'].value_counts())


PLOT_simple(temp.T, var_coloration = 'ID_radar', signal = signal, arg_legend = True, title = True, palette = 'tab20b',
              var1 = 'FN_unif', var2 = 'DI_unif', var3 = 'LEVEL', var4 = 'FN_unif', var5 = 'DI_unif',
                                          label_var1 = 'Frequency (MHz)', label_var2 = 'Pulse width (ns)', 
                                          label_var3 = 'Level (dBm)', label_var4 = 'Frequency (MHz)', label_var5 = 'Pulse width (ns)',
                                          save = mode_save, save_name = 'original_data')

#  --- Dendogrammes
#  TOA
k1_ot_toa, k1_dist_ot_toa = 4, 1.117
Z_bin_ot_toa2 = Z_bin_ot_toa.copy()


# Z_bin_ot_toa2.iloc[10, 2] = 0.1201
Z_bin_ot_toa2.iloc[11, 2] = 1.535
Z_bin_ot_toa2.iloc[12, 2] = 2.18


PLOT_dendo(data = temp_without_outliers, signal = signal, linkage_matrix = Z_bin_ot_toa2, var_clust = 'cluster_unif', value = True, 
         title = True, distance_cut = k1_dist_ot_toa, save = mode_save, save_name = 'dendo_ot_toa')



#  TOA + LEVEL
k1_ot_max_toa, k1_dist_ot_max_toa = 5, 0.748

Z_bin_ot_max_toa2 = Z_bin_ot_max_toa.copy()

Z_bin_ot_max_toa2.iloc[10, 2] = 0.977
Z_bin_ot_max_toa2.iloc[11, 2] = 1.164
Z_bin_ot_max_toa2.iloc[12, 2] = 2.592
Z_bin_ot_max_toa2.iloc[13, 2] = 2.791


PLOT_dendo(data = temp_without_outliers, signal = signal, linkage_matrix = Z_bin_ot_max_toa2, var_clust = 'cluster_unif', value = True, 
          title = True, distance_cut = k1_dist_ot_max_toa, save = mode_save, save_name = 'dendo_ot_max_toa')


# LEVEL
k1_ot_lvl, k1_dist_ot_lvl = 2, 0.75524607610568e-05

Z_bin_ot_lvl2 = Z_bin_ot_lvl.copy()

# Z_bin_ot_lvl2.iloc[11, 2] = 3.58732948540934e-06
Z_bin_ot_lvl2.iloc[12, 2] = 0.556865883680803e-05

PLOT_dendo(data = temp_without_outliers, signal = signal, linkage_matrix = Z_bin_ot_lvl2, var_clust = 'cluster_unif', value = True, 
         title = True, distance_cut = k1_dist_ot_lvl, save = mode_save, save_name = 'dendo_ot_lvl')

#  ------------------------------------------------------------------------------------

#       Cas d'application 3

#  ------------------------------------------------------------------------------------
# from ScenarioFO
# Sélection signal
signal = 2
temp = mise_en_forme(signal, orientation = 'col') 

#  Création variable
temp['ID_radar'] = -1


# Boucle
for i in range(len(temp)):
    
    # --- A8
    if(temp.iloc[i, temp.columns.get_loc('FN')] > 9505 and temp.iloc[i, temp.columns.get_loc('FN')] < 9515):
        temp.iloc[i, temp.columns.get_loc('ID_radar')] = 0
                
    # --- A9
    elif(temp.iloc[i, temp.columns.get_loc('FN')] > 9400 and temp.iloc[i, temp.columns.get_loc('FN')] < 9410):
        temp.iloc[i, temp.columns.get_loc('ID_radar')] = 1

    # --- D2
    elif(temp.iloc[i, temp.columns.get_loc('FN')] > 9595 and temp.iloc[i, temp.columns.get_loc('FN')] < 9650):
        temp.iloc[i, temp.columns.get_loc('ID_radar')] = 2
        

    # --- B4
    elif(temp.iloc[i, temp.columns.get_loc('FN')] > 9750 and temp.iloc[i, temp.columns.get_loc('FN')] < 10000):
        temp.iloc[i, temp.columns.get_loc('ID_radar')] = 3
        
    # --- A7
    elif(temp.iloc[i, temp.columns.get_loc('FN')] > 9190 and temp.iloc[i, temp.columns.get_loc('FN')] < 9270):
        temp.iloc[i, temp.columns.get_loc('ID_radar')] = 4
    
        
#  Check
pd.DataFrame(temp['ID_radar'].value_counts())


PLOT_simple(temp.T, var_coloration = 'ID_radar', signal = signal, arg_legend = True, title = True, palette = 'tab20',
              var1 = 'FN', var2 = 'DI', var3 = 'LEVEL', var4 = 'FN', var5 = 'DI',
                                          label_var1 = 'Frequency (MHz)', label_var2 = 'Pulse width (ns)', 
                                          label_var3 = 'Level (dBm)', label_var4 = 'Frequency (MHz)', label_var5 = 'Pulse width (ns)',
                                          save = mode_save, save_name = 'original_data')


# temp =  clustering(data = temp, hdb = hdb, normalisation = True)
#  --- Dendogrammes
#  LEVEL
k1_ot_lvl, k1_dist_ot_lvl = 4, 0.000002

Z_bin_ot_lvl2 = Z_bin_ot_lvl.copy()

Z_bin_ot_lvl2.iloc[11, 2] = 3.58732948540934e-06
Z_bin_ot_lvl2.iloc[12, 2] = 3.96573248540934e-06

PLOT_dendo(data = temp_without_outliers, signal = signal, linkage_matrix = Z_bin_ot_lvl2, var_clust = 'cluster_unif', value = True, 
         title = True, distance_cut = k1_dist_ot_lvl, save = mode_save, save_name = 'dendo_ot_lvl')


#  TOA
k1_ot_toa, k1_dist_ot_toa = 8, 0.0418

Z_bin_ot_toa2 = Z_bin_ot_toa.copy()


Z_bin_ot_toa2.iloc[10, 2] = 0.1201
Z_bin_ot_toa2.iloc[11, 2] = 0.1356
Z_bin_ot_toa2.iloc[12, 2] = 0.1902


PLOT_dendo(data = temp_without_outliers, signal = signal, linkage_matrix = Z_bin_ot_toa2, var_clust = 'cluster_unif', value = True, 
         title = True, distance_cut = k1_dist_ot_toa, save = mode_save, save_name = 'dendo_ot_toa')

#  TOA + LEVEL
k1_ot_max_toa, k1_dist_ot_max_toa = 5, 0.05

Z_bin_ot_max_toa2 = Z_bin_ot_max_toa.copy()


Z_bin_ot_max_toa2.iloc[10, 2] = 0.1603
Z_bin_ot_max_toa2.iloc[11, 2] = 0.2364
Z_bin_ot_max_toa2.iloc[12, 2] = 0.461


PLOT_dendo(data = temp_without_outliers, signal = signal, linkage_matrix = Z_bin_ot_max_toa2, var_clust = 'cluster_unif', value = True, 
          title = True, distance_cut = k1_dist_ot_max_toa, save = mode_save, save_name = 'dendo_ot_max_toa')


