9#include "tpcclibConfig.h"
23static char *info[] = {
24 "Make arithmetic calculations with PET time-activity data.",
25 "Operations can be made between two TAC files or between one TAC file and",
28 "Usage: @P [options] file1 operation constant|file2 outputfile",
32 " Program does not mind if the time or calibration units",
33 " cannot be converted to match.",
36 "Example 1: Add constant 2 to all activity concentrations in pet.dat",
37 " @P pet.dat + 2 sum.dat",
38 "Example 2: Subtract one TAC from all TACs in the first data file",
39 " @P cortex.dat - reference.dat bound.dat",
41 "The first TAC file can have one or more TACs. Second TAC file may",
42 "contain either only one TAC or equally many TACs as the first file",
43 "(if the TAC number is different, only the first TAC is used).",
44 "Data is interpolated, if necessary, to the times of the first file.",
45 "If the second file contains only one sample time (frame), the value",
46 "from that sample will be used for all the samples of the first file.",
48 "The following characters are accepted as operators: +, -, x, and :.",
50 "See also: tacunit, metabcor, dftsuv, dftratio, taccbv, fit2dat, tacinv",
52 "Keywords: TAC, modelling, simulation, tool",
71int main(
int argc,
char **argv)
73 int ai, help=0, version=0, verbose=1;
78 char *cptr, d1file[FILENAME_MAX], d2file[FILENAME_MAX], rfile[FILENAME_MAX];
80 TAC tac1, tac2, itac2;
86 if(argc==1) {
tpcPrintUsage(argv[0], info, stderr);
return(1);}
88 d1file[0]=d2file[0]=rfile[0]=(char)0;
90 for(ai=1; ai<argc; ai++)
if(*argv[ai]==
'-') {
92 cptr=argv[ai]+1;
if(*cptr==
'-') cptr++;
if(!*cptr)
continue;
93 if(strcasecmp(cptr,
"F")==0 || strcasecmp(cptr,
"FORCE")==0) {
94 checkUnits=0;
continue;
95 }
else if(strcasecmp(cptr,
"NT")==0) {
97 checkUnits=0;
continue;
99 fprintf(stderr,
"Error: invalid option '%s'\n", argv[ai]);
108 if(help==2) {
tpcHtmlUsage(argv[0], info,
"");
return(0);}
113 for(; ai<argc; ai++) {
114 if(verbose>3) printf(
"argv[%d] := '%s'\n", ai, argv[ai]);
116 strcpy(d1file, argv[ai]);
continue;
117 }
else if(operation==0) {
118 if(strcasecmp(argv[ai],
"DIV")==0) {operation=4;
continue;}
120 case '+' : operation=1;
break;
121 case '-' : operation=2;
break;
125 case 'x' : operation=3;
break;
127 case ':' : operation=4;
break;
129 if(strlen(argv[ai])>1 || operation==0) {
130 fprintf(stderr,
"Error: invalid operator.\n");
134 }
else if(isvalue==0 && !d2file[0]) {
136 if(ret==0) {isvalue=1;
continue;}
137 else strcpy(d2file, argv[ai]);
139 }
else if(!rfile[0]) {
140 strcpy(rfile, argv[ai]);
continue;
142 fprintf(stderr,
"Error: invalid argument '%s'.\n", argv[ai]);
147 if(!rfile[0]) {
tpcPrintUsage(argv[0], info, stdout);
return(1);}
152 for(ai=0; ai<argc; ai++) printf(
"%s ", argv[ai]);
154 printf(
"d1file := %s\n", d1file);
155 printf(
"operation := %d\n", operation);
156 if(isvalue) printf(
"value := %g\n", value);
157 else printf(
"d2file := %s\n", d2file);
158 printf(
"rfile := %s\n", rfile);
159 printf(
"checkUnits = %d\n", checkUnits);
167 if(verbose>1) printf(
"reading %s\n", d1file);
168 ret=
tacRead(&tac1, d1file, &status);
170 fprintf(stderr,
"Error (%d): %s\n", ret,
errorMsg(status.
error));
175 printf(
"tacNr := %d\n", tac1.
tacNr);
176 printf(
"sampleNr := %d\n", tac1.
sampleNr);
185 if(isvalue==0 && d2file[0]) {
187 if(verbose>1) printf(
"reading %s\n", d1file);
188 ret=
tacRead(&tac2, d2file, &status);
190 fprintf(stderr,
"Error (%d): %s\n", ret,
errorMsg(status.
error));
195 printf(
"tacNr := %d\n", tac2.
tacNr);
196 printf(
"sampleNr := %d\n", tac2.
sampleNr);
202 if(verbose>2) printf(
"file #2 contains the constant.\n");
206 fprintf(stderr,
"Note: %s and %s have different or unknown concentration units.\n",
208 if(verbose>2) fprintf(stderr,
"Status: %s\n",
errorMsg(status.
error));
220 value=tac2.
c[0].
y[0];
221 if(verbose>1) printf(
"using %g as the constant value.\n", value);
234 fprintf(stderr,
"Error: cannot operate the files.\n");
241 if(verbose>0) fprintf(stderr,
"Note: using only the first TAC.\n");
249 fprintf(stderr,
"Note: %s and %s have different or unknown time units.\n", d1file, d2file);
250 if(verbose>2) fprintf(stderr,
"Status: %s\n",
errorMsg(status.
error));
257 fprintf(stderr,
"Warning: unknown time units.\n");
269 fprintf(stderr,
"Note: %s and %s have different or unknown concentration units.\n",
271 if(verbose>2) fprintf(stderr,
"Status: %s\n",
errorMsg(status.
error));
277 if(operation==3 || operation==4)
289 fprintf(stderr,
"Error: cannot interpolate TAC.\n");
306 if(verbose>1) printf(
"using first sample in %s for all samples in %s\n", d2file, d1file);
308 for(
int fi=0; fi<itac2.
sampleNr; fi++)
309 for(
int ri=0; ri<itac2.
tacNr; ri++)
310 itac2.
c[ri].
y[fi]=tac2.
c[ri].
y[0];
317 if(verbose>1) printf(
"sample times match; no interpolation necessary\n");
318 for(ri=0; ri<itac2.
tacNr; ri++)
320 itac2.
c[ri].
y[fi]=tac2.
c[ri].
y[fi];
322 if(verbose>1) printf(
"interpolating\n");
325 double xmin1, xmin2, xmax1, xmax2, xmin, xmax, xrange;
328 xmin=xmin1;
if(xmin2<xmin) xmin=xmin2;
329 xmax=xmax1;
if(xmax2>xmax) xmax=xmax2;
331 if((xmin2>xmin1 && (xmin2-xmin1)/xrange>0.05) || (xmax2<xmax1 && (xmin1-xmax2)/xrange>0.10)) {
332 fprintf(stderr,
"Warning: check the time ranges.\n");
336 for(ri=0, ret=0; ri<itac2.
tacNr && ret==0; ri++) {
339 itac2.
x1, itac2.
x2, itac2.
c[ri].
y, NULL, NULL, itac2.
sampleNr, 4, 1, verbose-6);
342 itac2.
x, itac2.
c[ri].
y, NULL, NULL, itac2.
sampleNr, 4, 1, verbose-6);
345 fprintf(stderr,
"Error: cannot interpolate TAC %d.\n", 1+ri);
346 if(verbose>1) fprintf(stderr,
"error_code := %d\n", ret);
360 if(!isfinite(value)) {
361 fprintf(stderr,
"Error: invalid value of constant.\n");
364 if(operation==4 && fabs(value)<1.0E-12) {
365 fprintf(stderr,
"Error: invalid constant for division.\n");
375 if(verbose>1) printf(
"computing with constant\n");
379 for(ri=0; ri<tac1.
tacNr; ri++)
for(fi=0; fi<tac1.
sampleNr; fi++)
380 if(!isnan(tac1.
c[ri].
y[fi])) tac1.
c[ri].
y[fi]+=value;
383 for(ri=0; ri<tac1.
tacNr; ri++)
for(fi=0; fi<tac1.
sampleNr; fi++)
384 if(!isnan(tac1.
c[ri].
y[fi])) tac1.
c[ri].
y[fi]-=value;
387 for(ri=0; ri<tac1.
tacNr; ri++)
for(fi=0; fi<tac1.
sampleNr; fi++)
388 if(!isnan(tac1.
c[ri].
y[fi])) tac1.
c[ri].
y[fi]*=value;
391 for(ri=0; ri<tac1.
tacNr; ri++)
for(fi=0; fi<tac1.
sampleNr; fi++)
392 if(!isnan(tac1.
c[ri].
y[fi])) tac1.
c[ri].
y[fi]/=value;
396 if(verbose>1) printf(
"computing with TACs\n");
401 for(ri=0; ri<tac1.
tacNr; ri++) {
403 if(itac2.
tacNr==1) y2=itac2.
c[0].
y;
else y2=itac2.
c[ri].
y;
405 if(isfinite(y1[fi]) && isfinite(y2[fi])) y1[fi]+=y2[fi];
else y1[fi]=nan(
"");
409 for(ri=0; ri<tac1.
tacNr; ri++) {
411 if(itac2.
tacNr==1) y2=itac2.
c[0].
y;
else y2=itac2.
c[ri].
y;
413 if(isfinite(y1[fi]) && isfinite(y2[fi])) y1[fi]-=y2[fi];
else y1[fi]=nan(
"");
417 for(ri=0; ri<tac1.
tacNr; ri++) {
419 if(itac2.
tacNr==1) y2=itac2.
c[0].
y;
else y2=itac2.
c[ri].
y;
421 if(isfinite(y1[fi]) && isfinite(y2[fi])) y1[fi]*=y2[fi];
else y1[fi]=nan(
"");
425 for(ri=0; ri<tac1.
tacNr; ri++) {
427 if(itac2.
tacNr==1) y2=itac2.
c[0].
y;
else y2=itac2.
c[ri].
y;
429 if(!isfinite(y1[fi]) || !isfinite(y2[fi])) {y1[fi]=nan(
"");
continue;}
430 if(fabs(y2[fi])<1.0E-12) y1[fi]=0.0;
else y1[fi]/=y2[fi];
443 if(verbose>1) printf(
"writing %s\n", rfile);
444 FILE *fp; fp=fopen(rfile,
"w");
446 fprintf(stderr,
"Error: cannot open file for writing (%s)\n", rfile);
452 fprintf(stderr,
"Error (%d): %s\n", ret,
errorMsg(status.
error));
455 if(verbose>=0) printf(
"%s saved.\n", rfile);
int atofCheck(const char *s, double *v)
int liInterpolate(double *x, double *y, const int nr, double *newx, double *newy, double *newyi, double *newyii, const int newnr, const int se, const int ee, const int verbose)
Linear interpolation and/or integration with trapezoidal method.
int liInterpolateForPET(double *x, double *y, const int nr, double *newx1, double *newx2, double *newy, double *newyi, double *newyii, const int newnr, const int se, const int ee, const int verbose)
Linear TAC interpolation and/or integration to PET frames.
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)
int verbose
Verbose level, used by statusPrint() etc.
tpcerror error
Error code.
int tacAllocate(TAC *tac, int sampleNr, int tacNr)
int tacCopyTacchdr(TACC *d1, TACC *d2)
int tacCopyHdr(TAC *tac1, TAC *tac2)
Copy TAC header data from tac1 to tac2.
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 tacYUnitConvert(TAC *tac, const int u, TPCSTATUS *status)
int tacXUnitConvert(TAC *tac, const int u, TPCSTATUS *status)
int tacXMatch(TAC *d1, TAC *d2, const int verbose)
Check whether sample (frame) times are the same (or very close to) in two TAC structures.
int tacXCopy(TAC *tac1, TAC *tac2, int i1, int i2)
int tacXRange(TAC *d, double *xmin, double *xmax)
Get the range of x values (times) in TAC structure.
Header file for library libtpcextensions.
char * unitName(int unit_code)
Header file for library libtpcift.
Header file for libtpcli.
Header file for library libtpctac.
@ TAC_FORMAT_UNKNOWN
Unknown format.
@ TAC_FORMAT_PMOD
PMOD TAC format.