TPCCLIB
Loading...
Searching...
No Matches
integr.c File Reference

linear interpolation and integration of PET and blood/plasma TACs. More...

#include "libtpcmodel.h"

Go to the source code of this file.

Functions

int interpolate (double *x, double *y, int nr, double *newx, double *newy, double *newyi, double *newyii, int newnr)
 Linear interpolation and integration.
 
int finterpolate (float *x, float *y, int nr, float *newx, float *newy, float *newyi, float *newyii, int newnr)
 float version of interpolate().
 
int integrate (double *x, double *y, int nr, double *yi)
 
int fintegrate (float *x, float *y, int nr, float *yi)
 float version of integrate().
 
int petintegrate (double *x1, double *x2, double *y, int nr, double *newyi, double *newyii)
 
int fpetintegrate (float *x1, float *x2, float *y, int nr, float *newyi, float *newyii)
 Calculates integrals of PET data at frame end times. Float version of petintegrate().
 
int interpolate4pet (double *x, double *y, int nr, double *newx1, double *newx2, double *newy, double *newyi, double *newyii, int newnr)
 Interpolate and integrate TAC to PET frames.
 
int finterpolate4pet (float *x, float *y, int nr, float *newx1, float *newx2, float *newy, float *newyi, float *newyii, int newnr)
 Interpolate and integrate TAC to PET frames. Float version of interpolate4pet().
 
int petintegral (double *x1, double *x2, double *y, int nr, double *ie, double *iie)
 Integrate PET TAC data to frame mid times.
 
int fpetintegral (float *x1, float *x2, float *y, int nr, float *ie, float *iie)
 Integrate PET TAC data to frame mid times. Float version of petintegral().
 
int petintegrate2fe (double *x1, double *x2, double *y, int nr, double *e, double *ie, double *iie)
 Integrate PET TAC data to frame end times.
 
int fpetintegrate2fe (float *x1, float *x2, float *y, int nr, float *e, float *ie, float *iie)
 Integrate PET TAC data to frame end times. Float version of petintegrate2fe().
 

Detailed Description

linear interpolation and integration of PET and blood/plasma TACs.

Author
Vesa Oikonen, Kaisa Liukko

Definition in file integr.c.

Function Documentation

◆ fintegrate()

int fintegrate ( float * x,
float * y,
int nr,
float * yi )

float version of integrate().

Linear integration from time 0 to x[0..nr-1]. If x[0] is >0 and x[0]<=(x[1]-x[0]), then the beginning is interpolated from it to (0,0).

Returns
Returns 0 if OK, or 1, if error.
See also
integrate, fpetintegrate, finterpolate
Parameters
xOriginal x values; duplicates are not allowed, all must be >=0. Data must be sorted by ascending x
yOriginal y values
nrNr of values
yiArray for integrals

Definition at line 300 of file integr.c.

310 {
311 int j;
312
313 if(nr==1 || x[0]<=(x[1]-x[0])) yi[0]=0.5*y[0]*x[0];
314 else yi[0]=0; /*If the gap in the beginning is longer than time
315 between first and second time point */
316 for(j=1; j<nr; j++) yi[j]=yi[j-1]+0.5*(y[j]+y[j-1])*(x[j]-x[j-1]);
317
318 return 0;
319}

◆ finterpolate()

int finterpolate ( float * x,
float * y,
int nr,
float * newx,
float * newy,
float * newyi,
float * newyii,
int newnr )

float version of interpolate().

It is assumed that both original and new interpolated data represent the actual values at specified time points (not from framed data). The integration is calculated dot-by-dot.

If NULL is specified for newy[], newyi[] and/or newyii[], their values are not calculated.

Original data and new x values must be sorted by ascending x. Subsequent x values can have equal values, enabling the use of step functions. Negative x (time) values can be processed. If necessary, the data is extrapolated assuming that: 1) y[inf]=y[nr-1] and 2) if x[0]>0, y[0]>0 and x[0]<=x[1]-x[0], then an imaginary line is drawn from (0,0) to (x[0],y[0]).

Returns
Non-zero in case of an error.
See also
interpolate, fintegrate
Parameters
xInput data x (time) values
yInput data y values
nrNumber of values in input data
newxOutput data x values
newyInterpolated (extrapolated) y values; NULL can be given if not needed
newyiIntegrals; NULL can be given if not needed
newyii2nd integrals; NULL can be given if not needed
newnrNr of values in output data

Definition at line 161 of file integr.c.

