TPCCLIB
Loading...
Searching...
No Matches
dft2img.c
Go to the documentation of this file.
1
7/*****************************************************************************/
8#include "tpcclibConfig.h"
9/*****************************************************************************/
10#include <stdio.h>
11#include <stdlib.h>
12#include <unistd.h>
13#include <math.h>
14#include <string.h>
15#include <time.h>
16/*****************************************************************************/
17#include "libtpcmisc.h"
18#include "libtpccurveio.h"
19#include "libtpcimgio.h"
20#include "libtpcroi.h"
21#include "libtpcimgp.h"
22/*****************************************************************************/
23
24/*****************************************************************************/
25static char *info[] = {
26 "Creating a PET image file in ECAT 6 or 7 format, with contents from",
27 "the user-specified TAC file. Extension of output image filename (.img or .v)",
28 "determines whether ECAT 6 or 7 format is used.",
29 "Image area is divided into equally sized rectangles, containing as pixel",
30 "values the regional TAC values.",
31 "Only one image plane is written to image (z dimension will be 1).",
32 "Frame times are written as specified in the TAC file.",
33 " ",
34 "Usage: @P [Options] tacfile imagefile [roifile]",
35 " ",
36 "If roifile is given, the rectangular regions are saved in it.",
37 "Not effective with option -tpl.",
38 " ",
39 "Options:",
40 " -scanner=<Advance|931|HR+|HRRT>",
41 " Scanner, by default GE Advance.",
42 " -zoom=<zoom>",
43 " Reconstruction zoom factor, minimum and default is 1.41421356.",
44 " -tpl=<filename>",
45 " Image area is not divided into rectangles, but instead the template",
46 " image containing pixel values [1,TAC nr] is used; ROIs are not saved",
47 " with this option.",
48 " -dim=<image dimension>",
49 " Image x,y-size in pixels; default 256; not effective with template.",
50 " -nodecay",
51 " If TAC data is not corrected for decay, use this option; otherwise",
52 " image headers will tell that image is corrected for decay.",
53 " -stdoptions", // List standard options like --help, -v, etc
54 " ",
55 "See also: flat2img, imgadd, img2tif, img2dft, tac2nii, pxl2mask, simframe",
56 " ",
57 "Keywords: image, ECAT, simulation, software testing",
58 0};
59/*****************************************************************************/
60
61/*****************************************************************************/
62/* Turn on the globbing of the command line, since it is disabled by default in
63 mingw-w64 (_dowildcard=0); in MinGW32 define _CRT_glob instead, if necessary;
64 In Unix&Linux wildcard command line processing is enabled by default. */
65/*
66#undef _CRT_glob
67#define _CRT_glob -1
68*/
69int _dowildcard = -1;
70/*****************************************************************************/
71
72/*****************************************************************************/
76/*****************************************************************************/
77int main(int argc, char **argv)
78{
79 int ai, help=0, version=0, verbose=1;
80 int fi, ri, zi, rowNr, colNr, w, h, row, col;
81 DFT dft;
82 char dfile[FILENAME_MAX], ifile[FILENAME_MAX], rfile[FILENAME_MAX],
83 tfile[FILENAME_MAX], *cptr;
84 IMG img;
85 int image_dimx=256, image_dimy=256, image_dimz=1;
86 int scanner_type=SCANNER_ADVANCE;
87 float zoom=1.41421356;
88 int decay=IMG_DC_CORRECTED;
89
90
91
92 /*
93 * Get arguments
94 */
95 if(argc==1) {tpcPrintUsage(argv[0], info, stderr); return(1);}
96 dfile[0]=ifile[0]=rfile[0]=tfile[0]=(char)0;
97 imgInit(&img); dftInit(&dft);
98 /* Options */
99 for(ai=1; ai<argc; ai++) if(*argv[ai]=='-') { /* options */
100 cptr=argv[ai]+1; if(*cptr=='-') cptr++; if(cptr==NULL) continue;
101 if(tpcProcessStdOptions(argv[ai], &help, &version, &verbose)==0) continue;
102 if(strncasecmp(cptr, "SCANNER=", 8)==0) {
103 cptr+=8;
104 if(*cptr=='9') {scanner_type=SCANNER_ECAT931; continue;}
105 if(*cptr=='A' || *cptr=='a') {scanner_type=SCANNER_ADVANCE; continue;}
106 if(strcasecmp(cptr, "HRRT")==0) {scanner_type=SCANNER_HRRT; continue;}
107 if(strncmp(cptr, "HR", 2)==0 || strncmp(cptr, "hr", 2)==0) {
108 scanner_type=SCANNER_HRPLUS; continue;}
109 } else if(strncasecmp(cptr, "DIM=", 4)==0) {
110 cptr+=4; image_dimx=image_dimy=atoi(cptr); if(image_dimx>1) continue;
111 } else if(strncasecmp(cptr, "ZOOM=", 5)==0) {
112 cptr+=5; zoom=atof_dpi(cptr); if(zoom>1.41421356) continue;
113 } else if(strncasecmp(cptr, "NODECAY", 1)==0) {
114 decay=IMG_DC_NONCORRECTED; continue;
115 } else if(strncasecmp(cptr, "TPL=", 4)==0) {
116 cptr+=4; strlcpy(tfile, cptr, FILENAME_MAX); if(strlen(tfile)>0) continue;
117 }
118 fprintf(stderr, "Error: invalid option '%s'.\n", argv[ai]);
119 return(1);
120 } else break;
121
122 /* Print help or version? */
123 if(help==2) {tpcHtmlUsage(argv[0], info, ""); return(0);}
124 if(help) {tpcPrintUsage(argv[0], info, stdout); return(0);}
125 if(version) {tpcPrintBuild(argv[0], stdout); return(0);}
126
127 /* Process other arguments, starting from the first non-option */
128 if(ai<argc) {strlcpy(dfile, argv[ai], FILENAME_MAX); ai++;}
129 if(ai<argc) {strlcpy(ifile, argv[ai], FILENAME_MAX); ai++;}
130 if(ai<argc) {strlcpy(rfile, argv[ai], FILENAME_MAX); ai++;}
131 if(ai<argc) {fprintf(stderr, "Error: invalid argument '%s'.\n", argv[ai]); return(1);}
132
133
134 /* Is something missing? */
135 if(!ifile[0]) {
136 fprintf(stderr, "Error: missing command-line argument; try %s --help\n", argv[0]);
137 return(1);
138 }
139
140 /* In verbose mode print arguments and options */
141 if(verbose>1) {
142 printf("dfile := %s\n", dfile);
143 printf("ifile := %s\n", ifile);
144 printf("rfile := %s\n", rfile);
145 printf("tfile := %s\n", tfile);
146 printf("scanner_type := %d\n", scanner_type);
147 if(!tfile[0]) { // these will be reset later if template is given
148 printf("image_dimx := %d\n", image_dimx);
149 printf("image_dimy := %d\n", image_dimy);
150 printf("image_dimz := %d\n", image_dimz);
151 }
152 printf("zoom := %g\n", zoom);
153 printf("decay := %d\n", decay);
154 fflush(stdout);
155 }
156
157
158 /*
159 * Read regional data
160 */
161 if(verbose>1) printf("Reading TAC file %s\n", dfile);
162 if(dftRead(dfile, &dft)) {
163 fprintf(stderr, "Error in reading '%s': %s\n", dfile, dfterrmsg);
164 return(2);
165 }
166 if(verbose>2) printf("roiNr := %d\nframeNr := %d\n", dft.voiNr, dft.frameNr);
167
168
169 /*
170 * If template is given, then read image dimensions etc from there
171 */
172 if(tfile[0]) {
173 /* Read template image header */
174 if(verbose>1) fprintf(stdout, "reading header from template %s\n", tfile);
175 IMG timg; imgInit(&timg);
176 if(imgReadHeader(tfile, &timg, timg._fileFormat)!=0) {
177 fprintf(stderr, "Error: %s\n", timg.statmsg);
178 if(verbose>3) imgInfo(&timg);
179 dftEmpty(&dft); imgEmpty(&timg);
180 return(3);
181 }
182 if(verbose>19) imgInfo(&timg);
183 image_dimx=timg.dimx;
184 image_dimy=timg.dimy;
185 image_dimz=timg.dimz;
186 zoom=timg.zoom;
187 imgEmpty(&timg); // not needed for awhile
188 if(verbose>2) {
189 printf("image_dimx := %d\n", image_dimx);
190 printf("image_dimy := %d\n", image_dimy);
191 printf("image_dimz := %d\n", image_dimz);
192 }
193 }
194
195
196 /*
197 * Create the image struct
198 */
199 /* Allocate memory for it */
200 if(verbose>1) printf("allocating memory for image data\n");
201 if(imgAllocate(&img, image_dimz, image_dimy, image_dimx, dft.frameNr)) {
202 fprintf(stderr, "Error in memory allocation.\n");
203 dftEmpty(&dft); imgEmpty(&img); return(4);
204 }
205 /* Set header information */
206 if(verbose>1) printf("setting image headers\n");
208 imgSetUnit(&img, dft.unit);
209 strcpy(img.studyNr, dft.studynr);
210 img.zoom=zoom;
211 img.decayCorrection=decay;
212 (void)imgSetScanner(&img, scanner_type);
214 img.planeNumber[0]=1;
215 for(fi=0; fi<dft.frameNr; fi++) {
216 img.start[fi]=dft.x1[fi]; img.end[fi]=dft.x2[fi]; img.mid[fi]=dft.x[fi];
217 if(dft.timeunit==TUNIT_MIN) {
218 img.start[fi]*=60.; img.end[fi]*=60.; img.mid[fi]*=60.;}
219 }
220 /* Scan start time */
221 {
222 struct tm stm;
223 if(get_datetime(dft.scanStartTime, &stm, 0)==0) {
224 img.scanStart=timegm(&stm);
225 } else {
226 img.scanStart=time(NULL);
227 }
228 }
229
230
231 /*
232 * Fill the image data, either square areas, or using template
233 */
234 if(!tfile[0]) { // no template
235
236 ROI_list roilist;
237 roiInit(&roilist);
238
239 /*
240 * Set the regions
241 */
242 if(verbose>1) printf("Setting ROIs\n");
243 /* Allocate memory */
244 if((roilist.roi=(ROI*)calloc(dft.voiNr, sizeof(ROI)))==NULL) {
245 fprintf(stderr, "Error in memory allocation.\n");
246 dftEmpty(&dft); imgEmpty(&img); return(5);
247 }
248 for(ri=0; ri<dft.voiNr; ri++) {
249 roilist.roi[ri].point_nr=5;
250 roilist.roi[ri].x=(int*)calloc(roilist.roi[ri].point_nr, sizeof(int));
251 roilist.roi[ri].y=(int*)calloc(roilist.roi[ri].point_nr, sizeof(int));
252 }
253 roilist.nr=dft.voiNr;
254 /* Set ROI headers */
255 for(ri=0; ri<dft.voiNr; ri++) {
256 strcpy(roilist.roi[ri].imgfile, ifile);
257 roilist.roi[ri].zoom=1.0; roilist.roi[ri].recon_zoom=zoom;
258 roilist.roi[ri].type=ROI_TRACE;
259 sprintf(roilist.roi[ri].roiname, "%s %s",
260 dft.voi[ri].voiname, dft.voi[ri].hemisphere);
261 roilist.roi[ri].matnum=mat_numcod(1, 1, 1, 0, 0);
262 roilist.roi[ri].roi=1+ri;
263 }
264 img.zoom=roilist.roi[0].recon_zoom;
265 /* Calculate the number of ROI rectangles inside image matrix */
266 colNr=ceil(sqrt((double)dft.voiNr));
267 rowNr=ceil((double)dft.voiNr/(double)colNr);
268 /* Calculate the width and height of the ROIs in pixels */
269 w=image_dimx/colNr; h=image_dimy/rowNr; if(w<2 || h<2) {
270 fprintf(stderr, "Error: too many TACs.\n");
271 dftEmpty(&dft); imgEmpty(&img); roiEmpty(&roilist); return(5);
272 }
273 if(verbose>=0)
274 printf("setting %dx%d ROIs of width %d and height %d pixels with %d frames\n",
275 colNr, rowNr, w, h, dft.frameNr);
276 /* Set region definitions */
277 for(ri=col=row=0; ri<dft.voiNr; ri++) {
278 if(verbose>1) printf("Setting ROI (%d,%d) %s:\n", col, row, roilist.roi[ri].roiname);
279 roilist.roi[ri].pos_x=col*w; roilist.roi[ri].pos_y=row*h;
280 roilist.roi[ri].x[0]=roilist.roi[ri].y[0]=0;
281 roilist.roi[ri].x[1]=w-1; roilist.roi[ri].y[1]=0;
282 roilist.roi[ri].x[2]=w-1; roilist.roi[ri].y[2]=h-1;
283 roilist.roi[ri].x[3]=0; roilist.roi[ri].y[3]=h-1;
284 roilist.roi[ri].x[4]=0; roilist.roi[ri].y[4]=0;
285 col++; if(col==colNr) {col=0; row++;}
286 if(verbose>10) roiPrint(roilist.roi+ri);
287 }
288 /* Save ROI file, if required */
289 if(rfile[0]) {
290 if(verbose>=0) printf("Writing ROI file %s\n", rfile);
291 if(roiSave(rfile, &roilist)) {
292 fprintf(stderr, "Error in writing ROI file.\n");
293 dftEmpty(&dft); roiEmpty(&roilist); imgEmpty(&img); return(11);
294 }
295 }
296 /* Set contents of image matrices */
297 if(verbose>1) printf("setting image data contents\n");
298 for(ri=0; ri<dft.voiNr; ri++) {
299 if(verbose>2) printf(" roi=%d\n", ri);
300 for(row=roilist.roi[ri].pos_y;
301 row<=roilist.roi[ri].pos_y+roilist.roi[ri].y[2]; row++)
302 for(col=roilist.roi[ri].pos_x;
303 col<=roilist.roi[ri].pos_x+roilist.roi[ri].x[2]; col++)
304 for(fi=0; fi<dft.frameNr; fi++) {
305 if(verbose>30) printf(" m[%d][%d][%d][%d]=%g\n", 0, row, col, fi, dft.voi[ri].y[fi]);
306 for(zi=0; zi<img.dimz; zi++)
307 img.m[zi][row][col][fi]=dft.voi[ri].y[fi];
308 }
309 }
310 if(verbose>20) imgInfo(&img);
311 roiEmpty(&roilist);
312
313 } else { // use template image
314
315 int xi, yi, zi, notset;
316 IMG timg;
317 imgInit(&timg);
318
319 /* Read template image */
320 if(verbose>1) fprintf(stdout, "reading template %s\n", tfile);
321 if(imgRead(tfile, &timg)!=0) {
322 fprintf(stderr, "Error: %s\n", timg.statmsg);
323 if(verbose>0) imgInfo(&timg);
324 dftEmpty(&dft); imgEmpty(&img); imgEmpty(&timg);
325 return(6);
326 }
327 if(verbose>19) imgInfo(&timg);
328
329 /* Check template image dimensions */
330 if(timg.dimt>1) {
331 fprintf(stderr, "Error: template contains more than one frame.\n");
332 dftEmpty(&dft); imgEmpty(&img); imgEmpty(&timg);
333 return(6);
334 }
335 if(timg.dimx!=img.dimx || timg.dimy!=img.dimy || timg.dimz!=img.dimz) {
336 fprintf(stderr, "Error: wrong template dimensions.\n");
337 dftEmpty(&dft); imgEmpty(&img); imgEmpty(&timg);
338 return(6);
339 }
340
341 /* Set zoom and pixel sizes based on template */
342 img.scanner=timg.scanner; img.modality=timg.modality;
343 img.zoom=timg.zoom;
344 img.sizex=timg.sizex; img.sizey=timg.sizey; img.sizez=timg.sizez;
345 img.gapx=timg.gapx; img.gapy=timg.gapy; img.gapz=timg.gapz;
347 img.axialFOV=timg.axialFOV; img.transaxialFOV=timg.transaxialFOV;
349
350
351 /* Set contents of image matrix */
352 for(ri=0; ri<dft.voiNr; ri++) dft.voi[ri].size=0.0;
353 notset=0;
354 for(zi=0; zi<img.dimz; zi++) {
355 for(yi=0; yi<img.dimy; yi++) {
356 for(xi=0; xi<img.dimx; xi++) {
357 ri=temp_roundf(timg.m[zi][yi][xi][0]) - 1;
358 if(ri<0 || ri>=dft.voiNr) {
359 for(fi=0; fi<dft.frameNr; fi++) img.m[zi][yi][xi][fi]=0.0;
360 notset++; continue;
361 }
362 for(fi=0; fi<dft.frameNr; fi++)
363 img.m[zi][yi][xi][fi]=dft.voi[ri].y[fi];
364 dft.voi[ri].size+=1.0;
365 }
366 }
367 }
368 if(verbose>0) {
369 printf("%d pixels were not assigned value from TAC.\n", notset);
370 for(ri=0; ri<dft.voiNr; ri++) {
371 printf("TAC %d was written in %d pixels.\n", 1+ri, (int)temp_roundf(dft.voi[ri].size));
372 }
373 }
374
375 imgEmpty(&timg);
376
377 }
378 dftEmpty(&dft);
379
380
381 /*
382 * Save image
383 */
384 if(verbose>1) printf("Writing image file %s ...\n", ifile);
385 if(imgWrite(ifile, &img)) {
386 fprintf(stderr, "Error: %s\n", img.statmsg);
387 imgEmpty(&img); return(13);
388 }
389 if(verbose>=0) printf("%s written\n", ifile);
390
391 /* Free memory */
392 imgEmpty(&img);
393
394 return(0);
395}
396/*****************************************************************************/
397
398/*****************************************************************************/
int get_datetime(char *str, struct tm *date, int verbose)
Definition datetime.c:322
time_t timegm(struct tm *tm)
Inverse of gmtime, converting struct tm to time_t.
Definition datetime.c:69
double atof_dpi(char *str)
Definition decpoint.c:59
void dftInit(DFT *data)
Definition dft.c:38
char dfterrmsg[64]
Definition dft.c:6
void dftEmpty(DFT *data)
Definition dft.c:20
int dftRead(char *filename, DFT *data)
Definition dftio.c:22
int mat_numcod(int frame, int plane, int gate, int data, int bed)
Definition ecat63ml.c:242
int roiSave(const char *fname, ROI_list *rl)
void imgInfo(IMG *image)
Definition img.c:359
int imgAllocate(IMG *image, int planes, int rows, int columns, int frames)
Definition img.c:194
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
int imgReadHeader(const char *fname, IMG *img, int format)
Definition imgfile.c:199
int imgSetScanner(IMG *img, int scanner_type)
Definition imgscanner.c:14
int imgSetUnit(IMG *img, char *unit)
Definition imgunits.c:328
Header file for libtpccurveio.
Header file for libtpcimgio.
#define SCANNER_ADVANCE
#define SCANNER_HRRT
#define IMG_UNKNOWN
#define IMG_DC_CORRECTED
#define IMG_DC_NONCORRECTED
#define SCANNER_HRPLUS
#define SCANNER_ECAT931
#define IMG_TYPE_IMAGE
Header file for libtpcimgp.
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
int temp_roundf(float e)
Definition petc99.c:20
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 libtpcroi.
#define roiEmpty
Definition libtpcroi.h:151
#define ROI_TRACE
Definition libtpcroi.h:40
#define roiPrint
Definition libtpcroi.h:155
#define roiInit
Definition libtpcroi.h:153
char scanStartTime[20]
Voi * voi
int timeunit
char studynr[MAX_STUDYNR_LEN+1]
double * x1
int voiNr
double * x2
int frameNr
double * x
char unit[MAX_UNITS_LEN+1]
float sizex
unsigned short int dimx
char type
float resolutionx
float resolutiony
float sampleDistance
float gapx
float **** m
char decayCorrection
float transaxialFOV
time_t scanStart
int _fileFormat
unsigned short int dimt
int * planeNumber
int scanner
float sizey
float * start
unsigned short int dimz
int modality
unsigned short int dimy
float * end
float zoom
const char * statmsg
char studyNr[MAX_STUDYNR_LEN+1]
float gapy
float gapz
float axialFOV
float * mid
float sizez
float resolutionz
ROI * roi
Definition libtpcroi.h:104
float zoom
Definition libtpcroi.h:47
int pos_x
Definition libtpcroi.h:57
int * x
Definition libtpcroi.h:72
int pos_y
Definition libtpcroi.h:59
int type
Definition libtpcroi.h:53
char roiname[256]
Definition libtpcroi.h:69
int matnum
Definition libtpcroi.h:51
int point_nr
Definition libtpcroi.h:78
int roi
Definition libtpcroi.h:67
float recon_zoom
Definition libtpcroi.h:49
int * y
Definition libtpcroi.h:75
char imgfile[FILENAME_MAX]
Definition libtpcroi.h:45
double size
char voiname[MAX_REGIONSUBNAME_LEN+1]
double * y
char hemisphere[MAX_REGIONSUBNAME_LEN+1]