10#include "tpcclibConfig.h"
30static char *info[] = {
31 "Computation of parametric images from dynamic PET image in ECAT, NIfTI,",
32 "or Analyze format applying irreversible two-tissue compartmental model with",
33 "arterial plasma input, using the basis function method (1).",
35 "Dynamic PET image and plasma and blood time-activity curves (PTAC and BTAC)",
36 "must be corrected for decay to the tracer administration time.",
37 "Enter 'none' in place of the name of btacfile, if you want to assume Vb=0.",
39 "Usage: @P [Options] ptacfile btacfile imgfile k3file",
43 " Pixels with AUC less than (threshold/100 x PTAC AUC) are set to zero;",
45 " -end=<Fit end time (min)>",
46 " Use data from 0 to end time; by default, model is fitted to all frames.",
48 " Parametric K1/(k2+k3) image is saved.",
50 " Parametric K1 image is saved.",
52 " Parametric k2 image is saved.",
54 " Parametric Ki image is saved.",
56 " Parametric Vb image is saved.",
57 " -min=<Min k2+k3> and -max=<Max k2+k3>",
58 " Enter the basis functions minimum and maximum k2+k3 (=alpha) in units 1/min;",
59 " defaults are 0.15 and 0.60, respectively.",
67 " Set number of basis functions; default is 200, minimum 50.",
69 " Parametric k2+k3 (=alpha) image is saved.",
71 " Parametric theta1 image is saved.",
73 " Parametric theta2 image is saved.",
75 " Basis function curves are written in specified TAC file.",
77 " Save image where the pixels that had k2+k3 at min or max value are",
78 " set to values 1 and 2, respectively, and other pixels are set to value 0.",
80 " By default, all weights are set to 1.0 (no weighting, option -w1); option -wf",
81 " sets weights based on frame lengths, and option -wfa based on both frame lengths",
82 " and mean activity during each frame.",
85 "Example 1. Calculation of K1, Ki, k3, and Vb images:",
86 " @P -k1=s2345k1.v -ki=s2345ki.v -Vb=s2345vb.v s2345ap.kbq s2345ab.kbq s2345dy.v s2345k3.v",
87 "Example 2. Calculation with assumption Vb=0:",
88 " @P -k1=s2345k1.v -ki=s2345ki.v s2345ap.kbq none s2345dy.v s2345k3.v",
90 "The units of pixel values in the parametric images are 1/min for k3,",
91 "ml/(min*ml) for K1 and Ki, and ml/ml for DV and Vb.",
94 "1. Hong YT et al. J Cereb Blood Flow Metab. 2011;31:648-657.",
96 "See also: imglhk3, imgki, imgcbv, imgunit, fitdelay",
98 "Keywords: image, modelling, irreversible uptake, Ki, basis function method",
114enum {METHOD_UNKNOWN, METHOD_QR, METHOD_BVLS};
115static char *method_str[] = {
"unknown",
"QR",
"BVLS", 0};
122int main(
int argc,
char **argv)
124 int ai, help=0, version=0, verbose=1;
125 char ptacfile[FILENAME_MAX], btacfile[FILENAME_MAX], petfile[FILENAME_MAX];
126 char k1file[FILENAME_MAX], k2file[FILENAME_MAX], vbfile[FILENAME_MAX];
127 char dvfile[FILENAME_MAX], kifile[FILENAME_MAX], k3file[FILENAME_MAX];
128 char errfile[FILENAME_MAX], bfsfile[FILENAME_MAX], k2k3file[FILENAME_MAX];
129 char t1file[FILENAME_MAX], t2file[FILENAME_MAX];
130 float calcThreshold=0.01;
134 double alphamin=0.15, alphamax=0.60;
135 double theta1max=1.0, theta2max=1.0, Vbmax=1.0;
137 int method=METHOD_QR;
144 if(argc==1) {
tpcPrintUsage(argv[0], info, stderr);
return(1);}
145 ptacfile[0]=btacfile[0]=petfile[0]=k3file[0]=(char)0;
146 vbfile[0]=k1file[0]=k2file[0]=kifile[0]=dvfile[0]=(char)0;
147 errfile[0]=bfsfile[0]=k2k3file[0]=t1file[0]=t2file[0]=(char)0;
149 for(ai=1; ai<argc; ai++)
if(*argv[ai]==
'-') {
151 char *cptr=argv[ai]+1;
if(*cptr==
'-') cptr++;
if(cptr==NULL)
continue;
152 if(strncasecmp(cptr,
"K1=", 3)==0) {
153 strlcpy(k1file, cptr+3, FILENAME_MAX);
continue;
154 }
else if(strncasecmp(cptr,
"K2=", 3)==0) {
155 strlcpy(k2file, cptr+3, FILENAME_MAX);
continue;
156 }
else if(strncasecmp(cptr,
"KI=", 3)==0) {
157 strlcpy(kifile, cptr+3, FILENAME_MAX);
continue;
158 }
else if(strncasecmp(cptr,
"VB=", 3)==0) {
159 strlcpy(vbfile, cptr+3, FILENAME_MAX);
continue;
160 }
else if(strncasecmp(cptr,
"DV=", 3)==0) {
161 strlcpy(dvfile, cptr+3, FILENAME_MAX);
continue;
162 }
else if(strncasecmp(cptr,
"K2K3=", 5)==0) {
163 strlcpy(k2k3file, cptr+5, FILENAME_MAX);
continue;
164 }
else if(strncasecmp(cptr,
"T1=", 3)==0) {
165 strlcpy(t1file, cptr+3, FILENAME_MAX);
continue;
166 }
else if(strncasecmp(cptr,
"T2=", 3)==0) {
167 strlcpy(t2file, cptr+3, FILENAME_MAX);
continue;
168 }
else if(strncasecmp(cptr,
"THR=", 4)==0) {
170 if(!ret && v>=0.0 && v<=200.0) {calcThreshold=(float)(0.01*v);
continue;}
171 }
else if(strncasecmp(cptr,
"END=", 4)==0) {
172 ret=
atof_with_check(cptr+4, &fittime);
if(!ret && fittime>0.0)
continue;
173 }
else if(strcasecmp(cptr,
"WFA")==0) {
175 }
else if(strcasecmp(cptr,
"WF")==0) {
177 }
else if(strcasecmp(cptr,
"W1")==0) {
179 }
else if(strncasecmp(cptr,
"min=", 4)==0) {
181 }
else if(strncasecmp(cptr,
"max=", 4)==0) {
183 }
else if(strncasecmp(cptr,
"theta1max=", 10)==0) {
184 if(
atof_with_check(cptr+10, &theta1max)==0 && theta1max>=0.0)
continue;
185 }
else if(strncasecmp(cptr,
"theta2max=", 10)==0) {
186 if(
atof_with_check(cptr+10, &theta2max)==0 && theta2max>=0.0)
continue;
187 }
else if(strncasecmp(cptr,
"Vbmax=", 6)==0) {
188 if(
atof_with_check(cptr+6, &Vbmax)==0 && Vbmax>=0.0 && Vbmax<=1.0)
continue;
189 }
else if(strncasecmp(cptr,
"NR=", 3)==0) {
190 bfNr=atoi(cptr+3);
if(bfNr>5E+04) bfNr=5E+04;
191 if(bfNr>=50)
continue;
192 }
else if(strncasecmp(cptr,
"BF=", 3)==0) {
193 strlcpy(bfsfile, cptr+3, FILENAME_MAX);
if(strlen(bfsfile)>0)
continue;
194 }
else if(strncasecmp(cptr,
"ERR=", 4)==0) {
195 strlcpy(errfile, cptr+4, FILENAME_MAX);
if(strlen(errfile)>0)
continue;
196 }
else if(strcasecmp(cptr,
"QR")==0) {
197 method=METHOD_QR;
continue;
198 }
else if(strcasecmp(cptr,
"BVLS")==0) {
199 method=METHOD_BVLS;
continue;
201 fprintf(stderr,
"Error: invalid option '%s'.\n", argv[ai]);
206 if(help==2) {
tpcHtmlUsage(argv[0], info,
"");
return(0);}
211 if(ai<argc)
strlcpy(ptacfile, argv[ai++], FILENAME_MAX);
212 if(ai<argc)
strlcpy(btacfile, argv[ai++], FILENAME_MAX);
213 if(ai<argc)
strlcpy(petfile, argv[ai++], FILENAME_MAX);
214 if(ai<argc)
strlcpy(k3file, argv[ai++], FILENAME_MAX);
216 fprintf(stderr,
"Error: invalid argument '%s'.\n", argv[ai]);
221 fprintf(stderr,
"Error: missing command-line argument; use option --help\n");
224 if(strcasecmp(btacfile,
"NONE")==0 || strcasecmp(btacfile,
"'NONE'")==0 || Vbmax<=0.0) {
225 fitVb=0; Vbmax=0.0; btacfile[0]=(char)0;
227 fprintf(stderr,
"Error: Vb cannot be calculated without BTAC file.\n");
234 printf(
"ptacfile := %s\n", ptacfile);
235 if(btacfile[0]) printf(
"btacfile := %s\n", btacfile);
236 printf(
"petfile := %s\n", petfile);
237 printf(
"k3file := %s\n", k3file);
238 if(vbfile[0]) printf(
"vbfile := %s\n", vbfile);
239 if(k1file[0]) printf(
"k1file := %s\n", k1file);
240 if(k2file[0]) printf(
"k2file := %s\n", k2file);
241 if(k2k3file[0]) printf(
"k2k3file := %s\n", k2k3file);
242 if(kifile[0]) printf(
"kifile := %s\n", kifile);
243 if(dvfile[0]) printf(
"dvfile := %s\n", dvfile);
244 if(errfile[0]) printf(
"errfile := %s\n", errfile);
245 if(t1file[0]) printf(
"t1file := %s\n", t1file);
246 if(t2file[0]) printf(
"t2file := %s\n", t2file);
247 if(bfsfile[0]) printf(
"bfsfile := %s\n", bfsfile);
248 printf(
"fitVb := %d\n", fitVb);
249 printf(
"method := %s\n", method_str[method]);
250 printf(
"calcThreshold :=%g\n", calcThreshold);
251 printf(
"weights := %d\n", weights);
252 if(fittime>0.0) printf(
"required_fittime := %g min\n", fittime);
253 printf(
"bfNr := %d\n", bfNr);
254 if(alphamin>0.0) printf(
"alpha_min := %g\n", alphamin);
255 if(alphamax>0.0) printf(
"alpha_max := %g\n", alphamax);
256 printf(
"theta1_max := %g\n", theta1max);
257 printf(
"theta2_max := %g\n", theta2max);
258 printf(
"Vb_max := %g\n", Vbmax);
264 if(alphamin>=alphamax) {
265 fprintf(stderr,
"Error: invalid range for k2+k3 (%g - %g).\n", alphamin, alphamax);
273 if(verbose>0) {printf(
"reading data files\n"); fflush(stdout);}
280 petfile, NULL, ptacfile, btacfile, NULL, &fittime, &dataNr, &img,
281 &inp, &tac, 1, stdout, verbose-2, errmsg);
283 fprintf(stderr,
"Error: %s.\n", errmsg);
284 if(verbose>1) printf(
" ret := %d\n", ret);
285 fflush(stderr); fflush(stdout);
290 if(verbose>0) fprintf(stderr,
"Warning: missing pixel values.\n");
293 for(
int fi=0; fi<tac.
frameNr; fi++) tac.
voi[0].
y2[fi]/=60.0;
294 for(
int fi=0; fi<tac.
frameNr; fi++) tac.
voi[0].
y3[fi]/=3600.0;
299 printf(
"fittimeFinal := %g min\n", fittime);
300 printf(
"dataNr := %d\n", dataNr);
304 fprintf(stderr,
"Error: too few time frames for fitting.\n");
310 if(verbose>1) fprintf(stdout,
"allocating working memory for pixel TACs\n");
313 fprintf(stderr,
"Error: cannot allocate memory.\n");
314 if(verbose>0) printf(
"ret := %d\n", ret);
317 strcpy(tac.
voi[0].
name,
"plasma");
318 strcpy(tac.
voi[1].
name,
"blood");
319 strcpy(tac.
voi[2].
name,
"tissue");
324 double threshold=calcThreshold*tac.
voi[0].
y2[dataNr-1];
325 if(verbose>1) printf(
"threshold_AUC := %g\n", threshold);
329 fprintf(stderr,
"Error: cannot calculate weights.\n");
332 for(
int i=0; i<dataNr; i++) tac.
w[i]=img.
weight[i];
338 if(verbose>1) fprintf(stdout,
"calculating basis functions\n");
341 ret=
bfIrr2TCM(&inp, &tac, &bf, bfNr, alphamin, alphamax, errmsg, verbose-2);
344 fprintf(stderr,
"Error: cannot calculate basis functions (%d).\n", ret);
354 int *bf_opt_nr=(
int*)malloc(bfNr*
sizeof(
int));
355 for(
int bi=0; bi<bf.
voiNr; bi++) bf_opt_nr[bi]=0.0;
363 if(verbose>1) fprintf(stdout,
"allocating memory for parametric image data\n");
385 fprintf(stderr,
"Error: cannot allocate memory for result image.\n");
396 dvimg.
end[0]=erimg.
end[0]=k2k3img.
end[0]=t1img.
end[0]=t2img.
end[0]=60.*fittime;
399 dvimg.
unit=vbimg.
unit=CUNIT_ML_PER_ML;
401 erimg.
unit=CUNIT_UNITLESS;
412 int thresholded_nr=0;
415 if(method==METHOD_QR) {
421 M=dataNr; N=3;
if(fitVb==0) N--;
422 double **mem, **A, *B, X[N], *tau, *residual, RNORM, *chain;
423 double *qrweight, **wws, *ws, *wwschain;
424 if(verbose>1) fprintf(stdout,
"allocating memory for QR\n");
425 chain=(
double*)malloc((M+1)*N*bf.
voiNr *
sizeof(
double));
426 mem=(
double**)malloc(bf.
voiNr *
sizeof(
double*));
427 A=(
double**)malloc(M *
sizeof(
double*));
428 B=(
double*)malloc(M*
sizeof(
double));
429 residual=(
double*)malloc(M*
sizeof(
double));
430 qrweight=(
double*)malloc(M*
sizeof(
double));
431 wwschain=(
double*)malloc((M*N+2*M)*
sizeof(
double));
432 wws=(
double**)malloc(M *
sizeof(
double*));
433 if(chain==NULL || B==NULL || A==NULL || residual==NULL || qrweight==NULL ||
434 wwschain==NULL || wws==NULL)
436 fprintf(stderr,
"Error: out of memory.\n");
443 for(
int bi=0; bi<bf.
voiNr; bi++) mem[bi]=chain+bi*(M+1)*N;
444 for(
int m=0; m<M; m++) wws[m]=wwschain+m*N;
448 for(
int m=0; m<M; m++) {
449 if(img.
weight[m]<=1.0e-20) qrweight[m]=0.0;
450 else qrweight[m]=sqrt(img.
weight[m]);
456 if(verbose>1) fprintf(stdout,
"calculating QR decomposition\n");
457 for(
int bi=0; bi<bf.
voiNr; bi++) {
460 for(
int m=0; m<M; m++) A[m]=mem[bi]+m*N;
464 for(
int m=0; m<M; m++) {
465 A[m][0]=tac.
voi[0].
y2[m];
466 A[m][1]=bf.
voi[bi].
y[m];
467 if(N>2) A[m][2]=tac.
voi[1].
y[m];
471 for(
int m=0; m<M; m++)
472 for(
int n=0; n<N; n++)
473 A[m][n]*=qrweight[m];
479 free(chain); free(B); free(residual);
480 free(A); free(wwschain); free(wws); free(qrweight); free(mem);
493 if(verbose>0) {fprintf(stdout,
"computing QR pixel-by-pixel\n"); fflush(stdout);}
494 double maxk3=0.0, maxk1=0.0;
495 double maxt1=0.0, maxt2=0.0;
498 for(
int pi=0; pi<img.
dimz; pi++) {
499 if(img.
dimz>1 && verbose>0) {fprintf(stdout,
"."); fflush(stdout);}
500 for(
int yi=0; yi<img.
dimy; yi++) {
501 for(
int xi=0; xi<img.
dimx; xi++) {
503 k3img.
m[pi][yi][xi][0]=0.0;
504 k1img.
m[pi][yi][xi][0]=0.0;
505 k2img.
m[pi][yi][xi][0]=0.0;
506 kiimg.
m[pi][yi][xi][0]=0.0;
507 dvimg.
m[pi][yi][xi][0]=0.0;
508 vbimg.
m[pi][yi][xi][0]=0.0;
509 erimg.
m[pi][yi][xi][0]=0.0;
510 k2k3img.
m[pi][yi][xi][0]=0.0;
511 t1img.
m[pi][yi][xi][0]=0.0;
512 t2img.
m[pi][yi][xi][0]=0.0;
514 for(
int m=0; m<M; m++) {ct[m]=img.
m[pi][yi][xi][m];}
518 if(cti[dataNr-1]<threshold) {thresholded_nr++;
continue;}
522 double rnorm_min=1.0E80;
523 double p1, p2, p3, p4; p1=p2=p3=p4=0.0;
524 for(
int bi=0; bi<bf.
voiNr; bi++) {
527 for(
int m=0; m<M; m++) {A[m]=mem[bi]+ m*N;}
531 for(
int m=0; m<M; m++) {
532 B[m]=img.
m[pi][yi][xi][m];
538 ret=
qr_solve(A, M, N, tau, B, X, residual, &RNORM, wws, ws);
540 for(
int n=0; n<N; n++) X[n]=0.0;
545 if(RNORM<rnorm_min) {
546 rnorm_min=RNORM; bi_min=bi;
549 if(N>2) p3=X[2];
else p3=0.0;
554 if(verbose>6 && yi==4*img.
dimy/10 && xi==4*img.
dimx/10) {
555 printf(
" Pixel (%d,%d,%d), P1=%g P2=%g P3=%g theta=%g\n",
556 pi, yi, xi, p1, p2, p3, p4);
561 if(!(rnorm_min<1.0E60)) {nosolution_nr++;
continue;}
562 else bf_opt_nr[bi_min]+=1;
565 if(bi_min==0) ret=1;
else if(bi_min==bf.
voiNr-1) ret=2;
else ret=0;
566 erimg.
m[pi][yi][xi][0]=(float)ret;
567 t1img.
m[pi][yi][xi][0]=p1;
568 t2img.
m[pi][yi][xi][0]=p2;
569 k2k3img.
m[pi][yi][xi][0]=p4;
570 if(p1>maxt1) maxt1=p1;
571 if(p2>maxt2) maxt2=p2;
573 vbimg.
m[pi][yi][xi][0]=p3;
574 if(p3>0.99)
continue;
577 if((p1+p2)<1.0E-10)
continue;
578 k1img.
m[pi][yi][xi][0]=p1+p2;
if(p3>0.0 && p3<0.9) k1img.
m[pi][yi][xi][0]/=(1.0-p3);
579 k2img.
m[pi][yi][xi][0]=p2*p4/(p1+p2);
580 k3img.
m[pi][yi][xi][0]=p1*p4/(p1+p2);
581 kiimg.
m[pi][yi][xi][0]=p1;
if(p3>0.0 && p3<0.9) kiimg.
m[pi][yi][xi][0]/=(1.0-p3);
582 if(p4>0.00001) dvimg.
m[pi][yi][xi][0]=k1img.
m[pi][yi][xi][0]/p4;
583 if(k1img.
m[pi][yi][xi][0]>maxk1) maxk1=k1img.
m[pi][yi][xi][0];
584 if(k3img.
m[pi][yi][xi][0]>maxk3) maxk3=k3img.
m[pi][yi][xi][0];
588 if(verbose>0) {fprintf(stdout,
"\ndone.\n"); fflush(stdout);}
589 if(verbose>1 || thresholded_nr>0) {
591 f=(double)thresholded_nr/((
double)(k3img.
dimx*k3img.
dimy*k3img.
dimz));
592 f*=100.;
if(f<3.0) printf(
"%g%%", f);
else printf(
"%.0f%%", f);
593 printf(
" of pixels were not fitted due to threshold.\n");
594 if(verbose>2) printf(
"thresholded %d pixels\n", thresholded_nr);
596 if(verbose>0 || nosolution_nr>0)
597 fprintf(stdout,
"no QR solution for %d pixels.\n", nosolution_nr);
599 printf(
"max_theta1 := %g\n", maxt1);
600 printf(
"max_theta2 := %g\n", maxt2);
601 printf(
"max_k1 := %g\n", maxk1);
602 printf(
"max_k3 := %g\n", maxk3);
606 free(chain); free(B); free(residual); free(A); free(wwschain);
607 free(wws); free(qrweight); free(mem);
610 }
else if(method==METHOD_BVLS) {
615 if(verbose>0) {fprintf(stdout,
"computing BF BVLS pixel-by-pixel\n"); fflush(stdout);}
617 int n=3;
if(fitVb==0) n--;
619 double maxk3=0.0, maxk1=0.0;
620 double maxt1=0.0, maxt2=0.0;
622#pragma omp parallel for
623 for(
int pi=0; pi<img.
dimz; pi++) {
624 if(img.
dimz>1 && verbose>0) {fprintf(stdout,
"."); fflush(stdout);}
625 for(
int yi=0; yi<img.
dimy; yi++) {
626 for(
int xi=0; xi<img.
dimx; xi++) {
628 k3img.
m[pi][yi][xi][0]=0.0;
629 k1img.
m[pi][yi][xi][0]=0.0;
630 k2img.
m[pi][yi][xi][0]=0.0;
631 kiimg.
m[pi][yi][xi][0]=0.0;
632 dvimg.
m[pi][yi][xi][0]=0.0;
633 vbimg.
m[pi][yi][xi][0]=0.0;
634 erimg.
m[pi][yi][xi][0]=0.0;
635 k2k3img.
m[pi][yi][xi][0]=0.0;
636 t1img.
m[pi][yi][xi][0]=0.0;
637 t2img.
m[pi][yi][xi][0]=0.0;
639 float pxlint[dataNr];
641 if(pxlint[dataNr-1]<60.*threshold) {thresholded_nr++;
continue;}
643 double *mat=(
double*)malloc(nm*
sizeof(
double));
644 if(mat==NULL)
continue;
645 double b[m], x[n], bl[n], bu[n], w[n], zz[m];
646 double act[m*(n+2)], r2;
647 int istate[n+1], iterNr;
650 double r2_min=1.0E80;
651 double p1, p2, p3, p4; p1=p2=p3=p4=0.0;
652 for(
int bi=0; bi<bf.
voiNr; bi++) {
654 for(
int mi=0; mi<m; mi++) b[mi]=img.
m[pi][yi][xi][mi];
655 for(
int mi=0; mi<m; mi++) {
656 mat[mi]=tac.
voi[0].
y2[mi];
657 mat[mi+m]=bf.
voi[bi].
y[mi];
658 if(n>2) mat[mi+(2*m)]=tac.
voi[1].
y[mi];
663 istate[n]=0;
for(
int ni=0; ni<n; ni++) istate[ni]=1+ni;
665 bl[0]=0.0; bu[0]=theta1max;
666 bl[1]=0.0; bu[1]=theta2max;
667 if(fitVb!=0) {bl[2]=0.0; bu[2]=Vbmax;}
671 ret=
bvls(1, m, n, mat, b, bl, bu, x, w, act, zz, istate, &iterNr, verbose-30);
676 r2_min=r2; bi_min=bi;
679 if(n>2) p3=x[2];
else p3=0.0;
686 if(!(r2_min<1.0E60)) {nosolution_nr++;
continue;}
687 else bf_opt_nr[bi_min]+=1;
690 if(bi_min==0) ret=1;
else if(bi_min==bf.
voiNr-1) ret=2;
else ret=0;
691 erimg.
m[pi][yi][xi][0]=(float)ret;
692 t1img.
m[pi][yi][xi][0]=p1;
693 t2img.
m[pi][yi][xi][0]=p2;
694 k2k3img.
m[pi][yi][xi][0]=p4;
695 if(p1>maxt1) maxt1=p1;
696 if(p2>maxt2) maxt2=p2;
698 vbimg.
m[pi][yi][xi][0]=p3;
699 if(p3>0.99)
continue;
701 if((p1+p2)<1.0E-10)
continue;
702 k1img.
m[pi][yi][xi][0]=p1+p2;
if(p3>0.0 && p3<0.9) k1img.
m[pi][yi][xi][0]/=(1.0-p3);
703 k2img.
m[pi][yi][xi][0]=p2*p4/(p1+p2);
704 k3img.
m[pi][yi][xi][0]=p1*p4/(p1+p2);
705 kiimg.
m[pi][yi][xi][0]=p1;
if(p3>0.0 && p3<0.9) kiimg.
m[pi][yi][xi][0]/=(1.0-p3);
706 if(p4>0.00001) dvimg.
m[pi][yi][xi][0]=k1img.
m[pi][yi][xi][0]/p4;
707 if(k1img.
m[pi][yi][xi][0]>maxk1) maxk1=k1img.
m[pi][yi][xi][0];
708 if(k3img.
m[pi][yi][xi][0]>maxk3) maxk3=k3img.
m[pi][yi][xi][0];
713 if(verbose>0) {fprintf(stdout,
"\ndone.\n"); fflush(stdout);}
714 if(verbose>1 || thresholded_nr>0) {
716 f=(double)thresholded_nr/((
double)(k3img.
dimx*k3img.
dimy*k3img.
dimz));
717 f*=100.;
if(f<3.0) printf(
"%g%%", f);
else printf(
"%.0f%%", f);
718 printf(
" of pixels were not fitted due to threshold.\n");
719 if(verbose>2) printf(
"thresholded %d pixels\n", thresholded_nr);
721 if(verbose>0 || nosolution_nr>0)
722 fprintf(stdout,
"no solution for %d pixels.\n", nosolution_nr);
724 printf(
"max_theta1 := %g\n", maxt1);
725 printf(
"max_theta2 := %g\n", maxt2);
726 printf(
"max_k1 := %g\n", maxk1);
727 printf(
"max_k3 := %g\n", maxk3);
732 fprintf(stderr,
"Error: selected method not available.");
752 for(
int bi=0; bi<bf.
voiNr; bi++)
753 sprintf(bf.
voi[bi].
place,
"%d", bf_opt_nr[bi]);
755 fprintf(stderr,
"Error in writing %s: %s\n", bfsfile,
dfterrmsg);
762 if(verbose>0) fprintf(stdout,
"basis functions were written in %s\n", bfsfile);
773 if(!ret && k1file[0]) ret=
imgWrite(k1file, &k1img);
774 if(!ret && k2file[0]) ret=
imgWrite(k2file, &k2img);
775 if(!ret && kifile[0]) ret=
imgWrite(kifile, &kiimg);
776 if(!ret && vbfile[0]) ret=
imgWrite(vbfile, &vbimg);
777 if(!ret && dvfile[0]) ret=
imgWrite(dvfile, &dvimg);
778 if(!ret && errfile[0]) ret=
imgWrite(errfile, &erimg);
779 if(!ret && k2k3file[0]) ret=
imgWrite(k2k3file, &k2k3img);
780 if(!ret && t1file[0]) ret=
imgWrite(t1file, &t1img);
781 if(!ret && t2file[0]) ret=
imgWrite(t2file, &t2img);
786 fprintf(stderr,
"Error: cannot write parametric image.\n");
789 if(verbose>0) fprintf(stdout,
"Parametric image(s) saved.\n");
int bfIrr2TCM(DFT *input, DFT *tissue, DFT *bf, int bfNr, double thetamin, double thetamax, char *status, int verbose)
int bvls(int key, const int m, const int n, double *a, double *b, double *bl, double *bu, double *x, double *w, double *act, double *zz, int *istate, int *iter, int verbose)
Bounded-value least-squares method to solve the linear problem A x ~ b , subject to limit1 <= x <= li...
int llsqWght(int N, int M, double **A, double *a, double *b, double *weight)
int atof_with_check(char *double_as_string, double *result_value)
int dftAddmem(DFT *dft, int voiNr)
int dftWrite(DFT *data, char *filename)
int dftTimeunitConversion(DFT *dft, int tunit)
unsigned long long imgNaNs(IMG *img, int fix)
int imgAllocateWithHeader(IMG *image, int planes, int rows, int columns, int frames, IMG *image_from)
void imgEmpty(IMG *image)
int imgWrite(const char *fname, IMG *img)
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().
Header file for libtpccurveio.
Header file for libtpcimgio.
#define IMG_DC_NONCORRECTED
Header file for libtpcimgp.
Header file for libtpcmisc.
int tpcProcessStdOptions(const char *s, int *print_usage, int *print_version, int *verbose_level)
size_t strlcpy(char *dst, const char *src, size_t dstsize)
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 qr_solve(double **QR, int M, int N, double *tau, double *b, double *x, double *residual, double *resNorm, double **cchain, double *chain)
int qr_decomp(double **a, int M, int N, double *tau, double **cchain, double *chain)
Header file for libtpcmodext.
int imgSetWeights(IMG *img, int wmet, int verbose)
char name[MAX_REGIONNAME_LEN+1]
char place[MAX_REGIONSUBNAME_LEN+1]