refactor a bit - ploot - simple plotting tools (HTM) git clone git://bitreich.org/ploot git://enlrupgkhuxnvlhsf6lc3fziv5h2hhfrinws65d7roiv6bfj7d652fid.onion/ploot (DIR) Log (DIR) Files (DIR) Refs (DIR) Tags (DIR) README (DIR) LICENSE --- (DIR) commit a2f50e1cb8af6ef5571c142b93b8ade388e0bfa5 (DIR) parent 1f4e757723ea483ab2c60c8fec2937569441af9e (HTM) Author: Josuah Demangeon <me@josuah.net> Date: Tue, 18 Feb 2020 08:33:24 +0100 refactor a bit Diffstat: M def.h | 48 +++++++------------------------ M drawille.c | 58 +++++++++++++++++++++++-------- M ploot-braille.c | 106 +++++++++---------------------- M ploot-farbfeld.c | 8 ++++---- M ploot-feed.c | 6 +++--- M test.csv | 1 + M util.c | 46 ------------------------------- 7 files changed, 90 insertions(+), 183 deletions(-) --- (DIR) diff --git a/def.h b/def.h @@ -35,62 +35,34 @@ struct vlist { char *label; /* for the legend */ }; -/* csv.c */ - +/**/ void csv_addrow (struct vlist *, size_t, char *); void csv_labels (FILE *, char *, struct vlist **, size_t *); void csv_values (FILE *, struct vlist *, size_t); - -/* drawille.c */ - -size_t drawille_fmt_row (struct drawille *, char *, size_t, int); +size_t drawille_put_row (struct drawille *, FILE *, int); void drawille_dot (struct drawille *, int, int); struct drawille *drawille_new (int, int); void drawille_line (struct drawille *, int, int, int, int); -void drawille_line_hist (struct drawille *, int, int, int, int, int); -void drawille_dot_hist (struct drawille *, int, int, int); +void drawille_histogram_dot (struct drawille *, int, int, int); +void drawille_histogram_line (struct drawille *, int, int, int, int, int); +int drawille_histogram (struct vlist *, struct drawille *, time_t, time_t, double, double); char * drawille_text (struct drawille *, int, int, struct font *, char *); - -/* font.c */ - size_t font_width (struct font *, int); size_t font_strlen (struct font *, char *); - -/* font*.c */ - -struct font font13; -struct font font7; -struct font font8; - -/* ploot-braille.c */ - +struct font font13; +struct font font7; +struct font font8; char const *arg0; - -/* ploot-farbfeld.c */ - -char const *arg0; - -/* ploot-feed.c */ - -char const *arg0; - -/* scale.c */ - int scale_ypos (double, double, double, int); int scale_xpos (time_t, time_t, time_t, int); void scale_vminmax (double *, double *, int); void scale (struct vlist *, int, time_t *, time_t *, time_t *, double *, double *, double *); - -/* util.c */ - size_t strlcpy (char *, const char *, size_t); void put3utf (long); char * strsep (char **, const char *); void estriplf (char *); double eatof (char *); long eatol (char *); -char * esfgets (char *, size_t, FILE *); int humanize (char *, double); -void vlog (char const *, char const *, va_list); -void warn (char const *, ...); -void err (int, char const *, ...); + +#endif (DIR) diff --git a/drawille.c b/drawille.c @@ -6,6 +6,7 @@ #include <stdio.h> #include <stdlib.h> #include <string.h> +#include <math.h> #include "def.h" @@ -52,7 +53,7 @@ drawille_get(struct drawille *drw, int row, int col) } size_t -drawille_fmt_row(struct drawille *drw, char *buf, size_t sz, int row) +drawille_put_row(struct drawille *drw, FILE *fp, int row) { char txt[] = "xxx"; size_t n; @@ -60,7 +61,7 @@ drawille_fmt_row(struct drawille *drw, char *buf, size_t sz, int row) n = 0; for (int col = 0; col < drw->col; col++) { drawille_cell_utf(drawille_get(drw, row, col), txt); - n += snprintf(buf+n, sz-n, "%s", txt); + n += fputs(txt, fp); } return n; } @@ -111,7 +112,7 @@ drawille_line_next(struct line *l) int e; if (l->x0 == l->x1 && l->y0 == l->y1) - return -1; + return 0; e = l->err; if (e > -l->dx) { @@ -122,7 +123,7 @@ drawille_line_next(struct line *l) l->y0 += l->sy; l->err += l->dx; } - return 0; + return 1; } void @@ -137,27 +138,54 @@ drawille_line(struct drawille *drw, int x0, int y0, int x1, int y1) } void -drawille_line_hist(struct drawille *drw, int x0, int y0, int x1, int y1, int zero) +drawille_histogram_dot(struct drawille *drw, int x, int y, int zero) { - struct line l; int sign; + sign = (y > zero) ? (+1) : (-1); + for (; y != zero + sign; y -= sign) + drawille_dot(drw, x, y); +} + +void +drawille_histogram_line(struct drawille *drw, int x0, int y0, int x1, int y1, int zero) +{ + struct line l; + drawille_line_init(&l, x0, y0, x1, y1); do { - sign = (l.y0 > zero) ? (-1) : (+1); - for (int y = l.y0; y != zero + sign; y += sign) - drawille_dot(drw, l.x0, y); + drawille_histogram_dot(drw, l.x0, l.y0, zero); } while (drawille_line_next(&l)); } -void -drawille_dot_hist(struct drawille *drw, int x, int y, int zero) +/* + * Plot the body as an histogram interpolating the gaps and include + * a vertical and horizontal axis. + */ +int +drawille_histogram(struct vlist *vl, struct drawille *drw, + time_t tmin, time_t tmax, double vmin, double vmax) { - int sign; + int x, xprev, y, yprev, zero; + double *v; + time_t *t; + size_t n; - sign = (y > zero) ? (-1) : (+1); - for (; y != zero + sign; y += sign) - drawille_dot(drw, x, y); + zero = scale_ypos(0, vmin, vmax, drw->row*4); + v = vl->v; + t = vl->t; + n = vl->n; + for (; n > 0; n--, t++, v++) { + if (isnan(*v)) /* XXX: better handling? */ + continue; + y = scale_ypos(*v, vmin, vmax, drw->row * 4); + x = scale_xpos(*t, tmin, tmax, drw->col * 2); + if (n < vl->n) + drawille_histogram_line(drw, xprev, yprev, x, y, zero); + xprev = x; + yprev = y; + } + return 0; } static int (DIR) diff --git a/ploot-braille.c b/ploot-braille.c @@ -12,61 +12,43 @@ char const *arg0 = NULL; -/* - * Return the step between two values. - */ static int -braille_time_interval(time_t step) +braille_axis_x(FILE *fp, time_t tmin, time_t tmax, time_t tstep, int col) { - time_t scale[] = { - 1, 5, 2, 10, 20, 30, 60, 60*2, 60*5, 60*10, 60*20, 60*30, - 3600, 3600*2, 3600*5, 3600*10, 3600*18, 3600*24, 3600*24*2, - 3600*24*5, 3600*24*10, 3600*24*20, 3600*24*30, 3600*24*50, - 3600*24*100, 3600*24*365, 0 - }; - - for (time_t *s = scale; *s != 0; s++) - if (*s >= 20 * step) - return *s; - return 1; -} - -static size_t -braille_axis_x(FILE *fp, time_t step, time_t tmax, int col) -{ - int x, prec; + int x, o, prec; char tmp[sizeof("MM/DD HH:MM")], *fmt; size_t n; - time_t t, interval; + time_t t; - interval = braille_time_interval(step); - fmt = (step < 3600 * 12) ? "^%H:%M:%S" : - (step < 3600 * 24) ? "^%m/%d %H:%M" : + fmt = (tstep < 3600 * 12) ? "^%H:%M:%S" : + (tstep < 3600 * 24) ? "^%m/%d %H:%M" : "^%Y/%m/%d"; n = x = 0; - t = tmax - col * 2 * step; - t += interval - t % interval; - for (; t < tmax; t += interval) { + t = tmin; + t += tstep - t % tstep; + for (; t < tmax; t += tstep) { + x = (t - tmin) * col / (tmax - tmin); strftime(tmp, sizeof tmp, fmt, localtime(&t)); - x = ((t - tmax) / 2 + col * step) / step; prec = x - n + strlen(tmp); - fprintf(fp, "%*s", prec, tmp); + if ((o = fprintf(fp, "%*s", prec, tmp)) < 0) + return -1; + n += o; } fputc('\n', fp); - return 1; + return 0; } /* * Plot a single line out of the y axis, at row <r> out of <rows>. */ static void -braille_axis_y(FILE *fp, double min, double max, int r, int rows) +braille_axis_y(FILE *fp, double vmin, double vmax, int r, int rows) { char tmp[10] = "", *s; double val; - val = (max - min) * (rows - r) / rows + min; + val = (rows - r) * (vmax - vmin) / rows; humanize(tmp, val); s = (r == 0) ? "┌" : (r == rows - 1) ? "└" : @@ -75,70 +57,40 @@ braille_axis_y(FILE *fp, double min, double max, int r, int rows) } static int -braille_render(struct drawille *drw, FILE *fp, time_t tmin, time_t tmax) +braille_render(struct drawille *drw, FILE *fp, double vmin, double vmax) { - char buf[LINE_MAX]; - /* Render the plot line by line. */ for (int row = 0; row < drw->row; row++) { - drawille_fmt_row(drw, buf, sizeof buf, row); - braille_axis_y(fp, tmin, tmax, row, drw->row); + drawille_put_row(drw, fp, row); + braille_axis_y(fp, vmin, vmax, row, drw->row); fputc('\n', fp); } return 0; } -/* - * Plot the body as an histogram interpolating the gaps and include - * a vertical and horizontal axis. - */ -static int -braille_hist(struct vlist *vl, FILE *fp, time_t tmin, time_t tmax, int row, int col) -{ - int x, y, zero, shift; - double *v, vmin, vmax; - time_t *t; - size_t n; - struct drawille *drw; - - if ((drw = drawille_new(row, col)) == NULL) - err(1, "allocating drawille canvas"); - - shift = (drw->row > 1) ? (2) : (0); /* center values on "|-" marks */ - vmin = vmax = 0; - zero = scale_ypos(0, vmin, vmax, drw->row*4) - shift; - v = vl->v; - t = vl->t; - n = vl->n; - for (; n > 0; n--, t++, v++) { - if (isnan(*v)) /* XXX: better handling? */ - continue; - y = scale_ypos(*v, vmin, vmax, drw->row * 4) - shift; - x = scale_xpos(*t, tmin, tmax, drw->col * 2); - drawille_dot_hist(drw, x, y, zero); - } - if (braille_render(drw, fp, tmin, tmax) == -1) - err(1, "rendering braille canvas"); - free(drw); - return 0; -} - -static int +static void plot(struct vlist *vl, FILE *fp, size_t ncol, int row, int col) { size_t len; double vmin, vmax, vstep; time_t tmin, tmax, tstep; + struct drawille *drw; len = 500; col -= 8; scale(vl, ncol, &tmin, &tmax, &tstep, &vmin, &vmax, &vstep); + warn("vstep=%lf vstep=%ld", vstep, tstep); - if (braille_hist(vl, fp, tmin, tmax, row, col) == -1) + if ((drw = drawille_new(row, col)) == NULL) err(1, "allocating drawille canvas"); - braille_axis_x(fp, tstep, tmax, col); - return 0; + if (drawille_histogram(vl, drw, tmin, tmax, vmin, vmax) == -1) + err(1, "allocating drawille canvas"); + if (braille_render(drw, fp, vmin, vmax) == -1) + err(1, "rendering braille canvas"); + if (braille_axis_x(fp, tmin, tmax, tstep, col) == -1) + err(1, "printing x axis");; + free(drw); } static void (DIR) diff --git a/ploot-farbfeld.c b/ploot-farbfeld.c @@ -65,10 +65,10 @@ struct canvas { struct color *buf; }; -char const *arg0 = NULL; -static char *tflag = ""; -static char *uflag = ""; -static struct font *font = &font13; +char const *arg0 = NULL; +static char *tflag = ""; +static char *uflag = ""; +static struct font *font = &font13; static struct cname cname[] = { /* name red green blue alpha */ (DIR) diff --git a/ploot-feed.c b/ploot-feed.c @@ -13,9 +13,9 @@ #define WIDTH_MAX 1024 #define BRAILLE_START 10240 -char const *arg0 = NULL; -static int wflag = 80; -static int width = 0; +char const *arg0 = NULL; +static int wflag = 80; +static int width = 0; /* * Turn the bit at position (row, col) on in the . (DIR) diff --git a/test.csv b/test.csv @@ -109,5 +109,6 @@ epoch,shortterm,midterm,longterm 1525294298,0.278198,0.260864,0.242920 1525295198,0.192505,0.183716,0.200806 1525296098,0.109375,0.185669,0.207153 +1525296098,-0.109375,0.185669,0.207153 1525296998,0.137085,0.126221,0.138184 1525297898,0.077881,0.092529,0.109619 (DIR) diff --git a/util.c b/util.c @@ -77,19 +77,6 @@ eatol(char *str) return atol(str); } -char * -esfgets(char *buf, size_t n, FILE *file) -{ - if (fgets(buf, n, file) == NULL) { - if (ferror(stdin)) - perror("fread from stdin"), exit(1); - else - return NULL; - } - estriplf(buf); - return buf; -} - /* * Set 'str' to a human-readable form of 'num' with always a width of 8 (+1 for * the '\0' terminator). Buffer overflow is ensured not to happen due to the @@ -114,36 +101,3 @@ humanize(char *str, double val) return exp * 3; } - -void -vlog(char const *base, char const *fmt, va_list va) -{ - fprintf(stderr, "%s: ", base); - vfprintf(stderr, fmt, va); - if (errno) - fprintf(stderr, ": %s", strerror(errno)); - fputc('\n', stderr); - fflush(stderr); - errno = 0; /* avoid repeating the error in loop */ -} - -void -warn(char const *fmt, ...) -{ - va_list va; - - va_start(va, fmt); - vlog(arg0, fmt, va); - va_end(va); -} - -void -err(int e, char const *fmt, ...) -{ - va_list va; - - va_start(va, fmt); - vlog(arg0, fmt, va); - va_end(va); - exit(e); -}