TPCCLIB
Loading...
Searching...
No Matches
interpolate.c
Go to the documentation of this file.
1
5/*****************************************************************************/
6#include "tpcclibConfig.h"
7/*****************************************************************************/
8#include <stdio.h>
9#include <stdlib.h>
10#include <math.h>
11#include <time.h>
12#include <string.h>
13/*****************************************************************************/
14#include "tpcextensions.h"
15/*****************************************************************************/
16#include "tpcli.h"
17/*****************************************************************************/
18
19/*****************************************************************************/
29 double *x,
31 const int nr
32) {
33 int i;
34 double s, d;
35 if(nr<1 || x==NULL) return 0.0;
36 s=x[nr-1];
37 for(i=1; i<nr; i++) {
38 d=x[i]-x[i-1];
39 if(d>1.0E-20) {s=d; break;}
40 }
41 return s;
42}
43/*****************************************************************************/
44
45/*****************************************************************************/
50unsigned int simSamples(
52 double initStep,
54 double maxStep,
56 double endTime,
62 int mode,
64 double *x
65) {
66 unsigned int n=0;
67 if(initStep<=0.0 || endTime<=0.0 || endTime<initStep) return(n);
68 if(maxStep<initStep) maxStep=endTime;
69
70 double x1=0.0, s=initStep;
71 if(mode==0) {
72 while(x1<endTime) {
73 if(x!=NULL) x[n]=x1;
74 x1+=s; n++;
75 }
76 if(x!=NULL) x[n]=x1;
77 n++;
78 } else if(mode==1) {
79 while(x1<endTime) {
80 for(int i=0; i<10 && x1<endTime; i++, n++) {
81 if(x!=NULL) x[n]=x1;
82 x1+=s;
83 }
84 s*=2.0; if(s>maxStep) s=maxStep;
85 for(int i=0; i<5 && x1<endTime; i++, n++) {
86 if(x!=NULL) x[n]=x1;
87 x1+=s;
88 }
89 s*=2.5; if(s>maxStep) s=maxStep;
90 for(int i=0; i<2 && x1<endTime; i++, n++) {
91 if(x!=NULL) x[n]=x1;
92 x1+=s;
93 }
94 s*=2.0; if(s>maxStep) s=maxStep;
95 }
96 if(x!=NULL) x[n]=x1;
97 n++;
98 } else if(mode==2) {
99 while(x1<endTime) {
100 for(int i=0; i<20 && x1<endTime; i++, n++) {
101 if(x!=NULL) x[n]=x1;
102 x1+=s;
103 }
104 s*=2.0; if(s>maxStep) s=maxStep;
105 for(int i=0; i<10 && x1<endTime; i++, n++) {
106 if(x!=NULL) x[n]=x1;
107 x1+=s;
108 }
109 s*=2.5; if(s>maxStep) s=maxStep;
110 for(int i=0; i<5 && x1<endTime; i++, n++) {
111 if(x!=NULL) x[n]=x1;
112 x1+=s;
113 }
114 s*=2.0; if(s>maxStep) s=maxStep;
115 }
116 if(x!=NULL) x[n]=x1;
117 n++;
118 }
119 return(n);
120}
121/*****************************************************************************/
122
123/*****************************************************************************/
144 double *x,
147 double *y,
149 const int nr,
152 double *newx,
154 double *newy,
156 double *newyi,
158 double *newyii,
160 const int newnr,
171 const int se,
176 const int ee,
178 const int verbose
179) {
180 if(verbose>0) printf("%s(x, y, %d, nx, ny, ni, ni2, %d, %d, %d)\n", __func__, nr, newnr, se, ee);
181 /* Check for data */
182 if(nr<1 || newnr<1) return 1;
183 if(x==NULL || y==NULL || newx==NULL) return 1;
184
185 int i, j;
186 double ty, tyi, tyii;
187 double ox1, ox2, oy1, oy2, oi1, oi2, oii1, oii2, dt, ndt;
188
189 /* Initiate first two input samples */
190 if(se==0) {
191 if(x[0]<0.0) {ox1=ox2=x[0]; oy1=oy2=y[0];}
192 else {ox1=0.0; ox2=x[0]; oy1=0.0; oy2=0.0;}
193 } else if(se==1) {
194 if(x[0]<0.0) {ox1=ox2=x[0]; oy1=oy2=y[0];}
195 else {ox1=0.0; ox2=x[0]; oy1=oy2=y[0];}
196 } else {
197 ox1=ox2=x[0];
198 oy1=oy2=y[0];
199 }
200 /* Extrapolate the initial phase with triangle... */
201 if(ox1>0.0 && se>=2) {
202 oy1=0.0;
203 if(se==2) { // always
204 ox1=0.0;
205 } else if(se==3 && y[0]>0.0) { // if y[0]>0
206 // and initial gap is not too big
207 if(liFirstStepSize(x, nr)-x[0] >= 1.0E-20)
208 ox1=0.0;
209 } else if(se==4 && y[0]>0.0) { // if y[0]>0
210 // if initial gap is not too big, start triangle from zero
211 if(liFirstStepSize(x, nr)-x[0] >= 1.0E-20)
212 ox1=0.0;
213 else
214 // otherwise start triangle from guessed zero sample
215 ox1=x[0]-liFirstStepSize(x, nr);
216 }
217 }
218
219 /* Integrals too */
220 oi1=oii1=0.0;
221 oi2=oi1 + (ox2-ox1)*(oy1+oy2)/2.0;
222 oii2=oii1 + (ox2-ox1)*(oi1+oi2)/2.0;
223 if(verbose>1) {
224 printf("ox1=%g oy1=%g oi1=%g oii1=%g\n", ox1, oy1, oi1, oii1);
225 printf("ox2=%g oy2=%g oi2=%g oii2=%g\n", ox2, oy2, oi2, oii2);
226 }
227
228 /* Set interpolated data before input data (even imaginary) to zero */
229 if(verbose>2) printf("before input start\n");
230 j=0; while(j<newnr && newx[j]<ox1) {
231 ty=tyi=tyii=0.0; if(verbose>2) printf(" ndt=%g\n", ox1-newx[j]);
232 if(verbose>2) printf(" j=%d newx=%g ty=%g tyi=%g tyii=%g\n", j, newx[j], ty, tyi, tyii);
233 if(newy!=NULL) newy[j]=ty;
234 if(newyi!=NULL) newyi[j]=tyi;
235 if(newyii!=NULL) newyii[j]=tyii;
236 j++;
237 }
238
239 /* Set interpolated data between ox1 and ox2 */
240 if(verbose>2) printf("before input start #2\n");
241// dt=ox2-ox1; if(dt>0.0) while(j<newnr && newx[j]<=ox2) {
242 dt=ox2-ox1; if(dt>0.0) while(j<newnr && newx[j]<ox2) {
243 ndt=newx[j]-ox1; if(verbose>2) printf(" ndt=%g\n", ndt);
244 ty=((oy2-oy1)/dt)*ndt + oy1; if(newy!=NULL) newy[j]=ty;
245 tyi=oi1 + 0.5*(ty+oy1)*ndt; if(newyi!=NULL) newyi[j]=tyi;
246 if(newyii!=NULL) newyii[j]=tyii= oii1 + 0.5*(tyi+oi1)*ndt;
247 if(verbose>2) printf(" j=%d newx=%g ty=%g tyi=%g tyii=%g\n", j, newx[j], ty, tyi, tyii);
248 j++;
249 }
250
251 /* Go through input data, sample-by-sample */
252 if(verbose>2) printf("inside input range\n");
253 for(i=0; i<nr && j<newnr; i++) {
254
255 ox1=ox2; oy1=oy2; oi1=oi2; oii1=oii2;
256 ox2=x[i]; oy2=y[i];
257 oi2=oi1 + (ox2-ox1)*(oy1+oy2)/2.0;
258 oii2=oii1 + (ox2-ox1)*(oi1+oi2)/2.0;
259 if(verbose>2) {
260 printf("ox1=%g oy1=%g oi1=%g oii1=%g\n", ox1, oy1, oi1, oii1);
261 printf("ox2=%g oy2=%g oi2=%g oii2=%g\n", ox2, oy2, oi2, oii2);
262 }
263
264 /* Calculate input sample distance */
265 dt=ox2-ox1; if(dt<0.0) return 3; else if(dt==0.0) continue;
266
267 /* Any need for interpolation between ox1 and ox2? */
268 while(j<newnr && newx[j]<=ox2) {
269 ndt=newx[j]-ox1;
270 ty=((oy2-oy1)/dt)*ndt + oy1; if(newy!=NULL) newy[j]=ty;
271 tyi=oi1 + 0.5*(ty+oy1)*ndt; if(newyi!=NULL) newyi[j]=tyi;
272 if(newyii!=NULL) newyii[j]=tyii= oii1 + 0.5*(tyi+oi1)*ndt;
273 if(verbose>4)
274 printf(" j=%d newx=%g ndt=%g ty=%g tyi=%g tyii=%g\n", j, newx[j], ndt, ty, tyi, tyii);
275 j++;
276 }
277
278 } // next input sample
279
280 /* Set interpolated data after input data, assuming zero or steady input */
281 if(verbose>2) printf("after input range\n");
282 while(j<newnr) {
283 ndt=newx[j]-ox2;
284 if(ee==0) ty=0.0; else ty=oy2;
285 if(ee==0) tyi=oi2; else tyi=oi2 + oy2*ndt;
286 tyii=oii2 + 0.5*(tyi+oi2)*ndt;
287 if(newy!=NULL) newy[j]=ty;
288 if(newyi!=NULL) newyi[j]=tyi;
289 if(newyii!=NULL) newyii[j]=tyii;
290 if(verbose>4) printf(" j=%d newx=%g ty=%g tyi=%g tyii=%g\n", j, newx[j], ty, tyi, tyii);
291 j++;
292 }
293
294 if(verbose>3) printf("%s() ready\n", __func__);
295 return 0;
296}
297/*****************************************************************************/
298
299/*****************************************************************************/
321 double *x,
323 double *y,
325 const int nr,
328 double *newx1,
332 double *newx2,
334 double *newy,
337 double *newyi,
340 double *newyii,
342 const int newnr,
353 const int se,
358 const int ee,
360 const int verbose
361) {
362 if(verbose>0)
363 printf("%s(x, y, %d, nx1, nx2, ny, ni, ni2, %d, %d, %d)\n", __func__, nr, newnr, se, ee);
364
365 /* Check for data */
366 if(nr<1 || newnr<1) return 1;
367 if(x==NULL || y==NULL || newx1==NULL || newx2==NULL) return 1;
368 /* Check that input data is not totally outside the input data */
369 if(newx2[newnr-1]<=x[0] || newx1[0]>=x[nr-1]) return 3;
370
371 /* Nothing to do if output arrays were not given */
372 if(newy==NULL && newyi==NULL && newyii==NULL) return 0;
373
374 int ret, fi, zeroframe=0, overlap=0;
375 double fdur;
376
377 /* Check frame lengths, also for overlap and zero length frames */
378 for(fi=0; fi<newnr; fi++) {
379 /* Calculate frame length */
380 fdur=newx2[fi]-newx1[fi];
381 /* If frame length is <0, that is an error */
382 if(fdur<0.0) return 4;
383 if(fdur==0.0) zeroframe++;
384 /* Overlap? */
385 if(fi>0 && newx2[fi-1]>newx1[fi]) overlap++;
386 }
387 if(verbose>2) {
388 printf("overlap := %d\n", overlap);
389 printf("zeroframe := %d\n", zeroframe);
390 }
391
392 /* Interpolate and integrate one frame at a time, if:
393 -there are overlapping frames
394 -there are frames of zero length
395 -only few interpolated frames
396 -if frame mean values are not needed
397 */
398
399 if(overlap>0 || zeroframe>0 || newnr<=3 || newy==NULL )
400 {
401 double petx[3], pety[3], petyi[3], petyii[3];
402
403 if(verbose>1) printf("frame-by-frame interpolation/integration\n");
404 for(fi=0; fi<newnr; fi++) {
405 /* Set frame start, middle and end times */
406 petx[0]=newx1[fi]; petx[2]=newx2[fi]; petx[1]=0.5*(petx[0]+petx[2]);
407 /* Calculate frame length */
408 fdur=petx[2]-petx[0];
409 /* If frame length is <0, that is an error */
410 if(fdur<0.0) return 4;
411 /* If frame length is 0, then use direct interpolation */
412 if(fdur==0.0) {
413 ret=liInterpolate(x, y, nr, petx, pety, petyi, petyii, 1, se, ee, verbose-1);
414 if(ret) return 10+ret;
415 if(newy!=NULL) newy[fi]=petyi[0];
416 if(newyi!=NULL) newyi[fi]=petyi[0];
417 if(newyii!=NULL) newyii[fi]=petyii[0];
418 continue;
419 }
420 /* Calculate integrals at frame start, middle, and end */
421 ret=liInterpolate(x, y, nr, petx, NULL, petyi, petyii, 3, se, ee, verbose-1);
422 if(ret) return 20+ret;
423 /* Set output integrals, if required */
424 if(newyi!=NULL) newyi[fi]=petyi[1];
425 if(newyii!=NULL) newyii[fi]=petyii[1];
426 /* Calculate frame mean, if required */
427 if(newy!=NULL) newy[fi]=(petyi[2]-petyi[0])/fdur;
428 } // next frame
429
430 } else {
431
432 if(verbose>1) printf("all-frames-at-once interpolation/integration\n");
433 /* Set temp array */
434 double *tp=NULL; tp=malloc(newnr*sizeof(double)); if(tp==NULL) return 7;
435 /* Integrate at frame start times */
436 ret=liInterpolate(x, y, nr, newx1, NULL, tp, NULL, newnr, se, ee, verbose-1);
437 if(ret) {free(tp); return 10+ret;}
438 /* Integrate at frame end times */
439 ret=liInterpolate(x, y, nr, newx2, NULL, newy, NULL, newnr, se, ee, verbose-1);
440 if(ret) {free(tp); return 10+ret;}
441 /* Calculate average frame value */
442 for(fi=0; fi<newnr; fi++)
443 newy[fi]=(newy[fi]-tp[fi])/(newx2[fi]-newx1[fi]);
444 /* Calculate integrals */
445 if(newyi!=NULL || newyii!=NULL) {
446 for(fi=0; fi<newnr; fi++) tp[fi]=0.5*(newx2[fi]+newx1[fi]);
447 ret=liInterpolate(x, y, nr, tp, NULL, newyi, newyii, newnr, se, ee, verbose-1);
448 if(ret) {free(tp); return 10+ret;}
449 }
450 free(tp);
451 }
452
453 if(verbose>1) printf("%s() ready\n", __func__);
454
455
456 return 0;
457}
458/*****************************************************************************/
459
460/*****************************************************************************/
461#if(0) // not useful
481int liFrameMidValue(
485 double *x1,
489 double *x2,
492 double *y,
494 const size_t nr,
496 double *newy,
498 const int verbose
499) {
500 if(verbose>0) printf("%s(x1, x2, y, %zu, ny, %d)\n", __func__, nr, verbose);
501
502 /* Check for data */
503 if(nr<1) return 1;
504 if(x1==NULL || x2==NULL || y==NULL || newy==NULL) return 1;
505 if(nr<3) {
506 if(verbose>2) printf("less than 3 frames; nothing done.\n");
507 for(size_t i=0; i<nr; i++) newy[i]=y[i];
508 return 0;
509 }
510
511 /* Calculate frame middle times and durations / 2.
512 Check that frames durations are >=0.
513 Check that frame times are in ascending order.
514 */
515 double hfdur[nr], x[nr];
516 for(size_t i=0; i<nr; i++) {
517 x[i]=0.5*(x1[i]+x2[i]);
518 hfdur[i]=0.5*(x2[i]-x1[i]);
519 if(hfdur[i]<0.0) {
520 if(verbose>0) fprintf(stderr, "negative frame length.\n");
521 return 2;
522 }
523 if(i>0 && x[i]<x[i-1]) {
524 if(verbose>0) fprintf(stderr, "frame times not ascending.\n");
525 return 3;
526 }
527 }
528
529 /* Compute data matrix for solving (very simply) the y values at frame middle times */
530 double A[2][nr], B[nr], xdif;
531 A[0][0]=1.0; A[1][0]=0.0; B[0]=y[0];
532 for(size_t i=1; i<nr-1; i++) {
533 xdif=x[i+1]-x[i];
534 if(!(hfdur[i]>1.0E-100) || !(xdif>1.0E-100)) { // catches both zero and NaN
535 A[0][i]=0.0; A[1][i]=0.0; B[i]=y[i];
536 } else {
537 A[0][i]=4.0*(x[i]-x[i-1])/hfdur[i] - (x[i+1]-x[i-1])/xdif;
538 A[1][i]=(x[i]-x[i-1])/xdif;
539 B[i]=4.0*y[i]*(x[i]-x[i-1])/hfdur[i];
540 }
541 }
542 A[0][nr-1]=1.0; A[1][nr-1]=0.0; B[nr-1]=y[nr-1];
543 if(verbose>4) {
544 printf("A[1]\tA[2]\t\tB\n");
545 for(size_t i=0; i<nr; i++) printf("%g\t%g\t\t%g\n", A[0][i], A[1][i], B[i]);
546 }
547
548 /* Solve */
549 for(size_t i=1; i<nr-1; i++) {
550 if(fabs(A[0][i])<1.0E-100) continue;
551 A[0][i]-=A[1][i-1]; B[i]-=B[i-1];
552 A[1][i]/=A[0][i]; B[i]/=A[0][i]; A[0][i]=1.0;
553 }
554 if(verbose>5) {
555 printf("A[1]\tA[2]\t\tB\n");
556 for(size_t i=0; i<nr; i++) printf("%g\t%g\t\t%g\n", A[0][i], A[1][i], B[i]);
557 }
558 newy[0]=y[0]; newy[nr-1]=y[nr-1];
559 for(size_t i=nr-2; i>0; i--) {
560 newy[i]=B[i]-newy[i+1]*A[1][i];
561 if(verbose>5) printf("X[%zu]=%g\n", i+1, newy[i]);
562 }
563 /* Set any NaNs to original values (which of course may be NaN as well) */
564 for(size_t i=1; i<nr-1; i++) if(isnan(newy[i])) newy[i]=y[i];
565
566 if(verbose>1) printf("%s() ready\n", __func__);
567 return 0;
568}
569#endif
570/*****************************************************************************/
571
572/*****************************************************************************/
unsigned int simSamples(double initStep, double maxStep, double endTime, int mode, double *x)
Definition interpolate.c:50
int liInterpolate(double *x, double *y, const int nr, double *newx, double *newy, double *newyi, double *newyii, const int newnr, const int se, const int ee, const int verbose)
Linear interpolation and/or integration with trapezoidal method.
double liFirstStepSize(double *x, const int nr)
Find the initial x step size.
Definition interpolate.c:25
int liInterpolateForPET(double *x, double *y, const int nr, double *newx1, double *newx2, double *newy, double *newyi, double *newyii, const int newnr, const int se, const int ee, const int verbose)
Linear TAC interpolation and/or integration to PET frames.
Header file for library libtpcextensions.
Header file for libtpcli.