5. LoRaWan – Linealiza un intervalo

Referencia: Chapra 17.1 p 466. Burden 8.1 p498, Mínimos cuadrados en Métodos numéricos

Las descripciones estadísticas de Rssi obtenidas en cada punto sobre una línea de propagación se usan para estimar el modelo de propagación para esa ruta.

La ecuación empírica con la que se realiza la primera estimación se modela como:

RSSI(d) = -10 \alpha \log_{10} (d) + P_{0} 1<d<L

La ruta de ejemplo sigue la dirección desde el gateway (Gw03) hacia una parcela de plantación de maiz (MA##) en la parte superior izquierda de la imagen. se añade la primera sección (M0##)  para cubrir todo el segmento de propagación desde el gateway.

La imagen presentada representa la ruta c_MA, la letra «c» identifica el modelo de dispositivo usado (c: cápsula, m: módulo)

Los valores de Rssi_media en cada punto, tanto los enlaces de subida (up) y bajada (down), se linealizan por el método de los mínimos cuadrados usando la distancia como variable independiente.

En cada punto Rssi se añaden las marcas ‘+’ que representan media+std y media-std.

Mejorando el modelo

Las perdidas de señal desde el gateway aumentan con la distancia, siendo más grandes al final del segmento para el canal de bajada (down), mostrando una mayor desviación estándar (std) que afectan al modelo. Para discriminar los puntos que no representan una buena cobertura, se utiliza una gráfica de desviaciones estándar, donde los valores fuera de rango no se usan en el modelo.

La selección de los puntos que incluyen en el modelo se realiza en el archivo «rssi_c_MA_lista.txt»

punto,up,down
M001,1,1
M002,1,1
M003,1,1
M004,1,1
M005,1,1
M006,1,1
M007,1,1
MA03,1,0
MA04,1,1
MA05,1,1
MA06,1,1
MA07,1,1
MA08,1,0
MA09,1,0
MA10,1,0
Ref01,1,1

En el archivo se muestra que los puntos MA03, MA08, MA09, MA10 no se usan para el enlace de bajada (down).

Se guarda el archivo de selección con la configuración, y se vuelve a ejecutar el algoritmo, y se obtiene el modelo mejorado de pérdidas de propagación:

 ecuaciones: 
                                        ecuacion_up                             ecuacion_down
alpha                                         3.01                                      2.58
beta                                        -21.37                                    -25.98
coef_correlacion                             -0.94                                     -0.93
coef_determinacion                            0.88                                      0.86
eq_latex     $ rssi = -10(3.01)log_{10}(d)-21.37 $     $ rssi = -10(2.58)log_{10}(d)-25.98 $
intervalox                           [1.0, 233.86]                             [1.0, 198.31]
error_medio                                   5.82                                      5.64
error_std                                     6.63                                      6.46
eqg_latex  $ d = 10^{(-21.37 - rssi)/(10(3.01))} $   $ d = 10^{(-25.98 - rssi)/(10(2.58))} $
intervaloy                        [-97.87, -25.75]                          [-87.68, -26.99]
errorx_medio                                 43.32                                     37.68
errorx_std                                   56.01                                     47.11

Una forma complementaria para observar los puntos «aberrantes» o fuera de rango es observar en cada punto la diferencia entre las medias del enlace de subida y el de bajada, donde se destaca que los valores se encuentran muy separados.

Las gráficas se realizan en bloques como funciones (def), a fin de activarlas o no durante el análisis detallado, además de incorporarlas a la librería girni_lorawan_lib.py

Las rutas posibles para este ejercicio se dan por medio de «carpeta_rsm», que es el directorio donde se encuentran los archivos con los detalles de cada punto.


Instrucciones en Python

Algunos parámetros se repiten entre algoritmos, por lo que se los ha separado en un archivo de texto ‘variables_generales.txt’.

El contenido de las ‘variables_generales.txt’ se muestra a continuación:

{"carpeta_DB"  : "BaseDatosJSON",
 "medida"         : "rssi",
 "medida_unidad"  : "dBm",
 "medida_normal"  : [-250,-1],
 "medida_grafica" : [-100,-60],
 "movAvg_cual"    : [8,16],
 "movAvg_color"   : ["lightgreen","orange"],
 "precision"  : 2,
 "gatewayDB"  : {"uCfr//5zvhk=":"Gw01",
                 "uCfr//4dylc=":"Gw03"},
 "arch_coord" : "coord_puntos.csv",
 "carp_coord" : "coordenadas",
 "zonaNum"    : 17,
 "zonaLetra"  : "M",
 "alturaGw"   : 8,
 "alturapunto": 1,
 "nFres"      : 1,
 "freq"       : 915,
 "muestras"   : 41,
 "guarda"     : 1
}

Con lo que las instrucciones en Python quedan como:

# Obtiene ecuación por mínimos cuadrados de una ruta
# usando las medidas y distancia al gateway de cada punto
# http://blog.espol.edu.ec/girni/

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

# INGRESO
carpeta_rsm = "resultado_c_Maiz_todo"
arch_coord  = "coord_puntos.csv"
arch_var_general = "variables_generales.txt"

# PROCEDIMIENTO
# carga variables desde archivos
with open(arch_var_general) as linea:
    texto = linea.read()
var_gen = json.loads(texto)
globals().update(var_gen)

var_gen['movAvg_cual'] = [2,4] #cada cuantas muestras

partes = carpeta_rsm.strip('/').split('_')
arch_nombre = partes[1]+'_'+partes[2]

def coordenadas_leer(arch_coord,carp_coord):
    ''' lista las coordenadas desde un archivo
        ubicado en la carpeta
    '''
    if len(carp_coord)>0:
        carp_coord = carp_coord+'/'
    archivo_ruta = carp_coord+arch_coord
    arch_coord_existe = os.path.exists(archivo_ruta)

    if arch_coord_existe:
        puntos = pd.read_csv(archivo_ruta,index_col='punto')
        # busca gateway y ubicación de punto observado
        Gw_nombre = ''
        for unpunto in puntos.index:
            if unpunto.startswith('Gw'):
                Gw_nombre = unpunto
        dist_Gtw = puntos['dist_'+Gw_nombre]   
    else:
        print(' ERROR: NO se encuentra el archivo...')
        print('        revise el ruta/nombre de archivo. ')
    return(dist_Gtw)

dist_Gtw = coordenadas_leer(arch_coord,carp_coord)

# crea lista archivos a usar si no existe
arch_lista = medida+"_"+arch_nombre+"_lista.txt"
archivo_ruta  = carpeta_rsm + '/' + arch_lista
archivoexiste = os.path.exists(archivo_ruta)
if not(archivoexiste):
    puntoUsar_Colum = ['punto', 'up', 'down'] 
    puntoUsar_Tipos = {'punto' : 'object',
                       'up'   : 'int64',
                       'down' : 'int64'}
    puntoUsar = pd.DataFrame(columns = puntoUsar_Colum)
    puntoUsar = puntoUsar.astype(dtype = puntoUsar_Tipos)
    for unarchivo in os.listdir(carpeta_rsm):
        verifica = unarchivo.startswith('describe_')
        verifica = verifica and unarchivo.endswith('.csv')
        if verifica:
            partes  = unarchivo.strip('.csv').split('_')
            unpunto = partes[2]
            puntodato = {'punto' : unpunto,
                         'up' : 1,
                         'down' : 1}
            puntodato = pd.DataFrame([puntodato])
            puntoUsar = pd.concat([puntoUsar,
                                   puntodato],
                                  ignore_index = True)
    puntoUsar = puntoUsar.set_index('punto')
    puntoUsar.to_csv(archivo_ruta)

if (archivoexiste):
    puntoUsar = pd.read_csv(archivo_ruta)
    puntoUsar = puntoUsar.set_index('punto')
  
# Analiza cada punto en lista
punto_columnas = ['codigopunto','dist_Gtw',
                  medida+'_up',medida+'_up'+'_std',
                  'usar_up',medida+'_down',
                  medida+'_down'+'_std',
                  'usar_down','dispositivo']
punto_tipos = {'codigopunto': 'object',
               'dist_Gtw'   : 'float64',
               medida+'_up' : 'float64',
               medida+'_up'+'_std': 'float64',
               'usar_up' : 'int64',
               medida+'_down': 'float64',
               medida+'_down'+'_std' :'float64',
               'usar_down' : 'int64',
               'dispositivo': 'object'}
punto_graf = pd.DataFrame(columns=punto_columnas)
punto_graf = punto_graf.astype(dtype=punto_tipos)
puntoSinDist =[]
for unarchivo in os.listdir(carpeta_rsm):
    if unarchivo.startswith('describe_'):
        codigopunto = unarchivo.strip('.csv').split('_')[2]
        
        # lectura del archivo
        unresumen  = carpeta_rsm+'/'+unarchivo
        descriptor = pd.read_csv(unresumen,index_col='Unnamed: 0')

        # Para Grafica
        condicion = (codigopunto in dist_Gtw.index)
        if condicion:
            undato = {'codigopunto': codigopunto,
                      'dist_Gtw'   : dist_Gtw[codigopunto],
                      medida+'_up' : descriptor['rssi_up']['mean'],
                      medida+'_up'+'_std': descriptor['rssi_up']['std'],
                      'usar_up' : puntoUsar['up'][codigopunto],
                      medida+'_down': descriptor['rssi_down']['mean'],
                      medida+'_down'+'_std' :descriptor['rssi_down']['std'],
                      'usar_down' : puntoUsar['down'][codigopunto],
                      'dispositivo': descriptor['dispositivo'][0]
                      }
            undato = pd.DataFrame([undato])
            punto_graf = pd.concat([punto_graf,undato],
                                   ignore_index=True)
        else:
            puntoSinDist.append(codigopunto)
punto_graf = punto_graf.set_index('codigopunto')
punto_graf = punto_graf.sort_values('dist_Gtw' )

# selecciona datos
dist = punto_graf['dist_Gtw']
usar_up = punto_graf['usar_up']
usar_down = punto_graf['usar_down']

# Eje x en log10()
xi = np.array(dist)

# enlace_up
media_up = punto_graf[medida+'_up']
std_up   = punto_graf[medida+'_up'+'_std']
media_up_techo = media_up + std_up
media_up_piso  = media_up - std_up

# ecuacion Enlace up
yi_up = np.array(media_up)
eq_up = girni.linealiza_lstsq(xi[usar_up==1],
                              yi_up[usar_up==1],
                              digitos = precision)
alpha_up = eq_up['alpha']
beta_up  = eq_up['beta']
fd_up = lambda d: -10*alpha_up*(np.log10(d))+beta_up

# Errores up respecto a ecuacion
fi_up = fd_up(xi)
dyi0std  = eq_up['error_std']
punto_graf['fi_up'] = fi_up

# enlace_down
media_down = punto_graf[medida+'_down']
std_down   = punto_graf[medida+'_down'+'_std']
media_down_techo = media_down + std_down
media_down_piso  = media_down - std_down

# ecuación Enlace down
yi_down = np.array(media_down)
eq_down = girni.linealiza_lstsq(xi[usar_down==1],
                                yi_down[usar_down==1],
                                digitos = precision)
alpha_down = eq_down['alpha']
beta_down  = eq_down['beta']
fd_down = lambda d: -10*alpha_down*(np.log10(d))+beta_down

# Errores down respecto a ecuacion
fi_down = fd_down(xi)
dyi1std = eq_down['error_std']
punto_graf['fi_down'] = fi_down

resultado = {'tabla'        : punto_graf,
             'ecuacion_up'  : eq_up,
             'ecuacion_down': eq_down}

ecuacion = resultado.copy()
ecuacion.pop('tabla')
ecuacion = pd.DataFrame(ecuacion)

# SALIDA
pd.options.display.float_format = '{:,.2f}'.format
print(resultado['tabla'])
print('\n ecuaciones: ')
print(ecuacion)
if len(puntoSinDist)>0:
    print('\n Error: Puntos que no registran distancia en coordenadas:')
    print(puntoSinDist)

# graba la tabla resumen rssi
unresumen = carpeta_rsm+'/'+medida+'_'+arch_nombre+'.csv'
resultado['tabla'].to_csv(unresumen)

def graf_gradiente(arch_nombre,punto_graf,ecuacion,var_gen):
    ''' grafica de un gradiente
    '''
    escalabase = 10    # 10
    escala = 'log'
    medida = var_gen['medida']
    precision = var_gen['precision']

    # enlace_up
    media_up = punto_graf[medida+'_up']
    std_up   = punto_graf[medida+'_up'+'_std']
    media_up_techo = media_up + std_up
    media_up_piso  = media_up - std_up
    yi_up = np.array(media_up)
    fi_up = punto_graf['fi_up']

    # enlace_down
    media_down = punto_graf[medida+'_down']
    std_down   = punto_graf[medida+'_down'+'_std']
    media_down_techo = media_down + std_down
    media_down_piso  = media_down - std_down
    yi_down = np.array(media_down)
    fi_down = punto_graf['fi_down']

    dist = punto_graf['dist_Gtw']
    usar_up = punto_graf['usar_up']
    usar_down = punto_graf['usar_down']

    eq_up = ecuacion['ecuacion_up']
    eq_down = ecuacion['ecuacion_down']

    dyi0std = eq_up['error_std']
    dyi1std = eq_down['error_std']

    fig_gradnt,(graf_up,graf_down) = plt.subplots(2,1)
    if escala == 'log':
        graf_up.set_xscale(escala,base=escalabase)
        graf_down.set_xscale(escala,base=escalabase)

    # medida up +/- std
    graf_up.scatter(dist,media_up,color='blue',marker='o')
    graf_up.scatter(dist,media_up_techo,color='blue',marker='+')
    graf_up.scatter(dist,media_up_piso,color='blue',marker='+')

    # medida down +/- std
    graf_down.scatter(dist,media_down,color='orange',marker='o')
    graf_down.scatter(dist,media_down_techo,color='orange',marker='+')
    graf_down.scatter(dist,media_down_piso,color='orange',marker='+')

    # linealizado up
    graf_up.plot(dist,fi_up,label = '  up:'+eq_up['eq_latex'],
                 color='blue')
    graf_up.plot(dist,fi_up+dyi0std,
                 color='blue',linestyle='dotted')
    graf_up.plot(dist,fi_up-dyi0std,
                 color='blue',linestyle='dotted')
    # linealizado down
    graf_down.plot(dist,fi_down,label = 'down:'+eq_down['eq_latex'],
                   color='orange')
    graf_down.plot(dist,fi_down+dyi1std,
                   color='orange',linestyle='dotted')
    graf_down.plot(dist,fi_down-dyi1std,
                   color='orange',linestyle='dotted')

    # ajuste de eje y
    y_min = np.min([np.min(media_up_piso),np.min(media_down_piso)])
    y_max = np.max([np.max(fi_up+dyi0std),np.max(fi_down+dyi1std)])
    if y_min<-135:
        y_min = np.min([np.min([media_up]),np.min([media_down])])
    graf_up.set_ylim(y_min,y_max)
    graf_down.set_ylim(y_min,y_max)

    # etiquetas up
    for unpunto in punto_graf.index:
        media_etiq = np.round(punto_graf[medida+'_up'][unpunto],precision)
        usarpunto  = punto_graf['usar_up'][unpunto]
        
        etiqueta = unpunto #+str(media_etiq)
        xi = punto_graf['dist_Gtw'][unpunto]
        yi = punto_graf['rssi_up'][unpunto]
        if usarpunto:
            graf_up.annotate(etiqueta,(xi,yi), rotation=45)
        if not(usarpunto):
            graf_up.annotate(etiqueta,(xi,yi), rotation=45,color='red')
            graf_up.scatter(dist[unpunto],media_up[unpunto],color='red',marker='o')
            graf_up.scatter(dist[unpunto],media_up_techo[unpunto],
                            color='red',marker='+')

    # etiquetas down
    for unpunto in punto_graf.index:
        media_etiq = np.round(punto_graf[medida+'_down'][unpunto],precision)
        usarpunto = punto_graf['usar_down'][unpunto]
        etiqueta = unpunto #+str(media_etiq)
        xi = punto_graf['dist_Gtw'][unpunto]
        yi = punto_graf['rssi_down'][unpunto]
        if usarpunto:
            graf_down.annotate(etiqueta,(xi,yi), rotation=45)
        if not(usarpunto):
            graf_down.annotate(etiqueta,(xi,yi), rotation=45,color='red')
            graf_down.scatter(dist[unpunto],media_down[unpunto],color='red',marker='o')
            graf_down.scatter(dist[unpunto],media_down_techo[unpunto],
                              color='red',marker='+')

    graf_up.set_ylabel(medida+'_up (dBm)',color='blue')
    graf_up.set_title(arch_nombre+' '+medida)
    graf_up.legend()
    graf_up.grid(True,linestyle='dotted',
                 axis='x', which='both')

    graf_down.set_xlabel('distancia')
    graf_down.set_ylabel(medida+'_down (dBm)',color='brown')
    graf_down.legend()
    graf_down.grid(True,linestyle='dotted',
                   axis='x', which='both')
    return(fig_gradnt)


def graf_diferencia_updown(arch_nombre,punto_graf,var_gen):
    '''Grafica de diferencias up-down
    '''
    medida = var_gen['medida']
    medida_unidad = var_gen['medida_unidad']
    movAvg_cual = var_gen['movAvg_cual']
    movAvg_color = var_gen['movAvg_color']
    precision = var_gen['precision']

    # analiza diferencias de medias y std --------------
    punto_graf['usar_dif'] = punto_graf['usar_up']*punto_graf['usar_down']
    usar_dif = punto_graf['usar_dif']
    punto_graf['dif_mean'] = punto_graf['rssi_up']-punto_graf['rssi_down']
    punto_graf['dif_std']  = punto_graf[medida+'_up_std']-punto_graf[medida+'_down_std']
    punto_graf['dif_top']  = punto_graf['dif_mean']+punto_graf['dif_std']
    punto_graf['dif_bottom'] = punto_graf['dif_mean']-punto_graf['dif_std']

    dist = punto_graf['dist_Gtw']
    usar_dif = punto_graf['usar_dif']

    # linealiza diferencia
    xi_dif = np.array(punto_graf['dist_Gtw'][usar_dif==1])
    yi_dif = np.array(punto_graf['dif_mean'][usar_dif==1])
    eq_dif = girni.linealiza_lstsq(xi_dif,yi_dif,digitos = precision)
    alpha_dif = eq_dif['alpha']
    beta_dif  = eq_dif['beta']
    fdistdif0 = lambda d: -10*alpha_dif*(np.log10(d))+beta_dif
    yi_dif0   = fdistdif0(xi_dif)

    ecua_dif = pd.DataFrame(eq_dif)

    # medias moviles en movAvg_cual[]
    serie_media  = pd.Series(punto_graf['dif_mean'][usar_dif==1])
    movAvg_dmedia = []
    m = len(movAvg_cual)
    for j in range(0,m,1):
        k = movAvg_cual[j]
        movAvg_dmedia.append(serie_media.rolling(k).mean())

    # Grafica diferencia
    escalabase = 10    # 10
    escala = 'log'
    
    fig_dif_updown,graf_dmean = plt.subplots()
    if escala == 'log':
        graf_dmean.set_xscale(escala,base=escalabase)

    # diferencia medida up - down
    graf_dmean.scatter(dist,punto_graf['dif_mean'],color='purple',marker='o')
    graf_dmean.plot(xi_dif,yi_dif0,label = '  dif:'+eq_dif['eq_latex'],color='blue')
    graf_dmean.set_ylabel('media Up-Down (dBm)')

    # medida_up, medias móviles
    for j in range(0,m,1):
        k = str(movAvg_cual[j])
        graf_dmean.plot(dist[usar_dif==1],movAvg_dmedia[j],
                      label='movAvg_dmedia_'+k,color=movAvg_color[j])

    # etiquetas
    i=0
    for unpunto in punto_graf.index:
        media_etiq = np.round(punto_graf[medida+'_up'][unpunto],precision)
        etiqueta = unpunto # + ' ' +str(media_etiq)
        usar_dif = punto_graf['usar_dif'][unpunto]
        xi = punto_graf['dist_Gtw'][unpunto]
        yi = punto_graf.iloc[i]['dif_mean']
        i = i+1
        if usar_dif:
            graf_dmean.annotate(etiqueta,(xi,yi), rotation=30)
        if not(usar_dif):
            graf_dmean.annotate(etiqueta,(xi,yi),color='red',rotation=30)
            graf_dmean.scatter(xi,yi,color='red',marker='o')

    graf_dmean.axhline(0,color='grey')
    graf_dmean.grid(True,linestyle='dotted',axis='x', which='both')

    graf_dmean.legend()
    graf_dmean.set_title(arch_nombre+': '+medida+' media Up-Down')
    return(fig_dif_updown)

def graf_gradiente_std(arch_nombre,punto_graf,medida,precision):
    ''' Grafica de std_up y std_down ------
    '''
    xi_std      = np.array(punto_graf['dist_Gtw'])
    yi_std_up   = np.array(punto_graf[medida+'_up_std'])
    yi_std_down = np.array(punto_graf[medida+'_down_std'])

    # linealiza std
    usar_up   = punto_graf['usar_up']
    usar_down = punto_graf['usar_down']

    eq_std_up = girni.linealiza_lstsq(xi_std[usar_up==1],
                                      yi_std_up[usar_up==1],
                                      digitos = precision)
    alpha_std_up = eq_std_up['alpha']
    beta_std_up  = eq_std_up['beta']
    fdiststd_up0 = lambda d: -10*alpha_std_up*(np.log10(d))+beta_std_up
    yi_std_up0   = fdiststd_up0(xi_std)

    eq_std_down = girni.linealiza_lstsq(xi_std[usar_down==1],
                                        yi_std_down[usar_down==1],
                                        digitos = precision)
    alpha_std_down = eq_std_down['alpha']
    beta_std_down  = eq_std_down['beta']
    fdiststd_down0 = lambda d: -10*alpha_std_down*(np.log10(d))+beta_std_down
    yi_std_down0   = fdiststd_down0(xi_std)

    # grafica std
    escalabase = 10    # 10
    escala = 'log'
    
    fig_grad_std,(graf_std_up,graf_std_down) = plt.subplots(2,1)
    if escala == 'log':
        graf_std_up.set_xscale(escala,base=escalabase)
        graf_std_down.set_xscale(escala,base=escalabase)

    graf_std_up.plot(xi_std,yi_std_up0,
                     label = '  std_up:'+eq_std_up['eq_latex'],
                     color='blue')
        
    # medida up +/- std
    graf_std_up.scatter(xi_std,yi_std_up,color='blue',marker='+')
    graf_std_down.scatter(xi_std,yi_std_down,color='orange',marker='+')

    # etiquetas
    i=0
    for unpunto in punto_graf.index:
        media_etiq = np.round(punto_graf[medida+'_up'][unpunto],precision)
        etiqueta   = unpunto # + ' ' +str(media_etiq)
        usar_up    = punto_graf['usar_up'][unpunto]
        usar_down  = punto_graf['usar_down'][unpunto]
        xi  = punto_graf['dist_Gtw'][unpunto]
        yiu = punto_graf.iloc[i][medida+'_up_std']
        yid = punto_graf.iloc[i][medida+'_down_std']
        i = i+1
        if usar_up:
            graf_std_up.annotate(etiqueta,(xi,yiu), rotation=30)
        if not(usar_up):
            graf_std_up.annotate(etiqueta,(xi,yiu),color='red',rotation=30)
            graf_std_up.scatter(xi,yiu,color='red',marker='o')
        if usar_down:
            graf_std_down.annotate(etiqueta,(xi,yid), rotation=30)
        if not(usar_down):
            graf_std_down.annotate(etiqueta,(xi,yid),color='red',rotation=30)
            graf_std_down.scatter(xi,yid,color='red',marker='o')

    graf_std_down.plot(xi_std,yi_std_down0,
                    label = 'std_down:'+eq_std_down['eq_latex'],
                    color='orange')

    # otras etiquetas
    graf_std_up.set_ylabel('std_up (dBm)', color='blue')
    graf_std_up.set_xlabel('distancia')
    graf_std_up.axhline(0,color='grey')
    graf_std_up.grid(True,linestyle='dotted',
                    axis='x', which='both')
    graf_std_up.set_title(arch_nombre+': '+medida+' std')
    graf_std_up.legend()

    graf_std_down.set_ylabel('std_down (dBm)', color='brown')
    graf_std_down.set_xlabel('distancia')
    graf_std_down.axhline(0,color='grey')
    graf_std_down.grid(True,linestyle='dotted',
                    axis='x', which='both')
    graf_std_down.legend()

    return(fig_grad_std)

fig_gradnt = graf_gradiente(arch_nombre,punto_graf,ecuacion,var_gen)
unarchivo = carpeta_rsm+'/ecuacion_'+arch_nombre+'.png'
fig_gradnt.savefig(unarchivo)

fig_dif_updown = graf_diferencia_updown(arch_nombre,punto_graf,var_gen)
fig_grad_std = graf_gradiente_std(arch_nombre,punto_graf,medida,precision)

plt.show() # pasa a programa principal