9#include "tpcclibConfig.h"
28static char *info[] = {
29 "Make a map of cerebral blood flow from dynamic radiowater PET image,.",
30 "correcting for the PVE (Iida et al., 2000).",
32 "Currently only NIfTI format is supported.",
33 "Radioactivity concentrations in image and blood data must be in same units.",
34 "Maps of grey matter blood flow and alpha (PTF) are saved.",
36 "Usage: @P [options] imgfile btacfile fgmap agmap",
39 " -end=<Fit end time (sec)>",
40 " Use data from 0 to end time; by default, 300 s.",
42 " Pixels with AUC less than (threshold/100 x BTAC AUC) are set to zero.",
45 " Map of white matter alpha (PTF).",
46 " -Va=<filename | 0>",
47 " Va map is saved in units mL blood/mL PET volume, or, Va is fixed to 0.",
48 " -dT=<filename | delay>",
49 " Time delay map is saved, or, delay is fixed to given time in sec.",
52 "See also: imgflow, imgdelay",
54 "Keywords: image, blood flow, radiowater, brain",
97 int verbose=0;
if(status!=NULL) verbose=status->
verbose;
98 if(verbose>2) {printf(
"%s(inp, tis, %g, %g, %g, ...)\n", __func__, dtmin, dtmax, dtstep); fflush(stdout);}
106 printf(
" %d BTAC ", btac->
sampleNr);
if(btac->
isframe) printf(
"frames\n");
else printf(
"samples\n");
107 printf(
" %d TTAC ", ttac->
sampleNr);
if(ttac->
isframe) printf(
"frames\n");
else printf(
"samples\n");
113 double brange[2], trange[2];
114 if(
tacXRange(ttac, &trange[0], &trange[1])!=0 ||
tacXRange(btac, &brange[0], &brange[1])!=0) {
119 printf(
" TTAC range := %g - %g\n BTAC range := %g - %g\n",
120 trange[0], trange[1], brange[0], brange[1]);
123 if(isfinite(dtstep) && dtstep>0.0) {
124 double r=dtmax-dtmin;
125 if(!(r>5.0*dtstep)) {
135 if((brange[1]+dtmin)<0.95*trange[1]) {
136 if(verbose>2) printf(
"BTAC tmax=%g TTAC tmax=%g dtmin=%g\n", brange[1], trange[1], dtmin);
143 if(b1==NULL && b2==NULL && b3==NULL) {
144 if(verbose>2) {printf(
" no output required\n"); fflush(stdout);}
153 if(verbose>3) {printf(
" integrating BTAC samples\n"); fflush(stdout);}
158 if(verbose>3) {printf(
" integrating BTAC frames\n"); fflush(stdout);}
163 if(verbose>2) {printf(
" -> returns %d\n", ret); fflush(stdout);}
169 if(verbose>3) {printf(
" room for output\n"); fflush(stdout);}
186 if(verbose>3) {printf(
" interpolating BTAC\n"); fflush(stdout);}
188 for(
int ci=0; ci<b1->
tacNr; ci++) {
189 double dt=0.0;
if(dtNr>1) dt=dtmin+dtstep*(double)ci;
191 for(
int ti=0; ti<btac->
sampleNr; ti++) dx[ti]=btac->
x[ti]+dt;
201 if(b2!=NULL && !ret) {
202 if(verbose>3) {printf(
" interpolating BTAC integral\n"); fflush(stdout);}
204 for(
int ci=0; ci<b2->
tacNr; ci++) {
205 double dt=0.0;
if(dtNr>1) dt=dtmin+dtstep*(double)ci;
207 for(
int ti=0; ti<btac->
sampleNr; ti++) dx[ti]=ix[ti]+dt;
217 if(b3!=NULL && !ret) {
218 if(verbose>3) {printf(
" interpolating BTAC 2nd integral\n"); fflush(stdout);}
220 for(
int ci=0; ci<b3->
tacNr; ci++) {
221 double dt=0.0;
if(dtNr>1) dt=dtmin+dtstep*(double)ci;
223 for(
int ti=0; ti<btac->
sampleNr; ti++) dx[ti]=ix[ti]+dt;
234 if(verbose>2) {printf(
" -> returns %d\n", ret); fflush(stdout);}
248int main(
int argc,
char **argv)
250 int ai, help=0, version=0, verbose=1;
252 char imgfile[FILENAME_MAX], btacfile[FILENAME_MAX];
253 char fgfile[FILENAME_MAX], agfile[FILENAME_MAX], fwfile[FILENAME_MAX], awfile[FILENAME_MAX];
254 char vafile[FILENAME_MAX], dtfile[FILENAME_MAX], ssfile[FILENAME_MAX];
255 char llsqfile[FILENAME_MAX];
256 char kmapfile[FILENAME_MAX];
257 double fixedVa=nan(
"");
258 double fixeddT=nan(
"");
259 double endtime=300.0;
260 double endtimemin=120.0;
261 double dtrange[2]={-10.,+50.};
263 float calcThreshold=0.01;
272 if(argc==1) {
tpcPrintUsage(argv[0], info, stderr);
return(1);}
273 imgfile[0]=btacfile[0]=(char)0;
274 fgfile[0]=agfile[0]=vafile[0]=awfile[0]=fwfile[0]=dtfile[0]=ssfile[0]=(char)0;
275 llsqfile[0]=kmapfile[0]=(char)0;
277 for(ai=1; ai<argc; ai++)
if(*argv[ai]==
'-') {
279 char *cptr=argv[ai]+1;
if(*cptr==
'-') cptr++;
if(!*cptr)
continue;
280 if(strncasecmp(cptr,
"END=", 4)==0) {
281 ret=
atofCheck(cptr+4, &endtime);
if(!ret && endtime>0.0)
continue;
282 }
else if(strncasecmp(cptr,
"MIN=", 4)==0) {
283 ret=
atofCheck(cptr+4, &dtrange[0]);
if(!ret && isfinite(dtrange[0]))
continue;
284 }
else if(strncasecmp(cptr,
"MAX=", 4)==0) {
285 ret=
atofCheck(cptr+4, &dtrange[1]);
if(!ret && isfinite(dtrange[1]))
continue;
286 }
else if(strncasecmp(cptr,
"THR=", 4)==0) {
288 if(!ret && v<100.0) {calcThreshold=(float)(0.01*v);
continue;}
289 }
else if(strncasecmp(cptr,
"AW=", 3)==0) {
290 strlcpy(awfile, cptr+3, FILENAME_MAX);
if(strlen(awfile))
continue;
291 }
else if(strncasecmp(cptr,
"FW=", 3)==0) {
292 strlcpy(fwfile, cptr+3, FILENAME_MAX);
if(strlen(fwfile))
continue;
293 }
else if(strcasecmp(cptr,
"VA=0")==0) {
294 fixedVa=0.0;
continue;
295 }
else if(strncasecmp(cptr,
"VA=", 3)==0) {
296 strlcpy(vafile, cptr+3, FILENAME_MAX);
if(strlen(vafile))
continue;
297 }
else if(strncasecmp(cptr,
"DT=", 3)==0) {
299 if(!ret && v>=-50.0 && v<=50.0) {fixeddT=v;
continue;}
300 strlcpy(dtfile, cptr+3, FILENAME_MAX);
if(strlen(dtfile))
continue;
301 }
else if(strncasecmp(cptr,
"SS=", 3)==0) {
302 strlcpy(ssfile, cptr+3, FILENAME_MAX);
if(strlen(ssfile))
continue;
303 }
else if(strncasecmp(cptr,
"LLSQ=", 5)==0) {
304 strlcpy(llsqfile, cptr+5, FILENAME_MAX);
if(strlen(llsqfile))
continue;
305 }
else if(strncasecmp(cptr,
"KMAP=", 5)==0) {
306 strlcpy(kmapfile, cptr+5, FILENAME_MAX);
if(strlen(kmapfile))
continue;
308 fprintf(stderr,
"Error: invalid option '%s'.\n", argv[ai]);
313 if(help==2) {
tpcHtmlUsage(argv[0], info,
"");
return(0);}
318 if(ai<argc)
strlcpy(imgfile, argv[ai++], FILENAME_MAX);
319 if(ai<argc)
strlcpy(btacfile, argv[ai++], FILENAME_MAX);
320 if(ai<argc)
strlcpy(fgfile, argv[ai++], FILENAME_MAX);
321 if(ai<argc)
strlcpy(agfile, argv[ai++], FILENAME_MAX);
322 if(ai<argc) {fprintf(stderr,
"Error: too many arguments: '%s'.\n", argv[ai]);
return(1);}
324 if(!agfile[0]) {
tpcPrintUsage(argv[0], info, stdout);
return(1);}
327 if(endtime<endtimemin) {
328 fprintf(stderr,
"Error: too short fit time set with option -end.\n");
331 if(isfinite(fixeddT)) {
332 dtrange[0]=dtrange[1]=fixeddT;
335 if(dtrange[0]>dtrange[1]) {
int i=dtrange[0]; dtrange[0]=dtrange[1]; dtrange[1]=i;}
336 if((dtrange[1]-dtrange[0])>180.) {
337 fprintf(stderr,
"Error: too wide delay range.\n");
339 }
else if((dtrange[1]-dtrange[0])>120.) {
340 fprintf(stderr,
"Warning: large delay range.\n");
341 }
else if((dtrange[1]-dtrange[0])<4.) {
342 fprintf(stderr,
"Error: too short delay range.\n");
349 printf(
"imgfile := %s\n", imgfile);
350 printf(
"btacfile := %s\n", btacfile);
351 printf(
"fgfile := %s\n", fgfile);
352 printf(
"agfile := %s\n", agfile);
353 printf(
"endtime := %g s\n", endtime);
354 printf(
"delay_range := %g - %g s\n", dtrange[0], dtrange[1]);
355 printf(
"delay_step_size := %g s\n", dtstep);
356 printf(
"threshold := %g\n", calcThreshold);
357 if(awfile[0]) printf(
"awfile := %s\n", awfile);
358 if(fwfile[0]) printf(
"fwfile := %s\n", fwfile);
359 if(vafile[0]) printf(
"vafile := %s\n", vafile);
360 if(isfinite(fixedVa)) printf(
"fixed_Va := %g\n", fixedVa);
361 if(dtfile[0]) printf(
"dtfile := %s\n", dtfile);
362 if(isfinite(fixeddT)) printf(
"fixed_dT := %g\n", fixeddT);
363 if(ssfile[0]) printf(
"ssfile := %s\n", ssfile);
364 if(llsqfile[0]) printf(
"llsqfile := %s\n", llsqfile);
365 if(kmapfile[0]) printf(
"kmapfile := %s\n", kmapfile);
377 if(verbose>1) printf(
"reading %s\n", btacfile);
379 ret=
tacRead(&btac, btacfile, &status);
381 fprintf(stderr,
"Error: %s (%s)\n",
errorMsg(status.
error), btacfile);
386 printf(
"tacNr := %d\n", btac.
tacNr);
387 printf(
"sampleNr := %d\n", btac.
sampleNr);
390 printf(
"isframe := %d\n", btac.
isframe);
400 if(verbose>1) {printf(
"reading %s\n", imgfile); fflush(stdout);}
402 ret=
imgRead(&img, imgfile, &status);
405 fprintf(stderr,
"Error: %s (%s)\n",
errorMsg(status.
error), imgfile); fflush(stderr);
409 if(verbose>0) fprintf(stderr,
"Warning: missing pixel values.\n");
413 fprintf(stderr,
"Error: invalid sample times in %s\n", imgfile); fflush(stderr);
416 if(verbose>1) printf(
"Image range: %g - %g\n", ixmin, ixmax);
418 if(ixmax<endtimemin) {
419 fprintf(stderr,
"Error: image time range is too short.\n");
422 if(ixmax<endtime) endtime=ixmax;
429 if(verbose>0) fprintf(stderr,
"Warning: missing BTAC time units.\n");
432 fprintf(stderr,
"Error: invalid sample times in %s\n", btacfile); fflush(stderr);
438 fprintf(stderr,
"Warning: assuming BTAC sample times are in units %s.\n",
unitName(guessedUnit));
439 btac.
tunit=guessedUnit;
442 fprintf(stderr,
"Error: %s (%s)\n",
errorMsg(status.
error), btacfile); fflush(stderr);
452 fprintf(stderr,
"Error: invalid sample times in %s\n", btacfile); fflush(stderr);
455 if(verbose>1) printf(
"BTAC range: %g - %g\n", bxmin, bxmax);
461 fprintf(stderr,
"Warning: assuming image concentrations are in units %s.\n",
unitName(img.
cunit));
465 fprintf(stderr,
"Warning: assuming BTAC concentrations are in units %s.\n",
unitName(img.
cunit));
477 if(verbose>1) {printf(
"checking time range\n"); fflush(stdout);}
479 if(btac.
sampleNr<5) {fprintf(stderr,
"Error: BTAC has too few samples.\n"); ret++;}
480 if(img.
dimt<5) {fprintf(stderr,
"Error: image has too few frames.\n"); ret++;}
481 if(bxmax<endtimemin) {fprintf(stderr,
"Error: BTAC time range is too short.\n"); ret++;}
482 if(ixmax<endtimemin) {fprintf(stderr,
"Error: image time range is too short.\n"); ret++;}
483 if(dtrange[0]<0.0 && bxmax<(endtime+dtrange[0])) {
485 if(endtime<endtimemin) {
486 fprintf(stderr,
"Error: BTAC does not extend to required end time.\n"); ret++;}
489 for(
int i=0; i<img.
dimt; i++)
if(img.
x[i]<=endtime) frameNr++;
490 if(frameNr<5) {fprintf(stderr,
"Error: image has too few frames in fit time range.\n"); ret++;}
497 fprintf(stderr,
"Error: %s\n",
errorMsg(ret));
505 if(tacInputForLLSQ(&btac, &ttac, dtrange[0], dtrange[1], dtstep, &inp, &inp2, &inp3, &status)) {
511 printf(
"writing delayed, interpolated, and integrated BTACs\n");
512 FILE *fp=fopen(
"imgflowb_input1.tac",
"w");
515 fp=fopen(
"imgflowb_input2.tac",
"w");
518 fp=fopen(
"imgflowb_input3.tac",
"w");
525 if(verbose>1) {printf(
"allocating memory for LLSQ\n"); fflush(stdout);}
528 double **llsq_a=(
double**)malloc(llsq_n*
sizeof(
double*));
529 double *llsq_mat=(
double*)malloc((llsq_n*llsq_m)*
sizeof(
double));
530 if(llsq_a==NULL || llsq_mat==NULL) {
531 fprintf(stderr,
"Error: cannot allocate memory for LLSQ.\n");
535 for(
int ni=0; ni<llsq_n; ni++) llsq_a[ni]=llsq_mat+ni*llsq_m;
536 double llsq_b[llsq_m], llsq_x[llsq_n], llsq_wp[llsq_n], llsq_zz[llsq_m];
543 if(verbose>1) {printf(
"preparing LLSQ parameter map\n"); fflush(stdout);}
546 fprintf(stderr,
"Error: cannot allocate memory\n"); fflush(stderr);
548 free(llsq_a); free(llsq_mat);
556 double thrs=
tacAUC(&btac, 0, 0.0, img.
x2[frameNr-1], NULL);
564 if(verbose>0) {printf(
"processing %llu image pixels\n", pxlNr); fflush(stdout);}
565 for(
int zi=0; zi<img.
dimz; zi++) {
566 if(img.
dimz>2 && verbose>0) {fprintf(stdout,
"."); fflush(stdout);}
567 for(
int yi=0; yi<img.
dimy; yi++)
for(
int xi=0; xi<img.
dimx; xi++) {
568 for(
int pi=0; pi<map.
dimt; pi++) map.
m[zi][yi][xi][pi]=0.0;
569 for(
int mi=0; mi<llsq_m; mi++) ttac.
c[0].
y[mi]=img.
m[zi][yi][xi][mi];
573 if(ttac.
c[1].
y[llsq_m-1]<thrs)
continue;
576 double r2Best=nan(
"");
577 for(
int di=0; di<inp.
tacNr; di++) {
579 for(
int mi=0; mi<llsq_m; mi++)
580 llsq_b[mi]=img.
m[zi][yi][xi][mi];
581 for(
int mi=0; mi<llsq_m; mi++) {
582 if(isfinite(fixedVa))
585 llsq_mat[mi]=inp.
c[di].
y[mi];
586 llsq_mat[mi+1*llsq_m]=inp2.
c[di].
y[mi];
587 llsq_mat[mi+2*llsq_m]=-ttac.
c[1].
y[mi];
588 llsq_mat[mi+3*llsq_m]=inp3.
c[di].
y[mi];
589 llsq_mat[mi+4*llsq_m]=-ttac.
c[2].
y[mi];
593 int ret=
nnls(llsq_a, llsq_m, llsq_n, llsq_b, llsq_x, &r2, llsq_wp, llsq_zz, indexp);
595 if((isfinite(r2) && !isfinite(r2Best)) || r2<r2Best) {
598 for(
int pi=0; pi<llsq_n; pi++) map.
m[zi][yi][xi][pi]=llsq_x[pi];
599 map.
m[zi][yi][xi][llsq_n]=inp.
c[di].
size;
600 map.
m[zi][yi][xi][llsq_n+1]=r2;
603 if(diBest>=0) okNr++;
606 if(img.
dimz>2 && verbose>0) {fprintf(stdout,
"\n"); fflush(stdout);}
607 free(llsq_a); free(llsq_mat);
609 fprintf(stderr,
"Error: no pixels fitted successfully\n"); fflush(stderr);
614 if(verbose>0) printf(
" LLSQ successful in %lld/%lld pixels\n", okNr, pxlNr);
622 if(verbose>1) printf(
" writing %s\n", llsqfile);
624 fprintf(stderr,
"Error: %s\n",
errorMsg(status.
error)); fflush(stderr);
628 if(verbose>0) {printf(
" %s written.\n", llsqfile); fflush(stdout);}
632 fprintf(stderr,
"Error: cannot allocate memory\n"); fflush(stderr);
637 if(verbose>1) printf(
" writing %s\n", dtfile);
639 for(
int zi=0; zi<pimg.
dimz; zi++)
for(
int yi=0; yi<pimg.
dimy; yi++)
for(
int xi=0; xi<pimg.
dimx; xi++) {
640 pimg.
m[zi][yi][xi][0]=map.
m[zi][yi][xi][map.
dimt-2];
643 fprintf(stderr,
"Error: %s\n",
errorMsg(status.
error)); fflush(stderr);
647 if(verbose>0) {printf(
" %s written.\n", dtfile); fflush(stdout);}
650 if(verbose>1) printf(
" writing %s\n", ssfile);
652 for(
int zi=0; zi<pimg.
dimz; zi++)
for(
int yi=0; yi<pimg.
dimy; yi++)
for(
int xi=0; xi<pimg.
dimx; xi++) {
653 pimg.
m[zi][yi][xi][0]=map.
m[zi][yi][xi][map.
dimt-1];
656 fprintf(stderr,
"Error: %s\n",
errorMsg(status.
error)); fflush(stderr);
660 if(verbose>0) {printf(
" %s written.\n", ssfile); fflush(stdout);}
663 if(verbose>1) printf(
" writing %s\n", vafile);
665 for(
int zi=0; zi<pimg.
dimz; zi++)
for(
int yi=0; yi<pimg.
dimy; yi++)
for(
int xi=0; xi<pimg.
dimx; xi++) {
666 pimg.
m[zi][yi][xi][0]=map.
m[zi][yi][xi][0];
669 fprintf(stderr,
"Error: %s\n",
errorMsg(status.
error)); fflush(stderr);
673 if(verbose>0) {printf(
" %s written.\n", vafile); fflush(stdout);}
678 for(
int zi=0; zi<pimg.
dimz; zi++)
for(
int yi=0; yi<pimg.
dimy; yi++)
for(
int xi=0; xi<pimg.
dimx; xi++) {
679 double p[llsq_n];
for(
int i=0; i<llsq_n; i++) p[i]=map.
m[zi][yi][xi][i];
680 double k2a=(p[2]+sqrt(p[2]*p[2] - 4.0*p[4]))/2.0;
681 double k2b=(p[2]-sqrt(p[2]*p[2] - 4.0*p[4]))/2.0;
682 double K1a=(k2a*(p[1]-p[0]*p[2]) - p[3] + p[0]*p[4])/sqrt(p[2]*p[2]-4.0*p[4]);
683 double K1b=(p[3] - p[0]*p[4] - k2b*(p[1]-p[0]*p[2]))/sqrt(p[2]*p[2]-4.0*p[4]);
686 map.
m[zi][yi][xi][1]=60.*K1a;
687 map.
m[zi][yi][xi][2]=60.*k2a;
688 map.
m[zi][yi][xi][3]=60.*K1b;
689 map.
m[zi][yi][xi][4]=60.*k2b;
693 if(verbose>1) printf(
" writing %s\n", kmapfile);
695 fprintf(stderr,
"Error: %s\n",
errorMsg(status.
error)); fflush(stderr);
699 if(verbose>0) {printf(
" %s written.\n", kmapfile); fflush(stdout);}
704 if(verbose>1) printf(
" writing %s\n", fgfile);
706 for(
int zi=0; zi<pimg.
dimz; zi++)
for(
int yi=0; yi<pimg.
dimy; yi++)
for(
int xi=0; xi<pimg.
dimx; xi++) {
707 pimg.
m[zi][yi][xi][0]=pg*map.
m[zi][yi][xi][2];
708 if(pimg.
m[zi][yi][xi][0]>1.0) pimg.
m[zi][yi][xi][0]=1.0;
711 fprintf(stderr,
"Error: %s\n",
errorMsg(status.
error)); fflush(stderr);
715 if(verbose>0) {printf(
" %s written.\n", fgfile); fflush(stdout);}
718 if(verbose>1) printf(
" writing %s\n", fwfile);
720 for(
int zi=0; zi<pimg.
dimz; zi++)
for(
int yi=0; yi<pimg.
dimy; yi++)
for(
int xi=0; xi<pimg.
dimx; xi++) {
721 pimg.
m[zi][yi][xi][0]=pw*map.
m[zi][yi][xi][4];
722 if(pimg.
m[zi][yi][xi][0]>1.0) pimg.
m[zi][yi][xi][0]=1.0;
725 fprintf(stderr,
"Error: %s\n",
errorMsg(status.
error)); fflush(stderr);
729 if(verbose>0) {printf(
" %s written.\n", fwfile); fflush(stdout);}
733 if(verbose>1) printf(
" writing %s\n", agfile);
735 for(
int zi=0; zi<pimg.
dimz; zi++)
for(
int yi=0; yi<pimg.
dimy; yi++)
for(
int xi=0; xi<pimg.
dimx; xi++) {
736 pimg.
m[zi][yi][xi][0]=(map.
m[zi][yi][xi][1]/map.
m[zi][yi][xi][2])/pg;
737 if(!isfinite(pimg.
m[zi][yi][xi][0])) pimg.
m[zi][yi][xi][0]=0.0;
738 if(pimg.
m[zi][yi][xi][0]<0.0) pimg.
m[zi][yi][xi][0]=0.0;
739 if(pimg.
m[zi][yi][xi][0]>1.0) pimg.
m[zi][yi][xi][0]=1.0;
742 fprintf(stderr,
"Error: %s\n",
errorMsg(status.
error)); fflush(stderr);
746 if(verbose>0) {printf(
" %s written.\n", agfile); fflush(stdout);}
749 if(verbose>1) printf(
" writing %s\n", awfile);
751 for(
int zi=0; zi<pimg.
dimz; zi++)
for(
int yi=0; yi<pimg.
dimy; yi++)
for(
int xi=0; xi<pimg.
dimx; xi++) {
752 pimg.
m[zi][yi][xi][0]=(map.
m[zi][yi][xi][3]/map.
m[zi][yi][xi][4])/pw;
753 if(!isfinite(pimg.
m[zi][yi][xi][0])) pimg.
m[zi][yi][xi][0]=0.0;
754 if(pimg.
m[zi][yi][xi][0]<0.0) pimg.
m[zi][yi][xi][0]=0.0;
755 if(pimg.
m[zi][yi][xi][0]>1.0) pimg.
m[zi][yi][xi][0]=1.0;
758 fprintf(stderr,
"Error: %s\n",
errorMsg(status.
error)); fflush(stderr);
762 if(verbose>0) {printf(
" %s written.\n", awfile); fflush(stdout);}
int atofCheck(const char *s, double *v)
int imgXUnitConvert(IMG *img, const int u)
void imgContents(IMG *img, FILE *fp)
unsigned long long imgNaNs(IMG *img, int fix)
int imgAllocate(IMG *img, const unsigned int dimz, const unsigned int dimy, const unsigned int dimx, const unsigned int dimt, TPCSTATUS *status)
int imgXRange(IMG *img, double *xmin, double *xmax)
int imgRead(IMG *img, const char *fname, TPCSTATUS *status)
int imgWrite(IMG *img, const char *fname, TPCSTATUS *status)
int liIntegrateFE(double *x1, double *x2, double *y, int nr, double *ie, double *iie, const int verbose)
Linear integration of PET TAC to frame end times.
int liIntegrate(double *x, double *y, const int nr, double *yi, const int se, const int verbose)
Linear integration of TAC with trapezoidal method.
int liIntegratePET(double *x1, double *x2, double *y, int nr, double *ie, double *iie, const int verbose)
Calculate PET TAC AUC from start to each time frame, as averages during each frame.
int liInterpolate(double *x, double *y, const int nr, double *newx, double *newy, double *newyi, double *newyii, const int newnr, const int se, const int ee, const int verbose)
Linear interpolation and/or integration with trapezoidal method.
int liInterpolateForPET(double *x, double *y, const int nr, double *newx1, double *newx2, double *newy, double *newyi, double *newyii, const int newnr, const int se, const int ee, const int verbose)
Linear TAC interpolation and/or integration to PET frames.
double tacAUC(TAC *tac, int ti, double t1, double t2, TPCSTATUS *status)
Calculates TAC AUC from t1 to t2.
int tacAllocateWithIMG(TAC *tac, IMG *img, int tacNr)
Allocate TAC based on data in IMG.
int nnls(double **a, int m, int n, double *b, double *x, double *rnorm, double *wp, double *zzp, int *indexp)
int tpcProcessStdOptions(const char *s, int *print_usage, int *print_version, int *verbose_level)
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)
void statusInit(TPCSTATUS *s)
char * errorMsg(tpcerror e)
void statusSet(TPCSTATUS *s, const char *func, const char *srcfile, int srcline, tpcerror error)
size_t strlcpy(char *dst, const char *src, size_t dstsize)
int verbose
Verbose level, used by statusPrint() etc.
tpcerror error
Error code.
int tacDuplicate(TAC *tac1, TAC *tac2)
Make a duplicate of TAC structure.
int tacAllocateMore(TAC *tac, int tacNr)
int tacRead(TAC *d, const char *fname, TPCSTATUS *status)
char * tacFormattxt(tacformat c)
int tacWrite(TAC *tac, FILE *fp, tacformat format, int extra, TPCSTATUS *status)
int tacYUnitConvert(TAC *tac, const int u, TPCSTATUS *status)
int tacXUnitConvert(TAC *tac, const int u, TPCSTATUS *status)
int tacSetX(TAC *d, TPCSTATUS *status)
Set TAC x values based on x1 and x2 values, or guess x1 and x2 values based on x values.
int tacXRange(TAC *d, double *xmin, double *xmax)
Get the range of x values (times) in TAC structure.
Header file for library libtpccsv.
Header file for library libtpcextensions.
@ UNIT_ML_PER_ML_MIN
mL/(mL*min)
@ UNIT_UNKNOWN
Unknown unit.
@ TPCERROR_INVALID_XRANGE
Invalid sample time range.
@ TPCERROR_INVALID_VALUE
Invalid value.
@ TPCERROR_FAIL
General error.
@ TPCERROR_TOO_FEW
File contains too few samples.
char * unitName(int unit_code)
Header file for library libtpcift.
Header file for libtpcimage.
Header file for libtpcli.
Header file for libtpclinopt.
Header file for library libtpctac.
@ TAC_FORMAT_PMOD
PMOD TAC format.
Header file for libtpctacimg.
int tacimgXMatch(TAC *tac, IMG *img)
int tacimgXCopy(TAC *tac, IMG *img)
Header file for libtpctacmod.