TPCCLIB
Loading...
Searching...
No Matches
b2ptrap.c
Go to the documentation of this file.
1
7/*****************************************************************************/
8#include "tpcclibConfig.h"
9/*****************************************************************************/
10#include <stdio.h>
11#include <stdlib.h>
12#include <string.h>
13#include <math.h>
14/*****************************************************************************/
15#include "tpcextensions.h"
16#include "tpcfileutil.h"
17#include "tpcift.h"
18#include "tpctac.h"
19#include "tpcpar.h"
20#include "tpcli.h"
21#include "tpccm.h"
22#include "tpctacmod.h"
23#include "tpclinopt.h"
24#include "tpcrand.h"
25#include "tpcmodels.h"
26#include "tpcnlopt.h"
27/*****************************************************************************/
28
29/*****************************************************************************/
30const int maxParNr=1;
31/* Local functions */
32double func_b2p(int parNr, double *p, void*);
33/*****************************************************************************/
34typedef struct FITDATA {
36 unsigned int n;
38 double *x;
40 double *ymeas;
42 double *ysim;
44 double *w;
46 double start;
50 int verbose;
51} FITDATA;
52/*****************************************************************************/
53
54/*****************************************************************************/
55static char *info[] = {
56 "Calculate or fit PTAC based on BTAC in cell trapping model.",
57 "Give parameter k in units 1/min, or 'fit' in order to try to fit it.",
58 " ",
59 "Usage: @P [Options] btacfile k ptacfile",
60 " ",
61 "Options:",
62 " -ztime=<Time>",
63 " Time (in minutes) after the PTAC is assumed to be 0 and BTAC steady;",
64 " by default 3 min; only used when k is fitted.",
65 " -svg=<Filename>",
66 " BTAC and (1-HCT*)PTAC are plotted in specified SVG file.",
67 " -stdoptions", // List standard options like --help, -v, etc
68 " ",
69 "See also: fitmtrap, imgmtrap, b2rbc",
70 " ",
71 "Keywords: input, blood, plasma",
72 0};
73/*****************************************************************************/
74
75/*****************************************************************************/
76/* Turn on the globbing of the command line, since it is disabled by default in
77 mingw-w64 (_dowildcard=0); in MinGW32 define _CRT_glob instead, if necessary;
78 In Unix&Linux wildcard command line processing is enabled by default. */
79/*
80#undef _CRT_glob
81#define _CRT_glob -1
82*/
83int _dowildcard = -1;
84/*****************************************************************************/
85
86/*****************************************************************************/
89/*****************************************************************************/
90
91/*****************************************************************************/
95int main(int argc, char **argv)
96{
97 int ai, help=0, version=0, verbose=1;
98 char btacfile[FILENAME_MAX], ptacfile[FILENAME_MAX];
99 char svgfile[FILENAME_MAX];
100 double fixed_k=nan("");
101 double zt=3.0;
102 int weights=1; // 0=file, 1=no weighting, 2=frequency
104
105
106
107 /*
108 * Get arguments
109 */
110 if(argc==1) {tpcPrintUsage(argv[0], info, stderr); return(1);}
111 btacfile[0]=ptacfile[0]=svgfile[0]=(char)0;
112 /* Options */
113 for(ai=1; ai<argc; ai++) if(*argv[ai]=='-') {
114 if(tpcProcessStdOptions(argv[ai], &help, &version, &verbose)==0) continue;
115 char *cptr=argv[ai]+1; if(*cptr=='-') cptr++; if(!*cptr) continue;
116 if(strncasecmp(cptr, "SVG=", 4)==0 && strlen(cptr)>4) {
117 strlcpy(svgfile, cptr+4, FILENAME_MAX); continue;
118 } else if(strncasecmp(cptr, "ZTIME=", 6)==0 && strlen(cptr)>6) {
119 if(!atofCheck(cptr+6, &zt) && zt>0.0) continue;
120 } else if(strcasecmp(cptr, "W1")==0) {
121 weights=1; continue;
122 } else if(strcasecmp(cptr, "WF")==0) {
123 weights=2; continue;
124 }
125 fprintf(stderr, "Error: invalid option '%s'.\n", argv[ai]);
126 return(1);
127 } else break;
128
129 TPCSTATUS status; statusInit(&status);
130 statusSet(&status, __func__, __FILE__, __LINE__, TPCERROR_OK);
131 status.verbose=verbose-3;
132
133 /* Print help or version? */
134 if(help==2) {tpcHtmlUsage(argv[0], info, ""); return(0);}
135 if(help) {tpcPrintUsage(argv[0], info, stdout); return(0);}
136 if(version) {tpcPrintBuild(argv[0], stdout); return(0);}
137
138 /* Process other arguments, starting from the first non-option */
139 if(ai<argc) strlcpy(btacfile, argv[ai++], FILENAME_MAX);
140 if(ai<argc) {
141 if(strcasecmp(argv[ai], "FIT")!=0) {
142 if(atofCheck(argv[ai], &fixed_k) || !(fixed_k>0.0)) {
143 fprintf(stderr, "Error: invalid k value '%s'.\n", argv[ai]);
144 return(1);
145 }
146 }
147 ai++;
148 }
149 if(ai<argc) strlcpy(ptacfile, argv[ai++], FILENAME_MAX);
150 if(ai<argc) {
151 fprintf(stderr, "Error: invalid argument '%s'.\n", argv[ai]);
152 return(1);
153 }
154
155 /* Did we get all the information that we need? */
156 if(!ptacfile[0]) {
157 fprintf(stderr, "Error: missing command-line argument; use option --help\n");
158 return(1);
159 }
160
161
162 /* In verbose mode print arguments and options */
163 if(verbose>1) {
164 printf("btacfile := %s\n", btacfile);
165 printf("ptacfile := %s\n", ptacfile);
166 if(!isnan(fixed_k)) printf("fixed_k := %g\n", fixed_k);
167 else printf("ztime := %g min\n", zt);
168 printf("optcrit := %s\n", optcritCode(optcrit));
169 fflush(stdout);
170 }
171
172
173 /*
174 * Read TAC data
175 */
176 if(verbose>1) printf("reading %s\n", btacfile);
177 TAC tac; tacInit(&tac);
178 if(tacRead(&tac, btacfile, &status)!=TPCERROR_OK) {
179 fprintf(stderr, "Error: %s\n", errorMsg(status.error));
180 tacFree(&tac); return(2);
181 }
182 if(verbose>1) {
183 printf("fileformat := %s\n", tacFormattxt(tac.format));
184 printf("tacNr := %d\n", tac.tacNr);
185 printf("sampleNr := %d\n", tac.sampleNr);
186 printf("xunit := %s\n", unitName(tac.tunit));
187 printf("yunit := %s\n", unitName(tac.cunit));
188 printf("isframe := %d\n", tac.isframe);
189 }
190 if(tac.tacNr<1) {
191 fprintf(stderr, "Error: file contains no data.\n");
192 tacFree(&tac); return(2);
193 } else if(tac.tacNr>1) {
194 if(verbose>0) fprintf(stderr, "Warning: file contains more than one curve.\n");
195 tac.tacNr=1;
196 }
197 /* Check NaNs */
198 if(tacNaNs(&tac)>0) {
199 fprintf(stderr, "Error: data contains missing values.\n");
200 tacFree(&tac); return(2);
201 }
202 /* Sort data by sample time */
203 tacSortByTime(&tac, &status);
204 /* Take average of any duplicate samples */
205 if(tacMultipleSamples(&tac, 1, &tac, verbose-2)!=0) {
206 fprintf(stderr, "Error: cannot process duplicate samples.\n");
207 tacFree(&tac); return(2);
208 }
209 /* Get initial x range */
210 double xmin, xmax;
211 if(tacXRange(&tac, &xmin, &xmax)!=0) {
212 fprintf(stderr, "Error: invalid data sample times.\n");
213 tacFree(&tac); return(2);
214 }
215 /* Convert sample times into minutes */
216 if(tac.tunit==UNIT_UNKNOWN) {
217 if(xmax<10.0) tac.tunit=UNIT_MIN; else tac.tunit=UNIT_SEC;
218 }
219 if(tacXUnitConvert(&tac, UNIT_MIN, &status)!=TPCERROR_OK) {
220 fprintf(stderr, "Error: %s\n", errorMsg(status.error));
221 tacFree(&tac); return(2);
222 }
223 /* Get final x range */
224 if(tacXRange(&tac, &xmin, &xmax)!=0) {
225 fprintf(stderr, "Error: invalid data sample times.\n");
226 tacFree(&tac); return(2);
227 }
228 if(verbose>1) {
229 printf("xmin := %g\n", xmin);
230 printf("xmax := %g\n", xmax);
231 }
232 if(tac.sampleNr<3) {
233 fprintf(stderr, "Error: too few samples.\n");
234 tacFree(&tac); return(2);
235 }
236 /* Check that ztime setting is feasible with the data */
237 if(isnan(fixed_k) && (zt>=xmax || zt<=xmin)) {
238 fprintf(stderr, "Error: ztime outside of data range.\n");
239 tacFree(&tac); return(2);
240 }
241
242
243 /* Add place for PTAC */
244 if(verbose>1) fprintf(stdout, "allocating memory for PTAC\n");
245 if(tacAllocateMore(&tac, 1)!=TPCERROR_OK) {
246 fprintf(stderr, "Error: cannot allocate memory.\n");
247 tacFree(&tac); return(3);
248 }
249 strcpy(tac.c[1].name, "PTAC");
250 strcpy(tac.c[0].name, "BTAC");
251 tac.tacNr=2;
252
253
254 /* Add data weights, if requested */
255 if(weights==1) {
257 for(int i=0; i<tac.sampleNr; i++) tac.w[i]=1.0;
258 } else if(weights==2) {
259 if(tacWByFreq(&tac, ISOTOPE_UNKNOWN, &status)!=TPCERROR_OK) {
260 fprintf(stderr, "Error: %s\n", errorMsg(status.error));
261 tacFree(&tac); return(3);
262 }
263 }
264
265
266
267 /* Set data pointers for the fit */
268 FITDATA fitdata;
269 fitdata.n=tac.sampleNr;
270 fitdata.x=tac.x;
271 fitdata.ymeas=tac.c[0].y;
272 fitdata.ysim=tac.c[1].y;
273 fitdata.w=tac.w;
274 fitdata.start=zt;
275 fitdata.optcrit=optcrit;
276 if(verbose>10) fitdata.verbose=verbose-10; else fitdata.verbose=0;
277
278
279 /*
280 * If k is given, then simulate PTAC
281 */
282 if(fixed_k>0.0) {
283 func_b2p(1, &fixed_k, &fitdata);
284 }
285
286
287 /*
288 * Fitting, if k value was not given
289 */
290 if(isnan(fixed_k)) {
291
292 if(verbose>1) printf("preparing for fitting\n");
293 drandSeed(1);
294
295 /* Set NLLS options */
296 NLOPT nlo; nloptInit(&nlo);
297 if(nloptAllocate(&nlo, 1)!=TPCERROR_OK) {
298 fprintf(stderr, "Error: cannot initiate NLLS.\n");
299 tacFree(&tac); return(5);
300 }
301 nlo._fun=func_b2p;
302 nlo.fundata=&fitdata;
303 nlo.totalNr=1;
304 nlo.xlower[0]=0.0;
305 nlo.xupper[0]=1.0;
306 nlo.xtol[0]=0.00001;
307 nlo.xfull[0]=0.25; // initial guess
308 nlo.maxFunCalls=500000;
309 /* Fit */
310 if(verbose>4) nloptWrite(&nlo, stdout);
311 if(nloptITGO1(&nlo, 1, 0, 10000, 20, &status)!=TPCERROR_OK) {
312 fprintf(stderr, "Error: %s\n", errorMsg(status.error));
313 tacFree(&tac); nloptFree(&nlo); return(6);
314 }
315 nlo._fun(nlo.totalNr, nlo.xfull, nlo.fundata);
316 if(verbose>2) nloptWrite(&nlo, stdout);
317 if(verbose>6) {
318 printf("measured and simulated TAC:\n");
319 for(int i=0; i<tac.sampleNr; i++)
320 printf("\t%g\t%g\t%g\n", tac.x[i], tac.c[0].y[i], tac.c[1].y[i]);
321 }
322 if(verbose>0) printf("WSS := %g\n", nlo.funval);
323 if(verbose>0) printf("k := %g\n", nlo.xfull[0]);
324
325 nloptFree(&nlo);
326 }
327
328 /*
329 * Write PTAC
330 */
331 {
332 if(verbose>1) printf("saving (1-HCT)*Cp TAC\n");
333 tacSwapTACCs(&tac, 0, 1);
334 tac.tacNr=1;
335 int ret=TPCERROR_OK;
336 FILE *fp; fp=fopen(ptacfile, "w");
337 if(fp==NULL) {
338 fprintf(stderr, "Error: cannot open file for writing '%s'.\n", ptacfile);
339 ret=TPCERROR_FAIL;
340 } else {
341 ret=tacWrite(&tac, fp, TAC_FORMAT_PMOD, 1, &status);
342 fclose(fp);
343 if(ret!=TPCERROR_OK) fprintf(stderr, "Error: %s\n", errorMsg(status.error));
344 }
345 if(ret!=TPCERROR_OK) {
346 tacFree(&tac);
347 return(11);
348 }
349 if(verbose>0) printf("(1-HCT)*PTAC written in %s.\n", ptacfile);
350 }
351
352
353 tacFree(&tac);
354 return(0);
355}
356/*****************************************************************************/
357
358/*****************************************************************************
359 *
360 * Functions to be minimized
361 *
362 *****************************************************************************/
363double func_b2p(int parNr, double *p, void *fdata)
364{
365 FITDATA *d=(FITDATA*)fdata;
366
367 if(d->verbose>0) {printf("%s()\n", __func__); fflush(stdout);}
368 if(parNr!=1) return(nan(""));
369 if(d->verbose>20) printf("p[]: %g\n", p[0]);
370
371 /* Calculate the curve values and weighted SS */
372
373 double cpi=0.0;
374 double t_last=0.0, cp_last=0.0, cpi_last=0.0;
375
376 double wss=0.0;
377 for(unsigned int i=0; i<d->n; i++) {
378 /* delta time / 2 */
379 double dt2=0.5*(d->x[i]-t_last);
380 if(!isnan(d->ymeas[i]) && !isnan(d->x[i]) && dt2>0.0) {
381 /* plasma */
382 d->ysim[i] = (d->ymeas[i] - p[0]*(cpi_last + dt2*cp_last)) / (1.0 + dt2*p[0]);
383 /* integral */
384 cpi+=(d->ysim[i]+cp_last)*dt2;
385 } else {
386 d->ysim[i]=cp_last;
387 }
388 t_last=d->x[i];
389 cp_last=d->ysim[i];
390 cpi_last=cpi;
391 double v=d->ysim[i]; // PTAC compared to zero
392 if(d->x[i]>=d->start && !isnan(v)) {
393 if(d->optcrit==OPTCRIT_LAD)
394 wss+=d->w[i]*fabs(v);
395 else
396 wss+=d->w[i]*v*v;
397 }
398 }
399
400 if(d->verbose>20) printf("p[]: %g WSS=%g start=%g\n", p[0], wss, d->start);
401 return(wss);
402}
403/*****************************************************************************/
404
405/*****************************************************************************/
int atofCheck(const char *s, double *v)
Definition decpoint.c:94
unsigned int drandSeed(short int seed)
Make and optionally set the seed for rand(), drand, drandRange, and drandGaussian().
Definition gaussdev.c:27
void nloptInit(NLOPT *nlo)
Definition nlopt.c:25
int nloptAllocate(NLOPT *nlo, unsigned int parNr)
Definition nlopt.c:74
void nloptFree(NLOPT *nlo)
Definition nlopt.c:52
void nloptWrite(NLOPT *d, FILE *fp)
Definition nlopt.c:302
char * optcritCode(optimality_criterion id)
Definition optcrit.c:60
int tpcProcessStdOptions(const char *s, int *print_usage, int *print_version, int *verbose_level)
Definition proginfo.c:47
int tpcHtmlUsage(const char *program, char *text[], const char *path)
Definition proginfo.c:169
void tpcPrintBuild(const char *program, FILE *fp)
Definition proginfo.c:339
void tpcPrintUsage(const char *program, char *text[], FILE *fp)
Definition proginfo.c:114
void statusInit(TPCSTATUS *s)
Definition statusmsg.c:104
char * errorMsg(tpcerror e)
Definition statusmsg.c:68
void statusSet(TPCSTATUS *s, const char *func, const char *srcfile, int srcline, tpcerror error)
Definition statusmsg.c:142
size_t strlcpy(char *dst, const char *src, size_t dstsize)
Definition stringext.c:632
double(* _fun)(int, double *, void *)
Definition tpcnlopt.h:42
double funval
Definition tpcnlopt.h:50
unsigned int maxFunCalls
Definition tpcnlopt.h:46
double * xupper
Definition tpcnlopt.h:33
double * xlower
Definition tpcnlopt.h:31
void * fundata
Definition tpcnlopt.h:44
double * xfull
Definition tpcnlopt.h:29
double * xtol
Definition tpcnlopt.h:39
unsigned int totalNr
Definition tpcnlopt.h:27
char name[MAX_TACNAME_LEN+1]
Definition tpctac.h:81
double * y
Definition tpctac.h:75
Definition tpctac.h:87
double * x
Definition tpctac.h:97
unit cunit
Definition tpctac.h:105
tacformat format
Definition tpctac.h:93
int sampleNr
Definition tpctac.h:89
double * w
Definition tpctac.h:111
int isframe
Definition tpctac.h:95
TACC * c
Definition tpctac.h:117
weights weighting
Definition tpctac.h:115
unit tunit
Definition tpctac.h:109
int tacNr
Definition tpctac.h:91
int verbose
Verbose level, used by statusPrint() etc.
tpcerror error
Error code.
void tacFree(TAC *tac)
Definition tac.c:106
void tacInit(TAC *tac)
Definition tac.c:24
int tacAllocateMore(TAC *tac, int tacNr)
Definition tac.c:178
int tacRead(TAC *d, const char *fname, TPCSTATUS *status)
Definition tacio.c:413
char * tacFormattxt(tacformat c)
Definition tacio.c:98
int tacWrite(TAC *tac, FILE *fp, tacformat format, int extra, TPCSTATUS *status)
Definition tacio.c:332
int tacNaNs(TAC *tac)
Definition tacnan.c:71
int tacSortByTime(TAC *d, TPCSTATUS *status)
Definition tacorder.c:74
int tacSwapTACCs(TAC *d, int i1, int i2)
Definition tacorder.c:282
int tacMultipleSamples(TAC *d1, const int fixMode, TAC *d2, const int verbose)
Check TAC data for multiple samples with the same sample time. Optionally replace the multiple sample...
Definition tacorder.c:336
int tacXUnitConvert(TAC *tac, const int u, TPCSTATUS *status)
Definition tacunits.c:23
int tacWByFreq(TAC *tac, isotope isot, TPCSTATUS *status)
Definition tacw.c:134
int tacXRange(TAC *d, double *xmin, double *xmax)
Get the range of x values (times) in TAC structure.
Definition tacx.c:124
int nloptITGO1(NLOPT *nlo, const int doLocal, unsigned int tgoNr, unsigned int sampleNr, unsigned int neighNr, TPCSTATUS *status)
Definition tgo.c:59
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).
@ UNIT_MIN
minutes
@ UNIT_UNKNOWN
Unknown unit.
@ UNIT_SEC
seconds
@ TPCERROR_FAIL
General error.
@ TPCERROR_OK
No error.
char * unitName(int unit_code)
Definition units.c:143
Header file for libtpcfileutil.
Header file for library libtpcift.
@ ISOTOPE_UNKNOWN
Unknown.
Definition tpcisotope.h:51
Header file for libtpcli.
Header file for libtpclinopt.
Header file for libtpcmodels.
optimality_criterion
Optimality Criterion for statistical optimizations.
Definition tpcmodels.h:67
@ OPTCRIT_OLS
Ordinary Least Squares (sum-of-squares, SS).
Definition tpcmodels.h:69
@ OPTCRIT_LAD
Least Absolute Deviations (sum of absolute deviations, LAE, LAV, LAR).
Definition tpcmodels.h:71
Header file for library libtpcnlopt.
Header file for libtpcpar.
Header file for libtpcrand.
Header file for library libtpctac.
@ TAC_FORMAT_PMOD
PMOD TAC format.
Definition tpctac.h:33
Header file for libtpctacmod.