El algoritmo para realizar dos o más intervalos considera usar un estimado de frontera a lo largo de las mediciones.
Se implementa añadiendo al bloque de ingreso dos parámetros en el bloque ‘analiza’:
1. frontera es un vector donde se indican las distancia de los puntos de corte de los subintervalos sin considerar los extremos, corresponden a la frontera estimada en el mapa. El algoritmo actualiza la frontera con la intersección de la linealización de dos subintervalos consecutivos. Si frontera es un vector vacío []
se asume que se trabaja con todo el intervalo.
2. ‘atipInterv_std’ es un vector para la discriminación de los valores atipicos aplicada en cada subintervalo.
Como referencia para comparar, el resultado del análisis de todo el intervalo se denomina ‘r0’. Los subintervalos se identifican por ‘r1′,’r2’, etc, en orden al alejarse de la baliza.
En el resultado como valor complementario de revisión se añade el coeficiente de correlación de los puntos usados en el análisis.
Algoritmo en Python
# LoRa-Multipunto, Rssi vs distancia # linealización Rssi vs log10(distancia) # por mínimos cuadrados # Graficas 2D y 3D # Girni 2020-10-07 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_medidaubica = 'rsmP06_'+medida+'Ubica01Intervalo.txt' # archivos de salida arch_ecuaciones = 'rsmP07_ecuacion01Intervalos.json' # Analizar por segmentos analiza = {'gtwRECT':{'analizar' : 1, 'atipico_std' : 1, 'frontera' : [320], 'atipInterv_std': [1,1], 'p_amplia': 4, 'grp' : ['RECT','FIEC'], 'tip' : ['punto'], 'LOS' : [1]}, 'gtwFIEC':{'analizar' : 1, 'atipico_std' : 1, 'frontera' : [190], 'atipInterv_std': [1,1], 'p_amplia': 4, 'grp' : ['FIEC','FCNM'], 'tip' : ['punto'], 'LOS' : [1,0]}, 'gtwFCNM':{'analizar' : 1, 'atipico_std' : 1, 'frontera' : [235.0], 'atipInterv_std': [2,2], 'p_amplia': 4, 'grp' : ['FIEC','FCNM'], 'tip' : ['punto'], 'LOS' : [1,0]} } 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 = 3 intersectar = 1 # 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 # Resultados de análisis ecuacion = {} eq_graf = {} # leer datos tabla = pd.read_csv(arch_medidaubica, index_col='etiqueta') tabla = pd.DataFrame(tabla) # analiza datos hacia una baliza for unabaliza in analiza: # Parámetros analizar = analiza[unabaliza]['analizar'] if analizar: ecuacion[unabaliza] = {} eq_graf[unabaliza] = {} # pares a usar de baliza [pares,par_etiqueta] = girni.pares_usar(tabla,baliza, analiza,unabaliza, medida = medida , modo = modo) # todos los puntos # analiza puntos para mínimos cuadrados xi = pares[:,0] yi = pares[:,1] n_xi = len(xi) # coeficiente de correlación correlacion = np.corrcoef(xi,yi)[0,1] # minimos cuadrados ecuacion0 = girni.linealiza_lstsq(xi,yi) # selecciona atipicos atipico_std = analiza[unabaliza]['atipico_std'] alpha = ecuacion0['alpha'] beta = ecuacion0['beta'] fdist0 = lambda d: -10*alpha*(np.log10(d))+beta yi0 = fdist0(xi) dyi0std = ecuacion0['error_std'] dyi0 = yi - yi0 atipicos = np.abs(dyi0) >= dyi0std*atipico_std xi0_e = xi[atipicos] yi0_e = yi[atipicos] etiq0_e = par_etiqueta[atipicos] unintervalo = 'r0' # todos # para exportar hacia archivo o gráfica ecuacion[unabaliza] = {unintervalo: ecuacion0} ecuacion[unabaliza][unintervalo]['correlacion'] = correlacion eq_graf[unabaliza] = {unintervalo: {'xi_graf':xi, 'yi_graf':yi, 'etiqueta': par_etiqueta, 'linea' : yi0, 'atipicos':[xi0_e,yi0_e], 'atip_etiq': etiq0_e} } # Intervalos radiales en sector intervalo = [np.min(xi),np.max(xi)] frontera = analiza[unabaliza]['frontera'] if len(frontera)>0: # revisar si frontera esta dentro intervalo frontera = np.array(frontera, dtype=float) revisar = (frontera>=np.min(xi)) & (frontera<=np.max(xi)) enintervalo = list(frontera[revisar]) intervalo.extend(enintervalo) intervalo = np.array(intervalo) ordenar = np.argsort(intervalo) intervalo = intervalo[ordenar] n_intervalo = len(intervalo) # analizar cada subintervalo p_inicio = 0 p_desde = 0 p_amplia = analiza[unabaliza]['p_amplia'] atipIntv_std = analiza[unabaliza]['atipInterv_std'] for i in range(0,n_intervalo-1,1): i_eq = 'r'+str(i+1) # indice en texto # puntos en subintervalo [a,b] a = intervalo[i] b = intervalo[i+1] subintervalo = (xi >= a) & (xi <= b) xi_sub = xi[subintervalo] yi_sub = yi[subintervalo] n_sub = len(xi_sub) etiq_sub = par_etiqueta[p_inicio:p_inicio + n_sub] # amplia sub-intervalo, mejora intersecta rectas detras = p_inicio retrocede = detras if detras > p_amplia: retrocede = p_amplia delante = n_xi - (p_inicio+n_sub)# -1) avanza = delante if delante >= p_amplia: avanza = p_amplia p_desde = p_inicio - retrocede p_hasta = p_inicio + (n_sub) + avanza p_inicio = p_inicio + (n_sub-1) # subintervalo, amplia puntos xi_a = xi[p_desde:p_hasta] yi_a = yi[p_desde:p_hasta] etiq_a = par_etiqueta[p_desde:p_hasta] # coeficiente de correlación correlacion1 = np.corrcoef(xi_a,yi_a)[0,1] # analiza subintervalo ecuacion1 = girni.linealiza_lstsq(xi_a,yi_a) ecuacion[unabaliza][i_eq] = ecuacion1 ecuacion[unabaliza][i_eq]['correlacion'] = correlacion1 # atipicos del subintervalo extendido alpha = ecuacion1['alpha'] beta = ecuacion1['beta'] fdist1 = lambda d: -10*alpha*(np.log10(d))+beta yi1 = fdist1(xi_a) dyi1std = ecuacion1['error_std'] atipico_std = analiza[unabaliza]['atipInterv_std'][i] dyi1 = yi_a - yi1 atipicos = np.zeros(len(xi_a),dtype=bool) if np.abs(dyi1std) > casicero: atipicos = np.abs(dyi1) >= dyi1std*atipico_std xi1_e = xi_a[atipicos] yi1_e = yi_a[atipicos] etiq1_e = etiq_a[atipicos] # para gráfica, atipicos sin extender puntos atipicos_sub = (xi1_e >= a) & (xi1_e<=b) xi_sub1_e = xi1_e[atipicos_sub] yi_sub1_e = yi1_e[atipicos_sub] etiq_sub1e = etiq1_e[atipicos_sub] eq_graf[unabaliza][i_eq] = {'atipicos': [xi_sub1_e,yi_sub1_e], 'atip_etiq':etiq_sub1e} # subintervalo sin atipicos if len(xi1_e)>0: atipicoNo = np.abs(dyi1) <= dyi1std*atipico_std xi2 = xi_a[atipicoNo] yi2 = yi_a[atipicoNo] etiq2 = etiq_a[atipicoNo] # coeficiente de correlación correlacion2 = np.corrcoef(xi2,yi2)[0,1] ecuacion2 = girni.linealiza_lstsq(xi2,yi2) # actualiza ecuación sin atipicos intervaloy intervalox = ecuacion1['intervalox'] ecuacion2['intervalox'] = intervalox.copy() alpha = ecuacion2['alpha'] beta = ecuacion2['beta'] fdist = lambda d: -10*alpha*(np.log10(d))+beta intervaloy = fdist(intervalox) ordenar = np.argsort(intervaloy) intervaloy = list(intervaloy[ordenar]) ecuacion2['intervaloy'] = intervaloy ecuacion[unabaliza][i_eq] = ecuacion2 #ecuacion[unabaliza][i_eq]['correlacion1'] = correlacion1 ecuacion[unabaliza][i_eq]['correlacion'] = correlacion2 # Revisa frontera entre subintervalos, # usa intersección de rectas como nueva frontera interv_calc = np.copy(intervalo) if len(intervalo) >2 and intersectar==1 : for i in range(0,n_intervalo-2,1): ai = 'r'+str(i+1) bi = 'r'+str(i+2) ma = ecuacion[unabaliza][ai]['alpha'] ba = ecuacion[unabaliza][ai]['beta'] mb = ecuacion[unabaliza][bi]['alpha'] bb = ecuacion[unabaliza][bi]['beta'] # punto de intersección o cruce cruzanx = 10**((bb-ba)/(10*(mb-ma))) dfrontera = frontera-cruzanx # cruce dentro de intervalo de ecuacion if cruzanx > intervalo[-1]: cruzanx = intervalo[-1] if cruzanx < intervalo[0]: cruzanx = intervalo[0] interv_calc[i+1] = cruzanx # para grafica evalua cada subintervalo sin atipicos n_interv_calc = len(interv_calc) for i in range(0,n_interv_calc-1,1): i_eq = 'r'+str(i+1) a = interv_calc[i] b = interv_calc[i+1] subintervalo = (xi >= a) & (xi <= b) xi_sub = xi[subintervalo] yi_sub = yi[subintervalo] xi_graf = np.copy(xi[subintervalo]) if not(a in xi_sub): xi_graf = np.concatenate(([a],xi_graf),axis=0) if not(b in xi_sub): xi_graf = np.concatenate((xi_graf,[b]),axis=0) # Evalua subintervalo con la ecuacion sin atipicos alpha = ecuacion[unabaliza][i_eq]['alpha'] beta = ecuacion[unabaliza][i_eq]['beta'] fdist = lambda d: -10*alpha*(np.log10(d))+beta yi1_sub = fdist(xi_sub) yi_graf = fdist(xi_graf) eq_graf[unabaliza][i_eq]['xi_graf'] = xi_graf eq_graf[unabaliza][i_eq]['yi_graf'] = yi_graf a = np.round(np.min([xi_graf]),precision) b = np.round(np.max([xi_graf]),precision) ecuacion[unabaliza][i_eq]['intervalox'] = [a,b] ay = np.round(np.min([yi_graf]),precision) by = np.round(np.max([yi_graf]),precision) ecuacion[unabaliza][i_eq]['intervaloy'] = [ay,by] # SALIDA for unabaliza in ecuacion: print('baliza: ',unabaliza) for unaecuacion in ecuacion[unabaliza]: unintervalo = ecuacion[unabaliza][unaecuacion]['intervalox'] unintervaloy = ecuacion[unabaliza][unaecuacion]['intervaloy'] error_medio = ecuacion[unabaliza][unaecuacion]['error_medio'] error_std = ecuacion[unabaliza][unaecuacion]['error_std'] eq_latex = ecuacion[unabaliza][unaecuacion]['eq_latex'] errorx_medio = ecuacion[unabaliza][unaecuacion]['errorx_medio'] errorx_std = ecuacion[unabaliza][unaecuacion]['errorx_std'] correlacion = ecuacion[unabaliza][unaecuacion]['correlacion'] print(' intervalo: ',unaecuacion) print(' ' + eq_latex) print(' ','intervalox: ',np.round(unintervalo,precision)) print(' ','intervaloy: ',np.round(unintervaloy,precision)) print(' correlación: ',np.round(correlacion,precision)) print(' |error_rssi| promedio: ',np.round(error_medio,precision), ' , std:',np.round(error_std,precision)) print(' |error_dist| promedio: ',np.round(errorx_medio,precision), ' , std:',np.round(errorx_std,precision)) print() # salida hacia archivo with open(arch_ecuaciones, '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 ecuacion: figura,grafica = plt.subplots() if escala == 'log': grafica.set_xscale(escala,base=escalabase) # todos los puntos unintervalo = 'r0' xi = eq_graf[unabaliza][unintervalo]['xi_graf'] yi = eq_graf[unabaliza][unintervalo]['yi_graf'] etiqueta = eq_graf[unabaliza][unintervalo]['etiqueta'] grafica.scatter(xi,yi,marker='.') m = len(xi) for i in range(0,m,1): grafica.annotate(etiqueta[i], (xi[i],yi[i])) # linea con todos los puntos fdtxt = ecuacion[unabaliza][unintervalo]['eq_latex'] yi0 = eq_graf[unabaliza][unintervalo]['linea'] a = np.round(np.min([xi]),2) b = np.round(np.max([xi]),2) eq_texto = fdtxt+' ; ['+str(a)+','+str(b)+']' grafica.plot(xi,yi0, label = eq_texto, linestyle='dotted') # lineas por cada subintervalo eq_interv = list(ecuacion[unabaliza].keys()) eq_interv.pop(0) n_intervalo = len(eq_interv) for i_eq in eq_interv: fdtxt = ecuacion[unabaliza][i_eq]['eq_latex'] xi_graf = eq_graf[unabaliza][i_eq]['xi_graf'] yi_graf = eq_graf[unabaliza][i_eq]['yi_graf'] a = np.round(np.min([xi_graf]),precision) b = np.round(np.max([xi_graf]),precision) eq_texto = fdtxt+' ; ['+str(a)+','+str(b)+']' grafica.plot(xi_graf,yi_graf, label = eq_texto) # atipicos marcados en subintervalo [xi1_e,yi1_e] = eq_graf[unabaliza][i_eq]['atipicos'] etiq1_e = eq_graf[unabaliza][i_eq]['atip_etiq'] grafica.scatter(xi1_e,yi1_e, color='red') m = len(etiq1_e) for i in range(0,m,1): grafica.annotate(etiq1_e[i], (xi1_e[i],yi1_e[i]), color='red') # lineas de frontera grafica.axvline(a, color='lightblue') valor_frontera = str(np.round(a,precision)) grafica.annotate(valor_frontera, (a,np.max([yi,yi0])), color='lightblue') grafica.axvline(b, color='lightblue') valor_frontera = str(np.round(b,precision)) grafica.annotate(valor_frontera, (b,np.max([yi,yi0])), color='lightblue') # 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+': '+medida+'_'+modo + ' vs distancia' grafica.set_title(untitulo) plt.show()