El efecto «sombra» añade el parámetro sector a la ecuación que se incorpora al resultado de la linealización en cada baliza.
La ecuación de una baliza se compone entonces de dos parámetros de selección: sector
e intervalo
.
Como ilustración se muestra la figura que tiene tres partes o ecuaciones:
ecuacion[‘s0’][‘r1’]
ecuacion[‘s0’][‘r2’]
ecuacion[‘s1’][‘r0’]
El primer parámetro para seleccionar la ecuación es el sector, ‘s0’ y ‘s1’, que en caso que sea un solo círculo se identifica como ‘s0’.
Dentro de cada sector, se mantiene el concepto de intervalos de distancia o radio. Se mantiene el concepto de la sección anterior, donde ‘r0’ corresponde a la linealización de todos los puntos en el sector. Cuando exiten sub-intervalos se usa ‘r1’, ‘r2’, etc para cada intervalo.
El número de ecuaciones corresponde al número de balizas y sectores establecidos para el análisis.
Se realizan cambios menores a la función pares_usar() de la librería girni para incorporar el parámetro sector, que al ser vacío ''
funciona como fué descrito en las secciones anteriores.
pares_usar(tabla,baliza, analiza,unabaliza, unsector =», medida = ‘rssi’, modo = ‘rx’)
También se actualizaron los nombres de los archivos de entrada y salida para diferenciar de los resultados anteriores y disponer de los archivos para comparar con los resultados del método que solo usa intervalos.
Algoritmo en Python
# LoRa-Multipunto, Rssi vs distancia con mínimos cuadrados # linealización Rssi vs log10(distancia) # por Sectores e intervalos , Graficas '2D' # 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' arch_medidaubica = 'rsmP06_'+medida+'Ubica01sector1.txt' # archivos de salida arch_ecuaciones = 'rsmP07_ecuacionSector01.json' arch_medUbAtrib = 'rsmP07_'+medida+'UbicaUsarSector01.txt' # Analizar por segmentos analiza = {'gtwRECT':{'analizar' : 1, 'sector_ref' : ['FIEC112','FCNM110'], 's0':{'atipico_std' : 1, 'frontera' : [300], 'atipInterv_std': [2,2], 'p_amplia': 2, 'grp' : ['RECT','FIEC'], 'tip' : ['punto'], 'LOS' : [1] }, 's1':{'atipico_std' : 1, 'frontera' : [], 'atipInterv_std': [2], 'p_amplia': 2, 'grp' : ['FIEC','FCNM'], 'tip' : ['punto'], 'LOS' : [1,0] } }, 'gtwFIEC':{'analizar' : 1, 'sector_ref' : [], 's0':{'atipico_std' : 1, 'frontera' : [190], 'atipInterv_std': [1,1], 'p_amplia': 4, 'grp' : ['FIEC','FCNM'], 'tip' : ['punto'], 'LOS' : [0,1] } }, 'gtwFCNM':{'analizar' : 1, 'sector_ref' : [], 's0':{'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','' sin grafica escala = 'log' # 'normal','log' escalabase = 10 # 10 casicero = 1e-4 precision = 2 intersectar = 1 # 0:Falso, 1: Verdadero # PROCEDIMIENTO # leer datos tabla = pd.read_csv(arch_medidaubica, index_col='etiqueta') tabla = pd.DataFrame(tabla) baliza_key = list(baliza.keys()) baliza_val = list(baliza.values()) # Resultados de análisis ecuacion = {} eq_graf = {} # analiza datos hacia una baliza for unabaliza in analiza: donde = baliza_val.index(unabaliza) cualbaliza = baliza_key[donde] # Parámetros analizar = analiza[unabaliza]['analizar'] if analizar: # Crea ecuacion por baliza ecuacion[unabaliza] = {'sector_rad':[]} eq_graf[unabaliza] = {} # sectores sectores = [] sector_ref = analiza[unabaliza]['sector_ref'] tabla['sector_'+cualbaliza] = 0 # 'todos' predeterminado # coordenadas baliza para identificar ángulo b_este = tabla['c_este'][unabaliza] b_norte = tabla['c_norte'][unabaliza] # sectores por puntos de referencia if len(sector_ref)>0: for cadapunto in sector_ref: 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 and dx<0: theta = theta + 2*np.pi sectores.append(theta) sectores = np.array(sectores) ordenar = np.argsort(sectores) sectores = list(sectores[ordenar]) nsectores = len(sectores) # clasifica puntos por sector particular for cadapunto in tabla.index: dentrosector = 0 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 and dx<0: theta = theta + 2*np.pi for j in range(0,nsectores-1,1): if theta>sectores[j] and theta<sectores[j+1]: dentrosector = j+1 tabla.loc[cadapunto,'sector_'+cualbaliza] = dentrosector # ecuacion por baliza y sector ecuacion[unabaliza]['sector_rad'] = sectores nsectores = len(sectores) if nsectores == 0: nsectores = 1 for cadasector in range(0,nsectores,1): unsector = 's'+str(cadasector) ecuacion[unabaliza][unsector] = {} eq_graf[unabaliza][unsector] = {} # ecuación con todos los puntos como referencia [pares,par_etiqueta] = girni.pares_usar(tabla,baliza,analiza, unabaliza,unsector, medida,modo) 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 de todos los puntos atipico_std = analiza[unabaliza][unsector]['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][unsector] = {unintervalo: ecuacion0 } ecuacion[unabaliza][unsector][unintervalo]['correlacion'] = correlacion eq_graf[unabaliza][unsector] = {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][unsector]['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][unsector]['p_amplia'] atipIntv_std = analiza[unabaliza][unsector]['atipInterv_std'] for i in range(0,n_intervalo-1,1): i_eq = 'r' + str(i+1) # 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][unsector][i_eq] = ecuacion1 ecuacion[unabaliza][unsector][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'] atipicos = np.zeros(len(xi_a),dtype=bool) atipico_std = analiza[unabaliza][unsector]['atipInterv_std'][i] dyi1 = yi_a - yi1 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][unsector][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][unsector][i_eq] = ecuacion2 ecuacion[unabaliza][unsector][i_eq]['correlacion'] = correlacion2 # Revisar frontera entre subintervalos, # calcula 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][unsector][ai]['alpha'] ba = ecuacion[unabaliza][unsector][ai]['beta'] mb = ecuacion[unabaliza][unsector][bi]['alpha'] bb = ecuacion[unabaliza][unsector][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_graf): xi_graf = np.concatenate(([a],xi_graf),axis=0) if not(b in xi_graf): xi_graf = np.concatenate((xi_graf,[b]),axis=0) # Evalua subintervalo con la ecuacion sin atipicos alpha = ecuacion[unabaliza][unsector][i_eq]['alpha'] beta = ecuacion[unabaliza][unsector][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][unsector][i_eq]['xi_graf'] = xi_graf eq_graf[unabaliza][unsector][i_eq]['yi_graf'] = yi_graf a = np.round(np.min([xi_graf]),precision) b = np.round(np.max([xi_graf]),precision) ecuacion[unabaliza][unsector][i_eq]['intervalox'] = [a,b] ay = np.round(np.min([yi_graf]),precision) by = np.round(np.max([yi_graf]),precision) ecuacion[unabaliza][unsector][i_eq]['intervaloy'] = [ay,by] # SALIDA for unabaliza in ecuacion: for unsector in ecuacion[unabaliza]: if unsector == 'sector_rad': print('baliza: ',unabaliza) print(' sectores radianes: ',ecuacion[unabaliza]['sector_rad']) if unsector != 'sector_rad': for i_eq in ecuacion[unabaliza][unsector]: unintervalo = ecuacion[unabaliza][unsector][i_eq]['intervalox'] unintervaloy = ecuacion[unabaliza][unsector][i_eq]['intervaloy'] error_medio = ecuacion[unabaliza][unsector][i_eq]['error_medio'] error_std = ecuacion[unabaliza][unsector][i_eq]['error_std'] eq_latex = ecuacion[unabaliza][unsector][i_eq]['eq_latex'] errorx_medio = ecuacion[unabaliza][unsector][i_eq]['errorx_medio'] errorx_std = ecuacion[unabaliza][unsector][i_eq]['errorx_std'] correlacion = ecuacion[unabaliza][unsector][i_eq]['correlacion'] print(' [sector][intervalo]: ',unsector,',',i_eq) 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) tabla.to_csv(arch_medUbAtrib) # GRAFICA # Referencias para gráfica grupo = ['FIEC' ,'FCNM' ,'RECT','CIRC'] colores = ['green','orange','grey','magenta'] tipo = ['punto','1m' ,'gtw','dispositivo'] marcas = [ 'o','D' ,'D' ,'*' ] if tipograf=='2D': for unabaliza in ecuacion: for unsector in ecuacion[unabaliza]: if not(unsector=='sector_rad'): figura,grafica = plt.subplots() if escala == 'log': grafica.set_xscale(escala,base=escalabase) # todos los puntos unintervalo = 'r0' xi = eq_graf[unabaliza][unsector][unintervalo]['xi_graf'] yi = eq_graf[unabaliza][unsector][unintervalo]['yi_graf'] etiqueta = eq_graf[unabaliza][unsector][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])) # linealizado con todos los puntos fdtxt = ecuacion[unabaliza][unsector][unintervalo]['eq_latex'] yi0 = eq_graf[unabaliza][unsector][unintervalo]['linea'] a = np.round(np.min([xi]),precision) b = np.round(np.max([xi]),precision) eq_texto = fdtxt +' ; ['+ str(a) +','+ str(b)+']' grafica.plot(xi,yi0,label=eq_texto,linestyle='dotted') # linealizado por subintervalo eq_interv = list(ecuacion[unabaliza][unsector].keys()) eq_interv.pop(0) n_intervalo = len(eq_interv) for i_eq in eq_interv: fdtxt = ecuacion[unabaliza][unsector][i_eq]['eq_latex'] grtxt = ecuacion[unabaliza][unsector][i_eq]['eqg_latex'] xi_graf = eq_graf[unabaliza][unsector][i_eq]['xi_graf'] yi_graf = eq_graf[unabaliza][unsector][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][unsector][i_eq]['atipicos'] etiq1_e = eq_graf[unabaliza][unsector][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+'_'+unsector+': ' untitulo = untitulo+medida+'_'+modo+' vs distancia' grafica.set_title(untitulo) plt.show()