6.1 Puntos de prueba vs Modelo de propagación

Una revisión del modelo de propagación encontrado con los puntos de entrenamiento se puede realizar con puntos de prueba. Las lecturas de los puntos de prueba se realizaron dos semanas después de los puntos de entrenamiento.

Los puntos de prueba tienen una lectura a cada baliza, a diferencia de al menos cien de los puntos de entrenamiento.

En la revisión se encuentra que los puntos de prueba se encuentran en el rango de las mediciones del modelo, sin embargo los puntos se encuentran distribuidos en la gráfica desplazados hacia arriba del modelo, indicando que es necesario incorporar más variables para ajustar el modelo, por ejemplo la temperatura del entorno u otra variable que se determinaría en una siguiente fase del experimento.

Para cuantificar el desplazamiento Δrssi, se calcula el error entre cada punto y la ecuación modelo. Bajo el concepto que los errores se distribuyen equitativamente sobre y debajo la ecuación, se obtiene el valor de la mediana que indica el desplazamiento más optimo como ajuste al modelo bajo las nuevas condiciones.

Revisando la aplicabilidad del modelo, se obtiene el coeficiente de correlación para los puntos de prueba clasificados en gtwFIEC, que es de -0.88 que permite estimar que se puede aplicar relación lineal con pendiente negativa en el intervalo.

gtwFIEC s0 r0  error_mediana: 5.99 correlacion: -0.88
gtwFIEC s0 r1  error_mediana: 7.14 correlacion: -0.68
gtwFIEC s0 r2  error_mediana: 1.98 correlacion: -0.76

Se puede proseguir con los otros puntos de prueba para las otras balizas, encontrando que en la baliza gtwRECT los mejores valores de correlación con los datos disponibles tan dado en el área de vegetación sin sombra.  El modelo estimado en vegetación para la zona con sombra debe ser revisados pues hay un valores cercanos a cero en correlación, por lo que la linealización con los datos puede ser insuficiente para estimar que hay una relación lineal entre las dos variables. Se requiere en ese caso expandir la toma de muestra y revisar con mas datos el modelo.

Desplazamientos de puntos de prueba
 respecto al modelo:
[baliza,sector,intervalo,drssi]
gtwRECT s0 r0  error_mediana: 7.8 correlacion: -0.54
gtwRECT s0 r1  error_mediana: 5.55 correlacion: -0.13
gtwRECT s0 r2  error_mediana: 9.3 correlacion: -0.47
gtwRECT s1 r0  error_mediana: 3.7 correlacion: 0.13
gtwRECT s1 r1  error_mediana: 3.7 correlacion: 0.13
gtwFIEC s0 r0  error_mediana: 5.99 correlacion: -0.88
gtwFIEC s0 r1  error_mediana: 7.14 correlacion: -0.68
gtwFIEC s0 r2  error_mediana: 1.98 correlacion: -0.76
gtwFCNM s0 r0  error_mediana: 8.56 correlacion: -0.76
gtwFCNM s0 r1  error_mediana: 6.59 correlacion: -0.75
gtwFCNM s0 r2  error_mediana: 9.98 correlacion: -0.29

Algoritmo en Python

Se adjunta el algoritmo correspondiente:

# LoRa-Multipunto, Revisa grafica Rssi vs distancia
# con puntos de prueba 'CIRC'
# linealización Rssi vs log10(distancia) por mínimos cuadrados
# Graficas 2D y 3D
# Girni 2020-01-30 propuesta: edelros@espol.edu.ec

import numpy as np
import pandas as pd
import json
import matplotlib.pyplot as plt
import girni_lora_libreria as girni

# INGRESO
# archivos de entrada
modo       = 'rx'
medida     = 'rssi'
descriptor = 'mean'
arch_ecuaciones  = 'rsmP07_ecuacionSector01.json'
arch_medidaubica = 'rsmP06_'+medida+'UbicaCirc01.txt'
# archivos de salida
arch_ecuaciones2  = 'rsmP07_ecuacionSector02.json'


