9#include "tpcclibConfig.h"
25static char *info[] = {
26 "For estimation and correction of the delay-time (difference in appearance",
27 "times of radioactivity) between PET tissue and input (blood or plasma) TACs.",
29 "Program is based on the previously published methods (1,2,3):",
30 "The plasma/blood curve is shifted -60 - +60 sec, and a two-tissue",
31 "compartment model (with parameters K1, k2, k3, k4 and Vb) in multilinear",
32 "form (3,4) is fitted to the shifted TAC and each regional tissue TAC,",
33 "with the non-negative least squares method (5).",
34 "For each region, the delay leading to the lowest sum-of-squares is selected;",
35 "the over-all delay value is calculated as a median of the regional delays.",
36 "Dispersion is not considered in this application.",
38 "Usage: @P [options] inputfile tissuefile fittime [inputfile2 [inputfile3 [inputfile4]]]",
42 " Filename for the time delay corrected TAC made from inputfile.",
44 " Filename for the time delay corrected TAC made from inputfile2.",
46 " Filename for the time delay corrected TAC made from inputfile3.",
48 " Filename for the time delay corrected TAC made from inputfile4.",
49 " -timeunit=<min|sec>",
50 " If datafile(s) do not contain the unit of sample times, it is",
51 " recommended to specify it with this option. By default, units in data",
52 " files are trusted.",
53 " -format=<none|dft|pmod|if>",
54 " Specify the output data format; none means that no title lines are saved.",
56 " Filename for fitted best TACs; by default these are not saved.",
58 " Select whether 1- or 2-tissue (default) compartment model is applied.",
60 " Time delay and other log information is written as comments in",
61 " the corrected TAC file, if format supports comments.",
62 " -matrix=<Filename>",
63 " Filename for saving NNLS matrix in CSV format for testing purposes.",
64 " With this option the tissue file must contain one TAC only.",
67 "As tissue data, the scanner count-rate curve is recommended, unless scanned",
68 "volume contains heart or large artery or vein where tracer was injected;",
69 "It may be possible to use also regional TACs, if datafile contains frame",
70 "start and end times. If tissue data contains background, remove it first",
71 "with dftrmbkg. The units of sample times should be specified in datafiles;",
72 "file format is specified in (5).",
74 "Fit time must be given in seconds.",
76 "Estimated tracer appearance times in blood/plasma and tissue curves, and",
77 "their differences (time delays and median time delay) are written in stdout.",
78 "By default, delay corrected blood/plasma file is written with name *.delay.*",
79 "but this can be changed with option -o=<Filename>.",
80 "The same correction can be applied to 1-3 additional files, for",
81 "example plasma metabolite TACs.",
84 "Delay correction for C-11 or F-18 labelled tracer data, using",
85 "metabolite corrected plasma curve as input and count-rate data as tissue",
86 "and correcting also plasma metabolites and total blood for the delay-time:",
87 " fitdelay ut345ap_pure.kbq ut345dy1.img.cr 1800 ut345ap_met.kbq ut345ab.kbq",
90 "Delay correction for [O-15]water data, using regional tissue",
91 "curves as replacement for count-rate data:",
92 " fitdelay ut111ab.kbq ut111dy1.dft 120",
95 " 1. Iida H et al. Evaluation of regional differences of tracer appearance",
96 " time in cerebral tissues using [15O]water and dynamic positron emission",
97 " tomography. J Cereb Blood Flow Metab. 1988; 8:285-288.",
98 " 2. Meyer. Simultaneous correction for tracer arrival delay and dispersion",
99 " in CBF measurements by the H215O autoradiographic method and dynamic PET.",
100 " J Nucl Med 1989; 30:1069-1078.",
101 " 3. van den Hoff et al. Accurate local blood flow measurements with",
102 " dynamic PET: fast determination of input function delay and dispersion",
103 " by multilinear minimization. J Nucl Med 1993; 34:1770-1777.",
104 " 4. Blomqvist G. On the construction of functional maps in positron",
105 " emission tomography. J Cereb Blood Flow Metab 1984; 4:629-632.",
106 " 5. Lawson CL & Hanson RJ. Solving least squares problems.",
107 " Prentice-Hall, 1974.",
108 " 5. https://www.turkupetcentre.net/petanalysis/format_tpc_dft.html",
110 "See also: tactime, imghead, tacmean, tocr, dftrmbkg, tacunit, fit_h2o, fitdt",
112 "Keywords: TAC, modelling, input, blood, time delay",
131int main(
int argc,
char **argv)
133 int ai, help=0, version=0, verbose=1;
134 int ri, fi, fj, di, ret;
137 int time_unit=TUNIT_UNKNOWN;
138 int orig_tissue_time_unit, orig_input_time_unit;
141 double v, f, ss, coeff[5], minv, maxv, length=-1.0, onep;
142 double *regional_delay;
143 char *cptr, tmp[FILENAME_MAX];
144 char pfile[FILENAME_MAX], tfile[FILENAME_MAX], rfile[FILENAME_MAX];
145 char p2file[FILENAME_MAX], p3file[FILENAME_MAX], p4file[FILENAME_MAX];
146 char r2file[FILENAME_MAX], r3file[FILENAME_MAX], r4file[FILENAME_MAX];
147 char ffile[FILENAME_MAX];
148 char matfile[FILENAME_MAX];
149 DFT pdata, data, ipdata, fdata;
152 int n, m, nnls_n, nnls_m, nnls_index[NNLS_N];
153 double *nnls_a[NNLS_N], *nnls_b, *nnls_zz, nnls_x[NNLS_N], *nnls_mat,
154 nnls_wp[NNLS_N], *dptr, nnls_rnorm;
160 if(argc==1) {
tpcPrintUsage(argv[0], info, stderr);
return(1);}
161 pfile[0]=rfile[0]=tfile[0]=p2file[0]=p3file[0]=r2file[0]=r3file[0]=(char)0;
162 p4file[0]=r4file[0]=ffile[0]=(char)0;
165 orig_tissue_time_unit=orig_input_time_unit=TUNIT_UNKNOWN;
168 for(ai=1; ai<argc; ai++)
if(*argv[ai]==
'-') {
169 cptr=argv[ai]+1;
if(*cptr==
'-') cptr++;
if(cptr==NULL)
continue;
172 if(strcasecmp(cptr,
"L")==0 || strcasecmp(cptr,
"LOG")==0) {
173 make_log=1;
continue;
174 }
else if(strncasecmp(cptr,
"O=", 2)==0) {
175 cptr+=2;
if(strlen(cptr)>0) {strcpy(rfile, cptr);
continue;}
176 }
else if(strncasecmp(cptr,
"O2=", 3)==0) {
177 cptr+=3;
if(strlen(cptr)>0) {strcpy(r2file, cptr);
continue;}
178 }
else if(strncasecmp(cptr,
"O3=", 3)==0) {
179 cptr+=3;
if(strlen(cptr)>0) {strcpy(r3file, cptr);
continue;}
180 }
else if(strncasecmp(cptr,
"O4=", 3)==0) {
181 cptr+=3;
if(strlen(cptr)>0) {strcpy(r4file, cptr);
continue;}
182 }
else if(strncasecmp(cptr,
"MATRIX=", 7)==0) {
183 cptr+=7;
if(strlen(cptr)>0) {strcpy(matfile, cptr);
continue;}
184 }
else if(strncasecmp(cptr,
"TIMEUNIT=", 9)==0) {
186 if(strncasecmp(cptr,
"S", 1)==0) {time_unit=TUNIT_SEC;
continue;}
187 if(strncasecmp(cptr,
"M", 1)==0) {time_unit=TUNIT_MIN;
continue;}
188 }
else if(strncasecmp(cptr,
"FORMAT=", 7)==0) {
190 if(strncasecmp(cptr,
"DFT", 1)==0) {
192 if(strncasecmp(cptr,
"NONE", 2)==0) {
194 if(strncasecmp(cptr,
"PMOD", 2)==0) {
196 if(strcasecmp(cptr,
"IF")==0) {
198 }
else if(strncasecmp(cptr,
"MODEL=", 6)==0) {
199 model=atoi(cptr+6);
if(model==1 || model==2)
continue;
200 }
else if(strncasecmp(cptr,
"FIT=", 4)==0) {
201 cptr+=4; strcpy(ffile, cptr);
if(strlen(ffile)>0)
continue;
203 fprintf(stderr,
"Error: invalid option '%s'.\n", argv[ai]);
208 if(help==2) {
tpcHtmlUsage(argv[0], info,
"");
return(0);}
213 for(; ai<argc; ai++) {
214 if(!pfile[0]) {strcpy(pfile, argv[ai]);
continue;}
215 if(!tfile[0]) {strcpy(tfile, argv[ai]);
continue;}
217 length=
atof_dpi(argv[ai]);
if(length>0.0)
continue;
218 fprintf(stderr,
"Error: invalid fit time as an argument.\n");
return(1);
220 if(!p2file[0]) {strcpy(p2file, argv[ai]);
continue;}
221 if(!p3file[0]) {strcpy(p3file, argv[ai]);
continue;}
222 if(!p4file[0]) {strcpy(p4file, argv[ai]);
continue;}
223 fprintf(stderr,
"Error: invalid argument '%s'.\n", argv[ai]);
229 fprintf(stderr,
"Error: missing tissue file name.\n");
233 fprintf(stderr,
"Error: invalid fit time.\n");
239 printf(
"pfile := %s\n", pfile);
240 printf(
"p2file := %s\n", p2file);
241 printf(
"p3file := %s\n", p3file);
242 printf(
"p4file := %s\n", p4file);
243 printf(
"tfile := %s\n", tfile);
244 printf(
"rfile := %s\n", rfile);
245 printf(
"r2file := %s\n", r2file);
246 printf(
"r3file := %s\n", r3file);
247 printf(
"r4file := %s\n", r4file);
248 printf(
"ffile := %s\n", ffile);
249 if(matfile[0]) printf(
"matfile := %s\n", matfile);
250 printf(
"output_format := %d\n", output_format);
251 printf(
"make_log := %d\n", make_log);
252 printf(
"time_unit := %s\n",
petTunit(time_unit));
253 printf(
"length := %g\n", length);
254 printf(
"model := %d\n", model);
258 if(p2file[0] && access(p2file, 0)==-1) {
259 fprintf(stderr,
"Error: %s not found.\n", p2file);
return(1);}
260 if(p3file[0] && access(p3file, 0)==-1) {
261 fprintf(stderr,
"Error: %s not found.\n", p3file);
return(1);}
262 if(p4file[0] && access(p4file, 0)==-1) {
263 fprintf(stderr,
"Error: %s not found.\n", p4file);
return(1);}
266 if(model==1) NNLS_N=3;
else NNLS_N=5;
274 if(verbose>1) printf(
"reading %s\n", pfile);
276 fprintf(stderr,
"Error in reading '%s': %s\n", pfile,
dfterrmsg);
280 fprintf(stderr,
"Warning: %s contains %d TACs; only first is used.\n",
284 orig_input_time_unit=pdata.
timeunit;
288 if(verbose>1) printf(
"reading %s\n", tfile);
290 fprintf(stderr,
"Error in reading '%s': %s\n", tfile,
dfterrmsg);
293 orig_tissue_time_unit=data.
timeunit;
296 if(verbose>2) printf(
"last_t := %g\n", pdata.
x[pdata.
frameNr-1]);
298 if(verbose>2) printf(
"last_t := %g\n", data.
x[data.
frameNr-1]);
302 if(data.
voiNr>1 && matfile[0]) {
304 fprintf(stderr,
"Warning: option -matrix disabled because more than one tissue TAC found.\n");
310 if(verbose>1) printf(
"checking time units\n");
313 if(time_unit!=TUNIT_UNKNOWN) {
325 fprintf(stderr,
"Warning: assuming input time_unit := %s\n",
petTunit(pdata.
timeunit));
330 if(time_unit!=TUNIT_UNKNOWN) {
342 fprintf(stderr,
"Warning: assuming tissue time_unit := %s\n",
petTunit(data.
timeunit));
346 orig_input_time_unit=pdata.
timeunit;
347 orig_tissue_time_unit=data.
timeunit;
349 printf(
"orig_input_time_unit := %s\n",
petTunit(orig_input_time_unit));
350 printf(
"orig_tissue_time_unit := %s\n",
petTunit(orig_tissue_time_unit));
355 fprintf(stdout,
"Note: tissue sample times are converted to seconds for fitting.\n");
360 fprintf(stdout,
"Note: input sample times are converted to seconds for fitting.\n");
364 if(length<data.
x[data.
frameNr-1]/60.0 || length<pdata.
x[pdata.
frameNr-1]/60.0)
365 fprintf(stderr,
"Warning: fit time (%g s) is short, compared with data.\n", length);
369 if(verbose>1) printf(
"checking if the ascending part of plasma TAC has been missed\n");
370 for(fi=1, n=0, maxv=pdata.
voi[0].
y[0]; fi<pdata.
frameNr; fi++) {
371 v=pdata.
voi[0].
y[fi];
372 if(fi>1 && fi<pdata.
frameNr-2) {
374 v+=pdata.
voi[0].
y[fi-1]+pdata.
voi[0].
y[fi+1];
375 v+=pdata.
voi[0].
y[fi-2]+pdata.
voi[0].
y[fi+2];
377 }
else if(fi>0 && fi<pdata.
frameNr-1) {
379 v+=pdata.
voi[0].
y[fi-1]+pdata.
voi[0].
y[fi+1];
382 if(v>maxv) {maxv=v; n=fi;}
384 if(verbose>2) printf(
"maxv := %g\nmax_index := %d\nmax_time := %g\n", maxv, n, pdata.
x[n]);
386 fprintf(stderr,
"Error: missed the ascending phase of plasma/blood data.\n");
389 if(pdata.
x[n]>length) {
391 "Error: missed the plasma/blood peak; check the time unit.\n");
395 if(verbose>1) printf(
"checking if the ascending part of tissue TAC has been missed\n");
396 for(fi=1, n=0, maxv=data.
voi[0].
y[0]; fi<data.
frameNr; fi++)
397 if(data.
voi[0].
y[fi]>maxv) {maxv=data.
voi[0].
y[fi]; n=fi;}
398 if(verbose>2) printf(
"maxv := %g\nmax_index := %d\n", maxv, n);
400 fprintf(stderr,
"Error: missed the ascending phase of tissue data.\n");
404 if(n<2) fprintf(stderr,
"Warning: check the first samples in %s\n", tfile);
413 for(fi=0; fi<data.
frameNr; fi++) {
415 else {
if(data.
x[fi]>=length)
break;}
418 fprintf(stderr,
"Error: too few time frames included in fit.\n");
427 if(verbose>3) printf(
"fit_frameNr := %d\nfit_length := %g\n", data.
frameNr, length);
431 if(verbose>2) printf(
"last_t := %g\n", pdata.
x[pdata.
frameNr-1]);
433 if(verbose>2) printf(
"last_t := %g\n", data.
x[data.
frameNr-1]);
437 for(fi=0; fi<pdata.
frameNr; fi++)
if(pdata.
x[fi]>length)
break;
438 if(verbose>1) printf(
"nr of input samples in fit range := %d\n", fi);
439 if(fi<5 || (fi<10 && fi<data.
frameNr)) {
440 fprintf(stderr,
"Error: too few plasma/blood samples included in fit.\n");
446 if(verbose>1) printf(
"integrating tissue TACs\n");
447 for(ri=0; ri<data.
voiNr; ri++) {
455 fprintf(stderr,
"Error in integration of tissue data (%d).\n", ret);
464 fprintf(stderr,
"Error in integration of plasma data (%d).\n", ret);
467 for(fi=0, onep=0.0; fi<pdata.
frameNr-1; fi++)
468 if(pdata.
voi[0].
y2[fi]>=0.001*pdata.
voi[0].
y2[pdata.
frameNr-1]) {onep=pdata.
x[fi];
break;}
469 if(verbose>1) fprintf(stdout,
"Plasma curve starts to rise at about %g s.\n", onep);
475 if(verbose>1) printf(
"integrating input TACs\n");
478 fprintf(stderr,
"Error: out of memory.\n");
483 for(fi=0; fi<data.
frameNr; fi++) {
484 ipdata.
x[fi]=data.
x[fi]; ipdata.
x1[fi]=data.
x1[fi]; ipdata.
x2[fi]=data.
x2[fi];}
489 ipdata.
x1, ipdata.
x2,
497 fprintf(stderr,
"Error (%d) in interpolation of plasma data.\n", ret);
501 if(verbose>3) printf(
"%s ip-integrals: %g %g %g\n", ipdata.
voi[ri].
voiname,
505 for(ri=1; ri<=MAX_DELAY; ri++) {
506 for(fi=0; fi<pdata.
frameNr; fi++) {
507 pdata.
x[fi]-=1.0; pdata.
x1[fi]-=1.0; pdata.
x2[fi]-=1.0;}
517 fprintf(stderr,
"Error (%d) in interpolation.\n", ret);
521 if(verbose>7) printf(
"%s ip-integrals: %g %g %g\n", ipdata.
voi[ri].
voiname,
525 for(fi=0; fi<pdata.
frameNr; fi++) {
526 pdata.
x[fi]+=(double)MAX_DELAY;
527 pdata.
x1[fi]+=(double)MAX_DELAY; pdata.
x2[fi]+=(double)MAX_DELAY;
530 for(ri=MAX_DELAY+1; ri<=2*MAX_DELAY; ri++) {
531 for(fi=0; fi<pdata.
frameNr; fi++) {
532 pdata.
x[fi]+=1.0; pdata.
x1[fi]+=1.0; pdata.
x2[fi]+=1.0;}
538 for(fi=0; fi<ipdata.
frameNr; fi++)
539 ipdata.
voi[ri].
y[fi]=ipdata.
voi[ri].
y2[fi]=ipdata.
voi[ri].
y3[fi]=0.0;
547 fprintf(stderr,
"Error in interpolation (%d).\n", ret);
550 sprintf(ipdata.
voi[ri].
voiname,
"d%d", ri-MAX_DELAY);
551 if(verbose>7) printf(
"%s ip-integrals: %g %g %g\n", ipdata.
voi[ri].
voiname,
555 for(fi=0; fi<pdata.
frameNr; fi++) {
556 pdata.
x[fi]-=(double)MAX_DELAY;
557 pdata.
x1[fi]-=(double)MAX_DELAY; pdata.
x2[fi]-=(double)MAX_DELAY;
565 if(verbose>1) printf(
"fitting\n");
567 nnls_n=NNLS_N; nnls_m=data.
frameNr;
568 nnls_mat=(
double*)malloc(((nnls_n+2)*nnls_m)*
sizeof(
double));
570 fprintf(stderr,
"Error: cannot allocate memory for NNLS.\n");
574 for(n=0, dptr=nnls_mat; n<nnls_n; n++) {nnls_a[n]=dptr; dptr+=nnls_m;}
575 nnls_b=dptr; dptr+=nnls_m; nnls_zz=dptr;
577 regional_delay=(
double*)calloc(data.
voiNr,
sizeof(
double));
578 if(regional_delay==NULL) {
579 fprintf(stderr,
"Error: cannot allocate memory for regional delays.\n");
585 ret=
dftdup(&data, &fdata);
587 fprintf(stderr,
"Error: cannot allocate memory for fitted TAC(s).\n");
589 free(nnls_mat); free(regional_delay);
596 for(m=0; m<nnls_m; m++) {
597 if(data.
w[m]<=1.0e-20) data.
w[m]=0.0;
else data.
w[m]=sqrt(data.
w[m]);}
599 if(data.
voiNr>1) printf(
"Regional time delays:\n");
600 for(ri=0; ri<data.
voiNr; ri++) {
606 mfp=fopen(matfile,
"w");
608 fprintf(stderr,
"Error: cannot write file '%s'.\n", matfile);
610 free(nnls_mat); free(regional_delay);
616 min=-1; minv=9.9e+99;
617 for(di=0; di<=2*MAX_DELAY; di++) {
621 for(m=0; m<nnls_m; m++) {
622 nnls_a[0][m]=ipdata.
voi[di].
y[m];
623 nnls_a[1][m]=ipdata.
voi[di].
y2[m];
624 nnls_a[2][m]=-data.
voi[ri].
y2[m];
625 nnls_b[m]=data.
voi[ri].
y[m];
628 for(m=0; m<nnls_m; m++) {
629 nnls_a[0][m]=ipdata.
voi[di].
y[m];
630 nnls_a[1][m]=ipdata.
voi[di].
y2[m];
631 nnls_a[2][m]=ipdata.
voi[di].
y3[m];
632 nnls_a[3][m]=-data.
voi[ri].
y2[m];
633 nnls_a[4][m]=-data.
voi[ri].
y3[m];
634 nnls_b[m]=data.
voi[ri].
y[m];
639 if(data.
isweight)
for(m=0; m<nnls_m; m++) {
640 nnls_b[m]*=data.
w[m];
641 for(n=0; n<nnls_n; n++) nnls_a[n][m]*=data.
w[m];
647 if(di<=MAX_DELAY) dt=-di;
else dt=di-MAX_DELAY;
648 fprintf(mfp,
"%d\nB", dt);
649 for(
int n=0; n<nnls_n; n++) fprintf(mfp,
",A%d", n+1);
651 for(
int m=0; m<nnls_m; m++) {
652 fprintf(mfp,
"%g", nnls_b[m]);
653 for(
int n=0; n<nnls_n; n++) fprintf(mfp,
",%g", nnls_a[n][m]);
659 ret=
nnls(nnls_a, nnls_m, nnls_n, nnls_b, nnls_x, &nnls_rnorm, nnls_wp, nnls_zz, nnls_index);
662 }
else if(ret==1) { }
664 for(n=0; n<nnls_n; n++) coeff[n]=nnls_x[n];
667 for(m=0; m<nnls_m; m++) {
668 nnls_a[0][m]=ipdata.
voi[di].
y[m];
669 nnls_a[1][m]=ipdata.
voi[di].
y2[m];
670 nnls_a[2][m]=-data.
voi[ri].
y2[m];
671 nnls_b[m]=data.
voi[ri].
y[m];
674 for(m=0; m<nnls_m; m++) {
675 nnls_a[0][m]=ipdata.
voi[di].
y[m];
676 nnls_a[1][m]=ipdata.
voi[di].
y2[m];
677 nnls_a[2][m]=ipdata.
voi[di].
y3[m];
678 nnls_a[3][m]=-data.
voi[ri].
y2[m];
679 nnls_a[4][m]=-data.
voi[ri].
y3[m];
680 nnls_b[m]=data.
voi[ri].
y[m];
684 for(m=0, ss=0.0; m<nnls_m; m++) {
685 for(n=0, f=0.0; n<nnls_n; n++) f+=nnls_x[n]*nnls_a[n][m];
686 fdata.
voi[ri].
y2[m]=f;
689 if(data.
isweight)
for(m=0; m<nnls_m; m++) {
690 nnls_b[m]*=data.
w[m];
691 for(n=0; n<nnls_n; n++) nnls_a[n][m]*=data.
w[m];
693 for(m=0, ss=0.0; m<nnls_m; m++) {
694 for(n=0, f=0.0; n<nnls_n; n++) f+=nnls_x[n]*nnls_a[n][m];
695 v=f; f-=nnls_b[m]; ss+=f*f;
700 printf(
"Fit %2d -> SS=%12.3e Vb=%g K1+Vb*k2=%g k2=%g\n", di, ss, coeff[0], coeff[1], coeff[2]);
702 printf(
"Fit %2d -> SS=%12.3e Vb=%g K1+Vb*(k2+k3+k4)=%g\n", di, ss, coeff[0], coeff[1]);
703 printf(
" K1*(k3+k4)=%g k2+k3+k4=%g k2k4=%g\n", coeff[2], coeff[3], coeff[4]);
710 if(ffile[0])
for(m=0; m<nnls_m; m++) fdata.
voi[ri].
y[m]=fdata.
voi[ri].
y2[m];
715 if(matfile[0]) fclose(mfp);
718 if(verbose>5) printf(
" min TAC (%s) := %d\n", data.
voi[ri].
name, min);
719 if(min<=MAX_DELAY) min=-min;
else min-=MAX_DELAY;
720 regional_delay[ri]=(double)min;
721 if(verbose>=0 && data.
voiNr>1)
722 printf(
" time_delay for %s := %g s\n", data.
voi[ri].
name, regional_delay[ri]);
733 if(verbose>1) printf(
"calculating median\n");
736 free(regional_delay);
738 printf(
"Estimated tracer appearance time in plasma := %.1f s\n", onep);
739 printf(
"Estimated tracer appearance time in tissue := %.1f s\n", onep+(
double)v);
740 printf(
"Median time delay := %g s\n", v);
750 fprintf(stderr,
"Warning: possible error in determined tracer appearance time.\n");
751 fprintf(stderr,
" Please check the delay corrected input against tissue data.\n");
761 if(verbose>1) printf(
"correcting input TACs\n");
762 for(fi=0; fi<pdata.
frameNr; fi++) {
763 pdata.
x[fi]+=delayT; pdata.
x1[fi]+=delayT; pdata.
x2[fi]+=delayT;}
765 fi=0;
while(fi<pdata.
frameNr) {
766 if(pdata.
x[fi]>=0.0)
break;
767 for(fj=fi+1; fj<pdata.
frameNr; fj++) {
768 for(ri=0; ri<pdata.
voiNr; ri++) pdata.
voi[ri].
y[fj-1]=pdata.
voi[ri].
y[fj];
769 pdata.
x[fj-1]=pdata.
x[fj]; pdata.
x1[fj-1]=pdata.
x1[fj];
770 pdata.
x2[fj-1]=pdata.
x2[fj];
775 fprintf(stderr,
"Error: no positive sample times left.\n");
787 cptr=strrchr(pfile,
'.');
if(cptr!=NULL) n=strlen(cptr);
else n=0;
788 strcpy(rfile, pfile); rfile[strlen(pfile)-n]=(char)0;
789 strcat(rfile,
".delay");
if(cptr!=NULL) strcat(rfile, cptr);
790 if(verbose>2) printf(
"rfile := %s\n", rfile);
791 if(verbose>=0) printf(
" %s -> %s\n", pfile, rfile);
796 if(pdata.
timeunit!=orig_input_time_unit) {
797 if(verbose>2) printf(
"converting input %s to %s\n",
799 if(verbose>3) printf(
"last_t := %g\n", pdata.
x[pdata.
frameNr-1]);
801 if(verbose>3) printf(
"last_t := %g\n", pdata.
x[pdata.
frameNr-1]);
807 sprintf(tmp,
"# delay_fit_time := %g s\n", length);
809 sprintf(tmp,
"# time_delay := %g s\n", delayT);
811 sprintf(tmp,
"# tissue_compartment_nr := %d\n", model);
815 if(verbose>1) printf(
"writing %s\n", rfile);
817 fprintf(stderr,
"Error in writing '%s': %s\n", rfile,
dfterrmsg);
831 sprintf(fdata.
comments,
"# Curves fitted from %s\n", tfile);
834 if(data.
timeunit!=orig_tissue_time_unit) {
840 sprintf(tmp,
"# delay_fit_time := %g s\n", length);
842 sprintf(tmp,
"# time_delay := %g s\n", delayT);
844 sprintf(tmp,
"# tissue_compartment_nr := %d\n", model);
847 if(verbose>1) printf(
"writing %s\n", ffile);
849 fprintf(stderr,
"Error in writing '%s': %s\n", ffile,
dfterrmsg);
862 if(verbose>1) printf(
"reading %s\n", p2file);
864 fprintf(stderr,
"Error in reading '%s': %s\n", p2file,
dfterrmsg);
870 pdata.
timeunit=orig_input_time_unit;
873 f=delayT;
if(pdata.
timeunit==TUNIT_MIN) f/=60;
874 for(fi=0; fi<pdata.
frameNr; fi++) {
875 pdata.
x[fi]+=f; pdata.
x1[fi]+=f; pdata.
x2[fi]+=f;}
877 fi=0;
while(fi<pdata.
frameNr) {
878 if(pdata.
x[fi]>=0.0)
break;
879 for(fj=fi+1; fj<pdata.
frameNr; fj++) {
880 for(ri=0; ri<pdata.
voiNr; ri++)
881 pdata.
voi[ri].
y[fj-1]=pdata.
voi[ri].
y[fj];
882 pdata.
x[fj-1]=pdata.
x[fj]; pdata.
x1[fj-1]=pdata.
x1[fj];
883 pdata.
x2[fj-1]=pdata.
x2[fj];
888 fprintf(stderr,
"Error: no positive sample times left.\n");
893 strcpy(r2file, p2file); cptr=strrchr(p2file,
'.');
894 if(cptr!=NULL) r2file[strlen(p2file)-strlen(cptr)]=(char)0;
895 strcat(r2file,
".delay");
if(cptr!=NULL) strcat(r2file, cptr);
903 sprintf(tmp,
"# delay_fit_time := %g s\n", length);
905 sprintf(tmp,
"# time_delay := %g s\n", delayT);
907 sprintf(tmp,
"# tissue_compartment_nr := %d\n", model);
910 if(verbose>=0) printf(
" %s -> %s\n", p2file, r2file);
914 "Error (%d) in writing '%s': %s\n", ret, r2file,
dfterrmsg);
921 if(verbose>1) printf(
"reading %s\n", p3file);
924 fprintf(stderr,
"Error in reading '%s': %s\n", p3file,
dfterrmsg);
930 pdata.
timeunit=orig_input_time_unit;
933 f=delayT;
if(pdata.
timeunit==TUNIT_MIN) f/=60;
934 for(fi=0; fi<pdata.
frameNr; fi++) {
935 pdata.
x[fi]+=f; pdata.
x1[fi]+=f; pdata.
x2[fi]+=f;}
937 fi=0;
while(fi<pdata.
frameNr) {
938 if(pdata.
x[fi]>=0.0)
break;
939 for(fj=fi+1; fj<pdata.
frameNr; fj++) {
940 for(ri=0; ri<pdata.
voiNr; ri++)
941 pdata.
voi[ri].
y[fj-1]=pdata.
voi[ri].
y[fj];
942 pdata.
x[fj-1]=pdata.
x[fj]; pdata.
x1[fj-1]=pdata.
x1[fj];
943 pdata.
x2[fj-1]=pdata.
x2[fj];
948 fprintf(stderr,
"Error: no positive sample times left.\n");
953 strcpy(r3file, p3file); cptr=strrchr(p3file,
'.');
954 if(cptr!=NULL) r3file[strlen(p3file)-strlen(cptr)]=(char)0;
955 strcat(r3file,
".delay");
if(cptr!=NULL) strcat(r3file, cptr);
963 sprintf(tmp,
"# delay_fit_time := %g s\n", length);
965 sprintf(tmp,
"# time_delay := %g s\n", delayT);
967 sprintf(tmp,
"# tissue_compartment_nr := %d\n", model);
970 if(verbose>=0) printf(
" %s -> %s\n", p3file, r3file);
973 fprintf(stderr,
"Error (%d) in writing '%s': %s\n", ret, r3file,
dfterrmsg);
980 if(verbose>1) printf(
"reading %s\n", p4file);
983 fprintf(stderr,
"Error in reading '%s': %s\n", p4file,
dfterrmsg);
989 pdata.
timeunit=orig_input_time_unit;
992 f=delayT;
if(pdata.
timeunit==TUNIT_MIN) f/=60;
993 for(fi=0; fi<pdata.
frameNr; fi++) {
994 pdata.
x[fi]+=f; pdata.
x1[fi]+=f; pdata.
x2[fi]+=f;}
996 fi=0;
while(fi<pdata.
frameNr) {
997 if(pdata.
x[fi]>=0.0)
break;
998 for(fj=fi+1; fj<pdata.
frameNr; fj++) {
999 for(ri=0; ri<pdata.
voiNr; ri++) pdata.
voi[ri].
y[fj-1]=pdata.
voi[ri].
y[fj];
1000 pdata.
x[fj-1]=pdata.
x[fj]; pdata.
x1[fj-1]=pdata.
x1[fj];
1001 pdata.
x2[fj-1]=pdata.
x2[fj];
1006 fprintf(stderr,
"Error: no positive sample times left.\n");
1011 strcpy(r4file, p4file); cptr=strrchr(p4file,
'.');
1012 if(cptr!=NULL) r4file[strlen(p3file)-strlen(cptr)]=(char)0;
1013 strcat(r4file,
".delay");
if(cptr!=NULL) strcat(r4file, cptr);
1021 sprintf(tmp,
"# delay_fit_time := %g s\n", length);
1023 sprintf(tmp,
"# time_delay := %g s\n", delayT);
1025 sprintf(tmp,
"# tissue_compartment_nr := %d\n", model);
1028 if(verbose>=0) printf(
" %s -> %s\n", p4file, r4file);
1031 fprintf(stderr,
"Error (%d) in writing '%s': %s\n", ret, r4file,
dfterrmsg);
double atof_dpi(char *str)
int dftdup(DFT *dft1, DFT *dft2)
void dftSetComments(DFT *dft)
int dftSetmem(DFT *data, int frameNr, int voiNr)
int dftCopymainhdr(DFT *dft1, DFT *dft2)
int dftRead(char *filename, DFT *data)
int dftWrite(DFT *data, char *filename)
int dftTimeunitConversion(DFT *dft, int tunit)
int petintegral(double *x1, double *x2, double *y, int nr, double *ie, double *iie)
Integrate PET TAC data to frame mid times.
int integrate(double *x, double *y, int nr, double *yi)
int interpolate(double *x, double *y, int nr, double *newx, double *newy, double *newyi, double *newyii, int newnr)
Linear interpolation and integration.
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.
Header file for libtpccurveio.
#define DFT_FORMAT_STANDARD
#define DFT_TIME_STARTEND
#define DFT_FORMAT_UNKNOWN
Header file for libtpcmisc.
int tpcProcessStdOptions(const char *s, int *print_usage, int *print_version, int *verbose_level)
char * petTunit(int tunit)
int tpcHtmlUsage(const char *program, char *text[], const char *path)
void tpcPrintBuild(const char *program, FILE *fp)
void tpcPrintUsage(const char *program, char *text[], FILE *fp)
Header file for libtpcmodel.
int nnls(double **a, int m, int n, double *b, double *x, double *rnorm, double *w, double *zz, int *index)
double dmedian(double *data, int n)
char comments[_DFT_COMMENT_LEN+1]
char voiname[MAX_REGIONSUBNAME_LEN+1]
char name[MAX_REGIONNAME_LEN+1]