8#include "tpcclibConfig.h"
23static char *info[] = {
24 "Iterative deconvolution method for partial volume correction of PET images",
25 "in ECAT 6.3, 7.x, and Analyze 7.5 and NIfTI-1 formats.",
26 "Not for production use!",
28 "Usage: @P [Options] image FWHMxy FWHMz pvcimage",
32 " Use van Cittert or Richardson-Lucy method; VC by default.",
34 " Include reblurring step; by default yes.",
36 " Converging rate parameter (0.0<alpha<10.0).",
38 " Upper limit for deconvolved image as a factor of image maximum value.",
40 " Maximum number of iterations.",
42 " Limit for termination (0.0<term<1.0).",
45 "FWHM can be given in mm (default) or in pixels. If image file does not",
46 "contain correct pixel sizes, then FWHM must be entered in pixels.",
48 "Example: FWHM in mm",
49 " @P i5998dy1.v 2.5 2.65 i5998dy1_pvc.v",
50 "Example: FWHM in pixels",
51 " @P i5998dy1.v 2.1pxl 1.7pxl i5998dy1_pvc.v",
53 "See also: imgfiltg, imgbox, imgmask",
55 "Keywords: image, PVC",
112 printf(
"%s(i, %g, %g, %d, %g, %g, %d, %g, ...)\n",
113 __func__, FWHMxy, FWHMz, reblur, betaFactor, alpha, maxIterNr, termLimit);
116 if(img1==NULL || img2==NULL)
return(1);
118 if(!(FWHMxy>0.0))
return(3);
119 if(img1->
dimz<2) FWHMz=0.0;
120 if(!(betaFactor>0.0)) betaFactor=1.4;
121 if(maxIterNr<1) maxIterNr=25;
122 if(!(alpha>0.0)) alpha=1.6;
123 if(!(termLimit>0.0) || termLimit>=1) termLimit=0.005;
126 float SDxy=FWHMxy/2.355;
127 float SDz=FWHMz/2.355;
129 int x, dimx=img1->
dimx;
130 int y, dimy=img1->
dimy;
131 int z, dimz=img1->
dimz;
132 int t, dimt=img1->
dimt;
137 if(ret)
return(10+ret);
151 for(t=0; t<dimt; t++) {
152 if(verbose>2 && dimt>1) {printf(
" frame %d\n", 1+t); fflush(stdout);}
155 for(z=0; z<dimz; z++)
for(y=0; y<dimy; y++)
for(x=0; x<dimx; x++)
156 tkm.
m[z][y][x][0]=img1->
m[z][y][x][t];
161 if(!(omax>omin) || !(omax>0.0))
continue;
162 double beta=betaFactor*omax;
164 printf(
" image_min := %g\n image_max := %g\n", omin, omax);
165 printf(
" beta := %g\n", beta);
171 for(iterNr=0; iterNr<maxIterNr; iterNr++) {
172 if(verbose>3) {printf(
" iteration %d\n", 1+iterNr); fflush(stdout);}
174 for(z=0; z<dimz; z++)
for(y=0; y<dimy; y++)
for(x=0; x<dimx; x++)
175 cm.
m[z][y][x][0]=tkm.
m[z][y][x][0];
177 if(ret) {ret+=100;
break;}
179 for(z=0; z<dimz; z++)
for(y=0; y<dimy; y++)
for(x=0; x<dimx; x++) {
180 float f=img1->
m[z][y][x][t]/cm.
m[z][y][x][0];
182 if(fabs(img1->
m[z][y][x][t])<1.0E-06) f=0.0;
else f=1.0;
189 if(ret) {ret+=200;
break;}
193 double dsum=0.0, psum=0.0;
194 for(z=0; z<dimz; z++)
for(y=0; y<dimy; y++)
for(x=0; x<dimx; x++) {
195 double prev=tkm.
m[z][y][x][0];
196 tkm.
m[z][y][x][0]*=cm.
m[z][y][x][0];
197 if(tkm.
m[z][y][x][0]<=0.0 && img1->
m[z][y][x][t]>0.0)
198 tkm.
m[z][y][x][0]=0.01*img1->
m[z][y][x][t];
199 if(tkm.
m[z][y][x][0]>beta) tkm.
m[z][y][x][0]=beta;
200 double d=tkm.
m[z][y][x][0]-prev;
201 dsum+=d*d; psum+=prev*prev;
203 double dssqr=sqrt(dsum)/sqrt(psum);
if(verbose>4) printf(
" dssqr := %g\n", dssqr);
204 if(dssqr<termLimit)
break;
207 if(verbose>3) {printf(
" iterNr := %d\n", (iterNr>=maxIterNr?maxIterNr:1+iterNr)); fflush(stdout);}
210 for(z=0; z<dimz; z++)
for(y=0; y<dimy; y++)
for(x=0; x<dimx; x++)
211 img2->
m[z][y][x][t]=tkm.
m[z][y][x][0];
259 printf(
"%s(i, %g, %g, %d, %g, %g, %d, %g, ...)\n",
260 __func__, FWHMxy, FWHMz, reblur, betaFactor, alpha, maxIterNr, termLimit);
263 if(img1==NULL || img2==NULL)
return(1);
265 if(!(FWHMxy>0.0))
return(3);
266 if(img1->
dimz<2) FWHMz=0.0;
267 if(!(betaFactor>0.0)) betaFactor=1.4;
268 if(maxIterNr<1) maxIterNr=25;
269 if(!(alpha>0.0)) alpha=1.6;
270 if(!(termLimit>0.0) || termLimit>=1) termLimit=0.005;
273 float SDxy=FWHMxy/2.355;
274 float SDz=FWHMz/2.355;
276 int x, dimx=img1->
dimx;
277 int y, dimy=img1->
dimy;
278 int z, dimz=img1->
dimz;
279 int t, dimt=img1->
dimt;
284 if(ret)
return(10+ret);
298 for(t=0; t<dimt; t++) {
299 if(verbose>2 && dimt>1) {printf(
" frame %d\n", 1+t); fflush(stdout);}
302 for(z=0; z<dimz; z++)
for(y=0; y<dimy; y++)
for(x=0; x<dimx; x++)
303 tkm.
m[z][y][x][0]=img1->
m[z][y][x][t];
308 if(!(omax>omin) || !(omax>0.0))
continue;
309 double beta=betaFactor*omax;
311 printf(
" image_min := %g\n image_max := %g\n", omin, omax);
312 printf(
" beta := %g\n", beta);
318 for(iterNr=0; iterNr<maxIterNr; iterNr++) {
319 if(verbose>3) {printf(
" iteration %d\n", 1+iterNr); fflush(stdout);}
321 for(z=0; z<dimz; z++)
for(y=0; y<dimy; y++)
for(x=0; x<dimx; x++)
322 cm.
m[z][y][x][0]=tkm.
m[z][y][x][0];
324 if(ret) {ret+=100;
break;}
326 for(z=0; z<dimz; z++)
for(y=0; y<dimy; y++)
for(x=0; x<dimx; x++)
327 cm.
m[z][y][x][0]=img1->
m[z][y][x][t]-cm.
m[z][y][x][0];
331 if(ret) {ret+=200;
break;}
335 double dsum=0.0, psum=0.0;
336 for(z=0; z<dimz; z++)
for(y=0; y<dimy; y++)
for(x=0; x<dimx; x++) {
337 double r=alpha*(1.0 - (2.0/beta)*fabs(tkm.
m[z][y][x][0] - beta/2.0));
338 double d=r*cm.
m[z][y][x][0]; dsum+=d*d; psum+=tkm.
m[z][y][x][0]*tkm.
m[z][y][x][0];
339 tkm.
m[z][y][x][0]+=r*cm.
m[z][y][x][0];
341 double dssqr=sqrt(dsum)/sqrt(psum);
if(verbose>4) printf(
" dssqr := %g\n", dssqr);
342 if(dssqr<termLimit)
break;
345 if(verbose>3) {printf(
" iterNr := %d\n", (iterNr>=maxIterNr?maxIterNr:1+iterNr)); fflush(stdout);}
348 for(z=0; z<dimz; z++)
for(y=0; y<dimy; y++)
for(x=0; x<dimx; x++)
349 img2->
m[z][y][x][t]=tkm.
m[z][y][x][0];
363int main(
int argc,
char **argv)
365 int ai, help=0, version=0, verbose=1;
366 char petfile[FILENAME_MAX], outfile[FILENAME_MAX];
367 double FWHMxy=nan(
""), FWHMz=nan(
"");
368 int FWHMxyUnit=1, FWHMzUnit=1;
371 double betaFactor=1.4;
374 double termLimit=0.01;
380 if(argc==1) {
tpcPrintUsage(argv[0], info, stderr);
return(1);}
381 petfile[0]=outfile[0]=(char)0;
383 for(ai=1; ai<argc; ai++)
if(*argv[ai]==
'-') {
385 char *cptr=argv[ai]+1;
if(*cptr==
'-') cptr++;
if(cptr==NULL)
continue;
386 if(strncasecmp(cptr,
"METHOD=", 7)==0) {
388 if(strncasecmp(cptr,
"VC", 1)==0) {method=0;
continue;}
389 if(strncasecmp(cptr,
"RL", 1)==0) {method=1;
continue;}
390 }
else if(strncasecmp(cptr,
"REBLUR=", 7)==0) {
392 if(strncasecmp(cptr,
"YES", 1)==0) {reblur=1;
continue;}
393 if(strncasecmp(cptr,
"NO", 1)==0) {reblur=0;
continue;}
394 }
else if(strncasecmp(cptr,
"BETA=", 5)==0 && strlen(cptr)>5) {
395 betaFactor=
atof_dpi(cptr+5);
if(betaFactor>0.0)
continue;
396 }
else if(strncasecmp(cptr,
"ALPHA=", 6)==0) {
397 alpha=
atof_dpi(cptr+6);
if(alpha>0.0)
continue;
398 }
else if(strncasecmp(cptr,
"TERM=", 5)==0) {
399 termLimit=
atof_dpi(cptr+5);
if(termLimit>0.0 && termLimit<1)
continue;
400 }
else if(strncasecmp(cptr,
"ITER=", 5)==0) {
401 maxIterNr=atoi(cptr+5);
if(maxIterNr>0)
continue;
403 fprintf(stderr,
"Error: invalid option '%s'.\n", argv[ai]);
408 if(help==2) {
tpcHtmlUsage(argv[0], info,
"");
return(0);}
413 if(ai<argc) {
strlcpy(petfile, argv[ai++], FILENAME_MAX);}
416 if(ret==0 && FWHMxy>=0.0) {
418 if(
strcasestr(argv[ai],
"pxl")!=NULL) FWHMxyUnit=0;
419 if(
strcasestr(argv[ai],
"mm")!=NULL) FWHMxyUnit=1;
420 if(
strcasestr(argv[ai],
"cm")!=NULL) FWHMxyUnit=2;
423 fprintf(stderr,
"Error: invalid x,y FWHM.\n");
429 if(ret==0 && FWHMz>=0.0) {
431 if(
strcasestr(argv[ai],
"pxl")!=NULL) FWHMzUnit=0;
432 if(
strcasestr(argv[ai],
"mm")!=NULL) FWHMzUnit=1;
433 if(
strcasestr(argv[ai],
"cm")!=NULL) FWHMzUnit=2;
436 fprintf(stderr,
"Error: invalid z FWHM.\n");
440 if(ai<argc) {
strlcpy(outfile, argv[ai++], FILENAME_MAX);}
442 fprintf(stderr,
"Error: invalid argument '%s'.\n", argv[ai]);
448 fprintf(stderr,
"Error: missing command-line argument; use option --help\n");
451 if(!(FWHMxy>0.0) && !(FWHMz>0.0)) {
452 fprintf(stderr,
"Error: invalid FWHM.\n");
458 printf(
"petfile := %s\n", petfile);
459 printf(
"FWHMxy := %g\n", FWHMxy);
460 printf(
"FWHMz := %g\n", FWHMz);
461 printf(
"outfile := %s\n", outfile);
462 if(method==1) printf(
"method := RL\n");
else printf(
"method := VC\n");
463 printf(
"reblur := %d\n", reblur);
464 printf(
"alpha := %g\n", alpha);
465 printf(
"betaFactor := %g\n", betaFactor);
466 printf(
"termLimit := %g\n", termLimit);
467 printf(
"maxIterNr := %d\n", maxIterNr);
475 if(verbose>0) fprintf(stdout,
"reading image %s\n", petfile);
478 fprintf(stderr,
"Error: %s\n", img.
statmsg);
if(verbose>1)
imgInfo(&img);
482 printf(
"image dimensions[z y x]: %d %d %d\n", img.
dimz, img.
dimy, img.
dimx);
483 printf(
"image voxel size[z y x]: %g %g %g\n", img.
sizez, img.
sizey, img.
sizex);
484 printf(
"image frame nr: %d\n", img.
dimt);
488 fprintf(stderr,
"Error: %s is not an image.\n", petfile);
492 if(verbose>0) fprintf(stderr,
"Warning: missing pixel values.\n");
497 if((FWHMxyUnit!=0 && (!(img.
sizex>0.0) || !(img.
sizey>0.0))) || (FWHMzUnit!=0 && !(img.
sizez>0.0)))
499 fprintf(stderr,
"Error: unknown image pixel size.\n");
503 if(FWHMxyUnit==2) {FWHMxy*=10.0; FWHMxyUnit=1;}
504 if(FWHMzUnit==2) {FWHMz*=10.0; FWHMzUnit=1;}
506 if(FWHMxyUnit==1) {FWHMxy/=img.
sizex; FWHMxyUnit=0; printf(
"FWHMxy[pxl] := %g\n", FWHMxy);}
507 if(FWHMzUnit==1) {FWHMz/=img.
sizez; FWHMzUnit=0; printf(
"FWHMz[pxl] := %g\n", FWHMz);}
513 if(verbose>0) fprintf(stdout,
"correcting...\n");
518 ret=
imgPVCRRL(&img, FWHMxy, FWHMz, reblur, betaFactor, alpha, maxIterNr, termLimit,
521 ret=
imgPVCRVC(&img, FWHMxy, FWHMz, reblur, betaFactor, alpha, maxIterNr, termLimit,
524 fprintf(stderr,
"Error: cannot correct image.\n");
525 if(verbose>1) printf(
"ret=%d\n", ret);
537 if(verbose>1) fprintf(stdout,
"writing image in %s\n", outfile);
541 fprintf(stderr,
"Error: %s\n", out.
statmsg);
544 if(verbose>0) fprintf(stdout,
"Image was written in %s\n", outfile);
int atof_with_check(char *double_as_string, double *result_value)
double atof_dpi(char *str)
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 imgRead(const char *fname, IMG *img)
int imgWrite(const char *fname, IMG *img)
int imgGaussianFIRFilter(IMG *img, float xsd, float ysd, float zsd, double tolerance, int verbose)
int imgPVCRRL(IMG *img1, double FWHMxy, double FWHMz, int reblur, double betaFactor, double alpha, int maxIterNr, double termLimit, IMG *img2, int verbose)
int imgPVCRVC(IMG *img1, double FWHMxy, double FWHMz, int reblur, double betaFactor, double alpha, int maxIterNr, double termLimit, IMG *img2, int verbose)
int imgMinMax(IMG *img, float *minvalue, float *maxvalue)
Header file for libtpcimgio.
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)
char * strcasestr(const char *haystack, const char *needle)
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)