baliza = {'d1':'gtwRECT',
          'd2':'gtwFIEC',
          'd3':'gtwFCNM'}

# Parámetros de grafica
tipograf      = '2D'  # '2D','3D'
escala        = 'log' # 'normal','log'
escalabase    = 10    # 10, np.exp()
casicero   = 1e-4
precision  = 2
intersectar = 0 # 0:Falso, 1: Verdadero

# Referencias de gráfica
grupo   = ['FIEC' ,'FCNM'  ,'RECT','CIRC']
colores = ['green','orange','grey','magenta']
tipo    = ['punto','1m' ,'gtw','dispositivo']
marcas  = [    'o','D'  ,'D'  ,'*' ]

mostrargrpeti = ['FIEC','FCNM','RECT']
mostrartipeti = ['1m','gtw']

# PROCEDIMIENTO
# leer datos
with open(arch_ecuaciones) as json_file: 
    ecuacion = json.load(json_file) 
tabla = pd.read_csv(arch_medidaubica, index_col='etiqueta')
tabla = pd.DataFrame(tabla)

baliza_key = list(baliza.keys())
baliza_val = list(baliza.values())
eq_graf  = {}

# Revisa un sector_estimado
for cualbaliza in baliza:
    sector_baliza = 'sector_'+cualbaliza
    tabla[sector_baliza] = 0
for cadapunto in tabla.index:
    for cualbaliza in baliza:
        # evalua en sector
        sector_baliza = 'sector_'+cualbaliza
        donde = baliza_key.index(cualbaliza)
        # coordenadas baliza para identificar ángulo
        b_este  = tabla['c_este'][baliza[cualbaliza]]
        b_norte = tabla['c_norte'][baliza[cualbaliza]]
        # coordenadas del punto
        p_este  = tabla['c_este'][cadapunto]
        p_norte = tabla['c_norte'][cadapunto]
        dx = p_este-b_este
        dy = p_norte-b_norte
        theta = np.arctan2(dy,dx)
        if theta<0:
            theta = theta + 2*np.pi
        sectores   =  ecuacion[baliza[cualbaliza]]['sector_rad']
        nsectores  = len(sectores)
        otrosector = ''
        for i in range(0,nsectores-1,1):
            a = sectores[i]
            b = sectores[i+1]
            if theta>=a and theta<b:
                otrosector = i+1
        if otrosector !='':
            tabla.loc[cadapunto,'sector_'+cualbaliza] = otrosector

