fix the horizontal scale - ploot - simple plotting tools | |
git clone git://bitreich.org/ploot git://enlrupgkhuxnvlhsf6lc3fziv5h2hhfrinws65… | |
Log | |
Files | |
Refs | |
Tags | |
README | |
LICENSE | |
--- | |
commit 26a6e01805dd158f9f97be0cc9bf43f3d5b6db37 | |
parent 1d056caf74acaf182318297e2911fa8595fbd45c | |
Author: Josuah Demangeon <[email protected]> | |
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(-) | |
--- | |
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 $@ [email protected] ${obj} $(lib) | |
+ ${CC} ${LFLAGS} -o $@ [email protected] ${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} | |
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 vmi… | |
} | |
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, row… | |
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 co… | |
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 co… | |
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) { | |
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 or… | |
+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 [email protected] | |
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 or… | |
-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 [email protected] | |
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… | |
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)); | |
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 | |
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; | |
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). | |
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. | |
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); | |
-} | |
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 *,… | |
+void scale_minmax (struct csv *, int, time_t *, … | |
+time_t scale_tstep (time_t, time_t, int); | |
+double scale_vstep (double, double, int); | |
#endif | |
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; | |
-} | |
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; | |
+} | |
diff --git a/src/tool.h b/src/util.h |