1
0
Fork 0
mirror of https://git.rwth-aachen.de/acs/public/villas/node/ synced 2025-03-16 00:00:02 +01:00
VILLASnode/lib/hist.c

176 lines
3.8 KiB
C
Raw Normal View History

/** Histogram functions.
*
* @author Steffen Vogel <stvogel@eonerc.rwth-aachen.de>
2016-02-09 05:33:19 +01:00
* @copyright 2014-2016, Institute for Automation of Complex Power Systems, EONERC
2016-06-08 23:21:42 +02:00
* This file is part of VILLASnode. All Rights Reserved. Proprietary and confidential.
2015-08-07 01:11:43 +02:00
* Unauthorized copying of this file, via any medium is strictly prohibited.
2015-06-02 21:53:04 +02:00
*********************************************************************************/
#include <stdio.h>
#include <stdlib.h>
2015-06-03 10:13:35 +02:00
#include <string.h>
#include <float.h>
#include <math.h>
#include <time.h>
#include "utils.h"
#include "hist.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));
2015-08-07 01:11:43 +02:00
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);
2015-10-08 10:49:51 +02:00
h->last = value;
2015-08-07 01:11:43 +02:00
/* Update min/max */
if (value > h->highest)
h->highest = value;
if (value < h->lowest)
h->lowest = value;
2015-08-07 01:11:43 +02:00
/* Check bounds and increment */
if (idx >= h->length)
h->higher++;
else if (idx < 0)
h->lower++;
else
h->data[idx]++;
2015-08-07 01:11:43 +02:00
h->total++;
2015-08-07 01:11:43 +02:00
/* Online / running calculation of variance and mean
* by Donald Knuths 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]);
2015-08-07 01:11:43 +02:00
// set up for next iteration
2015-08-07 01:11:43 +02:00
h->_m[1] = h->_m[0];
h->_s[1] = h->_s[0];
}
2015-08-07 01:11:43 +02:00
}
void hist_reset(struct hist *h)
{
h->total = 0;
h->higher = 0;
h->lower = 0;
2015-08-07 01:11:43 +02:00
h->highest = DBL_MIN;
h->lowest = DBL_MAX;
2015-08-07 01:11:43 +02:00
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)
{ INDENT
2015-10-13 12:06:50 +02:00
stats("Counted values: %u (%u between %f and %f)", h->total, h->total-h->higher-h->lower, h->high, h->low);
stats("Highest: %f Lowest: %f", h->highest, h->lowest);
stats("Mu: %f Sigma2: %f Sigma: %f", hist_mean(h), hist_var(h), hist_stddev(h));
2015-08-07 01:11:43 +02:00
if (h->total - h->higher - h->lower > 0) {
char *buf = hist_dump(h);
2015-10-13 12:06:50 +02:00
stats("Matlab: %s", buf);
free(buf);
2015-10-13 12:06:50 +02:00
hist_plot(h);
}
}
void hist_plot(struct hist *h)
{
char buf[HIST_HEIGHT];
memset(buf, '#', sizeof(buf));
2015-08-07 01:11:43 +02:00
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];
}
2015-08-07 01:11:43 +02:00
/* Print plot */
2015-10-13 12:06:50 +02:00
stats("%9s | %5s | %s", "Value", "Count", "Plot");
line();
for (int i = 0; i < h->length; i++) {
2015-10-14 12:18:25 +02:00
double value = VAL(h, i);
int cnt = h->data[i];
int bar = HIST_HEIGHT * ((double) cnt / max);
2015-08-07 01:11:43 +02:00
2015-10-14 12:18:25 +02:00
if (value > h->lowest || value < h->highest)
stats("%+9g | " "%5u" " | %.*s", value, cnt, bar, buf);
}
}
char * hist_dump(struct hist *h)
{
char *buf = alloc(128);
strcatf(&buf, "[ ");
for (int i = 0; i < h->length; i++)
strcatf(&buf, "%u ", h->data[i]);
strcatf(&buf, "]");
return buf;
}
void hist_matlab(struct hist *h, FILE *f)
{
char *buf = hist_dump(h);
2015-08-07 01:11:43 +02:00
fprintf(f, "%lu = struct( ", time(NULL));
fprintf(f, "'min', %f, 'max', %f, ", h->low, h->high);
fprintf(f, "'total', %u, higher', %u, 'lower', %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");
free(buf);
}