178 {
179 int i, j;
180 float ty, tyi, tyii;
181 float ox1, ox2, oy1, oy2, oi1, oi2, oii1, oii2, dt, ndt;
182 int verbose=0;
183
184 if(verbose>0) printf("in finterpolate()\n");
185 /* Check for data */
186 if(nr<1 || newnr<1) return 1;
187 /* Check that programmer understood that outp data must've been allocated */
188 if(newy==NULL && newyi==NULL && newyii==NULL) return 2;
189
190 /* Initiate first two input samples */
191 ox1=ox2=x[0];
192 oy1=oy2=y[0];
193 /* Extrapolate the initial phase with triangle... */
194 if(ox1>0.0) {
195 oy1=0.0;
196 /* unless:
197 -first input sample y<=0
198 -initial gap is longer than input TAC sampling frequency
199 */
200 if(y[0]>0.0 && (nr>1 && x[0]<=x[1]-x[0])) ox1=0.0;
201 }
202 /* Integrals too */
203 oi1=oii1=0.0;
204 oi2=oi1 + (ox2-ox1)*(oy1+oy2)/2.0;
205 oii2=oii1 + (ox2-ox1)*(oi1+oi2)/2.0;
206
207 /* Set interpolated data before input data (even imaginary) to zero */
208 j=0; while(j<newnr && newx[j]<ox1) {
209 ty=tyi=tyii=0.0;
210 if(newy!=NULL) newy[j]=ty;
211 if(newyi!=NULL) newyi[j]=tyi;
212 if(newyii!=NULL) newyii[j]=tyii;
213 j++;
214 }
215
216 /* Set interpolated data between ox1 and ox2 */
217 dt=ox2-ox1; if(dt>0.0) while(j<newnr && newx[j]<=ox2) {
218 ndt=newx[j]-ox1;
219 ty=((oy2-oy1)/dt)*ndt + oy1; if(newy!=NULL) newy[j]=ty;
220 tyi=oi1 + 0.5*(ty+oy1)*ndt; if(newyi!=NULL) newyi[j]=tyi;
221 if(newyii!=NULL) newyii[j]=tyii= oii1 + 0.5*(tyi+oi1)*ndt;
222 j++;
223 }
224
225 /* Go through input data, sample-by-sample */
226 for(i=0; i<nr && j<newnr; i++) {
227
228 ox1=ox2; oy1=oy2; oi1=oi2; oii1=oii2;
229 ox2=x[i]; oy2=y[i];
230 oi2=oi1 + (ox2-ox1)*(oy1+oy2)/2.0;
231 oii2=oii1 + (ox2-ox1)*(oi1+oi2)/2.0;
232
233 /* Calculate input sample distance */
234 dt=ox2-ox1; if(dt<0.0) return 3; else if(dt==0.0) continue;
235
236 /* Any need for interpolation between ox1 and ox2? */
237 while(j<newnr && newx[j]<=ox2) {
238 ndt=newx[j]-ox1;
239 ty=((oy2-oy1)/dt)*ndt + oy1; if(newy!=NULL) newy[j]=ty;
240 tyi=oi1 + 0.5*(ty+oy1)*ndt; if(newyi!=NULL) newyi[j]=tyi;
241 if(newyii!=NULL) newyii[j]=tyii= oii1 + 0.5*(tyi+oi1)*ndt;
242 j++;
243 }
244
245 } // next input sample
246
247 /* Set interpolated data after input data, assuming steady input */
248 while(j<newnr) {
249 ndt=newx[j]-ox2;
250 ty=oy2;
251 tyi=oi2 + oy2*ndt;
252 tyii=oii2 + 0.5*(tyi+oi2)*ndt;
253 if(newy!=NULL) newy[j]=ty;
254 if(newyi!=NULL) newyi[j]=tyi;
255 if(newyii!=NULL) newyii[j]=tyii;
256 j++;
257 }
258
259 if(verbose>0) printf("out finterpolate()\n");
260 return 0;
261}

Referenced by finterpolate4pet(), and imgTimeIntegral().

◆ finterpolate4pet()

int finterpolate4pet ( float * x,
float * y,
int nr,
float * newx1,
float * newx2,
float * newy,
float * newyi,
float * newyii,
int newnr )

Interpolate and integrate TAC to PET frames. Float version of interpolate4pet().

It is assumed, that original data is not from framed data, but that the values represent the actual value at specified time point, which allows the integration to be calculated dot-by-dot.

If NULL is specified for *newy, *newyi and/or *newyii, their values are not calculated.

Original data and new x values must be sorted by ascending x. Subsequent x values can have equal values, enabling the use of step functions. PET frames can overlap, but interpolation may then be slower. Negative x (time) values can be processed. If necessary, the data is extrapolated assuming that 1) y[inf]=y[nr-1] and 2) if x[0]>0 and y[0]>0 and x[0]>x[1]-x[0], then an imaginary line is drawn from (0,0) to (x[0],y[0]).

Returns
Non-zero in case of an error.
See also
fpetintegral, interpolate4pet, fintegrate
Parameters
xTimes of original data
yValues of original data
nrNumber of original data values
newx1PET frame start times; frames may overlap
newx2PET frame end times; frames may overlap
newyMean value during PET frame, or NULL if not needed; calculation may be faster if newyi is calculated too
newyiIntegral at frame mid time, or NULL if not needed
newyii2nd integral at frame mid time, or NULL if not needed
newnrNumber of PET frames

Definition at line 646 of file integr.c.

