fix the horizontal scale - 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 26a6e01805dd158f9f97be0cc9bf43f3d5b6db37
(DIR) parent 1d056caf74acaf182318297e2911fa8595fbd45c
(HTM) 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