diff options
Diffstat (limited to 'gnuplot.c')
-rw-r--r-- | gnuplot.c | 132 |
1 files changed, 132 insertions, 0 deletions
diff --git a/gnuplot.c b/gnuplot.c new file mode 100644 index 0000000..e4fb1c0 --- /dev/null +++ b/gnuplot.c @@ -0,0 +1,132 @@ +#include "gnuplot.h" +#include <string.h> +#include <stdarg.h> + +/** + * Open a new gnuplot handle + * @return stream on success, or NULL on error + */ +FILE *gnuplot_open() { + // -p = persistent window after exit + //return popen("gnuplot --persist", "w"); + return popen("gnuplot -p", "w"); +} + +/** + * Close a gnuplot handle + * @param fp pointer to gnuplot stream + * @return 0 on success, or <0 on error + */ +int gnuplot_close(FILE *fp) { + return pclose(fp); +} + +/** + * Wait for plot window to exit + * @param fp pointer to gnuplot stream + * @return value of `gnuplot_sh` + */ +int gnuplot_wait(FILE *fp) { + return gnuplot_sh(fp, "pause mouse close\n"); +} + +/** + * Send shell command to gnuplot instance + * @param fp pointer to gnuplot stream + * @param fmt command to execute (requires caller to end string with a LF "\n") + * @param ... formatter arguments + * @return value of `vfprintf()`. <0 on error + */ +int gnuplot_sh(FILE *fp, char *fmt, ...) { + int status; + + va_list args; + va_start(args, fmt); + status = vfprintf(fp, fmt, args); + //fprintf(stdout, fmt, args); + va_end(args); + + return status; +} + +/** + * Generate a plot + * Each GNUPLOT_PLOT pointer in the `gp` array corresponds to a line. + * @param fp pointer to gnuplot stream + * @param gp pointer to an array of GNUPLOT_PLOT structures + * @param x an array representing the x axis + * @param y an array of double-precision arrays representing the y axes + * @param x_count total length of array x + * @param y_count total number of arrays in y + */ +void gnuplot_plot(FILE *fp, struct GNUPLOT_PLOT **gp, double x[], double *y[], size_t x_count, size_t y_count) { + // Configure plot + gnuplot_sh(fp, "set title '%s'\n", gp[0]->title); + gnuplot_sh(fp, "set xlabel '%s'\n", gp[0]->xlabel); + gnuplot_sh(fp, "set ylabel '%s'\n", gp[0]->ylabel); + if (gp[0]->grid_toggle) { + gnuplot_sh(fp, "set grid\n"); + if (gp[0]->grid_mxtics || gp[0]->grid_mytics) { + gnuplot_sh(fp, "set mytics %zu\n", gp[0]->grid_mytics); + gnuplot_sh(fp, "set mxtics %zu\n", gp[0]->grid_mxtics); + gnuplot_sh(fp, "set grid mxtics mytics\n"); + } + } + if (gp[0]->autoscale_toggle) + gnuplot_sh(fp, "set autoscale\n"); + if (gp[0]->legend_toggle) { + gnuplot_sh(fp, "set key nobox\n"); + //gnuplot_sh(fp, "set key bmargin\n"); + gnuplot_sh(fp, "set key font ',5'\n"); + gnuplot_sh(fp, "set key outside\n"); + } + if (gp[0]->legend_enhanced) { + gnuplot_sh(fp, "set key enhanced\n"); + } else { + gnuplot_sh(fp, "set key noenhanced\n"); + } + + // Begin plotting + gnuplot_sh(fp, "plot "); + for (size_t i = 0; i < y_count; i++) { + char pltbuf[1024] = {0}; + sprintf(pltbuf, "'-' "); + if (gp[0]->legend_toggle) { + sprintf(pltbuf + strlen(pltbuf), "title '%s' ", gp[i]->legend_title); + sprintf(pltbuf + strlen(pltbuf), "with lines "); + if (gp[i]->line_width) { + sprintf(pltbuf + strlen(pltbuf), "lw %0.1f ", gp[i]->line_width); + } + if (gp[i]->line_type) { + sprintf(pltbuf + strlen(pltbuf), "lt %s ", gp[i]->line_type); + } + if (gp[i]->line_color) { + sprintf(pltbuf + strlen(pltbuf), "lc rgb '#%06x' ", gp[i]->line_color); + } + gnuplot_sh(fp, "%s ", pltbuf); + } else { + gnuplot_sh(fp, "with lines "); + } + if (i < y_count - 1) { + gnuplot_sh(fp, ", "); + } + } + gnuplot_sh(fp, "\n"); + + // Emit MSTAT data + for (size_t arr = 0; arr < y_count; arr++) { + for (size_t i = 0; i < x_count; i++) { + gnuplot_sh(fp, "%lf %lf\n", x[i], y[arr][i]); + } + // Commit plot and execute + gnuplot_sh(fp, "e\n"); + } + fflush(fp); +} + +unsigned int gnuplot_rgb(unsigned char r, unsigned char g, unsigned char b) { + unsigned int result = r; + result = result << 8 | g; + result = result << 8 | b; + return result; +}
\ No newline at end of file |