packages = ["pandas", "matplotlib", "statsmodels"]

# importamos librerias import io import asyncio import pandas as pd import matplotlib.pyplot as plt import math import numpy as np import itertools # permutaciones import copy from time import time #from statsmodels.graphics.gofplots import qqplot # para qq test #import statsmodels.api as sm from js import document, FileReader from pyodide.ffi import create_proxy ################################### las funciones que se llaman aparte cada una tras cargar los datos pulsando botones # norma 1 (usando valor absoluto) #### value = 1 def norm_1(a,b): t = 0; for i in range(len(a)): t = t + abs(a[i]-b[i]) return t # coordenadas polares planas #### value = 3 def polares_2(a,b): ax = a[0]*math.cos(a[1]*math.pi/180) # a = [radio_a, angulo_a] b = [radio_b, angulo_b] ay = a[0]*math.sin(a[1]*math.pi/180) bx = b[0]*math.cos(b[1]*math.pi/180) by = b[0]*math.sin(b[1]*math.pi/180) av = [ax,ay] bv = [bx,by] return math.dist(av,bv) # coordenadas polares esféricas pero con distancia en recta #### value = 4 def esfericas_1(a,b): # a[0] = RAD a[1] = LAT a[2] = LON distancia esféricas pero en rectas ax = math.cos(a[2]*math.pi/180)*math.cos(a[1]*math.pi/180)*a[0] ay = math.sin(a[2]*math.pi/180)*math.cos(a[1]*math.pi/180)*a[0] az = math.sin(a[1]*math.pi/180)*a[0] bx = math.cos(b[2]*math.pi/180)*math.cos(b[1]*math.pi/180)*b[0] by = math.sin(b[2]*math.pi/180)*math.cos(b[1]*math.pi/180)*b[0] bz = math.sin(b[1]*math.pi/180)*b[0] av = [ax,ay,az] bv = [bx,by,bz] return math.dist(av,bv) # coordenadas esféricas con distancia en arco según radio #### value = 5 def esfericas_2(a,b): # radio fijo pero dado en primera columna de datos # vamos a recurrir a bibliotecas de numpy que ayudan trabajar con matrices y vectores ax = math.cos(a[2]*math.pi/180)*math.cos(a[1]*math.pi/180)*a[0] ay = math.sin(a[2]*math.pi/180)*math.cos(a[1]*math.pi/180)*a[0] az = math.sin(a[1]*math.pi/180)*a[0] bx = math.cos(b[2]*math.pi/180)*math.cos(b[1]*math.pi/180)*b[0] by = math.sin(b[2]*math.pi/180)*math.cos(b[1]*math.pi/180)*b[0] bz = math.sin(b[1]*math.pi/180)*b[0] av = np.array([ax,ay,az]) bv = np.array([bx,by,bz]) # calculamos el ángulo entre vectores con defincición de producto escalar pab = av@bv pa = math.sqrt(av@av) pb = math.sqrt(bv@bv) cos_alpha = pab/(pa*pb) alpha = math.acos(cos_alpha) dist = a[0]*alpha # el angulo ya viene dado en radianes return dist # coordenadas geográficas #### value = 6 def coordenadas(a,b): # radio fijo 6371 distancia en arco terrestre # vamos a recurrir a bibliotecas de numpy que ayudan trabajar con matrices y vectores r = 6371 ax = math.cos(a[1]*math.pi/180)*math.cos(a[0]*math.pi/180)*r ay = math.sin(a[1]*math.pi/180)*math.cos(a[0]*math.pi/180)*r az = math.sin(a[0]*math.pi/180)*r bx = math.cos(b[1]*math.pi/180)*math.cos(b[0]*math.pi/180)*r by = math.sin(b[1]*math.pi/180)*math.cos(b[0]*math.pi/180)*r bz = math.sin(b[0]*math.pi/180)*r av = np.array([ax,ay,az]) bv = np.array([bx,by,bz]) # calculamos el ángulo entre vectores con defincición de producto escalar pab = av@bv pa = math.sqrt(av@av) pb = math.sqrt(bv@bv) cos_alpha = pab/(pa*pb) alpha = math.acos(cos_alpha) dist = r*alpha # el angulo ya viene dado en radianes return dist # función distancia (normas) def norma(a,b): # aquí se introduce valor de radiobox para eligir la métrica if document.getElementById("norma1").checked: rate_value = document.getElementById("norma1").value; elif document.getElementById("norma2").checked: rate_value = document.getElementById("norma2").value; elif document.getElementById("polar_plana").checked: rate_value = document.getElementById("polar_plana").value; elif document.getElementById("polar_espacio").checked: rate_value = document.getElementById("polar_espacio").value; elif document.getElementById("polar_espacio_esféricas").checked: rate_value = document.getElementById("polar_espacio_esféricas").value; elif document.getElementById("coordenadas").checked: rate_value = document.getElementById("coordenadas").value; elif document.getElementById("tiempo").checked: rate_value = document.getElementById("tiempo").value; if rate_value == "1": norma = round(norm_1(a,b),2) elif rate_value == "2": norma = round(math.dist(a,b),2) elif rate_value == "3": norma = round(polares_2(a,b),2) elif rate_value == "4": norma = round(esfericas_1(a,b),2) elif rate_value == "5": norma = round(esfericas_2(a,b),2) elif rate_value == "6": norma = round(coordenadas(a,b),2) return norma def principal(): list_dist = [] # lista de distancias ordenada manual_div0 = Element("dato2") # indicamos donde lo vamos a representar l = len(df.iloc[:,0]) n = len(df.iloc[0,:]) k = 0; while k < l: r = k+1; while r <= l-1: a = df.iloc[k,1:n].to_list() # el primer elemento nocuenta porque es "nombre" apartir del segundo son coordenadas "-1" calcula hasta último b = df.iloc[r,1:n].to_list() d = norma(a,b) elem_1 = df.iloc[k,0] elem_2 = df.iloc[r,0] lista_val=[elem_1,elem_2,d] list_dist.append(lista_val) # hacemos lista de listas (matriz) donde cada elemento es elemento 1, elemento 2 y distancia entre ellos. r = r + 1; k = k + 1; manual_div0.element.innerText = []; # borrar todo manual_div0.element.innerText = list_dist; def rutas_posibles(): tiempo_inicial = time() l = len(df) listadeobjetos = [] listadeobjetos_titulos = [] for i in range(l): listadeobjetos.append(df.iloc[i,:].to_list()) # convertimos en lista todos objetos con todas parámetros permutations = list(itertools.permutations(listadeobjetos)) # hacemos salidas recortadas o normales en función de tectacles 2 que corresponde a linea de un punto concreto. # Solo se muestran rutas desde un punto concreto. Modificamos lista anterior añadiendo Solo # elementos que comienzan por dado punto de salida if int(document.getElementById("tentacles2").value)!= 0: value_3 = int(document.getElementById("tentacles2").value) - 1 # este indica posición en archivo y en dataframe del punto correspondente lista_reducida = []; # para acceder al numbre del unto debemos referirnos a df en este caso nombre = df.iloc[value_3,0] for j in range(len(permutations)): if permutations[j][0][0] == nombre: lista_reducida.append(permutations[j]) permutations = lista_reducida; # ahora voy a meter aqui en cada ruta su diustancia # como rutas no son variables globales es mejor hacerlo desde esta misma función # para cada elemento de permutations for k in range(len(permutations)): dist_total = 0; n = len(permutations[0][0]) j_len = len(permutations[0]) listadeobjetos_titulos.append([]) for j in range(j_len-1): dist_total = round(dist_total + norma(permutations[k][j][1:n],permutations[k][j+1][1:n]),2) listadeobjetos_titulos[k].append(permutations[k][j][0]) listadeobjetos_titulos[k].append(permutations[k][j_len-1][0]) # no se añade la última ciudad con el boocle por esto se hace aquí listadeobjetos_titulos[k].append(dist_total) # si está eligido checkbox de ida y vuelta quiere decir que tenemos que añadir ida desde el último punto hasta el primero if document.getElementById("ida_y_vuelta").checked: listadeobjetos_titulos[k][j_len] = round(dist_total + norma(permutations[k][0][1:n],permutations[k][j_len-1][1:n]),2) # eligimos entre varias opciones. Mostrar toda la ruta o solo la ruta minimal if document.getElementById("todas").checked: manual_div2 = Element("dato2") # indicamos donde lo vamos a representar manual_div2.element.innerText = ""; # borrar todo manual_div2.element.innerText = listadeobjetos_titulos; elif document.getElementById("ordenadas").checked: manual_div2 = Element("dato2") # indicamos donde lo vamos a representar manual_div2.element.innerText = ""; # borrar todo manual_div2.element.innerText = [2]; # rate_value_2 = document.getElementById("ordenadas").value; elif document.getElementById("minimal").checked: lista_distancias = [] len_elemento = len(listadeobjetos_titulos[0]) for i in range(len(listadeobjetos_titulos)): lista_distancias.append(listadeobjetos_titulos[i][len_elemento-1]) result = lista_distancias.index(min(lista_distancias)) manual_div2 = Element("dato2") # indicamos donde lo vamos a representar manual_div2.element.innerText = ""; # borrar todo manual_div2.element.innerText = listadeobjetos_titulos[result]; #### parte final de la función que imprime el resultado. tiempo_final = time() tiempo_total = tiempo_final - tiempo_inicial # borrar todao def borrar2(): manual_div = Element("dato2") manual_div.element.innerText = " "; ### //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ### ///////////////////////////// el código de abajo carga el archivo desde boton (1), define variables a partir de este (3), ### además representa parte de archivo en div content y define variables globales (4), ### el resto de código (superior) funciona ya correctamente con estas variables ### procesado de archivo async def process_file(event): fileList = event.target.files.to_py() ### 4. esta función se ejecuta automáticamente al cargar el archivo (en boocle de abajo) ### solo representa por pantalla rsumen del archivo ### y define variables globales para el resto del código def representar(dataframe): nombres_1 = dataframe.columns.values nombres_2 = str(nombres_1) document.getElementById("content").innerHTML = nombres_2 # también puede usarse innerHTML o innerText # ahora de una vez se guarda esta variable global para poder usarla en todo el script global df; df = dataframe; global tamanio; tamanio = len(dataframe) minimal = min(tamanio,4) # para decidir lineas máximo a representar # se imrime en ventana principal (capa 1) for x in range(minimal): document.getElementById("content" + str(x)).innerHTML = list(dataframe.iloc[x]) document.getElementById("content5").innerHTML = "... ... tamaño total: " + str(tamanio) ### 3. definimos variable df (no global de momento) a partir del texto ### y llamamos función para representar (que también define variables flobales) for f in fileList: data = await f.text() # read_csv recibe como parámetro archivo de texto pero en este caso le pasamos simple contenido del archivo # para que read_csv pueda recibir este formato hay que añadir io.stringIO función creada para esto df_0 = pd.read_csv(io.StringIO(data)) # representar parte de archivo en un div representar(df_0) ### 1. inicia aquí. Se carga desde el botón "myfile" def main(): # Create a Python proxy for the callback function # process_file() is your function to process events from FileReader file_event = create_proxy(process_file) # Set the listener to the callback e = document.getElementById("myfile") e.addEventListener("change", file_event, False) main()