Gnuplot y con que se come



Seguramente muchos de ustedes que hojean las publicaciones científicas occidentales han visto gráficos hermosos y simples. Quizás algunos de ustedes se hayan preguntado qué visualizan estos expertos con sus datos. Y ahora hay una herramienta de gráficos hermosa y muy simple, que está en casi todas partes: Windows, Linux, Android y otros, estoy seguro de que incluso bajo DOS. Es confiable, simple y le permite presentar cualquier dato tabular de texto en forma de hermosos gráficos.



¿Por qué gnuplot?



Si ya ha leído mis artículos " Prueba de velocidad simultánea en varios módems LTE ", " Oscilaciones armónicas ", " Crear un generador de números aleatorios de hardware ", es posible que haya notado gráficos hermosos.





Gráfico de la publicación sobre el generador de números aleatorios





Imagen de la publicación sobre los módems más rápidos Los



gráficos son simples y geniales. La ventaja más valiosa de gnuplot es que para trazarlos solo necesita un archivo de texto con los datos sin procesar, gnuplot en su sistema operativo favorito (aunque OpenWRT) y su editor de pruebas vim favorito.



A primera vista, podría parecer que gnuplot es más difícil de usar para trazar que MS Excel. Pero solo parece así, el umbral de entrada es un poco más alto (no puede usar un mouse para hacer clic en él, necesita leer la documentación aquí), pero en la práctica resulta mucho más fácil y conveniente. Escribí un guión una vez y lo he estado usando toda mi vida. Realmente es mucho más difícil para mí trazar un gráfico en Exel, donde no todo es lógico, que en gnuplot. Y la principal ventaja de gnuplot es que puede incrustarlo en sus programas y visualizar datos sobre la marcha. Además, gnuplot sin ningún problema construye un gráfico a partir de un archivo de datos estadísticos de 30 gigabytes, mientras que Exel simplemente falla y no puede abrirlo.



Las ventajas de gnuplot incluyen el hecho de que se puede integrar fácilmente en el código en lenguajes de programación estándar. Hay bibliotecas listas para usar para muchos idiomas, personalmente encontré php y python. Por lo tanto, puede generar gráficos directamente desde su programa.



Por ejemplo, diré que mi buena amiga, cuando estaba escribiendo su disertación, dominaba gnuplot (por sugerencia mía). Ella nunca es una experta en tecnología, pero lo descubrió en una noche. Después de eso, construyó gráficos solo allí, y el nivel de su trabajo comenzó a diferir favorablemente en comparación con los colegas que usaban Excel. Para mí, personalmente, un indicador de la alta calidad del trabajo científico son los gráficos construidos por programas especializados.



Por lo tanto, gnuplot es simple, accesible y hermoso. Vayamos más lejos.



Gnuplot - aplicación



Hay dos formas de trabajar con gnuplot: modo de comando y modo de ejecución de script. Recomiendo usar el segundo modo de inmediato, ya que es el más conveniente y rápido. Además, la funcionalidad es absolutamente la misma.



Pero para empezar, ejecutamos gnuplot en modo comando. Ejecute gnuplot desde la línea de comandos o de la forma que esté disponible para su sistema operativo. Puede comenzar a aprender ni siquiera leyendo este artículo, sino desde el primer comando de ayuda . Ella mostrará una ayuda magnífica y puedes ir más allá. Pero repasaremos los aspectos más destacados.



El gráfico se traza mediante el comando plot . Como parámetros de comando, puede especificar una función o el nombre del archivo de datos. Así como qué columna de datos usar y cómo conectar los puntos, cómo denotarlos, etc. Ilustremos.



gnuplot> plot sin(x)







Luego de ejecutar el comando, se abrirá una ventana donde habrá un gráfico de seno, con firmas predeterminadas. Mejoremos este gráfico y descubramos algunas opciones adicionales al mismo tiempo.

Firmemos los ejes.



set xlabel "X"


Especifica la etiqueta del eje de abscisas.



set ylabel "Y"


Especifica la etiqueta del eje de ordenadas.



Agreguemos una cuadrícula para mostrar dónde se construye el gráfico.



set grid


No me gusta el hecho de que la sinusoide en el eje de ordenadas se apoye en el final del gráfico, por lo que estableceremos los límites de los valores a los que se limitará el gráfico.



set yrange [-1.1:1.1] 


Así, el gráfico se dibujará desde el valor mínimo de -1,1 hasta el valor máximo de 1,1.

