source: sasview/sansmodels/src/sans/models/c_models/parameters.cpp @ 89b7858

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 89b7858 was a5e14410, checked in by Jae Cho <jhjcho@…>, 13 years ago

safer default values for polydispersion and lognormal fix

  • Property mode set to 100644
File size: 11.6 KB
Line 
1/**
2        This software was developed by the University of Tennessee as part of the
3        Distributed Data Analysis of Neutron Scattering Experiments (DANSE)
4        project funded by the US National Science Foundation.
5
6        If you use DANSE applications to do scientific research that leads to
7        publication, we ask that you acknowledge the use of the software with the
8        following sentence:
9
10        "This work benefited from DANSE software developed under NSF award DMR-0520547."
11
12        copyright 2008, University of Tennessee
13 */
14#include "parameters.hh"
15#include <stdio.h>
16#include <math.h>
17using namespace std;
18
19/**
20 * TODO: normalize all dispersion weight lists
21 */
22
23
24/**
25 * Weight points
26 */
27WeightPoint :: WeightPoint() {
28        value = 0.0;
29        weight = 0.0;
30}
31
32WeightPoint :: WeightPoint(double v, double w) {
33        value = v;
34        weight = w;
35}
36
37/**
38 * Dispersion models
39 */
40DispersionModel :: DispersionModel() {
41        npts  = 1;
42        width = 0.0;
43};
44
45void DispersionModel :: accept_as_source(DispersionVisitor* visitor, void* from, void* to) {
46        visitor->dispersion_to_dict(from, to);
47}
48void DispersionModel :: accept_as_destination(DispersionVisitor* visitor, void* from, void* to) {
49        visitor->dispersion_from_dict(from, to);
50}
51void DispersionModel :: operator() (void *param, vector<WeightPoint> &weights){
52        // Check against zero width
53        if (width<=0) {
54                width = 0.0;
55                npts  = 1;
56        }
57
58        Parameter* par = (Parameter*)param;
59        double value = (*par)();
60        double sig;
61        if (npts<2) {
62                weights.insert(weights.end(), WeightPoint(value, 1.0));
63        } else {
64                for(int i=0; i<npts; i++) {
65
66                        if ((*par).has_min==false){
67                                // width = sigma for angles
68                                sig = width;
69                        }
70                        else{
71                                //width = polydispersity (=sigma/value) for length
72                                sig = width * value;
73                        }
74                        double val = value + sig * (1.0*double(i)/double(npts-1) - 0.5);
75                        if ( ((*par).has_min==false || val>(*par).min)
76                          && ((*par).has_max==false || val<(*par).max)  )
77                                weights.insert(weights.end(), WeightPoint(val, 1.0));
78                }
79        }
80}
81
82/**
83 * Method to set the weights
84 * Not implemented for this class
85 */
86void DispersionModel :: set_weights(int npoints, double* values, double* weights){}
87
88/**
89 * Gaussian dispersion
90 */
91
92GaussianDispersion :: GaussianDispersion() {
93        npts  = 100;
94        width = 0.0;
95        nsigmas = 10;
96};
97
98void GaussianDispersion :: accept_as_source(DispersionVisitor* visitor, void* from, void* to) {
99        visitor->gaussian_to_dict(from, to);
100}
101void GaussianDispersion :: accept_as_destination(DispersionVisitor* visitor, void* from, void* to) {
102        visitor->gaussian_from_dict(from, to);
103}
104
105double gaussian_weight(double mean, double sigma, double x) {
106        double vary, expo_value;
107    vary = x-mean;
108    expo_value = -vary*vary/(2.0*sigma*sigma);
109    //return 1.0;
110    return exp(expo_value);
111}
112
113/**
114 * Gaussian dispersion
115 * @param mean: mean value of the Gaussian
116 * @param sigma: standard deviation of the Gaussian
117 * @param x: value at which the Gaussian is evaluated
118 * @return: value of the Gaussian
119 */
120void GaussianDispersion :: operator() (void *param, vector<WeightPoint> &weights){
121        // Check against zero width
122        if (width<=0) {
123                width = 0.0;
124                npts  = 1;
125                nsigmas = 10;
126        }
127
128        Parameter* par = (Parameter*)param;
129        double value = (*par)();
130        double sig;
131        if (npts<2) {
132                weights.insert(weights.end(), WeightPoint(value, 1.0));
133        } else {
134                for(int i=0; i<npts; i++) {
135                        if ((*par).has_min==false){
136                                // width = sigma for angles
137                                sig = width;
138                        }
139                        else{
140                                //width = polydispersity (=sigma/value) for length
141                                sig = width * value;
142                        }
143                        // We cover n(nsigmas) times sigmas on each side of the mean
144                        double val = value + sig * (2.0*nsigmas*double(i)/double(npts-1) - nsigmas);
145                        if ( ((*par).has_min==false || val>(*par).min)
146                          && ((*par).has_max==false || val<(*par).max)  ) {
147                                double _w = gaussian_weight(value, sig, val);
148                                weights.insert(weights.end(), WeightPoint(val, _w));
149                        }
150                }
151        }
152}
153
154
155/**
156 * Flat dispersion
157 */
158
159RectangleDispersion :: RectangleDispersion() {
160        npts  = 100;
161        width = 0.0;
162        nsigmas = 1.73205;
163};
164
165void RectangleDispersion :: accept_as_source(DispersionVisitor* visitor, void* from, void* to) {
166        visitor->rectangle_to_dict(from, to);
167}
168void RectangleDispersion :: accept_as_destination(DispersionVisitor* visitor, void* from, void* to) {
169        visitor->rectangle_from_dict(from, to);
170}
171
172double rectangle_weight(double mean, double sigma, double x) {
173        double vary, expo_value;
174    double wid = fabs(sigma) * sqrt(3.0);
175    if (x>= (mean-wid) && x<=(mean+wid)){
176        return 1.0;
177    }
178    else{
179        return 0.0;
180    }
181}
182
183/**
184 * Flat dispersion
185 * @param mean: mean value
186 * @param sigma: half width of top hat function
187 * @param x: value at which the Flat is evaluated
188 * @return: value of the Flat
189 */
190void RectangleDispersion :: operator() (void *param, vector<WeightPoint> &weights){
191        // Check against zero width
192        if (width<=0) {
193                width = 0.0;
194                npts  = 1;
195                nsigmas = 1.73205;
196        }
197
198        Parameter* par = (Parameter*)param;
199        double value = (*par)();
200        double sig;
201        if (npts<2) {
202                weights.insert(weights.end(), WeightPoint(value, 1.0));
203        } else {
204                for(int i=0; i<npts; i++) {
205                        if ((*par).has_min==false){
206                                // width = sigma for angles
207                                sig = width;
208                        }
209                        else{
210                                //width = polydispersity (=sigma/value) for length
211                                sig = width * value;
212                        }
213                        // We cover n(nsigmas) times sigmas on each side of the mean
214                        double val = value + sig * (2.0*nsigmas*double(i)/double(npts-1) - nsigmas);
215                        if ( ((*par).has_min==false || val>(*par).min)
216                          && ((*par).has_max==false || val<(*par).max)  ) {
217                                double _w = rectangle_weight(value, sig, val);
218                                weights.insert(weights.end(), WeightPoint(val, _w));
219                        }
220                }
221        }
222}
223
224
225/**
226 * LogNormal dispersion
227 */
228
229LogNormalDispersion :: LogNormalDispersion() {
230        npts  = 100;
231        width = 0.0;
232        nsigmas = 10.0;
233};
234
235void LogNormalDispersion :: accept_as_source(DispersionVisitor* visitor, void* from, void* to) {
236        visitor->lognormal_to_dict(from, to);
237}
238void LogNormalDispersion :: accept_as_destination(DispersionVisitor* visitor, void* from, void* to) {
239        visitor->lognormal_from_dict(from, to);
240}
241
242double lognormal_weight(double mean, double sigma, double x) {
243
244        double sigma2 = pow(sigma, 2.0);
245        return 1.0/(x*sigma) * exp( -pow((log(x) - mean), 2.0) / (2.0*sigma2));
246
247}
248
249/**
250 * Lognormal dispersion
251 * @param mean: mean value of the LogNormal
252 * @param sigma: standard deviation of the LogNormal
253 * @param x: value at which the LogNormal is evaluated
254 * @return: value of the LogNormal
255 */
256void LogNormalDispersion :: operator() (void *param, vector<WeightPoint> &weights){
257        // Check against zero width
258        if (width<=0) {
259                width = 0.0;
260                npts  = 1;
261                nsigmas = 10.0;
262        }
263
264        Parameter* par = (Parameter*)param;
265        double value = (*par)();
266        double sig;
267        double log_value;
268        if (npts<2) {
269                weights.insert(weights.end(), WeightPoint(value, 1.0));
270        } else {
271                for(int i=0; i<npts; i++) {
272                        // Note that the definition of sigma is different from Gaussian
273                        if ((*par).has_min==false){
274                                // sig  for angles
275                                sig = width;
276                        }
277                        else{
278                                // by lognormal definition, PD is same as sigma
279                                sig = width * value;
280                        }
281                       
282                        // We cover n(nsigmas) times sigmas on each side of the mean
283                        //constant bin in real space
284                        double val = value + sig * (2.0*nsigmas*double(i)/double(npts-1) - nsigmas);
285                        // sigma in the lognormal function is in ln(R) space, thus needs converting
286                        sig = fabs(sig/value); 
287                        if ( ((*par).has_min==false || val>(*par).min)
288                          && ((*par).has_max==false || val<(*par).max)  ) {
289                                double _w = lognormal_weight(log(value), sig, val);
290                                weights.insert(weights.end(), WeightPoint(val, _w));
291                                //printf("%g \t %g\n",val,_w);
292
293                        }
294                }
295        }
296}
297
298
299
300/**
301 * Schulz dispersion
302 */
303
304SchulzDispersion :: SchulzDispersion() {
305        npts  = 100;
306        width = 0.0;
307        nsigmas = 10.0;
308};
309
310void SchulzDispersion :: accept_as_source(DispersionVisitor* visitor, void* from, void* to) {
311        visitor->schulz_to_dict(from, to);
312}
313void SchulzDispersion :: accept_as_destination(DispersionVisitor* visitor, void* from, void* to) {
314        visitor->schulz_from_dict(from, to);
315}
316
317double schulz_weight(double mean, double sigma, double x) {
318        double vary, expo_value;
319    double z = pow(mean/ sigma, 2.0)-1.0;
320        double R= x/mean;
321        double zz= z+1.0;
322        double expo;
323        expo = zz*log(zz)+z*log(R)-R*zz-log(mean)-lgamma(zz);
324        return  exp(expo);
325}
326
327/**
328 * Schulz dispersion
329 * @param mean: mean value of the Schulz
330 * @param sigma: standard deviation of the Schulz
331 * @param x: value at which the Schulz is evaluated
332 * @return: value of the Schulz
333 */
334void SchulzDispersion :: operator() (void *param, vector<WeightPoint> &weights){
335        // Check against zero width
336        if (width<=0) {
337                width = 0.0;
338                npts  = 1;
339                nsigmas = 10.0;
340        }
341
342        Parameter* par = (Parameter*)param;
343        double value = (*par)();
344        double sig;
345        if (npts<2) {
346                weights.insert(weights.end(), WeightPoint(value, 1.0));
347        } else {
348                for(int i=0; i<npts; i++) {
349                        if ((*par).has_min==false){
350                                // width = sigma for angles
351                                sig = width;
352                        }
353                        else{
354                                //width = polydispersity (=sigma/value) for length
355                                sig = width * value;
356                        }
357                        // We cover n(nsigmas) times sigmas on each side of the mean
358                        double val = value + sig * (2.0*nsigmas*double(i)/double(npts-1) - nsigmas);
359
360                        if ( ((*par).has_min==false || val>(*par).min)
361                          && ((*par).has_max==false || val<(*par).max)  ) {
362                                double _w = schulz_weight(value, sig, val);
363                                weights.insert(weights.end(), WeightPoint(val, _w));
364                        }
365                }
366        }
367}
368
369
370
371
372/**
373 * Array dispersion based on input arrays
374 */
375
376void ArrayDispersion :: accept_as_source(DispersionVisitor* visitor, void* from, void* to) {
377        visitor->array_to_dict(from, to);
378}
379void ArrayDispersion :: accept_as_destination(DispersionVisitor* visitor, void* from, void* to) {
380        visitor->array_from_dict(from, to);
381}
382
383/**
384 * Method to get the weights
385 */
386void ArrayDispersion :: operator() (void *param, vector<WeightPoint> &weights) {
387        Parameter* par = (Parameter*)param;
388        double value = (*par)();
389
390        if (npts<2) {
391                weights.insert(weights.end(), WeightPoint(value, 1.0));
392        } else {
393                for(int i=0; i<npts; i++) {
394                        double val = _values[i]; //+ value;  //ToDo: Talk to Paul and put back the 'value'.
395
396                        if ( ((*par).has_min==false || val>(*par).min)
397                          && ((*par).has_max==false || val<(*par).max)  )
398                                weights.insert(weights.end(), WeightPoint(val, _weights[i]));
399                }
400        }
401}
402/**
403 * Method to set the weights
404 */
405void ArrayDispersion :: set_weights(int npoints, double* values, double* weights){
406        npts = npoints;
407        _values = values;
408        _weights = weights;
409}
410
411
412/**
413 * Parameters
414 */
415Parameter :: Parameter() {
416        value = 0;
417        min   = 0.0;
418        max   = 0.0;
419        has_min = false;
420        has_max = false;
421        has_dispersion = false;
422        dispersion = new GaussianDispersion();
423}
424
425Parameter :: Parameter(double _value) {
426        value = _value;
427        min   = 0.0;
428        max   = 0.0;
429        has_min = false;
430        has_max = false;
431        has_dispersion = false;
432        dispersion = new GaussianDispersion();
433}
434
435Parameter :: Parameter(double _value, bool disp) {
436        value = _value;
437        min   = 0.0;
438        max   = 0.0;
439        has_min = false;
440        has_max = false;
441        has_dispersion = disp;
442        dispersion = new GaussianDispersion();
443}
444
445void Parameter :: get_weights(vector<WeightPoint> &weights) {
446        (*dispersion)((void*)this, weights);
447}
448
449void Parameter :: set_min(double value) {
450        has_min = true;
451        min = value;
452}
453
454void Parameter :: set_max(double value) {
455        has_max = true;
456        max = value;
457}
458
459double Parameter :: operator()() {
460        return value;
461}
462
463double Parameter :: operator=(double _value){
464        value = _value;
465}
Note: See TracBrowser for help on using the repository browser.