# analiza datos hacia una baliza
for unabaliza in ecuacion:
    donde = baliza_val.index(unabaliza)
    cualbaliza = baliza_key[donde]
    
    eq_graf[unabaliza] = {}
    for unsector in list(ecuacion[unabaliza].keys()):  
        if unsector != 'sector_rad':
            eq_graf[unabaliza][unsector] = {}
            for i_eq in list(ecuacion[unabaliza][unsector].keys()):
                eq_graf[unabaliza][unsector][i_eq] = {} 

    # puntos de tabla
    for unsector in list(ecuacion[unabaliza].keys()):
        if unsector != 'sector_rad':
            xi_p = [] ; yi_p = []
            xi = [] ; yi = [] ; etiqueta = []
            columna = medida+'_'+modo+'_'+cualbaliza
            for cadapunto in tabla.index:
                p_rssi = np.round(tabla[columna][cadapunto], precision)
                dist   = np.round(tabla['dist_'+cualbaliza][cadapunto], precision)
                ensector = 's'+str(tabla['sector_'+cualbaliza][cadapunto])
                LOS = tabla['LOS_'+cualbaliza][cadapunto]
                if not(np.isnan(p_rssi)) and dist>1 and LOS==1 and unsector==ensector:
                    yi_p.append(p_rssi)
                    xi_p.append(dist)
                    etiqueta.append(cadapunto)
                    if not(dist in xi):
                        xi.append(dist)
                        yi.append(p_rssi)
                    
            xi_p = np.array(xi_p)
            yi_p = np.array(yi_p)
            ordenar = np.argsort(xi_p)
            xi_p = list(xi_p[ordenar])
            yi_p = list(yi_p[ordenar])
            etiqueta = np.array(etiqueta)
            etiqueta = etiqueta[ordenar]

            xi = np.array(xi)
            yi = np.array(yi)
            ordenar = np.argsort(xi)
            xi = xi[ordenar]
            yi = yi[ordenar]

            i_eq = 'r0' # todos los puntos
            eq_graf[unabaliza][unsector][i_eq]['xi'] = xi_p.copy()
            eq_graf[unabaliza][unsector][i_eq]['yi'] = yi_p.copy()
            eq_graf[unabaliza][unsector][i_eq]['etiqueta'] = etiqueta.copy()
                
            
            # ecuacion linealizada
            for i_eq in list(ecuacion[unabaliza][unsector].keys()):
                a = ecuacion[unabaliza][unsector][i_eq]['intervalox'][0]
                b = ecuacion[unabaliza][unsector][i_eq]['intervalox'][1]
                
                alpha = ecuacion[unabaliza][unsector][i_eq]['alpha']
                beta  = ecuacion[unabaliza][unsector][i_eq]['beta']
                std   = ecuacion[unabaliza][unsector][i_eq]['error_std']
                fdist = lambda d: -10*alpha*(np.log10(d))+beta

                subintervalo = (xi >= a) & (xi <= b)
                xi_s = xi[subintervalo]
                yi_s = yi[subintervalo]

                # correlacion de los puntos
                correlacion = np.corrcoef(xi_s,yi_s)[0,1]
                
                # dibujar la línea en intervalo
                xi_sub = xi[subintervalo]
                if not(a in xi_sub):
                    xi_sub = np.concatenate(([a],xi_sub),axis=0)
                if not(b in xi_sub):
                    xi_sub = np.concatenate((xi_sub,[b]),axis=0)
                yi_sub = fdist(xi_sub)

                eq_graf[unabaliza][unsector][i_eq]['xi_graf'] = xi_sub.copy()
                eq_graf[unabaliza][unsector][i_eq]['yi_graf'] = yi_sub.copy()

                
                # Errores en subintervalo
                mediana = 0
                if intersectar == 0:
                    yie_s = yi_s - fdist(xi_s)
                    mediana = np.median(yie_s)
                else:
                    if i_eq=='r0':
                        yie_s = yi_s - fdist(xi_s)
                        mediana = np.median(yie_s)
                    else:
                        mediana = ecuacion[unabaliza][unsector]['r0']['desplaza']
                                    
                eq_graf[unabaliza][unsector][i_eq]['desplaza'] = mediana
                eq_graf[unabaliza][unsector][i_eq]['correlacion'] = correlacion
                ecuacion[unabaliza][unsector][i_eq]['desplaza'] = mediana
                

# SALIDA
print('Desplazamientos de puntos de prueba')
print(' respecto al modelo:')
print('[baliza,sector,intervalo,drssi]')
for unabaliza in ecuacion:
    for unsector in list(ecuacion[unabaliza].keys()):  
        if unsector != 'sector_rad':
            for i_eq in list(ecuacion[unabaliza][unsector].keys()):
                mediana = ecuacion[unabaliza][unsector][i_eq]['desplaza']
                mediana = np.round(mediana,precision)
                correlacion = eq_graf[unabaliza][unsector][i_eq]['correlacion']
                correlacion = np.round(correlacion,precision)
                texto = unabaliza + ' '+unsector + ' ' + i_eq + ' '
                texto = texto + ' error_mediana: '+ str(mediana)
                texto = texto + ' correlacion: '+str(correlacion)
                print(texto)

