source: sasview/pr_inversion/c_extensions/invertor.c @ a17ffdf

ESS_GUIESS_GUI_DocsESS_GUI_batch_fittingESS_GUI_bumps_abstractionESS_GUI_iss1116ESS_GUI_iss879ESS_GUI_iss959ESS_GUI_openclESS_GUI_orderingESS_GUI_sync_sascalccostrafo411magnetic_scattrelease-4.1.1release-4.1.2release-4.2.2release_4.0.1ticket-1009ticket-1094-headlessticket-1242-2d-resolutionticket-1243ticket-1249ticket885unittest-saveload
Last change on this file since a17ffdf was 9a23253e, checked in by Mathieu Doucet <doucetm@…>, 16 years ago

Started to add slit smearing. Added Rg and I(q=0) as outputs.

  • Property mode set to 100644
File size: 6.5 KB
Line 
1#include <math.h>
2#include "invertor.h"
3#include <memory.h>
4#include <stdio.h>
5#include <stdlib.h>
6
7double pi = 3.1416;
8
9/**
10 * Deallocate memory
11 */
12void invertor_dealloc(Invertor_params *pars) {
13        free(pars->x);
14        free(pars->y);
15        free(pars->err);
16}
17
18void invertor_init(Invertor_params *pars) {
19        pars->d_max = 180;
20        pars->q_min = -1.0;
21        pars->q_max = -1.0;
22        pars->has_bck = 0;
23}
24
25
26/**
27 * P(r) of a sphere, for test purposes
28 *
29 * @param R: radius of the sphere
30 * @param r: distance, in the same units as the radius
31 * @return: P(r)
32 */
33double pr_sphere(double R, double r) {
34    if (r <= 2.0*R) {
35        return 12.0* pow(0.5*r/R, 2.0) * pow(1.0-0.5*r/R, 2.0) * ( 2.0 + 0.5*r/R );
36    } else {
37        return 0.0;
38    }
39}
40
41/**
42 * Orthogonal functions:
43 * B(r) = 2r sin(pi*nr/d)
44 *
45 */
46double ortho(double d_max, int n, double r) {
47        return 2.0*r*sin(pi*n*r/d_max);
48}
49
50/**
51 * Fourier transform of the nth orthogonal function
52 *
53 */
54double ortho_transformed(double d_max, int n, double q) {
55        return 8.0*pow(pi, 2.0)/q * d_max * n * pow(-1.0, n+1)
56                *sin(q*d_max) / ( pow(pi*n, 2.0) - pow(q*d_max, 2.0) );
57}
58
59/**
60 * Slit-smeared Fourier transform of the nth orthogonal function.
61 * Smearing follows Lake, Acta Cryst. (1967) 23, 191.
62 */
63double ortho_transformed_smeared(double d_max, int n, double height, double width, double q, int npts) {
64        double sum, value, y, z;
65        int i, j;
66        double fnpts;
67        sum = 0.0;
68        fnpts = (float)npts-1.0;
69
70        for(i=0; i<npts; i++) {
71                y = -width/2.0+width/fnpts*(float)i;
72                for(j=0; j<npts; j++) {
73                        z = height/fnpts*(float)j;
74                        sum += ortho_transformed(d_max, n, sqrt((q-y)*(q-y)+z*z));
75                }
76        }
77
78        return sum/npts/npts/height/width;
79}
80
81/**
82 * First derivative in of the orthogonal function dB(r)/dr
83 *
84 */
85double ortho_derived(double d_max, int n, double r) {
86    return 2.0*sin(pi*n*r/d_max) + 2.0*r*cos(pi*n*r/d_max);
87}
88
89/**
90 * Scattering intensity calculated from the expansion.
91 */
92double iq(double *pars, double d_max, int n_c, double q) {
93    double sum = 0.0;
94        int i;
95    for (i=0; i<n_c; i++) {
96        sum += pars[i] * ortho_transformed(d_max, i+1, q);
97    }
98    return sum;
99}
100
101/**
102 * P(r) calculated from the expansion.
103 */
104double pr(double *pars, double d_max, int n_c, double r) {
105    double sum = 0.0;
106        int i;
107    for (i=0; i<n_c; i++) {
108        sum += pars[i] * ortho(d_max, i+1, r);
109    }
110    return sum;
111}
112
113/**
114 * P(r) calculated from the expansion, with errors
115 */
116void pr_err(double *pars, double *err, double d_max, int n_c,
117                double r, double *pr_value, double *pr_value_err) {
118    double sum = 0.0;
119    double sum_err = 0.0;
120    double func_value;
121        int i;
122    for (i=0; i<n_c; i++) {
123        func_value = ortho(d_max, i+1, r);
124        sum += pars[i] * func_value;
125        //sum_err += err[i]*err[i]*func_value*func_value;
126        sum_err += err[i*n_c+i]*func_value*func_value;
127    }
128    *pr_value = sum;
129    if (sum_err>0) {
130        *pr_value_err = sqrt(sum_err);
131    } else {
132        *pr_value_err = sum;
133    }
134}
135
136/**
137 * dP(r)/dr calculated from the expansion.
138 */
139double dprdr(double *pars, double d_max, int n_c, double r) {
140    double sum = 0.0;
141        int i;
142    for (i=0; i<n_c; i++) {
143        sum += pars[i] * 2.0*(sin(pi*(i+1)*r/d_max) + pi*(i+1)*r/d_max * cos(pi*(i+1)*r/d_max));
144    }
145    return sum;
146}
147
148/**
149 * regularization term calculated from the expansion.
150 */
151double reg_term(double *pars, double d_max, int n_c, int nslice) {
152    double sum = 0.0;
153    double r;
154    double deriv;
155        int i;
156    for (i=0; i<nslice; i++) {
157        r = d_max/(1.0*nslice)*i;
158        deriv = dprdr(pars, d_max, n_c, r);
159        sum += deriv*deriv;
160    }
161    return sum/(1.0*nslice)*d_max;
162}
163
164/**
165 * regularization term calculated from the expansion.
166 */
167double int_p2(double *pars, double d_max, int n_c, int nslice) {
168    double sum = 0.0;
169    double r;
170    double value;
171        int i;
172    for (i=0; i<nslice; i++) {
173        r = d_max/(1.0*nslice)*i;
174        value = pr(pars, d_max, n_c, r);
175        sum += value*value;
176    }
177    return sum/(1.0*nslice)*d_max;
178}
179
180/**
181 * Integral of P(r)
182 */
183double int_pr(double *pars, double d_max, int n_c, int nslice) {
184    double sum = 0.0;
185    double r;
186    double value;
187        int i;
188    for (i=0; i<nslice; i++) {
189        r = d_max/(1.0*nslice)*i;
190        value = pr(pars, d_max, n_c, r);
191        sum += value;
192    }
193    return sum/(1.0*nslice)*d_max;
194}
195
196/**
197 * Get the number of P(r) peaks.
198 */
199int npeaks(double *pars, double d_max, int n_c, int nslice) {
200    double r;
201    double value;
202        int i;
203        double previous = 0.0;
204        double slope    = 0.0;
205        int count = 0;
206    for (i=0; i<nslice; i++) {
207        r = d_max/(1.0*nslice)*i;
208        value = pr(pars, d_max, n_c, r);
209        if (previous<=value){
210                //if (slope<0) count += 1;
211                slope = 1;
212        } else {
213                //printf("slope -1");
214                if (slope>0) count += 1;
215                slope = -1;
216        }
217        previous = value;
218    }
219    return count;
220}
221
222/**
223 * Get the fraction of the integral of P(r) over the whole range
224 * of r that is above zero.
225 * A valid P(r) is define as being positive for all r.
226 */
227double positive_integral(double *pars, double d_max, int n_c, int nslice) {
228    double r;
229    double value;
230        int i;
231        double sum_pos = 0.0;
232        double sum = 0.0;
233
234    for (i=0; i<nslice; i++) {
235        r = d_max/(1.0*nslice)*i;
236        value = pr(pars, d_max, n_c, r);
237        if (value>0.0) sum_pos += value;
238        sum += fabs(value);
239    }
240    return sum_pos/sum;
241}
242
243/**
244 * Get the fraction of the integral of P(r) over the whole range
245 * of r that is at least one sigma above zero.
246 */
247double positive_errors(double *pars, double *err, double d_max, int n_c, int nslice) {
248    double r;
249    double value;
250        int i;
251        double sum_pos = 0.0;
252        double sum = 0.0;
253        double pr_val;
254        double pr_val_err;
255
256    for (i=0; i<nslice; i++) {
257        r = d_max/(1.0*nslice)*i;
258        pr_err(pars, err, d_max, n_c, r, &pr_val, &pr_val_err);
259        if (pr_val>pr_val_err) sum_pos += pr_val;
260        sum += fabs(pr_val);
261
262
263    }
264    return sum_pos/sum;
265}
266
267/**
268 * R_g radius of gyration calculation
269 *
270 * R_g**2 = integral[r**2 * p(r) dr] /  (2.0 * integral[p(r) dr])
271 */
272double rg(double *pars, double d_max, int n_c, int nslice) {
273    double sum_r2 = 0.0;
274    double sum    = 0.0;
275    double r;
276    double value;
277        int i;
278    for (i=0; i<nslice; i++) {
279        r = d_max/(1.0*nslice)*i;
280        value = pr(pars, d_max, n_c, r);
281        sum += value;
282        sum_r2 += r*r*value;
283    }
284    return sqrt(sum_r2/(2.0*sum));
285}
286
Note: See TracBrowser for help on using the repository browser.