10#include "tpcclibConfig.h"
34static char *info[] = {
35 "Computation of parametric images from dynamic PET image in ECAT, NIfTI,",
36 "or Analyze format applying irreversible two-tissue compartmental model with",
37 "arterial plasma input, using the basis function method (1).",
39 "Dynamic PET image and plasma and blood time-activity curves (PTAC and BTAC)",
40 "must be corrected for decay to the tracer administration time.",
41 "Enter 'none' in place of the name of btacfile, if you want to assume Vb=0.",
43 "Usage: @P [Options] ptacfile btacfile imgfile k3file",
47 " Pixels with AUC less than (threshold/100 x PTAC AUC) are set to zero;",
49 " -end=<Fit end time (min)>",
50 " Use data from 0 to end time; by default, model is fitted to all frames.",
52 " Parametric K1/(k2+k3) image is saved.",
54 " Parametric K1 image is saved.",
56 " Parametric k2 image is saved.",
58 " Parametric Ki image is saved.",
60 " Parametric Vb image is saved.",
61 " -min=<Min k2+k3> and -max=<Max k2+k3>",
62 " Enter the basis functions minimum and maximum k2+k3 (=alpha) in units 1/min;",
63 " defaults are 0.15 and 0.60, respectively.",
71 " Set number of basis functions; default is 200, minimum 50.",
73 " Parametric k2+k3 (=alpha) image is saved.",
75 " Parametric theta1 image is saved.",
77 " Parametric theta2 image is saved.",
79 " Basis function curves are written in specified TAC file.",
81 " Save image where the pixels that had k2+k3 at min or max value are",
82 " set to values 1 and 2, respectively, and other pixels are set to value 0.",
84 " By default, all weights are set to 1.0 (no weighting, option -w1); option -wf",
85 " sets weights based on frame lengths, and option -wfa based on both frame lengths",
86 " and mean activity during each frame.",
89 "Example 1. Calculation of K1, Ki, k3, and Vb images:",
90 " @P -k1=s2345k1.v -ki=s2345ki.v -Vb=s2345vb.v s2345ap.kbq s2345ab.kbq s2345dy.v s2345k3.v",
91 "Example 2. Calculation with assumption Vb=0:",
92 " @P -k1=s2345k1.v -ki=s2345ki.v s2345ap.kbq none s2345dy.v s2345k3.v",
94 "The units of pixel values in the parametric images are 1/min for k3,",
95 "ml/(min*ml) for K1 and Ki, and ml/ml for DV and Vb.",
98 "1. Hong YT et al. J Cereb Blood Flow Metab. 2011;31:648-657.",
100 "See also: imglhk3, imgki, imgcbv, imgunit, fitdelay",
102 "Keywords: image, modelling, irreversible uptake, Ki, basis function method",
118enum {METHOD_UNKNOWN, METHOD_QR, METHOD_BVLS};
119static char *method_str[] = {
"unknown",
"QR",
"BVLS", 0};
126int main(
int argc,
char **argv)
128 int ai, help=0, version=0, verbose=1;
129 char ptacfile[FILENAME_MAX], btacfile[FILENAME_MAX], petfile[FILENAME_MAX];
130 char k1file[FILENAME_MAX], k2file[FILENAME_MAX], vbfile[FILENAME_MAX];
131 char dvfile[FILENAME_MAX], kifile[FILENAME_MAX], k3file[FILENAME_MAX];
132 char errfile[FILENAME_MAX], bfsfile[FILENAME_MAX], k2k3file[FILENAME_MAX];
133 char t1file[FILENAME_MAX], t2file[FILENAME_MAX];
134 float calcThreshold=0.01;
138 double alphamin=0.15, alphamax=0.60;
139 double theta1max=1.0, theta2max=1.0, Vbmax=1.0;
141 int method=METHOD_QR;
148 if(argc==1) {
tpcPrintUsage(argv[0], info, stderr);
return(1);}
149 ptacfile[0]=btacfile[0]=petfile[0]=k3file[0]=(char)0;
150 vbfile[0]=k1file[0]=k2file[0]=kifile[0]=dvfile[0]=(char)0;
151 errfile[0]=bfsfile[0]=k2k3file[0]=t1file[0]=t2file[0]=(char)0;
153 for(ai=1; ai<argc; ai++)
if(*argv[ai]==
'-') {
155 char *cptr=argv[ai]+1;
if(*cptr==
'-') cptr++;
if(cptr==NULL)
continue;
156 if(strncasecmp(cptr,
"K1=", 3)==0) {
157 strlcpy(k1file, cptr+3, FILENAME_MAX);
continue;
158 }
else if(strncasecmp(cptr,
"K2=", 3)==0) {
159 strlcpy(k2file, cptr+3, FILENAME_MAX);
continue;
160 }
else if(strncasecmp(cptr,
"KI=", 3)==0) {
161 strlcpy(kifile, cptr+3, FILENAME_MAX);
continue;
162 }
else if(strncasecmp(cptr,
"VB=", 3)==0) {
163 strlcpy(vbfile, cptr+3, FILENAME_MAX);
continue;
164 }
else if(strncasecmp(cptr,
"DV=", 3)==0) {
165 strlcpy(dvfile, cptr+3, FILENAME_MAX);
continue;
166 }
else if(strncasecmp(cptr,
"K2K3=", 5)==0) {
167 strlcpy(k2k3file, cptr+5, FILENAME_MAX);
continue;
168 }
else if(strncasecmp(cptr,
"T1=", 3)==0) {
169 strlcpy(t1file, cptr+3, FILENAME_MAX);
continue;
170 }
else if(strncasecmp(cptr,
"T2=", 3)==0) {
171 strlcpy(t2file, cptr+3, FILENAME_MAX);
continue;
172 }
else if(strncasecmp(cptr,
"THR=", 4)==0) {
174 if(!ret && v>=0.0 && v<=200.0) {calcThreshold=(float)(0.01*v);
continue;}
175 }
else if(strncasecmp(cptr,
"END=", 4)==0) {
176 ret=
atof_with_check(cptr+4, &fittime);
if(!ret && fittime>0.0)
continue;
177 }
else if(strcasecmp(cptr,
"WFA")==0) {
179 }
else if(strcasecmp(cptr,
"WF")==0) {
181 }
else if(strcasecmp(cptr,
"W1")==0) {
183 }
else if(strncasecmp(cptr,
"min=", 4)==0) {
185 }
else if(strncasecmp(cptr,
"max=", 4)==0) {
187 }
else if(strncasecmp(cptr,
"theta1max=", 10)==0) {
188 if(
atof_with_check(cptr+10, &theta1max)==0 && theta1max>=0.0)
continue;
189 }
else if(strncasecmp(cptr,
"theta2max=", 10)==0) {
190 if(
atof_with_check(cptr+10, &theta2max)==0 && theta2max>=0.0)
continue;
191 }
else if(strncasecmp(cptr,
"Vbmax=", 6)==0) {
192 if(
atof_with_check(cptr+6, &Vbmax)==0 && Vbmax>=0.0 && Vbmax<=1.0)
continue;
193 }
else if(strncasecmp(cptr,
"NR=", 3)==0) {
194 bfNr=atoi(cptr+3);
if(bfNr>5E+04) bfNr=5E+04;
195 if(bfNr>=50)
continue;
196 }
else if(strncasecmp(cptr,
"BF=", 3)==0) {
197 strlcpy(bfsfile, cptr+3, FILENAME_MAX);
if(strlen(bfsfile)>0)
continue;
198 }
else if(strncasecmp(cptr,
"ERR=", 4)==0) {
199 strlcpy(errfile, cptr+4, FILENAME_MAX);
if(strlen(errfile)>0)
continue;
200 }
else if(strcasecmp(cptr,
"QR")==0) {
201 method=METHOD_QR;
continue;
202 }
else if(strcasecmp(cptr,
"BVLS")==0) {
203 method=METHOD_BVLS;
continue;
205 fprintf(stderr,
"Error: invalid option '%s'.\n", argv[ai]);
210 if(help==2) {
tpcHtmlUsage(argv[0], info,
"");
return(0);}
215 if(ai<argc)
strlcpy(ptacfile, argv[ai++], FILENAME_MAX);
216 if(ai<argc)
strlcpy(btacfile, argv[ai++], FILENAME_MAX);
217 if(ai<argc)
strlcpy(petfile, argv[ai++], FILENAME_MAX);
218 if(ai<argc)
strlcpy(k3file, argv[ai++], FILENAME_MAX);
220 fprintf(stderr,
"Error: invalid argument '%s'.\n", argv[ai]);
225 fprintf(stderr,
"Error: missing command-line argument; use option --help\n");
228 if(strcasecmp(btacfile,
"NONE")==0 || strcasecmp(btacfile,
"'NONE'")==0 || Vbmax<=0.0) {
229 fitVb=0; Vbmax=0.0; btacfile[0]=(char)0;
231 fprintf(stderr,
"Error: Vb cannot be calculated without BTAC file.\n");
238 printf(
"ptacfile := %s\n", ptacfile);
239 if(btacfile[0]) printf(
"btacfile := %s\n", btacfile);
240 printf(
"petfile := %s\n", petfile);
241 printf(
"k3file := %s\n", k3file);
242 if(vbfile[0]) printf(
"vbfile := %s\n", vbfile);
243 if(k1file[0]) printf(
"k1file := %s\n", k1file);
244 if(k2file[0]) printf(
"k2file := %s\n", k2file);
245 if(k2k3file[0]) printf(
"k2k3file := %s\n", k2k3file);
246 if(kifile[0]) printf(
"kifile := %s\n", kifile);
247 if(dvfile[0]) printf(
"dvfile := %s\n", dvfile);
248 if(errfile[0]) printf(
"errfile := %s\n", errfile);
249 if(t1file[0]) printf(
"t1file := %s\n", t1file);
250 if(t2file[0]) printf(
"t2file := %s\n", t2file);
251 if(bfsfile[0]) printf(
"bfsfile := %s\n", bfsfile);
252 printf(
"fitVb := %d\n", fitVb);
253 printf(
"method := %s\n", method_str[method]);
254 printf(
"calcThreshold :=%g\n", calcThreshold);
255 printf(
"weights := %d\n", weights);
256 if(fittime>0.0) printf(
"required_fittime := %g min\n", fittime);
257 printf(
"bfNr := %d\n", bfNr);
258 if(alphamin>0.0) printf(
"alpha_min := %g\n", alphamin);
259 if(alphamax>0.0) printf(
"alpha_max := %g\n", alphamax);
260 printf(
"theta1_max := %g\n", theta1max);
261 printf(
"theta2_max := %g\n", theta2max);
262 printf(
"Vb_max := %g\n", Vbmax);
268 if(alphamin>=alphamax) {
269 fprintf(stderr,
"Error: invalid range for k2+k3 (%g - %g).\n", alphamin, alphamax);
277 if(verbose>0) {printf(
"reading data files\n"); fflush(stdout);}
284 petfile, NULL, ptacfile, btacfile, NULL, &fittime, &dataNr, &img,
285 &inp, &tac, 1, stdout, verbose-2, errmsg);
287 fprintf(stderr,
"Error: %s.\n", errmsg);
288 if(verbose>1) printf(
" ret := %d\n", ret);
289 fflush(stderr); fflush(stdout);
294 if(verbose>0) fprintf(stderr,
"Warning: missing pixel values.\n");
297 for(
int fi=0; fi<tac.
frameNr; fi++) tac.
voi[0].
y2[fi]/=60.0;
298 for(
int fi=0; fi<tac.
frameNr; fi++) tac.
voi[0].
y3[fi]/=3600.0;
303 printf(
"fittimeFinal := %g min\n", fittime);
304 printf(
"dataNr := %d\n", dataNr);
308 fprintf(stderr,
"Error: too few time frames for fitting.\n");
314 if(verbose>1) fprintf(stdout,
"allocating working memory for pixel TACs\n");
317 fprintf(stderr,
"Error: cannot allocate memory.\n");
318 if(verbose>0) printf(
"ret := %d\n", ret);
321 strcpy(tac.
voi[0].
name,
"plasma");
322 strcpy(tac.
voi[1].
name,
"blood");
323 strcpy(tac.
voi[2].
name,
"tissue");
328 double threshold=calcThreshold*tac.
voi[0].
y2[dataNr-1];
329 if(verbose>1) printf(
"threshold_AUC := %g\n", threshold);
333 fprintf(stderr,
"Error: cannot calculate weights.\n");
336 for(
int i=0; i<dataNr; i++) tac.
w[i]=img.
weight[i];
342 if(verbose>1) fprintf(stdout,
"calculating basis functions\n");
345 ret=
bfIrr2TCM(&inp, &tac, &bf, bfNr, alphamin, alphamax, errmsg, verbose-2);
348 fprintf(stderr,
"Error: cannot calculate basis functions (%d).\n", ret);
358 int *bf_opt_nr=(
int*)malloc(bfNr*
sizeof(
int));
359 for(
int bi=0; bi<bf.
voiNr; bi++) bf_opt_nr[bi]=0.0;
367 if(verbose>1) fprintf(stdout,
"allocating memory for parametric image data\n");
389 fprintf(stderr,
"Error: cannot allocate memory for result image.\n");
400 dvimg.
end[0]=erimg.
end[0]=k2k3img.
end[0]=t1img.
end[0]=t2img.
end[0]=60.*fittime;
403 dvimg.
unit=vbimg.
unit=CUNIT_ML_PER_ML;
405 erimg.
unit=CUNIT_UNITLESS;
416 int thresholded_nr=0;
419 if(method==METHOD_QR) {
425 M=dataNr; N=3;
if(fitVb==0) N--;
426 double **mem, **A, *B, X[N], *tau, *residual, RNORM, *chain;
427 double *qrweight, **wws, *ws, *wwschain;
428 if(verbose>1) fprintf(stdout,
"allocating memory for QR\n");
429 chain=(
double*)malloc((M+1)*N*bf.
voiNr *
sizeof(
double));
430 mem=(
double**)malloc(bf.
voiNr *
sizeof(
double*));
431 A=(
double**)malloc(M *
sizeof(
double*));
432 B=(
double*)malloc(M*
sizeof(
double));
433 residual=(
double*)malloc(M*
sizeof(
double));
434 qrweight=(
double*)malloc(M*
sizeof(
double));
435 wwschain=(
double*)malloc((M*N+2*M)*
sizeof(
double));
436 wws=(
double**)malloc(M *
sizeof(
double*));
437 if(chain==NULL || B==NULL || A==NULL || residual==NULL || qrweight==NULL ||
438 wwschain==NULL || wws==NULL)
440 fprintf(stderr,
"Error: out of memory.\n");
447 for(
int bi=0; bi<bf.
voiNr; bi++) mem[bi]=chain+bi*(M+1)*N;
448 for(
int m=0; m<M; m++) wws[m]=wwschain+m*N;
452 for(
int m=0; m<M; m++) {
453 if(img.
weight[m]<=1.0e-20) qrweight[m]=0.0;
454 else qrweight[m]=sqrt(img.
weight[m]);
460 if(verbose>1) fprintf(stdout,
"calculating QR decomposition\n");
461 for(
int bi=0; bi<bf.
voiNr; bi++) {
464 for(
int m=0; m<M; m++) A[m]=mem[bi]+m*N;
468 for(
int m=0; m<M; m++) {
469 A[m][0]=tac.
voi[0].
y2[m];
470 A[m][1]=bf.
voi[bi].
y[m];
471 if(N>2) A[m][2]=tac.
voi[1].
y[m];
475 for(
int m=0; m<M; m++)
476 for(
int n=0; n<N; n++)
477 A[m][n]*=qrweight[m];
483 free(chain); free(B); free(residual);
484 free(A); free(wwschain); free(wws); free(qrweight); free(mem);
497 if(verbose>0) {fprintf(stdout,
"computing QR pixel-by-pixel\n"); fflush(stdout);}
498 double maxk3=0.0, maxk1=0.0;
499 double maxt1=0.0, maxt2=0.0;
502 for(
int pi=0; pi<img.
dimz; pi++) {
503 if(img.
dimz>1 && verbose>0) {fprintf(stdout,
"."); fflush(stdout);}
504 for(
int yi=0; yi<img.
dimy; yi++) {
505 for(
int xi=0; xi<img.
dimx; xi++) {
507 k3img.
m[pi][yi][xi][0]=0.0;
508 k1img.
m[pi][yi][xi][0]=0.0;
509 k2img.
m[pi][yi][xi][0]=0.0;
510 kiimg.
m[pi][yi][xi][0]=0.0;
511 dvimg.
m[pi][yi][xi][0]=0.0;
512 vbimg.
m[pi][yi][xi][0]=0.0;
513 erimg.
m[pi][yi][xi][0]=0.0;
514 k2k3img.
m[pi][yi][xi][0]=0.0;
515 t1img.
m[pi][yi][xi][0]=0.0;
516 t2img.
m[pi][yi][xi][0]=0.0;
518 for(
int m=0; m<M; m++) {ct[m]=img.
m[pi][yi][xi][m];}
522 if(cti[dataNr-1]<threshold) {thresholded_nr++;
continue;}
526 double rnorm_min=1.0E80;
527 double p1, p2, p3, p4; p1=p2=p3=p4=0.0;
528 for(
int bi=0; bi<bf.
voiNr; bi++) {
531 for(
int m=0; m<M; m++) {A[m]=mem[bi]+ m*N;}
535 for(
int m=0; m<M; m++) {
536 B[m]=img.
m[pi][yi][xi][m];
542 ret=
qr_solve(A, M, N, tau, B, X, residual, &RNORM, wws, ws);
544 for(
int n=0; n<N; n++) X[n]=0.0;
549 if(RNORM<rnorm_min) {
550 rnorm_min=RNORM; bi_min=bi;
553 if(N>2) p3=X[2];
else p3=0.0;
558 if(verbose>6 && yi==4*img.
dimy/10 && xi==4*img.
dimx/10) {
559 printf(
" Pixel (%d,%d,%d), P1=%g P2=%g P3=%g theta=%g\n",
560 pi, yi, xi, p1, p2, p3, p4);
565 if(!(rnorm_min<1.0E60)) {nosolution_nr++;
continue;}
566 else bf_opt_nr[bi_min]+=1;
569 if(bi_min==0) ret=1;
else if(bi_min==bf.
voiNr-1) ret=2;
else ret=0;
570 erimg.
m[pi][yi][xi][0]=(float)ret;
571 t1img.
m[pi][yi][xi][0]=p1;
572 t2img.
m[pi][yi][xi][0]=p2;
573 k2k3img.
m[pi][yi][xi][0]=p4;
574 if(p1>maxt1) maxt1=p1;
575 if(p2>maxt2) maxt2=p2;
577 vbimg.
m[pi][yi][xi][0]=p3;
578 if(p3>0.99)
continue;
581 if((p1+p2)<1.0E-10)
continue;
582 k1img.
m[pi][yi][xi][0]=p1+p2;
if(p3>0.0 && p3<0.9) k1img.
m[pi][yi][xi][0]/=(1.0-p3);
583 k2img.
m[pi][yi][xi][0]=p2*p4/(p1+p2);
584 k3img.
m[pi][yi][xi][0]=p1*p4/(p1+p2);
585 kiimg.
m[pi][yi][xi][0]=p1;
if(p3>0.0 && p3<0.9) kiimg.
m[pi][yi][xi][0]/=(1.0-p3);
586 if(p4>0.00001) dvimg.
m[pi][yi][xi][0]=k1img.
m[pi][yi][xi][0]/p4;
587 if(k1img.
m[pi][yi][xi][0]>maxk1) maxk1=k1img.
m[pi][yi][xi][0];
588 if(k3img.
m[pi][yi][xi][0]>maxk3) maxk3=k3img.
m[pi][yi][xi][0];
592 if(verbose>0) {fprintf(stdout,
"\ndone.\n"); fflush(stdout);}
593 if(verbose>1 || thresholded_nr>0) {
595 f=(double)thresholded_nr/((
double)(k3img.
dimx*k3img.
dimy*k3img.
dimz));
596 f*=100.;
if(f<3.0) printf(
"%g%%", f);
else printf(
"%.0f%%", f);
597 printf(
" of pixels were not fitted due to threshold.\n");
598 if(verbose>2) printf(
"thresholded %d pixels\n", thresholded_nr);
600 if(verbose>0 || nosolution_nr>0)
601 fprintf(stdout,
"no QR solution for %d pixels.\n", nosolution_nr);
603 printf(
"max_theta1 := %g\n", maxt1);
604 printf(
"max_theta2 := %g\n", maxt2);
605 printf(
"max_k1 := %g\n", maxk1);
606 printf(
"max_k3 := %g\n", maxk3);
610 free(chain); free(B); free(residual); free(A); free(wwschain);
611 free(wws); free(qrweight); free(mem);
614 }
else if(method==METHOD_BVLS) {
619 if(verbose>0) {fprintf(stdout,
"computing BF BVLS pixel-by-pixel\n"); fflush(stdout);}
621 int n=3;
if(fitVb==0) n--;
623 double maxk3=0.0, maxk1=0.0;
624 double maxt1=0.0, maxt2=0.0;
626#pragma omp parallel for
627 for(
int pi=0; pi<img.
dimz; pi++) {
628 if(img.
dimz>1 && verbose>0) {fprintf(stdout,
"."); fflush(stdout);}
629 for(
int yi=0; yi<img.
dimy; yi++) {
630 for(
int xi=0; xi<img.
dimx; xi++) {
632 k3img.
m[pi][yi][xi][0]=0.0;
633 k1img.
m[pi][yi][xi][0]=0.0;
634 k2img.
m[pi][yi][xi][0]=0.0;
635 kiimg.
m[pi][yi][xi][0]=0.0;
636 dvimg.
m[pi][yi][xi][0]=0.0;
637 vbimg.
m[pi][yi][xi][0]=0.0;
638 erimg.
m[pi][yi][xi][0]=0.0;
639 k2k3img.
m[pi][yi][xi][0]=0.0;
640 t1img.
m[pi][yi][xi][0]=0.0;
641 t2img.
m[pi][yi][xi][0]=0.0;
643 float pxlint[dataNr];
645 if(pxlint[dataNr-1]<60.*threshold) {thresholded_nr++;
continue;}
647 double *mat=(
double*)malloc(nm*
sizeof(
double));
648 if(mat==NULL)
continue;
649 double b[m], x[n], bl[n], bu[n], w[n], zz[m];
650 double act[m*(n+2)], r2;
651 int istate[n+1], iterNr;
654 double r2_min=1.0E80;
655 double p1, p2, p3, p4; p1=p2=p3=p4=0.0;
656 for(
int bi=0; bi<bf.
voiNr; bi++) {
658 for(
int mi=0; mi<m; mi++) b[mi]=img.
m[pi][yi][xi][mi];
659 for(
int mi=0; mi<m; mi++) {
660 mat[mi]=tac.
voi[0].
y2[mi];
661 mat[mi+m]=bf.
voi[bi].
y[mi];
662 if(n>2) mat[mi+(2*m)]=tac.
voi[1].
y[mi];
667 istate[n]=0;
for(
int ni=0; ni<n; ni++) istate[ni]=1+ni;
669 bl[0]=0.0; bu[0]=theta1max;
670 bl[1]=0.0; bu[1]=theta2max;
671 if(fitVb!=0) {bl[2]=0.0; bu[2]=Vbmax;}
675 ret=
bvls(1, m, n, mat, b, bl, bu, x, w, act, zz, istate, &iterNr, verbose-30);
680 r2_min=r2; bi_min=bi;
683 if(n>2) p3=x[2];
else p3=0.0;
690 if(!(r2_min<1.0E60)) {nosolution_nr++;
continue;}
691 else bf_opt_nr[bi_min]+=1;
694 if(bi_min==0) ret=1;
else if(bi_min==bf.
voiNr-1) ret=2;
else ret=0;
695 erimg.
m[pi][yi][xi][0]=(float)ret;
696 t1img.
m[pi][yi][xi][0]=p1;
697 t2img.
m[pi][yi][xi][0]=p2;
698 k2k3img.
m[pi][yi][xi][0]=p4;
699 if(p1>maxt1) maxt1=p1;
700 if(p2>maxt2) maxt2=p2;
702 vbimg.
m[pi][yi][xi][0]=p3;
703 if(p3>0.99)
continue;
705 if((p1+p2)<1.0E-10)
continue;
706 k1img.
m[pi][yi][xi][0]=p1+p2;
if(p3>0.0 && p3<0.9) k1img.
m[pi][yi][xi][0]/=(1.0-p3);
707 k2img.
m[pi][yi][xi][0]=p2*p4/(p1+p2);
708 k3img.
m[pi][yi][xi][0]=p1*p4/(p1+p2);
709 kiimg.
m[pi][yi][xi][0]=p1;
if(p3>0.0 && p3<0.9) kiimg.
m[pi][yi][xi][0]/=(1.0-p3);
710 if(p4>0.00001) dvimg.
m[pi][yi][xi][0]=k1img.
m[pi][yi][xi][0]/p4;
711 if(k1img.
m[pi][yi][xi][0]>maxk1) maxk1=k1img.
m[pi][yi][xi][0];
712 if(k3img.
m[pi][yi][xi][0]>maxk3) maxk3=k3img.
m[pi][yi][xi][0];
717 if(verbose>0) {fprintf(stdout,
"\ndone.\n"); fflush(stdout);}
718 if(verbose>1 || thresholded_nr>0) {
720 f=(double)thresholded_nr/((
double)(k3img.
dimx*k3img.
dimy*k3img.
dimz));
721 f*=100.;
if(f<3.0) printf(
"%g%%", f);
else printf(
"%.0f%%", f);
722 printf(
" of pixels were not fitted due to threshold.\n");
723 if(verbose>2) printf(
"thresholded %d pixels\n", thresholded_nr);
725 if(verbose>0 || nosolution_nr>0)
726 fprintf(stdout,
"no solution for %d pixels.\n", nosolution_nr);
728 printf(
"max_theta1 := %g\n", maxt1);
729 printf(
"max_theta2 := %g\n", maxt2);
730 printf(
"max_k1 := %g\n", maxk1);
731 printf(
"max_k3 := %g\n", maxk3);
736 fprintf(stderr,
"Error: selected method not available.");
756 for(
int bi=0; bi<bf.
voiNr; bi++)
757 sprintf(bf.
voi[bi].
place,
"%d", bf_opt_nr[bi]);
759 fprintf(stderr,
"Error in writing %s: %s\n", bfsfile,
dfterrmsg);
766 if(verbose>0) fprintf(stdout,
"basis functions were written in %s\n", bfsfile);
777 if(!ret && k1file[0]) ret=
imgWrite(k1file, &k1img);
778 if(!ret && k2file[0]) ret=
imgWrite(k2file, &k2img);
779 if(!ret && kifile[0]) ret=
imgWrite(kifile, &kiimg);
780 if(!ret && vbfile[0]) ret=
imgWrite(vbfile, &vbimg);
781 if(!ret && dvfile[0]) ret=
imgWrite(dvfile, &dvimg);
782 if(!ret && errfile[0]) ret=
imgWrite(errfile, &erimg);
783 if(!ret && k2k3file[0]) ret=
imgWrite(k2k3file, &k2k3img);
784 if(!ret && t1file[0]) ret=
imgWrite(t1file, &t1img);
785 if(!ret && t2file[0]) ret=
imgWrite(t2file, &t2img);
790 fprintf(stderr,
"Error: cannot write parametric image.\n");
793 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]