plotting time series - ploot - simple plotting tools HTML git clone git://bitreich.org/ploot git://enlrupgkhuxnvlhsf6lc3fziv5h2hhfrinws65d7roiv6bfj7d652fid.onion/ploot DIR Log DIR Files DIR Refs DIR Tags DIR README DIR LICENSE --- DIR commit 51d676a1197f90fba3e657a875ad3905b95646a2 DIR parent 413abf823787458e35396a700f9acf1af53ef239 HTML Author: Josuah Demangeon <mail@josuah.net> Date: Tue, 6 Feb 2018 23:03:45 +0100 plotting time series Diffstat: M ploot.c | 77 +++++++++++++++++++++++-------- 1 file changed, 59 insertions(+), 18 deletions(-) --- DIR diff --git a/ploot.c b/ploot.c @@ -12,8 +12,8 @@ #define ABS(x) ((x) < 0 ? -(x) : (x)) #define MIN(x, y) ((x) < (y) ? (x) : (y)) -#define LEN(x) (sizeof(x) / sizeof(*x)) - +#define MAX(x, y) ((x) > (y) ? (x) : (y)) +#define LEN(buf) (sizeof(buf) / sizeof(*(buf))) /* * Add `val' at the current position `pos' of the `ring' buffer and set pos to @@ -37,6 +37,7 @@ do { \ int flag_h = 20; char *flag_t = NULL; +time_t flag_o = 0; /* * Set `str' to a human-readable form of `num' with always a width of 7 (+ 1 @@ -108,11 +109,13 @@ vaxis(double val, int pos) * Print horizontal axis for up to `col' values. */ void -haxis(int col) +haxis(double *beg, double *end) { + double *tp; + printf("%*d -+", MARGIN, 0); - while (col-- > 0) - putchar('-'); + for (tp = beg; tp < end; tp++) + putchar((*tp < 0) ? ('x') : ('-')); putchar('\n'); } @@ -151,7 +154,7 @@ plot(int height, double *beg, double *end, char *str) vaxis(top, h); line(beg, end, top, bot); } - haxis(end - beg); + haxis(beg, end); } /* @@ -169,7 +172,6 @@ read_simple(double buf[MAX_VAL]) for (p = pos = 0; scanf("%lf\n", &val) > 0; p++) RING_ADD(rbuf, len, pos, val); len = MIN(len, p); - pos = MIN(pos, p); RING_COPY(buf, rbuf, len, pos); @@ -182,43 +184,75 @@ read_simple(double buf[MAX_VAL]) * least MAX_VAL wide and return a pointer to the last element of `vbuf' or NULL if the * input contains error. */ -double * +time_t * read_time_series(double *vbuf, time_t *tbuf) { - size_t p, pos, len; + size_t p, pos, nul, len; double vrbuf[MAX_VAL], vval; time_t trbuf[MAX_VAL], tval; len = LEN(vrbuf); - for (p = pos = 0; scanf("%zd %lf\n", &tval, &vval) > 0; p++) + for (p = pos = 0; scanf("%zd %lf\n", &tval, &vval) > 0; p++) { RING_ADD(trbuf, len, pos, tval); - RING_ADD(vrbuf, len, pos, vval); + RING_ADD(vrbuf, len, nul, vval); + } len = MIN(len, p); - pos = MIN(pos, p); RING_COPY(tbuf, trbuf, len, pos); RING_COPY(vbuf, vrbuf, len, pos); + return tbuf + len; +} + +/* + * Walk from `tbeg' and `tend' and add offset in `tbuf' every time there is no + * value in `step' amount of time, by setting a value to -1. + */ +double * +fill_gaps(time_t *tbeg, time_t *tend, double *vbuf, time_t step) +{ + size_t p, pos, len; + time_t *tp, toff; + double *vp, vrbuf[MAX_VAL]; + + /* Compute the average alignment of the timestamps values according to + * the step size. */ + toff = 0; + for (tp = tbeg; tp < tend; tp++) + toff += *tp % step; + toff = *tbeg + toff / (tend - tbeg) + step / 2; + + /* Fill `vbuf' with gap added at each time gap using vrbuf as + * intermediate ring buffer. */ + len = LEN(vrbuf); + for (p = pos = 0, tp = tbeg, vp = vbuf; tp < tend; p++, vp++, tp++) { + for (; toff < *tp; toff += step) + RING_ADD(vrbuf, len, pos, -1); + RING_ADD(vrbuf, len, pos, *vp); + toff += step; + } + len = MAX(MIN(p, len), pos); + + RING_COPY(vbuf, vrbuf, len, pos); + return vbuf + len; } void usage(void) { - printf("usage: ploot [-h <height>] [-t <title>]\n"); + printf("usage: ploot [-h <height>] [-t <title>] -o <offset>\n"); exit(1); } int main(int argc, char **argv) { -/* - time_t tbuf[MAX_VAL]; -*/ + time_t tbuf[MAX_VAL], *tend; double vbuf[MAX_VAL], *vend; char c; - while ((c = getopt(argc, argv, "h:t:")) != -1) { + while ((c = getopt(argc, argv, "h:t:o:")) != -1) { switch (c) { case -1: break; @@ -229,12 +263,19 @@ main(int argc, char **argv) case 't': flag_t = optarg; break; + case 'o': + flag_o = atol(optarg); + break; default: usage(); } } + if (flag_o == 0) + usage(); + + tend = read_time_series(vbuf, tbuf); + vend = fill_gaps(tbuf, tend, vbuf, flag_o); - vend = read_simple(vbuf); plot(flag_h, vbuf, vend, flag_t); return 0; }