Alien-libhisto

 view release on metacpan or  search on metacpan

bundled/tools/src/cmd_fill.c  view on Meta::CPAN

/*
 * CLI subcommand histo fill: ingest data streams and serialize histograms.
 */

#include "cli_common.h"
#include "histo/histo2d.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <stdbool.h>
#include <ctype.h>
#include <math.h>
#include <unistd.h>


static void print_fill_usage(FILE *out) {
    if (!out) out = stdout;
    fprintf(out, "Usage: histo-fill [OPTIONS] [FILE...]\n");
    fprintf(out, "       histo fill [OPTIONS] [FILE...]\n\n");
    fprintf(out, "Reads streaming data, aggregates into a histogram (1D or 2D), and emits the serialized result.\n\n");
    fprintf(out, "1D Geometry Options:\n");
    fprintf(out, "  -n, --bins=<N>           Number of uniform bins (default: 50)\n");
    fprintf(out, "      --min=<X>            Lower boundary (required unless --auto-range)\n");
    fprintf(out, "      --max=<X>            Upper boundary (required unless --auto-range)\n");
    fprintf(out, "      --edges=<E0,E1,...>  Variable bin edges (comma-separated)\n");
    fprintf(out, "      --auto-range         Buffer input to determine min/max automatically\n");
    fprintf(out, "  -a, --auto-bins[=RULE]   Buffer input and estimate optimal bins (fd, scott, sturges, doane, knuth)\n\n");
    fprintf(out, "2D Geometry Options:\n");
    fprintf(out, "      --2d                 Enable 2D bivariate histogramming mode\n");
    fprintf(out, "      --xbins=<N>          Number of bins along X axis (default: 50)\n");
    fprintf(out, "      --xmin=<X>, --xmax=<X> X axis bounds\n");
    fprintf(out, "      --ybins=<N>          Number of bins along Y axis (default: 50)\n");
    fprintf(out, "      --ymin=<Y>, --ymax=<Y> Y axis bounds\n\n");
    fprintf(out, "Input Parsing & Columns:\n");
    fprintf(out, "  -w, --weights            Input contains weights: reads 'x weight' pairs\n");
    fprintf(out, "      --value-col=<COL>    1-based column for sample coordinate (default: 1)\n");
    fprintf(out, "      --xcol=<COL>         1-based column for X coordinate in 2D mode (default: 1)\n");
    fprintf(out, "      --ycol=<COL>         1-based column for Y coordinate in 2D mode (default: 2)\n");
    fprintf(out, "      --weights-col=<COL>  1-based column for sample weight (default: 2 for 1D, 3 for 2D)\n");
    fprintf(out, "  -d, --delimiter=<CHAR>   Field delimiter character (default: auto-detect comma/tab/semicolon/space)\n");
    fprintf(out, "      --binary-f64         Read raw Little-Endian double binary stream\n");
    fprintf(out, "      --merge              Read and add/merge incoming serialized histograms\n\n");
    fprintf(out, "Histogram Features & Transformations:\n");
    fprintf(out, "      --sumw2              Enable sum_w2 error tracking (default: ON)\n");
    fprintf(out, "      --no-sumw2           Disable sum_w2 error tracking\n");
    fprintf(out, "      --exact-moments      Enable online exact Welford moments\n");
    fprintf(out, "      --rebin=<FACTOR>     Rebin uniform histogram by integer factor (1D only)\n");
    fprintf(out, "      --slice=<MIN:MAX>    Slice bin sub-range [MIN, MAX]\n");
    fprintf(out, "      --cdf                Generate Cumulative Distribution Function (CDF)\n");
    fprintf(out, "      --normalize=<AREA>   Scale histogram total weight to target area\n\n");
    fprintf(out, "Output & Streaming Options:\n");
    fprintf(out, "  -o, --output=<FORMAT>    Output format: binary (default for pipes), json, tsv, table\n");
    fprintf(out, "  -f, --output-file=<FILE> Output destination (default: stdout)\n");
    fprintf(out, "      --emit-every=<N>     Emit intermediate snapshot every N samples\n");
    fprintf(out, "      --emit-interval=<S>  Emit intermediate snapshot every S seconds\n");
    fprintf(out, "  -h, --help               Show this help message\n");
}


static char auto_detect_delimiter(const char *line) {
    int commas = 0, tabs = 0, semicolons = 0, pipes = 0;
    for (const char *p = line; *p; ++p) {
        if (*p == ',') commas++;
        else if (*p == '\t') tabs++;
        else if (*p == ';') semicolons++;
        else if (*p == '|') pipes++;
    }
    if (commas > 0 && commas >= tabs && commas >= semicolons && commas >= pipes) return ',';
    if (tabs > 0 && tabs >= semicolons && tabs >= pipes) return '\t';
    if (semicolons > 0 && semicolons >= pipes) return ';';
    if (pipes > 0) return '|';
    return ' ';
}

static histo_status_t emit_histogram(const histo_t *h, const char *fmt, FILE *out_fp,
                                     uint32_t rebin_factor, bool do_cdf, double norm_area) {
    if (!h || !out_fp) return HISTO_ERR_INVALID_ARG;
    histo_t *emit_h = (histo_t *)h;
    bool needs_free = false;



( run in 0.925 second using v1.01-cache-2.11-cpan-9789f410c06 )