TPCCLIB
Loading...
Searching...
No Matches
ecatnorm.c
Go to the documentation of this file.
1
10/*****************************************************************************/
11#include "tpcclibConfig.h"
12/*****************************************************************************/
13#include <stdio.h>
14#include <stdlib.h>
15#include <math.h>
16#include <string.h>
17#include <unistd.h>
18#include <ctype.h>
19#include <dirent.h>
20#include <sys/stat.h>
21#include <time.h>
22/*****************************************************************************/
23#include "libtpcmisc.h"
24#include "libtpcimgio.h"
25/*****************************************************************************/
26
27/*****************************************************************************/
28static char *info[] = {
29 "Normalization and optionally attenuation correction for CTI ECAT 931",
30 "transmission or emission sinogram.",
31 " ",
32 "Usage: @P [Options] scnfile nrmfile [atnfile] scnfile2",
33 " ",
34 "Options:",
35 " -rm",
36 " Normalization and attenuation correction are removed from a previously",
37 " corrected sinogram.",
38 " -dtc=<y|N>",
39 " Dead-time correction is done (y), or not done (n, default);",
40 " if normalization is to be removed, then this option decides whether",
41 " dead-time correction is removed (y, default), or kept (n).",
42 " Reconstruction programs ecatfbp and ecatmrp correct the data for",
43 " dead-time, therefore it is not done by default here.",
44 " -stdoptions", // List standard options like --help, -v, etc
45 " ",
46 "Example 1: Normalization correction for transmission sinogram",
47 " @P a2345tr1.scn a2345sta.nrm a2345tr1_normalized.scn",
48 " ",
49 "Example 2: Normalization and attenuation correction for emission sinogram",
50 " @P a2345dy1.scn a2345sta.nrm a2345tr1.atn a2345dy1_corrected.scn",
51 " ",
52 "See also: ecatfbp, ecatmrp, atnmake, egetstrt, edecay, ecalibr, eframe",
53 " ",
54 "Keywords: ECAT, sinogram, reconstruction, normalization, attenuation",
55 0};
56/*****************************************************************************/
57
58/*****************************************************************************/
59/* Turn on the globbing of the command line, since it is disabled by default in
60 mingw-w64 (_dowildcard=0); in MinGW32 define _CRT_glob instead, if necessary;
61 In Unix&Linux wildcard command line processing is enabled by default. */
62/*
63#undef _CRT_glob
64#define _CRT_glob -1
65*/
66int _dowildcard = -1;
67/*****************************************************************************/
68
69/*****************************************************************************/
73int main(int argc, char **argv)
74{
75 int ai, help=0, version=0, verbose=1;
76 char scnfile[FILENAME_MAX], nrmfile[FILENAME_MAX],
77 atnfile[FILENAME_MAX], scnfile2[FILENAME_MAX];
78 int dtc=0; // by default no, because done when scan is read to IMG
79 int normalization=1; // 0=remove corrections; 1=correct
80 char *cptr;
81 int ret;
82
83
84
85 /*
86 * Get arguments
87 */
88 if(argc==1) {tpcPrintUsage(argv[0], info, stderr); return(1);}
89 scnfile[0]=nrmfile[0]=atnfile[0]=scnfile2[0]=(char)0;
90 /* Options */
91 for(ai=1; ai<argc; ai++) if(*argv[ai]=='-') { /* options */
92 cptr=argv[ai]+1; if(*cptr=='-') cptr++; if(cptr==NULL) continue;
93 if(tpcProcessStdOptions(argv[ai], &help, &version, &verbose)==0) continue;
94 if(strncasecmp(cptr, "DTC=", 4)==0) {
95 cptr+=4;
96 if(strncasecmp(cptr, "YES", 1)==0 || strcasecmp(cptr, "ON")==0) {
97 dtc=1; continue;
98 }
99 if(strncasecmp(cptr, "NO", 1)==0 || strcasecmp(cptr, "OFF")==0) {
100 dtc=0; continue;
101 }
102 } else if(strcasecmp(cptr, "RM")==0) {
103 normalization=0; continue;
104 }
105 fprintf(stderr, "Error: invalid option '%s'.\n", argv[ai]);
106 return(1);
107 } else break;
108
109 /* Print help or version? */
110 if(help==2) {tpcHtmlUsage(argv[0], info, ""); return(0);}
111 if(help) {tpcPrintUsage(argv[0], info, stdout); return(0);}
112 if(version) {tpcPrintBuild(argv[0], stdout); return(0);}
113
114 /* Process other arguments, starting from the first non-option */
115 if(ai<argc) {strlcpy(scnfile, argv[ai++], FILENAME_MAX);}
116 if(ai<argc) {strlcpy(nrmfile, argv[ai++], FILENAME_MAX);}
117 if(ai<argc-1) {strlcpy(atnfile, argv[ai++], FILENAME_MAX);}
118 if(ai<argc) {strlcpy(scnfile2, argv[ai++], FILENAME_MAX);}
119 if(ai<argc) {
120 fprintf(stderr, "Error: too many arguments.\n");
121 return(1);
122 }
123
124 /* Is something missing? */
125 if(!scnfile2[0]) {
126 fprintf(stderr, "Error: missing command-line argument; use --help\n");
127 return(1);
128 }
129
130 /* In verbose mode print arguments and options */
131 if(verbose>1) {
132 printf("scnfile := %s\n", scnfile);
133 printf("nrmfile := %s\n", nrmfile);
134 if(atnfile[0]) printf("atnfile := %s\n", atnfile);
135 printf("scnfile2 := %s\n", scnfile2);
136 printf("normalization := %d\n", normalization);
137 printf("dtc := %d\n", dtc);
138 }
139
140 /* Check that input and output files do not have the same filename */
141 if(strcasecmp(scnfile, scnfile2)==0) {
142 fprintf(stderr, "Error: original sinogram must not be overwritten.\n");
143 return(1);
144 }
145
146
147 /*
148 * Open CTI sinogram file
149 */
150 if(verbose==1) printf("reading %s\n", scnfile);
151 FILE *fpscn=NULL;
152 if(verbose>1) printf("opening %s\n", scnfile);
153 if((fpscn=fopen(scnfile, "rb")) == NULL) {
154 fprintf(stderr, "Error: cannot open file %s\n", scnfile);
155 return(2);
156 }
157
158 /*
159 * Read sinogram main header
160 */
161 if(verbose>1) printf("reading main header\n");
162 ECAT63_mainheader scn_main_header;
163 if((ret=ecat63ReadMainheader(fpscn, &scn_main_header))) {
164 fprintf(stderr, "Error: cannot read main header.\n");
165 fclose(fpscn); return(2);
166 }
167 if(verbose>10) ecat63PrintMainheader(&scn_main_header, stdout);
168
169 /* Check the file_type */
170 if(scn_main_header.file_type!=RAW_DATA) {
171 fprintf(stderr, "Error: only ECAT 931 sinogram can be normalized.\n");
172 fclose(fpscn); return(2);
173 }
174
175 /*
176 * Read sinogram matrix list
177 */
178 if(verbose>1) printf("reading matrix list\n");
179 static MATRIXLIST scn_mlist; ecat63InitMatlist(&scn_mlist);
180 ret=ecat63ReadMatlist(fpscn, &scn_mlist, verbose-1);
181 if(ret) {
182 fprintf(stderr, "Error: cannot read matrix list.\n");
183 fclose(fpscn); return(2);
184 }
185 if(scn_mlist.matrixNr<=0) {
186 fprintf(stderr, "Error: matrix list is empty.\n");
187 fclose(fpscn); return(2);
188 }
189 if(verbose>1) printf("sinogram_matrixNr := %d\n", scn_mlist.matrixNr);
190 if(ecat63CheckMatlist(&scn_mlist)) {
191 fprintf(stderr, "Error: check the matrix list.\n");
192 fclose(fpscn); ecat63EmptyMatlist(&scn_mlist);
193 return(2);
194 }
195
196
197
198
199 /*
200 * Open CTI normalization file
201 */
202 if(verbose==1) printf("reading %s\n", nrmfile);
203 FILE *fpnrm=NULL;
204 if(verbose>1) printf("opening %s\n", nrmfile);
205 if((fpnrm=fopen(nrmfile, "rb")) == NULL) {
206 fprintf(stderr, "Error: cannot open file %s\n", nrmfile);
207 fclose(fpscn); ecat63EmptyMatlist(&scn_mlist);
208 return(3);
209 }
210
211 /*
212 * Read normalization main header
213 */
214 if(verbose>1) printf("reading main header\n");
215 ECAT63_mainheader nrm_main_header;
216 if((ret=ecat63ReadMainheader(fpnrm, &nrm_main_header))) {
217 fprintf(stderr, "Error: cannot read main header.\n");
218 fclose(fpscn); ecat63EmptyMatlist(&scn_mlist);
219 fclose(fpnrm);
220 return(3);
221 }
222 if(verbose>10) ecat63PrintMainheader(&nrm_main_header, stdout);
223
224 /* Check the file_type */
225 if(nrm_main_header.file_type!=RAW_DATA) {
226 // files are in sinogram format, not NORM_DATA
227 fprintf(stderr, "Error: check the normalization file.\n");
228 fclose(fpscn); ecat63EmptyMatlist(&scn_mlist);
229 fclose(fpnrm);
230 return(3);
231 }
232
233 /*
234 * Read normalization matrix list
235 */
236 if(verbose>1) printf("reading matrix list\n");
237 static MATRIXLIST nrm_mlist; ecat63InitMatlist(&nrm_mlist);
238 ret=ecat63ReadMatlist(fpnrm, &nrm_mlist, verbose-1);
239 if(ret) {
240 fprintf(stderr, "Error: cannot read matrix list.\n");
241 fclose(fpscn); ecat63EmptyMatlist(&scn_mlist);
242 fclose(fpnrm);
243 return(3);
244 }
245 if(nrm_mlist.matrixNr<=0) {
246 fprintf(stderr, "Error: matrix list is empty.\n");
247 fclose(fpscn); ecat63EmptyMatlist(&scn_mlist);
248 fclose(fpnrm);
249 return(3);
250 }
251 if(verbose>1) printf("normalization_matrixNr := %d\n", nrm_mlist.matrixNr);
252 if(ecat63CheckMatlist(&nrm_mlist)) {
253 fprintf(stderr, "Error: check the matrix list.\n");
254 fclose(fpscn); ecat63EmptyMatlist(&scn_mlist);
255 fclose(fpnrm); ecat63EmptyMatlist(&nrm_mlist);
256 return(3);
257 }
258
259
260 /*
261 * Check that sinogram and normalization file have the same nr of planes
262 */
263 int scn_plane_nr, scn_frame_nr, nrm_plane_nr, nrm_frame_nr;
264 ret=ecat63GetPlaneAndFrameNr(&scn_mlist, &scn_main_header,
265 &scn_plane_nr, &scn_frame_nr);
266 if(ret==0) ret=ecat63GetPlaneAndFrameNr(&nrm_mlist, &nrm_main_header,
267 &nrm_plane_nr, &nrm_frame_nr);
268 if(ret) {
269 fprintf(stderr, "Error: invalid matrix list.\n");
270 fclose(fpscn); ecat63EmptyMatlist(&scn_mlist);
271 fclose(fpnrm); ecat63EmptyMatlist(&nrm_mlist);
272 return(4);
273 }
274 if(verbose>1) {
275 printf("sinogram_plane_nr := %d\n", scn_plane_nr);
276 printf("normalization_plane_nr := %d\n", nrm_plane_nr);
277 printf("sinogram_frame_nr := %d\n", scn_frame_nr);
278 }
279 if(scn_plane_nr!=nrm_plane_nr) {
280 fprintf(stderr, "Error: plane numbers do not match.\n");
281 fclose(fpscn); ecat63EmptyMatlist(&scn_mlist);
282 fclose(fpnrm); ecat63EmptyMatlist(&nrm_mlist);
283 return(4);
284 }
285 if(nrm_frame_nr>1) {
286 fprintf(stderr, "Error: invalid normalization file.\n");
287 fclose(fpscn); ecat63EmptyMatlist(&scn_mlist);
288 fclose(fpnrm); ecat63EmptyMatlist(&nrm_mlist);
289 return(4);
290 }
291
292
293 /*
294 * Optional attenuation data
295 */
296 FILE *fpatn=NULL;
297 ECAT63_mainheader atn_main_header;
298 static MATRIXLIST atn_mlist; ecat63InitMatlist(&atn_mlist);
299
300 if(atnfile[0]) {
301
302 /*
303 * Open CTI attenuation file
304 */
305 if(verbose==1) printf("reading %s\n", atnfile);
306 if(verbose>1) printf("opening %s\n", atnfile);
307 if((fpatn=fopen(atnfile, "rb")) == NULL) {
308 fprintf(stderr, "Error: cannot open file %s\n", atnfile);
309 fclose(fpscn); ecat63EmptyMatlist(&scn_mlist);
310 fclose(fpnrm); ecat63EmptyMatlist(&nrm_mlist);
311 return(5);
312 }
313
314 /*
315 * Read attenuation main header
316 */
317 if(verbose>1) printf("reading main header\n");
318 if((ret=ecat63ReadMainheader(fpatn, &atn_main_header))) {
319 fprintf(stderr, "Error: cannot read main header.\n");
320 fclose(fpscn); ecat63EmptyMatlist(&scn_mlist);
321 fclose(fpnrm); ecat63EmptyMatlist(&nrm_mlist);
322 if(fpatn!=NULL) fclose(fpatn);
323 return(5);
324 }
325 if(verbose>10) ecat63PrintMainheader(&atn_main_header, stdout);
326
327 /* Check the file_type */
328 if(atn_main_header.file_type!=ATTN_DATA) {
329 fprintf(stderr, "Error: check the attenuation file.\n");
330 fclose(fpscn); ecat63EmptyMatlist(&scn_mlist);
331 fclose(fpnrm); ecat63EmptyMatlist(&nrm_mlist);
332 if(fpatn!=NULL) fclose(fpatn);
333 return(5);
334 }
335
336 /*
337 * Read attenuation matrix list
338 */
339 if(verbose>1) printf("reading matrix list\n");
340 ret=ecat63ReadMatlist(fpatn, &atn_mlist, verbose-1);
341 if(ret) {
342 fprintf(stderr, "Error: cannot read matrix list.\n");
343 fclose(fpscn); ecat63EmptyMatlist(&scn_mlist);
344 fclose(fpnrm); ecat63EmptyMatlist(&nrm_mlist);
345 if(fpatn!=NULL) fclose(fpatn);
346 return(5);
347 }
348 if(atn_mlist.matrixNr<=0) {
349 fprintf(stderr, "Error: matrix list is empty.\n");
350 fclose(fpscn); ecat63EmptyMatlist(&scn_mlist);
351 fclose(fpnrm); ecat63EmptyMatlist(&nrm_mlist);
352 if(fpatn!=NULL) {fclose(fpatn); ecat63EmptyMatlist(&atn_mlist);}
353 return(5);
354 }
355 if(verbose>1) printf("attenuation_matrixNr := %d\n", atn_mlist.matrixNr);
356 if(ecat63CheckMatlist(&atn_mlist)) {
357 fprintf(stderr, "Error: check the matrix list.\n");
358 fclose(fpscn); ecat63EmptyMatlist(&scn_mlist);
359 fclose(fpnrm); ecat63EmptyMatlist(&nrm_mlist);
360 if(fpatn!=NULL) {fclose(fpatn); ecat63EmptyMatlist(&atn_mlist);}
361 return(5);
362 }
363
364
365 /*
366 * Check that sinogram and attenuation file have the same nr of planes
367 */
368 int atn_plane_nr, atn_frame_nr;
369 ret=ecat63GetPlaneAndFrameNr(&atn_mlist, &atn_main_header,
370 &atn_plane_nr, &atn_frame_nr);
371 if(ret) {
372 fprintf(stderr, "Error: invalid matrix list.\n");
373 fclose(fpscn); ecat63EmptyMatlist(&scn_mlist);
374 fclose(fpnrm); ecat63EmptyMatlist(&nrm_mlist);
375 if(fpatn!=NULL) {fclose(fpatn); ecat63EmptyMatlist(&atn_mlist);}
376 return(6);
377 }
378 if(verbose>1) {
379 printf("attenuation_plane_nr := %d\n", atn_plane_nr);
380 }
381 if(scn_plane_nr!=atn_plane_nr) {
382 fprintf(stderr, "Error: plane numbers do not match.\n");
383 fclose(fpscn); ecat63EmptyMatlist(&scn_mlist);
384 fclose(fpnrm); ecat63EmptyMatlist(&nrm_mlist);
385 if(fpatn!=NULL) {fclose(fpatn); ecat63EmptyMatlist(&atn_mlist);}
386 return(6);
387 }
388 if(atn_frame_nr>1) {
389 fprintf(stderr, "Error: invalid attenuation file.\n");
390 fclose(fpscn); ecat63EmptyMatlist(&scn_mlist);
391 fclose(fpnrm); ecat63EmptyMatlist(&nrm_mlist);
392 if(fpatn!=NULL) {fclose(fpatn); ecat63EmptyMatlist(&atn_mlist);}
393 return(6);
394 }
395 } // attenuation file matrix list ready
396
397
398
399
400 /*
401 * Create new sinogram data file and write the main header
402 */
403 if(verbose>0) printf("creating %s\n", scnfile2);
404 FILE *fpout=NULL;
405 fpout=ecat63Create(scnfile2, &scn_main_header);
406 if(fpout==NULL) {
407 fprintf(stderr, "Error: cannot write file %s\n", scnfile2);
408 fclose(fpscn); ecat63EmptyMatlist(&scn_mlist);
409 fclose(fpnrm); ecat63EmptyMatlist(&nrm_mlist);
410 if(fpatn!=NULL) {fclose(fpatn); ecat63EmptyMatlist(&atn_mlist);}
411 return(11);
412 }
413
414
415 /*
416 * Process one matrix at a time
417 */
418 if(verbose>0) {
419 char tmp[64];
420 if(!atnfile[0]) strcpy(tmp, "");
421 else strcpy(tmp, " and attenuation correction");
422 if(normalization) printf("normalization%s of sinogram...\n", tmp);
423 else printf("removing normalization%s from sinogram...\n", tmp);
424 fflush(stdout);
425 }
426
427 ECAT63_scanheader scan_header, norm_header;
428 ECAT63_attnheader attn_header;
429 Matval matval;
430 int nr=0, pxlNr=0, matnum=0, ni=0;
431 float *scnmat=NULL, *nrmmat=NULL;
432
433 for(int mi=nr=0; mi<scn_mlist.matrixNr; mi++) {
434
435 /* Get plane and frame nr */
436 mat_numdoc(scn_mlist.matdir[mi].matnum, &matval);
437 /* Read sinogram subheader and scaled data */
438 ret=ecat63ReadScanMatrix(fpscn, scn_mlist.matdir[mi].strtblk,
439 scn_mlist.matdir[mi].endblk, &scan_header, &scnmat);
440 if(ret) {
441 fprintf(stderr, "Error: cannot read sinogram matrix %u.\n",
442 scn_mlist.matdir[mi].matnum);
443 fflush(stderr);
444 fclose(fpscn); ecat63EmptyMatlist(&scn_mlist);
445 fclose(fpnrm); ecat63EmptyMatlist(&nrm_mlist);
446 if(fpatn!=NULL) {fclose(fpatn); ecat63EmptyMatlist(&atn_mlist);}
447 fclose(fpout); remove(scnfile2);
448 return(5);
449 }
450 if(verbose>8) {
451 printf("Matrix: plane %d frame %d gate %d bed %d\n",
452 matval.plane, matval.frame, matval.gate, matval.bed);
453 fflush(stdout);
454 }
455 if(verbose>20) {
456 ecat63PrintScanheader(&scan_header, stdout); fflush(stdout);
457 } else if(verbose>1 && mi==0) {
458 printf("Sinogram dimensions := %d x %d\n",
459 scan_header.dimension_1, scan_header.dimension_2);
460 fflush(stdout);
461 }
462 pxlNr=scan_header.dimension_1*scan_header.dimension_2;
463 /* If dead-time correction was requested, then do it */
464 if(dtc!=0 && scan_header.loss_correction_fctr>0.0) {
465 if(normalization) {
466 for(int i=0; i<pxlNr; i++)
467 scnmat[i]*=scan_header.loss_correction_fctr;
468 } else {
469 for(int i=0; i<pxlNr; i++)
470 scnmat[i]/=scan_header.loss_correction_fctr;
471 }
472 }
473
474 /* Search corresponding matrix from the normalization file */
475 matnum=mat_numcod(1, matval.plane, matval.gate, matval.data, matval.bed);
476 for(ni=0; ni<nrm_mlist.matrixNr; ni++)
477 if(nrm_mlist.matdir[ni].matnum==matnum)
478 break;
479 if(ni>=nrm_mlist.matrixNr) {
480 fprintf(stderr, "Error: cannot find matching normalization matrix.\n");
481 fflush(stderr);
482 fclose(fpscn); ecat63EmptyMatlist(&scn_mlist);
483 fclose(fpnrm); ecat63EmptyMatlist(&nrm_mlist);
484 if(fpatn!=NULL) {fclose(fpatn); ecat63EmptyMatlist(&atn_mlist);}
485 free(scnmat);
486 fclose(fpout); remove(scnfile2);
487 return(8);
488 }
489 /* Read normalization subheader and scaled data */
490 ret=ecat63ReadScanMatrix(fpnrm, nrm_mlist.matdir[ni].strtblk,
491 nrm_mlist.matdir[ni].endblk, &norm_header, &nrmmat);
492 if(ret) {
493 fprintf(stderr, "Error: cannot read normalization matrix %u.\n",
494 nrm_mlist.matdir[ni].matnum);
495 fflush(stderr);
496 fclose(fpscn); ecat63EmptyMatlist(&scn_mlist);
497 fclose(fpnrm); ecat63EmptyMatlist(&nrm_mlist);
498 if(fpatn!=NULL) {fclose(fpatn); ecat63EmptyMatlist(&atn_mlist);}
499 free(scnmat);
500 fclose(fpout); remove(scnfile2);
501 return(8);
502 }
503 if(verbose>20) {
504 ecat63PrintScanheader(&norm_header, stdout); fflush(stdout);
505 } else if(verbose>1 && mi==0) {
506 printf("Normalization dimensions := %d x %d\n",
507 norm_header.dimension_1, norm_header.dimension_2);
508 fflush(stdout);
509 }
510 if(norm_header.dimension_1!=scan_header.dimension_1
511 || norm_header.dimension_2!=scan_header.dimension_2)
512 {
513 fprintf(stderr, "Error: incompatible matrix dimensions.\n");
514 fflush(stderr);
515 fclose(fpscn); ecat63EmptyMatlist(&scn_mlist);
516 fclose(fpnrm); ecat63EmptyMatlist(&nrm_mlist);
517 if(fpatn!=NULL) {fclose(fpatn); ecat63EmptyMatlist(&atn_mlist);}
518 free(scnmat); free(nrmmat);
519 fclose(fpout); remove(scnfile2);
520 return(8);
521 }
522
523 /* Search corresponding matrix from the attenuation file */
524 if(atnfile[0]) {
525 matnum=mat_numcod(1, matval.plane, matval.gate, matval.data, matval.bed);
526 int ai;
527 for(ai=0; ai<atn_mlist.matrixNr; ai++)
528 if(atn_mlist.matdir[ai].matnum==matnum)
529 break;
530 if(ai>=atn_mlist.matrixNr) {
531 fprintf(stderr, "Error: cannot find matching attenuation matrix.\n");
532 fflush(stderr);
533 fclose(fpscn); ecat63EmptyMatlist(&scn_mlist);
534 fclose(fpnrm); ecat63EmptyMatlist(&nrm_mlist);
535 if(fpatn!=NULL) {fclose(fpatn); ecat63EmptyMatlist(&atn_mlist);}
536 free(scnmat); free(nrmmat);
537 fclose(fpout); remove(scnfile2);
538 return(8);
539 }
540 /* Read attenuation subheader and scaled data */
541 float *atnmat=NULL;
542 ret=ecat63ReadAttnMatrix(fpatn, atn_mlist.matdir[ai].strtblk,
543 atn_mlist.matdir[ai].endblk, &attn_header, &atnmat);
544 if(ret) {
545 fprintf(stderr, "Error: cannot read attenuation matrix %u.\n",
546 atn_mlist.matdir[ai].matnum);
547 fflush(stderr);
548 fclose(fpscn); ecat63EmptyMatlist(&scn_mlist);
549 fclose(fpnrm); ecat63EmptyMatlist(&nrm_mlist);
550 if(fpatn!=NULL) {fclose(fpatn); ecat63EmptyMatlist(&atn_mlist);}
551 free(scnmat); free(nrmmat);
552 fclose(fpout); remove(scnfile2);
553 return(8);
554 }
555 if(verbose>20) {
556 ecat63PrintAttnheader(&attn_header, stdout); fflush(stdout);
557 } else if(verbose>1 && mi==0) {
558 printf("Attenuation dimensions := %d x %d\n",
559 attn_header.dimension_1, attn_header.dimension_2);
560 fflush(stdout);
561 }
562 /* Sometimes attenuation dimensions are just in wrong order */
563 if((attn_header.dimension_1!=scan_header.dimension_1
564 || attn_header.dimension_2!=scan_header.dimension_2) &&
565 (attn_header.dimension_2!=scan_header.dimension_1
566 || attn_header.dimension_1!=scan_header.dimension_2))
567 {
568 fprintf(stderr, "Error: incompatible matrix dimensions.\n");
569 fflush(stderr);
570 fclose(fpscn); ecat63EmptyMatlist(&scn_mlist);
571 fclose(fpnrm); ecat63EmptyMatlist(&nrm_mlist);
572 if(fpatn!=NULL) {fclose(fpatn); ecat63EmptyMatlist(&atn_mlist);}
573 free(scnmat); free(nrmmat); free(atnmat);
574 fclose(fpout); remove(scnfile2);
575 return(8);
576 }
577
578 /* If attenuation value is < 1.0E-06, then use that as a limit */
579 for(int i=0; i<pxlNr; i++) if(atnmat[i]<1.0E-06) atnmat[i]=1.0E-06;
580
581 /* Multiply or divide sinogram matrix with attenuation data */
582 if(normalization) {
583 for(int i=0; i<pxlNr; i++)
584 scnmat[i]*=atnmat[i];
585 } else {
586 for(int i=0; i<pxlNr; i++)
587 scnmat[i]/=atnmat[i]; // attenuation data should be >= 1
588 }
589
590 /* Attenuation data is no more needed for this matrix */
591 free(atnmat);
592 }
593
594 /* If normalization value is < 1.0E-06, then use that as a limit */
595 for(int i=0; i<pxlNr; i++) if(nrmmat[i]<1.0E-06) nrmmat[i]=1.0E-06;
596
597 /* Multiply or divide sinogram data with normalization data */
598 if(normalization) {
599 for(int i=0; i<pxlNr; i++)
600 scnmat[i]*=nrmmat[i];
601 } else {
602 for(int i=0; i<pxlNr; i++)
603 scnmat[i]/=nrmmat[i];
604 }
605 free(nrmmat);
606
607
608 /* Write the corrected sinogram matrix */
609 ret=ecat63WriteScanMatrix(fpout, scn_mlist.matdir[mi].matnum, &scan_header,
610 scnmat);
611 if(ret) {
612 fprintf(stderr, "Error: cannot write matrix.\n");
613 fflush(stderr);
614 if(verbose>1) printf("ret := %d\n", ret);
615 fclose(fpscn); ecat63EmptyMatlist(&scn_mlist);
616 fclose(fpnrm); ecat63EmptyMatlist(&nrm_mlist);
617 if(fpatn!=NULL) {fclose(fpatn); ecat63EmptyMatlist(&atn_mlist);}
618 free(scnmat); free(nrmmat);
619 fclose(fpout); remove(scnfile2);
620 return(12);
621 }
622 free(scnmat);
623 nr++; // counter
624 } /* next matrix */
625 if(verbose>0) {printf("%d matrices processed.\n", nr); fflush(stdout);}
626
627 fclose(fpscn); ecat63EmptyMatlist(&scn_mlist);
628 fclose(fpnrm); ecat63EmptyMatlist(&nrm_mlist);
629 if(fpatn!=NULL) {fclose(fpatn); ecat63EmptyMatlist(&atn_mlist);}
630 fclose(fpout);
631
632 return(0);
633}
634/*****************************************************************************/
635
636/*****************************************************************************/
int ecat63ReadMatlist(FILE *fp, MATRIXLIST *ml, int verbose)
Definition ecat63ml.c:46
int ecat63GetPlaneAndFrameNr(MATRIXLIST *mlist, ECAT63_mainheader *h, int *plane_nr, int *frame_nr)
Definition ecat63ml.c:400
void ecat63InitMatlist(MATRIXLIST *mlist)
Definition ecat63ml.c:20
void ecat63EmptyMatlist(MATRIXLIST *mlist)
Definition ecat63ml.c:31
int mat_numcod(int frame, int plane, int gate, int data, int bed)
Definition ecat63ml.c:242
int ecat63CheckMatlist(MATRIXLIST *ml)
Definition ecat63ml.c:324
void mat_numdoc(int matnum, Matval *matval)
Definition ecat63ml.c:254
void ecat63PrintMainheader(ECAT63_mainheader *h, FILE *fp)
Definition ecat63p.c:16
void ecat63PrintScanheader(ECAT63_scanheader *h, FILE *fp)
Definition ecat63p.c:137
void ecat63PrintAttnheader(ECAT63_attnheader *h, FILE *fp)
Definition ecat63p.c:173
int ecat63ReadScanMatrix(FILE *fp, int first_block, int last_block, ECAT63_scanheader *h, float **fdata)
Definition ecat63r.c:731
int ecat63ReadAttnMatrix(FILE *fp, int first_block, int last_block, ECAT63_attnheader *h, float **fdata)
Definition ecat63r.c:830
int ecat63ReadMainheader(FILE *fp, ECAT63_mainheader *h)
Definition ecat63r.c:25
int ecat63WriteScanMatrix(FILE *fp, int matnum, ECAT63_scanheader *h, float *fdata)
Definition ecat63w.c:781
FILE * ecat63Create(const char *fname, ECAT63_mainheader *h)
Definition ecat63w.c:365
Header file for libtpcimgio.
#define ATTN_DATA
#define RAW_DATA
Header file for libtpcmisc.
int tpcProcessStdOptions(const char *s, int *print_usage, int *print_version, int *verbose_level)
Definition proginfo.c:40
size_t strlcpy(char *dst, const char *src, size_t dstsize)
Definition strext.c:245
int tpcHtmlUsage(const char *program, char *text[], const char *path)
Definition proginfo.c:213
void tpcPrintBuild(const char *program, FILE *fp)
Definition proginfo.c:383
void tpcPrintUsage(const char *program, char *text[], FILE *fp)
Definition proginfo.c:158
short int dimension_1
short int dimension_2
short int dimension_2
short int dimension_1
MatDir * matdir
int endblk
int matnum
int strtblk
int frame
int plane