666 {
667 int ret, fi, overlap=0, zeroframe=0;
668 float petx[3], pety[3], petyi[3], petyii[3], fdur;
669 int verbose=0;
670
671 if(verbose>0) printf("in finterpolate4pet()\n");
672
673 /* Check for data */
674 if(nr<1 || newnr<1) return 1;
675 /* Check that programmer understood that outp data must've been allocated */
676 if(newy==NULL && newyi==NULL && newyii==NULL) return 2;
677 /* Check that input data is not totally outside the input data */
678 if(newx2[newnr-1]<=x[0] || newx1[0]>=x[nr-1]) return 3;
679
680 /* Check frame lengths, also for overlap and zero length frames */
681 for(fi=0; fi<newnr; fi++) {
682 /* Calculate frame length */
683 fdur=newx2[fi]-newx1[fi];
684 /* If frame length is <0, that is an error */
685 if(fdur<0.0) return 4;
686 if(fdur==0.0) zeroframe++;
687 /* Overlap? */
688 if(fi>0 && newx2[fi-1]>newx1[fi]) overlap++;
689 }
690 if(verbose>1) {
691 printf("overlap := %d\n", overlap);
692 printf("zeroframe := %d\n", zeroframe);
693 }
694
695 /* Interpolate and integrate one frame at a time, if there is:
696 -overlap in frames
697 -frames of zero length
698 -only few interpolated frames
699 -if only integrals are needed
700 -if neither of integrals is needed, then there is no temp memory to
701 do otherwise
702 */
703 if(overlap>0 || zeroframe>0 || newnr<=3 || newy==NULL || (newyi==NULL && newyii==NULL) ) {
704
705 if(verbose>1) printf("frame-by-frame interpolation/integration\n");
706 for(fi=0; fi<newnr; fi++) {
707 /* Set frame start, middle and end times */
708 petx[0]=newx1[fi]; petx[2]=newx2[fi]; petx[1]=0.5*(petx[0]+petx[2]);
709 /* Calculate frame length */
710 fdur=petx[2]-petx[0];
711 /* If frame length is <0, that is an error */
712 if(fdur<0.0) return 4;
713 /* If frame length is 0, then use direct interpolation */
714 if(fdur==0.0) {
715 ret=finterpolate(x, y, nr, petx, pety, petyi, petyii, 1);
716 if(ret) return 10+ret;
717 if(newy!=NULL) newy[fi]=petyi[0];
718 if(newyi!=NULL) newyi[fi]=petyi[0];
719 if(newyii!=NULL) newyii[fi]=petyii[0];
720 continue;
721 }
722 /* Calculate integrals at frame start, middle, and end */
723 ret=finterpolate(x, y, nr, petx, NULL, petyi, petyii, 3);
724 if(ret) return 20+ret;
725 /* Set output integrals, if required */
726 if(newyi!=NULL) newyi[fi]=petyi[1];
727 if(newyii!=NULL) newyii[fi]=petyii[1];
728 /* Calculate frame mean, if required */
729 if(newy!=NULL) newy[fi]=(petyi[2]-petyi[0])/fdur;
730 } // next frame
731
732 } else {
733
734 if(verbose>1) printf("all-frames-at-once interpolation/integration\n");
735 /* Set temp array */
736 float *tp; if(newyii!=NULL) tp=newyii; else tp=newyi;
737 /* Integrate at frame start times */
738 ret=finterpolate(x, y, nr, newx1, NULL, tp, NULL, newnr);
739 if(ret) return 10+ret;
740 /* Integrate at frame end times */
741 ret=finterpolate(x, y, nr, newx2, NULL, newy, NULL, newnr);
742 if(ret) return 10+ret;
743 /* Calculate average frame value */
744 for(fi=0; fi<newnr; fi++)
745 newy[fi]=(newy[fi]-tp[fi])/(newx2[fi]-newx1[fi]);
746 /* Calculate integrals */
747 if(newyi!=NULL || newyii!=NULL) {
748 for(fi=0; fi<newnr; fi++) newx1[fi]+=0.5*(newx2[fi]-newx1[fi]);
749 ret=finterpolate(x, y, nr, newx1, NULL, newyi, newyii, newnr);
750 if(ret) return 10+ret;
751 for(fi=0; fi<newnr; fi++) newx1[fi]-=(newx2[fi]-newx1[fi]);
752 }
753
754 }
755
756 if(verbose>0) printf("out finterpolate4pet()\n");
757 return 0;
758}
int finterpolate(float *x, float *y, int nr, float *newx, float *newy, float *newyi, float *newyii, int newnr)
float version of interpolate().
Definition integr.c:161

◆ fpetintegral()

int fpetintegral ( float * x1,
float * x2,
float * y,
int nr,
float * ie,
float * iie )

Integrate PET TAC data to frame mid times. Float version of petintegral().

Any of output arrays may be set to NULL if that is not needed. Frames must be in ascending time order. Gaps and small overlap are allowed. If x1[0]>0 and x1[0]<=x2[0]-x1[0], then an imaginary line is drawn from (0,0) to (x[0],y[0]).

Returns
Returns 0 if ok.
See also
petintegral, finterpolate4pet
Parameters
x1frame start times
x2frame end times
yavg value during frame
nrnumber of frames
ieintegrals at frame mid time
iie2nd integrals at frame mid time

Definition at line 838 of file integr.c.

851 {
852 int i;
853 float x, last_x, last_x2, last_y, last_integral, box_integral, half_integral;
854 float gap_integral, integral, integral2, frame_len, xdist, s;
855
856 /* Check for data */
857 if(nr<1 || nr<1) return(1);
858 /* Check that programmer understood that output must've been allocated */
859 if(ie==NULL && iie==NULL) return(2);
860
861 /* Initiate values to zero */
862 last_x=last_x2=last_y=last_integral=0.0;
863 box_integral=gap_integral=integral=integral2=frame_len=0.0;
864
865 for(i=0; i<nr; i++) {
866 frame_len=x2[i]-x1[i]; if(frame_len<0.0) return(5);
867 x=0.5*(x1[i]+x2[i]); xdist=x-last_x; if(last_x>0.0 && xdist<=0.0) return(6);
868 if(x<0) {
869 if(ie!=NULL) ie[i]=integral;
870 if(iie!=NULL) iie[i]=integral2;
871 continue;
872 }
873 s=(y[i]-last_y)/xdist; /* slope */
874 /*If there is a big gap in the beginning it is eliminated */
875 if(i==0)if(x1[0]>x2[0]-x1[0]){last_x2=last_x=x1[0];}
876 /*Integral of a possible gap between frames*/
877 gap_integral=(x1[i]-last_x2)*(last_y+s*((last_x2+x1[i])/2.0-last_x));
878 /*Integral from the beginning of the frame i to the middle of the frame */
879 half_integral=(x-x1[i])*(last_y+s*((x1[i]+x)/2.0-last_x));
880 integral=box_integral+gap_integral+half_integral;
881 /* half_integral is not added to box because it is more accurate to
882 sum integrals of full frames */
883 box_integral+=gap_integral+frame_len*y[i];
884 integral2+=xdist*(integral+last_integral)*0.5;
885 if(ie!=NULL) ie[i]=integral;
886 if(iie!=NULL) iie[i]=integral2;
887 last_x=x; last_x2=x2[i];
888 last_y=y[i]; last_integral=integral;
889 }
890
891 return(0);
892}

Referenced by img_logan(), and img_patlak().

◆ fpetintegrate()

int fpetintegrate ( float * x1,
float * x2,
float * y,
int nr,
float * newyi,
float * newyii )

Calculates integrals of PET data at frame end times. Float version of petintegrate().

