Alien-libhisto
view release on metacpan or search on metacpan
bundled/tools/src/cmd_plot.c view on Meta::CPAN
double max_scaled = (log_scale && max_content > 0.0) ? log10(max_content + 1.0) : max_content;
bool is_ascii = (strcmp(style, "ascii") == 0);
for (uint32_t i = 0; i < nbins; ++i) {
double content = 0.0;
histo_bin_content(h, i, &content);
if (content <= 0.0 || max_scaled <= 0.0) {
fputc(' ', out);
continue;
}
double val_scaled = log_scale ? log10(content + 1.0) : content;
double frac = val_scaled / max_scaled;
int level = (int)(frac * 8.0 + 0.5);
if (level < 1) level = 1;
if (level > 8) level = 8;
if (use_color) {
char color_ansi[32] = "";
histo_palette_sample_ansi_fg(palette, frac, color_ansi, sizeof(color_ansi));
fprintf(out, "%s", color_ansi);
}
if (is_ascii) {
fprintf(out, "%s", SPARKLINE_ASCII[level]);
} else {
fprintf(out, "%s", SPARKLINE_UNICODE[level]);
}
if (use_color) {
fprintf(out, "\033[0m");
}
}
if (show_stats) {
double mean = 0.0, sdev = 0.0, rmin = 0.0, rmax = 0.0;
histo_mean(h, &mean);
histo_std_dev(h, &sdev);
histo_range(h, &rmin, &rmax);
uint64_t entries = histo_num_entries(h);
fprintf(out, " [N=%llu, range=[%.2g, %.2g), μ=%.2g, Ï=%.2g]",
(unsigned long long)entries, rmin, rmax, mean, sdev);
}
fprintf(out, "\n");
}
static void render_histogram_dispatch(const histo_t *h, int term_width, const char *style, bool use_color, histo_palette_t palette, bool log_scale, bool show_errors, bool show_stats, const char *title, bool sparkline, FILE *out) {
if (sparkline) {
render_histogram_sparkline(h, style, use_color, palette, log_scale, show_stats, out);
} else {
render_histogram_console(h, term_width, style, use_color, palette, log_scale, show_errors, show_stats, title, out);
}
}
#include "cli_opt.h"
int histo_cli_plot(int argc, char **argv, FILE *out, FILE *err) {
if (!out) out = stdout;
if (!err) err = stderr;
int term_width = cli_get_terminal_width(80);
const char *style = "blocks";
const char *color_mode = "auto";
const char *palette_name = NULL;
histo_palette_t palette = HISTO_PALETTE_VIRIDIS;
bool log_scale = false;
bool show_errors = false;
bool show_stats = true;
bool sparkline = false;
bool watch_mode = false;
bool clear_screen = false;
bool mode_2d = false;
double scale_input = 1.0;
const char *title = NULL;
const cli_opt_spec_t specs[] = {
{'W', "width", NULL, CLI_OPT_TYPE_INT, &term_width, NULL, 0, "COLS",
"Plot width in characters (default: auto terminal width)", NULL},
{'s', "style", NULL, CLI_OPT_TYPE_STRING, &style, NULL, 0, "STYLE",
"Glyph style: blocks (default), ascii, shaded, sparkline", "blocks"},
{'S', "sparkline", NULL, CLI_OPT_TYPE_BOOL, &sparkline, NULL, 0, NULL,
"Render compact single-line sparkline", NULL},
{0, "scale-input", NULL, CLI_OPT_TYPE_DOUBLE, &scale_input, NULL, 0, "FACTOR",
"Multiply incoming measurements by scale factor (e.g. 1e-3 for ns->us)", "1.0"},
{'c', "color", NULL, CLI_OPT_TYPE_STRING, &color_mode, NULL, 0, "MODE",
"Color mode: auto (default), always, never", "auto"},
{'p', "palette", "colormap", CLI_OPT_TYPE_STRING, &palette_name, NULL, 0, "NAME",
"Color palette: viridis (default), plasma, inferno, magma, turbo, cividis, grayscale, rainbow", "viridis"},
{'l', "log", NULL, CLI_OPT_TYPE_BOOL, &log_scale, NULL, 0, NULL,
"Use logarithmic scale for bar lengths / 2D intensity", NULL},
{'e', "errors", NULL, CLI_OPT_TYPE_BOOL, &show_errors, NULL, 0, NULL,
"Display error bars (1D mode when sum_w2 is tracked)", NULL},
{0, "2d", NULL, CLI_OPT_TYPE_BOOL, &mode_2d, NULL, 0, NULL,
"Render in 2D bivariate heatmap mode", NULL},
{0, "stats", NULL, CLI_OPT_TYPE_BOOL, &show_stats, NULL, CLI_OPT_FLAG_SET_TRUE, NULL,
"Show full statistical summary header/footer (default: ON)", NULL},
{0, "no-stats", NULL, CLI_OPT_TYPE_BOOL, &show_stats, NULL, CLI_OPT_FLAG_SET_FALSE, NULL,
"Suppress statistical summary header", NULL},
{0, "title", NULL, CLI_OPT_TYPE_STRING, &title, NULL, 0, "TITLE",
"Set custom plot title", NULL},
{'w', "watch", NULL, CLI_OPT_TYPE_BOOL, &watch_mode, NULL, 0, NULL,
"Continuously render incoming snapshots from stream", NULL},
{0, "clear", NULL, CLI_OPT_TYPE_BOOL, &clear_screen, NULL, 0, NULL,
"Clear entire screen between updates", NULL}
};
cli_opt_parser_t parser;
cli_opt_init(&parser, specs, sizeof(specs) / sizeof(specs[0]),
"histo-plot", "[OPTIONS] [HISTOGRAM_FILE...]",
"Renders 1D distributions and 2D bivariate heatmaps as ASCII / Unicode terminal charts.");
int rc = cli_opt_parse(&parser, argc, argv, 1);
if (rc < 0) {
cli_opt_print_help(&parser, out);
cli_opt_free(&parser);
return 0;
}
if (rc > 0) {
fprintf(err, "%s\n", cli_opt_error(&parser));
( run in 1.121 second using v1.01-cache-2.11-cpan-5c0b1e786e0 )