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

Calculation of quantification headers for the HRRT. More...

Go to the source code of this file.

Functions

int hrrtMakeCalHdr (char *imgName, int firstplane, int lastplane, int startplane, int endplane, float activityConcentration, int calcSTDV, char *status, int verbose)

Detailed Description

Calculation of quantification headers for the HRRT.

Calculates calibration factor counts/s -> Bq/ml and slice sensitivity coefficients.

The procedure is as follows:

  1. get mean value of a circular ROI centered on a HRRT interfile image of a cylindric phantom (for all 207 planes)
  2. calculate the average of plane 19-189
  3. normalise for duration of acquisition (get duration from header)
  4. devide by branching factor (get factor from header)
  5. apply in-frame decay correction
  6. apply deadtime correction (factor from header)
  7. get activity concentration in the phantom from command line
  8. calculate calibration factor ((Bq/ml)/(counts/s))
  9. calculate slice sensitivity coeficients
  10. generate output file name according to reconstruction parameters
  11. create slice sensitivity file and write output to it.
Author
Roman Krais, Jarkko Johansson, Timo Laitinen, Vesa Oikonen

Definition in file mkcalhdr.c.

Function Documentation

◆ hrrtMakeCalHdr()

int hrrtMakeCalHdr ( char * imgName,
int firstplane,
int lastplane,
int startplane,
int endplane,
float activityConcentration,
int calcSTDV,
char * status,
int verbose )

Read transmission scan file and blank scan file and calculate the attenuation correction data and the logarithmic correction data.

