From 59770f9bffbd47de5b518244a6dfcfbdfc8dad09 Mon Sep 17 00:00:00 2001 From: Thomas White Date: Wed, 8 May 2019 13:54:18 +0200 Subject: Move Histogram out of API It's only used by two test programs --- tests/CMakeLists.txt | 4 +- tests/histogram.c | 280 ++++++++++++++++++++++++++++++++++++++++++++++ tests/histogram.h | 64 +++++++++++ tests/integration_check.c | 3 +- tests/prof2d_check.c | 3 +- 5 files changed, 350 insertions(+), 4 deletions(-) create mode 100644 tests/histogram.c create mode 100644 tests/histogram.h (limited to 'tests') diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index beb141c3..af22977e 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -28,7 +28,7 @@ target_include_directories(centering_check PRIVATE ${COMMON_INCLUDES}) target_link_libraries(centering_check ${COMMON_LIBRARIES}) add_test(centering_check centering_check) -add_executable(integration_check integration_check.c) +add_executable(integration_check integration_check.c histogram.c) target_include_directories(integration_check PRIVATE ${COMMON_INCLUDES}) target_link_libraries(integration_check PRIVATE ${COMMON_LIBRARIES}) if (CURSES_FOUND) @@ -47,7 +47,7 @@ target_include_directories(prediction_gradient_check PRIVATE ${COMMON_INCLUDES}) target_link_libraries(prediction_gradient_check ${COMMON_LIBRARIES}) add_test(prediction_gradient_check prediction_gradient_check) -add_executable(prof2d_check prof2d_check.c) +add_executable(prof2d_check prof2d_check.c histogram.c) target_include_directories(prof2d_check PRIVATE ${COMMON_INCLUDES}) target_link_libraries(prof2d_check PRIVATE ${COMMON_LIBRARIES}) if (CURSES_FOUND) diff --git a/tests/histogram.c b/tests/histogram.c new file mode 100644 index 00000000..69acd987 --- /dev/null +++ b/tests/histogram.c @@ -0,0 +1,280 @@ +/* + * histogram.c + * + * Quick histogram functions + * + * Copyright © 2013-2014 Deutsches Elektronen-Synchrotron DESY, + * a research centre of the Helmholtz Association. + * + * Authors: + * 2013-2014 Thomas White + * + * This file is part of CrystFEL. + * + * CrystFEL is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * CrystFEL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with CrystFEL. If not, see . + * + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include + +#include "histogram.h" + +/** \file histogram.h */ + +struct _histogram +{ + int n_vals; + int max_vals; + double *vals; + + double min; + double max; + + int full; + + int n_bins; + double bin_width; + + int *bins; + + int plot_height; + int peak; + double mean; + double stddev; +}; + + +Histogram *histogram_init() +{ + Histogram *hi; + + hi = malloc(sizeof(struct _histogram)); + if ( hi == NULL ) return NULL; + + hi->n_vals = 0; + hi->max_vals = 0; + hi->vals = NULL; + hi->full = 0; + + hi->max = -INFINITY; + hi->min = INFINITY; + + hi->bins = NULL; + hi->n_bins = 50; + + hi->plot_height = 10; + + return hi; +} + + +void histogram_free(Histogram *hi) +{ + free(hi); +} + + +void histogram_add_value(Histogram *hi, double val) +{ + if ( hi->n_vals == hi->max_vals ) { + double *new_vals; + new_vals = realloc(hi->vals, (hi->max_vals+512)*sizeof(double)); + if ( new_vals == NULL ) { + hi->full = 1; + fprintf(stderr, "Histogram %p full.\n", hi); + return; + } + hi->max_vals += 512; + hi->vals = new_vals; + } + + hi->vals[hi->n_vals++] = val; + + if ( val > hi->max ) hi->max = val; + if ( val < hi->min ) hi->min = val; +} + + +static void calc_bins(Histogram *hi) +{ + int i; + + if ( hi->bins != NULL ) { + free(hi->bins); + } + + hi->bins = calloc(hi->n_bins, sizeof(int)); + if ( hi->bins == NULL ) { + fprintf(stderr, "Failed to allocate bins.\n"); + return; + } + + hi->bin_width = (hi->max - hi->min)/hi->n_bins; + + for ( i=0; in_vals; i++ ) { + + int j; + + j = (hi->vals[i] - hi->min) / hi->bin_width; + + /* Tidy up rounding errors */ + if ( j < 0 ) j = 0; + if ( j >= hi->n_bins ) j = hi->n_bins - 1; + + hi->bins[j]++; + + } + + hi->peak = 0; + for ( i=0; in_bins; i++ ) { + if ( hi->bins[i] > hi->peak ) hi->peak = hi->bins[i]; + } +} + + +static void calc_stddev(Histogram *hi) +{ + double sum = 0.0; + int i; + + for ( i=0; in_vals; i++ ) { + sum += hi->vals[i]; + } + hi->mean = sum / hi->n_vals; + + sum = 0.0; + for ( i=0; in_vals; i++ ) { + sum += pow(hi->vals[i] - hi->mean, 2.0); + } + hi->stddev = sqrt(sum / hi->n_vals); +} + + +int *histogram_get_data(Histogram *hi, int *n) +{ + calc_bins(hi); + *n = hi->n_bins; + return hi->bins; +} + + +void histogram_show(Histogram *hi) +{ + int i; + int *bins; + double lines_per_count; + char tmp[32]; + size_t n_left, n_mid, n_right; + + calc_bins(hi); + calc_stddev(hi); + + bins = malloc(hi->n_bins*sizeof(int)); + if ( bins == NULL ) { + fprintf(stderr, "Couldn't scale bins\n"); + return; + } + + lines_per_count = (double)hi->plot_height / hi->peak; + + for ( i=0; in_bins; i++ ) { + bins[i] = hi->bins[i] * lines_per_count; + } + + for ( i=hi->plot_height-1; i>=0; i-- ) { + + int j; + + for ( j=0; jn_bins; j++ ) { + if ( bins[j] > i ) { + printf("*"); + } else { + printf(" "); + } + } + printf("\n"); + + } + + printf("|"); + for ( i=1; in_bins-1; i++ ) { + double bin_low, bin_high; + bin_low = hi->min + i*hi->bin_width; + bin_high = hi->min + (i+1)*hi->bin_width; + if ( (bin_low < 0.0) && (bin_high > 0.0) ) { + printf("+"); + } else { + printf("-"); + } + } + printf("|\n"); + + snprintf(tmp, 31, "%.2f", hi->min); + n_left = strlen(tmp); + snprintf(tmp, 31, "%.2f", hi->max); + n_right = strlen(tmp); + n_mid = hi->n_bins - (n_left + n_right); + + printf("%.2f", hi->min); + for ( i=0; imax); + + printf("Mean = %.2f, Std dev = %.2f\n", hi->mean, hi->stddev); + + free(bins); +} + + +double histogram_get_min(Histogram *hi) +{ + return hi->min; +} + + +double histogram_get_max(Histogram *hi) +{ + return hi->max; +} + + +int histogram_get_num_bins(Histogram *hi) +{ + return hi->n_bins; +} + + +void histogram_set_min(Histogram *hi, double min) +{ + hi->min = min; +} + + +void histogram_set_max(Histogram *hi, double max) +{ + hi->max = max; +} + + +void histogram_set_num_bins(Histogram *hi, int n) +{ + hi->n_bins = n; +} diff --git a/tests/histogram.h b/tests/histogram.h new file mode 100644 index 00000000..2b9d4928 --- /dev/null +++ b/tests/histogram.h @@ -0,0 +1,64 @@ +/* + * histogram.h + * + * Quick histogram functions + * + * Copyright © 2013-2014 Deutsches Elektronen-Synchrotron DESY, + * a research centre of the Helmholtz Association. + * + * Authors: + * 2013-2014 Thomas White + * + * This file is part of CrystFEL. + * + * CrystFEL is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * CrystFEL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with CrystFEL. If not, see . + * + */ + +#ifndef HISTOGRAM_H +#define HISTOGRAM_H + +#ifdef HAVE_CONFIG_H +#include +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \file histogram.h + * Quick histogram functions + */ + +typedef struct _histogram Histogram; + +extern Histogram *histogram_init(); +extern void histogram_free(Histogram *hi); +extern void histogram_add_value(Histogram *hi, double val); +extern void histogram_show(Histogram *hi); + +extern int *histogram_get_data(Histogram *hi, int *n); +extern double histogram_get_min(Histogram *hi); +extern double histogram_get_max(Histogram *hi); +extern int histogram_get_num_bins(Histogram *hi); +extern void histogram_set_min(Histogram *hi, double min); +extern void histogram_set_max(Histogram *hi, double max); +extern void histogram_set_num_bins(Histogram *hi, int n); + +#ifdef __cplusplus +} +#endif + +#endif /* HISTOGRAM_H */ diff --git a/tests/integration_check.c b/tests/integration_check.c index 65241612..a6ceb2c4 100644 --- a/tests/integration_check.c +++ b/tests/integration_check.c @@ -36,7 +36,8 @@ #include #include -#include + +#include "histogram.h" #include "../libcrystfel/src/integration.c" diff --git a/tests/prof2d_check.c b/tests/prof2d_check.c index 8b9de871..803e60c4 100644 --- a/tests/prof2d_check.c +++ b/tests/prof2d_check.c @@ -36,7 +36,8 @@ #include #include -#include + +#include "histogram.h" #include "../libcrystfel/src/integration.c" -- cgit v1.2.3