Data does not have to be continuous, but it must be increasing in time. For faster performance in repetitive calls, allocate memory for integral[] even if it is not needed. If x1[0] is >0 AND x1[0] is <=(x2[0]-x1[0]), then the beginning is interpolated from (0, 0) to (x1[0], y1[0]*x1[0]/x) where x is midtime of the first frame.

Returns
Returns 0 if ok.
See also
petintegrate, finterpolate, fintegrate, finterpolate4pet, fpetintegrate2fe
Parameters
x1Array of frame start times
x2Array of frame end times
yArray of y values (avg during each frame)
nrNr of frames
newyiOutput: integral values at frame end times, or NULL
newyiiOutput: 2nd integral values at frame end times, or NULL

Definition at line 418 of file integr.c.

431 {
432 int i, allocated=0;
433 float *ti, x, a;
434
435
436 /* Check that data is increasing in time and is not (much) overlapping */
437 if(nr<1 || x1[0]<0) return 1;
438 for(i=0; i<nr; i++) if(x2[i]<x1[i]) return 2;
439 for(i=1; i<nr; i++) if(x1[i]<=x1[i-1]) return 3;
440
441 /* Allocate memory for temp data, if necessary */
442 if(newyi==NULL) {
443 allocated=1;
444 ti=(float*)malloc(nr*sizeof(float)); if(ti==NULL) return 4;
445 } else
446 ti=newyi;
447
448 /* Calculate the integral at the end of first frame */
449 ti[0]=(x2[0]-x1[0])*y[0];
450 /* If frame does not start at 0 time, add the area in the beginning */
451 /* But only if the gap in the beginning is less than the lenght of the
452 first frame */
453 if(x1[0]>0) {
454 if(x1[0]<=x2[0]-x1[0]) {
455 x=(x1[0]+x2[0])/2.0;
456 a=(x1[0]*(y[0]/x)*x1[0])/2.0;
457 ti[0]+=a;
458 }
459 }
460
461 /* Calculate integrals at the ends of following frames */
462 for(i=1; i<nr; i++) {
463 /* Add the area of this frame to the previous integral */
464 a=(x2[i]-x1[i])*y[i]; ti[i]=ti[i-1]+a;
465 /* Check whether frames are contiguous */
466 if(x1[i]==x2[i-1]) continue;
467 /* When not, calculate the area of an imaginary frame */
468 x=(x1[i]+x2[i-1])/2.0;
469 a=(x1[i]-x2[i-1])*
470 (y[i]-(y[i]-y[i-1])*(x2[i]+x1[i]-2.0*x)/(x2[i]+x1[i]-x2[i-1]-x1[i-1]));
471 ti[i]+=a;
472 }
473
474 /* Copy integrals to output if required */
475 if(allocated) for(i=0; i<nr; i++) newyi[i]=ti[i];
476
477 /* Calculate 2nd integrals if required */
478 if(newyii!=NULL) {
479 newyii[0]=x2[0]*ti[0]/2.0;
480 for(i=1; i<nr; i++)
481 newyii[i]=newyii[i-1]+(x2[i]-x2[i-1])*(ti[i-1]+ti[i])/2.0;
482 }
483
484 /* Free memory */
485 if(allocated) free((char*)ti);
486
487 return 0;
488}

◆ fpetintegrate2fe()

int fpetintegrate2fe ( float * x1,
float * x2,
float * y,
int nr,
float * e,
float * ie,
float * iie )

Integrate PET TAC data to frame end times. Float version of petintegrate2fe().

Any of output arrays may be set to NULL if that is not needed. Frames must be in ascending time order. Gaps and small overlap are allowed. If x1[0]>0 and x1[0]<=x2[0]-x1[0], then an imaginary line is drawn from (0,0) to (x[0],y[0]).

Returns
Returns 0 if ok.
See also
petintegrate2fe
Parameters
x1frame start times
x2frame end times
yavg value during frame
nrnumber of frames
evalues at frame end time
ieintegrals at frame end time
iie2nd integrals at frame end time

Definition at line 974 of file integr.c.

989 {
990 int i;
991 float x, last_x, last_x2, last_y, last_integral;
992 float value, integral, integral2, frame_len, xdist, s;
993
994 /* Check for data */
995 if(nr<1 || nr<1) return(1);
996 /* Check that programmer understood that output must've been allocated */
997 if(e==NULL && ie==NULL && iie==NULL) return(2);
998
999 /* Initiate values to zero */
1000 last_x=last_x2=last_y=last_integral=value=integral=integral2=frame_len=s=0.0;
1001
1002 for(i=0; i<nr; i++) {
1003 frame_len=x2[i]-x1[i]; if(frame_len<0.0) return(5);
1004 x=0.5*(x1[i]+x2[i]); xdist=x-last_x; if(last_x>0.0 && xdist<=0.0) return(6);
1005 if(x<0) {
1006 if(e!=NULL) e[i]=value;
1007 if(ie!=NULL) ie[i]=integral;
1008 if(iie!=NULL) iie[i]=integral2;
1009 continue;
1010 }
1011 s=(y[i]-last_y)/xdist; /* slope between x[i-1] and x[i] */
1012 /* If there is a big gap in the beginning, it is eliminated */
1013 if(i==0 && x1[0]>x2[0]-x1[0]) {last_x2=last_x=x1[0];}
1014 integral+=(x1[i]-last_x2)*(last_y+s*((last_x2+x1[i])/2.0-last_x)); /*gap*/
1015 integral+=frame_len*y[i];
1016 integral2+=(x2[i]-last_x2)*(integral+last_integral)*0.5;
1017 if(e!=NULL && i>0) {
1018 value=last_y+s*(last_x2-last_x); /* value at previous frame end */
1019 e[i-1]=value;
1020 }
1021 if(ie!=NULL) ie[i]=integral;
1022 if(iie!=NULL) iie[i]=integral2;
1023 last_x=x; last_x2=x2[i]; last_y=y[i]; last_integral=integral;
1024 }
1025 if(e!=NULL) {
1026 value=last_y+s*(last_x2-last_x); /* Value for the last frame */
1027 e[i-1]=value;
1028 }
1029
1030 return(0);
1031}

