elhacker.net cabecera Bienvenido(a), Visitante. Por favor Ingresar o Registrarse
¿Perdiste tu email de activación?.

 

 


Tema destacado: Guía rápida para descarga de herramientas gratuitas de seguridad y desinfección


+  Foro de elhacker.net
|-+  Programación
| |-+  Programación General
| | |-+  Hacer grafico de dispersion en Python con muchos datos
0 Usuarios y 1 Visitante están viendo este tema.
Páginas: [1] Ir Abajo Respuesta Imprimir
Autor Tema: Hacer grafico de dispersion en Python con muchos datos  (Leído 3,978 veces)
DarkSun812

Desconectado Desconectado

Mensajes: 19


Ver Perfil
Hacer grafico de dispersion en Python con muchos datos
« en: 20 Marzo 2022, 15:35 pm »

     Muy buenos dias amigos. La semana pasada empezo mi primer dia en un nuevo trabajo como desarrollador. A mi con un mes de anticipacion me dijeron que iba a programar con Python, estuve practicando y alcance un buen nivel en el lenguaje. Cuando llego me informan que ahora voy a programar con c++... Me dieron la semana pasada para ponerme al dia con el lenguaje y ya a partir de esta semana quieren ver resultados con el mismo... Yo estoy trabajando en eso pero les comento lo siguiente:

     La razon por la que ellos quieren que programe en C++ es porque necesitan graficar un cilindro con un grafico de dispersion de puntos, usando la libreria Matplotlib tarda al rededor de 8 - 20 minutos generarse la grafica en 3D. Por lo que optaron por cambiar a un lenguaje de bajo nivel donde todo se hace con mayor velocidad.

     Por lo que si consigo una manera de hacer ese grafico en un tiempo mucho menor entonces no tendria necesidad de usar c++ al menos para ese tema. Tienen alguna idea de que libreria o API o la manera que sea, en la que pueda graficar millones de datos en 3D utilizando python sin que tarde tanto tiempo??

     Estoy aprendiendo poco a poco y temo que no pueda cumplir sus espectativas, asi que si pueden ayudarme de alguna manera se los agradeceria enormemente...


En línea

Serapis
Colaborador
***
Desconectado Desconectado

Mensajes: 3.348


Ver Perfil
Re: Hacer grafico de dispersion en Python con muchos datos
« Respuesta #1 en: 20 Marzo 2022, 18:34 pm »

Me suena raro eso de que te den: "una semana para ponerte al día con el lenguaje".

Al grano... de entrada si se busca eficiencia, python al ser un lenguaje interpretado, no va a ir sobrado de eficiencia precisamente. Un lenguaje interpretado es entre 4 y 30 veces más lento que el mismo compilado (hoy día décadas atrás la diferencia podría ser entre 10 y 100 veces).

Por otro lado como ya te dije en otro mensaje, lo ideal es partir de datos binarios no de datos textuales... los archivos de geometría van bien cuando lo que se trata es de una pequeña figura (imagina por ejemplo una figura de ajedrez con unos pocos cientos de vértices).

En un principio, se dió a entender que podría tratarse de un ejercicio escolar, y que por tanto no cabe cambiar los datos de entrada... Si finalmente es un trabajo, ya no hay ninguna razón por la que los datos deban ser mantenidos en texto... será más eficiente al guardar y al leer.

En tu caso son puntos, lo que tienes que dibujar, supongamos un caso similar... un objeto 3d... lo inicial es diseñar la estructura del fichero, y lo adecuado es que así lo expongas a tus fejes y compañeros: los actuales deberán ser convertidos a binario y el programa que genere os datos deberia reformarse para adaptar su salida a esto...
El cambio será sencillo, ya que tú no deberías cambiar el orden de los datos, tan solo los tipos de los mismos...

Nota que a falt a de los detalles de tu fichero de geometría, yo parto de lo típico preciso para un fichero que describe la geometría de un objeto 3d, que se pretende graficar alambrado.
Código:
estructura Punto3D
    float X
    float Y
    float Z
    // entero Valor
fin estructura
estructura Punto2D
    entero X
    entero Y
    // entero Color
fin estructura
estructura Poligono
    entero NumVertices    
    lista de enteros listavertices[]
fin estructura


// estructura del fichero de datos de Geometría
entero NumVertices, NumPoligonos, NumAristas, NumVerticesPoligono    
por cada vertice de los NumVertices:
    float x, y, z
por cada polígono de los Numpoligonos
    entero numVerticesPol  // si NumVerticesPoligono vale 0, este valor no aparece, es fijo para cada poligono. numVerticesPol  = NumVerticesPoligono    
    por cada vertice de los numVerticesPol
        entero vertice                

