9#include "tpcclibConfig.h"
25static char *info[] = {
26 "Increase or decrease the sample (frame) times in regional or blood/plasma",
28 "Samples with negative times are not saved by default.",
29 "Time must be given in the same units that are used in the datafile.",
31 "Usage: @P [Options] tacfile [-]time [outputfile]",
33 "Time can be given as positive or negative value directly in the command",
34 "line, or in an ASCII file which contains a line with the time change value",
35 "in the following format: 'time_difference := time'.",
36 "Alternatively, time specified in that file with 'Ta' or 'start_time' is",
37 "subtracted from sample times.",
38 "If 'peak' is given as time, TAC(s) are moved to start at the peak time",
39 "or at start of peak frame.",
40 "If 'gap' is given as time, TAC(s) are moved to remove initial gap time.",
44 " Physical decay correction is changed with change in sample times;",
45 " without this option, radioactivity values are not changed.",
46 " Note that this option will provide correct result only if time unit",
47 " setting in datafile is correct.",
49 " Isotope must be known for the decay correction.",
50 " Accepted isotope codes are for example F-18, C-11, and O-15.",
51 " Isotope code can also be specified in input file in format",
52 " '# isotope := C-11'.",
54 " Samples with negative sample times are not removed from output.",
56 " While correction for physical decay is changed with option -decay,",
57 " sample times will not be changed.",
59 " Possible gap between time zero and first sample is filled.",
62 "See also: tacframe, tacdecay, injdifft, tacunit, fitdelay, tacmove, taccut",
64 "Keywords: TAC, simulation, late scan, input, time delay, peak",
83int main(
int argc,
char **argv)
85 int ai, help=0, version=0, verbose=1;
91 char tacfile1[FILENAME_MAX], tacfile2[FILENAME_MAX];
103 if(argc==1) {
tpcPrintUsage(argv[0], info, stderr);
return(1);}
104 tacfile1[0]=tacfile2[0]=(char)0;
106 for(ai=1; ai<argc; ai++)
if(*argv[ai]==
'-') {
108 char *cptr=argv[ai]+1;
if(*cptr==
'-') cptr++;
if(!*cptr)
continue;
109 if(strcasecmp(cptr,
"DECAY")==0) {
110 change_decay=1;
continue;
111 }
else if(strncasecmp(cptr,
"I=", 2)==0) {
114 fprintf(stderr,
"Error: invalid isotope '%s'.\n", cptr);
118 }
else if(strncasecmp(cptr,
"KEEPNEGATIVE", 5)==0) {
119 keep_negat=1;
continue;
120 }
else if(strncasecmp(cptr,
"KEEPTIMES", 5)==0) {
121 keep_times=1;
continue;
122 }
else if(strncasecmp(cptr,
"NOGAP", 5)==0) {
123 fill_gap=1;
continue;
125 fprintf(stderr,
"Error: invalid option '%s'.\n", argv[ai]);
134 if(help==2) {
tpcHtmlUsage(argv[0], info,
"");
return(0);}
139 if(ai<argc) {
strlcpy(tacfile1, argv[ai], FILENAME_MAX); ai++;}
140 else {fprintf(stderr,
"Error: missing file name.\n");
return(1);}
142 fprintf(stderr,
"Error: file '%s' does not exist.\n", tacfile1);
148 if(verbose>3) printf(
"argument for time difference: '%s'\n", argv[ai]);
150 if(!strcasecmp(
"PEAK", argv[ai]) || !strcasecmp(
"-PEAK", argv[ai])) {
151 peak_start=1; keep_times=0;
152 }
else if(!strcasecmp(
"GAP", argv[ai])) {
156 FILE *fp=fopen(argv[ai],
"r");
158 fprintf(stderr,
"Error: cannot open file %s\n", argv[ai]);
161 int ret=
iftRead(&ift, fp, 1, 1, &status); fclose(fp);
163 fprintf(stderr,
"Error: invalid contents in %s\n", argv[ai]);
167 int i=
iftFindKey(&ift,
"scan_start_time_difference", 0);
if(i>=0) time_sign=+1;
168 if(i<0) {i=
iftFindKey(&ift,
"time_difference", 0);
if(i>=0) time_sign=+1;}
169 if(i<0) {i=
iftFindKey(&ift,
"Ta", 0);
if(i>=0) time_sign=-1;}
170 if(i<0) {i=
iftFindKey(&ift,
"start_time", 0);
if(i>=0) time_sign=-1;}
172 fprintf(stderr,
"Error: keyword for time difference not found in '%s'.\n", argv[ai]);
177 fprintf(stderr,
"Error: invalid format for time in '%s'.\n", argv[ai]);
180 time_diff*=time_sign;
184 fprintf(stderr,
"Error: invalid argument for time: '%s'.\n", argv[ai]);
188 if(verbose>7) printf(
"time_diff := %g\n", time_diff);
189 if(time_diff==0.0 && !peak_start) {
190 fprintf(stderr,
"Warning: time change is zero.\n"); fflush(stderr);
194 fprintf(stderr,
"Error: missing time.\n");
199 if(ai<argc) {
strlcpy(tacfile2, argv[ai], FILENAME_MAX); ai++;}
200 else {strcpy(tacfile2, tacfile1);}
203 if(ai<argc) {fprintf(stderr,
"Error: extra command-line argument.\n");
return(1);}
207 if(keep_times==1 && change_decay==0) {
208 fprintf(stderr,
"Error: change in neither sample times or decay correction were requested.\n");
211 if(keep_times==1) keep_negat=1;
215 printf(
"tacfile1 := %s\n", tacfile1);
216 printf(
"tacfile2 := %s\n", tacfile2);
217 printf(
"keep_times := %d\n", keep_times);
218 printf(
"keep_negat := %d\n", keep_negat);
219 printf(
"fill_gap := %d\n", fill_gap);
220 printf(
"change_decay := %d\n", change_decay);
222 printf(
"peak_start := %d\n", peak_start);
223 printf(
"gap_start := %d\n", gap_start);
225 printf(
"time_diff := %g\n", time_diff);
235 if(verbose>1) printf(
"reading %s\n", tacfile1);
243 printf(
"tacNr := %d\n", tac.
tacNr);
244 printf(
"sampleNr := %d\n", tac.
sampleNr);
245 if(tac.
isframe) printf(
"frames := yes\n");
else printf(
"frames := no\n");
259 fprintf(stderr,
"Error: invalid sample range.\n");
262 if(verbose>1) printf(
"x_range: %g - %g\n", xmin, xmax);
263 if(!(xmax>xmin)) {fprintf(stderr,
"Warning: check the sample times.\n"); fflush(stderr);}
267 if(verbose>1) printf(
"gap_time_diff := %g\n", time_diff);
273 if(
tacYRange(&tac, -1, &ymin, &ymax, NULL, &ymax_index, NULL, NULL)) {
274 fprintf(stderr,
"Error: invalid concentration range.\n");
277 if(verbose>1) printf(
"y_range: %g - %g\n", ymin, ymax);
278 if(!(ymax>ymin)) {fprintf(stderr,
"Warning: check the data.\n"); fflush(stderr);}
282 if(tac.
isframe) time_diff=-tac.
x1[ymax_index];
else time_diff=-tac.
x[ymax_index];
283 time_diff_unit=tac.
tunit;
285 printf(
"peak_index := %d\n", ymax_index);
286 printf(
"time_diff := %g\n", time_diff);
295 if(verbose>3) {printf(
"tac.isotope := %s\n",
isotopeName(fisot)); fflush(stdout);}
298 if(verbose>1) printf(
"isotope := %s\n",
isotopeName(isot));
303 fprintf(stderr,
"Error: different isotope in %s\n", tacfile1);
310 fprintf(stderr,
"Error: isotope not specified.\n");
316 fprintf(stderr,
"Error: sample time unit unknown.\n");
324 fprintf(stderr,
"Error: incompatible time units.\n");
327 time_diff*=f; time_diff_unit=tac.
tunit;
329 if(verbose>1) printf(
"final_time_diff := %g %s\n", time_diff,
unitName(tac.
tunit));
338 tac.
x[i]+=time_diff; tac.
x1[i]+=time_diff; tac.
x2[i]+=time_diff;
346 fprintf(stderr,
"Error: No positive times left.\n");
352 if(verbose>1) printf(
"filling initial time gap\n");
354 fprintf(stderr,
"Error: cannot fill time gap.\n");
363 if(change_decay && time_diff!=0.0) {
364 if(verbose>3) printf(
"decay correcting for time %g\n", time_diff);
367 if(verbose>5) printf(
" tdiff := %g\n", tdiff);
369 if(time_diff<0.0) dcf=1.0/dcf;
371 fprintf(stderr,
"Error: cannot calculate decay correction factor.\n");
374 if(verbose>1) printf(
"decay_correction_factor := %g\n", dcf);
376 for(
int j=0; j<tac.
tacNr; j++)
for(
int i=0; i<tac.
sampleNr; i++) tac.
c[j].
y[i]*=dcf;
379 for(
int i=0; i<tac.
sampleNr; i++) tac.
w[i]/=dcf;
392 if(verbose>2) printf(
"injection_time: %s\n", buf);
394 if(verbose>5) printf(
" injection_time_tdiff := %g s\n", tdiff);
397 fprintf(stderr,
"Error: cannot correct injection time.\n");
400 if(verbose>0) printf(
"updated_injection_time := %s\n", buf);
408 if(verbose>1) printf(
"saving modified data in %s\n", tacfile2);
410 FILE *fp; fp=fopen(tacfile2,
"w");
412 fprintf(stderr,
"Error: cannot open file for writing\n");
424 if(keep_times==0) fprintf(stdout,
"Sample times changed by %g", time_diff);
425 else fprintf(stdout,
"Injection time changed by %g", -time_diff);
426 if(change_decay) fprintf(stdout,
" and values with decay of %s",
isotopeName(isot));
427 fprintf(stdout,
" in %s\n", tacfile2);
int strDateTimeAdd(int s, char *dt)
double decayCorrectionFactorFromIsotope(int isotope, double starttime, double duration)
int atofCheck(const char *s, double *v)
int fileExist(const char *filename)
int iftFindKey(IFT *ift, const char *key, int start_index)
int iftGetDoubleWithUnit(IFT *ift, int index, double *v, int *unit)
int iftRead(IFT *ift, FILE *fp, int is_key_required, int is_comment_accepted, TPCSTATUS *status)
char * isotopeName(int isotope_code)
int isotopeIdentify(const char *isotope)
int tpcProcessStdOptions(const char *s, int *print_usage, int *print_version, int *verbose_level)
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)
void statusInit(TPCSTATUS *s)
char * errorMsg(tpcerror e)
void statusSet(TPCSTATUS *s, const char *func, const char *srcfile, int srcline, tpcerror error)
size_t strlcpy(char *dst, const char *src, size_t dstsize)
IFT h
Optional (but often useful) header information.
int verbose
Verbose level, used by statusPrint() etc.
tpcerror error
Error code.
int tacGetIsotope(TAC *tac)
void tacSetIsotope(TAC *tac, int isotope)
int tacGetHeaderInjectiontime(IFT *h, char *s, TPCSTATUS *status)
int tacSetHeaderInjectiontime(IFT *h, const char *s)
int tacRead(TAC *d, const char *fname, TPCSTATUS *status)
char * tacFormattxt(tacformat c)
int tacWrite(TAC *tac, FILE *fp, tacformat format, int extra, TPCSTATUS *status)
int tacSortByTime(TAC *d, TPCSTATUS *status)
int tacIsWeighted(TAC *tac)
int tacWeightNorm(TAC *tac, TPCSTATUS *status)
int tacAddZeroSample(TAC *d, TPCSTATUS *status)
Add an initial sample to TAC(s) with zero time and concentration.
int tacDeleteSample(TAC *d, int i)
Delete a certain sample (time frame) from TAC structure.
int tacXRange(TAC *d, double *xmin, double *xmax)
Get the range of x values (times) in TAC structure.
int tacYRange(TAC *d, int i, double *ymin, double *ymax, int *smin, int *smax, int *imin, int *imax)
Get the range of y values (concentrations) in TAC struct.
Header file for library libtpccsv.
Header file for library libtpcextensions.
@ UNIT_UNKNOWN
Unknown unit.
double unitConversionFactor(const int u1, const int u2)
char * unitName(int unit_code)
Header file for libtpcfileutil.
Header file for library libtpcift.
Header file for library libtpcisotope.
@ ISOTOPE_UNKNOWN
Unknown.
Header file for library libtpctac.
@ TAC_FORMAT_UNKNOWN
Unknown format.