/** Histogram functions. * * @author Steffen Vogel * @copyright 2014-2015, Institute for Automation of Complex Power Systems, EONERC * This file is part of S2SS. All Rights Reserved. Proprietary and confidential. * Unauthorized copying of this file, via any medium is strictly prohibited. *********************************************************************************/ #include #include #include #include #include #include #include "hist.h" #include "utils.h" #define VAL(h, i) ((h)->low + (i) * (h)->resolution) #define INDEX(h, v) round((v - (h)->low) / (h)->resolution) void hist_create(struct hist *h, double low, double high, double resolution) { h->low = low; h->high = high; h->resolution = resolution; h->length = (high - low) / resolution; h->data = alloc(h->length * sizeof(unsigned)); hist_reset(h); } void hist_destroy(struct hist *h) { free(h->data); } void hist_put(struct hist *h, double value) { int idx = INDEX(h, value); /* Update min/max */ if (value > h->highest) h->highest = value; if (value < h->lowest) h->lowest = value; /* Check bounds and increment */ if (idx >= h->length) h->higher++; else if (idx < 0) h->lower++; else h->data[idx]++; h->total++; /* Online / running calculation of variance and mean * by Donald Knuth’s Art of Computer Programming, Vol 2, page 232, 3rd edition */ if (h->total == 1) { h->_m[1] = h->_m[0] = value; h->_s[1] = 0.0; } else { h->_m[0] = h->_m[1] + (value - h->_m[1]) / h->total; h->_s[0] = h->_s[1] + (value - h->_m[1]) * (value - h->_m[0]); // set up for next iteration h->_m[1] = h->_m[0]; h->_s[1] = h->_s[0]; } } void hist_reset(struct hist *h) { h->total = 0; h->higher = 0; h->lower = 0; h->highest = DBL_MIN; h->lowest = DBL_MAX; memset(h->data, 0, h->length * sizeof(unsigned)); } double hist_mean(struct hist *h) { return (h->total > 0) ? h->_m[0] : 0.0; } double hist_var(struct hist *h) { return (h->total > 1) ? h->_s[0] / (h->total - 1) : 0.0; } double hist_stddev(struct hist *h) { return sqrt(hist_var(h)); } void hist_print(struct hist *h) { printf("Total: %u values\n", h->total); printf("Highest value: %f\n", h->highest); printf("Lowest value: %f\n", h->lowest); printf("Mean: %f\n", hist_mean(h)); printf("Variance: %f\n", hist_var(h)); printf("Standard derivation: %f\n", hist_stddev(h)); if (h->higher > 0) printf("Missed: %u values above %f\n", h->higher, h->high); if (h->lower > 0) printf("Missed: %u values below %f\n", h->lower, h->low); if (h->total - h->higher - h->lower > 0) { hist_plot(h); char buf[(h->length + 1) * 8]; hist_dump(h, buf, sizeof(buf)); printf(buf); } } void hist_plot(struct hist *h) { char buf[HIST_HEIGHT]; memset(buf, '#', sizeof(buf)); hist_cnt_t max = 1; /* Get highest bar */ for (int i = 0; i < h->length; i++) { if (h->data[i] > max) max = h->data[i]; } /* Print plot */ printf("%3s | %9s | %5s | %s\n", "#", "Value", "Occur", "Plot"); printf("--------------------------------------------------------------------------------\n"); for (int i = 0; i < h->length; i++) { int bar = HIST_HEIGHT * ((double) h->data[i] / max); printf("%3u | %+5.2e | " "%5u" " | %.*s\n", i, VAL(h, i), h->data[i], bar, buf); } } void hist_dump(struct hist *h, char *buf, int len) { *buf = 0; strap(buf, len, "[ "); for (int i = 0; i < h->length; i++) strap(buf, len, "%u ", h->data[i]); strap(buf, len, "]"); } void hist_matlab(struct hist *h, FILE *f) { char buf[h->length * 8]; hist_dump(h, buf, sizeof(buf)); fprintf(f, "%lu = struct( ", time(NULL)); fprintf(f, "'min', %f, 'max', %f, ", h->low, h->high); fprintf(f, "'ok', %u, too_high', %u, 'too_low', %u, ", h->total, h->higher, h->lower); fprintf(f, "'highest', %f, 'lowest', %f, ", h->highest, h->lowest); fprintf(f, "'mean', %f, ", hist_mean(h)); fprintf(f, "'var', %f, ", hist_var(h)); fprintf(f, "'stddev', %f, ", hist_stddev(h)); fprintf(f, "'hist', %s ", buf); fprintf(f, "),\n"); }