11#include "tpcclibConfig.h"
28static char *info[] = {
29 "Linear fitting of sum of three exponentials function",
30 " f(x) = p1*exp(p2*x) + p3*exp(p4*x) + p5*exp(p6*x) + p7*exp(p8*x)",
31 ", where p8=0, to time-activity curves.",
33 "Usage: @P [options] TAC results",
37 " Fitted and measured TACs are plotted in specified SVG file.",
39 " Fitted regional TTACs are written in specified file.",
41 " Parameters of initial linear model are saved in specified file.",
44 "See also: fit_exp, fit_dexp",
46 "Keywords: TAC, modelling, compartmental model, LLSQ",
69int main(
int argc,
char **argv)
71 int ai, help=0, version=0, verbose=1;
72 char tacfile[FILENAME_MAX], resfile[FILENAME_MAX],
73 fitfile[FILENAME_MAX], svgfile[FILENAME_MAX], lpfile[FILENAME_MAX];
80 if(argc==1) {
tpcPrintUsage(argv[0], info, stderr);
return(1);}
81 tacfile[0]=resfile[0]=fitfile[0]=svgfile[0]=lpfile[0]=(char)0;
83 for(ai=1; ai<argc; ai++)
if(*argv[ai]==
'-') {
85 char *cptr=argv[ai]+1;
if(*cptr==
'-') cptr++;
if(!*cptr)
continue;
86 if(strncasecmp(cptr,
"SVG=", 4)==0) {
87 strlcpy(svgfile, cptr+4, FILENAME_MAX);
if(strlen(svgfile)>0)
continue;
88 }
else if(strncasecmp(cptr,
"FIT=", 4)==0) {
89 strlcpy(fitfile, cptr+4, FILENAME_MAX);
if(strlen(fitfile)>0)
continue;
90 }
else if(strncasecmp(cptr,
"LP=", 3)==0) {
91 strlcpy(lpfile, cptr+3, FILENAME_MAX);
if(strlen(lpfile)>0)
continue;
92 }
else if(strcasecmp(cptr,
"W1")==0) {
94 }
else if(strcasecmp(cptr,
"WF")==0) {
97 fprintf(stderr,
"Error: invalid option '%s'.\n", argv[ai]);
106 if(help==2) {
tpcHtmlUsage(argv[0], info,
"");
return(0);}
111 if(ai<argc)
strlcpy(tacfile, argv[ai++], FILENAME_MAX);
112 if(ai<argc)
strlcpy(resfile, argv[ai++], FILENAME_MAX);
114 fprintf(stderr,
"Error: invalid argument '%s'.\n", argv[ai]);
119 fprintf(stderr,
"Error: missing command-line argument; use option --help\n");
126 printf(
"tacfile := %s\n", tacfile);
127 printf(
"resfile := %s\n", resfile);
128 printf(
"fitfile := %s\n", fitfile);
129 printf(
"svgfile := %s\n", svgfile);
130 printf(
"lpfile := %s\n", lpfile);
131 printf(
"weights := %d\n",
weights);
139 if(verbose>1) printf(
"reading TAC data\n");
142 ret=
tacRead(&tac0, tacfile, &status);
149 printf(
"tacNr := %d\n", tac0.
tacNr);
150 printf(
"sampleNr := %d\n", tac0.
sampleNr);
155 fprintf(stderr,
"Error: too few samples for fitting.\n");
163 if(verbose>1) printf(
"integrating TACs\n");
174 for(
int i=0; i<tac2.
tacNr; i++) {
180 fprintf(stderr,
"Error: cannot make 3rd integral of TAC.\n");
189 if(verbose>1) printf(
"initializing LLSQ parameter data\n");
206 iftPut(&lp.
h,
"program", buf, 0, NULL);
208 iftPut(&lp.
h,
"tacfile", tacfile, 0, NULL);
212 for(i=0; i<lp.
tacNr; i++) {
218 for(i=0; i<MAX_LLSQ_N; i++) {
219 sprintf(lp.
n[i].
name,
"P%d", 1+i);
227 if(verbose>1) printf(
"allocating memory for LLSQ\n");
228 int llsq_n=MAX_LLSQ_N;
230 double *llsq_mat=(
double*)malloc((2*llsq_n*llsq_m)*
sizeof(
double));
232 fprintf(stderr,
"Error: cannot allocate memory.\n");
237 double **llsq_a=(
double**)malloc(llsq_m*
sizeof(
double*));
239 fprintf(stderr,
"Error: cannot allocate memory.\n");
244 for(
int mi=0; mi<llsq_m; mi++) llsq_a[mi]=llsq_mat+mi*llsq_n;
245 double r2, llsq_b[llsq_m], llsq_r[llsq_n];
246 double *matbackup=llsq_mat+llsq_n*llsq_m;
252 for(
int ti=0; ti<tac0.
tacNr; ti++) {
254 if(verbose>1 && tac0.
tacNr>1) {
255 printf(
"TAC %d %s\n", 1+ti, tac0.
c[ti].
name); fflush(stdout);}
258 for(
int mi=0; mi<llsq_m; mi++)
259 llsq_b[mi]=tac0.
c[ti].
y[mi];
260 for(
int mi=0; mi<llsq_m; mi++) {
261 llsq_a[mi][0]=tac3.
c[ti].
y[mi];
262 llsq_a[mi][1]=tac2.
c[ti].
y[mi];
263 llsq_a[mi][2]=tac1.
c[ti].
y[mi];
264 llsq_a[mi][3]=tac0.
x[mi]*tac0.
x[mi]*tac0.
x[mi];
265 llsq_a[mi][4]=tac0.
x[mi]*tac0.
x[mi];
266 llsq_a[mi][5]=tac0.
x[mi];
270 printf(
"Matrix A and vector B:\n");
271 for(
int mi=0; mi<llsq_m; mi++) {
272 printf(
"%.2e", llsq_a[0][mi]);
273 for(
int ni=1; ni<llsq_n; ni++) printf(
", %.2e", llsq_a[ni][mi]);
274 printf(
"; %.3e\n", llsq_b[mi]);
278 for(
int i=0; i<llsq_n*llsq_m; i++) matbackup[i]=llsq_mat[i];
284 printf(
"\nA matrix and B vector\n");
285 for(
int mi=0; mi<llsq_m; mi++) {
286 for(
int ni=0; ni<llsq_n; ni++) printf(
"\t%g", llsq_a[mi][ni]);
287 printf(
"\t\t%g\n", llsq_b[mi]);
293 if(verbose>5) printf(
"starting QR...\n");
294 ret=
qrLSQ(llsq_a, llsq_b, llsq_r, llsq_m, llsq_n, &r2);
295 if(verbose>5) printf(
" ... done.\n");
297 for(
int ni=0; ni<llsq_n; ni++) lp.
r[ti].
p[ni]=llsq_r[ni];
301 fprintf(stderr,
"Warning: no solution for TAC %d %s\n", 1+ti, tac0.
c[ti].
name);
302 for(
int ni=0; ni<llsq_n; ni++) lp.
r[ti].
p[ni]=0.0;
309 for(
int mi=0; mi<llsq_m; mi++) {
310 tac1.
c[ti].
y[mi]=0.0;
311 for(
int ni=0; ni<llsq_n; ni++) tac1.
c[ti].
y[mi]+=llsq_r[ni]*llsq_a[mi][ni];
317 free(llsq_a); free(llsq_mat);
320 fprintf(stderr,
"Error: no solution found for any of the TACs.\n");
327 if(verbose>1 && lp.
tacNr<50)
335 if(verbose>1) printf(
"writing %s\n", lpfile);
339 FILE *fp; fp=fopen(lpfile,
"w");
341 fprintf(stderr,
"Error: cannot open file for writing parameter file.\n");
353 if(verbose>0) printf(
"Results saved in %s.\n", lpfile);
360 if(verbose>1) printf(
"initializing exponential parameter data\n");
378 iftPut(&par.
h,
"program", buf, 0, NULL);
380 iftPut(&par.
h,
"tacfile", tacfile, 0, NULL);
384 for(i=0; i<par.
tacNr; i++) {
392 for(i=0; i<par.
parNr; i++) {
393 sprintf(par.
n[i].
name,
"P%d", 1+i);
395 for(
int i=0; i<par.
parNr; i+=2) {
406 for(
int ti=0; ti<tac0.
tacNr; ti++) {
408 if(verbose>1 && tac0.
tacNr>1) {
409 printf(
"TAC %d %s\n", 1+ti, tac0.
c[ti].
name); fflush(stdout);}
411 for(
int i=0; i<par.
parNr; i++) par.
r[ti].
p[i]=0.0;
415 double A=-lp.
r[ti].
p[2];
416 double B=-lp.
r[ti].
p[1];
417 double C=-lp.
r[ti].
p[0];
421 fprintf(stderr,
"Warning: no solution for TAC %d %s\n", 1+ti, tac0.
c[ti].
name);
425 printf(
" %d roots: %g", roots, x1);
426 if(roots>1) printf(
" %g", x2);
427 if(roots>2) printf(
" %g", x3);
432 if(roots>1) par.
r[ti].
p[5]=x2;
433 if(roots>2) par.
r[ti].
p[7]=x3;
438 llsq_mat=(
double*)malloc((llsq_n*llsq_m)*
sizeof(
double));
439 llsq_a=(
double**)malloc(llsq_m*
sizeof(
double*));
440 for(
int mi=0; mi<llsq_m; mi++) llsq_a[mi]=llsq_mat+mi*llsq_n;
444 for(
int mi=0; mi<llsq_m; mi++)
445 llsq_b[mi]=tac0.
c[ti].
y[mi];
446 for(
int mi=0; mi<llsq_m; mi++)
448 for(
int mi=0; mi<llsq_m; mi++)
449 llsq_a[mi][1]=exp(x1*tac0.
x[mi]);
450 if(llsq_n>2)
for(
int mi=0; mi<llsq_m; mi++)
451 llsq_a[mi][2]=exp(x2*tac0.
x[mi]);
452 if(llsq_n>3)
for(
int mi=0; mi<llsq_m; mi++)
453 llsq_a[mi][3]=exp(x3*tac0.
x[mi]);
459 printf(
"\nA matrix and B vector\n");
460 for(
int mi=0; mi<llsq_m; mi++) {
461 for(
int ni=0; ni<llsq_n; ni++) printf(
"\t%g", llsq_a[mi][ni]);
462 printf(
"\t\t%g\n", llsq_b[mi]);
468 if(verbose>5) printf(
"starting QR...\n");
469 ret=
qrLSQ(llsq_a, llsq_b, llsq_r, llsq_m, llsq_n, &r2);
470 if(verbose>5) printf(
" ... done.\n");
472 fprintf(stderr,
"Warning: no solution for TAC %d %s\n", 1+ti, tac0.
c[ti].
name);
476 printf(
" amplitudes: %g %g", llsq_r[0], llsq_r[1]);
477 if(llsq_n>2) printf(
" %g", llsq_r[2]);
478 if(llsq_n>3) printf(
" %g", llsq_r[3]);
482 par.
r[ti].
p[0]=llsq_r[0];
483 par.
r[ti].
p[2]=llsq_r[1];
484 if(llsq_n>2) par.
r[ti].
p[4]=llsq_r[2];
485 if(llsq_n>3) par.
r[ti].
p[6]=llsq_r[3];
489 free(llsq_a); free(llsq_mat);
492 fprintf(stderr,
"Error: no solution found for any of the TACs.\n");
502 if(verbose>0 && par.
tacNr<80)
509 if(verbose>1) printf(
"writing %s\n", resfile);
513 FILE *fp; fp=fopen(resfile,
"w");
515 fprintf(stderr,
"Error: cannot open file for writing parameter file.\n");
527 if(verbose>0) printf(
"Results saved in %s.\n", resfile);
535 if(svgfile[0] || fitfile[0]) {
536 if(verbose>1) printf(
"computing fitted TACs\n");
538 for(
int ti=0; ti<tac0.
tacNr; ti++) {
539 for(
int mi=0; mi<tac0.
sampleNr; mi++)
540 tac2.
c[ti].
y[mi]=par.
r[ti].
p[0] + par.
r[ti].
p[2]*exp(par.
r[ti].
p[3]*tac0.
x[mi]) +
541 par.
r[ti].
p[4]*exp(par.
r[ti].
p[5]*tac0.
x[mi]) +
542 par.
r[ti].
p[6]*exp(par.
r[ti].
p[7]*tac0.
x[mi]);
552 if(verbose>1) printf(
"saving SVG plot\n");
555 sprintf(buf,
"3exp");
558 if(i>=0) {strcat(buf,
": "); strcat(buf, tac0.
h.
item[i].
value);}
559 ret=
tacPlotFitSVG(&tac0, &tac2, buf, 0.0, nan(
""), 0.0, nan(
""), svgfile, &status);
566 if(verbose>0) printf(
"Plots written in %s.\n", svgfile);
574 if(verbose>1) printf(
"writing %s\n", fitfile);
575 FILE *fp; fp=fopen(fitfile,
"w");
577 fprintf(stderr,
"Error: cannot open file for writing fitted TTACs.\n");
589 if(verbose>0) printf(
"fitted TACs saved in %s.\n", fitfile);
char * ctime_r_int(const time_t *t, char *buf)
Convert calendar time t into a null-terminated string of the form YYYY-MM-DD hh:mm:ss,...
int iftPut(IFT *ift, const char *key, const char *value, char comment, TPCSTATUS *status)
int iftFindKey(IFT *ift, const char *key, int start_index)
int liIntegrate(double *x, double *y, const int nr, double *yi, const int se, const int verbose)
Linear integration of TAC with trapezoidal method.
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,...
char * parFormattxt(parformat c)
int parWrite(PAR *par, FILE *fp, parformat format, int extra, TPCSTATUS *status)
int parFormatFromExtension(const char *s)
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)
void tpcProgramName(const char *program, int version, int copyright, char *prname, int n)
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)
int qrLSQ(double **mat, double *rhs, double *sol, const unsigned int rows, const unsigned int cols, double *r2)
QR least-squares solving routine.
int qrWeight(int N, int M, double **A, double *b, double *weight, double *ws)
int rootsCubic(const double a, const double b, const double c, double *x1, double *x2, double *x3)
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)
IFT h
Optional (but often useful) header information.
char name[MAX_PARNAME_LEN+1]
char name[MAX_TACNAME_LEN+1]
IFT h
Optional (but often useful) header information.
int verbose
Verbose level, used by statusPrint() etc.
tpcerror error
Error code.
int tacDuplicate(TAC *tac1, TAC *tac2)
Make a duplicate of TAC structure.
int tacPlotFitSVG(TAC *tac1, TAC *tac2, const char *main_title, const double x1, const double x2, const double y1, const double y2, const char *fname, TPCSTATUS *status)
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 tacSetWeights(TAC *tac, weights weightMethod, int weightNr, TPCSTATUS *status)
int tacIsWeighted(TAC *tac)
unsigned int tacWSampleNr(TAC *tac)
Header file for library libtpcextensions.
weights
Is data weighted, or are weight factors available with data?
@ WEIGHTING_OFF
Not weighted or weights not available (weights for all included samples are 1.0).
@ WEIGHTING_ON_FD
Weights based on decay and sample frequency or frame length (Thiele et al, 2008).
@ WEIGHTING_UNKNOWN
Not known; usually assumed that not weighted.
@ TPCERROR_FAIL
General error.
char * unitName(int unit_code)
Header file for library libtpcift.
Header file for libtpcli.
Header file for libtpclinopt.
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_UNKNOWN
Unknown format.
Header file for libtpctacmod.