#include #include #include #include #include "common.h" #include "fft.h" #include "rl.h" /* Program options */ struct options { int convolved; int deconvolved; int original; size_t num_events; size_t bins; double sigma; size_t rounds; const char* mode; double noise; }; int show_help(char **argv) { fprintf(stderr, "Usage: %s -[hcdoebsrmn]\n", argv[0]); fprintf(stderr, " -h\t\tShow this message.\n"); fprintf(stderr, " -c\t\tPrint the convolved histogram to stdout.\n"); fprintf(stderr, " -d\t\tAttempt and print the deconvolved histogram.\n"); fprintf(stderr, " -o\t\tPrint the original histogram to stdout.\n"); fprintf(stderr, " -e N\t\tThe number of events. (default: 50000)\n"); fprintf(stderr, " -b N\t\tThe number of θ bins. (default: 150)\n"); fprintf(stderr, " -s SIGMA\tThe sigma of gaussian kernel. " "(default: 0.8)\n"); fprintf(stderr, " -r N\t\tThe number of RL deconvolution rounds." "(default: 3)\n"); fprintf(stderr, " -m MODE\tThe deconvolution mode: 'fft' or 'rl'." "(default: 'fft')\n"); fprintf(stderr, " -n SIGMA\tThe σ of the gaussian noise to add to " "the convolution. (default: 0)\n"); return EXIT_SUCCESS; } int main(int argc, char **argv) { struct options opts; /* Set default options */ opts.convolved = 0; opts.deconvolved = 0; opts.original = 1; opts.num_events = 50000; opts.bins = 150; opts.sigma = 0.8; opts.rounds = 3; opts.mode = "fft"; opts.noise = 0; /* Process CLI arguments */ for (int i = 1; i < argc; i++) { if (!strcmp(argv[i], "-c")) opts.convolved = 1; else if (!strcmp(argv[i], "-d")) opts.deconvolved = 1; else if (!strcmp(argv[i], "-o")) opts.original = 1; else if (!strcmp(argv[i], "-e")) opts.num_events = atol(argv[++i]); else if (!strcmp(argv[i], "-b")) opts.bins = atol(argv[++i]); else if (!strcmp(argv[i], "-s")) opts.sigma = atof(argv[++i]); else if (!strcmp(argv[i], "-r")) opts.rounds = atol(argv[++i]); else if (!strcmp(argv[i], "-m")) opts.mode = argv[++i]; else if (!strcmp(argv[i], "-n")) opts.noise = atof(argv[++i]); else return show_help(argv); } /* Initialize an RNG. */ gsl_rng_env_setup(); gsl_rng *r = gsl_rng_alloc(gsl_rng_default); gsl_histogram* hist = gsl_histogram_alloc(opts.bins); gsl_histogram_set_ranges_uniform(hist, 0, M_PI/2); double theta; struct param p = { 0.01, 0.0001, 1e4, 1 }; /* Sample events following the intensity * of a circular aperture diffraction I(θ) * while producing a histogram. */ fputs("# event sampling\n", stderr); fprintf(stderr, "max itensity: %.2f\n", intensity(0, p)); fprintf(stderr, "1. generating %ld events...", opts.num_events); for (size_t i = 0; i < opts.num_events; i++){ do { theta = acos(1 - gsl_rng_uniform(r)); } while(intensity(0, p) * gsl_rng_uniform(r) > intensity(theta, p)); gsl_histogram_increment(hist, theta); } fputs("done\n", stderr); /* Generate the gaussian kernel, convolve the * sample histogram with it and try to deconvolve it. */ fputs("\n# convolution\n", stderr); fputs("1. generating gaussian kernel...", stderr); gsl_histogram *kernel = gaussian_kernel(hist->n, opts.sigma); fputs("done\n", stderr); fputs("2. convolving...", stderr); gsl_histogram *conv = histogram_convolve(hist, kernel); fputs("done\n", stderr); /* Add gaussian noise with σ=opts.noise to * the convolution. */ if (opts.noise > 0) { fputs("2.1 adding noise...", stderr); for (size_t i = 0; i < conv->n; i++) conv->bin[i] += conv->bin[i] * gsl_ran_gaussian(r, opts.noise); fputs("done\n", stderr); } fprintf(stderr, "3. %s deconvolution...", opts.mode); gsl_histogram *clean; if (!strcmp(opts.mode, "fft")) clean = fft_deconvolve(conv, kernel); else if (!strcmp(opts.mode, "rl")) clean = rl_deconvolve(conv, kernel, opts.rounds); else { fputs("\n\nerror: invalid mode. select either 'fft' or 'rl'\n", stderr); return EXIT_FAILURE; } fputs("done\n", stderr); /* Print the selected histogram*/ fputs("\n# histogram \n", stderr); gsl_histogram *showing; if (opts.convolved) showing = conv; else if (opts.deconvolved) showing = clean; else if (opts.original) showing = hist; gsl_histogram_fprintf(stdout, showing, "%g", "%g"); // free memory gsl_rng_free(r); gsl_histogram_free(hist); gsl_histogram_free(kernel); gsl_histogram_free(conv); gsl_histogram_free(clean); return EXIT_SUCCESS; }