Del mismo modo, configuré el rango para la abscisa de modo que solo sea visible un período de la sinusoide.



set xrange[-pi:pi]


Necesitamos agregar un título a nuestro horario para que todo sea Feng Shui.



set title "Gnuplot for habr" font "Helvetica Bold, 20"


Tenga en cuenta que puede establecer fuentes y sus tamaños. Consulte la documentación de gnuplot para conocer las fuentes que se pueden utilizar.



Y finalmente, además del seno en el gráfico, también dibujemos el coseno y también establezcamos el tipo de línea y su color. Y también agregue leyendas, qué estamos dibujando.



plot sin(x) title "sinux" lc rgb "red", cos(x)  title "cosinus" lc rgb "green"


Aquí dibujamos dos gráficos en un lienzo, en rojo y verde. En general, hay muchas opciones para líneas (línea de puntos, trazo, sólido), anchos de línea, colores. Así como tipos de puntos. Mi objetivo es solo demostrar el abanico de posibilidades. Reunamos todos los comandos en una pila y ejecútelos secuencialmente. Para restablecer la configuración anterior, ingrese restablecer.



reset
set xlabel "X" 
set ylabel "Y"
set grid
set yrange [-1.1:1.1]
set xrange[-pi:pi]
set title "Gnuplot for habr" font "Helvetica Bold, 20"
plot sin(x) title "sinux"  lc rgb "red", cos(x)  title "cosinus" lc rgb "green"


Como resultado, obtenemos tal belleza.





Ya no es una pena publicar el calendario en una revista científica.



Si honestamente repitió todo esto después de mí, es posible que haya notado que ingresarlo manualmente cada vez, incluso copiarlo, de alguna manera no es comme il faut. ¿Pero es este un guión ya hecho? ¡Hagamoslo!

Salga del modo de comando con el comando exit y cree un archivo:



vim testsin.gpi


#! /usr/bin/gnuplot -persist
set xlabel "X" 
set ylabel "Y"
set grid
set yrange [-1.1:1.1]
set xrange[-pi:pi]
set title "Gnuplot for habr" font "Helvetica Bold, 20"
plot sin(x) title "sinux"  lc rgb "red", cos(x)  title "cosinus" lc rgb "green"


Lo hacemos ejecutable y lo ejecutamos. Bueno, no olvides cómo salir de vim.



chmod +x testsin.gpi
./testsin.gpi


Como resultado, obtenemos la misma ventana con gráficos. Si no se agrega "-persist" al título, la ventana se cerrará automáticamente después de que se ejecute el script.



Pero a menudo no es muy necesario crear una ventana, además de que no siempre es conveniente usarla y puede trabajar en un sistema operativo sin una GUI. Con mucha más frecuencia, necesita recibir archivos gráficos. Personalmente, prefiero el formato vectorial postscript, ya que con una gran cantidad de puntos, puedes hacer zoom en diferentes partes del gráfico sin perder calidad. Y también el visor en Linux actualiza automáticamente la ventana con el gráfico cuando se cambia el archivo postscript, lo cual también es muy conveniente.



Para enviar datos a un archivo y no a la pantalla, debe reasignar el terminal.



set terminal png size 800, 600
set output "result.png"


Como puede imaginar, indicamos el tipo de archivo, su resolución, luego indicamos el nombre del archivo. Agregue estas dos líneas al comienzo de nuestro script y obtenemos esta imagen en la carpeta actual.







Para guardar en posdata, debe utilizar los siguientes comandos:



set terminal postscript eps enhanced color solid
set output "result.ps"


Datos reales



Los senos y cosenos son ciertamente geniales de dibujar, ¡pero aún así, dibujar datos reales es mucho más interesante! Permítanme recordarles una tarea reciente sobre la que escribí un artículo : mostrar gráficos de la velocidad de Internet durante largos períodos de tiempo. El formato de los datos fue el siguiente.



Operador; #Prueba; Fecha; Hora; Coordenadas; Descarga Mb / s; Subir Mb / s; silbido; Testserver

Rostelecom; 0; 21/05/2020; 09: 56: 00; NA, NA; 3.7877656948451692; 5.231226008184113; 132.227; MaximaTelecom (Moscú) [0.12 km]: 132.227 ms

Rostelecom; 1; 21/05/2020; 10: 01: 02; NA, NA; 5.274994541394363; 5.1088572634075815; 127.52; MaximaTelecom (Moscú) [0.12 km]: 127.52 ms

