8#include "tpcclibConfig.h"
32double func_disp(
int parNr,
double *p,
void*);
34typedef struct FITDATA {
61static char *info[] = {
62 "Non-linear fitting of dispersion and delay from system input and output",
65 "Usage: @P [Options] inputfile outputfile [parfile]",
69 " Sum-of-squares (OLS) is minimized by default, but optionally",
70 " sum of absolute deviations (LAD) can be selected.",
72 " All weights are set to 1.0 (no weighting); by default, weights in",
73 " data file are used, if available.",
75 " Weight by sampling interval.",
77 " Fitted and measured TACs are plotted in specified SVG file.",
80 "Data files must contain 2 columns, sample times and concentrations,",
81 "possibly also weights as last column.",
84 " @P -svg=delayfit.svg input.tac output.tac delayfit.par",
86 "See also: disp4dft, fit_sinf, fit_xexp, convexpf, fit_wrlv",
88 "Keywords: dispersion, curve fitting, input, blood",
112int main(
int argc,
char **argv)
114 int ai, help=0, version=0, verbose=1;
115 char tacfile1[FILENAME_MAX], tacfile2[FILENAME_MAX],
116 parfile[FILENAME_MAX], svgfile[FILENAME_MAX];
125 if(argc==1) {
tpcPrintUsage(argv[0], info, stderr);
return(1);}
126 tacfile1[0]=tacfile2[0]=parfile[0]=svgfile[0]=(char)0;
128 for(ai=1; ai<argc; ai++)
if(*argv[ai]==
'-') {
130 char *cptr=argv[ai]+1;
if(*cptr==
'-') cptr++;
if(!*cptr)
continue;
131 if(strcasecmp(cptr,
"W1")==0) {
133 }
else if(strcasecmp(cptr,
"WF")==0) {
135 }
else if(strncasecmp(cptr,
"MIN=", 4)==0 && strlen(cptr)>4) {
137 }
else if(strncasecmp(cptr,
"SVG=", 4)==0 && strlen(cptr)>4) {
138 strlcpy(svgfile, cptr+4, FILENAME_MAX);
continue;
140 fprintf(stderr,
"Error: invalid option '%s'.\n", argv[ai]);
149 if(help==2) {
tpcHtmlUsage(argv[0], info,
"");
return(0);}
154 if(ai<argc)
strlcpy(tacfile1, argv[ai++], FILENAME_MAX);
155 if(ai<argc)
strlcpy(tacfile2, argv[ai++], FILENAME_MAX);
156 if(ai<argc)
strlcpy(parfile, argv[ai++], FILENAME_MAX);
158 fprintf(stderr,
"Error: invalid argument '%s'.\n", argv[ai]);
163 fprintf(stderr,
"Error: missing file name.\n");
169 printf(
"tacfile1 := %s\n", tacfile1);
170 printf(
"tacfile2 := %s\n", tacfile2);
171 if(parfile[0]) printf(
"parfile := %s\n", parfile);
172 if(svgfile[0]) printf(
"svgfile := %s\n", svgfile);
173 printf(
"weights := %d\n",
weights);
182 if(verbose>1) printf(
"reading TAC data\n");
186 double fitdur=1.0E+12;
188 &fitSampleNr, &tac2, &tac1, &status) !=
TPCERROR_OK)
202 printf(
"tac1.sampleNr := %d\n", tac1.
sampleNr);
203 printf(
"tac2.sampleNr := %d\n", tac2.
sampleNr);
204 printf(
"fitSampleNr := %d\n", fitSampleNr);
207 printf(
"fitdur := %g s\n", fitdur);
210 fprintf(stderr,
"Error: too few samples.\n");
219 for(
int i=0; i<tac2.
sampleNr; i++) tac2.
w[i]=1.0;
223 for(
int i=0; i<tac2.
sampleNr; i++) tac2.
w[i]=1.0;
235 if(verbose>1) printf(
"preparing space for parameters\n");
248 iftPut(&par.
h,
"program", buf, 0, NULL);
252 for(
int i=0; i<par.
tacNr; i++) {
262 iftPut(&par.
h,
"inputfile", tacfile1, 0, NULL);
263 iftPut(&par.
h,
"datafile", tacfile2, 0, NULL);
271 if(verbose>1) printf(
"preparing for fitting\n");
281 fitdata.yi=tac1.
c[0].
y;
284 fitdata.yo=tac2.
c[0].
y;
287 fitdata.optcrit=optcrit;
288 if(verbose>10) fitdata.verbose=verbose-10;
else fitdata.verbose=0;
292 fprintf(stderr,
"Error: cannot initiate NLLS.\n");
302 if(verbose>2) printf(
"non-linear optimization\n");
311 printf(
"measured and fitted TAC:\n");
312 for(
unsigned int i=0; i<fitdata.no; i++)
313 printf(
"\t%g\t%g\t%g\t%g\n", fitdata.yi[i], fitdata.yo[i], fitdata.ysim[i], fitdata.w[i]);
315 double final_wss=0.0;
316 for(
unsigned int i=0; i<fitdata.no; i++) {
317 double v=fitdata.ysim[i]-fitdata.yo[i];
318 final_wss+=fitdata.w[i]*v*v;
320 printf(
" final_wss := %g\n", final_wss);
324 for(
unsigned int i=0; i<nlo.
totalNr; i++) {
325 if(fabs(nlo.
xdelta[i])<1.0E-100)
continue;
327 else nlo.
xdelta[i]*=0.0103;
330 if(verbose>2) printf(
"non-linear optimization, 2nd time\n");
339 printf(
"measured and fitted TAC:\n");
340 for(
unsigned int i=0; i<fitdata.no; i++)
341 printf(
"\t%g\t%g\t%g\t%g\n", fitdata.yi[i], fitdata.yo[i], fitdata.ysim[i], fitdata.w[i]);
343 double final_wss=0.0;
344 for(
unsigned int i=0; i<fitdata.no; i++) {
345 double v=fitdata.ysim[i]-fitdata.yo[i];
346 final_wss+=fitdata.w[i]*v*v;
348 printf(
" final_wss := %g\n", final_wss);
352 for(
unsigned int i=0; i<nlo.
totalNr; i++) {
356 if(verbose>2) printf(
"non-linear optimization, 3rd time\n");
366 printf(
"measured and fitted TAC:\n");
367 for(
unsigned int i=0; i<fitdata.no; i++)
368 printf(
"\t%g\t%g\n", fitdata.yo[i], fitdata.ysim[i]);
370 double final_wss=0.0;
372 for(
unsigned int i=0; i<fitdata.no; i++) {
373 double v=fitdata.ysim[i]-fitdata.yo[i];
374 final_wss+=fitdata.w[i]*v*v;
377 if(verbose>3) printf(
" final_final_final_wss := %g\n", final_wss);
378 par.
r[0].
wss=final_wss;
381 for(
int i=0; i<par.
parNr; i++) par.
r[0].
p[i]=nlo.
xfull[i];
393 if(verbose>1) printf(
" saving %s\n", parfile);
394 FILE *fp=fopen(parfile,
"w");
396 fprintf(stderr,
"Error: cannot open file for writing.\n");
405 if(verbose>0) printf(
"parameters saved in %s\n", parfile);
414 if(verbose>1) printf(
"plotting measured and fitted data\n");
417 for(
int i=0; i<tac2.
sampleNr; i++) fit.
c[0].
y[i]=fitdata.ysim[i];
419 if(
tacPlotFitSVG(&tac2, &fit,
"", nan(
""), nan(
""), nan(
""), nan(
""), svgfile, &status)
426 if(verbose>0) printf(
"Measured and fitted data plotted in %s\n", svgfile);
441double func_disp(
int parNr,
double *p,
void *fdata)
443 FITDATA *d=(FITDATA*)fdata;
445 if(d->verbose>0) {printf(
"%s()\n", __func__); fflush(stdout);}
446 if(parNr!=2)
return(nan(
""));
447 if(d->verbose>20) printf(
"p[]: %g %g\n", p[0], p[1]);
450 double dtac[2*d->ni];
451 double *buf=dtac+d->ni;
452 for(
unsigned int i=0; i<d->ni; i++) dtac[i]=d->yi[i];
453 if(
simDispersion(d->xi, dtac, d->ni, p[0], 0.0, buf))
return(nan(
""));
456 for(
unsigned int i=0; i<d->ni; i++) buf[i]=d->xi[i]+p[1];
457 if(
liInterpolate(buf, dtac, d->ni, d->xo, d->ysim, NULL, NULL, d->no, 0, 1, 0)!=0)
return(nan(
""));
461 for(
unsigned int i=0; i<d->no; i++) {
462 if(isnan(d->ysim[i]) || isnan(d->xo[i]) || d->xo[i]<0.0)
continue;
463 double v=d->ysim[i]-d->yo[i];
465 wss+=d->w[i]*fabs(v);
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,...
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.
unsigned int modelCodeIndex(const char *s)
void nloptInit(NLOPT *nlo)
int nloptAllocate(NLOPT *nlo, unsigned int parNr)
void nloptFree(NLOPT *nlo)
void nloptWrite(NLOPT *d, FILE *fp)
char * optcritCode(optimality_criterion id)
optimality_criterion optcritId(const char *s)
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 simDispersion(double *x, double *y, const int n, const double tau1, const double tau2, double *tmp)
int nloptSimplex(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]
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)
char * tacFormattxt(tacformat c)
int tacXUnitConvert(TAC *tac, const int u, TPCSTATUS *status)
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 libtpcfileutil.
Header file for library libtpcift.
@ ISOTOPE_UNKNOWN
Unknown.
Header file for libtpcli.
Header file for libtpclinopt.
Header file for libtpcmodels.
optimality_criterion
Optimality Criterion for statistical optimizations.
@ OPTCRIT_OLS
Ordinary Least Squares (sum-of-squares, SS).
@ OPTCRIT_LAD
Least Absolute Deviations (sum of absolute deviations, LAE, LAV, LAR).
@ OPTCRIT_UNKNOWN
Unknown optimality criterion.
Header file for library libtpcnlopt.
Header file for libtpcpar.
@ PAR_FORMAT_UNKNOWN
Unknown format.
@ PAR_FORMAT_TSV_UK
UK TSV (point as decimal separator).
Header file for libtpcrand.
Header file for library libtpctac.
Header file for libtpctacmod.