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 methods used by Meyer et al. (1) and",
30 "van den Hoff et al. (2):",
31 "The plasma/blood curve is shifted -60 - +60 sec, and a two-tissue",
32 "compartment model (with parameters K1, k2, k3, k4 and Vb) in multilinear",
33 "form (3) is fitted to the shifted TAC and each regional tissue TAC,",
34 "with the nonnegative least squares method (4).",
35 "For each region, the delay leading to the lowest sum-of-squares is selected;",
36 "the over-all delay value is calculated as a median of the regional delays.",
37 "Dispersion is not considered in this application.",
39 "Usage: @P [options] inputfile tissuefile fittime [inputfile2 [inputfile3 [inputfile4]]]",
43 " Filename for the time delay corrected TAC made from inputfile.",
45 " Filename for the time delay corrected TAC made from inputfile2.",
47 " Filename for the time delay corrected TAC made from inputfile3.",
49 " Filename for the time delay corrected TAC made from inputfile4.",
50 " -timeunit=<min|sec>",
51 " If datafile(s) do not contain the unit of sample times, it is",
52 " recommended to specify it with this option. By default, units in data",
53 " files are trusted.",
54 " -format=<none|dft|pmod|if>",
55 " Specify the output data format; none means that no title lines are saved.",
57 " Filename for fitted best TACs; by default these are not saved.",
59 " Select whether 1- or 2-tissue (default) compartment model is applied.",
61 " Time delay and other log information is written as comments in",
62 " the corrected TAC file, if format supports comments.",
63 " -matrix=<Filename>",
64 " Filename for saving NNLS matrix in CSV format for testing purposes.",
65 " With this option the tissue file must contain one TAC only.",
68 "As tissue data, the scanner countrate curve is recommended, unless scanned",
69 "volume contains heart or large artery or vein where tracer was injected;",
70 "It may be possible to use also regional TACs, if datafile contains frame",
71 "start and end times. If tissue data contains background, remove it first",
72 "with dftrmbkg. The units of sample times should be specified in datafiles;",
73 "file format is specified in (5).",
75 "Fittime must be given in seconds.",
77 "Estimated tracer appearance times in blood/plasma and tissue curves, and",
78 "their differences (time delays and median time delay) are written in stdout.",
79 "By default, delay corrected blood/plasma file is written with name *.delay.*",
80 "but this can be changed with option -o=<Filename>.",
81 "The same correction can be applied to 1-3 additional files, for",
82 "example plasma metabolite TACs.",
85 "Delay correction for C-11 or F-18 labeled tracer data, using",
86 "metabolite corrected plasma curve as input and count-rate data as tissue",
87 "and correcting also plasma metabolites and total blood for the delay-time:",
88 " fitdelay ut345ap_pure.kbq ut345dy1.img.cr 1800 ut345ap_met.kbq ut345ab.kbq",
91 "Delay correction for [O-15]water data, using regional tissue",
92 "curves as replacement for count-rate data:",
93 " fitdelay ut111ab.kbq ut111dy1.dft 120",
96 " 1. Meyer. Simultaneous correction for tracer arrival delay and dispersion",
97 " in CBF measurements by the H215O autoradiographic method and dynamic PET.",
98 " J Nucl Med 1989; 30:1069-1078.",
99 " 2. van den Hoff et al. Accurate local blood flow measurements with",
100 " dynamic PET: fast determination of input function delay and dispersion",
101 " by multilinear minimization. J Nucl Med 1993; 34:1770-1777.",
102 " 3. Blomqvist G. On the construction of functional maps in positron",
103 " emission tomography. J Cereb Blood Flow Metab 1984; 4:629-632.",
104 " 4. Lawson CL & Hanson RJ. Solving least squares problems.",
105 " Prentice-Hall, 1974.",
106 " 5. https://www.turkupetcentre.net/petanalysis/format_tpc_dft.html",
108 "See also: tactime, imghead, tacmean, tocr, dftrmbkg, tacunit, fit_h2o",
110 "Keywords: TAC, modelling, input, blood, time delay",
129int main(
int argc,
char **argv)
131 int ai, help=0, version=0, verbose=1;
132 int ri, fi, fj, di, ret;
135 int time_unit=TUNIT_UNKNOWN;
136 int orig_tissue_time_unit, orig_input_time_unit;
139 double v, f, ss, coeff[5], minv, maxv, length=-1.0, onep;
140 double *regional_delay;
141 char *cptr, tmp[FILENAME_MAX];
142 char pfile[FILENAME_MAX], tfile[FILENAME_MAX], rfile[FILENAME_MAX];
143 char p2file[FILENAME_MAX], p3file[FILENAME_MAX], p4file[FILENAME_MAX];
144 char r2file[FILENAME_MAX], r3file[FILENAME_MAX], r4file[FILENAME_MAX];
145 char ffile[FILENAME_MAX];
146 char matfile[FILENAME_MAX];
147 DFT pdata, data, ipdata, fdata;
150 int n, m, nnls_n, nnls_m, nnls_index[NNLS_N];
151 double *nnls_a[NNLS_N], *nnls_b, *nnls_zz, nnls_x[NNLS_N], *nnls_mat,
152 nnls_wp[NNLS_N], *dptr, nnls_rnorm;
158 if(argc==1) {
tpcPrintUsage(argv[0], info, stderr);
return(1);}
159 pfile[0]=rfile[0]=tfile[0]=p2file[0]=p3file[0]=r2file[0]=r3file[0]=(char)0;
160 p4file[0]=r4file[0]=ffile[0]=(char)0;
163 orig_tissue_time_unit=orig_input_time_unit=TUNIT_UNKNOWN;
166 for(ai=1; ai<argc; ai++)
if(*argv[ai]==
'-') {
167 cptr=argv[ai]+1;
if(*cptr==
'-') cptr++;
if(cptr==NULL)
continue;
170 if(strcasecmp(cptr,
"L")==0 || strcasecmp(cptr,
"LOG")==0) {
171 make_log=1;
continue;
172 }
else if(strncasecmp(cptr,
"O=", 2)==0) {
173 cptr+=2;
if(strlen(cptr)>0) {strcpy(rfile, cptr);
continue;}
174 }
else if(strncasecmp(cptr,
"O2=", 3)==0) {
175 cptr+=3;
if(strlen(cptr)>0) {strcpy(r2file, cptr);
continue;}
176 }
else if(strncasecmp(cptr,
"O3=", 3)==0) {
177 cptr+=3;
if(strlen(cptr)>0) {strcpy(r3file, cptr);
continue;}
178 }
else if(strncasecmp(cptr,
"O4=", 3)==0) {
179 cptr+=3;
if(strlen(cptr)>0) {strcpy(r4file, cptr);
continue;}
180 }
else if(strncasecmp(cptr,
"MATRIX=", 7)==0) {
181 cptr+=7;
if(strlen(cptr)>0) {strcpy(matfile, cptr);
continue;}
182 }
else if(strncasecmp(cptr,
"TIMEUNIT=", 9)==0) {
184 if(strncasecmp(cptr,
"S", 1)==0) {time_unit=TUNIT_SEC;
continue;}
185 if(strncasecmp(cptr,
"M", 1)==0) {time_unit=TUNIT_MIN;
continue;}
186 }
else if(strncasecmp(cptr,
"FORMAT=", 7)==0) {
188 if(strncasecmp(cptr,
"DFT", 1)==0) {
190 if(strncasecmp(cptr,
"NONE", 2)==0) {
192 if(strncasecmp(cptr,
"PMOD", 2)==0) {
194 if(strcasecmp(cptr,
"IF")==0) {
196 }
else if(strncasecmp(cptr,
"MODEL=", 6)==0) {
197 model=atoi(cptr+6);
if(model==1 || model==2)
continue;
198 }
else if(strncasecmp(cptr,
"FIT=", 4)==0) {
199 cptr+=4; strcpy(ffile, cptr);
if(strlen(ffile)>0)
continue;
201 fprintf(stderr,
"Error: invalid option '%s'.\n", argv[ai]);
206 if(help==2) {
tpcHtmlUsage(argv[0], info,
"");
return(0);}
211 for(; ai<argc; ai++) {
212 if(!pfile[0]) {strcpy(pfile, argv[ai]);
continue;}
213 if(!tfile[0]) {strcpy(tfile, argv[ai]);
continue;}
215 length=
atof_dpi(argv[ai]);
if(length>0.0)
continue;
216 fprintf(stderr,
"Error: invalid fit time as an argument.\n");
return(1);
218 if(!p2file[0]) {strcpy(p2file, argv[ai]);
continue;}
219 if(!p3file[0]) {strcpy(p3file, argv[ai]);
continue;}
220 if(!p4file[0]) {strcpy(p4file, argv[ai]);
continue;}
221 fprintf(stderr,
"Error: invalid argument '%s'.\n", argv[ai]);
227 fprintf(stderr,
"Error: missing tissue file name.\n");
231 fprintf(stderr,
"Error: invalid fit time.\n");
237 printf(
"pfile := %s\n", pfile);
238 printf(
"p2file := %s\n", p2file);
239 printf(
"p3file := %s\n", p3file);
240 printf(
"p4file := %s\n", p4file);
241 printf(
"tfile := %s\n", tfile);
242 printf(
"rfile := %s\n", rfile);
243 printf(
"r2file := %s\n", r2file);
244 printf(
"r3file := %s\n", r3file);
245 printf(
"r4file := %s\n", r4file);
246 printf(
"ffile := %s\n", ffile);
247 if(matfile[0]) printf(
"matfile := %s\n", matfile);
248 printf(
"output_format := %d\n", output_format);
249 printf(
"make_log := %d\n", make_log);
250 printf(
"time_unit := %s\n",
petTunit(time_unit));
251 printf(
"length := %g\n", length);
252 printf(
"model := %d\n", model);
256 if(p2file[0] && access(p2file, 0)==-1) {
257 fprintf(stderr,
"Error: %s not found.\n", p2file);
return(1);}
258 if(p3file[0] && access(p3file, 0)==-1) {
259 fprintf(stderr,
"Error: %s not found.\n", p3file);
return(1);}
260 if(p4file[0] && access(p4file, 0)==-1) {
261 fprintf(stderr,
"Error: %s not found.\n", p4file);
return(1);}
264 if(model==1) NNLS_N=3;
else NNLS_N=5;
272 if(verbose>1) printf(
"reading %s\n", pfile);
274 fprintf(stderr,
"Error in reading '%s': %s\n", pfile,
dfterrmsg);
278 fprintf(stderr,
"Warning: %s contains %d TACs; only first is used.\n",
282 orig_input_time_unit=pdata.
timeunit;
286 if(verbose>1) printf(
"reading %s\n", tfile);
288 fprintf(stderr,
"Error in reading '%s': %s\n", tfile,
dfterrmsg);
291 orig_tissue_time_unit=data.
timeunit;
294 if(verbose>2) printf(
"last_t := %g\n", pdata.
x[pdata.
frameNr-1]);
296 if(verbose>2) printf(
"last_t := %g\n", data.
x[data.
frameNr-1]);
300 if(data.
voiNr>1 && matfile[0]) {
302 fprintf(stderr,
"Warning: option -matrix disabled because more than one tissue TAC found.\n");
308 if(verbose>1) printf(
"checking time units\n");
311 if(time_unit!=TUNIT_UNKNOWN) {
323 fprintf(stderr,
"Warning: assuming input time_unit := %s\n",
petTunit(pdata.
timeunit));
328 if(time_unit!=TUNIT_UNKNOWN) {
340 fprintf(stderr,
"Warning: assuming tissue time_unit := %s\n",
petTunit(data.
timeunit));
344 orig_input_time_unit=pdata.
timeunit;
345 orig_tissue_time_unit=data.
timeunit;
347 printf(
"orig_input_time_unit := %s\n",
petTunit(orig_input_time_unit));
348 printf(
"orig_tissue_time_unit := %s\n",
petTunit(orig_tissue_time_unit));
353 fprintf(stdout,
"Note: tissue sample times are converted to seconds for fitting.\n");
358 fprintf(stdout,
"Note: input sample times are converted to seconds for fitting.\n");
362 if(length<data.
x[data.
frameNr-1]/60.0 || length<pdata.
x[pdata.
frameNr-1]/60.0)
363 fprintf(stderr,
"Warning: fit time (%g s) is short, compared with data.\n", length);
367 if(verbose>1) printf(
"checking if the ascending part of plasma TAC has been missed\n");
368 for(fi=1, n=0, maxv=pdata.
voi[0].
y[0]; fi<pdata.
frameNr; fi++) {
369 v=pdata.
voi[0].
y[fi];
370 if(fi>1 && fi<pdata.
frameNr-2) {
372 v+=pdata.
voi[0].
y[fi-1]+pdata.
voi[0].
y[fi+1];
373 v+=pdata.
voi[0].
y[fi-2]+pdata.
voi[0].
y[fi+2];
375 }
else if(fi>0 && fi<pdata.
frameNr-1) {
377 v+=pdata.
voi[0].
y[fi-1]+pdata.
voi[0].
y[fi+1];
380 if(v>maxv) {maxv=v; n=fi;}
382 if(verbose>2) printf(
"maxv := %g\nmax_index := %d\nmax_time := %g\n", maxv, n, pdata.
x[n]);
384 fprintf(stderr,
"Error: missed the ascending phase of plasma/blood data.\n");
387 if(pdata.
x[n]>length) {
389 "Error: missed the plasma/blood peak; check the time unit.\n");
393 if(verbose>1) printf(
"checking if the ascending part of tissue TAC has been missed\n");
394 for(fi=1, n=0, maxv=data.
voi[0].
y[0]; fi<data.
frameNr; fi++)
395 if(data.
voi[0].
y[fi]>maxv) {maxv=data.
voi[0].
y[fi]; n=fi;}
396 if(verbose>2) printf(
"maxv := %g\nmax_index := %d\n", maxv, n);
398 fprintf(stderr,
"Error: missed the ascending phase of tissue data.\n");
402 if(n<2) fprintf(stderr,
"Warning: check the first samples in %s\n", tfile);
411 for(fi=0; fi<data.
frameNr; fi++) {
413 else {
if(data.
x[fi]>=length)
break;}
416 fprintf(stderr,
"Error: too few time frames included in fit.\n");
425 if(verbose>3) printf(
"fit_frameNr := %d\nfit_length := %g\n", data.
frameNr, length);
429 if(verbose>2) printf(
"last_t := %g\n", pdata.
x[pdata.
frameNr-1]);
431 if(verbose>2) printf(
"last_t := %g\n", data.
x[data.
frameNr-1]);
435 for(fi=0; fi<pdata.
frameNr; fi++)
if(pdata.
x[fi]>length)
break;
436 if(verbose>1) printf(
"nr of input samples in fit range := %d\n", fi);
437 if(fi<5 || (fi<10 && fi<data.
frameNr)) {
438 fprintf(stderr,
"Error: too few plasma/blood samples included in fit.\n");
444 if(verbose>1) printf(
"integrating tissue TACs\n");
445 for(ri=0; ri<data.
voiNr; ri++) {
453 fprintf(stderr,
"Error in integration of tissue data (%d).\n", ret);
462 fprintf(stderr,
"Error in integration of plasma data (%d).\n", ret);
465 for(fi=0, onep=0.0; fi<pdata.
frameNr-1; fi++)
466 if(pdata.
voi[0].
y2[fi]>=0.001*pdata.
voi[0].
y2[pdata.
frameNr-1]) {onep=pdata.
x[fi];
break;}
467 if(verbose>1) fprintf(stdout,
"Plasma curve starts to rise at about %g s.\n", onep);
473 if(verbose>1) printf(
"integrating input TACs\n");
476 fprintf(stderr,
"Error: out of memory.\n");
481 for(fi=0; fi<data.
frameNr; fi++) {
482 ipdata.
x[fi]=data.
x[fi]; ipdata.
x1[fi]=data.
x1[fi]; ipdata.
x2[fi]=data.
x2[fi];}
487 ipdata.
x1, ipdata.
x2,
495 fprintf(stderr,
"Error (%d) in interpolation of plasma data.\n", ret);
499 if(verbose>3) printf(
"%s ip-integrals: %g %g %g\n", ipdata.
voi[ri].
voiname,
503 for(ri=1; ri<=MAX_DELAY; ri++) {
504 for(fi=0; fi<pdata.
frameNr; fi++) {
505 pdata.
x[fi]-=1.0; pdata.
x1[fi]-=1.0; pdata.
x2[fi]-=1.0;}
515 fprintf(stderr,
"Error (%d) in interpolation.\n", ret);
519 if(verbose>7) printf(
"%s ip-integrals: %g %g %g\n", ipdata.
voi[ri].
voiname,
523 for(fi=0; fi<pdata.
frameNr; fi++) {
524 pdata.
x[fi]+=(double)MAX_DELAY;
525 pdata.
x1[fi]+=(double)MAX_DELAY; pdata.
x2[fi]+=(double)MAX_DELAY;
528 for(ri=MAX_DELAY+1; ri<=2*MAX_DELAY; ri++) {
529 for(fi=0; fi<pdata.
frameNr; fi++) {
530 pdata.
x[fi]+=1.0; pdata.
x1[fi]+=1.0; pdata.
x2[fi]+=1.0;}
536 for(fi=0; fi<ipdata.
frameNr; fi++)
537 ipdata.
voi[ri].
y[fi]=ipdata.
voi[ri].
y2[fi]=ipdata.
voi[ri].
y3[fi]=0.0;
545 fprintf(stderr,
"Error in interpolation (%d).\n", ret);
548 sprintf(ipdata.
voi[ri].
voiname,
"d%d", ri-MAX_DELAY);
549 if(verbose>7) printf(
"%s ip-integrals: %g %g %g\n", ipdata.
voi[ri].
voiname,
553 for(fi=0; fi<pdata.
frameNr; fi++) {
554 pdata.
x[fi]-=(double)MAX_DELAY;
555 pdata.
x1[fi]-=(double)MAX_DELAY; pdata.
x2[fi]-=(double)MAX_DELAY;
563 if(verbose>1) printf(
"fitting\n");
565 nnls_n=NNLS_N; nnls_m=data.
frameNr;
566 nnls_mat=(
double*)malloc(((nnls_n+2)*nnls_m)*
sizeof(
double));
568 fprintf(stderr,
"Error: cannot allocate memory for NNLS.\n");
572 for(n=0, dptr=nnls_mat; n<nnls_n; n++) {nnls_a[n]=dptr; dptr+=nnls_m;}
573 nnls_b=dptr; dptr+=nnls_m; nnls_zz=dptr;
575 regional_delay=(
double*)calloc(data.
voiNr,
sizeof(
double));
576 if(regional_delay==NULL) {
577 fprintf(stderr,
"Error: cannot allocate memory for regional delays.\n");
583 ret=
dftdup(&data, &fdata);
585 fprintf(stderr,
"Error: cannot allocate memory for fitted TAC(s).\n");
587 free(nnls_mat); free(regional_delay);
594 for(m=0; m<nnls_m; m++) {
595 if(data.
w[m]<=1.0e-20) data.
w[m]=0.0;
else data.
w[m]=sqrt(data.
w[m]);}
597 if(data.
voiNr>1) printf(
"Regional time delays:\n");
598 for(ri=0; ri<data.
voiNr; ri++) {
604 mfp=fopen(matfile,
"w");
606 fprintf(stderr,
"Error: cannot write file '%s'.\n", matfile);
608 free(nnls_mat); free(regional_delay);
614 min=-1; minv=9.9e+99;
615 for(di=0; di<=2*MAX_DELAY; di++) {
619 for(m=0; m<nnls_m; m++) {
620 nnls_a[0][m]=ipdata.
voi[di].
y[m];
621 nnls_a[1][m]=ipdata.
voi[di].
y2[m];
622 nnls_a[2][m]=-data.
voi[ri].
y2[m];
623 nnls_b[m]=data.
voi[ri].
y[m];
626 for(m=0; m<nnls_m; m++) {
627 nnls_a[0][m]=ipdata.
voi[di].
y[m];
628 nnls_a[1][m]=ipdata.
voi[di].
y2[m];
629 nnls_a[2][m]=ipdata.
voi[di].
y3[m];
630 nnls_a[3][m]=-data.
voi[ri].
y2[m];
631 nnls_a[4][m]=-data.
voi[ri].
y3[m];
632 nnls_b[m]=data.
voi[ri].
y[m];
637 if(data.
isweight)
for(m=0; m<nnls_m; m++) {
638 nnls_b[m]*=data.
w[m];
639 for(n=0; n<nnls_n; n++) nnls_a[n][m]*=data.
w[m];
645 if(di<=MAX_DELAY) dt=-di;
else dt=di-MAX_DELAY;
646 fprintf(mfp,
"%d\nB", dt);
647 for(
int n=0; n<nnls_n; n++) fprintf(mfp,
",A%d", n+1);
649 for(
int m=0; m<nnls_m; m++) {
650 fprintf(mfp,
"%g", nnls_b[m]);
651 for(
int n=0; n<nnls_n; n++) fprintf(mfp,
",%g", nnls_a[n][m]);
657 ret=
nnls(nnls_a, nnls_m, nnls_n, nnls_b, nnls_x, &nnls_rnorm, nnls_wp, nnls_zz, nnls_index);
660 }
else if(ret==1) { }
662 for(n=0; n<nnls_n; n++) coeff[n]=nnls_x[n];
665 for(m=0; m<nnls_m; m++) {
666 nnls_a[0][m]=ipdata.
voi[di].
y[m];
667 nnls_a[1][m]=ipdata.
voi[di].
y2[m];
668 nnls_a[2][m]=-data.
voi[ri].
y2[m];
669 nnls_b[m]=data.
voi[ri].
y[m];
672 for(m=0; m<nnls_m; m++) {
673 nnls_a[0][m]=ipdata.
voi[di].
y[m];
674 nnls_a[1][m]=ipdata.
voi[di].
y2[m];
675 nnls_a[2][m]=ipdata.
voi[di].
y3[m];
676 nnls_a[3][m]=-data.
voi[ri].
y2[m];
677 nnls_a[4][m]=-data.
voi[ri].
y3[m];
678 nnls_b[m]=data.
voi[ri].
y[m];
682 for(m=0, ss=0.0; m<nnls_m; m++) {
683 for(n=0, f=0.0; n<nnls_n; n++) f+=nnls_x[n]*nnls_a[n][m];
684 fdata.
voi[ri].
y2[m]=f;
687 if(data.
isweight)
for(m=0; m<nnls_m; m++) {
688 nnls_b[m]*=data.
w[m];
689 for(n=0; n<nnls_n; n++) nnls_a[n][m]*=data.
w[m];
691 for(m=0, ss=0.0; m<nnls_m; m++) {
692 for(n=0, f=0.0; n<nnls_n; n++) f+=nnls_x[n]*nnls_a[n][m];
693 v=f; f-=nnls_b[m]; ss+=f*f;
698 printf(
"Fit %2d -> SS=%12.3e Vb=%g K1+Vb*k2=%g k2=%g\n", di, ss, coeff[0], coeff[1], coeff[2]);
700 printf(
"Fit %2d -> SS=%12.3e Vb=%g K1+Vb*(k2+k3+k4)=%g\n", di, ss, coeff[0], coeff[1]);
701 printf(
" K1*(k3+k4)=%g k2+k3+k4=%g k2k4=%g\n", coeff[2], coeff[3], coeff[4]);
708 if(ffile[0])
for(m=0; m<nnls_m; m++) fdata.
voi[ri].
y[m]=fdata.
voi[ri].
y2[m];
713 if(matfile[0]) fclose(mfp);
716 if(verbose>5) printf(
" min TAC (%s) := %d\n", data.
voi[ri].
name, min);
717 if(min<=MAX_DELAY) min=-min;
else min-=MAX_DELAY;
718 regional_delay[ri]=(double)min;
719 if(verbose>=0 && data.
voiNr>1)
720 printf(
" time_delay for %s := %g s\n", data.
voi[ri].
name, regional_delay[ri]);
731 if(verbose>1) printf(
"calculating median\n");
734 free(regional_delay);
736 printf(
"Estimated tracer appearance time in plasma := %.1f s\n", onep);
737 printf(
"Estimated tracer appearance time in tissue := %.1f s\n", onep+(
double)v);
738 printf(
"Median time delay := %g s\n", v);
748 fprintf(stderr,
"Warning: possible error in determined tracer appearance time.\n");
749 fprintf(stderr,
" Please check the delay corrected input against tissue data.\n");
759 if(verbose>1) printf(
"correcting input TACs\n");
760 for(fi=0; fi<pdata.
frameNr; fi++) {
761 pdata.
x[fi]+=delayT; pdata.
x1[fi]+=delayT; pdata.
x2[fi]+=delayT;}
763 fi=0;
while(fi<pdata.
frameNr) {
764 if(pdata.
x[fi]>=0.0)
break;
765 for(fj=fi+1; fj<pdata.
frameNr; fj++) {
766 for(ri=0; ri<pdata.
voiNr; ri++) pdata.
voi[ri].
y[fj-1]=pdata.
voi[ri].
y[fj];
767 pdata.
x[fj-1]=pdata.
x[fj]; pdata.
x1[fj-1]=pdata.
x1[fj];
768 pdata.
x2[fj-1]=pdata.
x2[fj];
773 fprintf(stderr,
"Error: no positive sample times left.\n");
785 cptr=strrchr(pfile,
'.');
if(cptr!=NULL) n=strlen(cptr);
else n=0;
786 strcpy(rfile, pfile); rfile[strlen(pfile)-n]=(char)0;
787 strcat(rfile,
".delay");
if(cptr!=NULL) strcat(rfile, cptr);
788 if(verbose>2) printf(
"rfile := %s\n", rfile);
789 if(verbose>=0) printf(
" %s -> %s\n", pfile, rfile);
794 if(pdata.
timeunit!=orig_input_time_unit) {
795 if(verbose>2) printf(
"converting input %s to %s\n",
797 if(verbose>3) printf(
"last_t := %g\n", pdata.
x[pdata.
frameNr-1]);
799 if(verbose>3) printf(
"last_t := %g\n", pdata.
x[pdata.
frameNr-1]);
805 sprintf(tmp,
"# delay_fit_time := %g s\n", length);
807 sprintf(tmp,
"# time_delay := %g s\n", delayT);
809 sprintf(tmp,
"# tissue_compartment_nr := %d\n", model);
813 if(verbose>1) printf(
"writing %s\n", rfile);
815 fprintf(stderr,
"Error in writing '%s': %s\n", rfile,
dfterrmsg);
829 sprintf(fdata.
comments,
"# Curves fitted from %s\n", tfile);
832 if(data.
timeunit!=orig_tissue_time_unit) {
838 sprintf(tmp,
"# delay_fit_time := %g s\n", length);
840 sprintf(tmp,
"# time_delay := %g s\n", delayT);
842 sprintf(tmp,
"# tissue_compartment_nr := %d\n", model);
845 if(verbose>1) printf(
"writing %s\n", ffile);
847 fprintf(stderr,
"Error in writing '%s': %s\n", ffile,
dfterrmsg);
860 if(verbose>1) printf(
"reading %s\n", p2file);
862 fprintf(stderr,
"Error in reading '%s': %s\n", p2file,
dfterrmsg);
868 pdata.
timeunit=orig_input_time_unit;
871 f=delayT;
if(pdata.
timeunit==TUNIT_MIN) f/=60;
872 for(fi=0; fi<pdata.
frameNr; fi++) {
873 pdata.
x[fi]+=f; pdata.
x1[fi]+=f; pdata.
x2[fi]+=f;}
875 fi=0;
while(fi<pdata.
frameNr) {
876 if(pdata.
x[fi]>=0.0)
break;
877 for(fj=fi+1; fj<pdata.
frameNr; fj++) {
878 for(ri=0; ri<pdata.
voiNr; ri++)
879 pdata.
voi[ri].
y[fj-1]=pdata.
voi[ri].
y[fj];
880 pdata.
x[fj-1]=pdata.
x[fj]; pdata.
x1[fj-1]=pdata.
x1[fj];
881 pdata.
x2[fj-1]=pdata.
x2[fj];
886 fprintf(stderr,
"Error: no positive sample times left.\n");
891 strcpy(r2file, p2file); cptr=strrchr(p2file,
'.');
892 if(cptr!=NULL) r2file[strlen(p2file)-strlen(cptr)]=(char)0;
893 strcat(r2file,
".delay");
if(cptr!=NULL) strcat(r2file, cptr);
901 sprintf(tmp,
"# delay_fit_time := %g s\n", length);
903 sprintf(tmp,
"# time_delay := %g s\n", delayT);
905 sprintf(tmp,
"# tissue_compartment_nr := %d\n", model);
908 if(verbose>=0) printf(
" %s -> %s\n", p2file, r2file);
912 "Error (%d) in writing '%s': %s\n", ret, r2file,
dfterrmsg);
919 if(verbose>1) printf(
"reading %s\n", p3file);
922 fprintf(stderr,
"Error in reading '%s': %s\n", p3file,
dfterrmsg);
928 pdata.
timeunit=orig_input_time_unit;
931 f=delayT;
if(pdata.
timeunit==TUNIT_MIN) f/=60;
932 for(fi=0; fi<pdata.
frameNr; fi++) {
933 pdata.
x[fi]+=f; pdata.
x1[fi]+=f; pdata.
x2[fi]+=f;}
935 fi=0;
while(fi<pdata.
frameNr) {
936 if(pdata.
x[fi]>=0.0)
break;
937 for(fj=fi+1; fj<pdata.
frameNr; fj++) {
938 for(ri=0; ri<pdata.
voiNr; ri++)
939 pdata.
voi[ri].
y[fj-1]=pdata.
voi[ri].
y[fj];
940 pdata.
x[fj-1]=pdata.
x[fj]; pdata.
x1[fj-1]=pdata.
x1[fj];
941 pdata.
x2[fj-1]=pdata.
x2[fj];
946 fprintf(stderr,
"Error: no positive sample times left.\n");
951 strcpy(r3file, p3file); cptr=strrchr(p3file,
'.');
952 if(cptr!=NULL) r3file[strlen(p3file)-strlen(cptr)]=(char)0;
953 strcat(r3file,
".delay");
if(cptr!=NULL) strcat(r3file, cptr);
961 sprintf(tmp,
"# delay_fit_time := %g s\n", length);
963 sprintf(tmp,
"# time_delay := %g s\n", delayT);
965 sprintf(tmp,
"# tissue_compartment_nr := %d\n", model);
968 if(verbose>=0) printf(
" %s -> %s\n", p3file, r3file);
971 fprintf(stderr,
"Error (%d) in writing '%s': %s\n", ret, r3file,
dfterrmsg);
978 if(verbose>1) printf(
"reading %s\n", p4file);
981 fprintf(stderr,
"Error in reading '%s': %s\n", p4file,
dfterrmsg);
987 pdata.
timeunit=orig_input_time_unit;
990 f=delayT;
if(pdata.
timeunit==TUNIT_MIN) f/=60;
991 for(fi=0; fi<pdata.
frameNr; fi++) {
992 pdata.
x[fi]+=f; pdata.
x1[fi]+=f; pdata.
x2[fi]+=f;}
994 fi=0;
while(fi<pdata.
frameNr) {
995 if(pdata.
x[fi]>=0.0)
break;
996 for(fj=fi+1; fj<pdata.
frameNr; fj++) {
997 for(ri=0; ri<pdata.
voiNr; ri++) pdata.
voi[ri].
y[fj-1]=pdata.
voi[ri].
y[fj];
998 pdata.
x[fj-1]=pdata.
x[fj]; pdata.
x1[fj-1]=pdata.
x1[fj];
999 pdata.
x2[fj-1]=pdata.
x2[fj];
1004 fprintf(stderr,
"Error: no positive sample times left.\n");
1009 strcpy(r4file, p4file); cptr=strrchr(p4file,
'.');
1010 if(cptr!=NULL) r4file[strlen(p3file)-strlen(cptr)]=(char)0;
1011 strcat(r4file,
".delay");
if(cptr!=NULL) strcat(r4file, cptr);
1019 sprintf(tmp,
"# delay_fit_time := %g s\n", length);
1021 sprintf(tmp,
"# time_delay := %g s\n", delayT);
1023 sprintf(tmp,
"# tissue_compartment_nr := %d\n", model);
1026 if(verbose>=0) printf(
" %s -> %s\n", p4file, r4file);
1029 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]