Rostelecom; 2; 05.21.2020; 10: 04: 35; NA, NA; 3.61044819424076; 4.624132180211938; 135.456; MaximaTe 0,12 kilometros]: 135,456 ms


Se puede ver que tenemos un punto y coma como separador, necesitamos mostrar la velocidad de descarga, velocidad de carga dependiendo del tiempo. Además, si prestas atención a la fecha y la hora están en columnas diferentes. Ahora les diré cómo solucioné esto. Inmediatamente citaré el guión mediante el cual se construyó el gráfico.



#! /usr/bin/gnuplot -persist
set terminal postscript eps enhanced color solid
set output "Rostelecom.ps"

#set terminal png size 1024, 768
#set output "Rostelecom.png"
 
set datafile separator ';'
set grid xtics ytics
set xdata time
set timefmt '%d.%m.%Y;%H:%M:%S'

set ylabel "Speed Mb/s"
set xlabel 'Time'
set title "Rostelecom Speed"

plot "Rostelecom.csv" using 3:6 with lines title "Download", '' using 3:7 with lines title "Upload"
 
set title "Rostelecom 2 Ping"
set ylabel "Ping ms"
plot "Rostelecom.csv" using 3:8 with lines title "Ping"


Al comienzo del archivo, configuramos el archivo de salida postscript (o png, si es necesario).



establecer separador de archivos de datos ';' - establecemos el carácter delimitador. Las columnas están separadas por espacio de forma predeterminada, pero el archivo csv ofrece muchas opciones de delimitador y debería poder usarlas todas.

set grid xtics ytics : establece la cuadrícula (puedes configurar la cuadrícula solo a lo largo de un eje).

set xdata time es un punto importante, estamos hablando del hecho de que en el eje X el formato de datos será time.

set timefmt '% d.% m.% Y;% H:% M:% S ' - establece el formato de datos de tiempo. Tenga en cuenta que el carácter delimitador de columna (";") está incluido en el formato de hora, por lo que trataremos dos columnas como una.



Establecemos las etiquetas de los ejes y el gráfico. Luego construimos una gráfica.



trazar "Rostelecom.csv" usando 3: 6 con el título de líneas "Descargar", '' usando 3: 7 con el título de líneas "Cargar" - trazamos tanto la velocidad de descarga como la velocidad de carga en un gráfico. Usar 3: 6 es el número de columna en nuestro archivo de datos de origen, de lo que estamos construyendo (X: Y).



Luego trazamos el gráfico de ping de la misma manera. El gráfico resultante se verá así.





Esta es una captura de pantalla de la posdata. Las líneas rectas en el gráfico se deben al hecho de que hay brechas de datos. Aquí hay un ejemplo muy real de trazado.



¿Y 3D ???



¿Quieres 3D? ¡Los tengo!



Pensé durante mucho tiempo qué ejemplo de gráficos tridimensionales dar, y no se me ocurrió nada mejor que visualizar la imagen. De hecho, en esencia, una imagen es un gráfico tridimensional, donde el brillo del píxel es la coordenada z. Así que juguemos a un pequeño gamberro.

Toma la foto más famosa de Einstein.





Y hagamos un gráfico con eso. Para ello, conviértalo a formato pgm ASCII y elimine todos los espacios, reemplazándolo por una nueva línea, con un comando tan simple.



convert Einstein.jpg  -compress none pgm:- | tr -s '\012\015' ' '  | tr -s ' ' '\012'> outfile.pgm 


Para aquellos que no entienden lo que está sucediendo aquí, les explico: usamos imagemagic para convertir la imagen a formato pgm, y luego usamos tr para reemplazar el retorno de carro con una nueva línea en un espacio, y luego todos los espacios en un retorno de carro y guardarlo todo en el archivo de salida. pgm. Cualquiera que tenga dificultades puede abrir el archivo en gimp y exportarlo como pgm-ASCII.



Después de eso, abra el archivo resultante con nuestro editor favorito vim y elimine el título. En mi caso, estas son las tres primeras líneas. No olvide averiguar la resolución del archivo en el título, en este caso fue de 325x408 píxeles. Eso es todo, ¡tenemos un archivo de texto de coordenadas Z! Ahora nuestra tarea es sumar las coordenadas X e Y, para ello ejecutaremos todo esto mediante un script de Python.



f = open('outfile.pgm')
for x in range(408):
	for y in range(325):
		line = f.readline()
		print ('%d %d %s' % (x, y, line)),
f.close()


Guarde esto como convert.py y ejecute:



python convert.py > res.txt


