Read transmission scan file and blank scan file and calculate the attenuation correction data and the logarithmic correction data.
125 {
126 int i, j, k, ret;
127 char buf[512];
128
129
130 if(status!=NULL) sprintf(status, "invalid filename");
131 if(imgName==NULL || !imgName[0]) return(1);
132 if(status!=NULL) sprintf(status, "invalid efficient plane settings");
133 if(firstplane<1 || firstplane>lastplane) return(2);
134 if(status!=NULL) sprintf(status, "invalid mean plane settings");
135 if(startplane<1 || startplane>endplane) return(3);
136 if(status!=NULL) sprintf(status, "invalid activity concentration");
137
138
139
140
141 char hdrFile[FILENAME_MAX];
142 char imgFile[FILENAME_MAX];
143 strlcpy(imgFile, imgName, FILENAME_MAX);
144 strlcpy(hdrFile, imgName, FILENAME_MAX-4);
145 strcat(hdrFile, ".hdr");
146 if(verbose>2) printf("reading header in %s\n", hdrFile);
148 ret=
iftRead(&ift, hdrFile, 0, 0);
149
150 if(ret!=0) {
151 strlcpy(hdrFile, imgName, FILENAME_MAX-4);
152 strcat(hdrFile, ".i.hdr");
153 if(verbose>2) printf("reading header in %s\n", hdrFile);
154 ret=
iftRead(&ift, hdrFile, 0, 0);
155 if(ret==0) {
156
157 strlcpy(imgFile, imgName, FILENAME_MAX);
158 strcat(imgFile, ".i");
159 }
160 }
161
162 if(ret!=0) {
163 if(status!=NULL) sprintf(status, "cannot read file");
164 return(11);
165 }
166
167
168 int dimx, dimy, dimz;
169 if(
iftGetIntValue(&ift, 0,
"matrix size [1]", &dimx, 0)<0 || dimx<1) {
170 if(status!=NULL) sprintf(status, "cannot read dimx");
172 }
173 if(
iftGetIntValue(&ift, 0,
"matrix size [2]", &dimy, 0)<0 || dimy<1) {
174 if(status!=NULL) sprintf(status, "cannot read dimy");
176 }
177 if(
iftGetIntValue(&ift, 0,
"matrix size [3]", &dimz, 0)<0 || dimz<1) {
178 if(status!=NULL) sprintf(status, "cannot read dimz");
180 }
181 if(verbose>1) printf(" matrix_size := %d x %d x %d\n", dimx, dimy, dimz);
182
183 if(lastplane>dimz) {
184 if(status!=NULL) sprintf(status, "invalid efficient plane settings");
186 }
187 if(endplane>dimz) {
188 if(status!=NULL) sprintf(status, "invalid mean plane settings");
190 }
191 if(verbose>0) {
192 printf(" Efficient factor set to 0 for %d first planes\n", firstplane-1);
193 printf(" Efficient factor set to 0 for %d last planes\n", dimz-lastplane);
194 printf(" Excluding %d first planes from the mean calculation\n", startplane-1);
195 printf(" Excluding %d last planes from the mean calculation\n", dimz-endplane-1);
196 }
197
198
199 double xsize, ysize, zsize;
200 if(
iftGetDoubleValue(&ift, 0,
"scaling factor (mm/pixel) [1]", &xsize, 0)<0 || xsize<=0.0) {
201 if(status!=NULL) sprintf(status, "cannot read x size");
203 }
204 if(
iftGetDoubleValue(&ift, 0,
"scaling factor (mm/pixel) [2]", &ysize, 0)<0 || ysize<=0.0) {
205 if(status!=NULL) sprintf(status, "cannot read y size");
207 }
208 if(
iftGetDoubleValue(&ift, 0,
"scaling factor (mm/pixel) [3]", &zsize, 0)<0 || zsize<=0.0) {
209 if(status!=NULL) sprintf(status, "cannot read z size");
211 }
212 if(verbose>1) printf(" pixel_size := %g x %g x %g\n", xsize, ysize, zsize);
213 if(fabs(xsize-ysize)>0.01) {
214 if(status!=NULL) sprintf(status, "invalid x and y pixel sizes");
216 }
217
218 float ROIradius;
219 ROIradius=75.0/xsize;
220 if(verbose>0) printf(" ROIradius := %g\n", ROIradius);
221
222
223 double scanDuration;
224 if(
iftGetDoubleValue(&ift, 0,
"image duration", &scanDuration, 0)<0 || scanDuration<=0.0) {
225 if(status!=NULL) sprintf(status, "cannot read scan duration");
227 }
228 if(verbose>1) printf(" scanDuration := %g\n", scanDuration);
229
230
233 if(status!=NULL) sprintf(status, "cannot read branching fraction");
235 }
237
238
239 double halflife;
240 if(
iftGetDoubleValue(&ift, 0,
"isotope halflife", &halflife, 0)<0 || halflife<=0.0) {
241 if(status!=NULL) sprintf(status, "cannot read halflife");
243 }
244 if(verbose>1) printf(" halflife := %g\n", halflife);
245
246
247 double deadtimeCorFactor;
248 if(
iftGetDoubleValue(&ift, 0,
"Dead time correction factor", &deadtimeCorFactor, 0)<0
249 || deadtimeCorFactor<=0.0) {
250 if(status!=NULL) sprintf(status, "cannot read dead time");
252 }
253 if(verbose>1) printf(" deadtimeCorFactor := %g\n", deadtimeCorFactor);
254
255
256 int span;
258 if(status!=NULL) sprintf(status, "cannot read span");
260 }
261 if(verbose>1) printf(" span := %d\n", span);
262
263
264 char recMethod[256];
265 i=
iftGetFrom(&ift, 0,
"method of reconstruction used", 0);
266 if(i<0) i=
iftGetFrom(&ift, 0,
"reconstruction method", 0);
267 if(i<0) {
268 if(status!=NULL) sprintf(status, "cannot read reconstruction method");
270 }
272 for(i=j=0; i<(int)strlen(buf); i++) {
273 if(buf[i]!='/' && buf[i]!=' ') recMethod[j++]=buf[i];
274 }
275 recMethod[j]=(char)0;
276 if(verbose>1) printf(" reconstruction method := %s\n", recMethod);
277
278
279 int numIter;
280 if(
iftGetIntValue(&ift, 0,
"number of iterations", &numIter, 0)<0) {
281 numIter=0;
282 }
283 if(verbose>1) printf(" numIter := %d\n", numIter);
284
285
286 int numSubsets;
287 if(
iftGetIntValue(&ift, 0,
"number of subsets", &numSubsets, 0)<0) {
288 numSubsets=0;
289 }
290 if(verbose>1) printf(" numSubsets := %d\n", numSubsets);
291
292
294 if(i<0 || strcasecmp(ift.
item[i].
value,
"float")!=0) {
295 if(status!=NULL) sprintf(status, "data is not stored as floats");
297 }
298 i=
iftGetFrom(&ift, 0,
"number of bytes per pixel", 0);
299 if(i<0 || strcasecmp(ift.
item[i].
value,
"4")!=0) {
300 if(status!=NULL) sprintf(status, "data is not stored as 4-byte floats");
302 }
303
304
306
307
308
309
310
311 if(verbose>2) printf("reading image data in %s\n", imgFile);
312 float *img;
313 unsigned int pxlNr, n;
314 pxlNr=dimx*dimy*dimz;
315 img=(float*)malloc(pxlNr*sizeof(float));
316 if(img==NULL) {
317 if(status!=NULL) sprintf(status, "out of memory");
318 return(100);
319 }
320 FILE *fp;
321 fp=fopen(imgFile, "rb");
322 if(fp==NULL) {
323 if(status!=NULL) sprintf(status, "cannot open image file");
324 free(img); return(101);
325 }
326 n=fread(img, sizeof(float), pxlNr, fp);
327 fclose(fp);
328 if(n<pxlNr) {
329 if(status!=NULL) sprintf(status, "cannot read image");
330 free(img); return(102);
331 }
332
334 if(verbose>1) printf(" swapping bytes\n");
335 for(n=0; n<pxlNr; n++)
swawbip(&img[n],
sizeof(
float));
336 }
337
338
339
340
341 if(verbose>2) printf("ROI evaluation (circular, centered, 15 cm diameter)\n");
342 int numpix=0, planenumpix, x, y, z;
343 double sqrSum=0.0;
344 double VoISTDV=0.0;
345 float ROIsum=0.0, ROIavg;
346 float planesum, xsum, ysum, x0, y0;
347 float planeROIavg[dimz], planeROIsum;
348 for(i=0; i<dimz; i++) planeROIavg[i]=0.0;
349 j=k=0;
350
351 for(z=0; z<dimz; z++) {
352 planesum=xsum=ysum=0.0;
353
354 for(y=0; y<dimy; y++) {
355 for(x=0; x<dimx; x++) {
356 planesum+=img[j];
357 xsum+=(float)x*img[j];
358 ysum+=(float)y*img[j];
359 j++;
360 }
361 }
362 x0=xsum/planesum;
363 y0=ysum/planesum;
364 if(!isnormal(x0) || (int)x0<=0 || (int)x0>=dimx) x0=0.5*dimx;
365 if(!isnormal(y0) || (int)y0<=0 || (int)y0>=dimy) y0=0.5*dimy;
366 if(verbose>3) printf(" ROIcenter[%d] = (%f/%f)\n", z, x0, y0);
367 planeROIsum=0.0;
368 planenumpix=0;
369 for(y=0; y<dimy; y++) {
370 for(x=0; x<dimx; x++) {
371 if(hypotf((float)x-x0, (float)y-y0) <= ROIradius) {
372 planenumpix++;
373 planeROIsum+=img[k];
374 if((z+1)>=startplane && (z+1)<=endplane) {
375
376 numpix++;
377 ROIsum+=img[k];
378 }
379 }
380 k++;
381 }
382 }
383 planeROIavg[z]=planeROIsum/(float)planenumpix;
384 if(verbose>0) printf(" VOIaverage[%d] := %g\n", z, planeROIavg[z]);
385 }
386 ROIavg=ROIsum/(float)numpix;
387 if(verbose>2) printf(" ROIavg := %g\n", ROIavg);
388
389
390 if(calcSTDV!=0) {
391 j=k=dimx*dimy*(startplane-1);
392 for(z=startplane; z<endplane; z++) {
393 planesum=xsum=ysum=0.0;
394
395 for(y=0; y<dimy; y++) {
396 for(x=0; x<dimx; x++) {
397 planesum+=img[j];
398 xsum+=(float)x*img[j];
399 ysum+=(float)y*img[j];
400 j++;
401 }
402 }
403 x0=xsum/planesum;
404 y0=ysum/planesum;
405 for(y=0; y<dimy; y++) {
406 for(x=0; x<dimx; x++) {
407 if(hypotf((float)x-x0, (float)y-y0) <= ROIradius) {
408 sqrSum+=(img[k]-ROIavg)*(img[k]-ROIavg);
409 }
410 k++;
411 }
412 }
413 }
414 VoISTDV=sqrt(sqrSum/(double)numpix);
415 if(verbose>2) {
416 fprintf(stdout, " standard deviation in VoI := %f\n", VoISTDV);
417 fflush(stdout);
418 }
419 }
420
421 free(img);
422
423
424
425
426
427 if(verbose>2) printf("Calculating calibration factor\n");
428
429 double corROIavg=ROIavg/scanDuration;
430
432
433 double dfrac=scanDuration/halflife*log(2);
434 dfrac/=(1.0-exp(-dfrac));
435 if(verbose>0) printf(" decay correction := %f\n", dfrac);
436 corROIavg*=dfrac;
437
438 corROIavg*=deadtimeCorFactor;
439
440 float calibFactor=activityConcentration/corROIavg;
441 if(verbose>2) {
442 fprintf(stdout, " calibration factor := %e (counts/s)/(Bq/ml)\n",
443 calibFactor);
444 fflush(stdout);
445 }
446
447
448
449
450 if(verbose>2) printf("Writing output file\n");
451
452 char *cptr, calHdrName[512];
454 if((cptr=strpbrk(buf, "_-. "))!=NULL) *cptr='\0';
455 strcpy(calHdrName, buf);
456 strlcat(calHdrName,
"_", 512);
strlcat(calHdrName, recMethod, 512);
457 if(numIter>0) {
458 sprintf(buf,
"_i%02d", numIter);
strlcat(calHdrName, buf, 512);
459 } else {
460 strlcat(calHdrName,
"_i0", 512);
461 }
462 sprintf(buf,
"s%d", numSubsets);
strlcat(calHdrName, buf, 512);
463 sprintf(buf,
"_s%d", span);
strlcat(calHdrName, buf, 512);
464 if(dimx!=256) {sprintf(buf,
"_m%d", dimx);
strlcat(calHdrName, buf, 512);}
465 strlcat(calHdrName,
".cal.hdr", 512);
466
467 ret=
iftPut(&ift, NULL, imgName,
";", 0);
468 if(ret==0)
469 ret=
iftPutDouble(&ift,
"activity concentration used (Bq/ml)",
470 (double)activityConcentration, ";", 0);
471 if(ret==0) {
472 sprintf(buf, "VOI mean from planes %d - %d", startplane, endplane);
473 ret=
iftPut(&ift, NULL, buf,
";", 0);
474 }
475 if(ret==0) ret=
iftPutDouble(&ift,
"mean activity concentration in VOI", (
double)ROIavg,
";", 0);
476 if(calcSTDV!=0) {
477 if(ret==0) ret=
iftPutDouble(&ift,
"standard deviation in VOI", (
double)VoISTDV,
";", 0);
478 if(ret==0) ret=
iftPutDouble(&ift,
"CV in VOI", (
double)VoISTDV/ROIavg,
";", 0);
479 }
480 if(ret==0)
481 ret=
iftPutDouble(&ift,
"corrected VOI activity concentration", (
double)corROIavg,
";", 0);
482 if(ret==0) ret=
iftPut(&ift, NULL,
" ", NULL, 0);
483 if(ret==0) ret=
iftPut(&ift, NULL,
"calibration factor in (Bq/cc)/(counts/s)",
";", 0);
484 if(ret==0) ret=
iftPutDouble(&ift,
"calibration factor", (
double)calibFactor, NULL, 0);
485 if(ret==0) ret=
iftPut(&ift, NULL,
" ", NULL, 0);
486 for(j=1; j<=dimz && ret==0; j++) {
487 sprintf(buf, "efficient factor for plane %d", j-1);
488 if(j<firstplane || j>lastplane)
490 else
491 ret=
iftPutDouble(&ift, buf, ROIavg/planeROIavg[j-1], NULL, 0);
492 }
493 if(ret!=0) {
494 if(status!=NULL) sprintf(status, "cannot make calibration file");
496 }
497 if(verbose>0) {
498 printf("\n--------------------------------------------------\n");
499 printf("%s :\n", calHdrName);
500 printf("--------------------------------------------------\n");
502 }
503
506 if(ret!=0) {
507 if(status!=NULL) sprintf(status, "cannot write calibration file");
508 return(202);
509 }
510 fprintf(stdout, "\ncalibrations written in %s\n\n", calHdrName);
511 fflush(stdout);
512
513 return(0);
514}
float branchingFraction(int isotope)
int iftPutDouble(IFT *ift, char *key, double value, char *cmt_type, int verbose)
int iftPut(IFT *ift, char *key, char *value, char *cmt_type, int verbose)
int iftRead(IFT *ift, char *filename, int is_key_required, int verbose)
int iftWrite(IFT *ift, char *filename, int verbose)
int iftGetDoubleValue(IFT *ift, int si, const char *key, double *value, int verbose)
int iftGetIntValue(IFT *ift, int si, const char *key, int *value, int verbose)
int iftGetFrom(IFT *ift, int si, const char *key, int verbose)
void swawbip(void *buf, long long int size)
size_t strlcpy(char *dst, const char *src, size_t dstsize)
size_t strlcat(char *dst, const char *src, size_t dstsize)