9#include "tpcclibConfig.h"
24static char *info[] = {
25 "Change the scan_start_time and time frames in ECAT image or sinogram file",
26 "to refer to the injection time instead of the original delayed",
27 "scan_start_time. Correction for physical decay is changed accordingly",
28 "in images, but not in sinograms.",
30 "Before using this program, PET image must be decay corrected to its",
31 "scan_start_time, but sinogram must not be corrected for decay.",
32 "Please make backup of the original files before using this program.",
34 "Do not use this program for catenation of images; use ecatcat instead.",
36 "Usage: @P [Options] ecatfile [time]",
38 "Optional time is either the time (min) from radiotracer injection",
39 "to the PET scan start time, or, the new scan start time.",
40 "If time is not entered, then program makes no changes to the data, but",
41 "just displays the current scan_start_time and time when the collection of",
42 "the first frame was started.",
47 "Example 1. PET scan is known to have started 30.2 min after tracer injection.",
48 "Times and decay will be corrected to the new scan start time:",
49 " @P s2345dy1.v 30.2",
50 "Example 2. Injection time was 14:00:49, and PET times and decay will be",
51 "corrected to this new scan start time:",
52 " @P s2345dy1.v 14:00:49",
54 "See also: imgdecay, eframe, ecatcat, egetstrt, esetstrt, imgunit",
56 "Keywords: ECAT, image, physical decay, modelling",
75int main(
int argc,
char **argv)
77 int ai, help=0, version=0, verbose=1;
80 int matrixNr, is_image=1;
83 char ctifile[FILENAME_MAX], newtime[256], tmp[128], *cptr;
94 int hh=-1, mm=-1, ss=-1;
95 int frame_start_time, first_frame_start_time;
96 float decayf, isotope_halflife;
97 double diftime=nan(
"");
98 double starttime, injtime;
105 if(argc==1) {
tpcPrintUsage(argv[0], info, stderr);
return(1);}
106 ctifile[0]=newtime[0]=(char)0;
109 for(ai=1; ai<argc; ai++)
if(*argv[ai]==
'-') {
110 cptr=argv[ai]+1;
if(*cptr==
'-') cptr++;
if(cptr==NULL)
continue;
112 fprintf(stderr,
"Error: invalid option '%s'.\n", argv[ai]);
117 if(help==2) {
tpcHtmlUsage(argv[0], info,
"");
return(0);}
124 if(access(argv[ai], 0) == -1) {
125 fprintf(stderr,
"Error: file '%s' does not exist.\n", argv[ai]);
128 strcpy(ctifile, argv[ai]); ai++;
133 strlcpy(newtime, argv[ai], 256); ai++;
139 fprintf(stderr,
"Error: invalid argument %s\n", argv[ai]);
145 fprintf(stderr,
"Error: missing command-line argument; try %s --help\n",
156 sscanf(newtime,
"%d:%d:%d", &hh, &mm, &ss);
157 diftime=nan(
""); mode=2;
161 if(ret==0) diftime*=-60.0;
162 if(ret!=0 || diftime==0) {
163 fprintf(stderr,
"Error: invalid time difference.\n");
172 printf(
"ctifile := %s\n", ctifile);
173 printf(
"mode := %d\n", mode);
174 if(mode==1) printf(
"diftime := %g\n", diftime);
176 printf(
"required_scan_start_time := %02d:%02d:%02d\n", hh, mm, ss);
184 if(verbose>1) printf(
"opening file %s\n", ctifile);
185 if(mode==0) fp=fopen(ctifile,
"rb");
else fp=fopen(ctifile,
"r+b");
187 fprintf(stderr,
"Error: cannot open file %s\n", ctifile);
194 if(verbose>2) printf(
"reading main header in file %s\n", ctifile);
198 fprintf(stderr,
"Error (%d): cannot read main header.\n", ret);
199 fclose(fp);
return(3);
202 if(strncmp(e7mhdr.
magic_number, ECAT7V_MAGICNR, 7)==0) {
214 fprintf(stderr,
"Error: illegal file_type in %s\n", ctifile);
215 fclose(fp);
return(4);
219 fprintf(stderr,
"Error (%d): cannot read main header.\n", ret);
220 fclose(fp);
return(3);
226 fprintf(stderr,
"Error: illegal file_type in %s\n", ctifile);
227 fclose(fp);
return(4);
232 if(verbose>1) printf(
"%s is identified as ECAT %d\n", ctifile, fformat);
241 if(!
gmtime_r(&t, &stm) || !strftime(tmp, 32,
"%Y-%m-%d %H:%M:%S", &stm)) {
242 fprintf(stderr,
"Error: invalid scan_start_time in %s\n", ctifile);
243 fclose(fp);
return(5);
245 injtime=stm.tm_sec+60*stm.tm_min+3600*stm.tm_hour;
249 fprintf(stderr,
"Error: invalid scan_start_time in %s\n", ctifile);
250 fclose(fp);
return(5);
255 if(mode==0 || verbose>0) fprintf(stdout,
" scan_start_time := %s\n", tmp);
256 if(verbose>2) fprintf(stdout,
"injtime=%g\n", injtime);
262 if(verbose>2) fprintf(stdout,
" reading matrix list...\n");
266 fprintf(stderr,
"Error (%d): cannot read matrix list.\n", ret);
267 fclose(fp);
return(5);
269 if((fformat==63 && e63mlist.
matrixNr<=0) ||
270 (fformat==7 && e7mlist.
matrixNr<=0)) {
271 fprintf(stderr,
"Error: matrix list is empty.\n");
273 fclose(fp);
return(5);
283 if(verbose>2) printf(
"searching for the earliest frame start time\n");
285 first_frame_start_time=frame_start_time=0;
286 if(fformat==63) matrixNr=e63mlist.
matrixNr;
288 if(verbose>2) printf(
"reading subheaders\n");
289 for(m=0; m<matrixNr; m++) {
301 fprintf(stderr,
"Error: cannot read matrix %u subheader in '%s'.\n",
304 fclose(fp);
return(6);
325 fprintf(stderr,
"Error: cannot read matrix %u subheader in '%s'.\n",
328 fclose(fp);
return(6);
332 first_frame_start_time=frame_start_time;
334 if(frame_start_time<first_frame_start_time)
335 first_frame_start_time=frame_start_time;
339 if(mode==0 || verbose>0)
340 fprintf(stdout,
"First frame starts at %g min (%g s)\n",
341 (
double)first_frame_start_time/60000.,
342 (
double)first_frame_start_time/1000.
358 diftime=(3600*hh+60*mm+ss)-injtime;
359 if(verbose>1) fprintf(stdout,
"diftime := %d s\n", (
int)diftime);
362 if((first_frame_start_time>1000 &&
363 fabs(diftime+(first_frame_start_time/1000.))<15.0)
364 || fabs(diftime)<1.0 ) {
365 fprintf(stderr,
"Error: times seem to be already corrected.\n");
371 starttime=injtime+diftime;
372 if(verbose>1) fprintf(stdout,
"new_starttime := %d s\n", (
int)starttime);
373 hh=(int)floor(starttime/3600.0);
374 starttime-=3600*hh; mm=(int)floor(starttime/60.0);
375 starttime-=60*mm; ss=(int)floor(starttime);
385 if(!
gmtime_r(&t, &stm) || !strftime(tmp, 32,
"%Y-%m-%d %H:%M:%S", &stm))
391 fprintf(stderr,
"Error: invalid scan_start_time after update\n");
393 fclose(fp);
return(6);
395 if(verbose>0) fprintf(stdout,
" new_scan_start_time := %s\n", tmp);
402 if(verbose>1) printf(
"computing decay correction\n");
405 if(isotope_halflife<=0.0) {
406 fprintf(stderr,
"Error: %s does not contain isotope half-life.\n",
412 fprintf(stdout,
" isotope half-life: %g s\n", isotope_halflife);
413 decayf=exp(-
M_LN2*diftime/isotope_halflife);
415 fprintf(stdout,
" common decay correction factor: %g\n", decayf);
426 fprintf(stdout,
" correcting the %d subheaders...\n", matrixNr);
427 for(m=0; m<matrixNr; m++) {
441 fprintf(stderr,
"Error: cannot read matrix %u subheader in '%s'.\n",
453 fprintf(stderr,
"Error: cannot write matrix %u subheader in '%s'.\n",
479 fprintf(stderr,
"Error: cannot read matrix %u subheader in '%s'.\n",
497 fprintf(stderr,
"Error: cannot write matrix %u subheader in '%s'.\n",
506 if(verbose>1) fprintf(stdout,
" rewriting corrected main header.\n");
510 fprintf(stderr,
"Error: cannot write the mainheader.\n");
516 fprintf(stdout,
" corrected mainheader and %d subheaders.\n", matrixNr);
struct tm * gmtime_r(const time_t *t, struct tm *tm)
Convert time_t to GMT struct tm.
int atof_with_check(char *double_as_string, double *result_value)
int ecat63ReadMatlist(FILE *fp, MATRIXLIST *ml, int verbose)
void ecat63InitMatlist(MATRIXLIST *mlist)
void ecat63EmptyMatlist(MATRIXLIST *mlist)
void ecat63PrintMatlist(MATRIXLIST *ml)
void ecat63PrintMainheader(ECAT63_mainheader *h, FILE *fp)
char * ecat63ScanstarttimeInt(const ECAT63_mainheader *h, char *buf)
Convert scan_start_time in ECAT 6.3 main header into a null-terminated string of the form YYYY-MM-DD ...
int ecat63ReadScanheader(FILE *fp, int blk, ECAT63_scanheader *h, int verbose, char *errmsg)
int ecat63ReadImageheader(FILE *fp, int blk, ECAT63_imageheader *h, int verbose, char *errmsg)
int ecat63ReadMainheader(FILE *fp, ECAT63_mainheader *h)
int ecat63WriteImageheader(FILE *fp, int block, ECAT63_imageheader *h)
int ecat63WriteScanheader(FILE *fp, int block, ECAT63_scanheader *h)
int ecat63WriteMainheader(FILE *fp, ECAT63_mainheader *h)
void ecat7InitMatlist(ECAT7_MATRIXLIST *mlist)
int ecat7ReadMatlist(FILE *fp, ECAT7_MATRIXLIST *ml, int verbose)
void ecat7EmptyMatlist(ECAT7_MATRIXLIST *mlist)
void ecat7PrintMatlist(ECAT7_MATRIXLIST *ml)
int ecat7ReadScanheader(FILE *fp, int blk, ECAT7_scanheader *h)
int ecat7ReadMainheader(FILE *fp, ECAT7_mainheader *h)
int ecat7Read2DScanheader(FILE *fp, int blk, ECAT7_2Dscanheader *h)
int ecat7ReadImageheader(FILE *fp, int blk, ECAT7_imageheader *h)
int ecat7WriteScanheader(FILE *fp, int blk, ECAT7_scanheader *h)
int ecat7WriteImageheader(FILE *fp, int blk, ECAT7_imageheader *h)
int ecat7Write2DScanheader(FILE *fp, int blk, ECAT7_2Dscanheader *h)
int ecat7WriteMainheader(FILE *fp, ECAT7_mainheader *h)
Header file for libtpcimgio.
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)
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)
short int scan_start_second
short int scan_start_minute
short int scan_start_hour