9#include "tpcclibConfig.h"
22static char *info[] = {
23 "Add dispersion effect to ideal TAC data (ON), or correct a measured data set",
24 "for dispersion (OFF) (1, 2).",
25 "The time constant of the dispersion must be given in the same time units as",
26 "those that are used in the data file.",
27 "Program output is written in file in the same format as the input datafile.",
29 "Usage: @P [Options] ON|OFF tacfile dispersion outputfile",
33 " Dispersion time and other log information is written as comments in",
34 " the corrected TAC file.",
37 "Example 1: check that specified data files are suitable as input TACs",
38 " @P off us488.bld 2.5 us488blood_disp.bld",
41 " 1. Iida H, Kanno I, Miura S, Murakami M, Takahashi K, Uemura K. Error",
42 " analysis of a quantitative cerebral blood flow measurement using H215O",
43 " autoradiography and positron emission tomography, with respect to the",
44 " dispersion of the input function.",
45 " J Cereb Blood Flow Metab. 1986;6:536-545.",
46 " 2. Oikonen V. Model equations for the dispersion of the input function in",
47 " bolus infusion PET studies. TPCMOD0003 2002-09-03;",
48 " https://www.turkupetcentre.net/reports/tpcmod0003.pdf",
50 "See also: tacunit, fit_sinf, fitdelay, tactime, convexpf, simdisp",
52 "Keywords: TAC, dispersion, input, blood, simulation",
71int main(
int argc,
char **argv)
73 int ai, help=0, version=0, verbose=1;
76 char *cptr, tmp[FILENAME_MAX];
77 char ifile[FILENAME_MAX], ofile[FILENAME_MAX];
85 if(argc==1) {
tpcPrintUsage(argv[0], info, stderr);
return(1);}
86 ifile[0]=ofile[0]=(char)0;
89 for(ai=1; ai<argc; ai++)
if(*argv[ai]==
'-') {
91 cptr=argv[ai]+1;
if(*cptr==
'-') cptr++;
if(cptr==NULL)
continue;
92 if(strncasecmp(cptr,
"LOG", 1)==0) {
95 fprintf(stderr,
"Error: invalid option '%s'.\n", argv[ai]);
100 if(help==2) {
tpcHtmlUsage(argv[0], info,
"");
return(0);}
106 if(strcasecmp(argv[ai],
"OFF")==0) dispersion=0;
107 else if(strcasecmp(argv[ai],
"ON")==0) dispersion=1;
108 else if(strcasecmp(argv[ai],
"NO")==0) dispersion=0;
109 else if(strcasecmp(argv[ai],
"YES")==0) dispersion=1;
111 fprintf(stderr,
"Error: dispersion must be set ON or OFF.\n");
118 if(ai<argc) {strcpy(ifile, argv[ai]); ai++;}
124 fprintf(stderr,
"Error: invalid dispersion time constant.\n");
131 if(ai<argc) {strcpy(ofile, argv[ai]); ai++;}
135 fprintf(stderr,
"Error: invalid argument '%s'.\n", argv[ai]);
141 fprintf(stderr,
"Error: missing command-line argument; try %s --help\n",
145 if(tau>1.0E-08) k=1.0/tau;
else k=1.0E+08;
149 printf(
"ifile := %s\n", ifile);
150 printf(
"ofile := %s\n", ofile);
151 printf(
"dispersion := %i\n", dispersion);
152 printf(
"tau := %f\n", tau);
153 printf(
"1/tau := %g\n", k);
154 printf(
"makeLog := %d\n", makeLog);
161 if(verbose>1) printf(
"reading %s\n", ifile);
163 fprintf(stderr,
"Error in reading '%s': %s\n", ifile,
dfterrmsg);
167 fprintf(stderr,
"Warning: %s contains %d TACs.\n", ifile, tac.
voiNr);
171 fprintf(stderr,
"Error: data is not suitable for processing dispersion.\n");
181 double *meas, *ideal, *measi, *ideali, *tempData, *t, dt2;
184 tempData=(
double*)malloc(tac.
frameNr*
sizeof(
double));
186 fprintf(stderr,
"Error in allocating memory.\n");
189 if(dispersion==0 && (fabs(tau)>1.0E-08)) {
194 if(verbose>1) printf(
"correcting for dispersion\n");
196 for(j=1; j<tac.
frameNr; j++)
if(tac.
x[j]<=tac.
x[j-1]) {
197 fprintf(stderr,
"Error: invalid sample timing in datafile.\n");
198 dftEmpty(&tac); free((
char*)tempData);
return(5);
201 for(i=0; i<tac.
voiNr; i++) {
204 ideali=tempData; t=tac.
x; n=tac.
frameNr;
206 measi[0]=0.5*meas[0]*t[0];
208 measi[j]=measi[j-1]+0.5*(meas[j]+meas[j-1])*(t[j]-t[j-1]);
210 for(j=0; j<n; j++) ideali[j]=measi[j]+tau*meas[j];
213 if(dt2>0.0) ideal[j]=ideali[j]/dt2;
else ideal[j]=0.0;
214 for(j=1; j<n-1; j++) {
215 ideal[j]=(ideali[j+1]-ideali[j-1])/(t[j+1]-t[j-1]);
217 ideal[j]=(ideali[j]-ideali[j-1])/(t[j]-t[j-1]);
219 for(j=0; j<n; j++) printf(
"%9.3f %12.3e %16.7e %12.3e %12.3e\n",
220 t[j], ideal[j], ideali[j], meas[j], measi[j]);
224 }
else if(dispersion!=0 && (fabs(tau)>1.0E-08)) {
229 if(verbose>1) printf(
"adding dispersion\n");
231 for(i=0; i<tac.
voiNr; i++) {
234 measi=tempData; t=tac.
x; n=tac.
frameNr;
236 ideali[0]=0.5*ideal[0]*t[0];
238 ideali[j]=ideali[j-1]+0.5*(ideal[j]+ideal[j-1])*(t[j]-t[j-1]);
241 meas[j]=k*ideali[j]/(1.0+k*dt2);
242 measi[j]=meas[j]*dt2;
244 dt2=0.5*(t[j]-t[j-1]);
245 meas[j]=(k*ideali[j] - k*(measi[j-1] + dt2*meas[j-1])) / (1.0+k*dt2);
246 measi[j]=measi[j-1]+dt2*(meas[j]+meas[j-1]);
249 for(j=0; j<n; j++) printf(
"%9.3f %12.3e %12.3e %12.3e %12.3e\n",
250 t[j], ideal[j], ideali[j], meas[j], measi[j]);
255 if(tac.
x[n]>tac.
x[n-1]) {n++;
continue;}
257 tac.
x[j-1]=tac.
x[j]; tac.
x1[j-1]=tac.
x1[j]; tac.
x2[j-1]=tac.
x2[j];
258 for(i=0; i<tac.
voiNr; i++) {
268 fprintf(stderr,
"Warning: dispersion time constant is set to 0.\n");
274 for(i=0; i<tac.
voiNr; i++){
279 free((
char*)tempData);
286 if(verbose>3) printf(
"saving data\n");
291 if(verbose>2) printf(
"saving log information\n");
293 sprintf(tmp,
"# dispersion_time := %g\n", tau);
295 if(dispersion==0) strcat(tac.
comments,
"# dispersion := off\n");
296 else if(dispersion==1) strcat(tac.
comments,
"# dispersion := on\n");
299 if(verbose>1) printf(
"writing %s\n", ofile);
301 fprintf(stderr,
"Error in writing '%s': %s\n", ofile,
dfterrmsg);
304 if(verbose>0) printf(
"TAC written in %s\n", ofile);
double atof_dpi(char *str)
int dftSortByFrame(DFT *dft)
int dftRead(char *filename, DFT *data)
int dftWrite(DFT *data, char *filename)
Header file for libtpccurveio.
Header file for libtpcmisc.
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)
char comments[_DFT_COMMENT_LEN+1]