Eso es todo, ahora res.txt contiene las coordenadas de Einstein ... Hmm, o mejor dicho, las coordenadas de su imagen. Bueno, en general, entiendes la idea :).





406 317 60

406 318 54

406 319 30

406 320 41

406 321 84

406 322 101

406 323 112

406 324 119

407 0 128

407 1 53

407 2 89

407 3 95

407 4 87

...


Archivo de muestra.



El guión para construir esta belleza se ve así.



#! /usr/bin/gnuplot -persist
#set terminal png size 1024, 768
#set output "result.png"
#set grid xtics ytics

#set terminal postscript eps enhanced color solid
#set output "result.ps"

set title "Albert Einstein"
set palette gray
set hidden3d
set pm3d at bs
set dgrid3d 100,100 qnorm 2
set xlabel "X" font "Helvetica Bold	,18"
set ylabel "Y" rotate by 90 font "Helvetica Bold	,18"
set zlabel "Z" font "Helvetica Bold	,18"

set xrange [0:408]
set yrange [0:325]
set zrange [-256:256]
unset key 
splot "./res.txt" with l 


Antes de ir a analizar el script, si repite esto, le recomiendo encarecidamente que ejecute las líneas del script en modo comando para poder rotar el gráfico con el mouse (por supuesto, sin especificar el terminal establecido). ¡Esta muy padre!



Primero, establecemos el tipo de datos de salida, así como los límites de los datos. Los bordes se establecen de acuerdo con el tamaño de la imagen, y además desde la parte inferior he espaciado 256 caracteres a lo largo del eje Z para que la proyección de la imagen sea visible. A continuación, encabezamos el gráfico, etiquetamos los ejes. Usando el comando de teclado desarmado, desactivo las leyendas (no es necesario en el gráfico). ¡Y aquí viene la verdadera magia!



establecer paleta gris : configuramos la paleta. Si se deja como predeterminado, el gráfico se coloreará como en una cámara termográfica. Cuanto más alta, más amarilla es la mancha, más baja es la roja.



establecer hidden3d- por así decirlo, estira la superficie curva (elimina las líneas), formando así una hermosa superficie convexa.



establecer pm3d en bs : active el estilo de dibujo de datos 3D, que dibuja datos con una cuadrícula y un color. Lea más en la documentación, una descripción más detallada está más allá del alcance del artículo.



set dgrid3d 100,100 qnorm 2 : establece el tamaño de las celdas de la cuadrícula en 100x100 y el suavizado entre las celdas. El valor 100x100 ya es muy grande y el programa es muy lento. qnorm 2 es anti-aliasing (interpolación de datos entre celdas).



splot "./res.txt" con l - dibuja el gráfico resultante. "Con l" significa dibujar el gráfico con líneas. Este es un pequeño truco, porque los puntos son visibles en el gráfico (se pueden establecer pequeños puntos).



Después del lanzamiento, esperamos un tiempo y obtenemos un "bajorrelieve" poligonal. Intente experimentar con la configuración para obtener otras opciones de representación.





La imagen está en modo de comando después de ser girada.



Inmediatamente me viene a la mente una anécdota.

¿Cómo encontrar la plaza Lenin?

Solo una persona sin educación responderá a esta pregunta, que es necesario multiplicar la altura de Lenin por la anchura de Lenin.

Una persona educada sabe tomar una integral sobre una superficie.


Usando gnuplot en sus programas



El ejemplo está tomado de stackoverflow con mis modificaciones menores.



El código genera un archivo de texto y constantemente hace que se reconstruya el gráfico. Adjuntaré el código debajo del spoiler para no romper el artículo.



Ejemplo de código C usando gnuplot
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>


float s=10.;
float r=28.;
float b=8.0/3.0;
/* Definimos las funciones */
float f(float x,float y,float z){
    return s*(y-x);
}
float g(float x,float y,float z){
    return x*(r-z)-y;
}
float h(float x,float y,float z){
    return x*y-b*z;
}
FILE *output;
FILE *gp;