Returns
Returns 0 if ok.
Parameters
imgNamePointer to Interfile name, with or without .i extension.
firstplaneFirst plane for which the efficient factor is set.
lastplaneLast plane for which the efficient factor is set.
startplaneFirst plane used for mean calculation.
endplaneLast plane used for mean calculation.
activityConcentrationActivity concentration at scan start time in Bq/mL.
calcSTDVCalculate (<>0) or do not calculate (0) SD.
statusPointer to a string (allocated for at least 128 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 105 of file mkcalhdr.c.

125 {
126 int i, j, k, ret;
127 char buf[512];
128
129 /* Check the input */
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 * Read Interfile header
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);
147 IFT ift; iftInit(&ift);
148 ret=iftRead(&ift, hdrFile, 0, 0);
149 /* If error, try to add .i to filenames */
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 /* That was good, therefore fix image filename too */
157 strlcpy(imgFile, imgName, FILENAME_MAX);
158 strcat(imgFile, ".i");
159 }
160 }
161 /* In case of error, stop trying */
162 if(ret!=0) {
163 if(status!=NULL) sprintf(status, "cannot read file");
164 return(11);
165 }
166
167 /* Matrix size */
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");
171 iftEmpty(&ift); return(21);
172 }
173 if(iftGetIntValue(&ift, 0, "matrix size [2]", &dimy, 0)<0 || dimy<1) {
174 if(status!=NULL) sprintf(status, "cannot read dimy");
175 iftEmpty(&ift); return(22);
176 }
177 if(iftGetIntValue(&ift, 0, "matrix size [3]", &dimz, 0)<0 || dimz<1) {
178 if(status!=NULL) sprintf(status, "cannot read dimz");
179 iftEmpty(&ift); return(23);
180 }
181 if(verbose>1) printf(" matrix_size := %d x %d x %d\n", dimx, dimy, dimz);
182 /* Check plane limits against dimz */
183 if(lastplane>dimz) {
184 if(status!=NULL) sprintf(status, "invalid efficient plane settings");
185 iftEmpty(&ift); return(24);
186 }
187 if(endplane>dimz) {
188 if(status!=NULL) sprintf(status, "invalid mean plane settings");
189 iftEmpty(&ift); return(25);
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 /* Pixel size */
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");
202 iftEmpty(&ift); return(31);
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");
206 iftEmpty(&ift); return(32);
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");
210 iftEmpty(&ift); return(33);
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");
215 iftEmpty(&ift); return(34);
216 }
217 /* Calculate ROI radius in pixels */
218 float ROIradius;
219 ROIradius=75.0/xsize; /* 15 cm diameter ROI = 75 mm Radius */
220 if(verbose>0) printf(" ROIradius := %g\n", ROIradius);
221
222 /* Scan duration */
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");
226 iftEmpty(&ift); return(41);
227 }
228 if(verbose>1) printf(" scanDuration := %g\n", scanDuration);
229
230 /* Branching fraction */
231 double branchingFraction;
232 if(iftGetDoubleValue(&ift, 0, "branching factor", &branchingFraction, 0)<0 || branchingFraction<=0.0) {
233 if(status!=NULL) sprintf(status, "cannot read branching fraction");
234 iftEmpty(&ift); return(42);
235 }
236 if(verbose>1) printf(" branchingFraction := %g\n", branchingFraction);
237
238 /* Halflife */
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");
242 iftEmpty(&ift); return(43);
243 }
244 if(verbose>1) printf(" halflife := %g\n", halflife);
245
246 /* Dead time */
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");
251 iftEmpty(&ift); return(44);
252 }
253 if(verbose>1) printf(" deadtimeCorFactor := %g\n", deadtimeCorFactor);
254
255 /* Span */
256 int span;
257 if(iftGetIntValue(&ift, 0, "axial compression", &span, 0)<0) {
258 if(status!=NULL) sprintf(status, "cannot read span");
259 iftEmpty(&ift); return(45);
260 }
261 if(verbose>1) printf(" span := %d\n", span);
262
263 /* Reconstruction method */
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");
269 iftEmpty(&ift); return(46);
270 }
271 strlcpy(buf, ift.item[i].value, 256);
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 /* Nr of iterations (not always present) */
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 /* Nr of subsets (not always present) */
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 /* Check that image data is saved as 4-byte floats */
293 i=iftGetFrom(&ift, 0, "number format", 0);
294 if(i<0 || strcasecmp(ift.item[i].value, "float")!=0) {
295 if(status!=NULL) sprintf(status, "data is not stored as floats");
296 iftEmpty(&ift); return(51);
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");
301 iftEmpty(&ift); return(52);
302 }
303
304 /* free header data */
305 iftEmpty(&ift);
306
307
308 /*
309 * Read Interfile image data
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 /* Swap bytes if necessary */
333 if(little_endian()==0) {
334 if(verbose>1) printf(" swapping bytes\n");
335 for(n=0; n<pxlNr; n++) swawbip(&img[n], sizeof(float));
336 }
337
338 /*
339 * ROI evaluation
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; //dimx*dimy*(startplane-1);
350 //for(z=startplane-1; z<endplane; z++) {
351 for(z=0; z<dimz; z++) {
352 planesum=xsum=ysum=0.0;
353 /* centre of gravity */
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 /* Only these are included in the VOI mean */
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 /* Calculate standard deviation inside VOI, if requested */
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 /* centre of gravity */
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 * Calculate calibration factor
426 */
427 if(verbose>2) printf("Calculating calibration factor\n");
428 /* normalise mean for duration of acquisition */
429 double corROIavg=ROIavg/scanDuration;
430 /* divide by branching fraction */
431 corROIavg=corROIavg/branchingFraction;
432 /* in frame decay correction */
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 /* deadtime correction */
438 corROIavg*=deadtimeCorFactor;
439 /* calculate calibration factor */
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 * Write output file
449 */
450 if(verbose>2) printf("Writing output file\n");
451 /* Construct output file name */
452 char *cptr, calHdrName[512];
453 strlcpy(buf, imgFile, 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 /* Fill IFT struct */
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)
489 ret=iftPutDouble(&ift, buf, 0.0, NULL, 0);
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");
495 iftEmpty(&ift); return(201);
496 }
497 if(verbose>0) {
498 printf("\n--------------------------------------------------\n");
499 printf("%s :\n", calHdrName);
500 printf("--------------------------------------------------\n");
501 iftWrite(&ift, "stdout", 0);
502 }
503 /* Write the file */
504 ret=iftWrite(&ift, calHdrName, 0);
505 iftEmpty(&ift);
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)
Definition branch.c:14
int iftPutDouble(IFT *ift, char *key, double value, char *cmt_type, int verbose)
Definition ift.c:145
int iftPut(IFT *ift, char *key, char *value, char *cmt_type, int verbose)
Definition ift.c:82
void iftEmpty(IFT *ift)
Definition ift.c:60
void iftInit(IFT *ift)
Definition ift.c:45
int iftRead(IFT *ift, char *filename, int is_key_required, int verbose)
Definition iftfile.c:24
int iftWrite(IFT *ift, char *filename, int verbose)
Definition iftfile.c:282
int iftGetDoubleValue(IFT *ift, int si, const char *key, double *value, int verbose)
Definition iftsrch.c:268
int iftGetIntValue(IFT *ift, int si, const char *key, int *value, int verbose)
Definition iftsrch.c:309
int iftGetFrom(IFT *ift, int si, const char *key, int verbose)
Definition iftsrch.c:156
void swawbip(void *buf, long long int size)
Definition swap.c:93
size_t strlcpy(char *dst, const char *src, size_t dstsize)
Definition strext.c:245
int little_endian()
Definition swap.c:14
size_t strlcat(char *dst, const char *src, size_t dstsize)
Definition strext.c:206
IFT_KEY_AND_VALUE * item
Definition libtpcmisc.h:279