URI: 
       fix the horizontal scale - 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 26a6e01805dd158f9f97be0cc9bf43f3d5b6db37
   DIR parent 1d056caf74acaf182318297e2911fa8595fbd45c
  HTML Author: Josuah Demangeon <me@josuah.net>
       Date:   Tue,  3 Mar 2020 21:26:54 +0100
       
       fix the horizontal scale
       
       Diffstat:
         M Makefile                            |      18 +++++++++---------
         M ploot-braille.c                     |      26 +++++++++++++++-----------
         A ploot-csv.5                         |      77 +++++++++++++++++++++++++++++++
         D ploot-csv.7                         |      77 -------------------------------
         M ploot-farbfeld.c                    |       6 ++++--
         M ploot-feed.c                        |       2 +-
         M ploot-text.c                        |       2 +-
         M src/csv.c                           |       2 +-
         M src/ffplot.c                        |       2 +-
         M src/scale.c                         |      84 +++++++------------------------
         M src/scale.h                         |       8 +++-----
         D src/tool.c                          |      80 -------------------------------
         A src/util.c                          |      80 +++++++++++++++++++++++++++++++
         R src/tool.h -> src/util.h            |       0 
       
       14 files changed, 211 insertions(+), 253 deletions(-)
       ---
   DIR diff --git a/Makefile b/Makefile
       @@ -1,27 +1,27 @@
        include config.mk
        
        src = src/csv.c src/drawille.c src/ffplot.c src/font.c src/font13.c \
       -        src/font8.c src/log.c src/scale.c src/tool.c
       +        src/font8.c src/log.c src/scale.c src/util.c
        inc = src/csv.h src/drawille.h src/ffplot.h src/font.h src/log.h \
       -        src/scale.h src/tool.h
       +        src/scale.h src/util.h
        bin = ploot-farbfeld ploot-feed ploot-braille ploot-text
        obj = ${src:.c=.o}
        lib = -lm
        
       -all: $(bin)
       +all: ${bin}
        
        .c.o:
                ${CC} -c ${CFLAGS} -o $@ $<
        
        ${obj} ${bin:=.o}: ${inc} Makefile
        ${bin}: ${obj} ${bin:=.o}
       -        ${CC} $(LFLAGS) -o $@ $@.o ${obj} $(lib)
       +        ${CC} ${LFLAGS} -o $@ $@.o ${obj} ${lib}
        
       -install: $(bin)
       -        mkdir -p ${PREFIX}/bin $(MANDIR)/man1 $(MANDIR)/man7
       -        cp $(bin) ${PREFIX}/bin
       -        cp ploot-farbfeld.1 ploot-feed.1 $(MANDIR)/man1
       -        cp ploot-csv.7 $(MANDIR)/man7
       +install: ${bin}
       +        mkdir -p ${PREFIX}/bin ${MANDIR}/man1 ${MANDIR}/man5
       +        cp ${bin} ${PREFIX}/bin
       +        cp *.1 ${MANDIR}/man1
       +        cp *.5 ${MANDIR}/man7
        
        clean:
                rm -f *.o */*.o ${bin}
   DIR diff --git a/ploot-braille.c b/ploot-braille.c
       @@ -10,7 +10,7 @@
        
        #include "drawille.h"
        #include "scale.h"
       -#include "tool.h"
       +#include "util.h"
        #include "log.h"
        
        char const *arg0 = NULL;
       @@ -104,23 +104,26 @@ braille_render(struct drawille *drw, FILE *fp, double vmin, double vmax)
        }
        
        static void
       -plot(struct csv *vl, FILE *fp, size_t ncol, int row, int col)
       +plot(struct csv *vl, FILE *fp, size_t ncol, int rows, int cols)
        {
                double vmin, vmax, vstep;
                time_t tmin, tmax, tstep;
                struct drawille *drw;
        
       -        col -= 8;
       +        cols -= 8;                /* scale printed at the right */
        
       -        scale(vl, ncol, &tmin, &tmax, &tstep, &vmin, &vmax, &vstep);
       -        row -= ncol - 1;        /* room for the labels and the scale */
       -        row /= ncol;                /* plot <ncol> times */
       -        row = MAX(row, 3);        /* readable */
       +        scale_minmax(vl, ncol, &tmin, &tmax, &vmin, &vmax);
       +        tstep = scale_tstep(tmin, tmax, cols / 10);
       +        vstep = scale_vstep(vmin, vmax, rows / 10);
        
       -        debug("vstep=%lf vstep=%ld ncol=%zu row=%zu", vstep, tstep, ncol, row);
       +        rows -= ncol - 1;        /* room for the labels and the scale */
       +        rows /= ncol;                /* plot <ncol> times */
       +        rows = MAX(rows, 3);        /* readable */
       +
       +        debug("vstep=%lf vstep=%ld ncol=%zu rows=%zu", vstep, tstep, ncol, rows);
        
                for (; ncol > 0; vl++, ncol--) {
       -                assert(drw = drawille_new(row, col));
       +                assert(drw = drawille_new(rows, cols));
                        fprintf(fp, " %s\n", vl->label);
                        if (braille_histogram(vl, drw, tmin, tmax, vmin, vmax) == -1)
                                die(1, "allocating drawille canvas");
       @@ -128,7 +131,7 @@ plot(struct csv *vl, FILE *fp, size_t ncol, int row, int col)
                                die(1, "rendering braille canvas");
                        free(drw);
                }
       -        if (braille_axis_x(fp, tmin, tmax, tstep, col) == -1)
       +        if (braille_axis_x(fp, tmin, tmax, tstep, cols) == -1)
                        die(1, "printing x axis");;
        
        }
       @@ -136,7 +139,7 @@ plot(struct csv *vl, FILE *fp, size_t ncol, int row, int col)
        static void
        usage(void)
        {
       -        fprintf(stderr, "usage: %s\n", arg0);
       +        fprintf(stderr, "usage: %s [-r rows] [-c cols]\n", arg0);
                exit(1);
        }
        
       @@ -148,6 +151,7 @@ main(int argc, char **argv)
                int c, rows, cols;
        
                rows = 20, cols = 80;
       +        arg0 = *argv;
                optind = 0;
                while ((c = getopt(argc, argv, "r:c:")) > -1) {
                        switch (c) {
   DIR diff --git a/ploot-csv.5 b/ploot-csv.5
       @@ -0,0 +1,77 @@
       +.Dd $Mdocdate: February 01 2020$
       +.Dt PLOOT-CSV 5
       +.Os
       +.
       +.
       +.Sh NAME
       +.
       +.Nm ploot-csv
       +.Nd input format used by the ploot set of programs
       +.
       +.
       +.Sh SYNOPSIS
       +.
       +.Bd -literal
       +epoch,column-name-1,column-name-2
       +timestamp,value1,value2
       +timestamp,value1,value2
       +…
       +.Ed
       +.
       +.
       +.Sh DESCRIPTION
       +.
       +This is the simple comma-separated format used by the ploot-* programs.
       +.
       +.
       +.Sh INPUT FORMAT
       +.
       +.Nm
       +has a first header line, then zero or more data lines, both
       +comma-separated list of values.
       +.
       +.
       +.Ss Header line
       +.
       +The input must contain a first header line with the label of each column in order.
       +The first column is always
       +.Dq epoch .
       +Then there are the actual column names.
       +.
       +.Bd -literal -offset indent
       +epoch,free_memory,process_count
       +.Ed
       +.
       +.
       +.Ss Data lines
       +.
       +The following lines are the data.
       +The first column is always an unix timestamp as in
       +.Vt time_t .
       +The remaining columns are values parsed as floating point numbers by
       +.Xr strtod 3 :
       +.
       +.Bd -literal -offset indent
       +1533752053,16.3,45
       +1533752054,18.7,42
       +1533752055,40.1,39
       +1533752056,40.1,39
       +.Ed
       +.
       +.
       +.Sh SEE ALSO
       +.
       +.Xr ploot-feed 1 ,
       +.Xr ploot-farbfeld 1
       +.
       +.Sh HISTORY
       +.
       +.Nm
       +was defined at
       +.Lk gopher://bitreich.org/1/scm/ploot/ "Bitreich"
       +.
       +.
       +.Sh AUTHORS
       +.
       +.An Josuah Demangeon
       +.Aq Mt me@josuah.net
   DIR diff --git a/ploot-csv.7 b/ploot-csv.7
       @@ -1,77 +0,0 @@
       -.Dd $Mdocdate: February 01 2020$
       -.Dt PLOOT-CSV 7
       -.Os
       -.
       -.
       -.Sh NAME
       -.
       -.Nm ploot-csv
       -.Nd input format used by the ploot set of programs
       -.
       -.
       -.Sh SYNOPSIS
       -.
       -.Bd -literal
       -epoch,column-name-1,column-name-2
       -timestamp,value1,value2
       -timestamp,value1,value2
       -…
       -.Ed
       -.
       -.
       -.Sh DESCRIPTION
       -.
       -This is the simple comma-separated format used by the ploot-* programs.
       -.
       -.
       -.Sh INPUT FORMAT
       -.
       -.Nm
       -has a first header line, then zero or more data lines, both
       -comma-separated list of values.
       -.
       -.
       -.Ss Header line
       -.
       -The input must contain a first header line with the label of each column in order.
       -The first column is always
       -.Dq epoch .
       -Then there are the actual column names.
       -.
       -.Bd -literal -offset indent
       -epoch,free_memory,process_count
       -.Ed
       -.
       -.
       -.Ss Data lines
       -.
       -The following lines are the data.
       -The first column is always an unix timestamp as in
       -.Vt time_t .
       -The remaining columns are values parsed as floating point numbers by
       -.Xr strtod 3 :
       -.
       -.Bd -literal -offset indent
       -1533752053,16.3,45
       -1533752054,18.7,42
       -1533752055,40.1,39
       -1533752056,40.1,39
       -.Ed
       -.
       -.
       -.Sh SEE ALSO
       -.
       -.Xr ploot-feed 1 ,
       -.Xr ploot-farbfeld 1
       -.
       -.Sh HISTORY
       -.
       -.Nm
       -was defined at
       -.Lk gopher://bitreich.org/1/scm/ploot/ "Bitreich"
       -.
       -.
       -.Sh AUTHORS
       -.
       -.An Josuah Demangeon
       -.Aq Mt me@josuah.net
   DIR diff --git a/ploot-farbfeld.c b/ploot-farbfeld.c
       @@ -15,7 +15,7 @@
        #include "ffplot.h"
        #include "font.h"
        #include "log.h"
       -#include "tool.h"
       +#include "util.h"
        #include "scale.h"
        
        #define MARGIN                4
       @@ -211,7 +211,9 @@ plot(struct csv *vl, struct ffcolor **cl, size_t ncol, char *name, char *units)
                double vmin, vmax, vstep;
                time_t tmin, tmax, tstep;
        
       -        scale(vl, ncol, &tmin, &tmax, &tstep, &vmin, &vmax, &vstep);
       +        scale_minmax(vl, ncol, &tmin, &tmax, &vmin, &vmax);
       +        tstep = scale_tstep(tmin, tmax, 7);
       +        vstep = scale_vstep(vmin, vmax, 7);
        
                assert(plot.buf = calloc(IMAGE_H * IMAGE_W, sizeof *plot.buf));
        
   DIR diff --git a/ploot-feed.c b/ploot-feed.c
       @@ -9,7 +9,7 @@
        #include <time.h>
        #include <unistd.h>
        
       -#include "tool.h"
       +#include "util.h"
        #include "log.h"
        
        #define WIDTH_MAX 1024
   DIR diff --git a/ploot-text.c b/ploot-text.c
       @@ -5,7 +5,7 @@
        
        #include "drawille.h"
        #include "font.h"
       -#include "tool.h"
       +#include "util.h"
        
        char *arg0 = NULL;
        
   DIR diff --git a/src/csv.c b/src/csv.c
       @@ -9,7 +9,7 @@
        #include <time.h>
        
        #include "log.h"
       -#include "tool.h"
       +#include "util.h"
        
        /*
         * Read CSV data onto a set of (struct csv).
   DIR diff --git a/src/ffplot.c b/src/ffplot.c
       @@ -7,7 +7,7 @@
        #include <stdint.h>
        
        #include "font.h"
       -#include "tool.h"
       +#include "util.h"
        
        /*
         * Convert (x,y) coordinates to (row,col) for printing into the buffer.
   DIR diff --git a/src/scale.c b/src/scale.c
       @@ -3,7 +3,7 @@
        #include <stddef.h>
        #include <time.h>
        
       -#include "tool.h"
       +#include "util.h"
        #include "log.h"
        
        /*
       @@ -31,7 +31,7 @@ scale_xpos(time_t t, time_t t1, time_t t2, int szx)
                return szx * (t - t1) / (t2 - t1);
        }
        
       -static void
       +void
        scale_minmax(struct csv *vl, int ncol,
                time_t *tmin, time_t *tmax,
                double *vmin, double *vmax)
       @@ -56,10 +56,10 @@ scale_minmax(struct csv *vl, int ncol,
                        die(1, "invalid time scale: min=%lld max=%lld", *tmin, *tmax);
        }
        
       -static time_t
       -scale_tstep(time_t min, time_t max, int density)
       +time_t
       +scale_tstep(time_t min, time_t max, int nval)
        {
       -        time_t dt, *s, scale[] = {
       +        time_t dt, *sc, 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,
       @@ -67,75 +67,29 @@ scale_tstep(time_t min, time_t max, int density)
                };
        
                dt = max - min;
       -        for (s = scale; s < scale + LEN(scale); s++)
       -                if (dt < *s * density)
       -                        return *s;
       -        return 0;
       +
       +        for (sc = scale; *sc > 0; sc++)
       +                if (dt < *sc * nval)
       +                        return *sc;
       +        return dt / nval;
        }
        
       -static double
       -scale_vstep(double min, double max, int density)
       +double
       +scale_vstep(double min, double max, int nval)
        {
       -        double dv, d, *s, scale[] = { 1, 2, 3, 5 };
       +        double dv, d, *sc, scale[] = { 1, 2, 3, 5 };
        
                dv = max - min;
        
                if (dv > 1)
                        for (d = 1; d != 0; d *= 10)
       -                        for (s = scale; s < scale + LEN(scale); s++)
       -                                if (dv < *s * d * density)
       -                                        return *s * d;
       +                        for (sc = scale; sc < scale + LEN(scale); sc++)
       +                                if (dv < *sc * d * nval)
       +                                        return *sc * d;
                if (dv < 1)
                        for (d = 1; d != 0; d *= 10)
       -                        for (s = scale + LEN(scale) - 1; s >= scale; s--)
       -                                if (dv > *s / d * density / 2)
       -                                        return *s / d;
       +                        for (sc = scale + LEN(scale) - 1; sc >= scale; sc--)
       +                                if (dv > *sc / d * nval / 2)
       +                                        return *sc / d;
                return 0;
        }
       -
       -/*
       - * Adjust the vertical scale so that everything fits, with nice
       - * scale values.
       - */
       -void
       -scale_vminmax(double *min, double *max, int row)
       -{
       -        double unit, range, mi;
       -
       -        range = *max - *min;
       -        unit = 1;
       -
       -        /* Zoom until it fills the canvas. */
       -        for (; (row - 1) * unit > range; unit /= 10)
       -                continue;
       -
       -        /* Dezoom until it fits the canvas. */
       -        for (; (row - 1) * unit < range; unit *= 10)
       -                continue;
       -
       -        /* Fine tune. */
       -        if ((row - 1) * unit / 5 > range)
       -                unit /= 5;
       -        if ((row - 1) * unit / 4 > range)
       -                unit /= 4;
       -        if ((row - 1) * unit / 2 > range)
       -                unit /= 2;
       -
       -        /* Align the minimum (and the zero). */
       -        for (mi = 0; mi > *min - unit; mi -= unit)
       -                continue;
       -
       -        /* Update the displayed minimal and maximal. */
       -        *min = mi;
       -        *max = mi + unit * row;
       -}
       -
       -void
       -scale(struct csv *vl, int ncol,
       -        time_t *tmin, time_t *tmax, time_t *tstep,
       -        double *vmin, double *vmax, double *vstep)
       -{
       -        scale_minmax(vl, ncol, tmin, tmax, vmin, vmax);
       -        *tstep = scale_tstep(*tmin, *tmax, SCALE_X);
       -        *vstep = scale_vstep(*vmin, *vmax, SCALE_Y);
       -}
   DIR diff --git a/src/scale.h b/src/scale.h
       @@ -6,13 +6,11 @@
        
        #include "csv.h"
        
       -#define SCALE_X 7        /* nb of values on x axis */
       -#define SCALE_Y 7        /* nb of values on y axis */
       -
        /**/
        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 csv *, int, time_t *, time_t *, time_t *, double *, double *, double *);
       +void                scale_minmax                (struct csv *, int, time_t *, time_t *, double *, double *);
       +time_t                scale_tstep                (time_t, time_t, int);
       +double                scale_vstep                (double, double, int);
        
        #endif
   DIR diff --git a/src/tool.c b/src/tool.c
       @@ -1,80 +0,0 @@
       -#include "tool.h"
       -
       -#include <ctype.h>
       -#include <errno.h>
       -#include <limits.h>
       -#include <stdarg.h>
       -#include <stdio.h>
       -#include <stdlib.h>
       -#include <string.h>
       -
       -size_t
       -strlcpy(char *buf, const char *str, size_t sz)
       -{
       -        size_t len, cpy;
       -
       -        cpy = ((len = strlen(str)) > sz) ? (sz) : (len);
       -        memcpy(buf, str, cpy);
       -        buf[sz - 1] = '\0';
       -        return len;
       -}
       -
       -void
       -put3utf(long rune)
       -{
       -        putchar((char)(0xe0 | (0x0f & (rune >> 12))));        /* 1110xxxx */
       -        putchar((char)(0x80 | (0x3f & (rune >> 6))));        /* 10xxxxxx */
       -        putchar((char)(0x80 | (0x3f & (rune))));        /* 10xxxxxx */
       -}
       -
       -char *
       -strsep(char **strp, const char *sep)
       -{
       -        char *s, *prev;
       -
       -        if (*strp == NULL)
       -                return NULL;
       -        for (s = prev = *strp; strchr(sep, *s) == NULL; s++);
       -        if (*s == '\0') {
       -                *strp = NULL;
       -                return prev;
       -        }
       -        *s = '\0';
       -        *strp = s + 1;
       -
       -        return prev;
       -}
       -
       -void
       -strchomp(char *s)
       -{
       -        char *x = s + strlen(s);
       -
       -        while (--x >= s && (*x == '\r' || *x == '\n'))
       -                *x = '\0';
       -}
       -
       -/*
       - * 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
       - * max size of a double.  Return the exponent.
       - */
       -int
       -humanize(char *str, double val)
       -{
       -        int exp, precision;
       -        char label[] = { '\0', 'M', 'G', 'T', 'E' };
       -
       -        for (exp = 0; ABS(val) > 1000; exp++)
       -                val /= 1000;
       -
       -        precision = (ABS(val) < 10) ? 2 : (ABS(val) < 100) ? 1 : 0;
       -        precision += (exp == 0);
       -
       -        snprintf(str, 9, "%+.*f %c", precision, val, label[exp]);
       -        str[8] = '\0';
       -        if (val >= 0)
       -                str[0] = ' ';
       -
       -        return exp * 3;
       -}
   DIR diff --git a/src/util.c b/src/util.c
       @@ -0,0 +1,80 @@
       +#include "util.h"
       +
       +#include <ctype.h>
       +#include <errno.h>
       +#include <limits.h>
       +#include <stdarg.h>
       +#include <stdio.h>
       +#include <stdlib.h>
       +#include <string.h>
       +
       +size_t
       +strlcpy(char *buf, const char *str, size_t sz)
       +{
       +        size_t len, cpy;
       +
       +        cpy = ((len = strlen(str)) > sz) ? (sz) : (len);
       +        memcpy(buf, str, cpy);
       +        buf[sz - 1] = '\0';
       +        return len;
       +}
       +
       +void
       +put3utf(long rune)
       +{
       +        putchar((char)(0xe0 | (0x0f & (rune >> 12))));        /* 1110xxxx */
       +        putchar((char)(0x80 | (0x3f & (rune >> 6))));        /* 10xxxxxx */
       +        putchar((char)(0x80 | (0x3f & (rune))));        /* 10xxxxxx */
       +}
       +
       +char *
       +strsep(char **strp, const char *sep)
       +{
       +        char *s, *prev;
       +
       +        if (*strp == NULL)
       +                return NULL;
       +        for (s = prev = *strp; strchr(sep, *s) == NULL; s++);
       +        if (*s == '\0') {
       +                *strp = NULL;
       +                return prev;
       +        }
       +        *s = '\0';
       +        *strp = s + 1;
       +
       +        return prev;
       +}
       +
       +void
       +strchomp(char *s)
       +{
       +        char *x = s + strlen(s);
       +
       +        while (--x >= s && (*x == '\r' || *x == '\n'))
       +                *x = '\0';
       +}
       +
       +/*
       + * 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
       + * max size of a double.  Return the exponent.
       + */
       +int
       +humanize(char *str, double val)
       +{
       +        int exp, precision;
       +        char label[] = { '\0', 'M', 'G', 'T', 'E' };
       +
       +        for (exp = 0; ABS(val) > 1000; exp++)
       +                val /= 1000;
       +
       +        precision = (ABS(val) < 10) ? 2 : (ABS(val) < 100) ? 1 : 0;
       +        precision += (exp == 0);
       +
       +        snprintf(str, 9, "%+.*f %c", precision, val, label[exp]);
       +        str[8] = '\0';
       +        if (val >= 0)
       +                str[0] = ' ';
       +
       +        return exp * 3;
       +}
   DIR diff --git a/src/tool.h b/src/util.h