9#include "tpcclibConfig.h"
25 char *fname,
int *planeNr,
int *frameNr,
int *dim1,
int *dim2);
29static char *info[] = {
30 "Construct an ECAT PET image or sinogram from pixel values stored as 4-byte",
31 "(32-bits) floating point values in a binary flat file.",
32 "Data must be stored in this matrix order: all planes of the 1st frame,",
33 "2nd frame, and so on.",
34 "The format of the output file is determined from its file name extension",
35 "(*.v, *.s, *.i, *.img or *.scn).",
36 "The byte order of binary data is assumed to be the same as in current",
37 "platform; use option -e to change the byte order, if necessary.",
39 "Usage: @P [Options] flatfile ecatfile [zdim tdim xdim ydim]",
42 " -mif=<Matrix information file>",
43 " ASCII file containing the number of planes and frames, and x and y",
44 " dimensions, unless these are given as command-line arguments.",
45 " -scanner=<Advance|931|HR+|HRRT>",
46 " Set scanner specific parameters in headers.",
47 " -zoom=<reconstruction zoom>",
48 " Set reconstruction zoom in image headers (only for images)",
52 " Zero hot spots outside of FOV (only for images).",
53 " -bins=<Nr of bins>",
54 " Nr of bins in the output sinogram; use this to add (nr-dim1)/2 bins",
55 " filled with zeroes to both sides of sinogram.",
57 " Transpose the data, i.e. switch x and y axis.",
59 " Switch the byte order between little and big endian",
63 " @P -scanner=Advance xyz.dat xyz.scn 35 1 281 336",
64 " @P -scanner=HRRT -mif=qwe.mif qwe.dat qwe.v",
66 "See also: img2flat, flat2nii, asc2flat, ana2ecat, nii2ecat, e7emhdr, eframe",
68 "Keywords: ECAT, image, sinogram, format conversion, simulation",
87int main(
int argc,
char **argv)
89 int ai, help=0, version=0, verbose=1;
90 int pi, fi, xi, yi, n, ret, dim1=0, dim2=0;
91 int frameNr=0, planeNr=0, binNr=0;
92 int fov_corr=0, scanner_type=0, transpose=0, change_endian=0;
93 char imgfile[FILENAME_MAX], datfile[FILENAME_MAX],
94 miffile[FILENAME_MAX], iftfile[FILENAME_MAX];
104 if(argc==1) {
tpcPrintUsage(argv[0], info, stderr);
return(1);}
105 imgfile[0]=datfile[0]=miffile[0]=iftfile[0]=(char)0;
107 for(ai=1; ai<argc; ai++)
if(*argv[ai]==
'-') {
108 char *cptr=argv[ai]+1;
if(*cptr==
'-') cptr++;
if(cptr==NULL)
continue;
111 if(strncasecmp(cptr,
"ZERO", 2)==0) {
112 fov_corr=1;
continue;
113 }
else if(strncasecmp(cptr,
"MIF=", 4)==0) {
114 strcpy(miffile, cptr+4);
if(strlen(miffile)>0)
continue;
115 }
else if(strncasecmp(cptr,
"INF=", 4)==0) {
116 strcpy(miffile, cptr+4);
if(strlen(miffile)>0)
continue;
117 }
else if(strncasecmp(cptr,
"ZOOM=", 5)==0) {
120 if(ret==0 && f>0.01) {zoom=f;
continue;}
121 }
else if(strncasecmp(cptr,
"SCANNER=", 8)==0) {
125 if(strcasecmp(cptr,
"HRRT")==0) {scanner_type=
SCANNER_HRRT;
continue;}
126 if(strncasecmp(cptr,
"HR", 2)==0) {scanner_type=
SCANNER_HRPLUS;
continue;}
127 }
else if(strncasecmp(cptr,
"BINS=", 5)==0) {
128 binNr=atoi(cptr+5);
if(binNr>0.0)
continue;
129 }
else if(strncasecmp(cptr,
"TRANSPOSE", 2)==0) {
130 transpose=1;
continue;
131 }
else if(strcasecmp(cptr,
"E")==0) {
132 change_endian=1;
continue;
134 fprintf(stderr,
"Error: invalid option '%s'\n", argv[ai]);
139 if(help==2) {
tpcHtmlUsage(argv[0], info,
"");
return(0);}
144 if(ai<argc) {
strlcpy(datfile, argv[ai], FILENAME_MAX); ai++;}
145 if(ai<argc) {
strlcpy(imgfile, argv[ai], FILENAME_MAX); ai++;}
147 fprintf(stderr,
"Error: missing command-line argument; use option --help\n");
151 if(ai<argc) planeNr=atoi(argv[ai++]);
152 if(ai<argc) frameNr=atoi(argv[ai++]);
153 if(ai<argc) dim1=atoi(argv[ai++]);
154 if(ai<argc) dim2=atoi(argv[ai++]);
155 if(planeNr<=0 || frameNr<=0 || dim1<=0 || dim2<=0) {
156 fprintf(stderr,
"Error: missing/invalid data size argument.\n");
return(1);}
158 if(ai<argc) {fprintf(stderr,
"Error: too many arguments.\n");
return(1);}
161 if(strcasecmp(imgfile, datfile)==0) {
162 fprintf(stderr,
"Error: same name for input and output file.\n");
165 if(!miffile[0] && (planeNr==0 || frameNr==0 || dim1==0 || dim2==0)) {
166 fprintf(stderr,
"Error: information on data size not given.\n");
172 printf(
"datfile := %s\n", datfile);
173 printf(
"imgfile := %s\n", imgfile);
174 printf(
"miffile := %s\n", miffile);
176 printf(
"zoom := %g\n", zoom);
177 printf(
"scanner_type := %d\n", scanner_type);
178 printf(
"transpose := %d\n", transpose);
179 printf(
"change_endian := %d\n", change_endian);
180 printf(
"fov_corr := %d\n", fov_corr);
187 if(verbose>1) printf(
"reading %s\n", miffile);
190 fprintf(stderr,
"Error: invalid matrix information file.\n");
195 if(planeNr<1 || frameNr<1 || dim1<2 || dim2<2) {
196 fprintf(stderr,
"Error: invalid matrix dimensions.\n");
203 fprintf(stderr,
"Error: binNr should be larger than dimx.\n");
206 n=binNr; binNr=dim1; dim1=n;
212 printf(
"planeNr := %d\n", planeNr);
213 printf(
"frameNr := %d\n", frameNr);
214 printf(
"dimx := %d\n", dim1);
215 printf(
"dimy := %d\n", dim2);
216 printf(
"binNr := %d\n", binNr);
223 if(verbose>1) printf(
"defining output file type\n");
226 char *cptr=strrchr(imgfile,
'.');
if(cptr!=NULL) cptr++;
227 if(strcasecmp(cptr,
"SCN")==0) {
230 }
else if(strcasecmp(cptr,
"IMG")==0) {
233 }
else if(strcasecmp(cptr,
"S")==0) {
236 }
else if(strcasecmp(cptr,
"I")==0) {
239 }
else if(strcasecmp(cptr,
"V")==0) {
242 }
else if(strcasecmp(cptr,
"NII")==0) {
246 fprintf(stderr,
"Error: invalid output filename.\n");
251 fprintf(stderr,
"Error: option -zero is available only for images.\n");
255 fprintf(stderr,
"Error: bin nr can be used only with sinograms.\n");
259 printf(
"type := %d\n", img.
type);
267 if(verbose>1) printf(
"allocating memory for one PET time frame\n");
270 fprintf(stderr,
"Error: cannot allocate memory for PET data.\n");
275 for(pi=0; pi<planeNr; pi++) img.
planeNumber[pi]=pi+1;
281 if(verbose>1) printf(
"setting header information\n");
283 img.
unit=IMGUNIT_UNKNOWN;
300 if(scanner_type==0) {
305 else fprintf(stderr,
"Warning: scanner specific fields are left empty!\n");
316 if(verbose>1) printf(
"Allocating memory for input data\n");
317 int pxlNr=binNr*dim2;
319 fdata=(
float*)malloc(pxlNr*4);
321 fprintf(stderr,
"Error: cannot allocate memory for binary data.\n");
328 if(verbose>1) printf(
"Opening input datafile %s\n", datfile);
329 if((fp=fopen(datfile,
"rb")) == NULL) {
330 fprintf(stderr,
"Error: cannot open file %s\n", datfile);
331 imgEmpty(&img); free(fdata);
return(4);
337 if(access(imgfile, 0)!=-1 && remove(imgfile)!=0) {
338 fprintf(stderr,
"Error: cannot remove existing %s\n", imgfile);
339 imgEmpty(&img); free(fdata);
return(11);
346 for(fi=0; fi<frameNr; fi++) {
348 if(verbose>0) printf(
"reading frame %d\n", fi+1);
350 for(pi=0; pi<planeNr; pi++) {
351 if(verbose>2) {fflush(stdout); printf(
" reading plane %d\n", pi+1);}
354 ret=fread((
char*)fptr, 4, pxlNr, fp);
if(ret<pxlNr) {
356 fprintf(stderr,
"Error in reading data on pl%02d fr%02d.\n",
359 fprintf(stderr,
"Error: file does not contain all pixel values.\n");
360 free(fdata); fclose(fp);
imgEmpty(&img);
364 if(change_endian) {fptr=fdata;
swawbip(fptr, 4*pxlNr);}
370 for(xi=(dim1-binNr)/2; xi<(dim1+binNr)/2; xi++)
371 for(yi=0; yi<dim2; yi++)
372 img.
m[pi][yi][xi][0]=(*fptr++);
374 for(yi=0; yi<dim2; yi++)
375 for(xi=(dim1-binNr)/2; xi<(dim1+binNr)/2; xi++)
376 img.
m[pi][yi][xi][0]=(*fptr++);
385 if(verbose>2) {fflush(stdout); printf(
" writing frame\n");}
388 fprintf(stderr,
"Error: %s\n",
imgStatus(ret));
389 free(fdata); fclose(fp);
imgEmpty(&img);
return(13);
393 if(verbose>0) fprintf(stdout,
"%s saved.\n", imgfile);
397 if(verbose>1) printf(
"verifying that all data was read\n");
398 fptr=fdata; count=fread((
char*)fptr, 4, 1, fp);
399 if(!feof(fp) || count>0)
400 fprintf(stderr,
"Warning: some data in %s were not read!\n", datfile);
402 free(fdata); fclose(fp);
405 if(n!=(frameNr*planeNr)) {
406 fprintf(stderr,
"Error: %s did not contain %dx%d matrices!\n",
407 datfile, planeNr, frameNr);
422 fprintf(stderr,
"Error (%d) in reading %s: %s\n", ret, iftfile, ift.status);
427 ret=imgApplyIFT(&img, &ift);
429 fprintf(stderr,
"Warning: no information was retrieved from IF header.\n");
451 r=(float)dim/2.0;
if(r>25.0) r-=5.0;
453 for(i=0; i<dim*dim; i++, fptr++ ) {
454 d=hypotf((
float)(i/dim-dim/2), (
float)(i-dim*(i/dim)-dim/2));
483 if(fname==NULL || planeNr==NULL || frameNr==NULL || dim1==NULL || dim2==NULL)
485 fp=fopen(fname,
"r");
if(fp==NULL)
return(2);
486 n=fscanf(fp,
"%d %d %d %d", planeNr, frameNr, dim1, dim2);
487 fclose(fp);
if(n!=4)
return(3);
488 if(*planeNr<1 || *frameNr<1 || *dim1<1 || *dim2<1)
return(4);
int atof_with_check(char *double_as_string, double *result_value)
void zero_hot_spots(float *fdata, int dim)
int readMatrixInformation(char *fname, int *planeNr, int *frameNr, int *dim1, int *dim2)
int iftRead(IFT *ift, char *filename, int is_key_required, int verbose)
char * imgStatus(int status_index)
int imgAllocate(IMG *image, int planes, int rows, int columns, int frames)
void imgEmpty(IMG *image)
int imgWriteFrame(const char *fname, int frame_to_write, IMG *img, int frame_index)
int imgSetScanner(IMG *img, int scanner_type)
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)
void swawbip(void *buf, long long int size)
size_t strlcpy(char *dst, const char *src, size_t dstsize)
int tpcHtmlUsage(const char *program, char *text[], const char *path)
int studynr_from_fname(char *fname, char *studynr)
void tpcPrintBuild(const char *program, FILE *fp)
void tpcPrintUsage(const char *program, char *text[], FILE *fp)
char radiopharmaceutical[32]
char studyNr[MAX_STUDYNR_LEN+1]