8#include "tpcclibConfig.h"
22static char *info[] = {
23 "Calculate the regional tissue to reference tissue ratio, which is often",
24 "used as a robust and model independent index of receptor availability.",
25 "By default, ratio of AUCs is calculated as",
27 " Regional AUC(t1..t2) ",
28 "Ratio = --------------------- ",
29 " Reference AUC(t1..t2) ",
31 "Data concentration units are cancelled out from the ratio. Therefore",
32 "the result is the same if it is calculated from original radioactivity",
33 "concentrations or SUV TACs (SUV ratio, SUR).",
35 "Usage: @P [options] ttacfile reference t1 t2 resultfile",
37 "Reference can be given either as the name or number of the reference TAC",
38 "inside the TTAC file or the name of file containing the reference TAC.",
39 "Start and end times (t1 and t2) must be given in minutes, if TAC file(s)",
40 "do not contain time units. To use the whole time range of ttacfile, enter",
41 "zeroes as t1 and t2.",
45 " Bound/free-ratio is calculated instead of Total/free;",
46 " reference region TAC is first subtracted from other regional TACs.",
48 " Bound TAC maximum value is searched between start and end times,",
49 " and Bound/free ratio is calculated at this time point; this should",
50 " not be used with noisy data.",
52 " Ratio curve is saved for plotting.",
56 " @P ut1234.tac occip 40 60 ut1234ratio.res",
58 "See also: imgratio, taccalc, dftinteg, interpol, tacunit, dftsuv",
60 "Keywords: TAC, modelling, AUC, ratio",
79int main(
int argc,
char **argv)
81 int ai, help=0, version=0, verbose=1;
83 char tacfile[FILENAME_MAX], resfile[FILENAME_MAX], ratfile[FILENAME_MAX];
84 char refname[FILENAME_MAX], reffile[FILENAME_MAX];
94 if(argc==1) {
tpcPrintUsage(argv[0], info, stderr);
return(1);}
95 tacfile[0]=resfile[0]=ratfile[0]=reffile[0]=refname[0]=(char)0;
98 for(ai=1; ai<argc; ai++)
if(*argv[ai]==
'-') {
100 cptr=argv[ai]+1;
if(*cptr==
'-') cptr++;
if(cptr==NULL)
continue;
101 if(strncasecmp(cptr,
"BOUND", 1)==0) {
103 }
else if(strncasecmp(cptr,
"MAX", 1)==0) {
105 }
else if(strncasecmp(cptr,
"RAT=", 4)==0 && strlen(cptr)>4) {
106 strlcpy(ratfile, cptr+4, FILENAME_MAX);
continue;
108 fprintf(stderr,
"Error: invalid option '%s'\n", argv[ai]);
113 if(help==2) {
tpcHtmlUsage(argv[0], info,
"");
return(0);}
118 if(ai<argc) {
strlcpy(tacfile, argv[ai++], FILENAME_MAX);}
119 if(ai<argc) {
strlcpy(reffile, argv[ai++], FILENAME_MAX);}
122 fprintf(stderr,
"Error: invalid t1 '%s'\n", argv[ai]);
return(1);
128 fprintf(stderr,
"Error: invalid t2 '%s'\n", argv[ai]);
return(1);
132 if(ai<argc) {
strlcpy(resfile, argv[ai++], FILENAME_MAX);}
134 fprintf(stderr,
"Error: extra command-line argument.\n");
138 if(!resfile[0]) {
tpcPrintUsage(argv[0], info, stderr);
return(1);}
140 fprintf(stderr,
"Error: illegal time range %g-%g\n", tstart, tstop);
147 printf(
"tacfile := %s\n", tacfile);
148 printf(
"reference := %s\n", reffile);
149 printf(
"t1 := %g\n", tstart);
150 printf(
"t2 := %g\n", tstop);
151 printf(
"resfile := %s\n", resfile);
152 printf(
"ratmode := %d\n", ratmode);
153 if(ratfile[0]) printf(
"ratfile := %s\n", ratfile);
160 if(verbose>1) printf(
"reading %s\n", tacfile);
163 fprintf(stderr,
"Error in reading '%s': %s\n", tacfile,
dfterrmsg);
168 fprintf(stderr,
"Error: missing values in %s\n", tacfile);
176 tstart*=60.0; tstop*=60.0;
177 if(verbose) printf(
"time range is converted to seconds.\n");
178 }
else if(dft.
timeunit==TUNIT_UNKNOWN) {
179 fprintf(stderr,
"Warning: unknown data time units.\n");
180 fprintf(stderr,
"Assuming that data and time range are in same units.\n");
184 if(tstart==0.0 && tstop==0.0) {
186 else {tstart=dft.
x[0]; tstop=dft.
x[dft.
frameNr-1];}
193 if(dft.
x2[dft.
frameNr-1] < 0.5*(tstart+tstop) || dft.
x1[0]> 0.5*(tstart+tstop) ) {
194 fprintf(stderr,
"Error: data does not contain specified time range.\n");
198 fprintf(stderr,
"Warning: specified time range exceeds the data.\n");
200 for(
int fi=0; fi<dft.
frameNr; fi++)
201 if(dft.
x2[fi]>tstart && dft.
x1[fi]<tstop) n++;
204 if(dft.
x[dft.
frameNr-1] < 0.5*(tstart+tstop) || dft.
x[0]> 0.5*(tstart+tstop) ) {
205 fprintf(stderr,
"Error: data does not contain the specified time range.\n");
209 fprintf(stderr,
"Warning: specified time range exceeds the data.\n");
211 for(
int fi=0; fi<dft.
frameNr; fi++)
if(dft.
x[fi]>=tstart && dft.
x[fi]<=tstop) n++;
214 printf(
"tstart := %g min\n", tstart);
215 printf(
"tstop := %g\n", tstop);
219 fprintf(stderr,
"Error: data does not contain the specified time range.\n");
222 fprintf(stderr,
"Warning: only %d sample(s) in specified time range.\n", n);
230 if(verbose>1) printf(
"reading reference %s\n", reffile);
234 if(
dftReadinput(&rdft, &dft, reffile, &inputtype, &f, &g, 0, tmp, verbose-1)) {
235 fprintf(stderr,
"Error in reading '%s': %s\n", reffile, tmp);
239 if(verbose>2) printf(
"inputtype := %d\n", inputtype);
242 fprintf(stdout,
"selected reference region := %s\n", rdft.
voi[0].
name);
244 fprintf(stderr,
"Warning: %s selected of %d reference regions.\n",
246 strcpy(refname, rdft.
voi[0].
name);
249 if(verbose>2) printf(
"Reference tissue calibration unit := %s\n", rdft.
unit);
251 fprintf(stderr,
"Warning: only the first of reference curves is used.\n");
252 if(f>tstart || g<tstop)
253 fprintf(stderr,
"Warning: time range may not be optimal for reference data.\n");
261 if(verbose>1) printf(
"Subtracting the ref TAC\n");
262 for(
int ri=0; ri<dft.
voiNr; ri++)
263 for(
int fi=0; fi<dft.
frameNr; fi++)
264 dft.
voi[ri].
y[fi]-=rdft.
voi[0].
y[fi];
272 if(verbose>1) printf(
"initializing result data\n");
275 fprintf(stderr,
"Error: cannot setup memory for results.\n");
281 if(refname[0]) snprintf(res.
refroi, 63,
"%s", refname);
282 if(reffile[0]) strcpy(res.
reffile, reffile);
293 pi=0; strcpy(res.
parname[pi],
"B/F"); strcpy(res.
parunit[pi],
"");
294 pi++; strcpy(res.
parname[pi],
"tMax");
299 pi=0; strcpy(res.
parname[pi],
"B/F"); strcpy(res.
parunit[pi],
"");
301 pi=0; strcpy(res.
parname[pi],
"T/F"); strcpy(res.
parunit[pi],
"");
303 pi++; strcpy(res.
parname[pi],
"AUC"); strcpy(res.
parunit[pi],
"");
310 if(verbose>1) printf(
"computing the ratios\n");
322 if(
dftTimeIntegral(&rdft, tstart, tstop, &auc, 0, NULL, verbose-3)!=0) {
323 fprintf(stderr,
"Error in integration of reference region TAC.\n");
326 aucref=auc.
voi[0].
y[0];
328 if(verbose>2) printf(
"%s AUC = %g\n", rdft.
voi[0].
name, aucref);
330 fprintf(stderr,
"Error: invalid reference region AUC; check the data.\n");
337 if(
dftTimeIntegral(&dft, tstart, tstop, &auc, 0, NULL, verbose-3)!=0) {
338 fprintf(stderr,
"Error in integration of regional TACs.\n");
341 for(
int ri=0; ri<dft.
voiNr; ri++) {
342 if(verbose>2) printf(
"%s %s %s AUC = %g\n",
355 double x[2], yi[2], aucref, aucroi;
356 x[0]=tstart; x[1]=tstop;
358 fprintf(stderr,
"Error in integration of reference region TAC.\n");
362 if(verbose>2) printf(
"%s AUC%g - AUC%g = %g\n", rdft.
voi[0].
name, yi[1], yi[0], aucref);
364 fprintf(stderr,
"Error: invalid reference region AUC; check the data.\n");
371 for(
int ri=0; ri<dft.
voiNr; ri++) {
374 fprintf(stderr,
"Error in integration of region %d.\n", ri+1);
378 if(verbose>2) printf(
"%s %s %s AUC%g - AUC%g = %g\n",
389 for(
int ri=0; ri<dft.
voiNr; ri++) {
392 for(
int fi=0; fi<dft.
frameNr; fi++) {
394 if(dft.
x[fi]>=tstart && dft.
x[fi]<=tstop && rdft.
voi[0].
y[fi]>0.0) {
395 if(dft.
voi[ri].
y[fi]>aucroi) {
396 n=fi; aucroi=dft.
voi[ri].
y[fi];
415 if(verbose>0) {
resPrint(&res); fprintf(stdout,
"\n");}
421 if(verbose>1) printf(
"saving results\n");
422 if(
resWrite(&res, resfile, verbose-3)!=0) {
423 fprintf(stderr,
"Error in writing '%s': %s\n", resfile,
reserrmsg);
433 if(verbose>1) printf(
"Calculating ratio curves\n");
434 for(
int ri=0; ri<dft.
voiNr; ri++) {
435 for(
int fi=0; fi<dft.
frameNr; fi++) {
436 if(isnan(rdft.
voi[0].
y[fi]) || isnan(dft.
voi[ri].
y[fi]) ||
437 fabs(rdft.
voi[0].
y[fi])<1.0E-20) {
438 dft.
voi[ri].
y[fi]=0.0;
440 dft.
voi[ri].
y[fi]/=rdft.
voi[0].
y[fi];
445 for(
int ri=0; ri<dft.
voiNr; ri++)
for(
int fi=0; fi<dft.
frameNr; fi++) {
446 if(ratmode>0) {
if(dft.
voi[ri].
y[fi]<-1.0) dft.
voi[ri].
y[fi]=-1.0;}
447 else {
if(dft.
voi[ri].
y[fi]<0.0) dft.
voi[ri].
y[fi]=0.0;}
451 for(
int ri=0; ri<dft.
voiNr; ri++)
for(
int fi=2; fi<dft.
frameNr; fi++) {
452 if(dft.
voi[ri].
y[fi]>f) f=dft.
voi[ri].
y[fi];
453 else if(dft.
voi[ri].
y[fi]<g) g=dft.
voi[ri].
y[fi];
455 for(
int ri=0; ri<dft.
voiNr; ri++)
for(
int fi=0; fi<2 && fi<dft.
frameNr; fi++) {
456 if(dft.
voi[ri].
y[fi]>f) dft.
voi[ri].
y[fi]=f;
457 else if(dft.
voi[ri].
y[fi]<g) dft.
voi[ri].
y[fi]=g;
465 fprintf(stderr,
"Error in writing '%s': %s\n", ratfile,
dfterrmsg);
int atof_with_check(char *double_as_string, double *result_value)
int dftSortByFrame(DFT *dft)
int dft_nr_of_NA(DFT *dft)
int dftTimeIntegral(DFT *dft, double t1, double t2, DFT *idft, int calc_mode, char *status, int verbose)
int dftRead(char *filename, DFT *data)
int dftWrite(DFT *data, char *filename)
int res_allocate_with_dft(RES *res, DFT *dft)
void dftUnitToDFT(DFT *dft, int dunit)
int interpolate(double *x, double *y, int nr, double *newx, double *newy, double *newyi, double *newyii, int newnr)
Linear interpolation and integration.
Header file for libtpccurveio.
int resWrite(RES *res, char *filename, int verbose)
#define DFT_TIME_STARTEND
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)
void tpcProgramName(const char *program, int version, int copyright, char *prname, int n)
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.
Header file for libtpcmodext.
char comments[_DFT_COMMENT_LEN+1]
char unit[MAX_UNITS_LEN+1]
char parname[MAX_RESPARAMS][MAX_RESPARNAME_LEN+1]
char datafile[FILENAME_MAX]
char reffile[FILENAME_MAX]
char parunit[MAX_RESPARAMS][MAX_RESPARNAME_LEN+1]
double parameter[MAX_RESPARAMS]
char voiname[MAX_REGIONSUBNAME_LEN+1]
char name[MAX_REGIONNAME_LEN+1]
char hemisphere[MAX_REGIONSUBNAME_LEN+1]
char place[MAX_REGIONSUBNAME_LEN+1]