TPCCLIB
Loading...
Searching...
No Matches
ecatfbp.c
Go to the documentation of this file.
1
9/*****************************************************************************/
10#include "tpcclibConfig.h"
11/*****************************************************************************/
12#include <stdio.h>
13#include <stdlib.h>
14#include <math.h>
15#include <string.h>
16#include <unistd.h>
17#include <ctype.h>
18#include <dirent.h>
19#include <sys/stat.h>
20#include <sys/file.h>
21#include <time.h>
22/*****************************************************************************/
23#include "libtpcmisc.h"
24#include "libtpcimgio.h"
25#include "libtpcrec.h"
26/*****************************************************************************/
27
28/*****************************************************************************/
29static char *info[] = {
30 "Reconstruct PET image from attenuation and normalization corrected",
31 "2D PET sinogram using filtered back-projection (FBP).",
32 "This program does not correct image data for decay.",
33 "Image is corrected for the dead-time based on factors in the sinogram.",
34 "Image data is written in units ECAT counts per pixel per second.",
35 " ",
36 "Not for clinical use! Program is not thoroughly tested!",
37 " ",
38 "Usage: @P [Options] scnfile imgfile",
39 " ",
40 "Options:",
41 " -filter=<None|Ramp|Butter|Hann|Hamm|Parzen|Shepp>",
42 " Set the reconstruction filter; by default Hann.",
43 " -cutoff=<value>",
44 " Set cut-off value; by default 0.3.",
45 " -zoom=<value>",
46 " Set zoom factor; by default 1.0 (no zoom).",
47 " -dim=<value>",
48 " Set image x and y dimensions; by default 128.",
49 " -rot[ation]=<value>",
50 " Set image rotation in degrees, -180 - 180; by default 0 (no rotation).",
51 " -x=<value>",
52 " Set image shift in x direction (in cm); by default 0.",
53 " -y=<value>",
54 " Set image shift in y direction (in cm); by default 0.",
55 " -perv",
56 " Divide image voxel values by voxel volume (mL); by default the voxel",
57 " volume is corrected later during image calibration.",
58 " -stdoptions", // List standard options like --help, -v, etc
59 " ",
60 "Example:",
61 " @P -dim=256 a2345dy1.scn a2345dy1.img",
62 " ",
63 "See also: ecatnorm, edecay, ecalibr, atnmake, eframe, ecatmrp, img2scn",
64 " ",
65 "Keywords: ECAT, sinogram, image, reconstruction, FBP",
66 0};
67/*****************************************************************************/
68
69/*****************************************************************************/
70/* Turn on the globbing of the command line, since it is disabled by default in
71 mingw-w64 (_dowildcard=0); in MinGW32 define _CRT_glob instead, if necessary;
72 In Unix&Linux wildcard command line processing is enabled by default. */
73/*
74#undef _CRT_glob
75#define _CRT_glob -1
76*/
77int _dowildcard = -1;
78/*****************************************************************************/
79
80/*****************************************************************************/
84int main(int argc, char **argv)
85{
86 int ai, help=0, version=0, verbose=1;
87 char scnfile[FILENAME_MAX], imgfile[FILENAME_MAX];
88 int filter=FBP_FILTER_HANN;
89 float cutoff=0.3;
90 float rotate=0.0;
91 float zoom=1.0;
92 float shiftX=0.0, shiftY=0.0;
93 int pervol=0;
94 int imgDim=128;
95 char *cptr;
96 int ret;
97 static char *fbpFilterName[]={
98 "None","Ramp","Butter","Hann","Hamm","Parzen","Shepp", 0
99 };
100
101
102 /*
103 * Get arguments
104 */
105 if(argc==1) {tpcPrintUsage(argv[0], info, stderr); return(1);}
106 scnfile[0]=imgfile[0]=(char)0;
107 /* Options */
108 for(ai=1; ai<argc; ai++) if(*argv[ai]=='-') { /* options */
109 cptr=argv[ai]+1; if(*cptr=='-') cptr++; if(cptr==NULL) continue;
110 if(tpcProcessStdOptions(argv[ai], &help, &version, &verbose)==0) continue;
111 if(strncasecmp(cptr, "FILTER=", 7)==0) {
112 cptr+=7; filter=-1;
113 int i=0;
114 while(fbpFilterName[i]!=0) {
115 if(!strcasecmp(cptr, fbpFilterName[i])) {
116 filter=i; break;
117 } else i++;
118 }
119 if(filter>=0) continue;
120 } else if(strncasecmp(cptr, "DIM=", 4)==0) {
121 imgDim=atoi(cptr+4); if(imgDim>1 && imgDim<=2048) continue;
122 } else if(strncasecmp(cptr, "ZOOM=", 5)==0) {
123 zoom=atof_dpi(cptr+5); if(zoom>0.1 && zoom<100.0) continue;
124 } else if(strncasecmp(cptr, "CUTOFF=", 7)==0) {
125 cutoff=atof_dpi(cptr+7); if(cutoff>0.0 && cutoff<1.0) continue;
126 } else if(strncasecmp(cptr, "ROTATION=", 9)==0) {
127 double v;
128 ret=atof_with_check(cptr+9, &v);
129 if(v>=-180.0 && v<=180.0) {rotate=v; continue;}
130 } else if(strncasecmp(cptr, "ROT=", 4)==0) {
131 double v;
132 ret=atof_with_check(cptr+4, &v);
133 if(v>-360.0 && v<360.0) {rotate=v; continue;}
134 } else if(strncasecmp(cptr, "X=", 2)==0) {
135 double v;
136 ret=atof_with_check(cptr+2, &v);
137 if(v>-50.0 && v<50.0) {shiftX=10.0*v; continue;}
138 } else if(strncasecmp(cptr, "Y=", 2)==0) {
139 double v;
140 ret=atof_with_check(cptr+2, &v);
141 if(v>-50.0 && v<50.0) {shiftY=10.0*v; continue;}
142 }
143 fprintf(stderr, "Error: invalid option '%s'.\n", argv[ai]);
144 return(1);
145 } else break;
146
147 /* Print help or version? */
148 if(help==2) {tpcHtmlUsage(argv[0], info, ""); return(0);}
149 if(help) {tpcPrintUsage(argv[0], info, stdout); return(0);}
150 if(version) {tpcPrintBuild(argv[0], stdout); return(0);}
151
152 /* Process other arguments, starting from the first non-option */
153 if(ai<argc) {strlcpy(scnfile, argv[ai++], FILENAME_MAX);}
154 if(ai<argc) {strlcpy(imgfile, argv[ai++], FILENAME_MAX);}
155 if(ai<argc) {
156 fprintf(stderr, "Error: too many arguments.\n");
157 return(1);
158 }
159
160 /* Is something missing? */
161 if(!imgfile[0]) {
162 fprintf(stderr, "Error: missing command-line argument; use --help\n");
163 return(1);
164 }
165
166 /* In verbose mode print arguments and options */
167 if(verbose>1) {
168 printf("scnfile := %s\n", scnfile);
169 printf("imgfile := %s\n", imgfile);
170 printf("Filter := %s\n", fbpFilterName[filter]);
171 printf("Cut-off := %g\n", cutoff);
172 printf("Zoom := %g\n", zoom);
173 printf("Dimension := %d\n", imgDim);
174 printf("Rotation := %g\n", rotate);
175 printf("X_shift_mm := %g\n", shiftX);
176 printf("Y_shift_mm := %g\n", shiftY);
177 printf("volume_correction := %d\n", pervol);
178 }
179
180 /* Check that input and output files do not have the same filename */
181 if(strcasecmp(imgfile, scnfile)==0) {
182 fprintf(stderr, "Error: original sinogram must not be overwritten.\n");
183 return(1);
184 }
185 /* Check that image dimension is even */
186 if(imgDim%2) {
187 fprintf(stderr, "Error: invalid image dimension.\n");
188 return(1);
189 }
190
191
192 /*
193 * Read sinogram
194 */
195 if(verbose>0) printf("reading sinogram %s\n", scnfile);
196 IMG scn; imgInit(&scn);
197 ret=imgRead(scnfile, &scn);
198 if(ret) {
199 fprintf(stderr, "Error: %s\n", scn.statmsg);
200 if(verbose>1) printf("ret := %d\n", ret);
201 return(2);
202 }
203 if(verbose>1) {
204 printf("dimx := %d\n", scn.dimx);
205 printf("dimy := %d\n", scn.dimy);
206 printf("dimz := %d\n", scn.dimz);
207 printf("dimt := %d\n", scn.dimt);
208 }
209 /* Check that we have a sinogram */
210 if(scn.type!=IMG_TYPE_RAW) {
211 fprintf(stderr, "Error: file is not a sinogram.\n");
212 imgEmpty(&scn);
213 return(2);
214 }
215
216 /*
217 * Reconstruction
218 */
219 IMG img; imgInit(&img);
220 if(verbose>0) printf("FBP reconstruction...\n");
221 ret=imgFBP(&scn, &img, imgDim, zoom, filter, cutoff, shiftX, shiftY, rotate,
222 verbose-2);
223 if(ret) {
224 fprintf(stderr, "Error in reconstruction.\n");
225 if(verbose>1) printf("ret := %d\n", ret);
226 imgEmpty(&scn);
227 return(3);
228 }
229
230 /* Set header info in the output data */
231 img.zoom=zoom;
232
233 /* Pixel volume correction, if required */
234 if(pervol) {
235 if(verbose>0) printf("correcting for voxel volume\n");
236 float vol=0.001*img.sizex*img.sizey*img.sizez;
237 if(vol>0.0) {
238 int zi, yi, xi, ti;
239 for(zi=0; zi<img.dimz; zi++)
240 for(yi=0; yi<img.dimy; yi++)
241 for(xi=0; xi<img.dimx; xi++)
242 for(ti=0; ti<img.dimt; ti++)
243 img.m[zi][yi][xi][ti]/=vol;
244 } else {
245 fprintf(stderr, "Warning: cannot correct for pixel volume.\n");
246 }
247 }
248
249
250 /*
251 * Save the image */
252 if(verbose>0) printf("writing image %s\n", imgfile);
253 if(imgWrite(imgfile, &img)) {
254 fprintf(stderr, "Error: %s\n", img.statmsg);
255 imgEmpty(&img); imgEmpty(&scn);
256 return(11);
257 }
258
259 imgEmpty(&img); imgEmpty(&scn);
260 if(verbose>0) fprintf(stdout, "done.\n");
261
262 return(0);
263}
264/*****************************************************************************/
265
266/*****************************************************************************/
int atof_with_check(char *double_as_string, double *result_value)
Definition decpoint.c:107
double atof_dpi(char *str)
Definition decpoint.c:59
int imgFBP(IMG *scn, IMG *img, int imgDim, float zoom, int filter, float cutoff, float shiftX, float shiftY, float rotation, int verbose)
Definition fbp.c:108
void imgEmpty(IMG *image)
Definition img.c:121
void imgInit(IMG *image)
Definition img.c:60
int imgRead(const char *fname, IMG *img)
Definition imgfile.c:26
int imgWrite(const char *fname, IMG *img)
Definition imgfile.c:136
Header file for libtpcimgio.
#define IMG_TYPE_RAW
Header file for libtpcmisc.
int tpcProcessStdOptions(const char *s, int *print_usage, int *print_version, int *verbose_level)
Definition proginfo.c:40
size_t strlcpy(char *dst, const char *src, size_t dstsize)
Definition strext.c:245
int tpcHtmlUsage(const char *program, char *text[], const char *path)
Definition proginfo.c:213
void tpcPrintBuild(const char *program, FILE *fp)
Definition proginfo.c:383
void tpcPrintUsage(const char *program, char *text[], FILE *fp)
Definition proginfo.c:158
Header file for libtpcrec.
float sizex
unsigned short int dimx
char type
float **** m
unsigned short int dimt
float sizey
unsigned short int dimz
unsigned short int dimy
float zoom
const char * statmsg
float sizez