TPCCLIB
Loading...
Searching...
No Matches
spillinp.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 "tpcift.h"
17#include "tpctac.h"
18#include "tpcfileutil.h"
19#include "tpcli.h"
20#include "tpctacmod.h"
21#include "tpclinopt.h"
22#include "tpcrand.h"
23#include "tpcnlopt.h"
24/*****************************************************************************/
25
26/*****************************************************************************/
27static char *info[] = {
28 "General geometrical model for cardiac spillover correction, based on",
29 "the following equations describing the regional TACs of myocardial muscle",
30 "and cavity with blood (Cb) and muscle tissue (Ct) curves:",
31 " ",
32 "Croi,myo(t) = fBV*Cb(t) + (1-fBV)*Ct(t) ",
33 "Croi,cav(t) = beta*Cb(t) + (1-beta)*Ct(t) ",
34 " ",
35 ", where fBV<beta. The spillover corrected BTAC can be calculated as",
36 " ",
37 " (1-fBV)*Croi,cav(t) + (1-beta)*Croi,myo(t)",
38 "Cb(t) = ------------------------------------------",
39 " beta*(1-fBV) - fBV*(1-beta)",
40 " ",
41 "and, optionally, the corrected tissue TAC can be calculated as",
42 " ",
43 " beta*Croi,myo(t) - fBV*Croi,cav(t)",
44 "Ct(t) = ----------------------------------",
45 " beta*(1-fBV) - fBV*(1-beta)",
46 " ",
47 "Radioactivity concentrations in regions-of-interest is given in TAC file,",
48 "including at least the myocardial muscle and cavity ROIs.",
49 "The names or numbers of these two ROIs are given next.",
50 " ",
51 "Usage: @P [Options] tacfile MYO CAV fBV beta cbfile [ctfile]",
52 " ",
53 "Options:",
54 " -sim[ulate]",
55 " Instead of PVC, PVE is simulated from Ct(t) and Cb(t).",
56 " -stdoptions", // List standard options like --help, -v, etc
57 " ",
58 "Example:",
59 " @P aim25.tac myoc cavity 0.2 0.9 aim25ab.tac",
60 " ",
61 "References:",
62 "1. Feng et al. (1996), https://doi.org/10.1109/10.486290",
63 "2. Li et al. (1998), https://doi.org/10.1007/BF02522867",
64 "3. Fang et al. (2008), https://doi.org/10.2967/jnumed.107.047613",
65 " ",
66 "See also: heartcor, tacadd, b2plasma, tacformat",
67 " ",
68 "Keywords: input, blood, PVC, myocardium, cavity, spill-over",
69 0};
70/*****************************************************************************/
71
72/*****************************************************************************/
73/* Turn on the globbing of the command line, since it is disabled by default in
74 mingw-w64 (_dowildcard=0); in MinGW32 define _CRT_glob instead, if necessary;
75 In Unix&Linux wildcard command line processing is enabled by default. */
76/*
77#undef _CRT_glob
78#define _CRT_glob -1
79*/
80int _dowildcard = -1;
81/*****************************************************************************/
82
83/*****************************************************************************/
84/* Local functions */
85double func_ggm(int parNr, double *p, void*);
86double func_ggm2(int parNr, double *p, void*);
87/*****************************************************************************/
88typedef struct FITDATA {
90 unsigned int nr;
92 double *xr;
94 double *ymyo;
96 double *ycav;
97
99 unsigned int nb;
101 double *xb;
103 double *yb;
104
106 int verbose;
107} FITDATA;
108/*****************************************************************************/
109
110/*****************************************************************************/
114int ggmEstim(
117 TAC *rtac,
119 const int iMyo,
121 const int iCav,
124 TAC *stac,
126 double start,
128 int method,
130 double *fBV,
132 double *beta,
134 TPCSTATUS *status
135) {
136 int verbose=0; if(status!=NULL) verbose=status->verbose;
137 if(verbose>0) printf("%s(*rtac, %d, %d, *stac, %g, %d)\n", __func__, iMyo, iCav, start, method);
138 if(rtac==NULL || stac==NULL || fBV==NULL || beta==NULL) {
139 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_FAIL);
140 return(TPCERROR_FAIL);
141 }
142 if(rtac->tacNr<2 || rtac->sampleNr<2 || stac->tacNr<1 || stac->sampleNr<1) {
143 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_NO_DATA);
144 return(TPCERROR_NO_DATA);
145 }
146 if(iMyo<0 || iMyo>=rtac->tacNr || iCav<0 || iCav>=rtac->tacNr) {
147 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_NO_DATA);
148 return(TPCERROR_NO_DATA);
149 }
150
151 /* Check/set start time */
152 double rx1, rx2, sx1, sx2;
153 if(tacXRange(rtac, &rx1, &rx2) || tacXRange(stac, &sx1, &sx2)) {
154 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INVALID_XRANGE);
156 }
157 if(!(start>0.0)) {
158 if(verbose>1) printf("setting start time\n");
159 if(method==0) {
160 start=0.5*(rx1+rx2);
161 if(sx1<start) start=sx1;
162 } else {
163 if(verbose>1) printf("finding peak\n");
164 int i;
165 double ymax;
166 if(tacYRange(rtac, iCav, NULL, &ymax, NULL, &i, NULL, NULL)) {
167 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INVALID_XRANGE);
169 }
170 start=rtac->x[i];
171 if(verbose>1) printf("Cavity peak %g at %g (frame %d)\n", ymax, start, i);
172 }
173 }
174 if(verbose>1) {
175 printf("ROI data range: %g - %g\n", rx1, rx2);
176 printf("Blood sample data range: %g - %g\n", sx1, sx2);
177 printf("Start time: %g\n", start);
178 }
179 /* Extract the data before start time */
180 TAC ftac; tacInit(&ftac);
181 int ret=tacExtractRange(rtac, &ftac, start, rx2);
182 if(ret==TPCERROR_OK && ftac.sampleNr<2) ret=TPCERROR_INVALID_XRANGE;
183 if(ret!=TPCERROR_OK) {
184 tacFree(&ftac);
185 statusSet(status, __func__, __FILE__, __LINE__, ret);
186 return(ret);
187 }
188
189 /* Set data for the fit */
190 FITDATA fitdata;
191 fitdata.verbose=0;
192 fitdata.nr=ftac.sampleNr;
193 fitdata.xr=ftac.x;
194 fitdata.ymyo=ftac.c[iMyo].y;
195 fitdata.ycav=ftac.c[iCav].y;
196 fitdata.nb=stac->sampleNr;
197 fitdata.xb=stac->x;
198 fitdata.yb=stac->c[0].y;
199
200 /* Set parameters for non-linear optimisation */
201 int parNr;
202 if(method==0) {
203 parNr=2; // beta and fb; fBV=fb*beta
204 } else {
205 parNr=8; // beta, fb (fBV=fb*beta), and Feng function parameters
206 }
207 NLOPT nlo; nloptInit(&nlo);
208 ret=nloptAllocate(&nlo, parNr);
209 if(ret!=TPCERROR_OK) {
210 tacFree(&ftac);
211 statusSet(status, __func__, __FILE__, __LINE__, ret);
212 return(ret);
213 }
214 /* Set function */
215 nlo.fundata=&fitdata;
216 nlo.totalNr=parNr;
217 {
218 nlo.xlower[0]=0.1; //0.1;
219 nlo.xupper[0]=1.0; //1.0;
220 nlo.xfull[0]=0.5; //0.45;
221 nlo.xdelta[0]=0.001;
222 nlo.xtol[0]=0.0001;
223 }
224 {
225 nlo.xlower[1]=0.0; //0.0;
226 nlo.xupper[1]=0.9; //0.9
227 nlo.xfull[1]=0.5; //0.69;
228 nlo.xdelta[1]=0.001;
229 nlo.xtol[1]=0.0001;
230 }
231 if(method==0) {
232 nlo._fun=func_ggm;
233 nlo.maxFunCalls=20000;
234 } else {
235 nlo._fun=func_ggm2;
236 nlo.maxFunCalls=50000;
237 int i=2; // A1
238 nlo.xlower[i]=0.0;
239 nlo.xupper[i]=5000.0;
240 nlo.xfull[i]=1300.0;
241 nlo.xdelta[i]=50.0;
242 nlo.xtol[i]=0.01;
243 i=4; // A2
244 nlo.xlower[i]=0.0;
245 nlo.xupper[i]=100.0;
246 nlo.xfull[i]=7.5;
247 nlo.xdelta[i]=0.5;
248 nlo.xtol[i]=0.01;
249 i=6; // A3
250 nlo.xlower[i]=0.0;
251 nlo.xupper[i]=100.0;
252 nlo.xfull[i]=6.8;
253 nlo.xdelta[i]=0.4;
254 nlo.xtol[i]=0.01;
255 i=3; // L1
256 nlo.xlower[i]=-8.;
257 nlo.xupper[i]=0.0;
258 nlo.xfull[i]=-6.7;
259 nlo.xdelta[i]=0.1;
260 nlo.xtol[i]=0.001;
261 i=5; // f*L1
262 nlo.xlower[i]=0.0;
263 nlo.xupper[i]=0.9;
264 nlo.xfull[i]=0.025;
265 nlo.xdelta[i]=0.002;
266 nlo.xtol[i]=0.0001;
267 i=7; // g*f*L1
268 nlo.xlower[i]=0.0;
269 nlo.xupper[i]=0.9;
270 nlo.xfull[i]=0.1;
271 nlo.xdelta[i]=0.02;
272 nlo.xtol[i]=0.001;
273 }
274
275#if(0)
276 // call function for testing
277 fitdata.verbose=10;
278 double ss=func_ggm(nlo.totalNr, nlo.xfull, &fitdata);
279 printf("ss=%g\n", ss);
280 nloptFree(&nlo);
281 *fBV=0.25; *beta=0.50; // placeholder
282#else
283 /* Fit */
284 if(verbose>2) {
285 printf("initial guess\n");
286 nlo.funval=nlo._fun(nlo.totalNr, nlo.xfull, nlo.fundata);
287 nloptWrite(&nlo, stdout);
288 fflush(stdout);
289 }
290
291 //fitdata.verbose=10;
292 //ret=nloptSimplexMS(&nlo, 500, status);
293 //ret=nloptIATGO(&nlo, 1, 1000, 0.15, status);
294 ret=nloptIATGO(&nlo, 1, 0, 0.15, status);
295 if(ret!=TPCERROR_OK) {
296 tacFree(&ftac); nloptFree(&nlo);
297 statusSet(status, __func__, __FILE__, __LINE__, ret);
298 return(ret);
299 }
300 *beta=nlo.xfull[0];
301 *fBV=nlo.xfull[1]*nlo.xfull[0];
302 if(verbose>1) {printf(" SS := %g\n", nlo.funval); fflush(stdout);}
303#endif
304
305 tacFree(&ftac); nloptFree(&nlo);
306
307 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_OK);
308 return(TPCERROR_OK);
309}
310/*****************************************************************************/
311
312/*****************************************************************************/
316int main(int argc, char **argv)
317{
318 int ai, help=0, version=0, verbose=1;
319 char tacfile[FILENAME_MAX], bfile[FILENAME_MAX], tfile[FILENAME_MAX];
320 char sfile[FILENAME_MAX];
321 char myocname[MAX_TACNAME_LEN+1], cavname[MAX_TACNAME_LEN+1];
322 double fBV=nan(""), beta=nan("");
323 int mode=0; // 0=correct, 1=simulate PVE, 2=fit
324 int method=0; // fit method
325
326
327 /*
328 * Get arguments
329 */
330 if(argc==1) {tpcPrintUsage(argv[0], info, stderr); return(1);}
331 tacfile[0]=bfile[0]=tfile[0]=sfile[0]=(char)0;
332 myocname[0]=cavname[0]=(char)0;
333
334 /* Options */
335 for(ai=1; ai<argc; ai++) if(*argv[ai]=='-') {
336 if(tpcProcessStdOptions(argv[ai], &help, &version, &verbose)==0) continue;
337 char *cptr=argv[ai]+1; if(*cptr=='-') cptr++; if(!*cptr) continue;
338 if(strncasecmp(cptr, "SIMULATE", 3)==0) {
339 mode=1; continue;
340 } else if(strncasecmp(cptr, "FFIT", 2)==0) {
341 method=1; continue;
342 }
343 fprintf(stderr, "Error: invalid option '%s'.\n", argv[ai]);
344 return(1);
345 } else break; // tac name argument may start with '-'
346
347 TPCSTATUS status; statusInit(&status);
348 statusSet(&status, __func__, __FILE__, __LINE__, TPCERROR_OK);
349 status.verbose=verbose-2;
350
351 /* Print help or version? */
352 if(help==2) {tpcHtmlUsage(argv[0], info, ""); return(0);}
353 if(help) {tpcPrintUsage(argv[0], info, stdout); return(0);}
354 if(version) {tpcPrintBuild(argv[0], stdout); return(0);}
355
356 /* The (non-option) arguments */
357 if(ai<argc) {strlcpy(tacfile, argv[ai], FILENAME_MAX); ai++;}
358 if(ai<argc) {strlcpy(myocname, argv[ai], MAX_TACNAME_LEN); ai++;}
359 if(ai<argc) {strlcpy(cavname, argv[ai], MAX_TACNAME_LEN); ai++;}
360 if(ai>argc) {fprintf(stderr, "Error: missing command-line argument(s).\n"); return(1);}
361
362 if(ai<argc) { // next one or two arguments: either sample file, or fBV and beta
363 if(!atofCheck(argv[ai], &fBV) && !atofCheck(argv[ai+1], &beta)) {
364 if(!(fBV>=0.0 && fBV<=1.0)) {
365 fprintf(stderr, "Error: invalid Fbv command-line argument.\n"); return(1);}
366 if(!(beta>=0.0 && beta<=1.0)) {
367 fprintf(stderr, "Error: invalid Beta command-line argument.\n"); return(1);}
368 /* Check that fBV<beta */
369 if(fBV>=beta) {
370 fprintf(stderr, "Error: fBV must be lower than beta.\n"); return(1);}
371 ai+=2;
372 } else {
373 if(!fileExist(argv[ai])) {
374 fprintf(stderr, "Error: missing sample file %s\n", argv[ai]); return(1);}
375 strlcpy(sfile, argv[ai], FILENAME_MAX);
376 mode=3;
377 ai++;
378 }
379 }
380 if(ai<argc) {strlcpy(bfile, argv[ai], FILENAME_MAX); ai++;}
381 if(ai<argc) {strlcpy(tfile, argv[ai], FILENAME_MAX); ai++;}
382 /* check that there are no extra arguments */
383 if(ai<argc) {fprintf(stderr, "Error: extra command-line argument.\n"); return(1);}
384 /* Is something missing? */
385 if(!bfile[0]) {tpcPrintUsage(argv[0], info, stdout); return(1);}
386
387 /* In verbose mode print arguments and options */
388 if(verbose>1) {
389 for(ai=0; ai<argc; ai++) printf("%s ", argv[ai]);
390 printf("\n");
391 printf("tacfile := %s\n", tacfile);
392 if(sfile[0]) printf("sfile := %s\n", sfile);
393 if(isfinite(fBV)) printf("fBV := %g\n", fBV);
394 if(isfinite(beta)) printf("beta := %g\n", beta);
395 printf("mode := %d\n", mode);
396 if(mode==3) printf("method := %d\n", method);
397 printf("bfile := %s\n", bfile);
398 if(tfile[0]) printf("tfile := %s\n", tfile);
399 }
400
401 /* Check that fBV<beta */
402 if(fBV>=beta) {
403 fprintf(stderr, "Error: fBV must be lower than beta.\n");
404 return(1);
405 }
406
407
408 /*
409 * Read the data
410 */
411 if(verbose>1) printf("reading TACs\n");
412 statusSet(&status, __func__, __FILE__, __LINE__, TPCERROR_OK);
413 TAC tac; tacInit(&tac);
414 if(tacRead(&tac, tacfile, &status)!=TPCERROR_OK) {
415 fprintf(stderr, "Error: %s\n", errorMsg(status.error));
416 tacFree(&tac); return(2);
417 }
418 if(tac.tacNr<2) {
419 fprintf(stderr, "Error: file does not contain myocardial and cavity ROI.\n");
420 tacFree(&tac); return(2);
421 }
422 /* Check NaNs */
423 if(tacNaNs(&tac)>0) {
424 fprintf(stderr, "Error: data contains missing values.\n");
425 tacFree(&tac); return(2);
426 }
427 /* Sort data by sample time */
428 tacSortByTime(&tac, &status);
429
430 /*
431 * Find the myocardial and cavity ROIs among the TACs
432 */
433 int iMyoc=-1;
434 {
435 int n=tacSelectTACs(&tac, myocname, 1, &status);
436 if(n>0) iMyoc=tacSelectBestReference(&tac);
437 if(iMyoc<0) {
438 fprintf(stderr, "Error: cannot identify myocardial ROI.\n");
439 tacFree(&tac); return(3);
440 }
441 }
442 int iCav=-1;
443 {
444 int n=tacSelectTACs(&tac, cavname, 1, &status);
445 if(n>0) iCav=tacSelectBestReference(&tac);
446 if(iCav<0) {
447 fprintf(stderr, "Error: cannot identify cavity ROI.\n");
448 tacFree(&tac); return(3);
449 }
450 }
451 if(verbose>1) {
452 printf("myocardial ROI: %s\n", tac.c[iMyoc].name);
453 printf("cavity ROI: %s\n", tac.c[iCav].name);
454 }
455
456
457 /*
458 * If blood sample file is available, then estimate fBV and beta
459 */
460 if(mode==3) {
461 if(verbose>1) printf("estimating PVC parameters\n");
462 /* Read the blood sample(s) */
463 TAC bs; tacInit(&bs);
464 if(tacRead(&bs, sfile, &status)!=TPCERROR_OK) {
465 fprintf(stderr, "Error: %s\n", errorMsg(status.error));
466 tacFree(&tac); tacFree(&bs); return(2);
467 }
468 if(bs.tacNr>1) {
469 fprintf(stderr, "Note: using only the first concentration column in sample file.\n");
470 bs.tacNr=1;
471 }
472 /* Check NaNs */
473 if(tacNaNs(&bs)>0) {
474 fprintf(stderr, "Error: blood sample file contains missing values.\n");
475 tacFree(&tac); tacFree(&bs); return(2);
476 }
477 /* Sort data by sample time */
478 tacSortByTime(&bs, &status);
479 /* Make sure that blood sample data are in same units as ROI TAC data */
480 if((bs.tunit!=tac.tunit && tacXUnitConvert(&bs, tac.tunit, &status)) ||
481 (bs.cunit!=tac.cunit && tacYUnitConvert(&bs, tac.cunit, &status))) {
482 fprintf(stderr, "Error: missing or incompatible data units.\n");
483 }
484
485 /* Estimation */
486 if(ggmEstim(&tac, iMyoc, iCav, &bs, 0.0, method, &fBV, &beta, &status)!=TPCERROR_OK) {
487 fprintf(stderr, "Error: %s\n", errorMsg(status.error));
488 tacFree(&tac); tacFree(&bs); return(9);
489 }
490
491
492 tacFree(&bs);
493 if(verbose>1) {
494 printf("fBV := %g\n", fBV);
495 printf("beta := %g\n", beta);
496 }
497 mode=0; // So that BTAC will be calculated next
498 }
499
500
501 /*
502 * Calculate BTAC or cavity TAC
503 */
504 TAC btac; tacInit(&btac);
505 {
506 /* Setup place for BTAC */
507 int cn=tac.tacNr;
508 tac.tacNr=1;
509 if(tacDuplicate(&tac, &btac)) {
510 fprintf(stderr, "Error: cannot set up BTAC data.\n");
511 tacFree(&tac); tacFree(&btac); return(4);
512 }
513 tac.tacNr=cn;
514 if(mode==0) {
515 /* Calculate BTAC */
516 strcpy(btac.c[0].name, "Blood");
517 double d=beta*(1.0-fBV)-fBV*(1.0-beta); if(verbose>2) printf("GGM-divider := %g\n", d);
518 if(!(fabs(d)>1.0E-010)) {
519 fprintf(stderr, "Error: invalid fBV and beta.\n");
520 tacFree(&tac); tacFree(&btac); return(4);
521 }
522 for(int i=0; i<tac.sampleNr; i++)
523 btac.c[0].y[i] = ((1.0-fBV)*tac.c[iCav].y[i] - (1.0-beta)*tac.c[iMyoc].y[i]) / d;
524 } else {
525 /* Calculate cavity TAC */
526 strcpy(btac.c[0].name, "Cav");
527 for(int i=0; i<tac.sampleNr; i++)
528 btac.c[0].y[i] = beta*tac.c[iCav].y[i] + (1.0-beta)*tac.c[iMyoc].y[i];
529 }
530 /* Write file */
531 FILE *fp; fp=fopen(bfile, "w");
532 if(fp==NULL) {
533 fprintf(stderr, "Error: cannot write %s\n", bfile);
534 tacFree(&tac); tacFree(&btac);
535 return(11);
536 }
537 int ret=tacWrite(&btac, fp, TAC_FORMAT_UNKNOWN, 0, &status);
538 fclose(fp);
539 if(ret!=TPCERROR_OK) {
540 fprintf(stderr, "Error: %s\n", errorMsg(status.error));
541 tacFree(&tac); tacFree(&btac);
542 return(11);
543 }
544 if(verbose>0) printf("saved %s\n", bfile);
545 tacFree(&btac);
546 }
547
548 /*
549 * If requested, calculate also TTAC or myocardial TAC
550 */
551 if(tfile[0]) {
552 /* Setup place for TTAC */
553 TAC ttac; tacInit(&ttac);
554 int cn=tac.tacNr;
555 tac.tacNr=1;
556 if(tacDuplicate(&tac, &ttac)) {
557 fprintf(stderr, "Error: cannot set up TTAC data.\n");
558 tacFree(&tac); tacFree(&ttac); return(5);
559 }
560 tac.tacNr=cn;
561 if(mode==0) {
562 /* Calculate TTAC */
563 strcpy(ttac.c[0].name, "Tissue");
564 double d=beta*(1.0-fBV)-fBV*(1.0-beta); //if(verbose>2) printf("GGM-divider := %g\n", d);
565 if(!(fabs(d)>1.0E-010)) {
566 fprintf(stderr, "Error: invalid fBV and beta.\n");
567 tacFree(&tac); tacFree(&ttac); return(5);
568 }
569 for(int i=0; i<tac.sampleNr; i++)
570 ttac.c[0].y[i] = (beta*tac.c[iMyoc].y[i] - fBV*tac.c[iCav].y[i]) / d;
571 } else {
572 /* Calculate Myo */
573 strcpy(ttac.c[0].name, "Myo");
574 for(int i=0; i<tac.sampleNr; i++)
575 ttac.c[0].y[i] = fBV*tac.c[iCav].y[i] + (1.0-fBV)*tac.c[iMyoc].y[i];
576 }
577 /* Write file */
578 FILE *fp; fp=fopen(tfile, "w");
579 if(fp==NULL) {
580 fprintf(stderr, "Error: cannot write %s\n", tfile);
581 tacFree(&tac); tacFree(&ttac);
582 return(12);
583 }
584 int ret=tacWrite(&ttac, fp, TAC_FORMAT_UNKNOWN, 0, &status);
585 fclose(fp);
586 if(ret!=TPCERROR_OK) {
587 fprintf(stderr, "Error: %s\n", errorMsg(status.error));
588 tacFree(&tac); tacFree(&ttac);
589 return(12);
590 }
591 if(verbose>0) printf("saved %s\n", tfile);
592 tacFree(&ttac);
593 }
594
595 tacFree(&tac);
596
597 return(0);
598}
599/*****************************************************************************/
600
601/*****************************************************************************
602 *
603 * Functions to be minimized
604 *
605 *****************************************************************************/
606double func_ggm(int parNr, double *p, void *fdata)
607{
608 FITDATA *d=(FITDATA*)fdata;
609
610 if(d->verbose>0) {printf("%s()\n", __func__); fflush(stdout);}
611 if(d->verbose>2) printf("p[]: %g %g\n", p[0], p[1]);
612
613 /* Process parameters */
614 double beta, fBV;
615 beta=p[0];
616 fBV=p[1]*beta;
617
618 /* GGM PVC */
619 double blood[d->nr], logblood[d->nr];
620 double v=beta*(1.0-fBV)-fBV*(1.0-beta); if(d->verbose>3) printf("GGM-divider := %g\n", v);
621 if(!(fabs(v)>1.0E-010)) return(nan(""));
622 for(unsigned int i=0; i<d->nr; i++)
623 blood[i] = ((1.0-fBV)*d->ycav[i] - (1.0-beta)*d->ymyo[i]) / v;
624 /* Line fit to log-transformed BTAC */
625 for(unsigned int i=0; i<d->nr; i++) logblood[i]=log(blood[i]);
626 double m, c;
627 int n=fitLine(d->xr, logblood, d->nr, &m, &c);
628 if(n<2) {
629 if(d->verbose>4) {
630 printf(" fitLine() -> %d\n", n);
631 for(unsigned int i=0; i<d->nr; i++)
632 printf(" %g %g %g\n", d->xr[i], blood[i], logblood[i]);
633 }
634 return(nan(""));
635 }
636 if(d->verbose>3) printf(" fitted line f(x) = %g*x + %g, n=%d\n", m, c, n);
637 /* Calculate SS between blood samples and fitted BTAC */
638 double ss=0.0;
639 n=0;
640 for(unsigned int i=0; i<d->nb; i++) {
641 double b = c + m*d->xb[i];
642 b = exp(b) - d->yb[i];
643 if(isfinite(b)) {ss+=b*b; n++;}
644 }
645 if(n==0) return(nan(""));
646 if(d->verbose>1) {
647 for(int i=0; i<parNr; i++) printf(" %g", p[i]);
648 printf(" -> %g\n", ss);
649 }
650
651 return(ss);
652}
653/*****************************************************************************/
654
655/*****************************************************************************/
656double func_ggm2(int parNr, double *p, void *fdata)
657{
658 FITDATA *d=(FITDATA*)fdata;
659
660 if(d->verbose>0) {printf("%s()\n", __func__); fflush(stdout);}
661
662 /* Process parameters */
663 double beta, fBV;
664 beta=p[0];
665 fBV=p[1]*beta;
666 double A1, A2, A3, L1, L2, L3;
667 A1=p[2]; L1=p[3];
668 A2=p[4]; L2=p[5]*L1;
669 A3=p[6]; L3=p[7]*L2;
670
671 /* GGM PVC */
672 double blood[d->nr];
673 double v=beta*(1.0-fBV)-fBV*(1.0-beta); if(d->verbose>3) printf("GGM-divider := %g\n", v);
674 if(!(fabs(v)>1.0E-010)) return(nan(""));
675 for(unsigned int i=0; i<d->nr; i++)
676 blood[i] = ((1.0-fBV)*d->ycav[i] - (1.0-beta)*d->ymyo[i]) / v;
677 /* SS between Feng function and BTAC */
678 double ss=0.0;
679 for(unsigned int i=0; i<d->nr; i++) {
680 double x=d->xr[i];
681 double f=(A1*x-A2-A3)*exp(L1*x)+A2*exp(L2*x)+A3*exp(L3*x);
682 f-=blood[i];
683 ss+=f*f;
684 }
685 /* Add SS between Feng function and blood sample(s) */
686 for(unsigned int i=0; i<d->nb; i++) {
687 double x=d->xb[i];
688 double f=(A1*x-A2-A3)*exp(L1*x)+A2*exp(L2*x)+A3*exp(L3*x);
689 f-=d->yb[i];
690 ss+=10.0*f*f;
691 }
692 if(d->verbose>1) {
693 for(int i=0; i<parNr; i++) printf(" %g", p[i]);
694 printf(" -> %g\n", ss);
695 }
696
697 return(ss);
698}
699/*****************************************************************************/
700
701/*****************************************************************************/
int atofCheck(const char *s, double *v)
Definition decpoint.c:94
int fileExist(const char *filename)
Definition filexist.c:17
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
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
int fitLine(double *x, double *y, const int n, double *m, double *c)
Definition regression.c:23
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 * xdelta
Definition tpcnlopt.h:36
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
int sampleNr
Definition tpctac.h:89
TACC * c
Definition tpctac.h:117
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
int tacDuplicate(TAC *tac1, TAC *tac2)
Make a duplicate of TAC structure.
Definition tac.c:356
void tacInit(TAC *tac)
Definition tac.c:24
int tacRead(TAC *d, const char *fname, TPCSTATUS *status)
Definition tacio.c:413
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 tacSelectTACs(TAC *d, const char *region_name, int reset, TPCSTATUS *status)
Definition tacselect.c:24
int tacSelectBestReference(TAC *d)
Definition tacselect.c:139
int tacYUnitConvert(TAC *tac, const int u, TPCSTATUS *status)
Definition tacunits.c:72
int tacXUnitConvert(TAC *tac, const int u, TPCSTATUS *status)
Definition tacunits.c:23
int tacExtractRange(TAC *d1, TAC *d2, double startT, double endT)
Extract the specified time (x) range from TAC structure.
Definition tacx.c:486
int tacXRange(TAC *d, double *xmin, double *xmax)
Get the range of x values (times) in TAC structure.
Definition tacx.c:124
int tacYRange(TAC *d, int i, double *ymin, double *ymax, int *smin, int *smax, int *imin, int *imax)
Get the range of y values (concentrations) in TAC struct.
Definition tacy.c:26
int nloptIATGO(NLOPT *nlo, const int doLocal, unsigned int maxIterNr, double neighFract, TPCSTATUS *status)
Definition tgo.c:681
Header file for library libtpcextensions.
#define MAX_TACNAME_LEN
Max length of TAC ID name (not including trailing zero).
@ TPCERROR_INVALID_XRANGE
Invalid sample time range.
@ TPCERROR_FAIL
General error.
@ TPCERROR_OK
No error.
@ TPCERROR_NO_DATA
File contains no data.
Header file for libtpcfileutil.
Header file for library libtpcift.
Header file for libtpcli.
Header file for libtpclinopt.
Header file for library libtpcnlopt.
Header file for libtpcrand.
Header file for library libtpctac.
@ TAC_FORMAT_UNKNOWN
Unknown format.
Definition tpctac.h:28
Header file for libtpctacmod.