// Declaraciones
entero NumVertices                // cantidad de vertices que tiene la figura 3d
entero NumPoligonos             //    "               polígonos    "
entero NumAristas                 //    "              aristas            "
entero NumVerticesPoligono    //    " de vértices que tienen todos los polígonos
array de punto3d  vertices[]    // (x,y,z)
array de poligono  poligonos[]
array de punto2d  mapa[]        // el cálculo de la proyección de los vértices, se guarda en este array que luego será el que se dibuje.


// 1- Las cantidades que define lo que vendrá debajo de cada 'cosa'.  
Si abrirfichero(ruta) = TRUE
  leer cabecera (numVertices, numPoligonos, numAristas, NumVerticesPoligono)
  leer el resto del fichero
  graficar
si no
  error al tratar de abrir el fichero...
fin si
Tomemos como ejemplo un cubo, que es fácil de imaginar y si falla la imaginación puede uno tomar una caja y 'contar' directamente.
Tiene 8 vertices, que forman 6 caras (polígonos) y 12 aristas. Estos son los datos de partida en el fichero...
NumVerticesPoligono: Señala cuantos vértices tiene cada polígono... esto puede simplificar un fichero cuando todos los polígonos tiene la misma cantidad de vertices, si cada polígono tiene una cantidad distinta este valor debe valer 0.

Seguimos: Debajo de las cantidades que son la cabecera del fichero, aparece la lista de vértices. Como ya sabemos cuantos son podemos crear el array del tamaño preciso. Y luego procede leerlos.
Código:
funcion leer resto del fichero
   entero k,n

    // leer los datos de los vértices:
    memoria para Array de punto3d Vertices[0 a NumVertices-1]  //alojar espacio para el array 3d
    memoria para Array de punto2d Mapa[0 a NumVertices-1]  //alojar espacio para el array 2d
    bucle para k desde 1 a NumVertices
       Vertices[k] = LeerSiguienteVertice   // el punto3d X,Y,Z
    siguiente

    // leer los datos de los poligonos:
    memoria para array de poligono Poligonos[0 a numPoligonos -1]   //alojar espacio para el array
    Si (NumVerticesPoligono = 0)  
        // cada políigono tiene una cantidad distinta de vertices, dicho dato aparece en el fichero.    
        bucle para k desde 1 a numPoligonos
            n = leer entero
            Poligonos[k].numVertices = n
            memoria para Poligonos[k].listaVertices[0 a n-1]
            bucle para j desde 0 a n-1
                Poligonos[k].listaVertices[j] = leer entero  // el entero leído es el índice del vértice (del array vértices)
            siguiente
        siguiente
    si no
        // el fichero omite la cantidad de vertices de cada polígono, porque el valor es el mismo para cada uno.
        bucle para k desde 1 a numPoligonos
            Poligonos[k].numVertices = NumVerticesPoligono
            memoria para Poligonos[k].listaVertices[0 a NumVerticesPoligono-1]
            bucle para j desde 0 a n-1
                Poligonos[k].listaVertices[j] = leer entero  // el entero leído es el índice del vértice (del array vértices)
            siguiente
        siguiente
    fin si
fin funcion

Punto3D = funcion LeerSiguienteVertice
   punto3d p

   leer p.x
   leer p.y
   leer p.z
   devlver p
fin funcion
En esta función se lee el resto dle fichero, puede notarse que la cabecera incluye un dato para determinar si todos los polígonos tienenel mismo número de vértices o cada uno tiene su valor.
Por ejemplo para el caso de un cubo, cada polígono está formado por exactamente 4 vértices, luego la lista de vertices que forman cada polígono, son 4... en el ejemplo de una figura como la mencionada más arriba (una figura de ajedrez), cada polígono tendrá un número distinto de vertices, esto se indica marcando en la cabecera un valor 0, e implica qwue en el fichero precediendo a la lista de vértices de cada políugono hay un entero que indica cuantos vertices componen ese polígono.
Por su parte la lista de vértices, lo que tiene es el índice del vértice del array vertices[], luego si un polígono dice tener:
4 114  83  97 140
Vendría a decir que ese polígono tiene 4 vertices y los forman los vértices: vertices[113], vertices[83], vertices[97] y vertices[140], luego el poligono supongamos que fuera el 520, en memoria sería:
poligonos[520].NumVertices = 4
poligonos[520].listaVertices[0] = 114
poligonos[520].listaVertices[1] = 83
poligonos[520].listaVertices[2] = 97
poligonos[520].listaVertices[3] = 140

Creo que está claro, no?...

Solo queda graficar.
En el caso de una figura 3D que no solo se quiere dibujar puntos, sino líneas, es solo un oco más de trabajo, porque hay que dibujar una línea entre cada par de puntos de un polígono, para cada polígono. En el ejemplo previo: del vértice 114, se dibujaria una línea hasta el 83, dle 83 hasta el 97, del 97 hasta el 140 y desde el 140 al primero, al 114.

