Hacer que el código C trace un gráfico automáticamente
⏰ 6 minutos de lectura
JMzance
He escrito un programa que escribe una lista de datos en un archivo ‘.dat’ con la intención de trazarlo por separado usando gnuplot. ¿Hay alguna manera de hacer que mi código lo trace automáticamente? Mi salida es de la forma:
Idealmente, cuando ejecuto el código, el gráfico también se imprimiría con una etiqueta x, una etiqueta y y un título (que podría cambiarse de mi código C). Muchas gracias.
Tal vez echa un vistazo a la system función.
– sje397
19 de agosto de 2010 a las 11:23
Ben B
Encontré esto mientras buscaba algo más sobre gnuplot. Aunque es una pregunta antigua, pensé en contribuir con un código de muestra. Lo uso para un programa mío, y creo que hace un trabajo bastante ordenado. AFAIK, este PIPEing solo funciona en sistemas Unix (consulte la edición a continuación para usuarios de Windows). Mi instalación de gnuplot es la instalación predeterminada del repositorio de Ubuntu.
#include <stdlib.h>
#include <stdio.h>
#define NUM_POINTS 5
#define NUM_COMMANDS 2
int main()
{
char * commandsForGnuplot[] = {"set title \"TITLEEEEE\"", "plot 'data.temp'"};
double xvals[NUM_POINTS] = {1.0, 2.0, 3.0, 4.0, 5.0};
double yvals[NUM_POINTS] = {5.0 ,3.0, 1.0, 3.0, 5.0};
FILE * temp = fopen("data.temp", "w");
/*Opens an interface that one can use to send commands as if they were typing into the
* gnuplot command line. "The -persistent" keeps the plot open even after your
* C program terminates.
*/
FILE * gnuplotPipe = popen ("gnuplot -persistent", "w");
int i;
for (i=0; i < NUM_POINTS; i++)
{
fprintf(temp, "%lf %lf \n", xvals[i], yvals[i]); //Write the data to a temporary file
}
for (i=0; i < NUM_COMMANDS; i++)
{
fprintf(gnuplotPipe, "%s \n", commandsForGnuplot[i]); //Send commands to gnuplot one by one.
}
return 0;
}
EDITAR
En mi aplicación, también me encontré con el problema de que la trama no aparece hasta que se cierra el programa de llamada. Para evitar esto, agregue un fflush(gnuplotPipe) después de haber usado fprintf para enviarle su comando final.
También he visto que los usuarios de Windows pueden usar _popen en lugar de popen — sin embargo, no puedo confirmar esto porque no tengo Windows instalado.
EDITAR 2
Uno puede evitar tener que escribir en un archivo enviando gnuplot el plot '-' comando seguido de puntos de datos seguidos de la letra “e”.
p.ej
fprintf(gnuplotPipe, "plot '-' \n");
int i;
for (int i = 0; i < NUM_POINTS; i++)
{
fprintf(gnuplotPipe, "%lf %lf\n", xvals[i], yvals[i]);
}
fprintf(gnuplotPipe, "e");
Sé que ha pasado mucho tiempo desde que se publicó esta respuesta, pero usé el código de su segunda edición más el bucle for con el commandsForGnuplot en él para agregar comandos, y traza pero no agrega ninguno de los comandos (título, xlabel o ylabel). ¿Cómo puedo agregarlos si no es así? Por favor.
– MO
22/09/2017 a las 19:34
Si alguien encuentra un ‘-‘ y un punto adicional en el gráfico, en realidad no son puntos trazados. Son parte de la leyenda. Hacer fprintf(gnuplotPipe, "plot '-' notitle\n"); y desaparecerían.
-Tommy Wolfheart
21 de marzo a las 10:36
Puede crear un script gnuplot y generar un proceso que ejecute gnuplot para trazar este script desde la línea de comandos, o puede usar una de las interfaces provistas. Para C, hay una interfaz basada en tubería POSIX de Nicolas Devillard disponible aquí: http://ndevilla.free.fr/gnuplot/
…y una versión de C++ basada en iostream está disponible a través de git (ver: http://www.stahlke.org/dan/gnuplot-iostream/ )
Sin embargo, la forma más portátil y probablemente la más fácil sería llamar a gnuplot para trazar un script. Como se mencionó en sje397, consulte su documentación para la llamada system() en stdlib.h.
En una nota al margen, también está GNU plotutils, que ofrece libplot, una biblioteca para trazar conjuntos de datos, que podría usar en su aplicación. Ver: http://www.gnu.org/software/plotutils/
No soy fantástico para entender todo este material de documentación, pero encontré la declaración para system(): int system(const char *command); ¿Es entonces solo un caso de agregar algo como esto?: system(gnuplot plot “data_set.dat” with 1:2 using lines);
– JMzance
19 de agosto de 2010 a las 11:54
Al final opté por algo como esto:
– JMzance
23 de septiembre de 2010 a las 11:56
#include “gnuplot_i.h” int main(void) { ARCHIVO archivo de salida; outFile = fopen(“Flight_Path.dat”, “w”); / Bucle iterativo que imprime en el archivo de salida: ejemplo.dat */ fclose(outFile); gnuplot_ctrl *k; k = gnuplot_init(); gnuplot_set_xlabel(k, “x”); gnuplot_set_ylabel(k, “y”); gnuplot_cmd(k,entrada_x); gnuplot_cmd(k,entrada_y); gnuplot_cmd(k, “establecer título \”Trayectoria con arrastre\””); gnuplot_cmd(k, “trazar \”Flight_Path.dat\” usando el título 1:2 \”Flight Path\” con líneas, \ sleep(7); gnuplot_close(k); return 0; }
– JMzance
23 de septiembre de 2010 a las 12:00
Estoy seguro de que le faltan algunos bits de ese código, es decir, está abriendo y cerrando el archivo inmediatamente después. Además, el formato en los comentarios simplemente apesta. Edite su publicación original y agregue código a eso; lo haría yo mismo, pero como dije, creo que a su código le falta algo.
-Jim Brissom
23 de septiembre de 2010 a las 21:50
Nidish Narayanaa
Aunque he visto muchas maneras de hacer esto, la forma más sencilla de hacerlo sería usando la función system() (de stdlib.h) en C. Primero haga un script gnuplot y guárdelo como “name. gp” (ni el nombre ni la extensión importan).
Un guión simple sería,
plot 'Output.dat' with lines
Después de guardar este archivo de script, simplemente agregue system("gnuplot -p name.gp");
al final de su código.
Es tan simple como eso.
Asegúrese de agregar la ruta gnuplot a las variables de ruta del sistema de Windows.
He adaptado la respuesta aceptada para trazar una matriz flotante y evitar el uso de un archivo temporal. En eso, float* data_ es la matriz y size_t size_ su tamaño. ¡Ojalá sea útil para alguien!
Salud,
Andrés
void plot(const char* name="FloatSignal"){
// open persistent gnuplot window
FILE* gnuplot_pipe = popen ("gnuplot -persistent", "w");
// basic settings
fprintf(gnuplot_pipe, "set title '%s'\n", name);
// fill it with data
fprintf(gnuplot_pipe, "plot '-'\n");
for(size_t i=0; i<size_; ++i){
fprintf(gnuplot_pipe, "%zu %f\n", i, data_[i]);
}
fprintf(gnuplot_pipe, "e\n");
// refresh can probably be omitted
fprintf(gnuplot_pipe, "refresh\n");
}
Sé que es demasiado tarde, pero responder si puede ayudar a alguien. fputs realmente hace el trabajo que quieres. primero debe imprimir los datos que desea trazar en un archivo temporal data.temp.
Esta web utiliza cookies propias y de terceros para su correcto funcionamiento y para fines analíticos y para mostrarte publicidad relacionada con sus preferencias en base a un perfil elaborado a partir de tus hábitos de navegación. Al hacer clic en el botón Aceptar, acepta el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos.
Configurar y más información
Tal vez echa un vistazo a la
system
función.– sje397
19 de agosto de 2010 a las 11:23