1 |
// $Header: /home/cvsuser/cvsroot/JSOC/proj/globalhs/libs/dtgf/detrend_code_C99.h,v 1.1 2013/04/28 07:46:58 tplarson Exp $ |
2 |
|
3 |
#include "ctypes_def.h" |
4 |
|
5 |
#if TYPE == FLOAT |
6 |
#define DETREND sdetrend |
7 |
#define DETREND_DISCONTIG sdetrend_discontig |
8 |
#define LEGENDRE_POLY slegendre_poly |
9 |
#define ORTHO_POLY sortho_poly |
10 |
#elif TYPE == DOUBLE |
11 |
#define DETREND ddetrend |
12 |
#define DETREND_DISCONTIG ddetrend_discontig |
13 |
#define LEGENDRE_POLY dlegendre_poly |
14 |
#define ORTHO_POLY dortho_poly |
15 |
#endif |
16 |
|
17 |
//#define DEBUGFILE |
18 |
|
19 |
static void LEGENDRE_POLY(int degree, int length, RTYPE **poly); |
20 |
static void ORTHO_POLY(int degree, int length, RTYPE **poly, int *isgood); |
21 |
|
22 |
|
23 |
void DETREND_DISCONTIG( int n, RTYPE *data, int *isgood, int degree, |
24 |
int length, int skip, int m, int *sect, int detrend_first) |
25 |
{ |
26 |
int i,first,last; |
27 |
// Seperately detrend m sections of data separated by |
28 |
// discontinuities. |
29 |
// The first section begins on data[0], |
30 |
// the m-1 first sections end on data[sect_last[i]], i=0,1,...,m-2, |
31 |
// and the last section ends on data[n-1]. |
32 |
|
33 |
if (m==0) |
34 |
DETREND(n,data,isgood,degree,length,skip,detrend_first); |
35 |
else |
36 |
{ |
37 |
for (i=0; i<m; i++) |
38 |
{ |
39 |
first = sect[2*i]; |
40 |
last = sect[2*i+1]; |
41 |
#ifdef DEBUGOUT |
42 |
printf("Detrending [%d:%d]\n",first,last); |
43 |
#endif |
44 |
DETREND(last-first+1,&data[first],&isgood[first],degree,length,skip,detrend_first); |
45 |
} |
46 |
} |
47 |
} |
48 |
|
49 |
|
50 |
|
51 |
void DETREND( int n, RTYPE *data, int *isgood, int degree, |
52 |
int length, int skip, int detrend_first) |
53 |
{ |
54 |
int first,i,d, overlap, start,end; |
55 |
RTYPE **legendre_poly, **gap_poly, *fit, gamma, *apodizer; |
56 |
#ifdef DEBUGFILE |
57 |
char name[20]; |
58 |
static int count=0; |
59 |
FILE *fh; |
60 |
#endif |
61 |
|
62 |
#ifdef DEBUGOUT |
63 |
printf("%s: n=%d, length=%d, skip=%d, degree=%d\n", |
64 |
__func__,n,length,skip,degree); |
65 |
#endif |
66 |
|
67 |
fit = (RTYPE *)calloc(n,sizeof(RTYPE)); |
68 |
// Set up Legendre polynomials |
69 |
legendre_poly = (RTYPE **)malloc((degree+1)*sizeof(RTYPE *)); |
70 |
gap_poly = (RTYPE **)malloc((degree+1)*sizeof(RTYPE *)); |
71 |
for (i=0; i<=degree; i++) |
72 |
{ |
73 |
legendre_poly[i] = (RTYPE *)malloc(2*length*sizeof(RTYPE)); |
74 |
gap_poly[i] = (RTYPE *)malloc(2*length*sizeof(RTYPE)); |
75 |
} |
76 |
LEGENDRE_POLY(degree,length, legendre_poly); |
77 |
|
78 |
// Set up apodization to stitch together individual fits. |
79 |
overlap = length-skip; |
80 |
apodizer = (RTYPE *)malloc(overlap*sizeof(RTYPE)); |
81 |
for (i=0;i<overlap;i++) |
82 |
{ |
83 |
apodizer[i] = cos(M_PI/2*((RTYPE) i+1)/(overlap+1)); |
84 |
apodizer[i] *= apodizer[i]; |
85 |
} |
86 |
|
87 |
// for (first=0; first<=n-length; first+=skip) |
88 |
first=detrend_first; |
89 |
do |
90 |
{ |
91 |
/* |
92 |
// Possibly grow the last interval to match n. |
93 |
if (first+2*length>n ) |
94 |
{ |
95 |
length = n-first; |
96 |
LEGENDRE_POLY(degree, length, legendre_poly); |
97 |
} |
98 |
*/ |
99 |
// don't grow it quite so much: |
100 |
if (first+3*length/2>n) |
101 |
{ |
102 |
length = n-first; |
103 |
LEGENDRE_POLY(degree, length, legendre_poly); |
104 |
} |
105 |
|
106 |
start = first; |
107 |
while (start<first+length && !isgood[start]) |
108 |
start++; |
109 |
if (start==first+length) |
110 |
{ |
111 |
/* An empty interval. fill with zeros and skip. */ |
112 |
for (i=first; i<first+length; i++) |
113 |
fit[i] = 0; |
114 |
// continue; |
115 |
// continue is not correct here because it skips the increment |
116 |
goto emptyinterval; |
117 |
} |
118 |
|
119 |
end = first+length-1; |
120 |
while (end>start && !isgood[end]) |
121 |
end--; |
122 |
end++; |
123 |
|
124 |
// printf("first = %d, start = %d, end = %d.\n",first,start,end); |
125 |
if ((end-start) < length/2) |
126 |
{ |
127 |
#ifdef DEBUGOUT |
128 |
printf("special treatment of [%d:%d], length = %d\n",start,end,length); |
129 |
#endif |
130 |
LEGENDRE_POLY(degree, (end-start), legendre_poly); |
131 |
// Modify polynomials to be orthonormal wrt. |
132 |
// the local gap structure. |
133 |
for (i=0; i<=degree; i++) |
134 |
memcpy(gap_poly[i],legendre_poly[i],(end-start)*sizeof(RTYPE)); |
135 |
ORTHO_POLY(degree,(end-start), gap_poly, &isgood[start]); |
136 |
for (i=start; i<end; i++) |
137 |
fit[i] = 0; |
138 |
for (d=0;d<=degree;d++) |
139 |
{ |
140 |
gamma = 0; |
141 |
for (i=start; i<end; i++) |
142 |
if (isgood[i]) |
143 |
gamma += gap_poly[d][i-start]*data[i]; |
144 |
for (i=start; i<end; i++) |
145 |
fit[i] += gamma*gap_poly[d][i-start]; |
146 |
} |
147 |
LEGENDRE_POLY(degree, length, legendre_poly); |
148 |
} |
149 |
else |
150 |
{ |
151 |
#ifdef DEBUGOUT |
152 |
printf("normal treatment [%d:%d]\n",first,first+length-1); |
153 |
#endif |
154 |
// Modify polynomials to be orthonormal wrt. |
155 |
// the local gap structure. |
156 |
for (i=0; i<=degree; i++) |
157 |
memcpy(gap_poly[i],legendre_poly[i],length*sizeof(RTYPE)); |
158 |
ORTHO_POLY(degree,length, gap_poly, &isgood[first]); |
159 |
|
160 |
// Subtract polynomial components one by one. |
161 |
if (first!=detrend_first) |
162 |
{ |
163 |
for (i=first; i<first+overlap; i++) |
164 |
{ |
165 |
RTYPE alpha = apodizer[i-first]; |
166 |
fit[i] = alpha*fit[i]; |
167 |
} |
168 |
} |
169 |
for (d=0;d<=degree;d++) |
170 |
{ |
171 |
gamma = 0; |
172 |
for (i=first; i<first+length; i++) |
173 |
if (isgood[i]) |
174 |
gamma += gap_poly[d][i-first]*data[i]; |
175 |
if (first!=detrend_first) |
176 |
for (i=first; i<first+overlap; i++) |
177 |
{ |
178 |
RTYPE alpha = apodizer[i-first]; |
179 |
fit[i] += (1-alpha)*gamma*gap_poly[d][i-first]; |
180 |
} |
181 |
else |
182 |
i=first; |
183 |
for (; i<first+length; i++) |
184 |
fit[i] += gamma*gap_poly[d][i-first]; |
185 |
} |
186 |
} |
187 |
emptyinterval: |
188 |
first += skip; |
189 |
// } while (first<=n-length); |
190 |
} while (first<=n-length/2); |
191 |
|
192 |
for (i=0; i<n; i++) |
193 |
if (!isgood[i]) |
194 |
fit[i] = 0; |
195 |
|
196 |
for (i=0; i<n; i++) |
197 |
if (isgood[i]) |
198 |
data[i] -= fit[i]; |
199 |
else |
200 |
data[i] = 0; |
201 |
|
202 |
#ifdef DEBUGFILE |
203 |
printf("writing debug file #%d\n",count); |
204 |
sprintf(name,"detrend_debug_%d.out",count++); |
205 |
fh = fopen(name,"w"); |
206 |
assert(fh); |
207 |
for (i=0; i<n; i++) |
208 |
fprintf(fh,"%e %e\n",fit[i],data[i]); |
209 |
fclose(fh); |
210 |
#endif |
211 |
|
212 |
for (i=0; i<=degree; i++) |
213 |
{ |
214 |
free(legendre_poly[i]); |
215 |
free(gap_poly[i]); |
216 |
} |
217 |
free(legendre_poly); |
218 |
free(gap_poly); |
219 |
free(fit); |
220 |
free(apodizer); |
221 |
} |
222 |
|
223 |
|
224 |
static void LEGENDRE_POLY(int degree, int length, RTYPE **poly) |
225 |
{ |
226 |
int d,i; |
227 |
|
228 |
// Set up Legendre polynomials using recurrence. |
229 |
for (i=0;i<(length+1)/2; i++) |
230 |
{ |
231 |
poly[0][i] = 1.0; |
232 |
poly[1][i] = -1.0+(2.0*(i+1))/(length+1); |
233 |
} |
234 |
for (d=1; d<degree; d++) |
235 |
for (i=0; i<(length+1)/2; i++) |
236 |
poly[d+1][i] = ((2*d+1)*poly[1][i]*poly[d][i]-d*poly[d-1][i])/(d+1); |
237 |
|
238 |
// Set up symmetric / anti-symmetric part. |
239 |
for (d=1; d<=degree; d+=2) |
240 |
for (i=0; i<length/2; i++) |
241 |
poly[d][length-i-1] = -poly[d][i]; |
242 |
for (d=0; d<=degree; d+=2) |
243 |
for (i=0; i<length/2; i++) |
244 |
poly[d][length-i-1] = poly[d][i]; |
245 |
} |
246 |
|
247 |
|
248 |
static void ORTHO_POLY(int degree, int length, RTYPE **poly, int *isgood) |
249 |
{ |
250 |
int d,i,j; |
251 |
RTYPE norm; |
252 |
|
253 |
// Normalize wrt. inner product on good part. |
254 |
for (d=0; d<=degree; d++) |
255 |
{ |
256 |
norm = 0.0; |
257 |
for (i=0; i<length; i++) |
258 |
if (isgood[i]) |
259 |
norm += poly[d][i]*poly[d][i]; |
260 |
norm = sqrt(norm); |
261 |
for (i=0; i<length; i++) |
262 |
poly[d][i] /= norm; |
263 |
} |
264 |
|
265 |
// Orthogonalize wrt. inner product on good part. |
266 |
for (d=0; d<=degree; d++) |
267 |
for (j=d-1; j>=0; j--) |
268 |
{ |
269 |
norm = 0; |
270 |
for (i=0; i<length; i++) |
271 |
if (isgood[i]) |
272 |
norm += poly[j][i]*poly[d][i]; |
273 |
for (i=0; i<length; i++) |
274 |
poly[d][i] -= norm*poly[j][i]; |
275 |
} |
276 |
|
277 |
// Normalize again wrt. inner product on good part. |
278 |
for (d=0; d<=degree; d++) |
279 |
{ |
280 |
norm = 0.0; |
281 |
for (i=0; i<length; i++) |
282 |
if (isgood[i]) |
283 |
norm += poly[d][i]*poly[d][i]; |
284 |
norm = sqrt(norm); |
285 |
for (i=0; i<length; i++) |
286 |
poly[d][i] /= norm; |
287 |
} |
288 |
|
289 |
} |
290 |
|
291 |
|
292 |
#undef DETREND |
293 |
#undef DETREND_DISCONTIG |
294 |
#undef LEGENDRE_POLY |
295 |
#undef ORTHO_POLY |
296 |
#include "ctypes_undef.h" |