◆ integrate()

int integrate ( double * x,
double * y,
int nr,
double * yi )

Linear integration from time 0 to x[0..nr-1]. If x[0] is >0 and x[0]<=(x[1]-x[0]), then the beginning is interpolated from it to (0,0).

Returns
Returns 0 if OK, or 1, if error.
See also
fintegrate, petintegrate, interpolate
Parameters
xOriginal x values; duplicates are not allowed, all must be >=0. Data must be sorted by ascending x
yOriginal y values
nrNr of values
yiArray for integrals

Definition at line 271 of file integr.c.

281 {
282 int j;
283
284 if(nr==1 || x[0]<=(x[1]-x[0])) yi[0]=0.5*y[0]*x[0];
285 else yi[0]=0; /*If the gap in the beginning is longer than time
286 between first and second time point */
287 for(j=1; j<nr; j++) yi[j]=yi[j-1]+0.5*(y[j]+y[j-1])*(x[j]-x[j-1]);
288
289 return 0;
290}

Referenced by dftReadReference().

◆ interpolate()

int interpolate ( double * x,
double * y,
int nr,
double * newx,
double * newy,
double * newyi,
double * newyii,
int newnr )

Linear interpolation and integration.

It is assumed that both original and new interpolated data represent the actual values at specified time points (not from framed data). The integration is calculated dot-by-dot.

If NULL is specified for newy[], newyi[] and/or newyii[], their values are not calculated.

Original data and new x values must be sorted by ascending x. Subsequent x values can have equal values, enabling the use of step functions. Negative x (time) values can be processed. If necessary, the data is extrapolated assuming that: 1) y[inf]=y[nr-1] and 2) if x[0]>0, y[0]>0 and x[0]<=x[1]-x[0], then an imaginary line is drawn from (0,0) to (x[0],y[0]).

Returns
Non-zero in case of an error.
See also
finterpolate, integrate, petintegrate, petintegral, dftTimeIntegral
Parameters
xInput data x (time) values
yInput data y values
nrNumber of values in input data
newxOutput data x values
newyInterpolated (extrapolated) y values; NULL can be given if not needed
newyiIntegrals; NULL can be given if not needed
newyii2nd integrals; NULL can be given if not needed
newnrNr of values in output data

Definition at line 28 of file integr.c.

45 {
46 int i, j;
47 double ty, tyi, tyii;
48 double ox1, ox2, oy1, oy2, oi1, oi2, oii1, oii2, dt, ndt;
49 int verbose=0;
50
51 if(verbose>0) printf("in interpolate()\n");
52 /* Check for data */
53 if(nr<1 || newnr<1) return 1;
54 /* Check that programmer understood that outp data must've been allocated */
55 if(newy==NULL && newyi==NULL && newyii==NULL) return 2;
56
57 /* Initiate first two input samples */
58 ox1=ox2=x[0];
59 oy1=oy2=y[0];
60 /* Extrapolate the initial phase with triangle... */
61 if(ox1>0.0) {
62 oy1=0.0;
63 /* unless:
64 -first input sample y<=0
65 -initial gap is longer than input TAC sampling frequency
66 */
67 if(y[0]>0.0 && (nr>1 && x[0]<=x[1]-x[0])) ox1=0.0;
68 }
69 /* Integrals too */
70 oi1=oii1=0.0;
71 oi2=oi1 + (ox2-ox1)*(oy1+oy2)/2.0;
72 oii2=oii1 + (ox2-ox1)*(oi1+oi2)/2.0;
73 if(verbose>2) {
74 printf("ox1=%g oy1=%g oi1=%g oii1=%g\n", ox1, oy1, oi1, oii1);
75 printf("ox2=%g oy2=%g oi2=%g oii2=%g\n", ox2, oy2, oi2, oii2);
76 }
77
78 /* Set interpolated data before input data (even imaginary) to zero */
79 j=0; while(j<newnr && newx[j]<ox1) {
80 ty=tyi=tyii=0.0; if(verbose>4) printf(" ndt=%g\n", ox1-newx[j]);
81 if(verbose>4) printf(" j=%d newx=%g ty=%g tyi=%g tyii=%g\n", j, newx[j], ty, tyi, tyii);
82 if(newy!=NULL) newy[j]=ty;
83 if(newyi!=NULL) newyi[j]=tyi;
84 if(newyii!=NULL) newyii[j]=tyii;
85 j++;
86 }
87
88 /* Set interpolated data between ox1 and ox2 */
89 dt=ox2-ox1; if(dt>0.0) while(j<newnr && newx[j]<=ox2) {
90 ndt=newx[j]-ox1; if(verbose>4) printf(" ndt=%g\n", ndt);
91 ty=((oy2-oy1)/dt)*ndt + oy1; if(newy!=NULL) newy[j]=ty;
92 tyi=oi1 + 0.5*(ty+oy1)*ndt; if(newyi!=NULL) newyi[j]=tyi;
93 if(newyii!=NULL) newyii[j]=tyii= oii1 + 0.5*(tyi+oi1)*ndt;
94 if(verbose>4) printf(" j=%d newx=%g ty=%g tyi=%g\n", j, newx[j], ty, tyi);
95 j++;
96 }
97
98 /* Go through input data, sample-by-sample */
99 for(i=0; i<nr && j<newnr; i++) {
100
101 ox1=ox2; oy1=oy2; oi1=oi2; oii1=oii2;
102 ox2=x[i]; oy2=y[i];
103 oi2=oi1 + (ox2-ox1)*(oy1+oy2)/2.0;
104 oii2=oii1 + (ox2-ox1)*(oi1+oi2)/2.0;
105 if(verbose>>3) {
106 printf("ox1=%g oy1=%g oi1=%g oii1=%g\n", ox1, oy1, oi1, oii1);
107 printf("ox2=%g oy2=%g oi2=%g oii2=%g\n", ox2, oy2, oi2, oii2);
108 }
109
110 /* Calculate input sample distance */
111 dt=ox2-ox1; if(dt<0.0) return 3; else if(dt==0.0) continue;
112
113 /* Any need for interpolation between ox1 and ox2? */
114 while(j<newnr && newx[j]<=ox2) {
115 ndt=newx[j]-ox1;
116 ty=((oy2-oy1)/dt)*ndt + oy1; if(newy!=NULL) newy[j]=ty;
117 tyi=oi1 + 0.5*(ty+oy1)*ndt; if(newyi!=NULL) newyi[j]=tyi;
118 if(newyii!=NULL) newyii[j]=tyii= oii1 + 0.5*(tyi+oi1)*ndt;
119 if(verbose>5) printf(" j=%d newx=%g ty=%g tyi=%g\n", j, newx[j], ty, tyi);
120 j++;
121 }
122
123 } // next input sample
124
125 /* Set interpolated data after input data, assuming steady input */
126 while(j<newnr) {
127 ndt=newx[j]-ox2;
128 ty=oy2;
129 tyi=oi2 + oy2*ndt;
130 tyii=oii2 + 0.5*(tyi+oi2)*ndt;
131 if(newy!=NULL) newy[j]=ty;
132 if(newyi!=NULL) newyi[j]=tyi;
133 if(newyii!=NULL) newyii[j]=tyii;
134 if(verbose>5) printf(" j=%d newx=%g ty=%g tyi=%g\n", j, newx[j], ty, tyi);
135 j++;
136 }
137
138 if(verbose>0) printf("out interpolate()\n");
139 return 0;
140}

