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);
-}