From 49b8b0758cacffc34f71cf5fb3d4ae4cf4641dfc Mon Sep 17 00:00:00 2001 From: Walter Van Herck <w.van.herck@fz-juelich.de> Date: Wed, 11 Jul 2012 10:55:27 +0200 Subject: [PATCH] Detector resolution function (step 2): finished --- App/src/TestDetectorResolution.cpp | 6 +-- .../inc/ConvolutionDetectorResolution.h | 14 +++--- Core/Algorithms/inc/GISASExperiment.h | 2 +- .../src/ConvolutionDetectorResolution.cpp | 46 +++++++++++++++---- Core/Algorithms/src/GISASExperiment.cpp | 2 +- Core/Tools/inc/MathFunctions.h | 2 +- Core/Tools/src/MathFunctions.cpp | 7 ++- 7 files changed, 52 insertions(+), 27 deletions(-) diff --git a/App/src/TestDetectorResolution.cpp b/App/src/TestDetectorResolution.cpp index 212c1262521..9b4b03169cb 100644 --- a/App/src/TestDetectorResolution.cpp +++ b/App/src/TestDetectorResolution.cpp @@ -29,7 +29,7 @@ void TestDetectorResolution::execute() GISASExperiment experiment; experiment.setSample(mp_sample); experiment.setDetectorParameters(0.0*Units::degree, 2.0*Units::degree, 100 - , 0.0*Units::degree, 2.0*Units::degree, 100, true); + , 0.0*Units::degree, 2.0*Units::degree, 100); experiment.setDetectorResolutionFunction(&testResolutionFunction); experiment.setBeamParameters(1.0*Units::angstrom, -0.2*Units::degree, 0.0*Units::degree); experiment.runSimulation(); @@ -42,9 +42,7 @@ double testResolutionFunction(double u, double v) { double sigma_u = 0.001; double sigma_v = 0.001; - double step_u = 0.02*Units::degree; - double step_v = 0.02*Units::degree; - return MathFunctions::IntegratedGaussian(u, 0.0, sigma_u, step_u)*MathFunctions::IntegratedGaussian(v, 0.0, sigma_v, step_v); + return MathFunctions::IntegratedGaussian(u, 0.0, sigma_u)*MathFunctions::IntegratedGaussian(v, 0.0, sigma_v); } void TestDetectorResolution::initializeSample() diff --git a/Core/Algorithms/inc/ConvolutionDetectorResolution.h b/Core/Algorithms/inc/ConvolutionDetectorResolution.h index c434df3d01d..4f8ae180727 100644 --- a/Core/Algorithms/inc/ConvolutionDetectorResolution.h +++ b/Core/Algorithms/inc/ConvolutionDetectorResolution.h @@ -26,12 +26,12 @@ class ConvolutionDetectorResolution : public IDetectorResolution { public: - typedef double (*resolution_function_1d)(double); - typedef double (*resolution_function_2d)(double, double); + typedef double (*cumulative_DF_1d)(double); + typedef double (*cumulative_DF_2d)(double, double); //! Constructor taking a 1 dimensional resolution function as argument - ConvolutionDetectorResolution(resolution_function_1d res_function_1d); + ConvolutionDetectorResolution(cumulative_DF_1d res_function_1d); //! Constructor taking a 2 dimensional resolution function as argument - ConvolutionDetectorResolution(resolution_function_2d res_function_2d); + ConvolutionDetectorResolution(cumulative_DF_2d res_function_2d); //! Destructor virtual ~ConvolutionDetectorResolution(); @@ -39,10 +39,12 @@ public: virtual void applyDetectorResolution(OutputData<double> *p_intensity_map) const; private: size_t m_dimension; - resolution_function_1d m_res_function_1d; - resolution_function_2d m_res_function_2d; + cumulative_DF_1d m_res_function_1d; + cumulative_DF_2d m_res_function_2d; void apply1dConvolution(const std::vector<NamedVectorBase *> &axes, OutputData<double> *p_intensity_map) const; void apply2dConvolution(const std::vector<NamedVectorBase *> &axes, OutputData<double> *p_intensity_map) const; + double getIntegratedPDF1d(double x, double step) const; + double getIntegratedPDF2d(double x, double step_x, double y, double step_y) const; }; diff --git a/Core/Algorithms/inc/GISASExperiment.h b/Core/Algorithms/inc/GISASExperiment.h index 5a1e477f62d..92c92a4961a 100644 --- a/Core/Algorithms/inc/GISASExperiment.h +++ b/Core/Algorithms/inc/GISASExperiment.h @@ -28,7 +28,7 @@ public: void setDetectorParameters(double phi_f_min, double phi_f_max, size_t n_phi, double alpha_f_min, double alpha_f_max, size_t n_alpha, bool isgisaxs_style=false); - void setDetectorResolutionFunction(ConvolutionDetectorResolution::resolution_function_2d resolution_function); + void setDetectorResolutionFunction(ConvolutionDetectorResolution::cumulative_DF_2d resolution_function); private: void initializeAnglesIsgisaxs(NamedVector<double> *p_axis, double start, double end, size_t size); }; diff --git a/Core/Algorithms/src/ConvolutionDetectorResolution.cpp b/Core/Algorithms/src/ConvolutionDetectorResolution.cpp index ef2c56b9bce..66accbf7001 100644 --- a/Core/Algorithms/src/ConvolutionDetectorResolution.cpp +++ b/Core/Algorithms/src/ConvolutionDetectorResolution.cpp @@ -6,7 +6,7 @@ #include <iostream> ConvolutionDetectorResolution::ConvolutionDetectorResolution( - resolution_function_1d res_function_1d) + cumulative_DF_1d res_function_1d) : m_dimension(1) , m_res_function_1d(res_function_1d) , m_res_function_2d(0) @@ -14,7 +14,7 @@ ConvolutionDetectorResolution::ConvolutionDetectorResolution( } ConvolutionDetectorResolution::ConvolutionDetectorResolution( - resolution_function_2d res_function_2d) + cumulative_DF_2d res_function_2d) : m_dimension(2) , m_res_function_1d(0) , m_res_function_2d(res_function_2d) @@ -58,15 +58,18 @@ void ConvolutionDetectorResolution::apply1dConvolution( // Construct source vector from original intensity map std::vector<double> source_vector = p_intensity_map->getRawDataVector(); size_t data_size = source_vector.size(); + if (data_size < 2) { + return; // No convolution for sets of zero or one element + } // Construct kernel vector from resolution function if (p_axis->getSize() != data_size) { throw LogicErrorException("Size of axis for intensity map does not correspond to the size of the data in the map."); } - double step_size = std::abs((*p_axis)[0]-(*p_axis)[p_axis->getSize()-1])/p_axis->getSize(); + double step_size = std::abs((*p_axis)[0]-(*p_axis)[p_axis->getSize()-1])/(data_size-1); double mid_value = (*p_axis)[p_axis->getSize()/2]; // Needed because Convolve class expects zero at midpoint std::vector<double> kernel; for (size_t index=0; index<data_size; ++index) { - kernel.push_back(m_res_function_1d((*p_axis)[index] - mid_value)*step_size); + kernel.push_back(getIntegratedPDF1d((*p_axis)[index] - mid_value, step_size)); } // Calculate convolution std::vector<double> result; @@ -90,6 +93,9 @@ void ConvolutionDetectorResolution::apply2dConvolution( NamedVector<double> *p_axis_2 = dynamic_cast<NamedVector<double> *>(axes[1]); size_t axis_size_1 = p_axis_1->getSize(); size_t axis_size_2 = p_axis_2->getSize(); + if (axis_size_1 < 2 || axis_size_2 < 2) { + return; // No 2d convolution for 1d data + } // Construct source vector array from original intensity map std::vector<double> raw_source_vector = p_intensity_map->getRawDataVector(); std::vector<std::vector<double> > source; @@ -102,26 +108,23 @@ void ConvolutionDetectorResolution::apply2dConvolution( source.push_back(row_vector); } // Construct kernel vector from resolution function - double kernel_total_sum = 0.0; // Temporary sum of the kernel values (should be 1 in total) std::vector<std::vector<double> > kernel; kernel.resize(axis_size_1); double mid_value_1 = (*p_axis_1)[axis_size_1/2]; // Needed because Convolve class expects zero at midpoint double mid_value_2 = (*p_axis_2)[axis_size_2/2]; // Needed because Convolve class expects zero at midpoint - double step_size_1 = std::abs((*p_axis_1)[0]-(*p_axis_1)[axis_size_1-1])/axis_size_1; - double step_size_2 = std::abs((*p_axis_2)[0]-(*p_axis_2)[axis_size_2-1])/axis_size_2; + double step_size_1 = std::abs((*p_axis_1)[0]-(*p_axis_1)[axis_size_1-1])/(axis_size_1-1); + double step_size_2 = std::abs((*p_axis_2)[0]-(*p_axis_2)[axis_size_2-1])/(axis_size_2-1); for (size_t index_1=0; index_1<axis_size_1; ++index_1) { double value_1 = (*p_axis_1)[index_1]-mid_value_1; std::vector<double> row_vector; row_vector.resize(axis_size_2); for (size_t index_2=0; index_2<axis_size_2;++index_2) { double value_2 = (*p_axis_2)[index_2]-mid_value_2; - double z_value = m_res_function_2d(value_1, value_2); // *step_size_1*step_size_2; + double z_value = getIntegratedPDF2d(value_1, step_size_1, value_2, step_size_2); row_vector[index_2] = z_value; - kernel_total_sum += z_value; } kernel[index_1] = row_vector; } - std::cout << "Total kernel value = " << kernel_total_sum << std::endl; // Calculate convolution std::vector<std::vector<double> > result; MathFunctions::Convolve cv; @@ -136,3 +139,26 @@ void ConvolutionDetectorResolution::apply2dConvolution( } p_intensity_map->setRawDataVector(result_vector); } + +double ConvolutionDetectorResolution::getIntegratedPDF1d(double x, + double step) const +{ + double halfstep = step/2.0; + double xmin = x - halfstep; + double xmax = x + halfstep; + return m_res_function_1d(xmax) - m_res_function_1d(xmin); +} + +double ConvolutionDetectorResolution::getIntegratedPDF2d(double x, + double step_x, double y, double step_y) const +{ + double halfstepx = step_x/2.0; + double halfstepy = step_y/2.0; + double xmin = x - halfstepx; + double xmax = x + halfstepx; + double ymin = y - halfstepy; + double ymax = y + halfstepy; + double result = m_res_function_2d(xmax, ymax) - m_res_function_2d(xmax, ymin) + - m_res_function_2d(xmin, ymax) + m_res_function_2d(xmin, ymin); + return result; +} diff --git a/Core/Algorithms/src/GISASExperiment.cpp b/Core/Algorithms/src/GISASExperiment.cpp index 017626e462d..9f58b7d8b71 100644 --- a/Core/Algorithms/src/GISASExperiment.cpp +++ b/Core/Algorithms/src/GISASExperiment.cpp @@ -44,7 +44,7 @@ void GISASExperiment::setDetectorParameters(double phi_f_min, double phi_f_max, } void GISASExperiment::setDetectorResolutionFunction( - ConvolutionDetectorResolution::resolution_function_2d resolution_function) + ConvolutionDetectorResolution::cumulative_DF_2d resolution_function) { m_detector.setDetectorResolution(new ConvolutionDetectorResolution(resolution_function)); } diff --git a/Core/Tools/inc/MathFunctions.h b/Core/Tools/inc/MathFunctions.h index 1ac50026a62..377e04a2668 100644 --- a/Core/Tools/inc/MathFunctions.h +++ b/Core/Tools/inc/MathFunctions.h @@ -26,7 +26,7 @@ namespace MathFunctions { double Gaussian(double value, double average, double std_dev); -double IntegratedGaussian(double value, double average, double std_dev, double step); +double IntegratedGaussian(double value, double average, double std_dev); double GenerateNormalRandom(double average, double std_dev); diff --git a/Core/Tools/src/MathFunctions.cpp b/Core/Tools/src/MathFunctions.cpp index 4c9f8644688..c9d0af01ee9 100644 --- a/Core/Tools/src/MathFunctions.cpp +++ b/Core/Tools/src/MathFunctions.cpp @@ -12,12 +12,11 @@ double MathFunctions::Gaussian(double value, double average, double std_dev) return StandardNormal((value-average)/std_dev)/std_dev; } -double MathFunctions::IntegratedGaussian(double value, double average, double std_dev, double step) +double MathFunctions::IntegratedGaussian(double value, double average, double std_dev) { - double left_margin = (value - average - step/2)/std_dev; - double right_margin = (value - average + step/2)/std_dev; + double normalized_value = (value - average)/std_dev; double root2 = std::sqrt(2.0); - return (gsl_sf_erf(right_margin/root2) - gsl_sf_erf(left_margin/root2))/2.0; + return (gsl_sf_erf(normalized_value/root2) + 1.0)/2.0; } double MathFunctions::StandardNormal(double value) -- GitLab