# salida hacia archivo
with open(arch_ecuaciones2, 'w') as outfile:
    json.dump(ecuacion, outfile) 

# GRAFICA
# Referencias para gráfica
grupo   = ['FIEC' ,'FCNM'  ,'RECT','CIRC']
colores = ['green','orange','grey','magenta']
tipo    = ['punto','1m' ,'gtw','dispositivo']
marcas  = [    'o','D'  ,'D'  ,'*' ]

mostrargrpeti = ['FIEC','FCNM','RECT']
mostrartipeti = ['1m','gtw']

if tipograf=='2D':
    for unabaliza in eq_graf:
        for unsector in eq_graf[unabaliza]:
            figura,grafica = plt.subplots()
            if escala == 'log':
                grafica.set_xscale(escala,base=escalabase)
                
            eq_graf2 = {}
            # todos los puntos
            unintervalo = 'r0'
            xi_p = eq_graf[unabaliza][unsector][unintervalo]['xi']
            yi_p = eq_graf[unabaliza][unsector][unintervalo]['yi']
            etiqueta = eq_graf[unabaliza][unsector][unintervalo]['etiqueta']
            grafica.scatter(xi_p,yi_p,marker='.')
            m = len(xi_p)
            for i in range(0,m,1):
                grafica.annotate(etiqueta[i],
                                (xi_p[i],yi_p[i]))
                
            # linea con todos los puntos
            for i_eq in list(eq_graf[unabaliza][unsector].keys()):
                fdtxt   = ecuacion[unabaliza][unsector][i_eq]['eq_latex']
                xi_graf = eq_graf[unabaliza][unsector][i_eq]['xi_graf']
                yi_graf = eq_graf[unabaliza][unsector][i_eq]['yi_graf']
                a = np.round(ecuacion[unabaliza][unsector][i_eq]['intervalox'][0],precision)
                b = np.round(ecuacion[unabaliza][unsector][i_eq]['intervalox'][1],precision)
                desplaza = eq_graf[unabaliza][unsector][i_eq]['desplaza']
                desplaza = np.round(desplaza,precision)
                estilo = 'solid'
                if i_eq =='r0':
                    estilo = 'dashed'
                eq_texto = i_eq+': '+fdtxt+' ; ['+str(a)+','+str(b)+']'
                grafica.plot(xi_graf,yi_graf,
                             label = eq_texto,
                             linestyle = estilo)
                # para linea desplazada
                eq_graf2[i_eq] = {'xi':xi_graf,
                              'yi':yi_graf + desplaza,
                              'desplaza': desplaza}
                
                # lineas de frontera
                grafica.axvline(a, color='lightblue')
                valor_frontera = str(np.round(a,precision))
                grafica.annotate(valor_frontera,
                                 (a,np.max(yi_p)),
                                 color='lightblue')
                grafica.axvline(b, color='lightblue')
                valor_frontera = str(np.round(b,precision))
                grafica.annotate(valor_frontera,
                                 (b,np.max(yi_p)),
                                 color='lightblue')
            for i_eq in list(ecuacion[unabaliza][unsector].keys()):
                estilo = 'solid'
                if i_eq =='r0':
                    estilo = 'dashed'
                xi = eq_graf2[i_eq]['xi']
                yi = eq_graf2[i_eq]['yi']
                desplaza = eq_graf2[i_eq]['desplaza']
                texto = i_eq + ' + $\Delta $Rssi'
                texto = texto + ' ; $ \Delta rssi$= '+ str(desplaza)
                grafica.plot(xi,yi, label = texto,
                             linestyle = estilo)
        
            # etiquetas y títulos
            grafica.legend()
            grafica.set_ylabel(medida+'_'+modo)
            grafica.set_xlabel('distancia')
            grafica.grid(True,linestyle='dotted',
                         axis='x', which='both')
            
            untitulo = unabaliza+' '+unsector+': Puntos de prueba desplazados'
            grafica.set_title(untitulo)
            
            plt.show()