12#include "tpcclibConfig.h"
32static char *info[] = {
33 "Estimation of rate constants K1, k2 and Va from dynamic PET image in",
34 "ECAT 6.3, ECAT 7.x, NIfTI-1, or Analyze 7.5 file format using",
35 "one-tissue compartment model (1), solved using the basis function",
38 "When applied to dynamic [O-15]H2O studies, the resulting K1 image",
39 "equals perfusion (blood flow) image. K1 image can be divided by tissue",
40 "density (g/mL) (option -density) and multiplied by 100 (option -dL)",
41 "to achieve the blood flow image in units (mL blood)/((100 g tissue) * min).",
43 "When applied to dynamic [O-15]O2 brain studies, the resulting K1 image",
44 "can be converted to oxygen consumption image by multiplying it by",
45 "arterial oxygen concentration (4) (mL O2 / dL blood) to get the",
46 "parametric image in units mL O2 / ((100 ml tissue) * min).",
47 "The model assumptions hold only when oxygen consumption is 1-6.7",
48 "mL O2/(100g * min) and fit time is set to 300 s or less (4).",
50 "Arterial blood TAC must be corrected for decay and delay, with sample times",
51 "in seconds. Dynamic PET image must be corrected for decay. Fit time must",
52 "be given in seconds.",
54 "Usage: @P [Options] btacfile imgfile fittime flowfile",
58 " Units in flow and Va images will be given per mL or per dL,",
59 " respectively. By default, units are per mL.",
60 " -density[=<value>]",
61 " With option -density the flow is calculated per gram or 100g tissue.",
62 " Tissue density can be changed from the default 1.04 g/mL.",
64 " Parametric K1/k2 (Vd, apparent p) image is saved.",
66 " Parametric k2 image is saved; in some situations perfusion calculation",
67 " from k2 can be more accurate than the default assumption of f=K1.",
68 " Perfusion can be calculated from k2 using equation f=k2*pH2O, where",
69 " pH2O is the physiological partition coefficient of water in tissue.",
71 " Parametric Va image is saved.",
72 " Set -Va=0, if Va=0 is assumed (pre-corrected); otherwise Va is fitted.",
74 " Weighted sum-of-squares are written in specified image file.",
76 " Pixels with AUC less than (threshold/100 x input AUC) are set to zero;",
78 " -k2min=<Min k2> and -k2max=<Max k2>",
79 " Enter the minimum and maximum k2 in units 1/min, applying to decay",
81 " -fmin=<Min K1> and -fmax=<Max K1>",
82 " Enter the minimum and maximum perfusion value; defaults are",
83 " 0.005 and 4.0 mL/(mL*min), respectively.",
84 " -pmin=<Min p> and -pmax=<pmax>",
85 " Enter the minimum and maximum value for apparent partition coefficient",
86 " for water; defaults are 0.3 and 1.0 mL/mL, respectively.",
88 " Set number of basis functions; default is 500, minimum 100.",
90 " Basis function curves are written in specified file.",
92 " Pixels with their k2 in its min or max value (calculated from min and",
93 " max K1 and p values) in the specified imagefile with values 1 and 2,",
94 " respectively, others with value 0.",
96 " Only the masked pixels are processed. If output images exist, then",
97 " pixel values outside of mask are preserved.",
100 "Example 1. Calculation of perfusion and arterial blood volume image,",
101 " stopping fit at 180 s:",
102 " @P -Va=s2345va.img s2345abfit.kbq s2345dy1.v 180 s2345flow.v",
104 "By default, the units of pixel values in the blood flow (K1) image is",
105 "(mL blood)/((mL tissue) * min), in Vd image (mL blood)/(mL tissue),",
106 "in k2 image 1/min, and in Va image (mL blood/mL tissue),",
107 "but the blood flow and Va units can be changed with above listed options.",
110 "1. Lammertsma AA, Jones T. J Cereb Blood Flow Metab. 1983;3:416-424.",
111 "2. Koeppe RA et al. J Cereb Blood Flow metab. 1985;5:224-234.",
112 "3. Boellaard R et al. Mol Imaging Biol. 2005;7:273-285.",
113 "4. Ohta S, et al. J Cereb Blood Flow Metab. 1992;12:179-192.",
115 "See also: bfmh2o, imgflow, arlkup, fit_h2o, imgunit, fitdelay, imgcbv",
117 "Keywords: image, modelling, perfusion, radiowater, basis function method",
136int main(
int argc,
char **argv)
138 int ai, help=0, version=0, verbose=1;
140 char inpfile[FILENAME_MAX], petfile[FILENAME_MAX], flowfile[FILENAME_MAX];
141 char vdfile[FILENAME_MAX], k2file[FILENAME_MAX], wssfile[FILENAME_MAX];
142 char errfile[FILENAME_MAX], bfsfile[FILENAME_MAX];
143 char vafile[FILENAME_MAX], maskfile[FILENAME_MAX], tmp[FILENAME_MAX+1], *cptr;
144 int bfNr=500, *bf_opt_nr;
145 float threshold, calcThreshold=0.0;
147 double flowMin=0.005, flowMax=4.0;
148 double pWaterMin=0.3, pWaterMax=1.0;
149 double k2min=-1.0, k2max=-1.0;
150 int ret, fi, pi, xi, yi;
151 int nosolution_nr=0, thresholded_nr=0;
152 clock_t fitStart, fitFinish;
159 IMG img, flowimg, k2img, vdimg, vaimg, wssimg, errimg;
165 if(argc==1) {
tpcPrintUsage(argv[0], info, stderr);
return(1);}
166 inpfile[0]=petfile[0]=flowfile[0]=vdfile[0]=k2file[0]=wssfile[0]=(char)0;
167 errfile[0]=bfsfile[0]=vafile[0]=maskfile[0]=(char)0;
169 for(ai=1; ai<argc; ai++)
if(*argv[ai]==
'-') {
171 cptr=argv[ai]+1;
if(*cptr==
'-') cptr++;
if(cptr==NULL)
continue;
172 if(strcasecmp(cptr,
"DL")==0) {
174 }
else if(strcasecmp(cptr,
"ML")==0) {
176 }
else if(strcasecmp(cptr,
"DENSITY")==0) {
177 per_gram=1;
continue;
178 }
else if(strncasecmp(cptr,
"DENSITY=", 8)==0) {
179 per_gram=1; density=
atof_dpi(cptr+8);
if(density>0.0)
continue;
180 }
else if(strncasecmp(cptr,
"VA=", 3)==0 || strncasecmp(cptr,
"VB=", 3)==0) {
181 strlcpy(vafile, cptr+3, FILENAME_MAX);
if(strlen(vafile))
continue;
182 }
else if(strncasecmp(cptr,
"k2min=", 6)==0) {
184 }
else if(strncasecmp(cptr,
"k2max=", 6)==0) {
186 }
else if(strncasecmp(cptr,
"fmin=", 5)==0 && strlen(cptr)>5) {
188 }
else if(strncasecmp(cptr,
"fmax=", 5)==0 && strlen(cptr)>5) {
190 }
else if(strncasecmp(cptr,
"pmin=", 5)==0 && strlen(cptr)>5) {
192 }
else if(strncasecmp(cptr,
"pmax=", 5)==0 && strlen(cptr)>5) {
194 }
else if(strncasecmp(cptr,
"VD=", 3)==0) {
195 strlcpy(vdfile, cptr+3, FILENAME_MAX);
if(strlen(vdfile)>1)
continue;
196 }
else if(strncasecmp(cptr,
"k2=", 3)==0) {
197 strlcpy(k2file, cptr+3, FILENAME_MAX);
if(strlen(k2file)>1)
continue;
198 }
else if(strncasecmp(cptr,
"NR=", 3)==0) {
199 bfNr=atoi(cptr+3);
if(bfNr>5E+04) bfNr=5E+04;
200 if(bfNr>=100)
continue;
201 }
else if(strncasecmp(cptr,
"BF=", 3)==0) {
202 strlcpy(bfsfile, cptr+3, FILENAME_MAX);
if(strlen(bfsfile)>0)
continue;
203 }
else if(strncasecmp(cptr,
"WSS=", 4)==0) {
204 strlcpy(wssfile, cptr+4, FILENAME_MAX);
if(strlen(wssfile)>0)
continue;
205 }
else if(strncasecmp(cptr,
"ERR=", 4)==0) {
206 strlcpy(errfile, cptr+4, FILENAME_MAX);
if(strlen(errfile)>0)
continue;
207 }
else if(strncasecmp(cptr,
"THR=", 4)==0 && strlen(cptr)>4) {
208 cptr+=4;
if(isdigit(*cptr) || *cptr==
'+' || *cptr==
'-') {
210 if(calcThreshold>=0.0 && calcThreshold<=2.0)
continue;
213 fprintf(stderr,
"Error: invalid option '%s'.\n", argv[ai]);
218 if(help==2) {
tpcHtmlUsage(argv[0], info,
"");
return(0);}
223 if(ai<argc)
strlcpy(inpfile, argv[ai++], FILENAME_MAX);
224 if(ai<argc)
strlcpy(petfile, argv[ai++], FILENAME_MAX);
228 fprintf(stderr,
"Error: invalid fit time '%s'.\n", argv[ai]);
233 if(ai<argc)
strlcpy(flowfile, argv[ai++], FILENAME_MAX);
235 fprintf(stderr,
"Error: invalid argument '%s'.\n", argv[ai]);
240 fprintf(stderr,
"Error: missing command-line argument; use option --help\n");
243 if(fittime<=0.0) fittime=1.0E+020;
245 if(strcasecmp(vafile,
"NONE")==0 || strcasecmp(vafile,
"ZERO")==0 ||
246 strcasecmp(vafile,
"0")==0) {vafile[0]=(char)0; fitVa=0;}
249 printf(
"petfile := %s\n", petfile);
250 printf(
"inpfile := %s\n", inpfile);
251 printf(
"flowfile := %s\n", flowfile);
252 if(vdfile[0]) printf(
"vdfile := %s\n", vdfile);
253 if(k2file[0]) printf(
"k2file := %s\n", k2file);
254 if(vafile[0]) printf(
"vafile := %s\n", vafile);
255 if(wssfile[0]) printf(
"wssfile := %s\n", wssfile);
256 if(errfile[0]) printf(
"errfile := %s\n", errfile);
257 if(bfsfile[0]) printf(
"bfsfile := %s\n", bfsfile);
258 if(maskfile[0]) printf(
"maskfile := %s\n", maskfile);
259 printf(
"fitVa := %d\n", fitVa);
260 printf(
"bfNr := %d\n", bfNr);
261 printf(
"per_dl := %d\n", per_dl);
262 printf(
"per_gram := %d\n", per_gram);
263 if(per_gram!=0) printf(
"density := %g\n", density);
264 printf(
"calcThreshold := %g\n", calcThreshold);
265 printf(
"requested_fittime := %g [min]\n", fittime);
266 if(k2min>0.0) printf(
"k2min := %g\n", k2min);
267 if(k2max>0.0) printf(
"k2max := %g\n", k2max);
268 printf(
"flowMax := %g\n", flowMax);
269 printf(
"flowMin := %g\n", flowMin);
270 printf(
"flowMax := %g\n", flowMax);
271 printf(
"pWaterMin := %g\n", pWaterMin);
272 printf(
"pWaterMax := %g\n", pWaterMax);
277 if(flowMin>=flowMax) {
278 fprintf(stderr,
"Error: invalid range for perfusion (%g - %g).\n",
282 if(pWaterMin>=pWaterMax) {
283 fprintf(stderr,
"Error: invalid range for p (%g - %g).\n",
284 pWaterMin, pWaterMax);
288 k2min=flowMin/pWaterMax;
289 if(verbose>1) printf(
"k2min := %g [1/min]\n", k2min);
292 k2max=flowMax/pWaterMin;
293 if(verbose>1) printf(
"k2max := %g [1/min]\n", k2max);
295 if(k2max<=k2min || k2min<=0.) {
296 fprintf(stderr,
"Error: invalid range for k2 (%g - %g).\n", k2min, k2max);
304 if(verbose>1) printf(
"reading data files\n");
307 petfile, NULL, inpfile, NULL, NULL, &fittime, &fitdimt, &img,
308 &blood, &tac, 1, stdout, verbose-2, tmp);
310 fprintf(stderr,
"Error: %s.\n", tmp);
311 if(verbose>1) printf(
" ret := %d\n", ret);
315 if(verbose>0) fprintf(stderr,
"Warning: missing pixel values.\n");
322 fprintf(stderr,
"Error: too few time frames for fitting.\n");
329 fprintf(stderr,
"Error (%d) in allocating memory.\n", ret); fflush(stderr);
335 printf(
"fittimeFinal := %g min\n", fittime);
336 printf(
"fitdimt := %d\n", fitdimt);
343 threshold=calcThreshold*tac.
voi[0].
y2[tac.
frameNr-1]/60.0;
344 if(verbose>2) {printf(
"threshold_AUC = %g\n", threshold); fflush(stdout);}
350 if(verbose>1) printf(
"setting weights\n");
353 fprintf(stderr,
"Warning: cannot calculate weights.\n"); fflush(stderr);
355 for(fi=0; fi<img.
dimt; fi++) img.
weight[fi]=1.0;
363 if(verbose>1) {fprintf(stdout,
"calculating basis functions\n"); fflush(stdout);}
366 ret=
bfRadiowater(&blood, &tac, &bf, bfNr, k2min, k2max, tmp, verbose-2);
370 fprintf(stderr,
"Error: cannot calculate basis functions (%d).\n", ret); fflush(stderr);
383 if(verbose>1) {printf(
"allocating memory for parametric images\n"); fflush(stdout);}
388 fprintf(stderr,
"Error: out of memory.\n");
392 flowimg.
start[0]=0.0; flowimg.
end[0]=fittime*60.0;
395 flowimg.
unit=IMGUNIT_ML_PER_ML_PER_MIN;
398 k2img.
unit=IMGUNIT_PER_MIN;
400 if(ret==0 && vdfile[0]) {
402 vdimg.
unit=IMGUNIT_UNITLESS;
404 if(ret==0 && vafile[0]) {
406 vaimg.
unit=IMGUNIT_UNITLESS;
408 if(ret==0 && wssfile[0]) {
410 wssimg.
unit=IMGUNIT_UNITLESS;
412 if(ret==0 && errfile[0]) {
414 errimg.
unit=IMGUNIT_UNITLESS;
417 fprintf(stderr,
"Error: out of memory.\n"); fflush(stderr);
429 if(verbose>1) printf(
"allocating memory for QR\n");
431 colNr=2;
if(fitVa==0) colNr--;
434 printf(
"QR_colNr := %d\n", colNr);
435 printf(
"QR_rowNr := %d\n", rowNr);
437 double *buf, **mat, *rhs, *sol, r2;
438 buf=(
double*)calloc(colNr*rowNr+rowNr+colNr,
sizeof(
double));
439 mat=(
double**)calloc(rowNr,
sizeof(
double*));
440 if(buf==NULL || mat==NULL) {
441 fprintf(stderr,
"Error: cannot allocate memory for QR\n");
447 for(
int i=0; i<rowNr; i++) mat[i]=buf+(i*colNr);
448 rhs=buf+(rowNr*colNr); sol=buf+(rowNr*colNr+rowNr);
454 if(verbose>0) {fprintf(stdout,
"computing QR pixel-by-pixel\n"); fflush(stdout);}
455 thresholded_nr=0; nosolution_nr=0;
460 bf_opt_nr=(
int*)malloc(bfNr*
sizeof(
int));
461 for(
int bi=0; bi<bf.
voiNr; bi++) bf_opt_nr[bi]=0.0;
463 for(pi=0; pi<img.
dimz; pi++) {
464 if(verbose>6) printf(
"computing plane %d\n", img.
planeNumber[pi]);
465 else if(img.
dimz>1 && verbose>0) {fprintf(stdout,
"."); fflush(stdout);}
466 for(yi=0; yi<img.
dimy; yi++) {
467 if(verbose>6 && yi==4*img.
dimy/10) printf(
" computing row %d\n", yi+1);
468 for(xi=0; xi<img.
dimx; xi++) {
469 if(verbose>6 && yi==4*img.
dimy/10 && xi==4*img.
dimx/10)
470 printf(
" computing column %d\n", xi+1);
474 for(
int i=0; i<rowNr; i++) {ct[i]=img.
m[pi][yi][xi][i];}
476 if(cti[rowNr-1]<threshold) {
477 flowimg.
m[pi][yi][xi][0]=0.0;
478 if(k2file[0]) k2img.
m[pi][yi][xi][0]=0.0;
479 if(vafile[0]) vaimg.
m[pi][yi][xi][0]=0.0;
480 if(vdfile[0]) vdimg.
m[pi][yi][xi][0]=0.0;
481 if(wssfile[0]) wssimg.
m[pi][yi][xi][0]=0.0;
482 if(errfile[0]) errimg.
m[pi][yi][xi][0]=0.0;
488 int bi_min=-1;
double r2_min=nan(
"");
489 for(
int bi=0; bi<bf.
voiNr; bi++) {
492 for(
int j=0; j<rowNr; j++) {
493 mat[j][0]=bf.
voi[bi].
y[j];
494 if(colNr>1) mat[j][1]=tac.
voi[0].
y[j];
499 if(
qrLSQ(mat, rhs, sol, rowNr, colNr, &r2)!=0)
continue;
501 if(isnan(r2_min) || r2_min>r2) {
502 r2_min=r2; bi_min=bi;
503 flowimg.
m[pi][yi][xi][0]=sol[0];
504 if(vafile[0] && colNr>1) vaimg.
m[pi][yi][xi][0]=sol[1];
507 if(isnan(r2_min)) {nosolution_nr++;
continue;}
508 else bf_opt_nr[bi_min]+=1;
510 if(flowimg.
m[pi][yi][xi][0]>flowMax) flowimg.
m[pi][yi][xi][0]=flowMax;
511 else if(flowimg.
m[pi][yi][xi][0]<0.0) flowimg.
m[pi][yi][xi][0]=0.0;
513 k2img.
m[pi][yi][xi][0]=bf.
voi[bi_min].
size;
514 if(k2img.
m[pi][yi][xi][0]>k2max) k2img.
m[pi][yi][xi][0]=k2max;
517 double f=flowimg.
m[pi][yi][xi][0]/k2img.
m[pi][yi][xi][0];
518 if(f>pWaterMax) f=pWaterMax;
519 vdimg.
m[pi][yi][xi][0]=f;
521 if(wssfile[0]) wssimg.
m[pi][yi][xi][0]=r2_min;
526 if(verbose>0) {fprintf(stdout,
"done.\n"); fflush(stdout);}
533 if(verbose>1) {fprintf(stdout,
"allocating memory for QR\n"); fflush(stdout);}
536 double rnorm_min, wss, f;
538 double **mem, **A, *B, X[MAX_N], *tau, *residual, RNORM, *chain;
539 double *qrweight, **wws, *ws, *wwschain, *ct, *cti;
541 M=bf.
frameNr; N=2;
if(fitVa==0) N--;
542 chain=(
double*)malloc((M+1)*N*bf.
voiNr *
sizeof(
double));
543 mem=(
double**)malloc(bf.
voiNr *
sizeof(
double*));
544 A=(
double**)malloc(M *
sizeof(
double*));
545 B=(
double*)malloc(M*
sizeof(
double));
546 residual=(
double*)malloc(M*
sizeof(
double));
547 qrweight=(
double*)malloc(M*
sizeof(
double));
548 wwschain=(
double*)malloc((M*N+2*M)*
sizeof(
double));
549 wws=(
double**)malloc(M *
sizeof(
double*));
550 if(chain==NULL || B==NULL || A==NULL || residual==NULL || qrweight==NULL || wwschain==NULL || wws==NULL)
552 fprintf(stderr,
"Error: out of memory.\n"); fflush(stderr);
558 for(bi=0; bi<bf.
voiNr; bi++) mem[bi]=chain+bi*(M+1)*N;
559 for(m=0; m<M; m++) wws[m]=wwschain+m*N;
564 if(img.
weight[m]<=1.0e-20) qrweight[m]=0.0;
565 else qrweight[m]=sqrt(img.
weight[m]);
570 if(verbose>1) {fprintf(stdout,
"calculating QR decomposition\n"); fflush(stdout);}
571 for(bi=0; bi<bf.
voiNr; bi++) {
574 for(m=0; m<M; m++) A[m]=mem[bi]+m*N;
579 A[m][0]=bf.
voi[bi].
y[m];
580 if(N>1) A[m][1]=tac.
voi[0].
y[m];
584 for(m=0; m<M; m++)
for(n=0; n<N; n++) A[m][n]*=qrweight[m];
590 free(chain); free(B); free(residual);
591 free(A); free(wwschain); free(wws); free(qrweight); free(mem);
603 if(verbose>0) {fprintf(stdout,
"computing QR pixel-by-pixel\n"); fflush(stdout);}
604 thresholded_nr=0; nosolution_nr=0;
608 bf_opt_nr=(
int*)malloc(bfNr*
sizeof(
int));
609 for(bi=0; bi<bf.
voiNr; bi++) bf_opt_nr[bi]=0.0;
611 for(pi=0; pi<img.
dimz; pi++) {
612 if(verbose>6) printf(
"computing plane %d\n", img.
planeNumber[pi]);
613 else if(img.
dimz>1 && verbose>0) {fprintf(stdout,
"."); fflush(stdout);}
614 for(yi=0; yi<img.
dimy; yi++) {
615 if(verbose>6 && yi==4*img.
dimy/10) printf(
" computing row %d\n", yi+1);
616 for(xi=0; xi<img.
dimx; xi++) {
617 if(verbose>6 && yi==4*img.
dimy/10 && xi==4*img.
dimx/10)
618 printf(
" computing column %d\n", xi+1);
622 for(m=0; m<M; m++) {ct[m]=img.
m[pi][yi][xi][m];}
626 if(verbose>6 && yi==4*img.
dimy/10 && xi==4*img.
dimx/10) {
627 printf(
" Pixel (%d,%d,%d), int= %f, threshold= %g\n", pi,yi,xi,cti[M-1],threshold);
630 printf(
" %02d:\t%g\t%g\n", m, img.
m[pi][yi][xi][m], tac.
voi[0].
y[m]);
633 if(cti[M-1]<threshold) {
634 flowimg.
m[pi][yi][xi][0]=0.0;
635 if(k2file[0]) k2img.
m[pi][yi][xi][0]=0.0;
636 if(vafile[0]) vaimg.
m[pi][yi][xi][0]=0.0;
637 if(vdfile[0]) vdimg.
m[pi][yi][xi][0]=0.0;
638 if(wssfile[0]) wssimg.
m[pi][yi][xi][0]=0.0;
639 if(errfile[0]) errimg.
m[pi][yi][xi][0]=0.0;
645 bi_min=-1; rnorm_min=1.0E80; p1=p2=p3=0.0;
646 for(bi=0; bi<bf.
voiNr; bi++) {
649 for(m=0; m<M; m++) {A[m]=mem[bi]+ m*N;}
654 B[m]=img.
m[pi][yi][xi][m];
660 ret=
qr_solve(A, M, N, tau, B, X, residual, &RNORM, wws, ws);
662 for(n=0; n<N; n++) X[n]=0.0;
666 if(RNORM<rnorm_min) {
667 rnorm_min=RNORM; bi_min=bi;
669 if(N>1) p2=X[1];
else p2=0.0;
673 if(rnorm_min>=1.0E60) nosolution_nr++;
674 else bf_opt_nr[bi_min]+=1;
676 if(verbose>6 && yi==4*img.
dimy/10 && xi==4*img.
dimx/10) {
677 printf(
" Pixel (%d,%d,%d), K1=%g Va=%g k2=%g\n", pi, yi, xi, p1, p2, p3);
682 for(m=0, wss=0.0; m<M; m++) {
683 f=p1*bf.
voi[bi_min].
y[m];
684 if(N>1) f+=p2*tac.
voi[0].
y[m];
685 f-=img.
m[pi][yi][xi][m];
689 if(p1>flowMax) flowimg.
m[pi][yi][xi][0]=flowMax;
690 else if(p1<0.0) flowimg.
m[pi][yi][xi][0]=0.0;
691 else flowimg.
m[pi][yi][xi][0]=p1;
692 if(vafile[0]) vaimg.
m[pi][yi][xi][0]=p2;
694 if(p3>k2max) k2img.
m[pi][yi][xi][0]=k2max;
695 else k2img.
m[pi][yi][xi][0]=p3;
698 f=p1/p3;
if(f>pWaterMax) f=pWaterMax;
699 vdimg.
m[pi][yi][xi][0]=f;
701 if(wssfile[0]) wssimg.
m[pi][yi][xi][0]=wss;
703 if(bi_min==0) ret=1;
else if(bi_min==bf.
voiNr-1) ret=2;
else ret=0;
704 errimg.
m[pi][yi][xi][0]=(float)ret;
710 if(verbose>0) {fprintf(stdout,
"done.\n"); fflush(stdout);}
711 if(verbose>1 || thresholded_nr>0) {
713 f=(double)thresholded_nr/((
double)(flowimg.
dimx*flowimg.
dimy*flowimg.
dimz));
714 f*=100.;
if(f<3.0) printf(
"%g%%", f);
else printf(
"%.0f%%", f);
715 printf(
" of pixels were not fitted due to threshold.\n");
716 if(verbose>2) printf(
"thresholded %d pixels\n", thresholded_nr);
719 if(verbose>1 || nosolution_nr>0) {
720 fprintf(stdout,
"no QR solution for %d pixels.\n", nosolution_nr); fflush(stdout);}
725 free(chain); free(B); free(residual); free(A); free(wwschain);
726 free(wws); free(qrweight); free(mem);
737 for(
int bi=0; bi<bf.
voiNr; bi++) sprintf(bf.
voi[bi].
place,
"%d", bf_opt_nr[bi]);
739 fprintf(stderr,
"Error in writing %s: %s\n", bfsfile,
dfterrmsg); fflush(stderr);
742 dftEmpty(&bf); free(bf_opt_nr);
return(11);
744 if(verbose>0) {fprintf(stdout,
"basis functions were written in %s\n", bfsfile); fflush(stdout);}
754 if(per_dl || per_gram) {
757 if(per_dl && per_gram) {
758 f=100.0/density; flowimg.
unit=IMGUNIT_ML_PER_DL_PER_MIN;
760 f=100.0; flowimg.
unit=IMGUNIT_ML_PER_DL_PER_MIN;
761 }
else if(per_gram) {
762 f=1.0/density; flowimg.
unit=IMGUNIT_ML_PER_ML_PER_MIN;
767 if(per_dl && vafile[0]) {
769 vaimg.
unit=IMGUNIT_ML_PER_DL;
776 if(verbose>1) {printf(
"Saving parametric images\n"); fflush(stdout);}
779 if(ret) {fprintf(stderr,
"Error: %s\n", flowimg.
statmsg); fflush(stderr);}
780 else if(verbose>0) {fprintf(stdout,
"Flow image %s saved.\n", flowfile); fflush(stdout);}
782 if(ret==0 && vafile[0]) {
784 if(ret) {fprintf(stderr,
"Error: %s\n", vaimg.
statmsg); fflush(stderr);}
785 else if(verbose>0) {fprintf(stdout,
"Va image %s saved.\n", vafile); fflush(stdout);}
787 if(ret==0 && vdfile[0]) {
789 if(ret) {fprintf(stderr,
"Error: %s\n", vdimg.
statmsg); fflush(stderr);}
790 else if(verbose>0) {fprintf(stdout,
"Vd image %s saved.\n", vdfile); fflush(stdout);}
792 if(ret==0 && k2file[0]) {
794 if(ret) {fprintf(stderr,
"Error: %s\n", k2img.
statmsg); fflush(stderr);}
795 else if(verbose>0) {fprintf(stdout,
"k2 image %s saved.\n", k2file); fflush(stdout);}
797 if(ret==0 && wssfile[0]) {
799 if(ret) {fprintf(stderr,
"Error: %s\n", wssimg.
statmsg); fflush(stderr);}
800 else if(verbose>0) {fprintf(stdout,
"WSS image %s saved.\n", wssfile); fflush(stdout);}
802 if(ret==0 && errfile[0]) {
804 if(ret) {fprintf(stderr,
"Error: %s\n", errimg.
statmsg); fflush(stderr);}
805 else if(verbose>0) {fprintf(stdout,
"Error image %s saved.\n", errfile); fflush(stdout);}
812 if(verbose>0) fprintf(stdout,
"parameter estimation time := %.1f [s]\n",
813 (
double)(fitFinish-fitStart) / CLOCKS_PER_SEC );
int bfRadiowater(DFT *input, DFT *tissue, DFT *bf, int bfNr, double k2min, double k2max, char *status, int verbose)
int atof_with_check(char *double_as_string, double *result_value)
double atof_dpi(char *str)
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 imgArithmConst(IMG *img, float operand, char operation, float ulimit, int verbose)
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.
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 qrLSQ(double **mat, double *rhs, double *sol, const unsigned int rows, const unsigned int cols, double *r2)
QR least-squares solving routine.
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 voiname[MAX_REGIONSUBNAME_LEN+1]
char place[MAX_REGIONSUBNAME_LEN+1]