8#include "tpcclibConfig.h"
23static char *info[] = {
24 "Linear (dot-to-dot) interpolation and integration of PET time-activity data.",
26 "Usage: @P [options] tacfile [outputfile]",
30 " TACs are interpolated (-y, default), integrated (-i), or the 2nd",
31 " integral (-ii) is calculated.",
32 " -X=<x1,x2,...> or -C=<start,stop,step> or -F=<xfile>",
33 " The sample times for interpolated or integral TACs can be specified with",
34 " these options; if none of these is given, the sample times of the",
35 " original datafile are used. Definite sample times can be given after",
36 " -X; regular sample timing can be specified using option -C; with -F the",
37 " sample times can be read from given TAC file.",
39 " Input TACs are interpolated and integrated with sample (0,0) or (t,0)",
40 " as their first measurement points.",
42 " Input TACs are interpolated and integrated with sample (0,y) added",
43 " if TAC starts later than at zero time. With option -0=F the first",
44 " existing sample value is used as y value.",
46 " Descriptive title lines (if header information is available) can be",
47 " included (default), or not included.",
50 "Input TAC data is considered to be non-framed even if it contains frame",
51 "start and end times; if necessary, frame mid times are calculated and used.",
52 "The interpolated or integrated values are calculated exactly at the",
53 "specified sample times, except when the start and end times of PET frames",
54 "are given with -F=<xfile>; then the time frame average values or integrals",
55 "at the frame mid time are calculated.",
57 "If output filename is not specified, the results are written to stdout.",
59 "If result consists of only one value, output file is not given, and option",
60 "-header=no is given, then just the value is printed, without time, for",
61 "easier use in scripts. For example in bash:",
63 " auc=$(interpol -i -x=50 -header=no plasma.dat)",
64 " printf \"AUC=%s\\n\" $auc ",
66 "See also: taccalc, dftinteg, simframe, tacframe, ainterp, taccut, extrapol",
68 "Keywords: TAC, modelling, simulation, tool, AUC, interpolation",
87int main(
int argc,
char **argv)
89 int ai, help=0, version=0, verbose=1;
92 char *cptr, tacfile[FILENAME_MAX], outfile[FILENAME_MAX],
94 static char *mode_str[] = {
"concentration",
"integral",
"2nd_integral", 0};
96 double start0, startY;
105 if(argc==1) {
tpcPrintUsage(argv[0], info, stderr);
return(1);}
107 tacfile[0]=outfile[0]=xfile[0]=(char)0;
109 start0=startY=nan(
"");
111 for(ai=1; ai<argc; ai++)
if(*argv[ai]==
'-') {
113 cptr=argv[ai]+1;
if(*cptr==
'-') cptr++;
if(!*cptr)
continue;
114 if(strcasecmp(cptr,
"Y")==0) {
116 }
else if(strcasecmp(cptr,
"I")==0) {
118 }
else if(strcasecmp(cptr,
"II")==0) {
120 }
else if(strncasecmp(cptr,
"F=", 2)==0) {
122 fprintf(stderr,
"Error: sample times specified with more than one way.\n");
123 free(xlist);
return(1);
125 strcpy(xfile, cptr+2);
if(strlen(xfile)>0)
continue;
126 }
else if(strncasecmp(cptr,
"C=", 2)==0) {
128 fprintf(stderr,
"Error: sample times specified with more than one way.\n");
129 free(xlist);
return(1);
134 if(
atofList(cptr,
";,_|: \t", v, 4) != 3) {
135 fprintf(stderr,
"Error: invalid format with option -C.\n");
138 if(v[0]>=v[1] || v[0]<0.0 || v[2]<=0.0) {
139 fprintf(stderr,
"Error: invalid values with option -C.\n");
143 n=1+(int)ceil(fabs(v[1]-v[0])/v[2]);
145 fprintf(stderr,
"Error: invalid step size.\n");
148 xlist=(
double*)malloc(n*
sizeof(
double));
150 fprintf(stderr,
"Error: out of memory.\n");
155 for(xnr=0; xnr<n; xnr++) {
156 f=v[0]+(double)xnr*v[2];
if(f>v[1])
break;
else xlist[xnr]=f;}
158 }
else if(strncasecmp(cptr,
"X=", 2)==0) {
160 fprintf(stderr,
"Error: sample times specified with more than one way.\n");
161 free(xlist);
return(1);
166 if(xnr<1 || xnr>100) {
167 fprintf(stderr,
"Error: invalid format with option -X.\n");
170 xlist=(
double*)malloc(xnr*
sizeof(
double));
172 fprintf(stderr,
"Error: out of memory.\n");
175 xnr=
atofList(cptr,
";,_|: \t", xlist, xnr);
177 fprintf(stderr,
"Error: invalid format with option -X.\n");
178 free(xlist); xnr=0;
return(1);
182 }
else if(strcasecmp(cptr,
"A")==0) {
183 start0=0.0;
continue;
184 }
else if(strncasecmp(cptr,
"A=", 2)==0) {
185 start0=
atofVerified(cptr+2);
if(isfinite(start0))
continue;
186 }
else if(strncasecmp(cptr,
"0=", 2)==0) {
188 if(strcasecmp(cptr,
"F")==0) {startY=-1.0E+20;
continue;}
189 startY=
atofVerified(cptr);
if(isfinite(startY))
continue;
190 }
else if(strncasecmp(cptr,
"HEADER=", 7)==0) {
192 if(strncasecmp(cptr,
"YES", 1)==0) {
194 }
else if(strncasecmp(cptr,
"NO", 1)==0) {
197 }
else if(strncasecmp(cptr,
"HDR=", 4)==0) {
199 if(strncasecmp(cptr,
"YES", 1)==0) {
201 }
else if(strncasecmp(cptr,
"NO", 1)==0) {
205 fprintf(stderr,
"Error: invalid option '%s'\n", argv[ai]);
214 if(help==2) {
tpcHtmlUsage(argv[0], info,
"");
return(0);}
220 printf(
"mode := %s\n", mode_str[mode]);
221 if(xfile[0]) printf(
"xfile := %s\n", xfile);
222 if(!isnan(start0)) printf(
"start0 := %g\n", start0);
223 if(!isnan(startY)) printf(
"startY := %g\n", startY);
226 for(
int i=0; i<xnr; i++) printf(
" %g", xlist[i]);
232 if(ai<argc)
strlcpy(tacfile, argv[ai++], FILENAME_MAX);
233 if(ai<argc)
strlcpy(outfile, argv[ai++], FILENAME_MAX);
235 fprintf(stderr,
"Error: invalid argument '%s'.\n", argv[ai]);
240 fprintf(stderr,
"Error: missing file name.\n");
246 printf(
"tacfile := %s\n", tacfile);
247 if(outfile[0]) printf(
"outfile := %s\n", outfile);
254 if(verbose>1) printf(
"reading %s\n", tacfile);
255 ret=
tacRead(&tac1, tacfile, &status);
258 tacFree(&tac1); free(xlist);
return(2);
262 printf(
"tacNr := %d\n", tac1.
tacNr);
263 printf(
"sampleNr := %d\n", tac1.
sampleNr);
271 tacFree(&tac1); free(xlist);
return(2);
276 if(verbose>1) printf(
"missing concentrations.\n");
280 fprintf(stderr,
"Error: missing concentrations in %s.\n", tacfile);
281 tacFree(&tac1); free(xlist);
return(2);
288 if(isnormal(start0)) {
289 if(verbose>1) printf(
"adding initial point\n");
292 x=tac1.
x[0]; x1=tac1.
x1[0]; x2=tac1.
x2[0];
293 tac1.
x[0]=tac1.
x1[0]=tac1.
x2[0]=1.0;
297 if(verbose>=0) printf(
"Note: check the data and option -A\n");
298 tacFree(&tac1); free(xlist);
return(3);
300 tac1.
x[1]=x; tac1.
x1[1]=x1; tac1.
x2[1]=x2;
302 tac1.
x[0]=tac1.
x1[0]=tac1.
x2[0]=start0;
303 for(
int j=0; j<tac1.
tacNr; j++) tac1.
c[j].
y[0]=0.0;
306 for(
int i=1; i<tac1.
sampleNr; i++) tac1.
x[i]=0.5*(tac1.
x1[i]+tac1.
x2[i]);
309 if(verbose>4) printf(
"deleting sample x=%g\n", tac1.
x[1]);
313 fprintf(stderr,
"Error: invalid data or option -A.\n");
314 tacFree(&tac1); free(xlist);
return(3);
323 if(isnormal(startY) && tac1.
x[0]>0.0) {
324 if(verbose>1) printf(
"adding initial value at zero\n");
328 if(verbose>=0) printf(
"Note: check the data and option -0\n");
329 tacFree(&tac1); free(xlist);
return(4);
332 tac1.
x[0]=tac1.
x1[0]=tac1.
x2[0]=0.0;
334 if(startY<-1.0E+10 && tac1.sampleNr>1)
335 for(
int j=0; j<tac1.
tacNr; j++) tac1.
c[j].
y[0]=tac1.
c[j].
y[1];
337 for(
int j=0; j<tac1.
tacNr; j++) tac1.
c[j].
y[0]=startY;
348 if(verbose>1) printf(
"reading %s\n", xfile);
349 ret=
tacRead(&tac2, xfile, &status);
356 printf(
"tacNr2 := %d\n", tac2.
tacNr);
357 printf(
"sampleNr2 := %d\n", tac2.
sampleNr);
364 fprintf(stderr,
"Warning: different or unknown time units.\n");
371 fprintf(stderr,
"Error: %s\n",
errorMsg(ret));
386 if(verbose>1) printf(
"allocating memory for %d samples\n", xnr);
389 fprintf(stderr,
"Error: %s\n",
errorMsg(ret));
400 for(
int j=0; j<xnr; j++) tac2.
x[j]=xlist[j];
407 fprintf(stderr,
"Error: %s\n",
errorMsg(ret));
416 printf(
"_tacNr2 := %d\n", tac2.
_tacNr);
417 printf(
"_sampleNr2 := %d\n", tac2.
_sampleNr);
418 printf(
"tacNr2 := %d\n", tac2.
tacNr);
419 printf(
"sampleNr2 := %d\n", tac2.
sampleNr);
428 if(verbose>1) printf(
"interpolating\n");
429 if(tac2.
isframe)
for(
int j=0; j<tac1.
tacNr && ret==0; j++) {
433 }
else for(
int j=0; j<tac1.
tacNr && ret==0; j++) {
439 if(verbose>1) printf(
"integrating\n");
440 if(tac2.
isframe)
for(
int j=0; j<tac1.
tacNr && ret==0; j++) {
444 }
else for(
int j=0; j<tac1.
tacNr && ret==0; j++) {
450 if(verbose>1) printf(
"computing 2nd integrals\n");
451 if(tac2.
isframe)
for(
int j=0; j<tac1.
tacNr && ret==0; j++) {
455 }
else for(
int j=0; j<tac1.
tacNr && ret==0; j++) {
462 fprintf(stderr,
"Error: cannot interpolate/integrate.\n");
463 if(verbose>1) printf(
"return_code := %d\n", ret);
478 if(verbose>1) printf(
"writing %s\n", outfile);
479 fp=fopen(outfile,
"w");
481 fprintf(stderr,
"Error: cannot open file for writing (%s)\n", outfile);
487 fprintf(stdout,
"%g\n", tac2.
c[0].
y[0]);
495 if(outfile[0]) fclose(fp);
500 if(verbose>=0 && outfile[0]) printf(
"%s saved.\n", outfile);
double atofVerified(const char *s)
int atofList(const char *s1, const char *s2, double *x, int maxn)
int iftDuplicate(IFT *ift1, IFT *ift2)
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 statSortDouble(double *data, unsigned int n, int order)
void statusInit(TPCSTATUS *s)
char * errorMsg(tpcerror e)
void statusSet(TPCSTATUS *s, const char *func, const char *srcfile, int srcline, tpcerror error)
int strTokenNr(const char *s1, const char *s2)
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 tacDuplicate(TAC *tac1, TAC *tac2)
Make a duplicate of TAC structure.
int tacAllocate(TAC *tac, int sampleNr, int tacNr)
int tacAllocateMore(TAC *tac, int tacNr)
int tacCopyTacchdr(TACC *d1, TACC *d2)
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 tacXUnitConvert(TAC *tac, const int u, 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.
Header file for library libtpcextensions.
@ WEIGHTING_OFF
Not weighted or weights not available (weights for all included samples are 1.0).
char * unitName(int unit_code)
Header file for library libtpcift.
Header file for libtpcli.
Header file for libtpcstatist.
Header file for library libtpctac.
@ TAC_FORMAT_UNKNOWN
Unknown format.
@ TAC_FORMAT_SIMPLE
x and y's with space delimiters
@ TAC_FORMAT_DFT
Data format of Turku PET Centre.