Referenced by bfIrr2TCM(), bfRadiowater(), dftDivideFrames(), dftDoubleFrames(), dftInterpolate(), dftInterpolateInto(), dftReadinput(), dftTimeIntegral(), and interpolate4pet().

◆ interpolate4pet()

int interpolate4pet ( double * x,
double * y,
int nr,
double * newx1,
double * newx2,
double * newy,
double * newyi,
double * newyii,
int newnr )

Interpolate and integrate TAC to PET frames.

It is assumed, that original data is not from framed data, but that the values represent the actual value at specified time point, which allows the integration to be calculated dot-by-dot.

If NULL is specified for *newy, *newyi and/or *newyii, their values are not calculated.

Original data and new x values must be sorted by ascending x. Subsequent x values can have equal values, enabling the use of step functions. PET frames can overlap, but interpolation may then be slower. Negative x (time) values can be processed. If necessary, the data is extrapolated assuming that 1) y[inf]=y[nr-1] and 2) if x[0]>0 and y[0]>0 and x[0]>x[1]-x[0], then an imaginary line is drawn from (0,0) to (x[0],y[0]).

Returns
Non-zero in case of an error.
See also
petintegrate, finterpolate4pet, interpolate, integrate, petintegral
Parameters
xTimes of original data
yValues of original data
nrNumber of original data values
newx1PET frame start times; frames may overlap
newx2PET frame end times; frames may overlap
newyMean value during PET frame, or NULL if not needed; calculation may be faster if newyi is calculated too
newyiIntegral at frame mid time, or NULL if not needed
newyii2nd integral at frame mid time, or NULL if not needed
newnrNumber of PET frames

Definition at line 510 of file integr.c.