int main(){
    gp = popen("gnuplot -","w");
    output = fopen("lorenzgplot.dat","w");
    float t=0.; 
    float dt=0.01;
    float tf=30;
    float x=3.;
    float y=2.;
    float z=0.;
    float k1x,k1y,k1z, k2x,k2y,k2z,k3x,k3y,k3z,k4x,k4y,k4z;
    fprintf(output,"%f %f %f \n",x,y,z);
    fprintf(gp, "splot './lorenzgplot.dat' with lines \n");
/* Ahora Runge Kutta de orden 4 */  
    while(t<tf){
        /* RK4 paso 1 */
        k1x = f(x,y,z)*dt;
        k1y = g(x,y,z)*dt;
        k1z = h(x,y,z)*dt;
        /* RK4 paso 2 */
        k2x = f(x+0.5*k1x,y+0.5*k1y,z+0.5*k1z)*dt;
        k2y = g(x+0.5*k1x,y+0.5*k1y,z+0.5*k1z)*dt;
        k2z = h(x+0.5*k1x,y+0.5*k1y,z+0.5*k1z)*dt;
        /* RK4 paso 3 */
        k3x = f(x+0.5*k2x,y+0.5*k2y,z+0.5*k2z)*dt;
        k3y = g(x+0.5*k2x,y+0.5*k2y,z+0.5*k2z)*dt;
        k3z = h(x+0.5*k2x,y+0.5*k2y,z+0.5*k2z)*dt;
        /* RK4 paso 4 */
        k4x = f(x+k3x,y+k3y,z+k3z)*dt;
        k4y = g(x+k3x,y+k3y,z+k3z)*dt;
        k4z = h(x+k3x,y+k3y,z+k3z)*dt;
        /* Actualizamos las variables y el tiempo */
        x += (k1x/6.0 + k2x/3.0 + k3x/3.0 + k4x/6.0);
        y += (k1y/6.0 + k2y/3.0 + k3y/3.0 + k4y/6.0);
        z += (k1z/6.0 + k2z/3.0 + k3z/3.0 + k4z/6.0);
        /* finalmente escribimos sobre el archivo */

        fprintf(output,"%f %f %f \n",x,y,z);
        fflush(output); 
        usleep(10000);
        fprintf(gp, "replot \n");
        fflush(gp);
        t += dt;
    }
    fclose(gp);
    fclose(output);
    return 0;
}




El código funciona de manera muy simple, abrimos una tubería:



gp = popen("gnuplot -","w");


Esto es similar a la barra vertical en bash, cuando escribimos otro comando después de un comando, solo dentro del programa. Escribimos los datos en el archivo lorenzgplot.dat. Llame al comando splot en gnuplot una vez:



fprintf(gp, "splot './lorenzgplot.dat' with lines \n");


Y luego, al agregar un nuevo punto, reconstruimos el gráfico.



fprintf(gp, "replot \n");


Como resultado, obtenemos una construcción lenta muy agradable del Atractor de Lorenz. A continuación se muestra un video tomado hace casi diez años con una cámara vieja, así que no jure demasiado. Lo importante del video es que todo funciona muy bien en un hardware tan antiguo como el Nokia N800. Es deseable verlo sin sonido.







Es importante entender que el comando replot consume muy bien la memoria y el tiempo del procesador, es decir, tal trazado no ralentiza tanto el sistema. Entonces, con todo el amor por gnuplot, esta no es la mejor manera de usarlo. Otro problema es que esta ventana no se puede cerrar ni mover.



Conclusión



Finalmente, quiero mostrar un video en el que recopilé cientos de gráficos de la distribución logarítmica aleatoria de registros de partículas radiactivas, datos reales de un estudio. El video puede y debe verse con sonido.







En este artículo, no pude decir ni una milésima parte de las capacidades de este plotter, excepto que familiaricé un poco al lector con este programa. A continuación, debe buscar ejemplos usted mismo, leer la documentación en el sitio web oficial gnuplot.sourceforge.net o www.gnuplot.info . Asegúrese de mirar los ejemplos, hay muchas cosas interesantes y útiles.



Para empezar, también puedo recomendar una breve introducción a gnuplot (rus) . Estoy sinceramente sorprendido de que un programa tan maravilloso no se estudie en todas las universidades técnicas a la par con Latex. Por alguna razón, nos enseñaron MS Excel y Word.



Aprender gnuplot no es difícil, pasé literalmente unos días tratando de resolverlo desde cero. Pero con este artículo, creo que todo será más rápido para ti. Ahora me olvidé de los trazadores Exel / Calc, solo uso gnuplot. Además, ni siquiera conozco una décima parte de todas las posibilidades de trazar gráficos.



Quiero señalar que hay muchos otros trazadores, no peores que gnuplot, sobre todo porque es bastante antiguo. Pero para mí, gnuplot resultó ser el más simple y completo. Además, es el trazador más común y hay una gran cantidad de ejemplos de su uso en la web. ¡Gracias por leer!






All Articles