TPCCLIB
Loading...
Searching...
No Matches
bootstrap.c File Reference

Procedure for counting the confidence intervals and standard deviations for estimates of parameters of compartmental PET models. More...

#include "libtpcmodel.h"

Go to the source code of this file.

Functions

int bootstrap (int iterNr, double *cLim1, double *cLim2, double *SD, double *parameter, double *lowlim, double *uplim, int frameNr, double *origTac, double *fitTac, double *bsTac, int parNr, double *weight, double(*objf)(int, double *, void *), char *status, int verbose)
 

Detailed Description

Procedure for counting the confidence intervals and standard deviations for estimates of parameters of compartmental PET models.

Author
Kaisa Sederholm, Vesa Oikonen

This method is based on the article "Estimation of component and parametric distributions in spectral analysis" by Turkheimer, Sokoloff, Bertoldo, Lucignani, Reivich, Jaggi and Schmidt in J Cereb Blood Flow Metabol. 1998; 18:1211-1222. Standard deviation calculation is based on the book "An introduction to bootstrap" by Efron & Tibshirani, 1993, Chapman & Hall, New York.

Todo
Enable optionally to use bobyqa instead of powell.
Test
Test with weights.

Definition in file bootstrap.c.

Function Documentation

◆ bootstrap()

int bootstrap ( int iterNr,
double * cLim1,
double * cLim2,
double * SD,
double * parameter,
double * lowlim,
double * uplim,
int frameNr,
double * origTac,
double * fitTac,
double * bsTac,
int parNr,
double * weight,
double(* objf )(int, double *, void *),
char * status,
int verbose )

Bootstrap method.

Original weights are assumed to be inversely proportional to variance. Square root is used, because bootstrap assumes them to be proportional to standard deviation. If only standard deviation is needed then cLim1 and cLim2 can be set to be NULL, and if only the confidence limits are wanted then SD can be set to be NULL. This function will not set seed for random number generator, therefore, make sure that it is set in your program, for example with srand(time(NULL));.

Returns
Return values:
  • 0, if ok.
  • 1 - 3 if some of the given parameters is not qualified.
  • 4, if Powell fails, and 5, if out of memory.
Parameters
iterNrBootstrap iteration number (>=100), set to zero to use the default (200).
cLim1Vector to put the lower confidence limits to; NULL if not needed.
cLim2Vector to put the upper confidence limits to; NULL if not needed.
SDVector to put the standard deviations to; NULL if not needed.
parameterBest parameter estimates (preserved by this function).
lowlimLower limits for the parameters.
uplimUpper limits for the parameters.
frameNrNr of samples in tissue TAC data.
origTacMeasured tissue TAC values (not modified; local copy is used).
fitTacBest fitted tissue TAC values (not modified; local copy is used).
bsTacPointer to (empty) tissue TAC vector, where bootstrapped TACs will be written in each bootstrap iteration, and which will be used by objective function to calculate WSS.
parNrNr of parameters.
weightsample weights.
objfThe object function.
statusPointer to a string (allocated for at least 64 chars) where error message or other execution status will be written; enter NULL, if not needed.
verboseVerbose level; if zero, then nothing is printed to stderr or stdout.

Definition at line 55 of file bootstrap.c.

