diff options
Diffstat (limited to 'silx/math/fit/functions/src/funs.c')
-rw-r--r-- | silx/math/fit/functions/src/funs.c | 1265 |
1 files changed, 0 insertions, 1265 deletions
diff --git a/silx/math/fit/functions/src/funs.c b/silx/math/fit/functions/src/funs.c deleted file mode 100644 index aae173f..0000000 --- a/silx/math/fit/functions/src/funs.c +++ /dev/null @@ -1,1265 +0,0 @@ -#/*########################################################################## -# Copyright (c) 2004-2016 European Synchrotron Radiation Facility -# -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the "Software"), to deal -# in the Software without restriction, including without limitation the rights -# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -# copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included in -# all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -# THE SOFTWARE. -# -#############################################################################*/ -/* - This file provides fit functions. - - It is adapted from PyMca source file "SpecFitFuns.c". The main difference - with the original code is that this code does not handle the python - wrapping, which is done elsewhere using cython. - - Authors: V.A. Sole, P. Knobel - License: MIT - Last modified: 17/06/2016 -*/ -#include <math.h> -#include <stdlib.h> -#include <stdio.h> -#include "functions.h" - -#ifndef M_PI -#define M_PI 3.1415926535 -#endif - -#define MIN(x, y) (((x) < (y)) ? (x) : (y)) -#define MAX(x, y) (((x) > (y)) ? (x) : (y)) - -#if defined(_WIN32) -#define erf myerf -#define erfc myerfc -#endif - -#define LOG2 0.69314718055994529 - - -int test_params(int len_params, - int len_params_one_function, - char* fun_name, - char* param_names) -{ - if (len_params % len_params_one_function) { - printf("[%s]Error: Number of parameters must be a multiple of %d.", - fun_name, len_params_one_function); - printf("\nParameters expected for %s: %s\n", - fun_name, param_names); - return(1); - } - if (len_params == 0) { - printf("[%s]Error: No parameters specified.", fun_name); - printf("\nParameters expected for %s: %s\n", - fun_name, param_names); - return(1); - } - return(0); -} - -/* Complementary error function for a single value*/ -double myerfc(double x) -{ - double z; - double t; - double r; - - z=fabs(x); - t=1.0/(1.0+0.5*z); - r=t * exp(-z * z - 1.26551223 + t * (1.00002368 + t * (0.3740916 + - t * (0.09678418 + t * (-0.18628806 + t * (0.27886807 + t * (-1.13520398 + - t * (1.48851587 + t * (-0.82215223+t*0.17087277))))))))); - if (x<0) - r=2.0-r; - return (r); -} - -/* Gauss error function for a single value*/ -double myerf(double x) -{ - return (1.0 - myerfc(x)); -} - -/* Gauss error function for an array - y[i]=erf(x[i]) - returns status code 0 -*/ -int erf_array(double* x, int len_x, double* y) -{ - int j; - for (j=0; j<len_x; j++) { - y[j] = erf(x[j]); - } - return(0); -} - -/* Complementary error function for an array - y[i]=erfc(x[i]) - returns status code 0*/ -int erfc_array(double* x, int len_x, double* y) -{ - int j; - for (j=0; j<len_x; j++) { - y[j] = erfc(x[j]); - } - return(0); -} - -/* Use lookup table for fast exp computation */ -double fastexp(double x) -{ - int expindex; - static double EXP[5000] = {0.0}; - int i; - -/*initialize */ - if (EXP[0] < 1){ - for (i=0;i<5000;i++){ - EXP[i] = exp(-0.01 * i); - } - } -/*calculate*/ - if (x < 0){ - x = -x; - if (x < 50){ - expindex = (int) (x * 100); - return EXP[expindex]*(1.0 - (x - 0.01 * expindex)) ; - }else if (x < 100) { - expindex = (int) (x * 10); - return pow(EXP[expindex]*(1.0 - (x - 0.1 * expindex)),10) ; - }else if (x < 1000){ - expindex = (int) x; - return pow(EXP[expindex]*(1.0 - (x - expindex)),20) ; - }else if (x < 10000){ - expindex = (int) (x * 0.1); - return pow(EXP[expindex]*(1.0 - (x - 10.0 * expindex)),30) ; - }else{ - return 0; - } - }else{ - if (x < 50){ - expindex = (int) (x * 100); - return 1.0/EXP[expindex]*(1.0 - (x - 0.01 * expindex)) ; - }else if (x < 100) { - expindex = (int) (x * 10); - return pow(EXP[expindex]*(1.0 - (x - 0.1 * expindex)),-10) ; - }else{ - return exp(x); - } - } -} - - -/* sum_gauss - Sum of gaussian functions, defined by (height, centroid, fwhm) - - *height* is the peak amplitude - *centroid* is the peak x-coordinate - *fwhm* is the full-width at half maximum - - Parameters: - ----------- - - - x: Independant variable where the gaussians are calculated. - - len_x: Number of elements in the x array. - - pvoigt: Array of gaussian parameters: - (height1, centroid1, fwhm1, height2, centroid2, fwhm2,...) - - len_pgauss: Number of elements in the pgauss array. Must be - a multiple of 3. - - y: Output array. Must have memory allocated for the same number - of elements as x (len_x). - - Adapted from PyMca module SpecFitFuns -*/ -int sum_gauss(double* x, int len_x, double* pgauss, int len_pgauss, double* y) -{ - int i, j; - double dhelp, inv_two_sqrt_two_log2, sigma; - double fwhm, centroid, height; - - if (test_params(len_pgauss, 3, "sum_gauss", "height, centroid, fwhm")) { - return(1); - } - - /* Initialize output array */ - for (j=0; j<len_x; j++) { - y[j] = 0.; - } - - inv_two_sqrt_two_log2 = 1.0 / (2.0 * sqrt(2.0 * LOG2)); - - for (i=0; i<len_pgauss/3; i++) { - height = pgauss[3*i]; - centroid = pgauss[3*i+1]; - fwhm = pgauss[3*i+2]; - - sigma = fwhm * inv_two_sqrt_two_log2; - - for (j=0; j<len_x; j++) { - dhelp = (x[j] - centroid) / sigma; - if (dhelp <= 20) { - y[j] += height * exp (-0.5 * dhelp * dhelp); - } - } - } - return(0); -} - -/* sum_agauss - Sum of gaussian functions defined by (area, centroid, fwhm) - - *area* is the area underneath the peak - *centroid* is the peak x-coordinate - *fwhm* is the full-width at half maximum - - Parameters: - ----------- - - - x: Independant variable where the gaussians are calculated. - - len_x: Number of elements in the x array. - - pgauss: Array of gaussian parameters: - (area1, centroid1, fwhm1, area2, centroid2, fwhm2,...) - - len_pgauss: Number of elements in the pgauss array. Must be - a multiple of 3. - - y: Output array. Must have memory allocated for the same number - of elements as x (len_x). - - Adapted from PyMca module SpecFitFuns -*/ -int sum_agauss(double* x, int len_x, double* pgauss, int len_pgauss, double* y) -{ - int i, j; - double dhelp, height, sqrt2PI, sigma, inv_two_sqrt_two_log2; - double fwhm, centroid, area; - - if (test_params(len_pgauss, 3, "sum_agauss", "area, centroid, fwhm")) { - return(1); - } - - /* Initialize output array */ - for (j=0; j<len_x; j++) { - y[j] = 0.; - } - - inv_two_sqrt_two_log2 = 1.0 / (2.0 * sqrt(2.0 * LOG2)); - sqrt2PI = sqrt(2.0*M_PI); - - for (i=0; i<len_pgauss/3; i++) { - area = pgauss[3*i]; - centroid = pgauss[3*i+1]; - fwhm = pgauss[3*i+2]; - - sigma = fwhm * inv_two_sqrt_two_log2; - height = area / (sigma * sqrt2PI); - - for (j=0; j<len_x; j++) { - dhelp = (x[j] - centroid)/sigma; - if (dhelp <= 35) { - y[j] += height * exp (-0.5 * dhelp * dhelp); - } - } - } - return(0); -} - - -/* sum_fastagauss - Sum of gaussian functions defined by (area, centroid, fwhm). - This implementation uses a lookup table of precalculated exp values - and a limited development (exp(-x) = 1 - x for small values of x) - - *area* is the area underneath the peak - *centroid* is the peak x-coordinate - *fwhm* is the full-width at half maximum - - Parameters: - ----------- - - - x: Independant variable where the gaussians are calculated. - - len_x: Number of elements in the x array. - - pgauss: Array of gaussian parameters: - (area1, centroid1, fwhm1, area2, centroid2, fwhm2,...) - - len_pgauss: Number of elements in the pgauss array. Must be - a multiple of 3. - - y: Output array. Must have memory allocated for the same number - of elements as x (len_x). - - Adapted from PyMca module SpecFitFuns -*/ - -int sum_fastagauss(double* x, int len_x, double* pgauss, int len_pgauss, double* y) -{ - int i, j, expindex; - double dhelp, height, sqrt2PI, sigma, inv_two_sqrt_two_log2; - double fwhm, centroid, area; - static double EXP[5000]; - - if (test_params(len_pgauss, 3, "sum_fastagauss", "area, centroid, fwhm")) { - return(1); - } - - if (EXP[0] < 1){ - for (i=0; i<5000; i++){ - EXP[i] = exp(-0.01 * i); - } - } - - /* Initialize output array */ - for (j=0; j<len_x; j++) { - y[j] = 0.; - } - - inv_two_sqrt_two_log2 = 1.0 / (2.0 * sqrt(2.0 * LOG2)); - sqrt2PI = sqrt(2.0*M_PI); - - for (i=0; i<len_pgauss/3; i++) { - area = pgauss[3*i]; - centroid = pgauss[3*i+1]; - fwhm = pgauss[3*i+2]; - - sigma = fwhm * inv_two_sqrt_two_log2; - height = area / (sigma * sqrt2PI); - - for (j=0; j<len_x; j++) { - dhelp = (x[j] - centroid)/sigma; - if (dhelp <= 15){ - dhelp = 0.5 * dhelp * dhelp; - if (dhelp < 50){ - expindex = (int) (dhelp * 100); - y[j] += height * EXP[expindex] * (1.0 - (dhelp - 0.01 * expindex)); - } - else if (dhelp < 100) { - expindex = (int) (dhelp * 10); - y[j] += height * pow(EXP[expindex] * (1.0 - (dhelp - 0.1 * expindex)), 10); - } - else if (dhelp < 1000){ - expindex = (int) (dhelp); - y[j] += height * pow(EXP[expindex] * (1.0 - (dhelp - expindex)), 20); - } - } - } - } - return(0); -} - -/* sum_splitgauss - Sum of split gaussian functions, defined by (height, centroid, fwhm1, fwhm2) - - *height* is the peak amplitude - *centroid* is the peak x-coordinate - *fwhm1* is the full-width at half maximum of the left half of the curve (x < centroid) - *fwhm1* is the full-width at half maximum of the right half of the curve (x > centroid) - - Parameters: - ----------- - - - x: Independant variable where the gaussians are calculated. - - len_x: Number of elements in the x array. - - pgauss: Array of gaussian parameters: - (height1, centroid1, fwhm11, fwhm21, height2, centroid2, fwhm12, fwhm22,...) - - len_pgauss: Number of elements in the pgauss array. Must be - a multiple of 4. - - y: Output array. Must have memory allocated for the same number - of elements as x (len_x). - - Adapted from PyMca module SpecFitFuns -*/ -int sum_splitgauss(double* x, int len_x, double* pgauss, int len_pgauss, double* y) -{ - int i, j; - double dhelp, inv_two_sqrt_two_log2, sigma1, sigma2; - double fwhm1, fwhm2, centroid, height; - - if (test_params(len_pgauss, 4, "sum_splitgauss", "height, centroid, fwhm1, fwhm2")) { - return(1); - } - - /* Initialize output array */ - for (j=0; j<len_x; j++) { - y[j] = 0.; - } - - inv_two_sqrt_two_log2 = 1.0 / (2.0 * sqrt(2.0 * LOG2)); - - for (i=0; i<len_pgauss/4; i++) { - height = pgauss[4*i]; - centroid = pgauss[4*i+1]; - fwhm1 = pgauss[4*i+2]; - fwhm2 = pgauss[4*i+3]; - - sigma1 = fwhm1 * inv_two_sqrt_two_log2; - sigma2 = fwhm2 * inv_two_sqrt_two_log2; - - for (j=0; j<len_x; j++) { - dhelp = (x[j] - centroid); - if (dhelp > 0) { - /* Use fwhm2 when x > centroid */ - dhelp = dhelp / sigma2; - } - else { - /* Use fwhm1 when x < centroid */ - dhelp = dhelp / sigma1; - } - - if (dhelp <= 20) { - y[j] += height * exp (-0.5 * dhelp * dhelp); - } - } - } - return(0); -} - -/* sum_apvoigt - Sum of pseudo-Voigt functions, defined by (area, centroid, fwhm, eta). - - The pseudo-Voigt profile PV(x) is an approximation of the Voigt profile - using a linear combination of a Gaussian curve G(x) and a Lorentzian curve - L(x) instead of their convolution. - - *area* is the area underneath both G(x) and L(x) - *centroid* is the peak x-coordinate for both functions - *fwhm* is the full-width at half maximum of both functions - *eta* is the Lorentz factor: PV(x) = eta * L(x) + (1 - eta) * G(x) - - Parameters: - ----------- - - - x: Independant variable where the gaussians are calculated. - - len_x: Number of elements in the x array. - - pvoigt: Array of Voigt function parameters: - (area1, centroid1, fwhm1, eta1, area2, centroid2, fwhm2, eta2,...) - - len_voigt: Number of elements in the pvoigt array. Must be - a multiple of 4. - - y: Output array. Must have memory allocated for the same number - of elements as x (len_x). - - Adapted from PyMca module SpecFitFuns -*/ -int sum_apvoigt(double* x, int len_x, double* pvoigt, int len_pvoigt, double* y) -{ - int i, j; - double dhelp, inv_two_sqrt_two_log2, sqrt2PI, sigma, height; - double area, centroid, fwhm, eta; - - if (test_params(len_pvoigt, 4, "sum_apvoigt", "area, centroid, fwhm, eta")) { - return(1); - } - - /* Initialize output array */ - for (j=0; j<len_x; j++) { - y[j] = 0.; - } - - inv_two_sqrt_two_log2 = 1.0 / (2.0 * sqrt(2.0 * LOG2)); - sqrt2PI = sqrt(2.0*M_PI); - - - for (i=0; i<len_pvoigt/4; i++) { - area = pvoigt[4*i]; - centroid = pvoigt[4*i+1]; - fwhm = pvoigt[4*i+2]; - eta = pvoigt[4*i+3]; - - sigma = fwhm * inv_two_sqrt_two_log2; - height = area / (sigma * sqrt2PI); - - for (j=0; j<len_x; j++) { - /* Lorentzian term */ - dhelp = (x[j] - centroid) / (0.5 * fwhm); - dhelp = 1.0 + (dhelp * dhelp); - y[j] += eta * (area / (0.5 * M_PI * fwhm * dhelp)); - - /* Gaussian term */ - dhelp = (x[j] - centroid) / sigma; - if (dhelp <= 35) { - y[j] += (1.0 - eta) * height * exp (-0.5 * dhelp * dhelp); - } - } - } - return(0); -} - -/* sum_pvoigt - Sum of pseudo-Voigt functions, defined by (height, centroid, fwhm, eta). - - The pseudo-Voigt profile PV(x) is an approximation of the Voigt profile - using a linear combination of a Gaussian curve G(x) and a Lorentzian curve - L(x) instead of their convolution. - - *height* is the peak amplitude of G(x) and L(x) - *centroid* is the peak x-coordinate for both functions - *fwhm* is the full-width at half maximum of both functions - *eta* is the Lorentz factor: PV(x) = eta * L(x) + (1 - eta) * G(x) - - Parameters: - ----------- - - - x: Independant variable where the gaussians are calculated. - - len_x: Number of elements in the x array. - - pvoigt: Array of Voigt function parameters: - (height1, centroid1, fwhm1, eta1, height2, centroid2, fwhm2, eta2,...) - - len_voigt: Number of elements in the pvoigt array. Must be - a multiple of 4. - - y: Output array. Must have memory allocated for the same number - of elements as x (len_x). - - Adapted from PyMca module SpecFitFuns -*/ -int sum_pvoigt(double* x, int len_x, double* pvoigt, int len_pvoigt, double* y) -{ - int i, j; - double dhelp, inv_two_sqrt_two_log2, sigma; - double height, centroid, fwhm, eta; - - if (test_params(len_pvoigt, 4, "sum_pvoigt", "height, centroid, fwhm, eta")) { - return(1); - } - - /* Initialize output array */ - for (j=0; j<len_x; j++) { - y[j] = 0.; - } - - inv_two_sqrt_two_log2 = 1.0 / (2.0 * sqrt(2.0 * LOG2)); - - for (i=0; i<len_pvoigt/4; i++) { - height = pvoigt[4*i]; - centroid = pvoigt[4*i+1]; - fwhm = pvoigt[4*i+2]; - eta = pvoigt[4*i+3]; - - sigma = fwhm * inv_two_sqrt_two_log2; - - for (j=0; j<len_x; j++) { - /* Lorentzian term */ - dhelp = (x[j] - centroid) / (0.5 * fwhm); - dhelp = 1.0 + (dhelp * dhelp); - y[j] += eta * height / dhelp; - - /* Gaussian term */ - dhelp = (x[j] - centroid) / sigma; - if (dhelp <= 35) { - y[j] += (1.0 - eta) * height * exp (-0.5 * dhelp * dhelp); - } - } - } - return(0); -} - -/* sum_splitpvoigt - Sum of split pseudo-Voigt functions, defined by - (height, centroid, fwhm1, fwhm2, eta). - - The pseudo-Voigt profile PV(x) is an approximation of the Voigt profile - using a linear combination of a Gaussian curve G(x) and a Lorentzian curve - L(x) instead of their convolution. - - *height* is the peak amplitude of G(x) and L(x) - *centroid* is the peak x-coordinate for both functions - *fwhm1* is the full-width at half maximum of both functions for x < centroid - *fwhm2* is the full-width at half maximum of both functions for x > centroid - *eta* is the Lorentz factor: PV(x) = eta * L(x) + (1 - eta) * G(x) - - Parameters: - ----------- - - - x: Independant variable where the gaussians are calculated. - - len_x: Number of elements in the x array. - - pvoigt: Array of Voigt function parameters: - (height1, centroid1, fwhm11, fwhm21, eta1, ...) - - len_voigt: Number of elements in the pvoigt array. Must be - a multiple of 5. - - y: Output array. Must have memory allocated for the same number - of elements as x (len_x). - - Adapted from PyMca module SpecFitFuns -*/ -int sum_splitpvoigt(double* x, int len_x, double* pvoigt, int len_pvoigt, double* y) -{ - int i, j; - double dhelp, inv_two_sqrt_two_log2, x_minus_centroid, sigma1, sigma2; - double height, centroid, fwhm1, fwhm2, eta; - - if (test_params(len_pvoigt, 5, "sum_splitpvoigt", "height, centroid, fwhm1, fwhm2, eta")) { - return(1); - } - - /* Initialize output array */ - for (j=0; j<len_x; j++) { - y[j] = 0.; - } - - inv_two_sqrt_two_log2 = 1.0 / (2.0 * sqrt(2.0 * LOG2)); - - for (i=0; i<len_pvoigt/5; i++) { - height = pvoigt[5*i]; - centroid = pvoigt[5*i+1]; - fwhm1 = pvoigt[5*i+2]; - fwhm2 = pvoigt[5*i+3]; - eta = pvoigt[5*i+4]; - - sigma1 = fwhm1 * inv_two_sqrt_two_log2; - sigma2 = fwhm2 * inv_two_sqrt_two_log2; - - for (j=0; j<len_x; j++) { - x_minus_centroid = (x[j] - centroid); - - /* Use fwhm2 when x > centroid */ - if (x_minus_centroid > 0) { - /* Lorentzian term */ - dhelp = x_minus_centroid / (0.5 * fwhm2); - dhelp = 1.0 + (dhelp * dhelp); - y[j] += eta * height / dhelp; - - /* Gaussian term */ - dhelp = x_minus_centroid / sigma2; - if (dhelp <= 35) { - y[j] += (1.0 - eta) * height * exp (-0.5 * dhelp * dhelp); - } - } - /* Use fwhm1 when x < centroid */ - else { - /* Lorentzian term */ - dhelp = x_minus_centroid / (0.5 * fwhm1); - dhelp = 1.0 + (dhelp * dhelp); - y[j] += eta * height / dhelp; - - /* Gaussian term */ - dhelp = x_minus_centroid / sigma1; - if (dhelp <= 35) { - y[j] += (1.0 - eta) * height * exp (-0.5 * dhelp * dhelp); - } - } - } - } - return(0); -} - -/* sum_lorentz - Sum of Lorentz functions, defined by (height, centroid, fwhm). - - *height* is the peak amplitude - *centroid* is the peak's x-coordinate - *fwhm* is the full-width at half maximum - - Parameters: - ----------- - - - x: Independant variable where the Lorentzians are calculated. - - len_x: Number of elements in the x array. - - plorentz: Array of lorentz function parameters: - (height1, centroid1, fwhm1, ...) - - len_lorentz: Number of elements in the plorentz array. Must be - a multiple of 3. - - y: Output array. Must have memory allocated for the same number - of elements as x (len_x). - - Adapted from PyMca module SpecFitFuns -*/ -int sum_lorentz(double* x, int len_x, double* plorentz, int len_plorentz, double* y) -{ - int i, j; - double dhelp; - double height, centroid, fwhm; - - if (test_params(len_plorentz, 3, "sum_lorentz", "height, centroid, fwhm")) { - return(1); - } - - /* Initialize output array */ - for (j=0; j<len_x; j++) { - y[j] = 0.; - } - - for (i=0; i<len_plorentz/3; i++) { - height = plorentz[3*i]; - centroid = plorentz[3*i+1]; - fwhm = plorentz[3*i+2]; - - for (j=0; j<len_x; j++) { - dhelp = (x[j] - centroid) / (0.5 * fwhm); - dhelp = 1.0 + (dhelp * dhelp); - y[j] += height / dhelp; - } - } - return(0); -} - - -/* sum_alorentz - Sum of Lorentz functions, defined by (area, centroid, fwhm). - - *area* is the area underneath the peak - *centroid* is the peak's x-coordinate - *fwhm* is the full-width at half maximum - - Parameters: - ----------- - - - x: Independant variable where the Lorentzians are calculated. - - len_x: Number of elements in the x array. - - plorentz: Array of lorentz function parameters: - (area1, centroid1, fwhm1, ...) - - len_lorentz: Number of elements in the plorentz array. Must be - a multiple of 3. - - y: Output array. Must have memory allocated for the same number - of elements as x (len_x). - - Adapted from PyMca module SpecFitFuns -*/ -int sum_alorentz(double* x, int len_x, double* plorentz, int len_plorentz, double* y) -{ - int i, j; - double dhelp; - double area, centroid, fwhm; - - if (test_params(len_plorentz, 3, "sum_alorentz", "area, centroid, fwhm")) { - return(1); - } - - /* Initialize output array */ - for (j=0; j<len_x; j++) { - y[j] = 0.; - } - - for (i=0; i<len_plorentz/3; i++) { - area = plorentz[3*i]; - centroid = plorentz[3*i+1]; - fwhm = plorentz[3*i+2]; - - for (j=0; j<len_x; j++) { - dhelp = (x[j] - centroid) / (0.5 * fwhm); - dhelp = 1.0 + (dhelp * dhelp); - y[j] += area / (0.5 * M_PI * fwhm * dhelp); - } - } - return(0); -} - - -/* sum_splitlorentz - Sum of Lorentz functions, defined by (height, centroid, fwhm1, fwhm2). - - *height* is the peak amplitude - *centroid* is the peak's x-coordinate - *fwhm1* is the full-width at half maximum for x < centroid - *fwhm2* is the full-width at half maximum for x > centroid - - Parameters: - ----------- - - - x: Independant variable where the Lorentzians are calculated. - - len_x: Number of elements in the x array. - - plorentz: Array of lorentz function parameters: - (height1, centroid1, fwhm11, fwhm21 ...) - - len_lorentz: Number of elements in the plorentz array. Must be - a multiple of 4. - - y: Output array. Must have memory allocated for the same number - of elements as x (len_x). - - Adapted from PyMca module SpecFitFuns -*/ -int sum_splitlorentz(double* x, int len_x, double* plorentz, int len_plorentz, double* y) -{ - int i, j; - double dhelp; - double height, centroid, fwhm1, fwhm2; - - if (test_params(len_plorentz, 4, "sum_splitlorentz", "height, centroid, fwhm1, fwhm2")) { - return(1); - } - - /* Initialize output array */ - for (j=0; j<len_x; j++) { - y[j] = 0.; - } - - for (i=0; i<len_plorentz/4; i++) { - height = plorentz[4*i]; - centroid = plorentz[4*i+1]; - fwhm1 = plorentz[4*i+2]; - fwhm2 = plorentz[4*i+3]; - - for (j=0; j<len_x; j++) { - dhelp = (x[j] - centroid); - if (dhelp>0) { - dhelp = dhelp / (0.5 * fwhm2); - } - else { - dhelp = dhelp / (0.5 * fwhm1); - } - dhelp = 1.0 + (dhelp * dhelp); - y[j] += height / dhelp; - } - } - return(0); -} - -/* sum_stepdown - Sum of stepdown functions, defined by (height, centroid, fwhm). - - *height* is the step amplitude - *centroid* is the step's x-coordinate - *fwhm* is the full-width at half maximum of the derivative - - Parameters: - ----------- - - - x: Independant variable where the stepdown functions are calculated. - - len_x: Number of elements in the x array. - - pdstep: Array of downstpe function parameters: - (height1, centroid1, fwhm1, ...) - - len_pdstep: Number of elements in the pdstep array. Must be - a multiple of 3. - - y: Output array. Must have memory allocated for the same number - of elements as x (len_x). - - Adapted from PyMca module SpecFitFuns -*/ -int sum_stepdown(double* x, int len_x, double* pdstep, int len_pdstep, double* y) -{ - int i, j; - double dhelp, sqrt2_inv_2_sqrt_two_log2 ; - double height, centroid, fwhm; - - if (test_params(len_pdstep, 3, "sum_stepdown", "height, centroid, fwhm")) { - return(1); - } - - /* Initialize output array */ - for (j=0; j<len_x; j++) { - y[j] = 0.; - } - - sqrt2_inv_2_sqrt_two_log2 = sqrt(2.0) / (2.0 * sqrt(2.0 * LOG2)); - - for (i=0; i<len_pdstep/3; i++) { - height = pdstep[3*i]; - centroid = pdstep[3*i+1]; - fwhm = pdstep[3*i+2]; - - for (j=0; j<len_x; j++) { - dhelp = fwhm * sqrt2_inv_2_sqrt_two_log2; - dhelp = (x[j] - centroid) / dhelp; - y[j] += height * 0.5 * erfc(dhelp); - } - } - return(0); -} - -/* sum_stepup - Sum of stepup functions, defined by (height, centroid, fwhm). - - *height* is the step amplitude - *centroid* is the step's x-coordinate - *fwhm* is the full-width at half maximum of the derivative - - Parameters: - ----------- - - - x: Independant variable where the stepup functions are calculated. - - len_x: Number of elements in the x array. - - pustep: Array of stepdown function parameters: - (height1, centroid1, fwhm1, ...) - - len_pustep: Number of elements in the pustep array. Must be - a multiple of 3. - - y: Output array. Must have memory allocated for the same number - of elements as x (len_x). - - Adapted from PyMca module SpecFitFuns -*/ -int sum_stepup(double* x, int len_x, double* pustep, int len_pustep, double* y) -{ - int i, j; - double dhelp, sqrt2_inv_2_sqrt_two_log2 ; - double height, centroid, fwhm; - - if (test_params(len_pustep, 3, "sum_stepup", "height, centroid, fwhm")) { - return(1); - } - - /* Initialize output array */ - for (j=0; j<len_x; j++) { - y[j] = 0.; - } - - sqrt2_inv_2_sqrt_two_log2 = sqrt(2.0) / (2.0 * sqrt(2.0 * LOG2)); - - for (i=0; i<len_pustep/3; i++) { - height = pustep[3*i]; - centroid = pustep[3*i+1]; - fwhm = pustep[3*i+2]; - - for (j=0; j<len_x; j++) { - dhelp = fwhm * sqrt2_inv_2_sqrt_two_log2; - dhelp = (x[j] - centroid) / dhelp; - y[j] += height * 0.5 * (1.0 + erf(dhelp)); - } - } - return(0); -} - - -/* sum_slit - Sum of slit functions, defined by (height, position, fwhm, beamfwhm). - - *height* is the slit height - *position* is the slit's center x-coordinate - *fwhm* is the full-width at half maximum of the slit - *beamfwhm* is the full-width at half maximum of derivative's peaks - - Parameters: - ----------- - - - x: Independant variable where the slit functions are calculated. - - len_x: Number of elements in the x array. - - pslit: Array of slit function parameters: - (height1, centroid1, fwhm1, beamfwhm1 ...) - - len_pslit: Number of elements in the pslit array. Must be - a multiple of 3. - - y: Output array. Must have memory allocated for the same number - of elements as x (len_x). - - Adapted from PyMca module SpecFitFuns -*/ -int sum_slit(double* x, int len_x, double* pslit, int len_pslit, double* y) -{ - int i, j; - double dhelp, dhelp1, dhelp2, sqrt2_inv_2_sqrt_two_log2, centroid1, centroid2; - double height, position, fwhm, beamfwhm; - - if (test_params(len_pslit, 4, "sum_slit", "height, centroid, fwhm, beamfwhm")) { - return(1); - } - - /* Initialize output array */ - for (j=0; j<len_x; j++) { - y[j] = 0.; - } - - sqrt2_inv_2_sqrt_two_log2 = sqrt(2.0) / (2.0 * sqrt(2.0 * LOG2)); - - for (i=0; i<len_pslit/4; i++) { - height = pslit[4*i]; - position = pslit[4*i+1]; - fwhm = pslit[4*i+2]; - beamfwhm = pslit[4*i+3]; - - centroid1 = position - 0.5 * fwhm; - centroid2 = position + 0.5 * fwhm; - - for (j=0; j<len_x; j++) { - dhelp = beamfwhm * sqrt2_inv_2_sqrt_two_log2; - dhelp1 = (x[j] - centroid1) / dhelp; - dhelp2 = (x[j] - centroid2) / dhelp; - y[j] += height * 0.25 * (1.0 + erf(dhelp1)) * erfc(dhelp2); - } - } - return(0); -} - - -/* sum_ahypermet - Sum of hypermet functions, defined by - (area, position, fwhm, st_area_r, st_slope_r, lt_area_r, lt_slope_r, step_height_r). - - - *area* is the area underneath the gaussian peak - - *position* is the center of the various peaks and the position of - the step down - - *fwhm* is the full-width at half maximum of the terms - - *st_area_r* is factor between the gaussian area and the area of the - short tail term - - *st_slope_r* is a parameter related to the slope of the short tail - in the low ``x`` values (the lower, the steeper) - - *lt_area_r* is factor between the gaussian area and the area of the - long tail term - - *lt_slope_r* is a parameter related to the slope of the long tail - in the low ``x`` values (the lower, the steeper) - - *step_height_r* is the factor between the height of the step down - and the gaussian height - - Parameters: - ----------- - - - x: Independant variable where the functions are calculated. - - len_x: Number of elements in the x array. - - phypermet: Array of hypermet function parameters: - *(area1, position1, fwhm1, st_area_r1, st_slope_r1, lt_area_r1, - lt_slope_r1, step_height_r1, ...)* - - len_phypermet: Number of elements in the phypermet array. Must be - a multiple of 8. - - y: Output array. Must have memory allocated for the same number - of elements as x (len_x). - - tail_flags: sum of binary flags to activate the various terms of the - function: - - - 1 (b0001): Gaussian term - - 2 (b0010): st term - - 4 (b0100): lt term - - 8 (b1000): step term - - E.g., to activate all termsof the hypermet, use ``tail_flags = 1 + 2 + 4 + 8 = 15`` - - Adapted from PyMca module SpecFitFuns -*/ -int sum_ahypermet(double* x, int len_x, double* phypermet, int len_phypermet, double* y, int tail_flags) -{ - int i, j; - int g_term_flag, st_term_flag, lt_term_flag, step_term_flag; - double c1, c2, sigma, height, sigma_sqrt2, sqrt2PI, inv_2_sqrt_2_log2, x_minus_position, epsilon; - double area, position, fwhm, st_area_r, st_slope_r, lt_area_r, lt_slope_r, step_height_r; - - if (test_params(len_phypermet, 8, "sum_hypermet", - "height, centroid, fwhm, st_area_r, st_slope_r, lt_area_r, lt_slope_r, step_height_r")) { - return(1); - } - - g_term_flag = tail_flags & 1; - st_term_flag = (tail_flags>>1) & 1; - lt_term_flag = (tail_flags>>2) & 1; - step_term_flag = (tail_flags>>3) & 1; - - /* Initialize output array */ - for (j=0; j<len_x; j++) { - y[j] = 0.; - } - - /* define epsilon to compare floating point values with 0. */ - epsilon = 0.00000000001; - - sqrt2PI= sqrt(2.0 * M_PI); - inv_2_sqrt_2_log2 = 1.0 / (2.0 * sqrt(2.0 * LOG2)); - - for (i=0; i<len_phypermet/8; i++) { - area = phypermet[8*i]; - position = phypermet[8*i+1]; - fwhm = phypermet[8*i+2]; - st_area_r = phypermet[8*i+3]; - st_slope_r = phypermet[8*i+4]; - lt_area_r = phypermet[8*i+5]; - lt_slope_r = phypermet[8*i+6]; - step_height_r = phypermet[8*i+7]; - - sigma = fwhm * inv_2_sqrt_2_log2; - height = area / (sigma * sqrt2PI); - - /* Prevent division by 0 */ - if (sigma == 0) { - printf("fwhm must not be equal to 0"); - return(1); - } - sigma_sqrt2 = sigma * 1.4142135623730950488; - - for (j=0; j<len_x; j++) { - x_minus_position = x[j] - position; - c2 = (0.5 * x_minus_position * x_minus_position) / (sigma * sigma); - /* gaussian term */ - if (g_term_flag) { - y[j] += exp(-c2) * height; - } - - /* st term */ - if (st_term_flag) { - if (fabs(st_slope_r) > epsilon) { - c1 = st_area_r * 0.5 * \ - erfc((x_minus_position/sigma_sqrt2) + 0.5 * sigma_sqrt2 / st_slope_r); - y[j] += ((area * c1) / st_slope_r) * \ - exp(0.5 * (sigma / st_slope_r) * (sigma / st_slope_r) + \ - (x_minus_position / st_slope_r)); - } - } - - /* lt term */ - if (lt_term_flag) { - if (fabs(lt_slope_r) > epsilon) { - c1 = lt_area_r * \ - 0.5 * erfc((x_minus_position/sigma_sqrt2) + 0.5 * sigma_sqrt2 / lt_slope_r); - y[j] += ((area * c1) / lt_slope_r) * \ - exp(0.5 * (sigma / lt_slope_r) * (sigma / lt_slope_r) + \ - (x_minus_position / lt_slope_r)); - } - } - - /* step term flag */ - if (step_term_flag) { - y[j] += step_height_r * (area / (sigma * sqrt2PI)) * \ - 0.5 * erfc(x_minus_position / sigma_sqrt2); - } - } - } - return(0); -} - -/* sum_fastahypermet - - Sum of hypermet functions, defined by - (area, position, fwhm, st_area_r, st_slope_r, lt_area_r, lt_slope_r, step_height_r). - - - *area* is the area underneath the gaussian peak - - *position* is the center of the various peaks and the position of - the step down - - *fwhm* is the full-width at half maximum of the terms - - *st_area_r* is factor between the gaussian area and the area of the - short tail term - - *st_slope_r* is a parameter related to the slope of the short tail - in the low ``x`` values (the lower, the steeper) - - *lt_area_r* is factor between the gaussian area and the area of the - long tail term - - *lt_slope_r* is a parameter related to the slope of the long tail - in the low ``x`` values (the lower, the steeper) - - *step_height_r* is the factor between the height of the step down - and the gaussian height - - Parameters: - ----------- - - - x: Independant variable where the functions are calculated. - - len_x: Number of elements in the x array. - - phypermet: Array of hypermet function parameters: - *(area1, position1, fwhm1, st_area_r1, st_slope_r1, lt_area_r1, - lt_slope_r1, step_height_r1, ...)* - - len_phypermet: Number of elements in the phypermet array. Must be - a multiple of 8. - - y: Output array. Must have memory allocated for the same number - of elements as x (len_x). - - tail_flags: sum of binary flags to activate the various terms of the - function: - - - 1 (b0001): Gaussian term - - 2 (b0010): st term - - 4 (b0100): lt term - - 8 (b1000): step term - - E.g., to activate all termsof the hypermet, use ``tail_flags = 1 + 2 + 4 + 8 = 15`` - - Adapted from PyMca module SpecFitFuns -*/ -int sum_fastahypermet(double* x, int len_x, double* phypermet, int len_phypermet, double* y, int tail_flags) -{ - int i, j; - int g_term_flag, st_term_flag, lt_term_flag, step_term_flag; - double c1, c2, sigma, height, sigma_sqrt2, sqrt2PI, inv_2_sqrt_2_log2, x_minus_position, epsilon; - double area, position, fwhm, st_area_r, st_slope_r, lt_area_r, lt_slope_r, step_height_r; - - if (test_params(len_phypermet, 8, "sum_hypermet", - "height, centroid, fwhm, st_area_r, st_slope_r, lt_area_r, lt_slope_r, step_height_r")) { - return(1); - } - - g_term_flag = tail_flags & 1; - st_term_flag = (tail_flags>>1) & 1; - lt_term_flag = (tail_flags>>2) & 1; - step_term_flag = (tail_flags>>3) & 1; - - /* Initialize output array */ - for (j=0; j<len_x; j++) { - y[j] = 0.; - } - - /* define epsilon to compare floating point values with 0. */ - epsilon = 0.00000000001; - - sqrt2PI= sqrt(2.0 * M_PI); - inv_2_sqrt_2_log2 = 1.0 / (2.0 * sqrt(2.0 * LOG2)); - - for (i=0; i<len_phypermet/8; i++) { - area = phypermet[8*i]; - position = phypermet[8*i+1]; - fwhm = phypermet[8*i+2]; - st_area_r = phypermet[8*i+3]; - st_slope_r = phypermet[8*i+4]; - lt_area_r = phypermet[8*i+5]; - lt_slope_r = phypermet[8*i+6]; - step_height_r = phypermet[8*i+7]; - - sigma = fwhm * inv_2_sqrt_2_log2; - height = area / (sigma * sqrt2PI); - - /* Prevent division by 0 */ - if (sigma == 0) { - printf("fwhm must not be equal to 0"); - return(1); - } - sigma_sqrt2 = sigma * 1.4142135623730950488; - - for (j=0; j<len_x; j++) { - x_minus_position = x[j] - position; - c2 = (0.5 * x_minus_position * x_minus_position) / (sigma * sigma); - /* gaussian term */ - if (g_term_flag && c2 < 100) { - y[j] += fastexp(-c2) * height; - } - - /* st term */ - if (st_term_flag && (fabs(st_slope_r) > epsilon) && (x_minus_position / st_slope_r) <= 612) { - c1 = st_area_r * 0.5 * \ - erfc((x_minus_position/sigma_sqrt2) + 0.5 * sigma_sqrt2 / st_slope_r); - y[j] += ((area * c1) / st_slope_r) * \ - fastexp(0.5 * (sigma / st_slope_r) * (sigma / st_slope_r) +\ - (x_minus_position / st_slope_r)); - } - - /* lt term */ - if (lt_term_flag && (fabs(lt_slope_r) > epsilon) && (x_minus_position / lt_slope_r) <= 612) { - c1 = lt_area_r * \ - 0.5 * erfc((x_minus_position/sigma_sqrt2) + 0.5 * sigma_sqrt2 / lt_slope_r); - y[j] += ((area * c1) / lt_slope_r) * \ - fastexp(0.5 * (sigma / lt_slope_r) * (sigma / lt_slope_r) +\ - (x_minus_position / lt_slope_r)); - - } - - /* step term flag */ - if (step_term_flag) { - y[j] += step_height_r * (area / (sigma * sqrt2PI)) *\ - 0.5 * erfc(x_minus_position / sigma_sqrt2); - } - } - } - return(0); -} - -void pileup(double* x, long len_x, double* ret, int input2, double zero, double gain) -{ - //int input2=0; - //double zero=0.0; - //double gain=1.0; - - int i, j, k; - double *px, *pret, *pall; - - /* the pointer to the starting position of par data */ - px = x; - pret = ret; - - *pret = 0; - k = (int )(zero/gain); - for (i=input2; i<len_x; i++){ - pall = x; - if ((i+k) >= 0) - { - pret = (double *) ret+(i+k); - for (j=0; j<len_x-i-k ;j++){ - *pret += *px * (*pall); - pall++; - pret++; - } - } - px++; - } -} |