9#include "tpcclibConfig.h"
26static char *info[] = {
27 "Subtracts the contribution of vascular radioactivity from regional",
28 "PET TTACs. Vascular volume fraction Vb can be given as a value that is",
29 "common to all regions, or as regional Vb values in a TAC or PAR file,",
30 "calculated from a [O-15]CO study or estimated by model fitting.",
32 "Usage: @P ttacfile btacfile Vb [outputfile]",
36 " Negative TAC values are set to 0.",
38 " Equation Ct=Cpet-Vb*Cb is applied by default or with option -pv;",
39 " with option -tv equation Ct=(Cpet-Vb*Cb)/(1-Vb) is applied.",
41 " Simulate the contribution of vascular radioactivity instead of",
42 " correcting for it, calculating Cpet from Ct using equations above.",
44 " Program does not mind if the time or calibration units",
45 " cannot be converted to match, or if TAC names do not match.",
49 " @P uo372.tac uo372ab.bld 0.045 uo372cbv.tac",
51 " @P uo372.dft uo372ab.kbq uo372vb.dft uo372cbv.dft",
53 "Vb values that are >=1 are assumed to be percentages.",
54 "Blood TAC can be given in a separate BTAC file, or as a region id inside",
55 "TTAC file. Original TTAC file is modified, if output file is not given.",
57 "See also: imgcbv, p2blood, fitvb, tacadd, interpol, taccalc, tacunit",
59 "Keywords: TAC, modelling, vascular fraction, simulation",
78int main(
int argc,
char **argv)
80 int ai, help=0, version=0, verbose=1;
81 char ttacfile[FILENAME_MAX], btacfile[FILENAME_MAX], outfile[FILENAME_MAX],
82 parfile[FILENAME_MAX];
93 if(argc==1) {
tpcPrintUsage(argv[0], info, stderr);
return(1);}
94 ttacfile[0]=btacfile[0]=outfile[0]=parfile[0]=(char)0;
97 for(ai=1; ai<argc; ai++)
if(*argv[ai]==
'-') {
99 char *cptr=argv[ai]+1;
if(*cptr==
'-') cptr++;
if(!*cptr)
continue;
100 if(strncasecmp(cptr,
"NONEGATIVES", 1)==0) {
101 leaveNegatives=0;
continue;
102 }
else if(strncasecmp(cptr,
"PV", 1)==0) {
103 petVolume=1;
continue;
104 }
else if(strncasecmp(cptr,
"TV", 1)==0) {
105 petVolume=0;
continue;
106 }
else if(strncasecmp(cptr,
"SIMULATE", 3)==0) {
108 }
else if(strcasecmp(cptr,
"F")==0 || strcasecmp(cptr,
"FORCE")==0) {
109 forceMode=1;
continue;
111 fprintf(stderr,
"Error: invalid option '%s'\n", argv[ai]);
120 if(help==2) {
tpcHtmlUsage(argv[0], info,
"");
return(0);}
125 if(ai<argc)
strlcpy(ttacfile, argv[ai++], FILENAME_MAX);
126 if(ai<argc)
strlcpy(btacfile, argv[ai++], FILENAME_MAX);
129 else if(!
atofCheck(argv[ai], &Vb) && Vb>=0.0) ai++;
130 else {fprintf(stderr,
"Error: invalid Vb: '%s'.\n", argv[ai]);
return(1);}
132 if(ai<argc)
strlcpy(outfile, argv[ai++], FILENAME_MAX);
134 fprintf(stderr,
"Error: invalid argument '%s'.\n", argv[ai]);
138 if(isnan(Vb) && !parfile[0]) {
139 fprintf(stderr,
"Error: missing command-line argument; use option --help\n");
142 if(!outfile[0]) strcpy(outfile, ttacfile);
143 if(Vb>=1.0) Vb/=100.;
147 printf(
"ttacfile := %s\n", ttacfile);
148 printf(
"btacfile := %s\n", btacfile);
149 printf(
"outfile := %s\n", outfile);
150 if(parfile[0]) printf(
"parfile := %s\n", parfile);
151 if(!isnan(Vb)) printf(
"Vb := %g %%\n", 100.0*Vb);
152 printf(
"petVolume := %d\n", petVolume);
153 printf(
"leaveNegatives := %d\n", leaveNegatives);
154 printf(
"addVb := %d\n", addVb);
155 printf(
"forceMode := %d\n", forceMode);
159 printf(
"\nApplying formula:\n");
161 if(petVolume==0) printf(
"Ct=(Cpet-Vb*Cb)/(1-Vb)\n");
162 else printf(
"Ct=Cpet-Vb*Cb\n");
164 if(petVolume==0) printf(
"Cpet=(1-Vb)*Ct+Vb*Cb\n");
165 else printf(
"Cpet=Ct+Vb*Cb\n");
167 printf(
"\n"); fflush(stdout);
174 if(verbose>1) printf(
"reading %s\n", ttacfile);
182 printf(
"ttac.tacNr := %d\n", ttac.
tacNr);
183 printf(
"ttac.sampleNr := %d\n", ttac.
sampleNr);
192 if(verbose>1) printf(
"reading %s\n", btacfile);
200 printf(
"btac.tacNr := %d\n", btac.
tacNr);
201 printf(
"btac.sampleNr := %d\n", btac.
sampleNr);
207 fprintf(stderr,
"Warning: BTAC file contains %d TACs.\n", btac.
tacNr);
208 fprintf(stdout,
"Note: using the first TAC in BTAC file.\n");
209 fflush(stderr); fflush(stdout);
216 if(verbose>0) fprintf(stdout,
"Note: TAC files have different or unknown time units.\n");
217 if(verbose>2) fprintf(stderr,
"Status: %s\n",
errorMsg(status.
error));
230 if(verbose>0) fprintf(stdout,
"Note: TAC files have different or unknown concentration units.\n");
231 if(verbose>2) fprintf(stderr,
"Status: %s\n",
errorMsg(status.
error));
252 double VbArray[ttac.
tacNr];
254 if(verbose>1) printf(
"reading %s\n", parfile);
256 int ret=
parRead(&par, parfile, &status);
259 ret=
tacRead(&tmp, parfile, &status);
265 fprintf(stderr,
"Error: cannot read Vb values from %s\n", parfile);
270 printf(
"\n Vb file contents:\n");
274 fprintf(stderr,
"Error: different number of TACs in Vb file.\n");
280 fprintf(stderr,
"Error: parameter Vb not identified in %s\n", parfile);
286 for(
int ri=0; ri<par.
tacNr; ri++) {
287 if(strcasecmp(par.
r[ri].
name, ttac.
c[ri].
name)!=0) {
289 printf(
" not matching: '%s' vs '%s'\n", par.
r[ri].
name, ttac.
c[ri].
name);
296 if(forceMode) fprintf(stderr,
"Warning: Vb file does not contain the same TACs.\n");
298 fprintf(stderr,
"Error: Vb file does not contain the same TACs.\n");
304 for(
int ri=0; ri<par.
tacNr; ri++) VbArray[ri]=par.
r[ri].
p[VbIndex];
308 if(verbose>1) {printf(
"Vb range: %g - %g\n", VbMin, VbMax); fflush(stdout);}
309 if(VbMin<0.0 || VbMax>100.0) {
310 fprintf(stderr,
"Error: invalid range of Vb values.\n");
315 for(
int ri=0; ri<ttac.
tacNr; ri++) VbArray[ri]*=0.01;
316 fprintf(stderr,
"Warning: Vb values were converted to fractions.\n"); fflush(stderr);
327 ret=
tacVb(&ttac, -1, &bitac, Vb, addVb, petVolume, &status);
329 for(
int ri=0; ri<ttac.
tacNr; ri++)
330 if((ret=
tacVb(&ttac, ri, &bitac, VbArray[ri], addVb, petVolume, &status)))
break;
337 if(!leaveNegatives) {
338 for(
int ri=0; ri<ttac.
tacNr; ri++)
for(
int fi=0; fi<ttac.
sampleNr; fi++)
339 if(ttac.
c[ri].
y[fi]<0.0) ttac.
c[ri].
y[fi]=0.0;
349 if(verbose>1) printf(
"writing %s\n", outfile);
350 FILE *fp; fp=fopen(outfile,
"w");
352 fprintf(stderr,
"Error: cannot open file for writing (%s)\n", outfile);
363 if(verbose>=0) printf(
"%s saved.\n", outfile);
int atofCheck(const char *s, double *v)
unsigned int doubleRange(double *a, const unsigned int n, double *amin, double *amax)
int fileExist(const char *filename)
int tacVb(TAC *ttac, const int i, TAC *btac, double Vb, const int simVb, const int petVolume, TPCSTATUS *status)
Correct TTACs for vascular blood, or simulate its effect.
int tacInterpolate(TAC *inp, TAC *xinp, TAC *tac, TAC *itac, TAC *iitac, TPCSTATUS *status)
Interpolate and/or integrate TACs from one TAC structure into a new TAC structure,...
int parWrite(PAR *par, FILE *fp, parformat format, int extra, TPCSTATUS *status)
int parRead(PAR *par, const char *fname, TPCSTATUS *status)
int parFindParameter(PAR *d, const char *par_name)
int tacToPAR(TAC *tac, PAR *par, TPCSTATUS *status)
Copy the contents of TAC struct into PAR struct.
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)
char name[MAX_TACNAME_LEN+1]
char name[MAX_TACNAME_LEN+1]
int verbose
Verbose level, used by statusPrint() etc.
tpcerror error
Error code.
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 tacYUnitConvert(TAC *tac, const int u, TPCSTATUS *status)
int tacXUnitConvert(TAC *tac, const int u, TPCSTATUS *status)
Header file for library libtpcextensions.
char * unitName(int unit_code)
Header file for libtpcfileutil.
Header file for library libtpcift.
Header file for libtpcli.
Header file for libtpcpar.
@ PAR_FORMAT_CSV_UK
UK CSV.
Header file for library libtpctac.
@ TAC_FORMAT_UNKNOWN
Unknown format.
Header file for libtpctacmod.