En tu caso es más sencillo, no tendrás ni polígonos, aunque tal vez tengas que asignar colores a cada punto basado en un valor que se adjunta con las cordenadas x,y,z,valor.

Como debes o deberías saber, al graficar debes calcular para vertice 3d, la proyección 2d, lo cual requiere señalar el ángulo de visión, la escala, desplazamiento y rotación desde el que se ha de ver, que se calcula con multiplicaciones de matrices:
Código:

funcion Graficar
   CalcularMatrices     // Calcula la matriz resultado que se ubicará en la matriz 'Tem[]
   CalcularProyeccion   // calcula las cordenadas 2D donde se proyectará el array de vértices 3D, dada la matriz Temp[]
   CalcularGrafico        // borra el gráfico previo y calcula el nuevo en un backbuffer
   Dibujargrafico       // vuelca el backbuffer a la ventana de la pantalla.
fin funcion

funcion CalcularMatrices
   MatrizBaseSetZero  // Asignar los valores por defecto de la matriz base.

   // Temp[] y Tmp2[] son las matrices que recoge el resultado temporal del cálculo, se va borrando su valor previo a su asignación.
   // RotX[], RotY[] y RotZ[] son las matrices que recoge los valores de rotacion en el eje X,Y y Z de la 'cámara'.
    // Escala[] y Desplazamiento[] son las matrices que recogen la escala en los ejes x,y,z y el desplazmaiento en los mismos ejes (a falta de datos, será el origen de cordenadas).
    MultiplicarMatrices(RotX[], Base[], Temp[])
    MultiplicarMatrices(RotY[], Temp(), Tmp2[])
    MultiplicarMatrices(RotZ[], Tmp2[], Temp[])
    MultiplicarMatrices(Escala[], Temp[], Tmp2[])
    MultiplicarMatrices(Deplazamiento[], Tmp2[], Temp[])  // el array Temp contiene los valores de salida que se usarán en el cálculo de la proyección.
fin funcion

Lógicamente para que funciones bien, cada vez que se cambie la vista de la cámara, la escala o el desplazamiento, debe actualizarse la matriz correspondiente, e invocar la función graficar, para que actualice la vista.

En tu caso posiblemente la proyección exija un array de una estructura que no es emramente un Punto2D... pues como dije más arriba, seguramente tus puntos incluyen también un valor.
Código:
estructura punto3DEspecial
    float X
    float Y
    float Z
    float Valor
fin estructura
Lo que precisará un punto 2D también espacial... es probable que el valor deba ser transformado en un color...
Código:
estructura Punto2DEspecial
   entero X
   entero Y
   entero Color

La proyección calculará para cada vértice 3D, el destino que ocupara en el espacio 2D, previamente definido. Al mismo tiempo para cada vértice si hay un dato asociado (como el sugerido valor), puede al mismo tiempo calcular el color que le corresponde...
La función calcularGrafico, borra el backbufer previo  o lo elimina y genera uno nuevo y transfiere el array 2D al mismo.

La función DibujarGrafico, vuelca el backbuffer a la pantalla. Si se borra la pantalla entera o parcialmente, esta misma función puede usarse para redibujarlo entero o parcialmente (puede admitir parámetros para el 'rect' a dibujar o dibujarlo todo siempre).

