TPCCLIB
Loading...
Searching...
No Matches
eframe.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 "libtpcimgio.h"
19#include "libtpcimgp.h"
20/*****************************************************************************/
21
22/*****************************************************************************/
23static char *info[] = {
24 "List the time frame information of an ECAT 6.3 or 7.x file.",
25 "The frame start times and lengths can be saved in SIF.",
26 " ",
27 "If an existing SIF is specified, the frame times are read from it and",
28 "written in the ECAT file; SIF and ECAT file must contain an equal number",
29 "of frames. If ECAT file does not contain isotope or scan start time,",
30 "they are copied from the SIF, too.",
31 " ",
32 "Warning! Make sure that SIF does not exist, unless you want to change",
33 "the frame times in ECAT file.",
34 " ",
35 "Usage: @P [-Options] ecatfile [SIF]",
36 " ",
37 "Options:",
38 " -ift",
39 " Frame file is written in interfile type format; currently",
40 " this format is not supported in changing the frame times.",
41 " Times are saved in min; use option -sec to save in sec.",
42 " -plain",
43 " Frame file is written with only frame start times and lengths.",
44 " Times are saved in min; use option -sec to save in sec.",
45 " -stdoptions", // List standard options like --help, -v, etc
46 " ",
47 "See also: esetstrt, egetstrt, ecattime, tacframe, imghead, imgdelfr",
48 " ",
49 "Keywords: image, ECAT, time, SIF",
50 0};
51/*****************************************************************************/
52
53/*****************************************************************************/
54/* Turn on the globbing of the command line, since it is disabled by default in
55 mingw-w64 (_dowildcard=0); in MinGW32 define _CRT_glob instead, if necessary;
56 In Unix&Linux wildcard command line processing is enabled by default. */
57/*
58#undef _CRT_glob
59#define _CRT_glob -1
60*/
61int _dowildcard = -1;
62/*****************************************************************************/
63
64/*****************************************************************************/
68int main(int argc, char **argv)
69{
70 int ai, help=0, version=0, verbose=1;
71 int fi, ret, sec=0, frame_nr;
72 int output_format=2; // 0=plain, 1=ift, 2=sif
73 char ecatfile[FILENAME_MAX], datfile[FILENAME_MAX], tmp[512], *cptr;
74 float start=0., dur=0., end=0.;
75 IMG img;
76 FILE *fp=NULL;
77 SIF esif, nsif;
78 double hl;
79
80
81 /*
82 * Get arguments
83 */
84 if(argc==1) {tpcPrintUsage(argv[0], info, stderr); return(1);}
85 ecatfile[0]=datfile[0]=tmp[0]=(char)0;
86 imgInit(&img); sifInit(&esif); sifInit(&nsif);
87 /* Options */
88 for(ai=1; ai<argc; ai++) if(*argv[ai]=='-') { /* options */
89 cptr=argv[ai]+1; if(*cptr=='-') cptr++; if(cptr==NULL) continue;
90 if(tpcProcessStdOptions(argv[ai], &help, &version, &verbose)==0) continue;
91 if(strcasecmp(cptr, "IFT")==0) {
92 output_format=1; continue;
93 } else if(strcasecmp(cptr, "SIF")==0) {
94 output_format=2; continue;
95 } else if(strcasecmp(cptr, "PLAIN")==0) {
96 output_format=0; continue;
97 } else if(strncasecmp(cptr, "SEC", 3)==0 || strcasecmp(cptr, "S")==0) {
98 sec=1; continue;
99 } else if(strncasecmp(cptr, "MIN", 3)==0 || strcasecmp(cptr, "M")==0) {
100 sec=0; continue;
101 }
102 fprintf(stderr, "Error: invalid option '%s'.\n", argv[ai]);
103 return(1);
104
105 } else break;
106
107 /* Print help or version? */
108 if(help==2) {tpcHtmlUsage(argv[0], info, ""); return(0);}
109 if(help) {tpcPrintUsage(argv[0], info, stdout); return(0);}
110 if(version) {tpcPrintBuild(argv[0], stdout); return(0);}
111
112 /* Process other arguments, starting from the first non-option */
113 if(ai<argc) strlcpy(ecatfile, argv[ai++], FILENAME_MAX);
114 if(ai<argc) strlcpy(datfile, argv[ai++], FILENAME_MAX);
115 if(ai<argc) {fprintf(stderr, "Error: invalid argument '%s'.\n", argv[ai]); return(1);}
116
117 /* Is something missing? */
118 if(!ecatfile[0]) {
119 fprintf(stderr, "Error: missing command-line argument; try %s --help\n", argv[0]);
120 return(1);
121 }
122
123 /* In verbose mode print arguments and options */
124 if(verbose>1) {
125 printf("ecatfile := %s\n", ecatfile);
126 printf("datfile := %s\n", datfile);
127 printf("output_format := %d\n", output_format);
128 printf("sec := %d\n", sec);
129 fflush(stdout);
130 }
131 if(verbose>2) ECAT63_TEST=verbose-2; else ECAT63_TEST=0;
132 if(verbose>2) ECAT7_TEST=verbose-2; else ECAT7_TEST=0;
133 if(verbose>2) IMG_TEST=verbose-2; else IMG_TEST=0;
134
135
136 /* If frame file is specified, check if it exists */
137 int mode=1; // 0=set frames, 1=list frames, 2=save frames
138 if(datfile[0]) {
139 /* Check if file exists */
140 if(access(datfile, 0) != -1) {
141 mode=0; /* frame file exists; change frames */
142 if(verbose>0) fprintf(stdout, "Setting frame times from %s\n", datfile);
143 } else {
144 mode=2; /* not existing; so create it */
145 /* Check if frame times are to be saved in SIF or IFT format */
146 char *cptr=strrchr(datfile, '.');
147 if(cptr!=NULL && strcasecmp(cptr, ".SIF")==0) output_format=2;
148 if(cptr!=NULL && strcasecmp(cptr, ".IFT")==0) output_format=1;
149 }
150 } else
151 mode=1; /* frame file not specified; just list frames */
152 if(verbose>1) printf("mode := %d\n", mode);
153 fflush(stdout);
154
155
156 /*
157 * Read information about input file
158 */
159 if(verbose>1) printf("reading ECAT file\n");
160 ret=imgReadHeader(ecatfile, &img, IMG_UNKNOWN); if(verbose>10) imgInfo(&img);
161 if(ret) {
162 fprintf(stderr, "Error in reading %s: %s\n", ecatfile, imgStatus(ret));
163 imgEmpty(&img); return(2);
164 }
165 frame_nr=img.dimt;
166 if(verbose>1) printf("frame_nr := %d\n", frame_nr);
167 /* Allocate SIF to store frame times */
168 ret=sifSetmem(&esif, frame_nr); if(ret!=0) {
169 fprintf(stderr, "Error: out of memory.\n");
170 imgEmpty(&img); return(2);
171 }
172 esif.colNr=4; esif.version=1;
173 /* Read frame information, one frame at a time */
174 imgEmpty(&img);
175 for(fi=0; fi<frame_nr; fi++) {
176 if(verbose>2) printf("\nframe %d\n", fi+1);
177 /* Read first/next frame in file */
178 ret=imgReadFrame(ecatfile, fi+1, &img, 0);
179 if(ret) {
180 fprintf(stderr, "\nError in reading %s: %s\n", ecatfile, imgStatus(ret));
181 imgEmpty(&img); return(3);
182 }
183 if(verbose>0 && frame_nr>2) {fprintf(stdout, "."); fflush(stdout);}
184 /* Set SIF frame time */
185 esif.x1[fi]=img.start[0]; esif.x2[fi]=img.end[0];
186 if(fi==0) {
187 /* Set isotope */
188 strcpy(esif.isotope_name, imgIsotope(&img) );
189 /* Set studynumber */
190 strcpy(esif.studynr, img.studyNr);
191 /* Set scan start time */
192 esif.scantime=img.scanStart;
193 }
194 } // next frame
195 if(verbose>0 && frame_nr>2) printf("\n");
196 if(verbose>10) sifPrint(&esif);
197
198 if(mode==1 || (verbose>0 && (mode==0 || mode==2))) {
199 printf("Frame Start End Dur (sec) Start End Dur (min)\n");
200 fflush(stdout);
201 for(fi=0; fi<esif.frameNr; fi++) {
202 printf("%5d %6.1f %6.1f %6.1f %7.3f %7.3f %7.3f\n",
203 fi+1, esif.x1[fi], esif.x2[fi], esif.x2[fi]-esif.x1[fi],
204 esif.x1[fi]/60., esif.x2[fi]/60., (esif.x2[fi]-esif.x1[fi])/60. );
205 }
206 fflush(stdout);
207 if(mode==1) {
208 /* Ready... Quit */
209 imgEmpty(&img); sifEmpty(&esif);
210 return(0);
211 }
212 }
213
214
215
216 /*
217 * List frame times on screen
218 */
219 if(mode>0) {
220 if(output_format==2) { /* SIF */
221 if(mode==1) strcpy(datfile, "stdout");
222 int ret=sifWrite(&esif, datfile);
223 if(ret!=0) {
224 fprintf(stderr, "Error: cannot write frame times in %s\n", datfile);
225 imgEmpty(&img); sifEmpty(&esif); return(11);
226 }
227 if(verbose>0 && mode==2) {
228 if(sec) fprintf(stdout, "Frame times (sec) written in %s\n", datfile);
229 else fprintf(stdout, "Frame times (min) written in %s\n", datfile);
230 }
231 /* Ready... Quit */
232 if(verbose>0 && mode==2) {
233 if(sec) fprintf(stdout, "Frame times (sec) written in %s\n", datfile);
234 else fprintf(stdout, "Frame times (min) written in %s\n", datfile);
235 }
236 imgEmpty(&img); sifEmpty(&esif);
237 return(0);
238 }
239
240 FILE *fp=NULL;
241 if(mode==1) {
242 fp=stdout; strcpy(datfile, "stdout");
243 } else { // mode==2
244 /* Open file for writing */
245 if((fp=fopen(datfile, "w"))==NULL ) {
246 fprintf(stderr, "Error: cannot write file %s\n", datfile);
247 imgEmpty(&img); sifEmpty(&esif); return(11);
248 }
249 }
250 if(output_format==0) { /* just frame times */
251 for(int fi=0; fi<esif.frameNr; fi++) {
252 if(sec) ret=fprintf(fp, "%g %g\n", esif.x1[fi], (esif.x2[fi]-esif.x1[fi]) );
253 else ret=fprintf(fp, "%g %g\n", esif.x1[fi]/60.0, (esif.x2[fi]-esif.x1[fi])/60.0 );
254 if(ret<4) {
255 fprintf(stderr, "Error: cannot write frame times in %s.\n", datfile);
256 imgEmpty(&img); sifEmpty(&esif); if(mode==2) fclose(fp);
257 return(11);
258 }
259 }
260 } else if(output_format==1) { /* Interfile type format */
261 fprintf(fp, "filename := %s\n", ecatfile);
262 fprintf(fp, "frame_nr := %d\n", esif.frameNr);
263 if(sec) strcpy(tmp, "sec"); else strcpy(tmp, "min");
264 fprintf(fp, "time_unit := %s\n", tmp);
265 for(int fi=0; fi<esif.frameNr; fi++) {
266 if(sec) sprintf(tmp, "%g", esif.x1[fi]); else sprintf(tmp, "%g", esif.x1[fi]/60.0);
267 fprintf(fp, "frame_start[%d] := %s\n", fi+1, tmp);
268 if(sec) sprintf(tmp, "%g", esif.x2[fi]-esif.x1[fi]);
269 else sprintf(tmp, "%g", (esif.x2[fi]-esif.x1[fi])/60.0);
270 ret=fprintf(fp, "frame_duration[%d] := %s\n", fi+1, tmp);
271 if(ret<4) {
272 fprintf(stderr, "Error: cannot write frame times.\n");
273 imgEmpty(&img); sifEmpty(&esif); if(mode==2) fclose(fp);
274 return(11);
275 }
276 }
277 }
278 if(mode==2) fclose(fp);
279
280 /* Ready... Quit */
281 if(verbose>0 && mode==2) {
282 if(sec) fprintf(stdout, "Frame times (sec) written in %s\n", datfile);
283 else fprintf(stdout, "Frame times (min) written in %s\n", datfile);
284 }
285 imgEmpty(&img); sifEmpty(&esif);
286 return(0);
287 }
288
289
290
291 /*
292 * Read the new frame times
293 */
294 /* Try first to read it as a SIF */
295 ret=sifRead(datfile, &nsif);
296 if(ret==0) { // SIF could be read
297 if(nsif.frameNr!=frame_nr) {
298 fprintf(stderr, "Error: different frame number in %s and %s\n", datfile, ecatfile);
299 imgEmpty(&img); sifEmpty(&esif); sifEmpty(&nsif); return(7);
300 }
301 } else { // it was not SIF
302 if(verbose>2) printf("%s is not SIF\n", datfile);
303 /* Open frame file (file with just frame times) */
304 if((fp=fopen(datfile, "r")) == NULL) {
305 fprintf(stderr, "Error in opening %s\n", datfile);
306 imgEmpty(&img); sifEmpty(&esif); return(5);
307 }
308 /* Allocate memory for frame data */
309 ret=sifSetmem(&nsif, frame_nr); if(ret!=0) {
310 fprintf(stderr, "Error: out of memory.\n");
311 imgEmpty(&img); sifEmpty(&esif); fclose(fp); return(6);
312 }
313 nsif.colNr=4; nsif.version=1;
314 /* Read and get frames */
315 int fi=0; end=0.0;
316 while(fgets(tmp, 256, fp)!=NULL) {
317 if(tmp[0]=='#') continue;
318 ret=sscanf(tmp, "%f %f", &start, &dur); if(ret<=0) continue;
319 if(verbose>22) printf("'%s' -> n=%d, start=%g\n", tmp, ret, start);
320 if(fi==frame_nr) {fi=0; break;}
321 if(ret==1) {
322 nsif.x1[fi]=end; nsif.x2[fi]=nsif.x1[fi]+start;
323 } else {
324 nsif.x1[fi]=start; nsif.x2[fi]=nsif.x1[fi]+dur;
325 }
326 end=nsif.x2[fi];
327 if(verbose>21) printf("fi=%d %g %g %g\n", fi, start, end, dur);
328 fi++;
329 }
330 fclose(fp);
331 if(fi!=frame_nr) {
332 fprintf(stderr, "Error: different frame number in %s and %s\n", datfile, ecatfile);
333 imgEmpty(&img); sifEmpty(&esif); sifEmpty(&nsif); return(7);
334 }
335 /* Convert times into seconds, if they are not seconds already */
336 if(sec==0) for(fi=0; fi<nsif.frameNr; fi++) {nsif.x1[fi]*=60.; nsif.x2[fi]*=60.;}
337 }
338 if(verbose>0) fprintf(stdout, "Frame times read from %s\n", datfile);
339 if(verbose>0) fflush(stdout);
340 if(verbose>10) sifPrint(&esif);
341
342
343 /*
344 * Change the frame times in ECAT file
345 */
346 /* Backup the original ECAT file */
347 if(access(ecatfile, 0) != -1) {
348 strcpy(tmp, ecatfile); strcat(tmp, ".bak");
349 if(access(tmp, 0) != -1) remove(tmp);
350 if(verbose>0) printf("Making backup %s -> %s\n", ecatfile, tmp);
351 rename(ecatfile, tmp);
352 if(access(ecatfile, 0) != -1) {
353 fprintf(stderr, "Error: cannot overwrite %s\n", ecatfile);
354 imgEmpty(&img); sifEmpty(&esif); sifEmpty(&nsif); return(12);
355 }
356 }
357 if(verbose>0) printf("editing ECAT file\n");
358 imgEmpty(&img);
359 for(int fi=0; fi<frame_nr; fi++) {
360 if(verbose>1) printf("\nframe %d\n", fi+1);
361 /* Read first/next frame in file */
362 /* Note: we are reading from backup file because file with original name
363 does not exist currently or contains just the output */
364 ret=imgReadFrame(tmp, fi+1, &img, 0);
365 if(ret) {
366 fprintf(stderr, "\nError in reading %s: %s\n", ecatfile, imgStatus(ret));
367 imgEmpty(&img); sifEmpty(&esif); sifEmpty(&nsif);
368 return(3);
369 }
370 /* Set frame time from SIF */
371 img.start[0]=nsif.x1[fi]; img.end[0]=nsif.x2[fi];
372 img.mid[0]=0.5*(img.start[0]+img.end[0]);
373 /* Set isotope, if it does not exist */
374 if(img.isotopeHalflife<=1.0) {
376 if(hl>0) {
377 if(verbose>0 && fi==0)
378 fprintf(stdout, "\nnew halflife := %g [s]\n", 60.0*hl);
379 img.isotopeHalflife=60.0*hl;
380 }
381 }
382 /* Do not set studynumber : strcpy(img.studyNr, esif.studynr); */
383 /* Set scan start time, if it does not exist */
384 if(nsif.scantime>1000 && img.scanStart<1000) img.scanStart=nsif.scantime;
385 /* Write frame in file */
386 ret=imgWriteFrame(ecatfile, fi+1, &img, 0);
387 if(ret) {
388 fprintf(stderr, "\nError in writing %s: %s\n", ecatfile, imgStatus(ret));
389 imgEmpty(&img); sifEmpty(&esif); sifEmpty(&nsif); return(13);
390 }
391 if(verbose>0 && frame_nr>2) {fprintf(stdout, "."); fflush(stdout);}
392 } // next frame
393 if(verbose>0 && frame_nr>2) printf("\n");
394
395
396 /*
397 * List modified frame times on screen.
398 */
399 if(verbose>0) {
400 printf("Modified frame times:\n");
401 printf("Frame Start End Dur (sec) Start End Dur (min)\n");
402 fflush(stdout);
403 for(int fi=0; fi<nsif.frameNr; fi++) {
404 printf("%5d %5.0f %5.0f %5.0f %6.2f %6.2f %6.2f\n",
405 fi+1, nsif.x1[fi], nsif.x2[fi], nsif.x2[fi]-nsif.x1[fi],
406 nsif.x1[fi]/60., nsif.x2[fi]/60., (nsif.x2[fi]-nsif.x1[fi])/60. );
407 }
408 }
409
410 imgEmpty(&img); sifEmpty(&esif); sifEmpty(&nsif);
411 return(0);
412}
413/*****************************************************************************/
414
415/*****************************************************************************/
int ECAT63_TEST
Definition ecat63h.c:6
int ECAT7_TEST
Definition ecat7h.c:6
double hlFromIsotope(char *isocode)
Definition halflife.c:55
int IMG_TEST
Definition img.c:6
void imgInfo(IMG *image)
Definition img.c:359
char * imgStatus(int status_index)
Definition img.c:330
void imgEmpty(IMG *image)
Definition img.c:121
void imgInit(IMG *image)
Definition img.c:60
char * imgIsotope(IMG *img)
Definition imgdecayc.c:76
int imgWriteFrame(const char *fname, int frame_to_write, IMG *img, int frame_index)
Definition imgfile.c:392
int imgReadFrame(const char *fname, int frame_to_read, IMG *img, int frame_index)
Definition imgfile.c:269
int imgReadHeader(const char *fname, IMG *img, int format)
Definition imgfile.c:199
Header file for libtpcimgio.
int sifWrite(SIF *data, char *filename)
Definition sifio.c:145
#define IMG_UNKNOWN
void sifInit(SIF *data)
Definition sif.c:17
void sifPrint(SIF *data)
Definition sifio.c:234
int sifSetmem(SIF *data, int frameNr)
Definition sif.c:56
void sifEmpty(SIF *data)
Definition sif.c:33
int sifRead(char *filename, SIF *data)
Definition sifio.c:21
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
void tpcPrintBuild(const char *program, FILE *fp)
Definition proginfo.c:383
void tpcPrintUsage(const char *program, char *text[], FILE *fp)
Definition proginfo.c:158
time_t scanStart
unsigned short int dimt
float * start
float * end
float isotopeHalflife
char studyNr[MAX_STUDYNR_LEN+1]
float * mid
double * x1
int frameNr
double * x2
int version
char studynr[MAX_STUDYNR_LEN+1]
time_t scantime
char isotope_name[8]
int colNr