9#include "tpcclibConfig.h"
30double func_xexp(
int parNr,
double *p,
void*);
32typedef struct FITDATA {
60static char *info[] = {
61 "Non-linear fitting of the parameters of response function, convolved with",
62 "input TAC, to reproduce given output TAC:",
63 " output(t) = input(t) (x) h(t)",
64 "Response function is:",
65 " h(t) = a1*exp(-b1*t) + a2*exp(-b2*t)",
67 "Usage: @P [Options] inputfile outputfile [parfile]",
71 " Constrain h(t) integral (AUC) from zero to infinity (a1/b1 + a2/b2)",
72 " to specified value; fitted by default.",
74 " Minimum value for AUC; by default 0.1.",
76 " Maximum value for AUC; by default 1.0.",
78 " All weights are set to 1.0 (no weighting); by default, weights in",
79 " output data file are used, if available.",
81 " Weight by output TAC sampling interval.",
83 " Fitted and measured TACs are plotted in specified SVG file.",
85 " Sample time interval (sec) in convolution; by default the shortest",
86 " interval in the input data; too long interval as compared to b leads",
90 "If TAC files contain more than one TAC, only the first is used.",
92 "See also: convexpf, sim_av",
94 "Keywords: TAC, curve fitting, convolution",
113int main(
int argc,
char **argv)
115 int ai, help=0, version=0, verbose=1;
116 char inpfile[FILENAME_MAX], outfile[FILENAME_MAX], parfile[FILENAME_MAX], svgfile[FILENAME_MAX];
118 double amin=0.1, amax=1.0;
119 double interval=nan(
"");
126 if(argc==1) {
tpcPrintUsage(argv[0], info, stderr);
return(1);}
127 inpfile[0]=outfile[0]=parfile[0]=svgfile[0]=(char)0;
129 for(ai=1; ai<argc; ai++)
if(*argv[ai]==
'-') {
131 char *cptr=argv[ai]+1;
if(*cptr==
'-') cptr++;
if(!*cptr)
continue;
132 if(strcasecmp(cptr,
"W1")==0) {
134 }
else if(strcasecmp(cptr,
"WF")==0) {
136 }
else if(strncasecmp(cptr,
"SVG=", 4)==0 && strlen(cptr)>4) {
137 strlcpy(svgfile, cptr+4, FILENAME_MAX);
continue;
138 }
else if(strncasecmp(cptr,
"AMIN=", 5)==0) {
140 }
else if(strncasecmp(cptr,
"AMAX=", 5)==0) {
142 }
else if(strncasecmp(cptr,
"A=", 2)==0) {
144 }
else if(strncasecmp(cptr,
"I=", 2)==0) {
145 interval=
atofVerified(cptr+2);
if(interval>0.0)
continue;
147 fprintf(stderr,
"Error: invalid option '%s'.\n", argv[ai]);
156 if(help==2) {
tpcHtmlUsage(argv[0], info,
"");
return(0);}
161 if(ai<argc)
strlcpy(inpfile, argv[ai++], FILENAME_MAX);
162 if(ai<argc)
strlcpy(outfile, argv[ai++], FILENAME_MAX);
163 if(ai<argc)
strlcpy(parfile, argv[ai++], FILENAME_MAX);
165 fprintf(stderr,
"Error: invalid argument '%s'.\n", argv[ai]);
170 fprintf(stderr,
"Error: missing command-line argument; use option --help\n");
175 fprintf(stderr,
"Error: invalid limits for a.\n");
181 printf(
"inpfile := %s\n", inpfile);
182 printf(
"outfile := %s\n", outfile);
183 if(parfile[0]) printf(
"parfile := %s\n", parfile);
184 if(svgfile[0]) printf(
"svgfile := %s\n", svgfile);
185 printf(
"amin := %g\n", amin);
186 printf(
"amax := %g\n", amax);
187 printf(
"weights := %d\n",
weights);
188 if(!isnan(interval)) printf(
"interval := %g\n", interval);
196 if(verbose>1) printf(
"reading TAC data\n");
200 double fitdur=1.0E+12;
202 &fitSampleNr, &otac, &itac, &status);
209 printf(
"inp.sampleNr := %d\n", itac.
sampleNr);
210 printf(
"out.sampleNr := %d\n", otac.
sampleNr);
211 printf(
"fitSampleNr := %d\n", fitSampleNr);
214 printf(
"fitdur := %g s\n", fitdur);
216 if(fitSampleNr<4 || itac.
sampleNr<4) {
217 fprintf(stderr,
"Error: too few samples.\n");
231 for(
int i=0; i<otac.
sampleNr; i++) otac.
w[i]=1.0;
235 for(
int i=0; i<otac.
sampleNr; i++) otac.
w[i]=1.0;
248 if(interval>0.1*itac.
x[itac.
sampleNr-1]) {
249 fprintf(stderr,
"Error: too long interval time.\n");
252 if(interval>0.01*itac.
x[itac.
sampleNr-1]) {
253 if(verbose>0) fprintf(stderr,
"Warning: interval time may be too long.\n");
262 fprintf(stderr,
"Error: cannot interpolate data to even sample times.\n");
266 double freq=iitac.
x2[0]-iitac.
x1[0];
268 printf(
"sample_intervals_in_convolution := %g\n", freq);
269 printf(
"interpolated data range: %g - %g\n", iitac.
x1[0], iitac.
x2[itac.
sampleNr-1]);
273 if(verbose>1) fprintf(stdout,
"allocate memory for kernel...\n");
274 double *kernel=(
double*)malloc(2*iitac.
sampleNr*
sizeof(
double));
276 fprintf(stderr,
"Error: out of memory.\n");
288 if(verbose>1) printf(
"preparing for fitting\n");
293 fitdata.kernel=kernel;
296 fitdata.iy=iitac.
c[0].
y;
301 fitdata.y=otac.
c[0].
y;
302 fitdata.ysim=otac.
c[1].
y;
310 if(verbose>2) printf(
"process initial parameter values\n");
331 for(
unsigned int i=0; i<nlo.
totalNr; i++) {
340 if(verbose>2) printf(
"fixedNr := %d\n", fixedNr);
351 if(verbose>0) printf(
"fitting\n");
360 printf(
"measured and fitted TAC:\n");
362 printf(
"\t%g\t%g\t%g\n", otac.
x[i], otac.
c[0].
y[i], otac.
c[1].
y[i]);
364 if(verbose>2) printf(
" wss := %g\n", nlo.
funval);
382 iftPut(&par.
h,
"program", buf, 0, NULL);
393 for(
int i=0; i<par.
parNr; i+=2) {
394 sprintf(par.
n[i].
name,
"a%d", 1+i/2);
395 sprintf(par.
n[i+1].
name,
"b%d", 1+i/2);
405 if(par.
r[0].
p[3]>par.
r[0].
p[1]) {
407 v=par.
r[0].
p[0]; par.
r[0].
p[0]=par.
r[0].
p[2]; par.
r[0].
p[2]=v;
408 v=par.
r[0].
p[1]; par.
r[0].
p[1]=par.
r[0].
p[3]; par.
r[0].
p[3]=v;
411 if(strlen(par.
r[0].
name)<1) strcpy(par.
r[0].
name,
"1");
413 iftPut(&par.
h,
"inputfile", inpfile, 0, NULL);
414 iftPut(&par.
h,
"datafile", outfile, 0, NULL);
420 if(verbose>1) printf(
" saving %s\n", parfile);
422 fp=fopen(parfile,
"w");
424 fprintf(stderr,
"Error: cannot open file for writing.\n");
433 if(verbose>0) printf(
"parameters saved in %s\n", parfile);
442 if(verbose>1) printf(
"plotting measured and fitted data\n");
443 for(
unsigned int i=0; i<fitdata.in; i++) iitac.
c[0].
y[i]=fitdata.cy[i];
445 ret=
tacPlotFitSVG(&otac, &iitac,
"", nan(
""), nan(
""), nan(
""), nan(
""), svgfile, &status);
452 if(verbose>0) printf(
"Measured and fitted data plotted in %s\n", svgfile);
469double func_xexp(
int parNr,
double *p,
void *fdata)
471 FITDATA *d=(FITDATA*)fdata;
473 if(d->verbose>0) {printf(
"%s()\n", __func__); fflush(stdout);}
474 if(d->verbose>2) printf(
"p[]: %g %g %g %g\n", p[0], p[1], p[2], p[3]);
479 if(d->verbose>1) {fprintf(stdout,
"computing the kernel...\n"); fflush(stdout);}
480 double a1, b1, a2, b2;
482 b1=a1/(p[1]*p[3]); b2=a2/((1.0-p[1])*p[3]);
483 if(d->verbose>2) printf(
"a1=%g b1=%g a2=%g b2=%g\n", a1, b1, a2, b2);
485 double freq=d->ix[1]-d->ix[0];
486 if(d->verbose>6) printf(
"\nData\tKernel:\n");
487 for(
unsigned int i=0; i<d->in; i++) {
488 d->kernel[i] = (a1/b1) * (exp(b1*freq) - 1.0) * exp(-b1*(d->ix[i]+0.5*freq)) +
489 (a2/b2) * (exp(b2*freq) - 1.0) * exp(-b2*(d->ix[i]+0.5*freq));
491 if(d->verbose>6) printf(
"%g\t%g\n", d->ix[i], d->kernel[i]);
493 if(d->verbose>2) printf(
"Sum of response function := %g\n", ksum);
494 if(!isnormal(ksum)) {
495 if(d->verbose>0) fprintf(stderr,
"Error: invalid kernel contents.\n");
502 if(d->verbose>1) {fprintf(stdout,
"convolution...\n"); fflush(stdout);}
503 if(
convolve1D(d->iy, d->in, d->kernel, d->in, d->cy)!=0) {
504 fprintf(stderr,
"Error: cannot convolve the data.\n");
508 printf(
"\nData x\ty\tKernel\tConvolved\n");
509 for(
unsigned int i=0; i<d->in; i++)
510 printf(
"%g\t%g\t%g\t%g\n", d->ix[i], d->iy[i], d->kernel[i], d->cy[i]);
514 if(d->verbose>2) {fprintf(stdout,
"interpolation...\n"); fflush(stdout);}
515 if(
liInterpolate(d->ix, d->cy, d->in, d->x, d->ysim, NULL, NULL, d->n, 0, 0, 0)!=0) {
516 fprintf(stderr,
"Error: cannot interpolate.\n");
520 printf(
"\nData x\ty\tSimulated\n");
521 for(
unsigned int i=0; i<d->n; i++)
522 printf(
"%g\t%g\t%g\n", d->x[i], d->y[i], d->ysim[i]);
526 if(d->verbose>2) {fprintf(stdout,
"computing WSS...\n"); fflush(stdout);}
528 for(
unsigned i=0; i<d->n; i++) {
529 double v=d->ysim[i] - d->y[i];
533 for(
int i=0; i<parNr; i++) printf(
" %g", p[i]);
534 printf(
" -> %g\n", wss);
int convolve1D(double *data, const int n, double *kernel, const int m, double *out)
Calculates the convolution sum of a discrete real data set data[0..n-1] and a discretized response fu...
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,...
double atofVerified(const char *s)
unsigned int drandSeed(short int seed)
Make and optionally set the seed for rand(), drand, drandRange, and drandGaussian().
int iftPut(IFT *ift, const char *key, const char *value, char comment, TPCSTATUS *status)
int liInterpolate(double *x, double *y, const int nr, double *newx, double *newy, double *newyi, double *newyii, const int newnr, const int se, const int ee, const int verbose)
Linear interpolation and/or integration with trapezoidal method.
int tacInterpolateToEqualLengthFrames(TAC *inp, double minfdur, double maxfdur, TAC *tac, TPCSTATUS *status)
unsigned int modelCodeIndex(const char *s)
void nloptInit(NLOPT *nlo)
int nloptAllocate(NLOPT *nlo, unsigned int parNr)
unsigned int nloptFixedNr(NLOPT *d)
void nloptFree(NLOPT *nlo)
void nloptWrite(NLOPT *d, FILE *fp)
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)
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 nloptSimplexARRS(NLOPT *nlo, unsigned int maxIter, TPCSTATUS *status)
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)
double(* _fun)(int, double *, void *)
IFT h
Optional (but often useful) header information.
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 tacAllocateMore(TAC *tac, int tacNr)
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)
char * tacFormattxt(tacformat c)
int tacIsWeighted(TAC *tac)
unsigned int tacWSampleNr(TAC *tac)
int tacWByFreq(TAC *tac, isotope isot, TPCSTATUS *status)
Header file for libtpccm.
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).
char * unitName(int unit_code)
Header file for library libtpcift.
@ ISOTOPE_UNKNOWN
Unknown.
Header file for libtpcli.
Header file for libtpclinopt.
Header file for library libtpcnlopt.
Header file for libtpcpar.
@ PAR_FORMAT_TSV_UK
UK TSV (point as decimal separator).
Header file for libtpcrand.
Header file for library libtpctac.
Header file for libtpctacmod.