530 {
531 int ret, fi, overlap=0, zeroframe=0;
532 double petx[3], pety[3], petyi[3], petyii[3], fdur;
533 int verbose=0;
534
535 if(verbose>0) printf("in interpolate4pet()\n");
536
537 /* Check for data */
538 if(nr<1 || newnr<1) return 1;
539 /* Check that programmer understood that outp data must've been allocated */
540 if(newy==NULL && newyi==NULL && newyii==NULL) return 2;
541 /* Check that input data is not totally outside the input data */
542 if(newx2[newnr-1]<=x[0] || newx1[0]>=x[nr-1]) return 3;
543
544 /* Check frame lengths, also for overlap and zero length frames */
545 for(fi=0; fi<newnr; fi++) {
546 /* Calculate frame length */
547 fdur=newx2[fi]-newx1[fi];
548 /* If frame length is <0, that is an error */
549 if(fdur<0.0) return 4;
550 if(fdur==0.0) zeroframe++;
551 /* Overlap? */
552 if(fi>0 && newx2[fi-1]>newx1[fi]) overlap++;
553 }
554 if(verbose>1) {
555 printf("overlap := %d\n", overlap);
556 printf("zeroframe := %d\n", zeroframe);
557 }
558
559 /* Interpolate and integrate one frame at a time, if there is:
560 -overlap in frames
561 -frames of zero length
562 -only few interpolated frames
563 -if only integrals are needed
564 -if neither of integrals is needed, then there is no temp memory to
565 do otherwise
566 */
567 if(overlap>0 || zeroframe>0 || newnr<=3 || newy==NULL || (newyi==NULL && newyii==NULL) ) {
568
569 if(verbose>1) printf("frame-by-frame interpolation/integration\n");
570 for(fi=0; fi<newnr; fi++) {
571 /* Set frame start, middle and end times */
572 petx[0]=newx1[fi]; petx[2]=newx2[fi]; petx[1]=0.5*(petx[0]+petx[2]);
573 /* Calculate frame length */
574 fdur=petx[2]-petx[0];
575 /* If frame length is <0, that is an error */
576 if(fdur<0.0) return 4;
577 /* If frame length is 0, then use direct interpolation */
578 if(fdur==0.0) {
579 ret=interpolate(x, y, nr, petx, pety, petyi, petyii, 1);
580 if(ret) return 10+ret;
581 if(newy!=NULL) newy[fi]=petyi[0];
582 if(newyi!=NULL) newyi[fi]=petyi[0];
583 if(newyii!=NULL) newyii[fi]=petyii[0];
584 continue;
585 }
586 /* Calculate integrals at frame start, middle, and end */
587 ret=interpolate(x, y, nr, petx, NULL, petyi, petyii, 3);
588 if(ret) return 20+ret;
589 /* Set output integrals, if required */
590 if(newyi!=NULL) newyi[fi]=petyi[1];
591 if(newyii!=NULL) newyii[fi]=petyii[1];
592 /* Calculate frame mean, if required */
593 if(newy!=NULL) newy[fi]=(petyi[2]-petyi[0])/fdur;
594 } // next frame
595
596 } else {
597
598 if(verbose>1) printf("all-frames-at-once interpolation/integration\n");
599 /* Set temp array */
600 double *tp; if(newyii!=NULL) tp=newyii; else tp=newyi;
601 /* Integrate at frame start times */
602 ret=interpolate(x, y, nr, newx1, NULL, tp, NULL, newnr);
603 if(ret) return 10+ret;
604 /* Integrate at frame end times */
605 ret=interpolate(x, y, nr, newx2, NULL, newy, NULL, newnr);
606 if(ret) return 10+ret;
607 /* Calculate average frame value */
608 for(fi=0; fi<newnr; fi++)
609 newy[fi]=(newy[fi]-tp[fi])/(newx2[fi]-newx1[fi]);
610 /* Calculate integrals */
611 if(newyi!=NULL || newyii!=NULL) {
612 for(fi=0; fi<newnr; fi++) newx1[fi]+=0.5*(newx2[fi]-newx1[fi]);
613 ret=interpolate(x, y, nr, newx1, NULL, newyi, newyii, newnr);
614 if(ret) return 10+ret;
615 for(fi=0; fi<newnr; fi++) newx1[fi]-=(newx2[fi]-newx1[fi]);
616 }
617 }
618
619 if(verbose>0) printf("out interpolate4pet()\n");
620 return 0;
621}
int interpolate(double *x, double *y, int nr, double *newx, double *newy, double *newyi, double *newyii, int newnr)
Linear interpolation and integration.
Definition integr.c:28

Referenced by bfIrr2TCM(), bfRadiowater(), dftAutointerpolate(), dftInterpolate(), dftInterpolateForIMG(), dftInterpolateInto(), img_k1_using_ki(), img_logan(), and img_patlak().

◆ petintegral()

int petintegral ( double * x1,
double * x2,
double * y,
int nr,
double * ie,
double * iie )

Integrate PET TAC data to frame mid times.

Any of output arrays may be set to NULL if that is not needed. Frames must be in ascending time order. Gaps and small overlap are allowed. If x1[0]>0 and x1[0]<=x2[0]-x1[0], then an imaginary line is drawn from (0,0) to (x[0],y[0]).

Returns
Returns 0 if ok.
See also
fpetintegral, interpolate4pet, petintegrate
Parameters
x1frame start times
x2frame end times
yavg value during frame
nrnumber of frames
ieintegrals at frame mid time
iie2nd integrals at frame mid time

Definition at line 771 of file integr.c.

784 {
785 int i;
786 double x, last_x, last_x2, last_y, last_integral, box_integral, half_integral;
787 double gap_integral, integral, integral2, frame_len, xdist, s;
788
789 /* Check for data */
790 if(nr<1 || nr<1) return(1);
791 /* Check that programmer understood that output must've been allocated */
792 if(ie==NULL && iie==NULL) return(2);
793
794 /* Initiate values to zero */
795 last_x=last_x2=last_y=last_integral=0.0;
796 box_integral=integral=integral2=frame_len=0.0;
797
798 for(i=0; i<nr; i++) {
799 frame_len=x2[i]-x1[i]; if(frame_len<0.0) return(5);
800 x=0.5*(x1[i]+x2[i]); xdist=x-last_x;
801 if(last_x>0.0 && xdist<=0.0) return(6);
802 if(x<0) {
803 if(ie!=NULL) ie[i]=integral;
804 if(iie!=NULL) iie[i]=integral2;
805 continue;
806 }
807 s=(y[i]-last_y)/xdist; /* slope */
808 /*If there is a big gap in the beginning it is eliminated */
809 if(i==0)if(x1[0]>x2[0]-x1[0]){last_x2=last_x=x1[0];}
810 /*Integral of a possible gap between frames*/
811 gap_integral=(x1[i]-last_x2)*(last_y+s*((last_x2+x1[i])/2.0-last_x));
812 /*Integral from the beginning of the frame to the middle of the frame */
813 half_integral=(x-x1[i])*(last_y+s*((x1[i]+x)/2.0-last_x));
814 integral=box_integral+gap_integral+half_integral;
815 /* half_integral is not added to box because it is more accurate to
816 increment integrals of full frames */
817 box_integral+=gap_integral+frame_len*y[i];
818 integral2+=xdist*(integral+last_integral)*0.5;
819 if(ie!=NULL) ie[i]=integral;
820 if(iie!=NULL) iie[i]=integral2;
821 last_x=x; last_x2=x2[i];
822 last_y=y[i]; last_integral=integral;
823 }
824
825 return(0);
826}

Referenced by dftInterpolate(), dftInterpolateForIMG(), dftInterpolateInto(), dftReadinput(), img_k1_using_ki(), img_logan(), and img_patlak().

◆ petintegrate()

int petintegrate ( double * x1,
double * x2,
double * y,
int nr,
double * newyi,
double * newyii )

Calculates integrals of PET data at frame end times.

Data does not have to be continuous, but it must be increasing in time. For faster performance in repetitive calls, allocate memory for integral[] even if it is not needed. If x1[0] is >0 AND x1[0] is <=(x2[0]-x1[0]), then the beginning is interpolated from (0, 0) to (x1[0], y1[0]*x1[0]/x) where x is midtime of the first frame.

