{"id":3895,"date":"2021-12-03T10:30:13","date_gmt":"2021-12-03T15:30:13","guid":{"rendered":"http:\/\/blog.espol.edu.ec\/girni\/?p=3895"},"modified":"2026-08-04T10:48:49","modified_gmt":"2026-08-04T15:48:49","slug":"lorawan-funciones-girni_lora_lib","status":"publish","type":"post","link":"https:\/\/blog.espol.edu.ec\/girni\/lorawan-funciones-girni_lora_lib\/","title":{"rendered":"4. LoRaWan - Funciones girni_lorawan_lib"},"content":{"rendered":"\n<p>El archivo contiene un grupo de&nbsp; funciones usadas para procesar los datos de este prototipo, se separaron del bloque principal de instrucciones con&nbsp; el objetivo de simplificar el desarrollo del las actividades principales.<\/p>\n\n\n\n<p>Recuerde disponer de este archivo en la misma carpeta que el algoritmo que invoca a la librer\u00eda.<\/p>\n\n\n\n<p>archivo de librer\u00eda: girni_lorawan_libreria<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Instrucciones Python<\/h2>\n\n\n<div class=\"wp-block-syntaxhighlighter-code alignwide\"><pre class=\"brush: python; title: ; notranslate\" title=\"\">\n# Girni LoRaWan librerias 2021-10-28\n# LoRaWan, lecturas de Rssi y SNR\n# Propuesta: edelros@espol.edu.ec\n# http:\/\/blog.espol.edu.ec\/girni\/\nimport numpy as np\nimport json\nimport pandas as pd\nimport datetime as dt\nimport os\nimport matplotlib.pyplot as plt\nimport matplotlib.dates as mdates\nimport matplotlib.units as munits\n\nimport geopandas as gpd\nimport fiona\nimport utm\n\ndef tablapunto(unarchivoDB,unsensor,gatewayDB,fechainicio,fechafin,zonaGMT=0):\n    '''Lectura de archivo.json hacia una tabla0\n       selecciona registros de &quot;un sensor&quot;\n       graba unreporte.csv con pandas\n    '''\n    campos = &#x5B;'domain','entity_id','state','attributes','created']\n\n    # Lectura de archivo json, cambia a formato DataFrame\n    tabla0 = pd.DataFrame()\n    archivoexiste = os.path.exists(unarchivoDB)\n    if archivoexiste:\n        tabla0 = pd.read_json(unarchivoDB)\n        tabla0 = pd.DataFrame(tabla0,columns=campos)\n    else:\n        print(' ERROR: NO se encuentra el archivo...')\n        print('        revise el nombre de archivo. ')\n\n    # Revisa cada registro \n    leidos = 0\n    tabla  = {}\n    if archivoexiste:\n        # Intervalo de fecha como datetime\n        hora_desplaza  = dt.timedelta(hours = abs(zonaGMT))\n        fechaformatoDB = '%Y-%m-%dT%H:%M:%S.%f'\n        fechaformato   = '%Y-%m-%d %H:%M:%S.%f'\n        fechatxt     = fechainicio&#x5B;0:np.min(&#x5B;26,len(fechainicio)])]\n        fechainicio  = dt.datetime.strptime(fechatxt,fechaformato)\n        fechatxt     = fechafin&#x5B;0:np.min(&#x5B;26,len(fechafin)])]\n        fechafin     = dt.datetime.strptime(fechatxt,fechaformato)\n\n        # datos de trama\n        for cadaregistro in tabla0.index:\n            unatrama   = tabla0&#x5B;'attributes']&#x5B;cadaregistro]\n            trama_mqtt = json.loads(unatrama)\n            \n            # selecciona registro por sensor, en fecha y con datos\n            cualsensor = (tabla0&#x5B;'entity_id']&#x5B;cadaregistro] == unsensor)\n            \n            unafecha = tabla0&#x5B;'created']&#x5B;cadaregistro]\n            unafecha = unafecha&#x5B;0:np.min(&#x5B;26,len(unafecha)])]\n            unafecha = dt.datetime.strptime(unafecha,fechaformato)\n            unafecha = unafecha - hora_desplaza\n            \n            enfecha  = (unafecha&gt;=fechainicio) and (unafecha&lt;=fechafin)\n            condatos = 'applicationID' in trama_mqtt.keys()\n            \n            selecciona = cualsensor and condatos and enfecha\n            if (selecciona == True):        \n                # datos en la mensaje MQTT\n                publishedAt = trama_mqtt&#x5B;&quot;publishedAt&quot;]\n                publishedAt = publishedAt&#x5B;0:np.min(&#x5B;26,len(publishedAt)])]\n                publishedAt = dt.datetime.strptime(publishedAt,fechaformatoDB)\n                publishedAt = publishedAt - hora_desplaza\n                \n                friendly_name = trama_mqtt&#x5B;&quot;friendly_name&quot;]\n                deviceName    = trama_mqtt&#x5B;&quot;deviceName&quot;]\n                dispositivo   = friendly_name.split('_')&#x5B;2]\n                \n                dr    = trama_mqtt&#x5B;&quot;dr&quot;]\n                fCnt  = trama_mqtt&#x5B;&quot;fCnt&quot;]\n                fPort = trama_mqtt&#x5B;&quot;fPort&quot;]\n\n                objectJSON  = trama_mqtt&#x5B;&quot;objectJSON&quot;]\n                datosensor  = json.loads(objectJSON)\n                \n                freq_tx   = trama_mqtt&#x5B;&quot;txInfo&quot;]&#x5B;&quot;frequency&quot;]\n                bandwidth   = trama_mqtt&#x5B;&quot;txInfo&quot;]&#x5B;&quot;loRaModulationInfo&quot;]&#x5B;&quot;bandwidth&quot;]\n                spreadingFactor = trama_mqtt&#x5B;&quot;txInfo&quot;]&#x5B;&quot;loRaModulationInfo&quot;]&#x5B;&quot;spreadingFactor&quot;]\n                     \n                datostrama = {&quot;publishedAt&quot;: publishedAt,\n                              &quot;dispositivo&quot;: dispositivo,\n                              &quot;fCnt&quot;: fCnt}\n                \n                # revisa gateway en la red LoRaWan\n                tamano = len(trama_mqtt&#x5B;&quot;rxInfo&quot;])\n                i = 0\n                while i&lt;tamano:\n                    gatewayID = trama_mqtt&#x5B;&quot;rxInfo&quot;]&#x5B;i]&#x5B;&quot;gatewayID&quot;]\n                    rssi      = trama_mqtt&#x5B;&quot;rxInfo&quot;]&#x5B;i]&#x5B;&quot;rssi&quot;]\n                    loRaSNR   = trama_mqtt&#x5B;&quot;rxInfo&quot;]&#x5B;i]&#x5B;&quot;loRaSNR&quot;]\n                    channel   = trama_mqtt&#x5B;&quot;rxInfo&quot;]&#x5B;i]&#x5B;&quot;channel&quot;]\n                    rfChain   = trama_mqtt&#x5B;&quot;rxInfo&quot;]&#x5B;i]&#x5B;&quot;rfChain&quot;]\n                    gtwNum    = gatewayDB&#x5B;gatewayID]\n                    \n                    # registra en tabla, incluyendo tramas repetidas\n                    datostrama&#x5B;'rssi_up']    = rssi\n                    datostrama&#x5B;'snr_up']     = loRaSNR\n                    datostrama&#x5B;'channel_up'] = channel\n                    datostrama&#x5B;'rfChain_up'] = rfChain\n                    datostrama&#x5B;'gtw_rx']     = gtwNum\n                    i = i + 1\n\n                # dato del sensor\n                equivale = {'Down_datarate': 'dr_down',\n                            'Down_rssi'    : 'rssi_down',\n                            'Down_snr'     : 'snr_down',\n                            'bateria_V'    : 'bateria_V'}\n                for undato in datosensor:\n                    if undato in equivale.keys():\n                        datostrama&#x5B;equivale&#x5B;undato]] = datosensor&#x5B;undato]\n                    else:\n                        datostrama&#x5B;undato] = datosensor&#x5B;undato]\n\n                # datos restantes\n                datostrama&#x5B;&quot;frequency&quot;] = freq_tx\n                datostrama&#x5B;&quot;bandwidth&quot;] = bandwidth\n                datostrama&#x5B;&quot;spreadingFactor&quot;] = spreadingFactor\n                datostrama&#x5B;&quot;fPort&quot;]     = fPort\n                datostrama&#x5B;&quot;dr&quot;]        = dr\n                datostrama&#x5B;&quot;created&quot;]   = unafecha\n\n                leidos = leidos + 1\n                \n                # revisa registro repetido\n                repetido = False\n                if leidos&gt;1:\n                    trama_num  = (fCnt == tabla&#x5B;leidos-1]&#x5B;'fCnt'])\n                    fecha_pub  = (publishedAt == tabla&#x5B;leidos-1]&#x5B;'publishedAt'])\n                    gtwNum_rep = (gtwNum == tabla&#x5B;leidos-1]&#x5B;'gtw_rx'])\n                    repetido   = (trama_num and fecha_pub and gtwNum_rep)\n                if not(repetido):\n                    tabla&#x5B;leidos] = datostrama\n                else:\n                    leidos = leidos - 1\n                \n        # convierte diccionario en DataFrame\n        if len(tabla)&gt;0:\n            tabla = pd.DataFrame(tabla)\n            tabla = tabla.T\n    return(tabla)\n\ndef describe_punto(tabla,codigopunto,carpeta_rsm,variables):\n    ''' Descriptores estadisticos de los datos.csv\n        de un dispositivo, revisa media, desviaci\u00f3 est\u00e1ndar, pmf\n        graba unreporte.csv con pandas y genera gr\u00e1ficas\n    '''\n    medida = variables&#x5B;'medida']\n    medida_unidad = variables&#x5B;'medida_unidad']\n    medida_normal = variables&#x5B;'medida_normal']\n    movAvg_cual = variables&#x5B;'movAvg_cual']\n    medida_grafica = variables&#x5B;'medida_grafica']\n    movAvg_color = variables&#x5B;'movAvg_color']\n    guarda = variables&#x5B;'guarda']\n    precision = variables&#x5B;'precision']\n                   \n    fechaformato = &quot;%Y-%m-%d %H:%M:%S.%f&quot;\n    # medida intervalo\n    medida_min = np.min(medida_normal)\n    medida_max = np.max(medida_normal)\n\n    # fechas series a datetime\n    tabla&#x5B;'publishedAt'] = pd.to_datetime(tabla&#x5B;'publishedAt'],\n                                          format=fechaformato)\n    tabla&#x5B;'created'] = pd.to_datetime(tabla&#x5B;'publishedAt'],\n                                      format=fechaformato)\n\n    # revisa errores de medida\n    tabla&#x5B;&quot;error_up&quot;]   = 0\n    tabla&#x5B;&quot;error_down&quot;] = 0\n    for undato in tabla&#x5B;'publishedAt'].keys():   \n        medida_up = tabla&#x5B;medida+'_up']&#x5B;undato]\n        enrango = (medida_up&gt;=np.min(medida_normal))\n        enrango = (enrango and medida_up&lt;=np.max(medida_normal))\n        if not(enrango):\n            tabla.at&#x5B;undato,&quot;error_up&quot;] = 1\n        \n        medida_down = tabla&#x5B;medida+'_down']&#x5B;undato]\n        enrango = (medida_down&gt;=np.min(medida_normal))\n        enrango = (enrango and medida_down&lt;=np.max(medida_normal))\n        if not(enrango):\n            tabla.at&#x5B;undato,&quot;error_down&quot;] = 1      \n\n    # tasa error trama\n    leidos = len(tabla)\n    if leidos &gt; 0:\n        error_up   = np.sum(tabla&#x5B;'error_up'])\n        error_up   = error_up\/leidos\n        error_down = np.sum(tabla&#x5B;'error_down'])\n        error_down = error_down\/leidos\n\n    # descriptor estad\u00edstico, datos sin errores\n    condicion_up = (tabla&#x5B;'error_up']==0)\n    condicion_down = (tabla&#x5B;'error_down']==0)\n\n    medida_up = tabla&#x5B;condicion_up]&#x5B;medida+'_up']\n    describe_up = medida_up.describe()\n    describe_up&#x5B;'error_trama'] = error_up\n\n    medida_down = tabla&#x5B;condicion_down]&#x5B;medida+'_down']\n    describe_down = medida_down.describe()\n    describe_down&#x5B;'error_trama'] = error_down\n\n    descriptor = describe_up.copy()\n    descriptor = pd.concat(&#x5B;descriptor,describe_down],axis=1)\n    descriptor&#x5B;'dispositivo'] = tabla&#x5B;'dispositivo']&#x5B;0]\n\n    pmf_up   = medida_pmf(medida_up,describe_up)\n    pmf_down = medida_pmf(medida_down,describe_down)\n\n    pmf_punto = {'pmf':{'pmf_up'   : pmf_up,\n                        'pmf_down' : pmf_down}}\n    pmf_punto = pd.DataFrame(pmf_punto)\n    pmf_punto&#x5B;'dispositivo'] = tabla&#x5B;'dispositivo']&#x5B;0]\n\n    # Para gr\u00e1ficas\n    # medias moviles en movAvg_cual&#x5B;]\n    serie_up  = pd.Series(medida_up)\n    movAvg_up_mean = &#x5B;]\n    movAvg_up_std = &#x5B;]\n    m = len(movAvg_cual)\n    for j in range(0,m,1):\n        k = movAvg_cual&#x5B;j]\n        movAvg_up_mean.append(list(serie_up.rolling(k).mean()))\n        movAvg_up_std.append(list(serie_up.rolling(k).std()))\n        \n    serie_down = pd.Series(medida_down)\n    movAvg_down_mean = &#x5B;]\n    movAvg_down_std = &#x5B;]\n    for j in range(0,m,1):\n        k = movAvg_cual&#x5B;j]\n        movAvg_down_mean.append(list(serie_down.rolling(k).mean()))\n        movAvg_down_std.append(list(serie_down.rolling(k).std()))\n\n    movAvgData ={'movAvg_cual'   : movAvg_cual,\n                 'movAvg_color'  : movAvg_color,\n                 'movAvg_up_mean'  : movAvg_up_mean,\n                 'movAvg_down_mean': movAvg_down_mean,\n                 'movAvg_up_std'   : movAvg_up_std,\n                 'movAvg_down_std' : movAvg_down_std\n                 }\n\n    grafData ={'codigopunto' : codigopunto,\n               'medida' : medida,\n               'precision': precision,\n               'medida_unidad' : medida_unidad,\n               'medida_grafica': medida_grafica\n               }\n    resultado = &#x5B;tabla,descriptor,pmf_punto,movAvgData,grafData]\n    return(resultado)\n\n# funci\u00f3n de probabilidad de masa pmf\ndef medida_pmf(valores,undescriptor):\n    pmin   = np.min(valores)\n    pmax   = np.max(valores)\n    tramo  = int(pmax-pmin)\n    conteo = np.zeros(tramo+1,dtype=int)\n    intervalo = np.arange(pmin,pmax+1,1)\n    for valor in valores:\n        donde = np.where(intervalo == valor)\n        conteo&#x5B;donde] = conteo&#x5B;donde] + 1\n    freq_relativa = np.array(conteo)\/np.sum(conteo)\n    unpmf = {'intervalo' : list(intervalo),\n             'freq_relativa' : list(freq_relativa)}\n    return(unpmf)\n\n# GRAFICA -----\ndef graf_puntos_serie(tabla,descriptor,movAvgData,grafData):\n    ''' grafica la serie de tiempo de cada punto\n        a\u00f1ade medias m\u00f3viles\n    '''\n    # ajuste de formato de fecha para eje x\n    converter = mdates.ConciseDateConverter()\n    munits.registry&#x5B;np.datetime64] = converter\n    munits.registry&#x5B;dt.date] = converter\n    munits.registry&#x5B;dt.datetime] = converter\n\n    # datos para grafica\n    precision   = grafData&#x5B;'precision']\n    medida = grafData&#x5B;'medida']\n    medida_unidad  = grafData&#x5B;'medida_unidad']\n    medida_grafica = grafData&#x5B;'medida_grafica']\n    \n    movAvg_cual  = movAvgData&#x5B;'movAvg_cual']\n    movAvg_color = movAvgData&#x5B;'movAvg_color']\n    \n    media_up    = descriptor&#x5B;medida+'_up']&#x5B;'mean']\n    std_up      = descriptor&#x5B;medida+'_up']&#x5B;'std']\n    media_down  = descriptor&#x5B;medida+'_down']&#x5B;'mean']\n    std_down    = descriptor&#x5B;medida+'_down']&#x5B;'std']\n\n    # ajuste de intervalo eje y\n    y_min = np.min(&#x5B;np.min(medida_grafica),\n                    media_up - 2*std_up,\n                    media_down - 2*std_down])\n    y_max = np.max(&#x5B;np.max(medida_grafica),\n                    media_up + 2*std_up,\n                    media_down + 2*std_down])\n    \n    # selecciona sin error\n    condicion_up = (tabla&#x5B;'error_up']==0)\n    condicion_down = (tabla&#x5B;'error_down']==0)\n\n    # grafica\n    fig_serie,(graf_up,graf_down) = plt.subplots(2,1)\n    \n    # medida_up -----\n    graf_up.plot(tabla&#x5B;condicion_up]&#x5B;'publishedAt'],\n                 tabla&#x5B;condicion_up]&#x5B;medida+'_up'],\n                 color='blue',marker ='.',\n                 linestyle='')\n    \n    # medida_up, medias y std\n    etiq_up = str(np.round(media_up,precision))+' +\/- '\n    etiq_up = etiq_up + str(np.round(std_up,precision))\n    graf_up.axhline(media_up,\n                    color='blue',label=etiq_up)\n    graf_up.axhline(media_up-std_up,\n                    color='blue',linestyle='dotted')\n    graf_up.axhline(media_up+std_up,\n                    color='blue',linestyle='dotted')\n    \n    # medida_up, medias m\u00f3viles\n    m = len(movAvg_cual)\n    for j in range(0,m,1):\n        k = str(movAvg_cual&#x5B;j])\n        graf_up.plot(tabla&#x5B;condicion_up]&#x5B;'publishedAt'],\n                     movAvgData&#x5B;'movAvg_up_mean']&#x5B;j],\n                     label='movAvg_'+k,\n                     color=movAvg_color&#x5B;j])\n    \n    graf_up.set_ylim(y_min,y_max)\n    graf_up.set_ylabel(medida+'_up ('+medida_unidad+')',\n                       color='blue')\n    graf_up.legend()\n    graf_up.grid(True,linestyle='dotted',\n                 axis='x',which='both')\n\n    # medida_down -------\n    graf_down.plot(tabla&#x5B;condicion_down]&#x5B;'publishedAt'],\n                   tabla&#x5B;condicion_down]&#x5B;medida+'_down'],\n                   color='brown',marker ='.',\n                   linestyle='')\n\n    # medida_down, medias y std\n    etiq_down = str(np.round(media_down,precision))+' +\/- '\n    etiq_down = etiq_down + str(np.round(std_down,precision))\n    graf_down.axhline(media_down,\n                      color='brown',label=etiq_down)\n    graf_down.axhline(media_down+std_down,\n                      color='brown',linestyle='dotted')\n    graf_down.axhline(media_down-std_down,\n                      color='brown',linestyle='dotted')\n    \n    # medida_down, medias moviles\n    for j in range(0,m,1):\n        k = str(movAvg_cual&#x5B;j])\n        graf_down.plot(tabla&#x5B;condicion_down]&#x5B;'publishedAt'],\n                       movAvgData&#x5B;'movAvg_down_mean']&#x5B;j],\n                       label='movAvg_'+k,\n                       color=movAvg_color&#x5B;j])\n    \n    graf_down.set_ylim(y_min,y_max)\n    graf_down.set_xlabel('fecha')\n    graf_down.set_ylabel(medida+'_down ('+medida_unidad+')',\n                         color='brown')\n    graf_down.legend()\n    graf_down.grid(True,linestyle='dotted',\n                   axis='x', which='both')\n    graf_up.set_title('Serie: '+grafData&#x5B;'codigopunto']+' '+ medida)\n    plt.tight_layout()\n    return(fig_serie)\n\ndef graf_puntos_pmf(pmf_punto,descriptor,grafData):\n    ''' grafica funci\u00f3n de probabilida de masa\n        para cada punto, media +\/- std\n    '''\n    # datos para grafica\n    x_pmfup   = pmf_punto&#x5B;'pmf']&#x5B;'pmf_up']&#x5B;'intervalo']\n    y_pmfup   = pmf_punto&#x5B;'pmf']&#x5B;'pmf_up']&#x5B;'freq_relativa']\n    x_pmfdown = pmf_punto&#x5B;'pmf']&#x5B;'pmf_down']&#x5B;'intervalo']\n    y_pmfdown = pmf_punto&#x5B;'pmf']&#x5B;'pmf_down']&#x5B;'freq_relativa']\n    \n    precision = grafData&#x5B;'precision']\n    medida = grafData&#x5B;'medida']\n    medida_unidad  = grafData&#x5B;'medida_unidad']\n    medida_grafica = grafData&#x5B;'medida_grafica']\n    \n    media_up   = descriptor&#x5B;medida+'_up']&#x5B;'mean']\n    std_up     = descriptor&#x5B;medida+'_up']&#x5B;'std']\n    media_down = descriptor&#x5B;medida+'_down']&#x5B;'mean']\n    std_down   = descriptor&#x5B;medida+'_down']&#x5B;'std']\n\n    prob_max = 0.40\n    # ajuste de intervalo eje y\n    y_min = np.min(&#x5B;np.min(medida_grafica),\n                    media_up - 2*std_up,\n                    media_down - 2*std_down])\n    y_max = np.max(&#x5B;np.max(medida_grafica),\n                    media_up + 2*std_up,\n                    media_down + 2*std_down])\n    # grafica\n    fig_pmf,graf_pmf = plt.subplots()\n    etiq_up = str(np.round(media_up,precision)) +' +\/- '\n    etiq_up = etiq_up + str(np.round(std_up,precision))\n    graf_pmf.plot(x_pmfup,y_pmfup,\n                  label='media_up '+etiq_up,\n                  color='blue')\n    graf_pmf.axvline(media_up,color='blue')\n    graf_pmf.axvline(media_up+std_up,\n                     linestyle='dotted',color='blue')\n    graf_pmf.axvline(media_up-std_up,\n                     linestyle='dotted',color='blue')\n\n    etiq_down = str(np.round(media_down,precision))+' +\/- '\n    etiq_down = etiq_down + str(np.round(std_down,precision))\n    graf_pmf.plot(x_pmfdown,y_pmfdown,\n                  label='media_down '+etiq_down,\n                  color='brown')\n    graf_pmf.axvline(media_down,color='brown')\n    graf_pmf.axvline(media_down+std_down,\n                     linestyle='dotted',color='brown')\n    graf_pmf.axvline(media_down-std_down,\n                     linestyle='dotted',color='brown')\n\n    graf_pmf.set_title('pmf: '+grafData&#x5B;'codigopunto']+' '+medida)\n    graf_pmf.set_xlim(y_min,y_max)\n    graf_pmf.set_ylim(0,prob_max)\n    graf_pmf.set_xlabel(medida+' ('+medida_unidad+')')\n    graf_pmf.set_ylabel('frecuencia relativa')\n    graf_pmf.legend()\n    graf_pmf.grid(True,linestyle='dotted',\n                  axis='x', which='both')\n    return(fig_pmf)\n\ndef graf_puntos_std(tabla,descriptor,movAvgData,grafData):\n    ''' grafica serie de std usando medias moviles\n        para cada punto, media_std\n    '''\n    # ajuste de formato de fecha para eje x\n    converter = mdates.ConciseDateConverter()\n    munits.registry&#x5B;np.datetime64] = converter\n    munits.registry&#x5B;dt.date] = converter\n    munits.registry&#x5B;dt.datetime] = converter\n    \n    # datos para grafica\n    precision = grafData&#x5B;'precision']\n    medida    = grafData&#x5B;'medida']\n    medida_unidad = grafData&#x5B;'medida_unidad']\n\n    movAvg_cual = movAvgData&#x5B;'movAvg_cual']\n    movAvg_color = movAvgData&#x5B;'movAvg_color']\n\n    # selecciona sin error\n    condicion_up   = (tabla&#x5B;'error_up']==0)\n    condicion_down = (tabla&#x5B;'error_down']==0)\n    \n    # ajuste de intervalo eje y\n    y_min = 0\n    y_max = np.max(&#x5B;2, 2*descriptor&#x5B;medida+'_up']&#x5B;'std'],\n                    2*descriptor&#x5B;medida+'_down']&#x5B;'std']])\n    # grafica\n    fig_std,(graf_stdUp,graf_stdDown) = plt.subplots(2,1)\n    \n    # std up\n    std_up = np.round(descriptor&#x5B;medida+'_up']&#x5B;'std'],precision)\n    graf_stdUp.axhline(std_up,label='std '+str(std_up),\n                       color='blue')\n    m = len(movAvg_cual)\n    for j in range(0,m,1):\n        k = str(movAvg_cual&#x5B;j])\n        graf_stdUp.plot(tabla&#x5B;condicion_up]&#x5B;'publishedAt'],\n                        movAvgData&#x5B;'movAvg_up_std']&#x5B;j],\n                        label='movAvg_'+k,\n                        color=movAvg_color&#x5B;j])\n    graf_stdUp.set_ylim(y_min,y_max)\n    graf_stdUp.set_ylabel('std_up ('+medida_unidad+')',\n                          color='blue')\n    graf_stdUp.legend()\n    graf_stdUp.grid(True,linestyle='dotted',\n                    axis='x', which='both')\n    graf_stdUp.set_title('std: '+grafData&#x5B;'codigopunto']+' '+ medida)\n\n    # std down\n    std_down = np.round(descriptor&#x5B;medida+'_down']&#x5B;'std'],precision)\n    graf_stdDown.axhline(std_down,label='std '+str(std_down),\n                         color='brown')\n    for j in range(0,m,1):\n        k = str(movAvg_cual&#x5B;j])\n        graf_stdDown.plot(tabla&#x5B;condicion_down]&#x5B;'publishedAt'],\n                          movAvgData&#x5B;'movAvg_down_std']&#x5B;j],\n                          label='movAvg_'+k,color=movAvg_color&#x5B;j])\n    graf_stdDown.set_ylim(y_min,y_max)\n    graf_stdDown.set_xlabel('fecha')\n    graf_stdDown.set_ylabel('std_down ('+medida_unidad+')',\n                            color='brown')\n    graf_stdDown.legend()\n    graf_stdDown.grid(True,linestyle='dotted',\n                      axis='x', which='both')\n    plt.tight_layout()\n    return(fig_std)\n\n\ndef linealiza_lstsq(xi,yi,digitos = 3):\n    ''' usa minimos cuadrados para entregar la ecuacion\n        digitos: usados en expresion latex\n    '''\n    unaecuacion = {}\n    # Eje x en log10()\n    xilog = np.log10(xi)\n    n = len(xi)\n    \n    # m\u00ednimos cuadrados (least square),\n    # distancia vs medida\n    A = np.vstack(&#x5B;xilog, np.ones(n)]).T\n    &#x5B;m0, b0] = np.linalg.lstsq(A, yi, rcond=None)&#x5B;0]\n    alpha = -m0\/10\n    beta  = b0\n\n    # coeficiente de correlaci\u00f3n\n    coeficientes = np.corrcoef(xilog,yi)\n    r = coeficientes&#x5B;0,1]\n    # coeficiente de determinaci\u00f3n\n    r2 = r**2\n\n    # ecuaciones expresion rssi(d)\n    fdist0 = lambda d: -10*alpha*(np.log10(d))+beta\n    \n    fdtxt0 = r'$ rssi = -10(' + str(np.round(alpha,digitos))\n    fdtxt0 = fdtxt0 + ')log_{10}(d)' # +('\n    texto = '+'\n    if beta &lt;0:\n        texto = '-'\n    fdtxt0 = fdtxt0 + texto + str(np.round(np.abs(beta),digitos))+' \n\n\n    # Errores respecto a rssi(d) \n    yi0  = fdist0(xi)\n    dyi0 = yi - yi0\n    dyi0mean = np.mean(np.abs(dyi0))\n    dyi0std  = np.std(dyi0, dtype=np.float64)\n\n    # ecuaciones expresion d(rssi)\n    grssi0 = lambda rssi: 10**((beta-rssi)\/(10*alpha))\n    grtxt0 = r&quot;$ d = 10^{(&quot; + str(np.round(beta,digitos)) + ' - '\n    grtxt0 = grtxt0 + 'rssi)\/' + '(10('+str(np.round(alpha,digitos))+'))} \n\n\n    # Errores respecto a rssi(d) \n    xi0  = grssi0(yi)\n    dxi0 = xi - xi0\n    dxi0mean = np.mean(np.abs(dxi0))\n    dxi0std  = np.std(dxi0, dtype=np.float64)\n    \n    yimin = np.around(np.min(yi),2)\n    yimax = np.around(np.max(yi),2)\n    \n    unaecuacion = {'alpha'   : alpha,\n                   'beta'    : beta,\n                   'coef_correlacion'   : r,\n                   'coef_determinacion' : r2,\n                   'eq_latex': fdtxt0,\n                   'intervalox' : &#x5B;np.min(xi),np.max(xi)],\n                   'error_medio': dyi0mean,\n                   'error_std'  : dyi0std,\n                   'eqg_latex'  : grtxt0,\n                   'intervaloy' : &#x5B;yimin,yimax],\n                   'errorx_medio': dxi0mean,\n                   'errorx_std'  : dxi0std,\n                   }\n    return(unaecuacion)\n\ndef ecuacion_gradiente(carpeta_rsm,arch_coord,var_gen):\n    ''' desarrolla la ecuaci\u00f3n para un gradiente\n    '''\n    var_gen&#x5B;'movAvg_cual'] = &#x5B;2,4] #cada cuantas muestras\n    partes = carpeta_rsm.strip('\/').split('_')\n    arch_nombre = partes&#x5B;1]+'_'+partes&#x5B;2]\n\n    carp_coord = var_gen&#x5B;'carp_coord']\n    medida = var_gen&#x5B;'medida']\n    precision = var_gen&#x5B;'precision']\n    \n    # lee coordenadas y su distancia al gateway\n    dist_Gtw = coordenadas_leer(arch_coord,carp_coord)\n\n    # crea lista.txt de archivos a usar si no existe\n    arch_lista = medida+&quot;_&quot;+arch_nombre+&quot;_lista.txt&quot;\n    archivo_ruta  = carpeta_rsm + '\/' + arch_lista\n    archivoexiste = os.path.exists(archivo_ruta)\n    if not(archivoexiste):\n        puntoUsar = pd.DataFrame(columns=&#x5B;'punto', 'up', 'down'])\n        for unarchivo in os.listdir(carpeta_rsm):\n            verifica = unarchivo.startswith('describe_')\n            verifica = verifica and unarchivo.endswith('.csv')\n            if verifica:\n                partes  = unarchivo.strip('.csv').split('_')\n                unpunto = partes&#x5B;2]\n                puntoUsar = puntoUsar.append({'punto' : unpunto,\n                                              'up' : 1,\n                                              'down' : 1},\n                                             ignore_index = True)\n        puntoUsar = puntoUsar.set_index('punto')\n        puntoUsar.to_csv(archivo_ruta)\n\n    # usa lista.txt de archivos seleccionados 1 \u00f3 0 para enlace up,down\n    if (archivoexiste):\n        puntoUsar = pd.read_csv(archivo_ruta)\n        puntoUsar = puntoUsar.set_index('punto')\n      \n    # Datos para gr\u00e1fica desde lista.txt\n    punto_graf  = pd.DataFrame()\n    puntoSinDist = &#x5B;]\n    for unarchivo in os.listdir(carpeta_rsm):\n        if unarchivo.startswith('describe_'):\n            codigopunto = unarchivo.strip('.csv').split('_')&#x5B;2]\n            \n            # lectura del archivo\n            unresumen  = carpeta_rsm+'\/'+unarchivo\n            descriptor = pd.read_csv(unresumen,index_col='Unnamed: 0')\n\n            if (codigopunto in dist_Gtw.index):\n                undato = {'codigopunto': codigopunto,\n                          'dist_Gtw'   : dist_Gtw&#x5B;codigopunto],\n                          medida+'_up' : descriptor&#x5B;'rssi_up']&#x5B;'mean'],\n                          medida+'_up'+'_std': descriptor&#x5B;'rssi_up']&#x5B;'std'],\n                          'usar_up' : puntoUsar&#x5B;'up']&#x5B;codigopunto],\n                          medida+'_down': descriptor&#x5B;'rssi_down']&#x5B;'mean'],\n                          medida+'_down'+'_std' :descriptor&#x5B;'rssi_down']&#x5B;'std'],\n                          'usar_down' : puntoUsar&#x5B;'down']&#x5B;codigopunto],\n                          'dispositivo': descriptor&#x5B;'dispositivo']&#x5B;0]\n                          }\n                punto_graf = punto_graf.append(undato,ignore_index=True)\n            else:\n                puntoSinDist.append(codigopunto)\n            \n    punto_graf = punto_graf.set_index('codigopunto')\n    punto_graf = punto_graf.sort_values('dist_Gtw' )\n\n    # selecciona datos\n    dist = punto_graf&#x5B;'dist_Gtw']\n    usar_up = punto_graf&#x5B;'usar_up']\n    usar_down = punto_graf&#x5B;'usar_down']\n\n    # Eje x en log10()\n    xi = np.array(dist)\n\n    # enlace_up\n    media_up = punto_graf&#x5B;medida+'_up']\n    std_up   = punto_graf&#x5B;medida+'_up'+'_std']\n    media_up_techo = media_up + std_up\n    media_up_piso  = media_up - std_up\n\n    # ecuacion enlace up\n    yi_up = np.array(media_up)\n    eq_up = linealiza_lstsq(xi&#x5B;usar_up==1],\n                            yi_up&#x5B;usar_up==1],\n                            digitos = precision)\n    alpha_up = eq_up&#x5B;'alpha']\n    beta_up  = eq_up&#x5B;'beta']\n    fd_up = lambda d: -10*alpha_up*(np.log10(d))+beta_up\n\n    # errores up de puntos vs ecuacion\n    fi_up = fd_up(xi)\n    dyi0std  = eq_up&#x5B;'error_std']\n    punto_graf&#x5B;'fi_up'] = fi_up\n\n    # enlace_down\n    media_down = punto_graf&#x5B;medida+'_down']\n    std_down   = punto_graf&#x5B;medida+'_down'+'_std']\n    media_down_techo = media_down + std_down\n    media_down_piso  = media_down - std_down\n\n    # ecuaci\u00f3n Enlace down\n    yi_down = np.array(media_down)\n    eq_down = linealiza_lstsq(xi&#x5B;usar_down==1],\n                              yi_down&#x5B;usar_down==1],\n                              digitos = precision)\n    alpha_down = eq_down&#x5B;'alpha']\n    beta_down  = eq_down&#x5B;'beta']\n    fd_down = lambda d: -10*alpha_down*(np.log10(d))+beta_down\n\n    # errores down de puntos vs ecuacion\n    fi_down = fd_down(xi)\n    dyi1std = eq_down&#x5B;'error_std']\n    punto_graf&#x5B;'fi_down'] = fi_down\n\n    resultado = {'tabla'         : punto_graf,\n                 'ecuacion_up'   : eq_up,\n                 'ecuacion_down' : eq_down,\n                 'puntoSinDist'  : puntoSinDist}\n    \n    return (resultado)\n\ndef coordenadas_leer(arch_coord,carp_coord):\n    ''' lista las coordenadas desde un archivo\n        ubicado en la carpeta\n    '''\n    if len(carp_coord)&gt;0:\n        carp_coord = carp_coord+'\/'\n    archivo_ruta = carp_coord+arch_coord\n    arch_coord_existe = os.path.exists(archivo_ruta)\n\n    if arch_coord_existe:\n        puntos = pd.read_csv(archivo_ruta,index_col='punto')\n        # busca gateway y ubicaci\u00f3n de punto observado\n        Gw_nombre = ''\n        for unpunto in puntos.index:\n            if unpunto.startswith('Gw'):\n                Gw_nombre = unpunto\n        dist_Gtw = puntos&#x5B;'dist_'+Gw_nombre]   \n    else:\n        print(' ERROR: NO se encuentra el archivo...')\n        print('        revise el ruta\/nombre de archivo. ')\n    return(dist_Gtw)\n\ndef graf_gradiente(arch_nombre,punto_graf,ecuacion,var_gen):\n    ''' grafica de un gradiente\n    '''\n    escalabase = 10    # 10\n    escala = 'log'\n    medida = var_gen&#x5B;'medida']\n    precision = var_gen&#x5B;'precision']\n\n    # enlace_up\n    media_up = punto_graf&#x5B;medida+'_up']\n    std_up   = punto_graf&#x5B;medida+'_up'+'_std']\n    media_up_techo = media_up + std_up\n    media_up_piso  = media_up - std_up\n    yi_up = np.array(media_up)\n    fi_up = punto_graf&#x5B;'fi_up']\n\n    # enlace_down\n    media_down = punto_graf&#x5B;medida+'_down']\n    std_down   = punto_graf&#x5B;medida+'_down'+'_std']\n    media_down_techo = media_down + std_down\n    media_down_piso  = media_down - std_down\n    yi_down = np.array(media_down)\n    fi_down = punto_graf&#x5B;'fi_down']\n\n    dist = punto_graf&#x5B;'dist_Gtw']\n    usar_up = punto_graf&#x5B;'usar_up']\n    usar_down = punto_graf&#x5B;'usar_down']\n\n    eq_up = ecuacion&#x5B;'ecuacion_up']\n    eq_down = ecuacion&#x5B;'ecuacion_down']\n\n    dyi0std = eq_up&#x5B;'error_std']\n    dyi1std = eq_down&#x5B;'error_std']\n\n    fig_gradnt,(graf_up,graf_down) = plt.subplots(2,1)\n    if escala == 'log':\n        graf_up.set_xscale(escala,base=escalabase)\n        graf_down.set_xscale(escala,base=escalabase)\n\n    # medida up +\/- std\n    graf_up.scatter(dist,media_up,color='blue',marker='o')\n    graf_up.scatter(dist,media_up_techo,color='blue',marker='+')\n    graf_up.scatter(dist,media_up_piso,color='blue',marker='+')\n\n    # medida down +\/- std\n    graf_down.scatter(dist,media_down,color='orange',marker='o')\n    graf_down.scatter(dist,media_down_techo,color='orange',marker='+')\n    graf_down.scatter(dist,media_down_piso,color='orange',marker='+')\n\n    # linealizado up\n    graf_up.plot(dist,fi_up,label = '  up:'+eq_up&#x5B;'eq_latex'],\n                 color='blue')\n    graf_up.plot(dist,fi_up+dyi0std,\n                 color='blue',linestyle='dotted')\n    graf_up.plot(dist,fi_up-dyi0std,\n                 color='blue',linestyle='dotted')\n    # linealizado down\n    graf_down.plot(dist,fi_down,label = 'down:'+eq_down&#x5B;'eq_latex'],\n                   color='orange')\n    graf_down.plot(dist,fi_down+dyi1std,\n                   color='orange',linestyle='dotted')\n    graf_down.plot(dist,fi_down-dyi1std,\n                   color='orange',linestyle='dotted')\n\n    # ajuste de eje y\n    y_min = np.min(&#x5B;np.min(media_up_piso),np.min(media_down_piso)])\n    y_max = np.max(&#x5B;np.max(yi_up+dyi0std),np.max(yi_down+dyi1std)])\n    if y_min&lt;-135:\n        y_min = np.min(&#x5B;np.min(&#x5B;media_up]),np.min(&#x5B;media_down])])\n    graf_up.set_ylim(y_min,y_max)\n    graf_down.set_ylim(y_min,y_max)\n\n    # etiquetas up\n    for unpunto in punto_graf.index:\n        media_etiq = np.round(punto_graf&#x5B;medida+'_up']&#x5B;unpunto],precision)\n        usarpunto  = punto_graf&#x5B;'usar_up']&#x5B;unpunto]\n        \n        etiqueta = unpunto #+str(media_etiq)\n        xi = punto_graf&#x5B;'dist_Gtw']&#x5B;unpunto]\n        yi = punto_graf&#x5B;'rssi_up']&#x5B;unpunto]\n        if usarpunto:\n            graf_up.annotate(etiqueta,(xi,yi), rotation=45)\n        if not(usarpunto):\n            graf_up.annotate(etiqueta,(xi,yi), rotation=45,color='red')\n            graf_up.scatter(dist&#x5B;unpunto],media_up&#x5B;unpunto],color='red',marker='o')\n            graf_up.scatter(dist&#x5B;unpunto],media_up_techo&#x5B;unpunto],\n                            color='red',marker='+')\n\n    # etiquetas down\n    for unpunto in punto_graf.index:\n        media_etiq = np.round(punto_graf&#x5B;medida+'_down']&#x5B;unpunto],precision)\n        usarpunto = punto_graf&#x5B;'usar_down']&#x5B;unpunto]\n        etiqueta = unpunto #+str(media_etiq)\n        xi = punto_graf&#x5B;'dist_Gtw']&#x5B;unpunto]\n        yi = punto_graf&#x5B;'rssi_down']&#x5B;unpunto]\n        if usarpunto:\n            graf_down.annotate(etiqueta,(xi,yi), rotation=45)\n        if not(usarpunto):\n            graf_down.annotate(etiqueta,(xi,yi), rotation=45,color='red')\n            graf_down.scatter(dist&#x5B;unpunto],media_down&#x5B;unpunto],color='red',marker='o')\n            graf_down.scatter(dist&#x5B;unpunto],media_down_techo&#x5B;unpunto],\n                              color='red',marker='+')\n\n    graf_up.set_ylabel(medida+'_up (dBm)',color='blue')\n    graf_up.set_title(arch_nombre+' '+medida)\n    graf_up.legend()\n    graf_up.grid(True,linestyle='dotted',\n                 axis='x', which='both')\n\n    graf_down.set_xlabel('distancia')\n    graf_down.set_ylabel(medida+'_down (dBm)',color='brown')\n    graf_down.legend()\n    graf_down.grid(True,linestyle='dotted',\n                   axis='x', which='both')\n    return(fig_gradnt)\n\ndef graf_diferencia_updown(arch_nombre,punto_graf,var_gen):\n    '''Grafica de diferencias up-down\n    '''\n    medida = var_gen&#x5B;'medida']\n    medida_unidad = var_gen&#x5B;'medida_unidad']\n    movAvg_cual = var_gen&#x5B;'movAvg_cual']\n    movAvg_color = var_gen&#x5B;'movAvg_color']\n    precision = var_gen&#x5B;'precision']\n\n    # analiza diferencias de medias y std --------------\n    punto_graf&#x5B;'usar_dif'] = punto_graf&#x5B;'usar_up']*punto_graf&#x5B;'usar_down']\n    usar_dif = punto_graf&#x5B;'usar_dif']\n    punto_graf&#x5B;'dif_mean'] = punto_graf&#x5B;'rssi_up']-punto_graf&#x5B;'rssi_down']\n    punto_graf&#x5B;'dif_std']  = punto_graf&#x5B;medida+'_up_std']-punto_graf&#x5B;medida+'_down_std']\n    punto_graf&#x5B;'dif_top']  = punto_graf&#x5B;'dif_mean']+punto_graf&#x5B;'dif_std']\n    punto_graf&#x5B;'dif_bottom'] = punto_graf&#x5B;'dif_mean']-punto_graf&#x5B;'dif_std']\n\n    dist = punto_graf&#x5B;'dist_Gtw']\n    usar_dif = punto_graf&#x5B;'usar_dif']\n\n    # linealiza diferencia\n    xi_dif = np.array(punto_graf&#x5B;'dist_Gtw']&#x5B;usar_dif==1])\n    yi_dif = np.array(punto_graf&#x5B;'dif_mean']&#x5B;usar_dif==1])\n    eq_dif = linealiza_lstsq(xi_dif,yi_dif,digitos = precision)\n    alpha_dif = eq_dif&#x5B;'alpha']\n    beta_dif  = eq_dif&#x5B;'beta']\n    fdistdif0 = lambda d: -10*alpha_dif*(np.log10(d))+beta_dif\n    yi_dif0   = fdistdif0(xi_dif)\n\n    ecua_dif = pd.DataFrame(eq_dif)\n\n    # medias moviles en movAvg_cual&#x5B;]\n    serie_media  = pd.Series(punto_graf&#x5B;'dif_mean']&#x5B;usar_dif==1])\n    movAvg_dmedia = &#x5B;]\n    m = len(movAvg_cual)\n    for j in range(0,m,1):\n        k = movAvg_cual&#x5B;j]\n        movAvg_dmedia.append(serie_media.rolling(k).mean())\n\n    # Grafica diferencia\n    escalabase = 10    # 10\n    escala = 'log'\n    \n    fig_dif_updown,graf_dmean = plt.subplots()\n    if escala == 'log':\n        graf_dmean.set_xscale(escala,base=escalabase)\n\n    # diferencia medida up - down\n    graf_dmean.scatter(dist,punto_graf&#x5B;'dif_mean'],color='purple',marker='o')\n    graf_dmean.plot(xi_dif,yi_dif0,label = '  dif:'+eq_dif&#x5B;'eq_latex'],color='blue')\n    graf_dmean.set_ylabel('media Up-Down (dBm)')\n\n    # medida_up, medias m\u00f3viles\n    for j in range(0,m,1):\n        k = str(movAvg_cual&#x5B;j])\n        graf_dmean.plot(dist&#x5B;usar_dif==1],movAvg_dmedia&#x5B;j],\n                      label='movAvg_dmedia_'+k,color=movAvg_color&#x5B;j])\n\n    # etiquetas\n    i=0\n    for unpunto in punto_graf.index:\n        media_etiq = np.round(punto_graf&#x5B;medida+'_up']&#x5B;unpunto],precision)\n        etiqueta = unpunto # + ' ' +str(media_etiq)\n        usar_dif = punto_graf&#x5B;'usar_dif']&#x5B;unpunto]\n        xi = punto_graf&#x5B;'dist_Gtw']&#x5B;unpunto]\n        yi = punto_graf.iloc&#x5B;i]&#x5B;'dif_mean']\n        i = i+1\n        if usar_dif:\n            graf_dmean.annotate(etiqueta,(xi,yi), rotation=30)\n        if not(usar_dif):\n            graf_dmean.annotate(etiqueta,(xi,yi),color='red',rotation=30)\n            graf_dmean.scatter(xi,yi,color='red',marker='o')\n\n    graf_dmean.axhline(0,color='grey')\n    graf_dmean.grid(True,linestyle='dotted',axis='x', which='both')\n\n    graf_dmean.legend()\n    graf_dmean.set_title(arch_nombre+': '+medida+' media Up-Down')\n    return(fig_dif_updown)\n\ndef graf_gradiente_std(arch_nombre,punto_graf,medida,precision):\n    ''' Grafica de std_up y std_down ------\n    '''\n    xi_std      = np.array(punto_graf&#x5B;'dist_Gtw'])\n    yi_std_up   = np.array(punto_graf&#x5B;medida+'_up_std'])\n    yi_std_down = np.array(punto_graf&#x5B;medida+'_down_std'])\n\n    # linealiza std\n    usar_up   = punto_graf&#x5B;'usar_up']\n    usar_down = punto_graf&#x5B;'usar_down']\n\n    eq_std_up = linealiza_lstsq(xi_std&#x5B;usar_up==1],\n                                      yi_std_up&#x5B;usar_up==1],\n                                      digitos = precision)\n    alpha_std_up = eq_std_up&#x5B;'alpha']\n    beta_std_up  = eq_std_up&#x5B;'beta']\n    fdiststd_up0 = lambda d: -10*alpha_std_up*(np.log10(d))+beta_std_up\n    yi_std_up0   = fdiststd_up0(xi_std)\n\n    eq_std_down = linealiza_lstsq(xi_std&#x5B;usar_down==1],\n                                        yi_std_down&#x5B;usar_down==1],\n                                        digitos = precision)\n    alpha_std_down = eq_std_down&#x5B;'alpha']\n    beta_std_down  = eq_std_down&#x5B;'beta']\n    fdiststd_down0 = lambda d: -10*alpha_std_down*(np.log10(d))+beta_std_down\n    yi_std_down0   = fdiststd_down0(xi_std)\n\n    # grafica std\n    escalabase = 10    # 10\n    escala = 'log'\n    \n    fig_grad_std,(graf_std_up,graf_std_down) = plt.subplots(2,1)\n    if escala == 'log':\n        graf_std_up.set_xscale(escala,base=escalabase)\n        graf_std_down.set_xscale(escala,base=escalabase)\n\n    graf_std_up.plot(xi_std,yi_std_up0,\n                     label = '  std_up:'+eq_std_up&#x5B;'eq_latex'],\n                     color='blue')\n        \n    # medida up +\/- std\n    graf_std_up.scatter(xi_std,yi_std_up,color='blue',marker='+')\n    graf_std_down.scatter(xi_std,yi_std_down,color='orange',marker='+')\n\n    # etiquetas\n    i=0\n    for unpunto in punto_graf.index:\n        media_etiq = np.round(punto_graf&#x5B;medida+'_up']&#x5B;unpunto],precision)\n        etiqueta   = unpunto # + ' ' +str(media_etiq)\n        usar_up    = punto_graf&#x5B;'usar_up']&#x5B;unpunto]\n        usar_down  = punto_graf&#x5B;'usar_down']&#x5B;unpunto]\n        xi  = punto_graf&#x5B;'dist_Gtw']&#x5B;unpunto]\n        yiu = punto_graf.iloc&#x5B;i]&#x5B;medida+'_up_std']\n        yid = punto_graf.iloc&#x5B;i]&#x5B;medida+'_down_std']\n        i = i+1\n        if usar_up:\n            graf_std_up.annotate(etiqueta,(xi,yiu), rotation=30)\n        if not(usar_up):\n            graf_std_up.annotate(etiqueta,(xi,yiu),color='red',rotation=30)\n            graf_std_up.scatter(xi,yiu,color='red',marker='o')\n        if usar_down:\n            graf_std_down.annotate(etiqueta,(xi,yid), rotation=30)\n        if not(usar_down):\n            graf_std_down.annotate(etiqueta,(xi,yid),color='red',rotation=30)\n            graf_std_down.scatter(xi,yid,color='red',marker='o')\n\n    graf_std_down.plot(xi_std,yi_std_down0,\n                    label = 'std_down:'+eq_std_down&#x5B;'eq_latex'],\n                    color='orange')\n    # otras etiquetas\n    graf_std_up.set_ylabel('std_up (dBm)', color='blue')\n    graf_std_up.set_xlabel('distancia')\n    graf_std_up.axhline(0,color='grey')\n    graf_std_up.grid(True,linestyle='dotted',\n                    axis='x', which='both')\n    graf_std_up.set_title(arch_nombre+': '+medida+' std')\n    graf_std_up.legend()\n\n    graf_std_down.set_ylabel('std_down (dBm)', color='brown')\n    graf_std_down.set_xlabel('distancia')\n    graf_std_down.axhline(0,color='grey')\n    graf_std_down.grid(True,linestyle='dotted',\n                    axis='x', which='both')\n    graf_std_down.legend()\n\n    return(fig_grad_std)\n\ndef coordenadas_kml_utm(archivo_ruta,zonaNum,zonaLetra,precision):\n    # Lectura de archivo\n    gpd.io.file.fiona.drvsupport.supported_drivers&#x5B;'KML'] = 'rw'\n    puntos  = gpd.read_file(archivo_ruta, driver='KML')\n    puntos&#x5B;'dist'] = 0\n\n    tabla = pd.DataFrame()\n    for i in puntos.index:\n        # en latitud, longitud y altura\n        punto_nombre = puntos.loc&#x5B;i]&#x5B;'Name']\n        longitud = puntos.loc&#x5B;i]&#x5B;'geometry'].x\n        latitud  = puntos.loc&#x5B;i]&#x5B;'geometry'].y\n        altitud  = puntos.loc&#x5B;i]&#x5B;'geometry'].z\n        altitud  = np.round(altitud,precision)\n        #en UTM\n        coord_utm  = utm.from_latlon(latitud,longitud,\n                                     zonaNum,zonaLetra)\n        utm_este  = np.round(coord_utm&#x5B;0],precision)\n        utm_norte = np.round(coord_utm&#x5B;1],precision)\n        \n        # distancias a Gateways\n        dist = 0.0\n        if punto_nombre.startswith('Gw'):\n            n_Gtw = punto_nombre\n            x1 = utm_este\n            y1 = utm_norte\n        else:\n            x2 = utm_este\n            y2 = utm_norte\n            dist  = np.sqrt((x2-x1)**2 + (y2-y1)**2)\n        dist = np.round(dist,precision)\n        \n        unpunto = {'punto'       : punto_nombre,\n                   'utm_este'    : utm_este,\n                   'utm_norte'   : utm_norte,\n                   'utm_zNum'    : int(zonaNum),\n                   'utm_zLetra'  : zonaLetra,\n                   'altitud'     : altitud,\n                   'altitud_gps' : altitud,\n                   'dist_'+n_Gtw : dist,\n                   'latitud'     : latitud,\n                   'longitud'    : longitud\n                   }\n        tabla = tabla.append(unpunto,ignore_index=True)\n    tabla = tabla.set_index('punto')\n    return(tabla)\n\ndef revisa_perfil(archivo_ruta,alturaGw,alturapunto,\n                  plantas,muestras=41,guarda=False):\n    LineaObs = archivo_ruta.strip('.csv').split('_')&#x5B;1]\n\n    planta_desde  = plantas&#x5B;0]\n    planta_hasta  = plantas&#x5B;1]\n    planta_altura = plantas&#x5B;2]\n\n    # lectura de datos\n    puntos = pd.read_csv(archivo_ruta,index_col='punto')\n\n    # busca gateway\n    n_Gtw = ''\n    for unpunto in puntos.index:\n        if unpunto.startswith('Gw'):\n            n_Gtw = unpunto\n\n    # perfil  \n    xi = np.array(puntos&#x5B;'dist_'+n_Gtw])\n    yi = np.array(puntos&#x5B;'altitud'])\n    etiqueta = puntos.index\n\n    # plantaciones\n    conplantas = (xi &gt; planta_desde) &amp; (xi &lt; planta_hasta)\n    plantacion = yi&#x5B;conplantas]+planta_altura\n\n    # GRAFICA\n    # plantacion\n    plt.fill_between(xi&#x5B;conplantas],\n                     yi&#x5B;conplantas],\n                     plantacion,\n                     color='lightgreen')\n    # perfil\n    xi = puntos&#x5B;'dist_'+n_Gtw]\n    yi = puntos&#x5B;'altitud']\n    plt.plot(xi,yi,color='brown')\n        \n    # antenas\n    for unpunto in puntos.index:\n        xip = xi&#x5B;unpunto]\n        yip = yi&#x5B;unpunto]\n        if unpunto.startswith('Gw'):\n            xigtw = xip\n            yigtw = yip+alturaGw\n            plt.scatter(xip ,yigtw)\n            plt.annotate(unpunto,(xigtw,yigtw))\n        else:\n            xid = xip\n            yid = yip+alturapunto\n            plt.plot((xigtw,xid),(yigtw,yid),\n                     color = 'green',\n                     linestyle='dotted')\n            plt.scatter(xid ,yid)\n            plt.annotate(unpunto,(xid,yid), rotation=45)\n    plt.title('Linea :'+LineaObs)\n    plt.xlabel('distancia')\n    plt.ylabel('altura')\n    plt.grid()\n\n    # plt.axis('equal')   \n    return(puntos)\n\ndef revisa_fresnel(analiza_punto, archivo_ruta,alturaGw,alturapunto,\n                  plantas,guarda=False,nFres =1,freq=915,muestras=41):\n    LineaObs = archivo_ruta.strip('.csv').split('_')&#x5B;1]\n\n    planta_desde  = plantas&#x5B;0]\n    planta_hasta  = plantas&#x5B;1]\n    planta_altura = plantas&#x5B;2]\n\n    # lambda Fresnel\n    lamb = 300\/freq #300e6(m\/s)\/(freq*1e6)\n    puntos = pd.read_csv(archivo_ruta,index_col='punto')\n\n    # busca gateway\n    i_Gw    = 0\n    i_punto = 0\n    n_Gtw = ''\n    i = 0\n    for unpunto in puntos.index:\n        if unpunto.startswith('Gw'):\n            n_Gtw = unpunto\n        if unpunto==analiza_punto:\n            i_punto = i\n        i = i+1\n\n    # perfil   \n    xi = np.array(puntos&#x5B;'dist_'+n_Gtw])\n    yi = np.array(puntos&#x5B;'altitud'])\n    etiqueta = puntos.index\n\n    # plantaciones\n    conplantas = (xi &gt; planta_desde) &amp; (xi &lt; planta_hasta)\n    plantacion = yi&#x5B;conplantas]+planta_altura\n\n    # a\u00f1ade alturas de antenas\n    yi_ant = np.copy(yi) + alturapunto\n    yi_ant&#x5B;i_Gw] = yi&#x5B;i_Gw] + alturaGw\n\n    # Zona de Fresnel\n    if i_punto&gt;0:\n        \n        # linea directa\n        dy = yi_ant&#x5B;i_punto]-yi_ant&#x5B;i_Gw]\n        dx = xi&#x5B;i_punto]-xi&#x5B;i_Gw]\n        m = dy\/dx\n        alpha = np.arctan(m)\n        yi_f = lambda x: m*x + yi_ant&#x5B;i_Gw]\n\n        xi_D = np.linspace(xi&#x5B;i_Gw],xi&#x5B;i_punto],\n                           muestras)\n        yi_D = yi_f(xi_D)\n        dist_D = np.sqrt(dx**2+dy**2)\n\n        # zona Fresnel 1\n        F1_up = np.zeros(len(xi_D))\n        F1_down = np.zeros(len(xi_D))\n        for i in range(0,len(xi_D),1):\n            d1 = xi_D&#x5B;i]\/np.cos(alpha)\n            d2 = dist_D-d1\n            F1 = np.sqrt(np.abs(nFres*lamb*d1*d2)\/(d1+d2))\n\n            xiu = xi_D&#x5B;i]-F1*np.sin(np.abs(alpha))\n            d1_u = xiu\n            d2_u = dist_D-d1_u\n\n            xid = xi_D&#x5B;i]+F1*np.sin(np.abs(alpha))\n            d1_d = xid\n            d2_d = dist_D-d1_d\n            # Fresnel, formula\n            Fup = np.sqrt(np.abs(nFres*lamb*d1_u*d2_u)\/(d1_u+d2_u))\n            Fdown = np.sqrt(np.abs(nFres*lamb*d1_d*d2_d)\/(d1_d+d2_d))\n            \n            # Linea directa +\/- Fresnel\n            F1_up&#x5B;i]   = yi_D&#x5B;i] + Fup*np.cos(alpha)\n            F1_down&#x5B;i] = yi_D&#x5B;i] - Fdown*np.cos(alpha)\n    else:\n        print('punto no encontrado',analiza_punto)\n\n    # SALIDA\n    # print('Radio Fresnel: ',np.max(F1u&#x5B;i]))\n\n    # GRAFICA\n    plt.fill_between(xi&#x5B;conplantas],yi&#x5B;conplantas],\n                     plantacion,color='lightgreen',\n                     label = 'plantas')\n    plt.plot(xi,yi,label='perfil', color = &quot;brown&quot;)\n    # antenas\n    plt.scatter(xi,yi_ant,label=\n                'Dispositivos',color='blue')\n    if i_punto&gt;0:\n        # Fresnel\n        plt.plot(xi_D,yi_D,\n                 label='Directo',color='orange',\n                 linestyle = 'dashed')\n        plt.plot(xi_D,F1_down,\n                 label='Fresnel1',color='orange')\n        plt.plot(xi_D,F1_up,\n                 color='orange')\n        \n    for i in range(0,len(xi),1):\n        plt.annotate(etiqueta&#x5B;i],\n                     (xi&#x5B;i],yi_ant&#x5B;i]),rotation=45)\n    plt.xlabel('distancia')\n    plt.ylabel('altura')\n    plt.title('L\u00ednea :'+LineaObs+', Enlace: '+n_Gtw+'-'+etiqueta&#x5B;i_punto])\n    plt.legend()\n    plt.grid()\n    # plt.axis('equal')\n    # plt.show()\n    return(puntos)\n<\/pre><\/div>","protected":false},"excerpt":{"rendered":"<p>El archivo contiene un grupo de&nbsp; funciones usadas para procesar los datos de este prototipo, se separaron del bloque principal de instrucciones con&nbsp; el objetivo de simplificar el desarrollo del las actividades principales. Recuerde disponer de este archivo en la misma carpeta que el algoritmo que invoca a la librer\u00eda. archivo de librer\u00eda: girni_lorawan_libreria Instrucciones [&hellip;]<\/p>\n","protected":false},"author":8043,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1466681],"tags":[],"class_list":["post-3895","post","type-post","status-publish","format-standard","hentry","category-lorawan-propagacion"],"_links":{"self":[{"href":"https:\/\/blog.espol.edu.ec\/girni\/wp-json\/wp\/v2\/posts\/3895","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/blog.espol.edu.ec\/girni\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blog.espol.edu.ec\/girni\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blog.espol.edu.ec\/girni\/wp-json\/wp\/v2\/users\/8043"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.espol.edu.ec\/girni\/wp-json\/wp\/v2\/comments?post=3895"}],"version-history":[{"count":12,"href":"https:\/\/blog.espol.edu.ec\/girni\/wp-json\/wp\/v2\/posts\/3895\/revisions"}],"predecessor-version":[{"id":4784,"href":"https:\/\/blog.espol.edu.ec\/girni\/wp-json\/wp\/v2\/posts\/3895\/revisions\/4784"}],"wp:attachment":[{"href":"https:\/\/blog.espol.edu.ec\/girni\/wp-json\/wp\/v2\/media?parent=3895"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.espol.edu.ec\/girni\/wp-json\/wp\/v2\/categories?post=3895"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.espol.edu.ec\/girni\/wp-json\/wp\/v2\/tags?post=3895"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}