Que sean 2 milones de puntos, no debe ser motivo para que sea lento.
Leer desde fichero un array de 2 millones de vértices, requiere mucho menos de 1sg. a no ser que se esté leyendo desde una unidad que requiere una preparación (esto es un CD, DVD, o una unidad que entra en un estado bajo de energía, etc...).
El cálculo igualmente debiera ser apenas de 1 décima de sg. o menos, transferir y volcar el contenido lo mismo... por lo que la actualización de los datos (por ejemplo si cambia la posición de la cámara, escalas, etc... debiera ser inmediato (menor que un parpadeo), y solo ser un pelín más lento cuando cargas desde fichero, tan solo por la lectura de los datos que requiere además la creación de los arrays, etc... supongamos que en ese caso 1sg. si la unidad está lista.
Si el fichero es mucho más grande, puede leerse entero en bytes y luego ir asignando los valores desde memoria... en este caso solo será más rápido si sabes manejarlo, es decir si conoces el lenguaje en cierta profundidad, si no posiblemente andes más liado, de ser el caso, lee el fichero como el pseudocódigo señala.

Una optimización que puede hacerse a cambio de un gasto de memoria algo mayor (en el ejemplo de una figura 3d), sería asumir un valor alto de vértice spor cada polígono, asegurando así que sea cual sea el valor siempre encaja (por ejemplo 20 vértices), esto premite rediseñar la estructura 'Poligono', y con ello el array poligonos, para ser un array de dos dimensiones, de esto:
Código:
estructura poligono
   entero numVertices
   lista de enteros listavertices[]
fin estructura
  array de poligono poligonos[]
//...

... a esto:
Código:

   array de enteros poligonos[]

   //...
   memoria para poligonos(0 a numPoligonos, 0 a 20)

El índice 0, podría contener el numero de vértices y la lista de vertices comenzar en el indice 1 hasta el 20 (comparar con lo mostrado más arriba)
Código:
poligonos[520, 0] = 4   // número de vértices
poligonos[520, 1] = 114
poligonos[520, 2] = 83
poligonos[520, 3] = 97
poligonos[520, 4] = 140
Este cambio permite reservar memoria de una sola vez, 1 solo array en vez de un array donde cada elemento tendrá luego otro mini array.
Lógicamente como tu no necesitas polígonos, para tu trabajo, este cambio no te afecta, pero debe ilustrarte en cuanto a la idea de operar más rápido a cambio de algo más de memoria.

Y sin más datos explicitos, no conviene aventurar supuestas optimizaciones.
Por cierto 2 milones de puntos, no son 'muchos datos'.

p.d.: Una figura de ejemplo... tiene 314 vértices (puntos), 320 polígonos (caras) y 1264 aristas (líneas). Dibujado en malla y luego en puntos.



p.d.:
Ejemplo dle fichero, para el cubo:
8 6 12 0
1 1 1
1 -1 1
1 -1 -1
1 1 -1
-1 1 1
-1 -1 1
-1 -1 -1
-1 1 -1
4 4 8 7 3
4 4 3 2 1
4 4 8 5 1
4 6 2 1 5
4 6 5 8 7
4 6 7 3 2

A pesar de que el cubo tiene 4 vertices por cada polígono, si consigno el valor 0 (final en la primera línea), le estoy indicando en el fichero que cuando se lea, lea el valor del numero de vértices para cada polígono. De haber consignado el valor 4 (en vez de 0), nos habríamos ahorrado poner 4, para cada poligono. Como aquí son solo 6 polígonos, no ahorramos gran cosa.
Lógicamente aunque aquí se ve textual (para poderlo leer), los datos se deben guardar en binario, no hay saltos de línea ni otra separación que el número de bytes que compone cada dato.
La primera línea son datos de tipo entero
Las 8 líneas de los vertices, son de tipo decimal con signo (aunque dado el cubo de lado 1, no reqiere dígitos decimales).
Las 6 lineas de los poligonos son de tipo entero.

Ejemplo para un dodecaedro (ahora en los vértices si se ven los decimales) y tambien se ha hecho constar el númeor de vértices en la primera linea (5):
20 12 60 5
1 -1 -1
1.61783 0.61783 0
1.61783 -0.61783 0
1 1 -1
0.61783 0 -1.61783
-0.61783 0 -1.61783
-1 1 -1
0 1.61783 -0.61783
0 1.61783 0.61783
1 1 1
-1 1 1
-1.61783 0.61783 0
-1.61783 -0.61783 0
-1 -1 -1
0 -1.61783 -0.61783
-0.61783 0 1.61783
-1 -1 1
0.61783 0 1.61783
1 -1 1
0 -1.61783 0.61783
4 5 6 7 8
4 5 1 3 2
2 4 8 9 10
7 8 9 11 12
6 7 12 13 14
1 5 6 14 15
17 16 18 19 20
11 12 13 17 16
13 14 15 20 17
1 3 19 20 15
3 2 10 18 19
10 9 11 16 18


« Última modificación: 21 Marzo 2022, 10:22 am por Serapis » En línea

Páginas: [1] Ir Arriba Respuesta Imprimir 

Ir a:  

Mensajes similares
Asunto Iniciado por Respuestas Vistas Último mensaje
Como hacer una pelicula de muchos megas en 2 partes?
Multimedia
daygo 1 1,495 Último mensaje 23 Octubre 2004, 06:40 am
por Songoku
COmo hacer grafico en Access
Software
_CrisiS_ 3 4,496 Último mensaje 21 Abril 2011, 06:08 am
por _CrisiS_
[Python] Motor gráfico con interfaz.
Scripting
tmb90 4 6,218 Último mensaje 22 Febrero 2014, 14:15 pm
por dRak0
Hacer grafico que se actualize desde la base de datos
Desarrollo Web
Citrusl 3 1,913 Último mensaje 16 Junio 2015, 19:15 pm
por engel lex
Crear entorno gráfico en python
Scripting
fenix2000 4 5,410 Último mensaje 1 Enero 2018, 21:42 pm
por edgardogomez24
WAP2 - Aviso Legal - Powered by SMF 1.1.21 | SMF © 2006-2008, Simple Machines