secantfunction.c
1 |
// from 68 and 80 % containment radii (in degrees), calculate the sigma and gamma
|
---|---|
2 |
// parameters for a normalized king function (WITH THE SECANT METHOD, fails if r80 < r68*1.1)
|
3 |
int calcKingParametersViaSecant( double rad68, double rad80, double & sigma, double & gamma ) |
4 |
{ |
5 |
// copied almost verbatim from
|
6 |
// $CTOOLS/scripts/cta_root2caldb.py's root2psf_king() function
|
7 |
|
8 |
// no point in continuing if only 0's
|
9 |
if ( rad68 <= 0.0 || rad80 <= 0.0 ) |
10 |
{ |
11 |
printf(" calcKingParameters(%.2f %.2f %.2f %.2f): Warning, a containment radius is 0, setting g/s to 0s...\n", rad68, rad80, sigma, gamma ) ;
|
12 |
gamma = 0.0 ; |
13 |
sigma = 0.0 ; |
14 |
return 1 ; |
15 |
} |
16 |
|
17 |
// initial ratios
|
18 |
double a = 1.0 - 0.68 ; |
19 |
double b = 1.0 - 0.80 ; |
20 |
double c = (rad68*rad68) / (rad80*rad80) ;
|
21 |
|
22 |
// solve equation (a^x-1)/(b^x-1)=c for x using secant
|
23 |
// method. Stop when we are better than 1e-6;
|
24 |
double x,f ;
|
25 |
double x1 = -0.5 ; |
26 |
double x2 = -10000.0 ; // if too close to x1=-0.5, fit will fail on some combinations of rad68 and rad80 (if rad68 and rad80 are within 5% of each other) |
27 |
double f1 = ( ( pow(a,x1)-1.0 ) / ( pow(b,x1) -1.0 ) ) - c ; |
28 |
double f2 = ( ( pow(a,x2)-1.0 ) / ( pow(b,x2) -1.0 ) ) - c ; |
29 |
int iter = 0 ; |
30 |
while ( true ) |
31 |
{ |
32 |
x = x1 - f1 * (x1-x2)/(f1-f2) ; |
33 |
f = ( pow(a,x)-1.0 ) / ( pow(b,x)-1.0 ) - c ; |
34 |
iter += 1 ;
|
35 |
if ( iter == 1 ) printf("\n"); |
36 |
|
37 |
char xwarn[100]="" ; |
38 |
if ( x > 0.0 ) sprintf(xwarn,"%sx:%.8f%s", KRED, x, KNRM ) ; |
39 |
else sprintf(xwarn,"x:%.8f" , x ) ; |
40 |
printf(" calcKingParameters(%7.3f %7.3f %7.3f %7.3f): iter:%d diff:%.8f %s f1=%f f2=%f...\n", rad68, rad80, sigma, gamma, iter, fabs(f), xwarn, f1, f2 ) ;
|
41 |
|
42 |
if ( fabs(f) < 1.0e-6 ) |
43 |
{ |
44 |
//printf(" calcKingParameters(%7.3f %7.3f %7.3f %7.3f): Warning, breaking!...\n", rad68, rad80, sigma, gamma ) ;
|
45 |
break ;
|
46 |
} |
47 |
else
|
48 |
{ |
49 |
f2 = f1 ; |
50 |
x2 = x1 ; |
51 |
f1 = f ; |
52 |
x1 = x ; |
53 |
} |
54 |
|
55 |
// compute gamma
|
56 |
if ( x < 0.0 ) |
57 |
{ |
58 |
gamma = 1.0 - (1.0/x) ; |
59 |
} |
60 |
else
|
61 |
{ |
62 |
gamma = 1.0 ; |
63 |
//printf(" calcKingParameters(%7.3f %7.3f %7.3f %7.3f): Warning, x(%7.4f) >= 0, setting gamma to 1...\n", rad68, rad80, sigma, gamma, x ) ;
|
64 |
} |
65 |
|
66 |
// compute sigma
|
67 |
double denom = 2.0 * gamma * ( pow(b,x)-1.0 ) ; |
68 |
if ( denom > 0.0 ) |
69 |
{ |
70 |
sigma = rad68 * sqrt(1.0/denom) ; |
71 |
} |
72 |
else
|
73 |
{ |
74 |
//printf(" calcKingParameters(%7.3f %7.3f %7.3f %7.3f): Warning, first denom is 0, attempting 2nd method...\n", rad68, rad80, sigma, gamma ) ;
|
75 |
denom = 2.0 * gamma * (pow(b,x)-1.0) ; |
76 |
if ( denom > 0.0 ) |
77 |
{ |
78 |
sigma = rad80 * sqrt(1.0/denom) ; |
79 |
} |
80 |
else
|
81 |
{ |
82 |
//printf(" calcKingParameters(%7.3f %7.3f %7.3f %7.3f): Warning, denom is still 0.0, setting g/s to 0s...\n", rad68, rad80, sigma, gamma ) ;
|
83 |
gamma = 0.0 ; |
84 |
sigma = 0.0 ; |
85 |
return 0 ; |
86 |
} |
87 |
} |
88 |
} |
89 |
|
90 |
return 0 ; |
91 |
} |
92 |
|