9#include "tpcclibConfig.h"
26static char *info[] = {
27 "Estimate Vb and Ct based on blood curve (BTAC), assuming that at BTAC peak",
28 "tissue concentration is zero, thus Vb=Ct/Cb.",
29 "Vb is then reduced to assure that other TACs remain non-negative.",
30 "The name or number of BTAC inside TAC file must be given.",
32 "Do not use this oversimplified method for quantitative analyses!",
34 "Usage: @P [options] tacfile BTAC [outputfile]",
38 " Estimated Vb is written in file.",
41 "See also: imgcbvp, taccbv, tacpeak, taccalc",
43 "Keywords: TAC, peak, vascular fraction",
62int main(
int argc,
char **argv)
64 int ai, help=0, version=0, verbose=1;
65 char tacfile[FILENAME_MAX], parfile[FILENAME_MAX], corfile[FILENAME_MAX];
72 if(argc==1) {
tpcPrintUsage(argv[0], info, stderr);
return(1);}
73 tacfile[0]=parfile[0]=corfile[0]=(char)0;
76 for(ai=1; ai<argc; ai++)
if(*argv[ai]==
'-') {
78 char *cptr=argv[ai]+1;
if(*cptr==
'-') cptr++;
if(!*cptr)
continue;
79 if(strncasecmp(cptr,
"PAR=", 4)==0) {
80 strlcpy(parfile, cptr+4, FILENAME_MAX);
if(strlen(parfile)>0)
continue;
82 fprintf(stderr,
"Error: invalid option '%s'\n", argv[ai]);
91 if(help==2) {
tpcHtmlUsage(argv[0], info,
"");
return(0);}
97 if(ai<argc)
strlcpy(tacfile, argv[ai++], FILENAME_MAX);
99 if(ai<argc)
strlcpy(corfile, argv[ai++], FILENAME_MAX);
100 if(ai<argc) {fprintf(stderr,
"Error: too many arguments.\n");
return(1);}
103 if(!bname[0]) {
tpcPrintUsage(argv[0], info, stdout);
return(1);}
107 for(ai=0; ai<argc; ai++) printf(
"%s ", argv[ai]);
109 printf(
"tacfile := %s\n", tacfile);
110 printf(
"bname := %s\n", bname);
111 if(parfile[0]) printf(
"parfile := %s\n", parfile);
112 if(corfile[0]) printf(
"corfile := %s\n", corfile);
119 if(verbose>1) printf(
"reading %s\n", tacfile);
127 printf(
"tacNr := %d\n", tac.
tacNr);
128 printf(
"sampleNr := %d\n", tac.
sampleNr);
133 fprintf(stderr,
"Error: invalid file.\n");
135 }
else if(tac.
tacNr<2) {
136 if(verbose>0) fprintf(stderr,
"Error: file contains just one TAC.\n");
141 fprintf(stderr,
"Error: data contains missing values.\n");
152 fprintf(stderr,
"Error: invalid data sample times.\n");
156 printf(
"xmin := %g\n", xmin);
157 printf(
"xmax := %g\n", xmax);
161 fprintf(stderr,
"Error: cannot process duplicate samples.\n");
165 fprintf(stderr,
"Error: too few samples.\n");
174 fprintf(stderr,
"Error: specified BTAC not found in %s.\n", tacfile);
177 fprintf(stderr,
"Error: %d TACs match '%s' in %s.\n", n, bname, tacfile);
182 printf(
"BTAC name := %s\n", tac.
c[ib].
name);
183 printf(
"BTAC index := %d\n", ib);
191 if(verbose>1) printf(
"preparing space for parameters\n");
200 for(
int i=0; i<tac.
tacNr; i++) {
207 strcpy(par.
n[0].
name,
"Vb");
214 if(verbose>1) printf(
"searching peak\n");
215 double bpeak=tac.
c[ib].
y[0];
218 if(tac.
c[ib].
y[i]>bpeak) {bpeak=tac.
c[ib].
y[i]; ipeak=i;}
220 printf(
" maxv := %g\n", bpeak);
221 printf(
" maxx := %g\n", tac.
x[ipeak]);
224 if(ipeak>0) bpeak+=tac.
c[ib].
y[ipeak-1];
226 printf(
" bpeak := %g\n", bpeak);
232 for(
int ci=0; ci<tac.
tacNr; ci++)
if(ci!=ib) {
235 for(
int i=0; i<tac.
sampleNr; i++)
if(tac.
c[ci].
y[i]<0.0) tac.
c[ci].
y[i]=0.0;
238 double tpeak=tac.
c[ci].
y[ipeak];
239 if(ipeak>0) tpeak+=tac.
c[ci].
y[ipeak-1];
240 double vb=tpeak/bpeak;
241 if(verbose>2) printf(
" tpeak[%d] := %g\n", ci, tpeak);
244 for(
int i=0; i<tac.
sampleNr; i++) tac.
c[ci].
y[i]=0.0;
253 ct[i]=tac.
c[ci].
y[i]-vb*tac.
c[ib].
y[i];
254 if(ct[i]<ctmin) {ctmin=ct[i]; ictmin=i;}
258 vb+=ctmin/tac.
c[ib].
y[ictmin];
260 ct[i]=tac.
c[ci].
y[i]-vb*tac.
c[ib].
y[i];
261 if(ct[i]<0.0) ct[i]=0.0;
265 for(
int i=0; i<tac.
sampleNr; i++) tac.
c[ci].
y[i]=ct[i];
280 if(verbose>1) printf(
" saving %s\n", parfile);
281 FILE *fp=fopen(parfile,
"w");
283 fprintf(stderr,
"Error: cannot open file for writing.\n");
292 if(verbose>0) printf(
"parameters saved in %s\n", parfile);
300 FILE *fp; fp=fopen(corfile,
"w");
302 fprintf(stderr,
"Error: cannot open file for writing '%s'.\n", corfile);
313 if(verbose>0) printf(
"Corrected TACs saved in %s.\n", corfile);
int parWrite(PAR *par, FILE *fp, parformat format, int extra, TPCSTATUS *status)
int parAllocateWithTAC(PAR *par, TAC *tac, int parNr, TPCSTATUS *status)
Allocate PAR based on data in TAC.
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_PARNAME_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 tacMultipleSamples(TAC *d1, const int fixMode, TAC *d2, const int verbose)
Check TAC data for multiple samples with the same sample time. Optionally replace the multiple sample...
int tacSelectTACs(TAC *d, const char *region_name, int reset, TPCSTATUS *status)
int tacFirstSelected(TAC *d)
unsigned int tacWSampleNr(TAC *tac)
int tacXRange(TAC *d, double *xmin, double *xmax)
Get the range of x values (times) in TAC structure.
Header file for library libtpcextensions.
#define MAX_TACNAME_LEN
Max length of TAC ID name (not including trailing zero).
@ TPCERROR_FAIL
General error.
char * unitName(int unit_code)
Header file for libtpcfunc.
Header file for library libtpcift.
Header file for libtpcmodels.
Header file for libtpcpar.
@ PAR_FORMAT_UNKNOWN
Unknown format.
@ PAR_FORMAT_TSV_UK
UK TSV (point as decimal separator).
Header file for library libtpctac.
@ TAC_FORMAT_PMOD
PMOD TAC format.
Header file for libtpctacmod.