90 {
91
92 int ret, i, j, powellItNr, lowindex, upindex;
93 double fret=0.0, *parMean, *chainptr, *chain, **matrix, *delta, *bsFitTac;
94 double help, *error, *wError, *biasEst, *unbiasPar, *estInOrder;
95 char bserrmsg[64];
96
97 if(verbose>0)
98 printf("%s(%d, ..., %d, ..., %d, ..., %d)\n", __func__, iterNr, frameNr, parNr, verbose);
99
100 /* Checking the given parameters */
101 if(status!=0) strcpy(status, "");
102 if(iterNr<100) iterNr=200;
103 if(frameNr<1 || parNr<1 ) {
104 strcpy(bserrmsg, "either framenumber or parameternumber is negative");
105 if(verbose>0) fprintf(stderr, "Error: %s.\n", bserrmsg);
106 if(status!=0) strcpy(status, bserrmsg);
107 return(1);
108 }
109 if(bsTac==NULL || parameter==NULL || objf==NULL || origTac==NULL ||
110 fitTac==NULL)
111 {
112 strcpy(bserrmsg, "some of the given parameters are not pointing anywhere");
113 if(verbose>0) fprintf(stderr, "Error: %s.\n", bserrmsg);
114 if(status!=0) strcpy(status, bserrmsg);
115 return(2);
116 }
117 for(i=0; i<parNr; i++) {
118 if(lowlim[i]>uplim[i]) {
119 strcpy(bserrmsg, "given limit values are not qualified");
120 if(verbose>0) fprintf(stderr, "Error: %s.\n", bserrmsg);
121 if(status!=0) strcpy(status, bserrmsg);
122 return(3);
123 }
124 }
125
126 /* Allocating memory */
127 if(verbose>1) printf(" allocating memory\n");
128 bsFitTac=(double*)malloc(frameNr*sizeof(double));
129 bs_parameter=(double*)malloc(parNr*sizeof(double));
130 bs_weight=(double*)malloc(frameNr*sizeof(double));
131 delta=(double*)malloc(parNr*sizeof(double));
132 parMean=(double*)malloc(parNr*sizeof(double));
133 chain=(double*)malloc((iterNr*parNr)*sizeof(double));
134 matrix=(double**)malloc(parNr*sizeof(double*));
135 error=(double*)malloc(frameNr*sizeof(double));
136 wError=(double*)malloc(frameNr*sizeof(double));
137 biasEst=(double*)malloc(parNr*sizeof(double));
138 unbiasPar=(double*)malloc(parNr*sizeof(double));
139 if(bsFitTac==NULL || bs_parameter==NULL || bs_weight==NULL || delta==NULL ||
140 parMean==NULL || chain==NULL || matrix==NULL || error==NULL ||
141 wError==NULL || biasEst==NULL || unbiasPar==NULL) {
142 strcpy(bserrmsg, "out of memory");
143 if(verbose>0) fprintf(stderr, "Error: %s.\n", bserrmsg);
144 if(status!=0) strcpy(status, bserrmsg);
145 return(5);
146 }
147 for(i=0, chainptr=chain; i<parNr; i++) {
148 matrix[i]=(chainptr + i*iterNr);
149 }
150
151 bs_parNr=parNr;
152 bs_frameNr=frameNr;
153 bs_func=objf;
154 bs_lowlim=lowlim;
155 bs_uplim=uplim;
156 for(i=0; i<bs_parNr; i++) {
157 bs_parameter[i]=parameter[i];
158 }
159
160 /* copy data and check the weights */
161 /* calculate the errors and weighted errors */
162 if(verbose>2) printf(" calculating errors and weighted errors");
163 for(i=0; i<bs_frameNr; i++) {
164 bsFitTac[i]=fitTac[i];
165 if(weight[i]<=0.0) bs_weight[i]=1; else bs_weight[i]=weight[i];
166 error[i]=origTac[i]-bsFitTac[i];
167 wError[i]=error[i]/sqrt(bs_weight[i]);
168 }
169 if(verbose>3) {
170 printf(" weighted errors:\n ");
171 for(i=0; i<bs_frameNr; i++) printf("%g ", wError[i]);
172 printf("\n");
173 }
174
175 /*
176 * bootstrap iterations
177 */
178 if(verbose>1) printf(" bootstrap iterations\n");
179 if(verbose>4) printf("Bootstrap matrix:\n");
180 int powellfailNr=0;
181
182 for(i=0; i<iterNr; i++) {
183
184 /* sample a new error distribution (to the pointer error) */
185 for(j=0; j<bs_frameNr; j++) {
186 error[j]=wError[(int)((bs_frameNr)*(double)rand()/((double)(RAND_MAX)+1))];
187 bsTac[j]=bsFitTac[j]+bs_weight[j]*error[j];
188 }
189
190 /* Powell local search */
191 for(j=0; j<bs_parNr; j++) {
192 delta[j]=0.01*(bs_uplim[j]-bs_lowlim[j]);
193 bs_parameter[j]=parameter[j];
194 }
195 powellItNr=400;
196 ret=powell(bs_parameter, delta, bs_parNr, 0.00001, &powellItNr, &fret, bs_func, NULL, 0);
197 if(ret>1 && ret!=3) {
198 sprintf(bserrmsg, "error %d in powell()", ret);
199 if(verbose>0) fprintf(stderr, "Error: %s.\n", bserrmsg);
200 if(status!=0) strcpy(status, bserrmsg);
201 free(bsFitTac);
202 free(bs_parameter);
203 free(bs_weight);
204 free(delta);
205 free(parMean);
206 free(matrix);
207 free(chain);
208 free(error);
209 free(wError);
210 free(biasEst);
211 free(unbiasPar);
212 return(4);
213 }
214 if(ret==3) { // powell sometimes fails, do not worry if not too often
215 powellfailNr++;
216 }
217
218 for(j=0; j<bs_parNr; j++) {
219 matrix[j][i]=bs_parameter[j];
220 }
221 if(verbose>4) {
222 for(j=0; j<bs_parNr; j++) printf("%g ", bs_parameter[j]);
223 printf("\n");
224 }
225
226 } /* end of bootstrap iterations */
227 if(powellfailNr>(iterNr/3)) {
228 sprintf(bserrmsg, "error %d in powell()", ret);
229 if(verbose>0) fprintf(stderr, "Error: too often %s.\n", bserrmsg);
230 if(status!=0) strcpy(status, bserrmsg);
231 free(bsFitTac);
232 free(bs_parameter);
233 free(bs_weight);
234 free(delta);
235 free(parMean);
236 free(matrix);
237 free(chain);
238 free(error);
239 free(wError);
240 free(biasEst);
241 free(unbiasPar);
242 return(4);
243 }
244
245 /* Computing the mean of each parameter and estimates for bias */
246 if(verbose>1) printf(" computing parameter bias\n");
247 for(i=0; i<bs_parNr; i++) {
248 for(j=0, help=0.0; j<iterNr; j++) help+=matrix[i][j];
249 parMean[i]=help/(double)iterNr;
250 biasEst[i]=parMean[i]-parameter[i];
251 /*unbiasPar[i]=parameter[i]-biasEst[i];*/
252 if(verbose>1) {
253 printf("parMean[%d] := %g\n", i, parMean[i]);
254 printf("parameter[%d] := %g\n", i, parameter[i]);
255 printf("biasEst[%d] := %g\n", i, biasEst[i]);
256 }
257 }
258
259 /* Computing the standard deviation for each parameter estimate */
260 if(SD!=NULL) {
261 if(verbose>1) printf("Standard deviations:\n");
262 for(i=0; i<bs_parNr; i++) {
263 for(j=0, help=0; j<iterNr; j++) {
264 help+=(matrix[i][j]-parMean[i])*(matrix[i][j]-parMean[i])/(iterNr-1);
265 }
266 SD[i]=sqrt(help); if(verbose>1) printf(" %g\n", SD[i]);
267 }
268 }
269
270 if(cLim1!=NULL && cLim2!=NULL) {
271 if(verbose>1) printf("Confidence intervals:\n");
272 lowindex=(int)temp_roundf(0.025*iterNr);
273 upindex=(int)temp_roundf(0.975*iterNr)-1;
274 /* Computing the 95% confidence intervals for each parameter estimate */
275 for(i=0; i<bs_parNr; i++) {
276
277 /* Arrange estimate samples in ascending order */
278 estInOrder=matrix[i];
279 qsort(estInOrder, iterNr, sizeof(double), bootstrapQSort);
280
281 /* Get the indices within which 95% of samples lie in */
282 if(fabs(estInOrder[lowindex]-biasEst[i])<1e-99) cLim1[i]=0.0;
283 else cLim1[i]=estInOrder[lowindex]-biasEst[i];
284 if(fabs(estInOrder[upindex]-biasEst[i])<1e-99) cLim2[i]=0.0;
285 else cLim2[i]=estInOrder[upindex]-biasEst[i];
286 if(verbose>1) {
287 printf(" %g - %g\n", cLim1[i], cLim2[i]);
288 }
289 }
290 if(verbose>6) {
291 printf("Sorted matrix\n");
292 for(j=0; j<iterNr; j++) {
293 for(i=0; i<bs_parNr; i++) printf(" %12.3e", matrix[i][j]);
294 printf("\n");
295 }
296 printf("lowindex := %d\nupindex := %d\n", lowindex, upindex);
297 }
298 }
299
300 free(bsFitTac);
301 free(bs_parameter);
302 free(bs_weight);
303 free(delta);
304 free(parMean);
305 free(matrix);
306 free(chain);
307 free(error);
308 free(wError);
309 free(biasEst);
310 free(unbiasPar);
311
312 if(verbose>0) {printf(" end of bootstrap()\n");}
313 return(0);
314
315} /* end bootstrap() */
#define RAND_MAX
Definition gaussdev.c:13
int temp_roundf(float e)
Definition petc99.c:20
int powell(double *p, double *delta, int parNr, double ftol, int *iterNr, double *fret, double(*_fun)(int, double *, void *), void *fundata, int verbose)
Definition powell.c:43