9#include "tpcclibConfig.h"
23static char *info[] = {
24 "Calculate TACs of authentic (unchanged) tracer and radioactive",
25 "metabolite(s) from measured plasma TAC and fractions of authentic tracer.",
27 "Usage: @P [Options] plasmafile fractionfile",
29 "Fraction file can have either of two formats:",
30 " 1) it can contain the sample times (min), and the fraction(s) of authentic",
31 " tracer, and optionally the fractions of different metabolites; or",
32 " 2) parameters of a mathematical function fitted to the fraction curves.",
34 "By default, result TACs are written in files named as *_pure.* and",
35 "*_met.*, and if several metabolites exist, the following as *_met2.*",
39 " -fnpure=<filename>",
40 " Replace default filename parent tracer TAC.",
42 " Replace default filename for the plasma metabolite TAC.",
43 " -fnmet2=<filename>",
44 " Replace default filename the second plasma metabolite TAC.",
45 " -fnmet3=<filename>",
46 " Replace default filename the 3rd plasma metabolite TAC.",
48 " The result file is named by adding specified id text before file",
49 " extension, instead of the default '_pure'.",
51 " The result file is named by adding specified id text before file",
52 " name extension, instead of the default '_met'.",
54 " The result file is named by adding specified id text before file",
55 " name extension, instead of the default '_met2'.",
57 " The result file is named by adding specified id text before file",
58 " name extension, instead of the default '_met3'.",
61 "See also: fit_ppf, fit_fexp, fit2dat, tac2svg, taccalc",
63 "Keywords: input, plasma, TAC, modelling, metabolite correction",
82int main(
int argc,
char **argv)
84 int ai, help=0, version=0, verbose=1;
85 int ri, fi, fj, n, filetype, ret;
89 char *cptr, tmp[FILENAME_MAX], plfile[FILENAME_MAX], ratfile[FILENAME_MAX];
90 char output_id0[128], output_id1[128], output_id2[128], output_id3[128];
97 if(argc==1) {
tpcPrintUsage(argv[0], info, stderr);
return(1);}
98 plfile[0]=ratfile[0]=(char)0;
99 for(n=0; n<4; n++) outfile[n]=(
char*)NULL;
100 strcpy(output_id0,
"_pure");
101 strcpy(output_id1,
"_met");
102 strcpy(output_id2,
"_met2");
103 strcpy(output_id3,
"_met3");
106 for(ai=1; ai<argc; ai++)
if(*argv[ai]==
'-') {
107 cptr=argv[ai]+1;
if(*cptr==
'-') cptr++;
if(cptr==NULL)
continue;
109 if(strncasecmp(cptr,
"PURE=", 5)==0) {
110 cptr+=5;
if(strlen(cptr)>0 && strlen(cptr)<128) {
111 strlcpy(output_id0, cptr, 128);
continue;}
112 }
else if(strncasecmp(cptr,
"MET=", 4)==0) {
113 cptr+=4;
if(strlen(cptr)>0 && strlen(cptr)<128) {
114 strlcpy(output_id1, cptr, 128);
continue;}
115 }
else if(strncasecmp(cptr,
"MET2=", 5)==0) {
116 cptr+=5;
if(strlen(cptr)>0 && strlen(cptr)<128) {
117 strlcpy(output_id2, cptr, 128);
continue;}
118 }
else if(strncasecmp(cptr,
"MET3=", 5)==0) {
119 cptr+=5;
if(strlen(cptr)>0 && strlen(cptr)<128) {
120 strlcpy(output_id3, cptr, 128);
continue;}
121 }
else if(strncasecmp(cptr,
"FNPURE=", 7)==0) {
122 cptr+=7;
if(strlen(cptr)>0 && strlen(cptr)<FILENAME_MAX) {
123 outfile[0]=cptr;
continue;}
124 }
else if(strncasecmp(cptr,
"FNMET=", 6)==0) {
125 cptr+=6;
if(strlen(cptr)>0 && strlen(cptr)<FILENAME_MAX) {
126 outfile[1]=cptr;
continue;}
127 }
else if(strncasecmp(cptr,
"FNMET2=", 7)==0) {
128 cptr+=7;
if(strlen(cptr)>0 && strlen(cptr)<FILENAME_MAX) {
129 outfile[2]=cptr;
continue;}
130 }
else if(strncasecmp(cptr,
"FNMET3=", 7)==0) {
131 cptr+=7;
if(strlen(cptr)>0 && strlen(cptr)<FILENAME_MAX) {
132 outfile[3]=cptr;
continue;}
134 fprintf(stderr,
"Error: invalid option '%s'.\n", argv[ai]);
139 if(help==2) {
tpcHtmlUsage(argv[0], info,
"");
return(0);}
144 for(; ai<argc; ai++) {
145 if(!plfile[0]) {strcpy(plfile, argv[ai]);
continue;}
146 else if(!ratfile[0]) {strcpy(ratfile, argv[ai]);
continue;}
147 fprintf(stderr,
"Error: invalid argument '%s'.\n", argv[ai]);
153 fprintf(stderr,
"Error: missing file name for fraction data.\n");
161 printf(
"plfile := %s\n", plfile);
162 printf(
"ratfile := %s\n", ratfile);
163 printf(
"output_id0 := %s\n", output_id0);
164 printf(
"output_id1 := %s\n", output_id1);
165 printf(
"output_id2 := %s\n", output_id2);
166 printf(
"output_id3 := %s\n", output_id3);
167 for(n=0; n<4; n++)
if(outfile[n]) printf(
"outfile%d := %s\n", n, outfile[n]);
174 if(verbose>1) printf(
"reading %s\n", plfile);
176 fprintf(stderr,
"Error in reading '%s': %s\n", plfile,
dfterrmsg);
182 "Warning: plasma file contains several TACs; only the first is used.\n");
188 if(plasma.
timeunit==TUNIT_UNKNOWN) {
190 fprintf(stderr,
"Warning: assuming time_unit := %s\n",
193 int orig_plasma_time_unit=plasma.
timeunit;
197 "Note: plasma sample times are converted to minutes.\n");
203 fprintf(stderr,
"Error in memory allocation.\n");
209 for(ri=1; ri<5; ri++) {
214 cptr=output_id0;
if(cptr[0]==
'_') cptr++; strcpy(plasma.
voi[1].
hemisphere, cptr);
215 cptr=output_id1;
if(cptr[0]==
'_') cptr++; strcpy(plasma.
voi[2].
hemisphere, cptr);
216 cptr=output_id2;
if(cptr[0]==
'_') cptr++; strcpy(plasma.
voi[3].
hemisphere, cptr);
217 cptr=output_id3;
if(cptr[0]==
'_') cptr++; strcpy(plasma.
voi[4].
hemisphere, cptr);
218 for(ri=1; ri<5; ri++)
223 if(!isnan(plasma.
voi[0].
y[fi])) {fi++;
continue;}
224 for(fj=fi+1; fj<plasma.
frameNr; fj++) {
225 plasma.
x1[fj-1]=plasma.
x1[fj];
226 plasma.
x2[fj-1]=plasma.
x2[fj];
227 plasma.
x[fj-1]=plasma.
x[fj];
228 plasma.
voi[0].
y[fj-1]=plasma.
voi[0].
y[fj];
229 plasma.
w[fj-1]=plasma.
w[fj];
233 if(verbose>2) printf(
"%d non-available sample(s) removed from plasma TAC.\n",
236 fprintf(stderr,
"Error in %s: invalid contents.\n", plfile);
244 if(verbose>1) printf(
"Reading fractions.\n");
248 fp=fopen(ratfile,
"r");
250 fprintf(stderr,
"Error: cannot open '%s'.\n", ratfile);
258 fprintf(stderr,
"Error: unknown fraction file format.\n");
261 if(verbose>2) printf(
"Fractions filetype=%d\n", filetype);
266 if(verbose>1) printf(
"reading %s\n", ratfile);
267 if(
fitRead(ratfile, &fit, verbose-5)) {
268 fprintf(stderr,
"Error in reading '%s': %s\n", ratfile,
fiterrmsg);
276 fprintf(stderr,
"Error in '%s': too many metabolites.\n", ratfile);
281 fprintf(stderr,
"Warning: excessive extrapolation needed for fractions.\n");
284 for(ri=0; ri<fit.
voiNr; ri++) {
287 fprintf(stderr,
"Error %d in function evaluation.\n", ret);
294 for(fi=0, v_max=v=0.0; fi<plasma.
frameNr; fi++) {
295 for(ri=1, v=0.0; ri<plasma.
voiNr; ri++) v+=plasma.
voi[ri].
y2[fi];
298 if(verbose>2) printf(
"v_max=%g\n", v_max);
300 fprintf(stderr,
"Error: invalid fraction values.\n");
304 fprintf(stderr,
"Warning: converting percentages to fractions.\n");
305 for(fi=0; fi<plasma.
frameNr; fi++)
for(ri=1; ri<plasma.
voiNr; ri++)
306 plasma.
voi[ri].
y2[fi]/=100.0;
312 if(verbose>1) printf(
"reading %s\n", ratfile);
314 fprintf(stderr,
"Error in reading '%s': %s\n", ratfile,
dfterrmsg);
321 fprintf(stderr,
"Error in '%s': too many metabolites.\n", ratfile);
325 for(fi=0, v_max=v=0.0; fi<fract.
frameNr; fi++) {
326 for(ri=0, v=0.0; ri<fract.
voiNr; ri++)
327 if(!isnan(fract.
voi[ri].
y[fi])) v+=fract.
voi[ri].
y[fi];
330 if(verbose>2) printf(
"v_max=%g\n", v_max);
332 fprintf(stderr,
"Error: invalid fraction values.\n");
336 fprintf(stderr,
"Warning: converting percentages to fractions.\n");
337 for(fi=0; fi<fract.
frameNr; fi++)
for(ri=0; ri<fract.
voiNr; ri++)
338 if(!isnan(fract.
voi[ri].
y[fi])) fract.
voi[ri].
y[fi]/=100.0;
342 if(verbose>2) printf(
"adding zero fraction sample\n");
345 fprintf(stderr,
"Error in processing fractions.\n");
348 fract.
voi[0].
y[0]=1.0;
352 for(ri=n=0; ri<fract.
voiNr; ri++)
for(fi=0; fi<fract.
frameNr; fi++) {
353 if(isnan(fract.
voi[ri].
y[fi])) {
355 fprintf(stderr,
"Error: missing metabolite fraction(s).\n");
362 if(verbose>1) printf(
"replacing NAs in fractions\n");
365 fprintf(stderr,
"Error in replacing missing fractions.\n");
372 fprintf(stderr,
"Error: excessive extrapolation needed for fractions.\n");
376 fprintf(stderr,
"Warning: excessive extrapolation needed for fractions.\n");
379 if(verbose>1) printf(
"interpolation of fractions\n");
380 for(ri=0; ri<fract.
voiNr; ri++) {
383 plasma.
x1, plasma.
x2, plasma.
voi[ri+1].
y2, NULL, NULL,
389 fprintf(stderr,
"Error in interpolation.\n");
401 if(plasma.
voiNr==2) {
403 printf(
"calculating metabolite fractions for extra metabolite\n");
404 for(fi=0; fi<plasma.
frameNr; fi++)
405 plasma.
voi[2].
y2[fi]=1.0-plasma.
voi[1].
y2[fi];
409 if(verbose>1) printf(
"checking the sum of fractions\n");
410 for(fi=0, v_max=0.0, n=0; fi<plasma.
frameNr; fi++) {
411 for(ri=1, v=0.0; ri<plasma.
voiNr; ri++) v+=plasma.
voi[ri].
y2[fi];
413 if(v>0.0) n++;
else continue;
414 if((1.0-v)>v_max) v_max=1.0-v;
416 if(verbose>2 && (v_max>0 || n>0))
417 printf(
"sum of fractions was less than 1.0; vmax=%g n=%d\n", v_max, n);
418 if(v_max>0.02 && n>1) {
420 fprintf(stderr,
"Error: sum of fractions was less than 1.0.\n");
423 printf(
"sum of fractions was less than 1.0; assuming another metabolite.\n");
433 for(ri=1; ri<plasma.
voiNr; ri++) {
435 for(fi=0; fi<plasma.
frameNr; fi++)
436 plasma.
voi[ri].
y[fi]=plasma.
voi[0].
y[fi]*plasma.
voi[ri].
y2[fi];
440 if(plasma.
timeunit!=orig_plasma_time_unit) {
441 if(verbose>3) printf(
"converting plasma %s to %s\n",
443 if(verbose>4) printf(
"last_t := %g\n", plasma.
x[plasma.
frameNr-1]);
445 if(verbose>4) printf(
"last_t := %g\n", plasma.
x[plasma.
frameNr-1]);
453 for(ri=1; ri<n; ri++) {
457 fprintf(stderr,
"Error in processing TACs.\n");
462 strcpy(tmp, outfile[ri-1]);
464 strcpy(tmp, plfile); cptr=strrchr(tmp,
'.');
if(cptr!=NULL) *cptr=(char)0;
466 case 1: strcat(tmp, output_id0);
break;
467 case 2: strcat(tmp, output_id1);
break;
468 case 3: strcat(tmp, output_id2);
break;
469 case 4: strcat(tmp, output_id3);
break;
471 fprintf(stderr,
"Error in programmer.\n");
474 cptr=strrchr(plfile,
'.');
if(cptr!=NULL) strcat(tmp, cptr);
477 if(verbose>0) fprintf(stdout,
" writing %s\n", tmp);
480 fprintf(stderr,
"Error (%d) in writing '%s': %s\n", ret, tmp,
dfterrmsg);
int dftAddnullframe(DFT *data)
int dftAddmem(DFT *dft, int voiNr)
int dftCopyvoi(DFT *data, int from, int to)
int dftRead(char *filename, DFT *data)
int dftFormat(char *fname)
int dftWrite(DFT *data, char *filename)
int dftTimeunitConversion(DFT *dft, int tunit)
int interpolate(double *x, double *y, int nr, double *newx, double *newy, double *newyi, double *newyii, int newnr)
Linear interpolation and integration.
int interpolate4pet(double *x, double *y, int nr, double *newx1, double *newx2, double *newy, double *newyi, double *newyii, int newnr)
Interpolate and integrate TAC to PET frames.
Header file for libtpccurveio.
int fitEvaltac(FitVOI *r, double *x, double *y, int dataNr)
int fitRead(char *filename, FIT *fit, int verbose)
#define DFT_TIME_STARTEND
#define DFT_FORMAT_UNKNOWN
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)
char * petTunit(int tunit)
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)
Header file for libtpcmodel.
char voiname[MAX_REGIONSUBNAME_LEN+1]
char name[MAX_REGIONNAME_LEN+1]
char hemisphere[MAX_REGIONSUBNAME_LEN+1]
char place[MAX_REGIONSUBNAME_LEN+1]