Returns
Returns 0 if ok.
See also
integrate, fpetintegrate, petintegral, interpolate
Parameters
x1Array of frame start times
x2Array of frame end times
yArray of y values (avg during each frame)
nrNr of frames
newyiOutput: integral values at frame end times, or NULL
newyiiOutput: 2nd integral values at frame end times, or NULL

Definition at line 334 of file integr.c.

347 {
348 int i, allocated=0;
349 double *ti, x, a;
350
351
352 /* Check that data is increasing in time and is not (much) overlapping */
353 if(nr<1 || x1[0]<0) return 1;
354 for(i=0; i<nr; i++) if(x2[i]<x1[i]) return 2;
355 for(i=1; i<nr; i++) if(x1[i]<=x1[i-1]) return 3;
356
357 /* Allocate memory for temp data, if necessary */
358 if(newyi==NULL) {
359 allocated=1;
360 ti=(double*)malloc(nr*sizeof(double)); if(ti==NULL) return 4;
361 } else
362 ti=newyi;
363
364 /* Calculate the integral at the end of first frame */
365 ti[0]=(x2[0]-x1[0])*y[0];
366 /* If frame does not start at 0 time, add the area in the beginning */
367 /* But only if the gap in the beginning is less than the lenght of the
368 first frame */
369 if(x1[0]>0) {
370 if(x1[0]<=x2[0]-x1[0]) {
371 x=(x1[0]+x2[0])/2.0;
372 a=(x1[0]*(y[0]/x)*x1[0])/2.0;
373 ti[0]+=a;
374 }
375 }
376
377 /* Calculate integrals at the ends of following frames */
378 for(i=1; i<nr; i++) {
379 /* Add the area of this frame to the previous integral */
380 a=(x2[i]-x1[i])*y[i]; ti[i]=ti[i-1]+a;
381 /* Check whether frames are contiguous */
382 if(x1[i]==x2[i-1]) continue;
383 /* When not, calculate the area of an imaginary frame */
384 x=(x1[i]+x2[i-1])/2.0;
385 a=(x1[i]-x2[i-1])*
386 (y[i]-(y[i]-y[i-1])*(x2[i]+x1[i]-2.0*x)/(x2[i]+x1[i]-x2[i-1]-x1[i-1]));
387 ti[i]+=a;
388 }
389
390 /* Copy integrals to output if required */
391 if(allocated) for(i=0; i<nr; i++) newyi[i]=ti[i];
392
393 /* Calculate 2nd integrals if required */
394 if(newyii!=NULL) {
395 newyii[0]=x2[0]*ti[0]/2.0;
396 for(i=1; i<nr; i++)
397 newyii[i]=newyii[i-1]+(x2[i]-x2[i-1])*(ti[i-1]+ti[i])/2.0;
398 }
399
400 /* Free memory */
401 if(allocated) free((char*)ti);
402
403 return 0;
404}

Referenced by dftReadReference().

◆ petintegrate2fe()

int petintegrate2fe ( double * x1,
double * x2,
double * y,
int nr,
double * e,
double * ie,
double * iie )

Integrate PET TAC data to frame end times.

Any of output arrays may be set to NULL if that is not needed. Frames must be in ascending time order. Gaps and small overlap are allowed. If x1[0]>0 and x1[0]<=x2[0]-x1[0], then an imaginary line is drawn from (0,0) to (x[0],y[0]).

Returns
Returns 0 if ok.
See also
fpetintegrate2fe
Parameters
x1frame start times
x2frame end times
yavg value during frame
nrnumber of frames
evalues at frame end time
ieintegrals at frame end time
iie2nd integrals at frame end time

Definition at line 905 of file integr.c.

920 {
921 int i;
922 double x, last_x, last_x2, last_y, last_integral;
923 double value, integral, integral2, frame_len, xdist, s;
924
925 /* Check for data */
926 if(nr<1 || nr<1) return(1);
927 /* Check that programmer understood that output must've been allocated */
928 if(e==NULL && ie==NULL && iie==NULL) return(2);
929
930 /* Initiate values to zero */
931 last_x=last_x2=last_y=last_integral=value=integral=integral2=frame_len=s=0.0;
932
933 for(i=0; i<nr; i++) {
934 frame_len=x2[i]-x1[i]; if(frame_len<0.0) return(5);
935 x=0.5*(x1[i]+x2[i]); xdist=x-last_x; if(last_x>0.0 && xdist<=0.0) return(6);
936 if(x<0) {
937 if(e!=NULL) e[i]=value;
938 if(ie!=NULL) ie[i]=integral;
939 if(iie!=NULL) iie[i]=integral2;
940 continue;
941 }
942 s=(y[i]-last_y)/xdist; /* slope between x[i-1] and x[i] */
943 /* If there is a big gap in the beginning, it is eliminated */
944 if(i==0 && x1[0]>x2[0]-x1[0]) {last_x2=last_x=x1[0];}
945 integral+=(x1[i]-last_x2)*(last_y+s*((last_x2+x1[i])/2.0-last_x)); /*gap*/
946 integral+=frame_len*y[i];
947 integral2+=(x2[i]-last_x2)*(integral+last_integral)*0.5;
948 if(e!=NULL && i>0) {
949 value=last_y+s*(last_x2-last_x); /* value at previous frame end */
950 e[i-1]=value;
951 }
952 if(ie!=NULL) ie[i]=integral;
953 if(iie!=NULL) iie[i]=integral2;
954 last_x=x; last_x2=x2[i]; last_y=y[i]; last_integral=integral;
955 }
956 if(e!=NULL) {
957 value=last_y+s*(last_x2-last_x); /* Value for the last frame */
958 e[i-1]=value;
959 }
960
961 return(0);
962}