1 |
/* |
2 |
* rdutil.c |
3 |
* |
4 |
* library of utility functions for dealing with ring-diagram fit files |
5 |
* |
6 |
* autoweed_vel automatically weed velocities for inversions |
7 |
* read_fit reads n, l, f, and d_f from a fit file |
8 |
* read_fit_v reads n, l, f, d_f, u_i and d_ui from a fit file |
9 |
* |
10 |
* Bugs: |
11 |
* read_fit() and read_fit_v() assume that the frequency error estimate |
12 |
* is in column 5 of the fit table; for fit files produced with versions |
13 |
* of rdfitc below 1.2, this is not the case |
14 |
*/ |
15 |
#include <stdio.h> |
16 |
#include <stdlib.h> |
17 |
#include <math.h> |
18 |
|
19 |
/* some or all of the following declarations may be unnecessary */ |
20 |
/* |
21 |
int interp_vel(int *n, double *l, double *f, double *ef, double *ux, |
22 |
double *eux, double *uy, double *euy, int npts); |
23 |
int interp_freq(int *n, double *l, double *f, double *ef, int npts, |
24 |
int *ni, int *li, double *fi, double *efi, int *npts_out); |
25 |
int freqdif(int *n1, int *n2, int *l1, double *l2, double *f1, double *f2, |
26 |
double *ef1, double *ef2, int npts1, int npts2, int *n, int *l, double *f, |
27 |
double *df, double *edf, int *npts); |
28 |
int autoweed(int *l, int *n, double *f, double *df, double *edf, int *msk, |
29 |
int npts); |
30 |
|
31 |
int nearst(double xb, double x[], int ntab); |
32 |
int divdif(double xb, double x[], double f[], int *nuse, int ntab, |
33 |
double fb[], double aeps, double *dfb, double *ddfb); |
34 |
int svdevl(int n, int m, double *u, double *v, double sigma[], int lu, |
35 |
int lv, double b[], double reps); |
36 |
int svd(int n, int m, double *a, double *v, double sigma[], int la, int lv); |
37 |
int llsq(int n, int m, int k, double *x, int ix, double f[], double ef[], |
38 |
double a[], double *u, double *v, int iu, int iv, double sigma[], |
39 |
double y[], void (* phi) (int , double * , double * ), double reps, |
40 |
double *chisq); |
41 |
void line(int m, double *x, double *y); |
42 |
*/ |
43 |
/* |
44 |
* The following have been commented out for dependencies and because they are |
45 |
* not used by rdfitc (which only uses autoweed_vel()) |
46 |
* interp_vel |
47 |
* interp_freq |
48 |
* freqdif |
49 |
* autoweed |
50 |
*/ |
51 |
int autoweed_vel (int *n, double *l, double *ux, double *uy, int *mask, |
52 |
int npts) { |
53 |
/* |
54 |
* Returns 'mask' of length npts: mask[i] is False for rejected modes. |
55 |
* Ux and Uy are weeded together. Values are rejected when their difference |
56 |
* from the mean exceeds 5 (tol?) std. dev., both the mean and std dev |
57 |
* being calculated over the central 3/5 of the l range for the order |
58 |
*/ |
59 |
const int maxn = 8; |
60 |
const double tol = 5.0; |
61 |
|
62 |
int i, j, offset; |
63 |
int n_num[maxn]; |
64 |
double num; |
65 |
double sumx, sumxx, sumy, sumyy, meanx, meany, stdx, stdy; |
66 |
double range, uxmin, uxmax, uymin, uymax; |
67 |
double lmin,lmax; |
68 |
|
69 |
for (i=0; i<maxn; i++) n_num[i] = 0; |
70 |
for (i=0; i<npts; i++) |
71 |
if (n[i] < maxn) n_num[n[i]]++; |
72 |
|
73 |
offset = 0; |
74 |
for (i=0; i<maxn; i++) { |
75 |
num = 0.0; |
76 |
sumx = 0.0; |
77 |
sumy = 0.0; |
78 |
sumxx = 0.0; |
79 |
sumyy = 0.0; |
80 |
/* get l limits */ |
81 |
lmin = lmax = l[offset]; |
82 |
for (j=offset; j < n_num[i] + offset; j++) { |
83 |
if (l[j] < lmin) lmin = l[j]; |
84 |
if (l[j] > lmax) lmax = l[j]; |
85 |
} |
86 |
range = 0.2 * (lmax - lmin); |
87 |
lmin += 2.0 * range; |
88 |
lmax -= 2.0 * range; |
89 |
for (j=offset; j < n_num[i] + offset; j++) { |
90 |
if ((l[j] <= lmax) && (l[j] >= lmin)) { |
91 |
sumx += ux[j]; |
92 |
sumxx += ux[j]*ux[j]; |
93 |
sumy += uy[j]; |
94 |
sumyy += uy[j]*uy[j]; |
95 |
num++; |
96 |
} |
97 |
} |
98 |
meanx = sumx / num; |
99 |
meany = sumy / num; |
100 |
stdx = num*sumxx - sumx*sumx; |
101 |
stdy = num*sumyy - sumy*sumy; |
102 |
stdx /= (num * (num - 1)); |
103 |
stdy /= (num * (num - 1)); |
104 |
stdx = sqrt (stdx); |
105 |
stdy = sqrt (stdy); |
106 |
uxmin = meanx - 5.0 * stdx; |
107 |
uxmax = meanx + 5.0 * stdx; |
108 |
uymin = meany - 5.0 * stdy; |
109 |
uymax = meany + 5.0 * stdy; |
110 |
|
111 |
for (j=offset; j<n_num[i]+offset; j++) { |
112 |
if (ux[j] <= uxmax && ux[j] >= uxmin && |
113 |
uy[j] <= uymax && uy[j] >= uymin) mask[j]=1; |
114 |
else mask[j]=0; |
115 |
} |
116 |
offset +=n_num[i]; |
117 |
} |
118 |
return 0; |
119 |
} |
120 |
|
121 |
int read_fit (FILE *fpt, int *npts, int **n, double **l, double **f, |
122 |
double **ef) { |
123 |
int i, nlines; |
124 |
char buffer[8192]; |
125 |
if (ferror (fpt)) return -1; |
126 |
if (feof (fpt)) rewind (fpt); |
127 |
|
128 |
nlines = 0; |
129 |
while (!feof(fpt)) { |
130 |
fgets (buffer, 8192, fpt); |
131 |
if (buffer[0] != '#' && !feof (fpt)) nlines++; |
132 |
} |
133 |
if (nlines == 0) return 1; |
134 |
|
135 |
*n = (int *)malloc (nlines * sizeof (int)); |
136 |
*l = (double *)malloc (nlines * sizeof (double)); |
137 |
*f = (double *)malloc (nlines * sizeof (double)); |
138 |
*ef = (double *)malloc (nlines * sizeof (double)); |
139 |
|
140 |
rewind (fpt); |
141 |
|
142 |
for (i=0; i<nlines; i++) { |
143 |
fgets (buffer, 8192, fpt); |
144 |
while (buffer[0] == '#') fgets( buffer, 8192, fpt); |
145 |
sscanf (buffer, "%i %lf %*f %lf %lf", &(*n)[i], &(*l)[i], &(*f)[i], |
146 |
&(*ef)[i]); |
147 |
} |
148 |
*npts = nlines; |
149 |
|
150 |
return 0; |
151 |
} |
152 |
|
153 |
int read_fit_v (FILE *fpt, int *npts, int **n, double **l, double **f, |
154 |
double **ef, double **ux, double **eux, double **uy, double **euy) { |
155 |
int i, nlines; |
156 |
char buffer[8192]; |
157 |
if (ferror (fpt)) return -1; |
158 |
if (feof (fpt)) rewind (fpt); |
159 |
|
160 |
nlines = 0; |
161 |
while (!feof (fpt)) { |
162 |
fgets (buffer, 8192, fpt); |
163 |
if (buffer[0] != '#' && !feof (fpt)) nlines++; |
164 |
} |
165 |
if (nlines == 0) return 1; |
166 |
|
167 |
*n = (int *)realloc (*n, nlines * sizeof (int)); |
168 |
*l = (double *)realloc (*l, nlines * sizeof (double)); |
169 |
*f = (double *)realloc (*f, nlines * sizeof (double)); |
170 |
*ef = (double *)realloc (*ef, nlines * sizeof (double)); |
171 |
*ux = (double *)realloc (*ux, nlines * sizeof (double)); |
172 |
*eux = (double *)realloc (*eux, nlines * sizeof (double)); |
173 |
*uy = (double *)realloc (*uy, nlines * sizeof (double)); |
174 |
*euy = (double *)realloc (*euy, nlines * sizeof (double)); |
175 |
|
176 |
rewind (fpt); |
177 |
|
178 |
for (i=0; i<nlines; i++) { |
179 |
fgets (buffer, 8192, fpt); |
180 |
while (buffer[0] == '#') fgets (buffer, 8192, fpt); |
181 |
sscanf (buffer, "%i %lf %*f %lf %lf %lf %lf %lf %lf", &(*n)[i], &(*l)[i], |
182 |
&(*f)[i], &(*ef)[i], &(*ux)[i], &(*eux)[i], &(*uy)[i], &(*euy)[i]); |
183 |
} |
184 |
*npts = nlines; |
185 |
|
186 |
return 0; |
187 |
} |
188 |
/* |
189 |
int interp_vel(int *n, double *l, double *f, double *ef, double *ux, |
190 |
double *eux, double *uy, double *euy, int npts) { |
191 |
*/ |
192 |
/* |
193 |
Function - interp |
194 |
Takes power spectra fit parameters, and interpolates them to integer l. |
195 |
Data are returned in the input arrays - **data is overwritten!** |
196 |
*/ |
197 |
/* |
198 |
int i, j, nuse, ierr, offset=0; |
199 |
int n_num[13]; |
200 |
double fb[10], ll; |
201 |
double dfb, ddfb, aeps=1e-7; |
202 |
double *inp_l, *inp_f, *inp_ef, *inp_ux, *inp_uy, *inp_eux, *inp_euy; |
203 |
FILE * outBug; |
204 |
|
205 |
// count number of frequencies for each n |
206 |
// note that it is assumed that all frequencies for each |
207 |
// n are grouped together in the arrays |
208 |
for(i=0; i<13; i++) n_num[i]=0; |
209 |
for(i=0; i < npts; i++) { |
210 |
n_num[n[i]] ++; |
211 |
} |
212 |
|
213 |
inp_l=(double*) malloc(npts*sizeof(double)); |
214 |
inp_f=(double*) malloc(npts*sizeof(double)); |
215 |
inp_ef=(double*) malloc(npts*sizeof(double)); |
216 |
inp_ux=(double*) malloc(npts*sizeof(double)); |
217 |
inp_uy=(double*) malloc(npts*sizeof(double)); |
218 |
inp_eux=(double*) malloc(npts*sizeof(double)); |
219 |
inp_euy=(double*) malloc(npts*sizeof(double)); |
220 |
// loop over n |
221 |
// outBug=fopen("tesbug","w"); |
222 |
for(i=0; i < 10; i++) { |
223 |
for(j=0;j<npts;j++) { |
224 |
inp_l[j]=0.0; |
225 |
inp_f[j]=0.0; |
226 |
inp_ef[j]=0.0; |
227 |
inp_ux[j]=0.0; |
228 |
inp_uy[j]=0.0; |
229 |
inp_eux[j]=0.0; |
230 |
inp_euy[j]=0.0; |
231 |
} |
232 |
for(j=0;j<n_num[i];j++) { |
233 |
inp_l[j]=l[j+offset]; |
234 |
inp_f[j]=f[j+offset]; |
235 |
inp_ef[j]=ef[j+offset]; |
236 |
inp_ux[j]=ux[j+offset]; |
237 |
inp_uy[j]=uy[j+offset]; |
238 |
inp_eux[j]=eux[j+offset]; |
239 |
inp_euy[j]=euy[j+offset]; |
240 |
} |
241 |
for(j=0;j<n_num[i];j++) { |
242 |
ll=(int)(inp_l[j]+0.5); |
243 |
nuse=3; |
244 |
ierr=divdif(ll, inp_l, inp_f, &nuse, |
245 |
n_num[i], fb, aeps, &dfb, &ddfb); |
246 |
f[j+offset]=fb[nuse]; |
247 |
nuse=3; |
248 |
ierr=divdif(ll, inp_l, inp_ef, &nuse, |
249 |
n_num[i], fb, aeps, &dfb, &ddfb); |
250 |
ef[j+offset]=fb[nuse]; |
251 |
nuse=3; |
252 |
ierr=divdif(ll, inp_l, inp_ux, &nuse, |
253 |
n_num[i], fb, aeps, &dfb, &ddfb); |
254 |
ux[j+offset]=fb[nuse]; |
255 |
nuse=3; |
256 |
ierr=divdif(ll, inp_l, inp_uy, &nuse, |
257 |
n_num[i], fb, aeps, &dfb, &ddfb); |
258 |
uy[j+offset]=fb[nuse]; |
259 |
nuse=3; |
260 |
ierr=divdif(ll, inp_l, inp_eux, &nuse, |
261 |
n_num[i], fb, aeps, &dfb, &ddfb); |
262 |
eux[j+offset]=fb[nuse]; |
263 |
nuse=3; |
264 |
ierr=divdif(ll, inp_l, inp_euy, &nuse, |
265 |
n_num[i], fb, aeps, &dfb, &ddfb); |
266 |
euy[j+offset]=fb[nuse]; |
267 |
l[j+offset]=ll; |
268 |
} |
269 |
offset+=n_num[i]; |
270 |
} |
271 |
|
272 |
return 0; |
273 |
} |
274 |
*/ |
275 |
/* |
276 |
int interp_freq(int *n, double *l, double *f, double *ef, int npts, |
277 |
int *ni, int *li, double *fi, double *efi, int *npts_out) { |
278 |
int i, j, nn, ll, nmin, nmax, this_npts, nuse; |
279 |
double *this_l, *this_f, *this_ef, all, fb[5]; |
280 |
double reps, dfb, ddfb, ff, error; |
281 |
|
282 |
this_l = (double*) malloc(npts*sizeof(double)); |
283 |
this_f = (double*) malloc(npts*sizeof(double)); |
284 |
this_ef = (double*) malloc(npts*sizeof(double)); |
285 |
|
286 |
*npts_out = 0; |
287 |
nmin = 100; |
288 |
nmax = 0; |
289 |
for(i=0; i<npts; i++) { |
290 |
if(n[i] < nmin) nmin = n[i]; |
291 |
if(n[i] > nmax) nmax = n[i]; |
292 |
} |
293 |
for(nn=nmin; nn<=nmax; nn++) { |
294 |
j = 0; |
295 |
for(i=0; i<npts; i++) { |
296 |
if(n[i]==nn) { |
297 |
this_l[j] = l[i]; |
298 |
this_f[j] = f[i]; |
299 |
this_ef[j] = ef[i]; |
300 |
j++; |
301 |
} |
302 |
} |
303 |
this_npts = j; |
304 |
j = *npts_out; |
305 |
//printf("%i %i\n",this_npts, *npts_out); |
306 |
for(i=0; i<this_npts; i++) { |
307 |
ll = (int) this_l[i] + 0.5; |
308 |
all = (double) ll; // cast back to double for function argument |
309 |
nuse = 3; |
310 |
reps = 1.0e-7; |
311 |
//printf("got here\n"); |
312 |
divdif(all, this_l, this_f, &nuse, this_npts, fb, reps, &dfb, &ddfb); |
313 |
ff = fb[nuse]; |
314 |
nuse = 3; |
315 |
divdif(all, this_l, this_ef, &nuse, this_npts, fb, reps, &dfb, &ddfb); |
316 |
error = fb[nuse]; |
317 |
//printf("%i %i %f %f\n",nn,ll,ff,error); |
318 |
if(error>0) { |
319 |
ni[j] = nn; |
320 |
li[j] = ll; |
321 |
fi[j] = ff; |
322 |
efi[j] = error; |
323 |
j++; |
324 |
} |
325 |
} |
326 |
//printf("%i\n",j); |
327 |
*npts_out = j; |
328 |
} |
329 |
|
330 |
return 0; |
331 |
} |
332 |
*/ |
333 |
/* |
334 |
int freqdif(int *n1, int *n2, int *l1, double *l2, double *f1, double *f2, |
335 |
double *ef1, double *ef2, int npts1, int npts2, int *n, int *l, double *f, |
336 |
double *df, double *edf, int *npts) { |
337 |
int i, j, nn, ll, *index, nmin, nmax, lmin, lmax, this_npts, ind; |
338 |
int nuse; |
339 |
double *this_l, *this_f, *this_ef, all, fb[5], dfb, ddfb, reps; |
340 |
double ff, error; |
341 |
|
342 |
*npts = 0; |
343 |
|
344 |
this_l = (double*) malloc(npts2*sizeof(double)); |
345 |
this_f = (double*) malloc(npts2*sizeof(double)); |
346 |
this_ef = (double*) malloc(npts2*sizeof(double)); |
347 |
|
348 |
nmin = n1[0]; |
349 |
nmax = n1[0]; |
350 |
// lmin = (int) l2[0]+0.5; |
351 |
// lmax = (int) l2[0]+0.5; |
352 |
for(i=1; i<npts1; i++) { |
353 |
if(n1[i] < nmin) nmin = n1[i]; |
354 |
if(n1[i] > nmax) nmax = n1[i]; |
355 |
// if(l2[i] < lmin) lmin = (int) l2[i]+0.5; |
356 |
// if(l2[i] > lmax) lmax = (int) l2[i]+0.5; |
357 |
} |
358 |
|
359 |
// index = (int*) malloc((nmax-nmin)*(lmax-lmin)*sizeof(int)); |
360 |
// for(i=0; i<(nmax-nmin)*(lmax-lmin); i++) index[i] = -1; |
361 |
// for(i=0; i<npts2; i++) { |
362 |
// ll = (int) l2[i]+0.5; |
363 |
// index[n2[i]*(lmax-lmin)+ll-lmin] = i; |
364 |
// } |
365 |
|
366 |
for(nn=nmin; nn<=nmax; nn++) { |
367 |
j = 0; |
368 |
lmin = 10000; |
369 |
lmax = 0; |
370 |
for(i=0; i<npts2; i++) { |
371 |
if(n2[i] == nn) { |
372 |
this_l[j] = l2[i]; |
373 |
this_f[j] = f2[i]; |
374 |
this_ef[j] = ef2[i]; |
375 |
if(lmin > l2[i]) lmin = (int) l2[i]+0.5; |
376 |
if(lmax < l2[i]) lmax = (int) l2[i]+0.5; |
377 |
j++; |
378 |
} |
379 |
} |
380 |
this_npts = j; |
381 |
//printf("this_npts = %i\n", this_npts); |
382 |
j = *npts; |
383 |
for(i=0; i<npts1; i++) { |
384 |
// ind = index[n1[i]*(lmax-lmin)+l1[i]-lmin]; |
385 |
// if(ind>=0) { |
386 |
if(n1[i] == nn && l1[i] >= lmin && l1[i] <= lmax) { |
387 |
//ll = (int) this_l[i] + 0.5; |
388 |
ll = l1[i]; |
389 |
all = (double) ll; // cast back to double for function argument |
390 |
nuse = 3; |
391 |
reps = 1.0e-7; |
392 |
divdif(all, this_l, this_f, &nuse, this_npts, fb, reps, &dfb, &ddfb); |
393 |
ff = fb[nuse]; |
394 |
nuse = 3; |
395 |
divdif(all, this_l, this_ef, &nuse, this_npts, fb, reps, &dfb, &ddfb); |
396 |
error = fb[nuse]; |
397 |
if(error>0.0) { |
398 |
n[j] = nn; |
399 |
l[j] = ll; |
400 |
f[j] = f1[i]; |
401 |
df[j] = f1[i] - ff; |
402 |
edf[j] = sqrt(ef1[i]*ef1[i]+error*error); |
403 |
//printf("%i %i %i %f %f %f\n",j, n[j], l[j], f[j], df[j], edf[j]); |
404 |
j++; |
405 |
} |
406 |
} |
407 |
} |
408 |
*npts = j; |
409 |
//printf("%i\n",*npts); |
410 |
} |
411 |
|
412 |
return 0; |
413 |
} |
414 |
*/ |
415 |
void line (int m, double *x, double *y) { |
416 |
y[0] = x[0]; |
417 |
y[1] = 1.0; |
418 |
return; |
419 |
} |
420 |
/* |
421 |
int autoweed(int *l, int *n, double *f, double *df, double *edf, int *msk, |
422 |
int npts) { |
423 |
int avglen = 4; |
424 |
double tol = 4.0; |
425 |
double delnu = 50.0; |
426 |
int i, j, nn, this_npts, llim, ulim, offset; |
427 |
int data_range[2], *this_l; |
428 |
double *this_f, *this_df, *this_edf, *slopes, *a, *u, *y; |
429 |
double v[4], sigma[2], chisq; |
430 |
double mean, std; |
431 |
|
432 |
this_l = (int*) malloc(npts*sizeof(int)); |
433 |
this_f = (double*) malloc(npts*sizeof(double)); |
434 |
this_df = (double*) malloc(npts*sizeof(double)); |
435 |
this_edf = (double*) malloc(npts*sizeof(double)); |
436 |
slopes = (double*) malloc(npts*sizeof(double)); |
437 |
a = (double*) malloc(avglen*sizeof(double)); |
438 |
u = (double*) malloc(2*avglen*sizeof(double)); |
439 |
y = (double*) malloc(avglen*sizeof(double)); |
440 |
offset = 0; |
441 |
for(i=0; i<npts; i++) msk[i] = 0; |
442 |
for(nn=0; nn<7; nn++) { |
443 |
j = 0; |
444 |
mean = 0.0; |
445 |
std = 0.0; |
446 |
for(i=0; i<npts; i++) { |
447 |
if(n[i] == nn) { |
448 |
this_l[j] = l[i]; |
449 |
this_f[j] = f[i]; |
450 |
this_df[j] = df[i]; |
451 |
this_edf[j] = edf[i]; |
452 |
j++; |
453 |
} |
454 |
} |
455 |
this_npts = j; |
456 |
if(this_npts > avglen + 5) { |
457 |
data_range[0] = (int) 2*this_npts/10.; |
458 |
data_range[1] = (int) 8*this_npts/10.; |
459 |
for(i=0; i<this_npts-avglen; i++) { |
460 |
llsq(avglen, 2, 1, &this_f[i], 1, &this_df[i], &this_edf[i], a, u, |
461 |
v, 2, 2, sigma, y, *line, 1.0e-6, &chisq); |
462 |
slopes[i] = a[0]; |
463 |
//printf("%i %f\n",nn,a[0]); |
464 |
mean += a[0]; |
465 |
} |
466 |
mean /= (double) this_npts; |
467 |
for(i=0; i<this_npts-avglen; i++) std += (slopes[i]-mean)*(slopes[i]-mean); |
468 |
std /= (double) this_npts; |
469 |
std = sqrt(std); |
470 |
// printf("%i %i %i\n",data_range[0], data_range[1], this_npts/2); |
471 |
llim = data_range[0]; |
472 |
ulim = data_range[1]; |
473 |
while(llim > 0) { |
474 |
if( fabs(slopes[llim]-mean)/std > tol) break; |
475 |
llim--; |
476 |
} |
477 |
while(ulim<this_npts-avglen-1) { |
478 |
if( fabs(slopes[ulim]-mean)/std > tol) break; |
479 |
ulim++; |
480 |
} |
481 |
i = this_npts/2; |
482 |
while(i>0) { |
483 |
if(this_f[i]-this_f[i-1] > delnu) break; |
484 |
i--; |
485 |
} |
486 |
if(i > llim) llim = i; |
487 |
i = this_npts/2; |
488 |
while(i<this_npts) { |
489 |
if(this_f[i]-this_f[i-1] > delnu) break; |
490 |
i++; |
491 |
} |
492 |
if(i < ulim) ulim = i; |
493 |
printf("%i %i %i %i\n",nn,this_npts,llim,ulim); |
494 |
for(i=offset+llim; i<offset+ulim; i++) msk[i] = 1;//i<this_npts+offset-ulim; i++) msk[i] = 1; |
495 |
offset += this_npts; |
496 |
} |
497 |
} |
498 |
|
499 |
return 0; |
500 |
} |
501 |
*/ |
502 |
|
503 |
int nearst (double xb, double x[], int ntab) { |
504 |
int low, igh, mid; |
505 |
|
506 |
low=0; igh=ntab-1; |
507 |
if((xb < x[low]) != (xb < x[igh]) ) { |
508 |
|
509 |
/* If the point is within the range of table, then locate it by bisection */ |
510 |
|
511 |
while(igh-low > 1) { |
512 |
mid=(low+igh)/2; |
513 |
if((xb < x[mid]) == (xb < x[low])) low=mid; |
514 |
else igh=mid; |
515 |
} |
516 |
} |
517 |
|
518 |
if(fabs(xb-x[low]) < fabs(xb-x[igh])) return low; |
519 |
else return igh; |
520 |
} |
521 |
|
522 |
int divdif(double xb, double x[], double f[], int *nuse, int ntab, |
523 |
double fb[], double aeps, double *dfb, double *ddfb) { |
524 |
int i,j,k,next,in,ip,nit,ier, nmax=10; |
525 |
double err,px,dpx,ddpx,xn[11],xd[11]; |
526 |
|
527 |
/* Find the nearest point */ |
528 |
|
529 |
next=nearst(xb,x,ntab); |
530 |
fb[1]=f[next]; |
531 |
xd[1]=f[next]; |
532 |
xn[1]=x[next]; |
533 |
ier=0; |
534 |
px=1.0; |
535 |
|
536 |
/* Initialisation for the derivatives */ |
537 |
|
538 |
*dfb=0.0; *ddfb=0.0; |
539 |
dpx=0.0; ddpx=0.0; |
540 |
|
541 |
/* Points between IN and IP are used for interpolation */ |
542 |
|
543 |
ip=next; in=next; |
544 |
|
545 |
/* Maximum number of points to be used for interpolation */ |
546 |
nit=*nuse; if(nmax<nit) nit=nmax; if(ntab<nit) nit=ntab; |
547 |
if(*nuse>nmax || *nuse>ntab) ier=22; |
548 |
if(*nuse<1) { |
549 |
ier=21; |
550 |
nit=6; if(nmax<nit) nit=nmax; if(ntab<nit) nit=ntab; |
551 |
} |
552 |
*nuse=1; |
553 |
|
554 |
/* Calculate successive interpolation polynomial */ |
555 |
for(j=2; j<=nit; ++j) { |
556 |
/* Choose the next nearest point to XB */ |
557 |
if(in<=0 ) { |
558 |
ip=ip+1; next=ip; |
559 |
} |
560 |
else if(ip >= ntab-1) { |
561 |
in=in-1; next=in; |
562 |
} |
563 |
else if(fabs(xb-x[ip+1]) < fabs(xb-x[in-1]) ) { |
564 |
ip=ip+1; next=ip; |
565 |
} |
566 |
else { |
567 |
in=in-1; next=in; |
568 |
} |
569 |
|
570 |
/* Calculating the divided differences */ |
571 |
xd[j]=f[next]; |
572 |
xn[j]=x[next]; |
573 |
for(k=j-1; k>=1; --k) xd[k]=(xd[k+1]-xd[k])/(xn[j]-xn[k]); |
574 |
|
575 |
/* Calculating the derivatives */ |
576 |
ddpx=ddpx*(xb-xn[j-1])+2.*dpx; |
577 |
dpx=dpx*(xb-xn[j-1])+px; |
578 |
*dfb = *dfb+dpx*xd[1]; |
579 |
*ddfb = *ddfb+ddpx*xd[1]; |
580 |
|
581 |
px=px*(xb-xn[j-1]); |
582 |
err=xd[1]*px; |
583 |
fb[j]=fb[j-1]+err; |
584 |
*nuse=j; |
585 |
|
586 |
if(fabs(err) < aeps) return ier; |
587 |
} |
588 |
return 23; |
589 |
} |
590 |
|
591 |
int svd (int n, int m, double *a, double *v, double sigma[], int la, int lv) { |
592 |
int i, j, k, l, itr, ier, itmax=30; |
593 |
double f, g, h, rmax, s, r1, r2, c, x, y, z, aeps, eps=1.e-16; |
594 |
// double *e; |
595 |
double e[2]; |
596 |
|
597 |
if(n>m || n<=0 || m<=0 || n>la || n>lv) return 105; |
598 |
ier=0; |
599 |
|
600 |
/* Reduction to Bidiagonal form using Householder transformations */ |
601 |
g=0.0; rmax=0.0; |
602 |
// e=(double *) calloc(n, sizeof(double)); |
603 |
|
604 |
for(i=0; i<n; ++i) { |
605 |
/* Off-diagonal elements of bidiagonal form */ |
606 |
e[i]=g; |
607 |
s=0.0; |
608 |
for(j=i; j<m; ++j) s=s+a[i+j*la]*a[i+j*la]; |
609 |
if(s <= 0.0) { |
610 |
/* transformation not required */ |
611 |
g=0.0; |
612 |
} |
613 |
else { |
614 |
f= a[i+i*la]; |
615 |
g=sqrt(s); |
616 |
if(f>=0.0) g=-g; |
617 |
h=f*g-s; |
618 |
a[i+i*la] = f-g; |
619 |
|
620 |
for(j=i+1; j<n; ++j) { |
621 |
s=0.0; |
622 |
for(k=i; k<m; ++k) s=s+a[i+k*la]*a[j+k*la]; |
623 |
f=s/h; |
624 |
for(k=i; k<m; ++k) a[j+k*la]= a[j+k*la]+f*a[i+k*la]; |
625 |
} |
626 |
} |
627 |
|
628 |
/* Diagonal elements of bidiagonal form */ |
629 |
sigma[i]=g; |
630 |
s=0.0; |
631 |
for(j=i+1; j<n; ++j) s=s+a[j+i*la]*a[j+i*la]; |
632 |
|
633 |
if(s<= 0.0) g=0.0; |
634 |
else { |
635 |
f= a[i*la+(i+1)]; |
636 |
g=sqrt(s); |
637 |
if(f>= 0.0) g=-g; |
638 |
h=f*g-s; |
639 |
a[i*la+(i+1)]=f-g; |
640 |
for(j=i+1; j<n; ++j) e[j]=a[j+i*la]/h; |
641 |
|
642 |
for(j=i+1; j<m; ++j) { |
643 |
s=0.0; |
644 |
for(k=i+1; k<n; ++k) s=s+a[k+j*la]*a[k+i*la]; |
645 |
for(k=i+1; k<n; ++k) a[k+j*la] = a[k+j*la]+s*e[k]; |
646 |
} |
647 |
} |
648 |
r1=fabs(sigma[i])+fabs(e[i]); |
649 |
if(r1 > rmax) rmax=r1; |
650 |
} |
651 |
|
652 |
/* Accumulation of right hand transformation in array V */ |
653 |
for(i=n-1; i>=0; --i) { |
654 |
if(g != 0.0) { |
655 |
h=g*a[i*la+(i+1)]; |
656 |
for(j=i+1; j<n; ++j) v[i+j*lv]=a[j+i*la]/h; |
657 |
|
658 |
for(j=i+1; j<n; ++j) { |
659 |
s=0.0; |
660 |
for(k=i+1; k<n; ++k) s=s+a[k+i*la]*v[j+k*lv]; |
661 |
for(k=i+1; k<n; ++k) v[j+k*lv]=v[j+k*lv]+s*v[i+k*lv]; |
662 |
} |
663 |
} |
664 |
|
665 |
for(j=i+1; j<n; ++j) { |
666 |
v[j+i*lv]=0.0; v[i+j*lv]=0.0; |
667 |
} |
668 |
v[i+i*lv]=1; |
669 |
g= e[i]; |
670 |
} |
671 |
|
672 |
/* Accumulation of left hand transformation overwritten on matrix A */ |
673 |
for(i=n-1; i>=0; --i) { |
674 |
g=sigma[i]; |
675 |
for(j=i+1; j<n; ++j) a[j+i*la]=0.0; |
676 |
if(g != 0.0) { |
677 |
h=g*a[i+i*la]; |
678 |
|
679 |
for(j=i+1; j<n; ++j) { |
680 |
s=0.0; |
681 |
for(k=i+1; k<m; ++k) s=s+a[i+k*la]*a[j+k*la]; |
682 |
f=s/h; |
683 |
for(k=i; k<m; ++k) a[j+k*la]=a[j+k*la]+f*a[i+k*la]; |
684 |
} |
685 |
|
686 |
for(j=i; j<m; ++j) a[i+j*la]=a[i+j*la]/g; |
687 |
} |
688 |
else { |
689 |
for(j=i; j<m; ++j) a[i+j*la]=0.0; |
690 |
} |
691 |
a[i+i*la] = a[i+i*la]+1; |
692 |
} |
693 |
|
694 |
/* Diagonalisation of the bidiagonal form */ |
695 |
aeps=eps*rmax; |
696 |
/* Loop over the singular values */ |
697 |
for(k=n-1; k>=0; --k) { |
698 |
/* The QR transformation */ |
699 |
for(itr=1; itr<=itmax; ++itr) { |
700 |
|
701 |
/* Test for splitting */ |
702 |
for(l=k; l>=0; --l) { |
703 |
if(fabs(e[l]) < aeps) goto split; |
704 |
if(fabs(sigma[l-1]) < aeps) break; |
705 |
} |
706 |
|
707 |
/* cancellation of E[L] if L>1 */ |
708 |
c=0.0; s=1.0; |
709 |
for(i=l; i<=k; ++i) { |
710 |
f=s*e[i]; |
711 |
e[i] = c*e[i]; |
712 |
if(fabs(f) < aeps) goto split; |
713 |
g=sigma[i]; |
714 |
sigma[i]=sqrt(f*f+g*g); |
715 |
c=g/sigma[i]; |
716 |
s=-f/sigma[i]; |
717 |
|
718 |
for(j=0; j<m; ++j) { |
719 |
r1= a[j*la+(l-1)]; |
720 |
r2= a[i+j*la]; |
721 |
a[j*la+(l-1)]=r1*c+r2*s; |
722 |
a[i+j*la]=c*r2-s*r1; |
723 |
} |
724 |
} |
725 |
|
726 |
split: z=sigma[k]; |
727 |
if(l == k) { |
728 |
/* QR iteration has converged */ |
729 |
if(z < 0.0) { |
730 |
sigma[k] = -z; |
731 |
for(j=0; j<n; ++j) v[k+j*lv]=-v[k+j*lv]; |
732 |
} |
733 |
break; |
734 |
} |
735 |
|
736 |
if(itr==itmax) {ier=12; break;} |
737 |
|
738 |
/* calculating shift from bottom 2x2 minor */ |
739 |
x=sigma[l]; |
740 |
y=sigma[k-1]; |
741 |
g=e[k-1]; |
742 |
h=e[k]; |
743 |
f=((y-z)*(y+z)+(g-h)*(g+h))/(2.*h*y); |
744 |
g=sqrt(1.+f*f); |
745 |
if(f < 0.0) g=-g; |
746 |
f=((x-z)*(x+z)+h*(y/(f+g)-h))/x; |
747 |
|
748 |
/* next QR transformation */ |
749 |
c=1.0; s=1.0; |
750 |
/* Given's rotation */ |
751 |
for(i=l+1; i<=k; ++i) { |
752 |
g=e[i]; |
753 |
y=sigma[i]; |
754 |
h=s*g; |
755 |
g=c*g; |
756 |
e[i-1]=sqrt(f*f+h*h); |
757 |
c=f/e[i-1]; |
758 |
s=h/e[i-1]; |
759 |
f=c*x+s*g; |
760 |
g=c*g-s*x; |
761 |
h=s*y; |
762 |
y=c*y; |
763 |
|
764 |
for(j=0; j<n; ++j) { |
765 |
x=v[j*lv+(i-1)]; |
766 |
z=v[i+j*lv]; |
767 |
v[j*lv+(i-1)]=c*x+s*z; |
768 |
v[i+j*lv]=c*z-s*x; |
769 |
} |
770 |
|
771 |
sigma[i-1]=sqrt(f*f+h*h); |
772 |
if(sigma[i-1] != 0.0) { |
773 |
c=f/sigma[i-1]; |
774 |
s=h/sigma[i-1]; |
775 |
} |
776 |
f=c*g+s*y; |
777 |
x=c*y-s*g; |
778 |
for(j=0; j<m; ++j) { |
779 |
y= a[j*la+(i-1)]; |
780 |
z= a[i+j*la]; |
781 |
a[j*la+(i-1)] = c*y+s*z; |
782 |
a[i+j*la] = c*z-s*y; |
783 |
} |
784 |
} |
785 |
|
786 |
e[l]=0.0; |
787 |
e[k]=f; |
788 |
sigma[k]=x; |
789 |
} |
790 |
} |
791 |
// free(e); |
792 |
return ier; |
793 |
} |
794 |
|
795 |
int svdevl(int n, int m, double *u, double *v, double sigma[], int lu, |
796 |
int lv, double b[], double reps) |
797 |
|
798 |
{ |
799 |
int i,j; |
800 |
double smax, aeps, s; |
801 |
double *wk; |
802 |
|
803 |
/* Finding the largest singular value */ |
804 |
smax=0.0; |
805 |
for(i=0; i<n; ++i) |
806 |
if(sigma[i] > smax) smax=sigma[i]; |
807 |
|
808 |
aeps=smax*reps; |
809 |
wk=(double *)calloc(n, sizeof(double)); |
810 |
for(i=0; i<n; ++i) { |
811 |
s=0.0; |
812 |
/* Only SIGMA[I] > AEPS contribute to the solution */ |
813 |
if(sigma[i] > aeps) { |
814 |
for(j=0; j<m; ++j) s=s+b[j]*u[i+j*lu]; |
815 |
s=s/sigma[i]; |
816 |
} |
817 |
wk[i]=s; |
818 |
} |
819 |
|
820 |
for(i=0; i<n; ++i) { |
821 |
s=0.0; |
822 |
for(j=0; j<n; ++j) s=s+v[j+i*lv]*wk[j]; |
823 |
b[i]=s; |
824 |
} |
825 |
free(wk); |
826 |
return 0; |
827 |
} |
828 |
|
829 |
int llsq(int n, int m, int k, double *x, int ix, double f[], double ef[], |
830 |
double a[], double *u, double *v, int iu, int iv, double sigma[], |
831 |
double y[], void (* phi) (int , double * , double * ), double reps, |
832 |
double *chisq) |
833 |
|
834 |
{ |
835 |
int i,j,ier; |
836 |
double s1; |
837 |
// double *wk; |
838 |
double wk[2]; |
839 |
|
840 |
if(m>n || m<=0 || n<=0 || k>ix) return 606; |
841 |
|
842 |
// wk=(double *) calloc(m, sizeof(double)); |
843 |
/* Setting up the design matrix and the RHS */ |
844 |
for(i=0; i<n; ++i) { |
845 |
if(ef[i]<=0.0) {/*free(wk); */return 607;} |
846 |
a[i]=f[i]/ef[i]; |
847 |
phi(m,&x[i*ix],wk); |
848 |
for(j=0; j<m; ++j) u[j+i*iu]=wk[j]/ef[i]; |
849 |
} |
850 |
|
851 |
ier=svd(m,n,u,v,sigma,iu,iv); |
852 |
if(ier>100) {/*free(wk);*/ return ier;} |
853 |
|
854 |
/* Calculate the least squares solution */ |
855 |
ier=svdevl(m,n,u,v,sigma,iu,iv,a,reps); |
856 |
|
857 |
/* Computing the \chi^2 from fitted coefficients */ |
858 |
*chisq=0.0; |
859 |
for(i=0; i<n; ++i) { |
860 |
phi(m,&x[i*ix],wk); |
861 |
s1=0.0; |
862 |
for(j=0; j<m; ++j) s1=s1+a[j]*wk[j]; |
863 |
y[i]=s1; |
864 |
s1=(f[i]-y[i])/ef[i]; |
865 |
*chisq=(*chisq)+s1*s1; |
866 |
} |
867 |
|
868 |
// free(wk); |
869 |
return 0; |
870 |
} |
871 |
|
872 |
int interp_vel (int *n, double *l, double *f, double *ef, double *ux, |
873 |
double *eux, double *uy, double *euy, int npts) { |
874 |
/* |
875 |
Takes power spectra fit parameters, and interpolates them to integer l. |
876 |
Data are returned in the input arrays - **data is overwritten!** |
877 |
*/ |
878 |
int i, j, nuse, ierr, offset=0; |
879 |
int n_num[13]; |
880 |
double fb[10], ll; |
881 |
double dfb, ddfb, aeps=1e-7; |
882 |
double *inp_l, *inp_f, *inp_ef, *inp_ux, *inp_uy, *inp_eux, *inp_euy; |
883 |
/* count number of frequencies for each n |
884 |
N.B. It is assumed that all frequencies for each n |
885 |
are grouped together in the arrays |
886 |
*/ |
887 |
for (i=0; i < 13; i++) n_num[i] = 0; |
888 |
for (i=0; i < npts; i++) if (n[i] < 13) n_num[n[i]]++; |
889 |
|
890 |
inp_l = (double *) malloc (npts*sizeof(double)); |
891 |
inp_f = (double *) malloc (npts*sizeof(double)); |
892 |
inp_ef = (double *) malloc (npts*sizeof(double)); |
893 |
inp_ux = (double *) malloc (npts*sizeof(double)); |
894 |
inp_uy = (double *) malloc (npts*sizeof(double)); |
895 |
inp_eux = (double *) malloc (npts*sizeof(double)); |
896 |
inp_euy = (double *) malloc (npts*sizeof(double)); |
897 |
/* loop over n */ |
898 |
for (i=0; i < 10; i++) { |
899 |
for (j=0; j<npts; j++) { |
900 |
inp_l[j] = 0.0; |
901 |
inp_f[j] = 0.0; |
902 |
inp_ef[j] = 0.0; |
903 |
inp_ux[j] = 0.0; |
904 |
inp_uy[j] = 0.0; |
905 |
inp_eux[j] = 0.0; |
906 |
inp_euy[j] = 0.0; |
907 |
} |
908 |
for(j=0; j<n_num[i]; j++) { |
909 |
inp_l[j] = l[j+offset]; |
910 |
inp_f[j] = f[j+offset]; |
911 |
inp_ef[j] = ef[j+offset]; |
912 |
inp_ux[j] = ux[j+offset]; |
913 |
inp_uy[j] = uy[j+offset]; |
914 |
inp_eux[j] = eux[j+offset]; |
915 |
inp_euy[j] = euy[j+offset]; |
916 |
} |
917 |
for (j = 0; j<n_num[i]; j++) { |
918 |
ll = (int)(inp_l[j]+0.5); |
919 |
nuse = 3; |
920 |
ierr = divdif (ll, inp_l, inp_f, &nuse, n_num[i], fb, aeps, &dfb, &ddfb); |
921 |
f[j+offset] = fb[nuse]; |
922 |
nuse = 3; |
923 |
ierr = divdif (ll, inp_l, inp_ef, &nuse, n_num[i], fb, aeps, &dfb, &ddfb); |
924 |
ef[j+offset] = fb[nuse]; |
925 |
nuse = 3; |
926 |
ierr = divdif (ll, inp_l, inp_ux, &nuse, n_num[i], fb, aeps, &dfb, &ddfb); |
927 |
ux[j+offset] = fb[nuse]; |
928 |
nuse = 3; |
929 |
ierr = divdif (ll, inp_l, inp_uy, &nuse, n_num[i], fb, aeps, &dfb, &ddfb); |
930 |
uy[j+offset] = fb[nuse]; |
931 |
nuse = 3; |
932 |
ierr = divdif (ll, inp_l, inp_eux, &nuse, n_num[i], fb, aeps, &dfb, &ddfb); |
933 |
eux[j+offset] = fb[nuse]; |
934 |
nuse = 3; |
935 |
ierr = divdif (ll, inp_l, inp_euy, &nuse, n_num[i], fb, aeps, &dfb, &ddfb); |
936 |
euy[j+offset] = fb[nuse]; |
937 |
l[j+offset] = ll; |
938 |
} |
939 |
offset += n_num[i]; |
940 |
} |
941 |
free (inp_l); |
942 |
free (inp_f); |
943 |
free (inp_ef); |
944 |
free (inp_ux); |
945 |
free (inp_uy); |
946 |
free (inp_eux); |
947 |
free (inp_euy); |
948 |
|
949 |
return 0; |
950 |
} |