TPCCLIB
Loading...
Searching...
No Matches
bf_1tcm.c
Go to the documentation of this file.
1
4/*****************************************************************************/
5#include "tpcclibConfig.h"
6/*****************************************************************************/
7#include <stdio.h>
8#include <stdlib.h>
9#include <math.h>
10#include <time.h>
11#include <string.h>
12/*****************************************************************************/
13#include "tpcextensions.h"
14#include "tpctac.h"
15#include "tpctacmod.h"
16#include "tpccm.h"
17/*****************************************************************************/
18#include "tpcbfm.h"
19/*****************************************************************************/
20
21/*****************************************************************************/
30 TAC *input,
32 TAC *tissue,
34 int bfNr,
37 const double k2min,
39 const double k2max,
41 const int distr,
43 TAC *bf,
45 TPCSTATUS *status
46) {
47 int verbose=0; if(status!=NULL) verbose=status->verbose;
48 if(verbose>0) printf("%s(itac, ttac, %d, %g, %g, %d, bf)\n", __func__, bfNr, k2min, k2max, distr);
49 if(input==NULL || tissue==NULL || bf==NULL) {
50 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_FAIL);
51 return TPCERROR_FAIL;
52 }
53 if(input->sampleNr<1 || input->tacNr<1 || tissue->sampleNr<1) {
54 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_NO_DATA);
55 return TPCERROR_NO_DATA;
56 }
57 if(input->sampleNr<3 || bfNr<2) {
58 if(verbose>1) printf("invalid sample or BF number\n");
59 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_TOO_FEW);
60 return TPCERROR_TOO_FEW;
61 }
62 if(fabs(k2min)<1.0E-10 || fabs(k2min)>=k2max) { // range cannot be computed otherwise
63 if(verbose>1) printf("invalid k2 range\n");
64 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INVALID_VALUE);
66 }
67
68 int ret;
69
70 /* Check units */
71 if(status==NULL || !status->forgiving) {
72 if(!unitIsTime(input->tunit) || input->tunit!=tissue->tunit) {
73 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_UNKNOWN_UNIT);
75 }
76 }
77
78 /* Allocate memory for basis functions */
79 if(verbose>1) printf("allocating memory for basis functions\n");
80 tacFree(bf);
81 ret=tacAllocate(bf, tissue->sampleNr, bfNr);
82 if(ret!=TPCERROR_OK) {
83 statusSet(status, __func__, __FILE__, __LINE__, ret);
84 return ret;
85 }
86 /* Copy and set information fields */
87 bf->tacNr=bfNr; bf->sampleNr=tissue->sampleNr;
89 bf->isframe=tissue->isframe; tacXCopy(tissue, bf, 0, tissue->sampleNr-1);
90 bf->tunit=tissue->tunit; bf->cunit=tissue->cunit;
91 for(int bi=0; bi<bf->tacNr; bi++) sprintf(bf->c[bi].name, "B%5.5d", bi+1);
92 /* Compute the range of k2 values to size fields */
93 if(verbose>1) printf("computing k2 values\n");
94 int zero=0; if(k2min<0.0) {zero=1; bf->c[0].size=0.0;}
95 if(distr==0) { // printf(" log-based distribution\n");
96 double a, b, c;
97 a=log10(fabs(k2min)); b=log10(k2max); c=(b-a)/(double)(bfNr-1-zero);
98 for(int bi=zero; bi<bf->tacNr; bi++) {
99 bf->c[bi].size=pow(10.0, (double)(bi-zero)*c+a);
100 }
101 } else { // printf(" even distribution\n");
102 double c=(k2max-fabs(k2min))/(double)(bfNr-1-zero);
103 for(int bi=zero; bi<bf->tacNr; bi++) {
104 bf->c[bi].size=fabs(k2min)+(double)(bi-zero)*c;
105 }
106 }
107
108
109#if(0) // The replasment works better with image-derived input with long frames
110
111 /* Allocate memory for simulated TAC */
112 double *sim;
113 sim=(double*)malloc(input->sampleNr*sizeof(double));
114 if(sim==NULL) {
115 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_OUT_OF_MEMORY);
117 }
118
119 /* Simulate the basis functions at input time points, and interpolate to tissue sample times */
120 double *cbi=NULL;
121 if(input->isframe!=0) {
122 // Time frames are available:
123 // Integrate BTAC to frame middle times and use it as input */
124 if(verbose>1) printf("using BTAC integral as simulation input\n");
125 cbi=(double*)malloc(input->sampleNr*sizeof(double));
126 if(cbi==NULL) {
127 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_OUT_OF_MEMORY);
128 tacFree(bf); free(sim); return TPCERROR_OUT_OF_MEMORY;
129 }
130 ret=liIntegratePET(input->x1, input->x2, input->c[0].y, input->sampleNr, cbi, NULL, verbose-10);
131 if(ret) {
132 if(verbose>1) printf("liIntegratePET() = %d\n", ret);
133 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INVALID_VALUE);
134 tacFree(bf); free(sim); free(cbi); return TPCERROR_INVALID_VALUE;
135 }
136 }
137 if(verbose>1) printf("computing basis functions\n");
138 ret=0;
139 for(int bi=0; bi<bf->tacNr && !ret; bi++) {
140 if(input->isframe==0) { // time frames not available
141 ret=simC1(input->x, input->c[0].y, input->sampleNr, 1.0, bf->c[bi].size, sim);
142 } else { // time frames are available
143 ret=simC1_i(input->x, cbi, input->sampleNr, 1.0, bf->c[bi].size, sim);
144 }
145 if(ret) break;
146 if(verbose>100) {
147 printf("\nk2 := %g\n", bf->c[bi].size);
148 printf("simulated TAC:\n");
149 for(int i=0; i<input->sampleNr; i++) printf(" %12.6f %12.3f\n", input->x[i], sim[i]);
150 }
151 /* interpolate to PET time frames */
152 if(tissue->isframe)
153 ret=liInterpolateForPET(input->x, sim, input->sampleNr,
154 tissue->x1, tissue->x2, bf->c[bi].y, NULL, NULL, bf->sampleNr, 4, 1, verbose-8);
155 else
156 ret=liInterpolate(input->x, sim, input->sampleNr, tissue->x,
157 bf->c[bi].y, NULL, NULL, bf->sampleNr, 4, 1, verbose-8);
158 if(ret) break;
159 } // next basis function
160 free(sim); free(cbi);
161 if(ret) {
162 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INVALID_VALUE);
164 }
165
166#else
167
168 /* Interpolate the input function to times based on both input and tissue data */
169 /* When input TAC has long frames, the last simulated tissue frame will be biased without this. */
170 TAC inp; tacInit(&inp);
171 tacInput2sim(input, tissue, &inp, status);
172
173 /* Allocate memory for simulated TAC */
174 double *sim;
175 sim=(double*)malloc(inp.sampleNr*sizeof(double));
176 if(sim==NULL) {
177 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_OUT_OF_MEMORY);
179 }
180
181 if(verbose>1) printf("computing basis functions\n");
182 ret=0;
183 for(int bi=0; bi<bf->tacNr && !ret; bi++) {
184 ret=simC1(inp.x, inp.c[0].y, inp.sampleNr, 1.0, bf->c[bi].size, sim);
185 if(ret) break;
186 if(verbose>100) {
187 printf("\nk2 := %g\n", bf->c[bi].size);
188 printf("simulated TAC:\n");
189 for(int i=0; i<inp.sampleNr; i++) printf(" %12.6f %12.3f\n", inp.x[i], sim[i]);
190 }
191 /* interpolate to PET time frames */
192 if(tissue->isframe)
193 ret=liInterpolateForPET(inp.x, sim, inp.sampleNr,
194 tissue->x1, tissue->x2, bf->c[bi].y, NULL, NULL, bf->sampleNr, 4, 1, verbose-8);
195 else
196 ret=liInterpolate(inp.x, sim, inp.sampleNr, tissue->x,
197 bf->c[bi].y, NULL, NULL, bf->sampleNr, 4, 1, verbose-8);
198 if(ret) break;
199 } // next basis function
200 free(sim);
201 if(ret) {
202 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_INVALID_VALUE);
204 }
205
206 tacFree(&inp);
207#endif
208
209
210 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_OK);
211 return(TPCERROR_OK);
212}
213/*****************************************************************************/
214
215/*****************************************************************************/
int bfm1TCM(TAC *input, TAC *tissue, int bfNr, const double k2min, const double k2max, const int distr, TAC *bf, TPCSTATUS *status)
Definition bf_1tcm.c:27
int liIntegratePET(double *x1, double *x2, double *y, int nr, double *ie, double *iie, const int verbose)
Calculate PET TAC AUC from start to each time frame, as averages during each frame.
Definition integrate.c:120
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 liInterpolateForPET(double *x, double *y, const int nr, double *newx1, double *newx2, double *newy, double *newyi, double *newyii, const int newnr, const int se, const int ee, const int verbose)
Linear TAC interpolation and/or integration to PET frames.
int tacInput2sim(TAC *itac, TAC *ttac, TAC *stac, TPCSTATUS *status)
Modify input TAC based on tissue TAC, for use in simulations.
Definition lisim.c:29
int simC1(double *t, double *ca, const int nr, const double k1, const double k2, double *ct)
Definition sim1cm.c:93
int simC1_i(double *t, double *cai, const int nr, const double k1, const double k2, double *ct)
Definition sim1cm.c:164
void statusSet(TPCSTATUS *s, const char *func, const char *srcfile, int srcline, tpcerror error)
Definition statusmsg.c:142
char name[MAX_TACNAME_LEN+1]
Definition tpctac.h:81
double * y
Definition tpctac.h:75
double size
Definition tpctac.h:71
Definition tpctac.h:87
double * x
Definition tpctac.h:97
tacformat format
Definition tpctac.h:93
int sampleNr
Definition tpctac.h:89
int cunit
Definition tpctac.h:105
int isframe
Definition tpctac.h:95
TACC * c
Definition tpctac.h:117
int tunit
Definition tpctac.h:109
double * x2
Definition tpctac.h:101
double * x1
Definition tpctac.h:99
int tacNr
Definition tpctac.h:91
int verbose
Verbose level, used by statusPrint() etc.
int forgiving
Force level, 0 for strict tests for data units etc.
void tacFree(TAC *tac)
Definition tac.c:106
int tacAllocate(TAC *tac, int sampleNr, int tacNr)
Definition tac.c:130
void tacInit(TAC *tac)
Definition tac.c:24
int tacXCopy(TAC *tac1, TAC *tac2, int i1, int i2)
Definition tacx.c:24
Header file for libtpcbfm.
Header file for libtpccm.
Header file for library libtpcextensions.
@ TPCERROR_INVALID_VALUE
Invalid value.
@ TPCERROR_UNKNOWN_UNIT
Unknown data unit.
@ TPCERROR_FAIL
General error.
@ TPCERROR_OUT_OF_MEMORY
Cannot allocate memory.
@ TPCERROR_OK
No error.
@ TPCERROR_NO_DATA
File contains no data.
@ TPCERROR_TOO_FEW
File contains too few samples.
int unitIsTime(int u)
Definition units.c:359
Header file for library libtpctac.
@ TAC_FORMAT_TSV_UK
UK TSV (point as decimal separator)
Definition tpctac.h:37
Header file for libtpctacmod.