11#include "tpcclibConfig.h"
28static char *info[] = {
29 "Normalization and optionally attenuation correction for CTI ECAT 931",
30 "transmission or emission sinogram.",
32 "Usage: @P [Options] scnfile nrmfile [atnfile] scnfile2",
36 " Normalization and attenuation correction are removed from a previously",
37 " corrected sinogram.",
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.",
46 "Example 1: Normalization correction for transmission sinogram",
47 " @P a2345tr1.scn a2345sta.nrm a2345tr1_normalized.scn",
49 "Example 2: Normalization and attenuation correction for emission sinogram",
50 " @P a2345dy1.scn a2345sta.nrm a2345tr1.atn a2345dy1_corrected.scn",
52 "See also: ecatfbp, ecatmrp, atnmake, egetstrt, edecay, ecalibr, eframe",
54 "Keywords: ECAT, sinogram, reconstruction, normalization, attenuation",
73int main(
int argc,
char **argv)
75 int ai, help=0, version=0, verbose=1;
76 char scnfile[FILENAME_MAX], nrmfile[FILENAME_MAX],
77 atnfile[FILENAME_MAX], scnfile2[FILENAME_MAX];
88 if(argc==1) {
tpcPrintUsage(argv[0], info, stderr);
return(1);}
89 scnfile[0]=nrmfile[0]=atnfile[0]=scnfile2[0]=(char)0;
91 for(ai=1; ai<argc; ai++)
if(*argv[ai]==
'-') {
92 cptr=argv[ai]+1;
if(*cptr==
'-') cptr++;
if(cptr==NULL)
continue;
94 if(strncasecmp(cptr,
"DTC=", 4)==0) {
96 if(strncasecmp(cptr,
"YES", 1)==0 || strcasecmp(cptr,
"ON")==0) {
99 if(strncasecmp(cptr,
"NO", 1)==0 || strcasecmp(cptr,
"OFF")==0) {
102 }
else if(strcasecmp(cptr,
"RM")==0) {
103 normalization=0;
continue;
105 fprintf(stderr,
"Error: invalid option '%s'.\n", argv[ai]);
110 if(help==2) {
tpcHtmlUsage(argv[0], info,
"");
return(0);}
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);}
120 fprintf(stderr,
"Error: too many arguments.\n");
126 fprintf(stderr,
"Error: missing command-line argument; use --help\n");
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);
141 if(strcasecmp(scnfile, scnfile2)==0) {
142 fprintf(stderr,
"Error: original sinogram must not be overwritten.\n");
150 if(verbose==1) printf(
"reading %s\n", scnfile);
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);
161 if(verbose>1) printf(
"reading main header\n");
164 fprintf(stderr,
"Error: cannot read main header.\n");
165 fclose(fpscn);
return(2);
171 fprintf(stderr,
"Error: only ECAT 931 sinogram can be normalized.\n");
172 fclose(fpscn);
return(2);
178 if(verbose>1) printf(
"reading matrix list\n");
182 fprintf(stderr,
"Error: cannot read matrix list.\n");
183 fclose(fpscn);
return(2);
186 fprintf(stderr,
"Error: matrix list is empty.\n");
187 fclose(fpscn);
return(2);
189 if(verbose>1) printf(
"sinogram_matrixNr := %d\n", scn_mlist.
matrixNr);
191 fprintf(stderr,
"Error: check the matrix list.\n");
202 if(verbose==1) printf(
"reading %s\n", nrmfile);
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);
214 if(verbose>1) printf(
"reading main header\n");
217 fprintf(stderr,
"Error: cannot read main header.\n");
227 fprintf(stderr,
"Error: check the normalization file.\n");
236 if(verbose>1) printf(
"reading matrix list\n");
240 fprintf(stderr,
"Error: cannot read matrix list.\n");
246 fprintf(stderr,
"Error: matrix list is empty.\n");
251 if(verbose>1) printf(
"normalization_matrixNr := %d\n", nrm_mlist.
matrixNr);
253 fprintf(stderr,
"Error: check the matrix list.\n");
263 int scn_plane_nr, scn_frame_nr, nrm_plane_nr, nrm_frame_nr;
265 &scn_plane_nr, &scn_frame_nr);
267 &nrm_plane_nr, &nrm_frame_nr);
269 fprintf(stderr,
"Error: invalid matrix list.\n");
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);
279 if(scn_plane_nr!=nrm_plane_nr) {
280 fprintf(stderr,
"Error: plane numbers do not match.\n");
286 fprintf(stderr,
"Error: invalid normalization file.\n");
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);
317 if(verbose>1) printf(
"reading main header\n");
319 fprintf(stderr,
"Error: cannot read main header.\n");
322 if(fpatn!=NULL) fclose(fpatn);
329 fprintf(stderr,
"Error: check the attenuation file.\n");
332 if(fpatn!=NULL) fclose(fpatn);
339 if(verbose>1) printf(
"reading matrix list\n");
342 fprintf(stderr,
"Error: cannot read matrix list.\n");
345 if(fpatn!=NULL) fclose(fpatn);
349 fprintf(stderr,
"Error: matrix list is empty.\n");
355 if(verbose>1) printf(
"attenuation_matrixNr := %d\n", atn_mlist.
matrixNr);
357 fprintf(stderr,
"Error: check the matrix list.\n");
368 int atn_plane_nr, atn_frame_nr;
370 &atn_plane_nr, &atn_frame_nr);
372 fprintf(stderr,
"Error: invalid matrix list.\n");
379 printf(
"attenuation_plane_nr := %d\n", atn_plane_nr);
381 if(scn_plane_nr!=atn_plane_nr) {
382 fprintf(stderr,
"Error: plane numbers do not match.\n");
389 fprintf(stderr,
"Error: invalid attenuation file.\n");
403 if(verbose>0) printf(
"creating %s\n", scnfile2);
407 fprintf(stderr,
"Error: cannot write file %s\n", scnfile2);
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);
430 int nr=0, pxlNr=0, matnum=0, ni=0;
431 float *scnmat=NULL, *nrmmat=NULL;
433 for(
int mi=nr=0; mi<scn_mlist.
matrixNr; mi++) {
441 fprintf(stderr,
"Error: cannot read sinogram matrix %u.\n",
447 fclose(fpout); remove(scnfile2);
451 printf(
"Matrix: plane %d frame %d gate %d bed %d\n",
457 }
else if(verbose>1 && mi==0) {
458 printf(
"Sinogram dimensions := %d x %d\n",
466 for(
int i=0; i<pxlNr; i++)
469 for(
int i=0; i<pxlNr; i++)
476 for(ni=0; ni<nrm_mlist.
matrixNr; ni++)
480 fprintf(stderr,
"Error: cannot find matching normalization matrix.\n");
486 fclose(fpout); remove(scnfile2);
493 fprintf(stderr,
"Error: cannot read normalization matrix %u.\n",
500 fclose(fpout); remove(scnfile2);
505 }
else if(verbose>1 && mi==0) {
506 printf(
"Normalization dimensions := %d x %d\n",
513 fprintf(stderr,
"Error: incompatible matrix dimensions.\n");
518 free(scnmat); free(nrmmat);
519 fclose(fpout); remove(scnfile2);
527 for(ai=0; ai<atn_mlist.
matrixNr; ai++)
531 fprintf(stderr,
"Error: cannot find matching attenuation matrix.\n");
536 free(scnmat); free(nrmmat);
537 fclose(fpout); remove(scnfile2);
545 fprintf(stderr,
"Error: cannot read attenuation matrix %u.\n",
551 free(scnmat); free(nrmmat);
552 fclose(fpout); remove(scnfile2);
557 }
else if(verbose>1 && mi==0) {
558 printf(
"Attenuation dimensions := %d x %d\n",
568 fprintf(stderr,
"Error: incompatible matrix dimensions.\n");
573 free(scnmat); free(nrmmat); free(atnmat);
574 fclose(fpout); remove(scnfile2);
579 for(
int i=0; i<pxlNr; i++)
if(atnmat[i]<1.0E-06) atnmat[i]=1.0E-06;
583 for(
int i=0; i<pxlNr; i++)
584 scnmat[i]*=atnmat[i];
586 for(
int i=0; i<pxlNr; i++)
587 scnmat[i]/=atnmat[i];
595 for(
int i=0; i<pxlNr; i++)
if(nrmmat[i]<1.0E-06) nrmmat[i]=1.0E-06;
599 for(
int i=0; i<pxlNr; i++)
600 scnmat[i]*=nrmmat[i];
602 for(
int i=0; i<pxlNr; i++)
603 scnmat[i]/=nrmmat[i];
612 fprintf(stderr,
"Error: cannot write matrix.\n");
614 if(verbose>1) printf(
"ret := %d\n", ret);
618 free(scnmat); free(nrmmat);
619 fclose(fpout); remove(scnfile2);
625 if(verbose>0) {printf(
"%d matrices processed.\n", nr); fflush(stdout);}
int ecat63ReadMatlist(FILE *fp, MATRIXLIST *ml, int verbose)
int ecat63GetPlaneAndFrameNr(MATRIXLIST *mlist, ECAT63_mainheader *h, int *plane_nr, int *frame_nr)
void ecat63InitMatlist(MATRIXLIST *mlist)
void ecat63EmptyMatlist(MATRIXLIST *mlist)
int mat_numcod(int frame, int plane, int gate, int data, int bed)
int ecat63CheckMatlist(MATRIXLIST *ml)
void mat_numdoc(int matnum, Matval *matval)
void ecat63PrintMainheader(ECAT63_mainheader *h, FILE *fp)
void ecat63PrintScanheader(ECAT63_scanheader *h, FILE *fp)
void ecat63PrintAttnheader(ECAT63_attnheader *h, FILE *fp)
int ecat63ReadScanMatrix(FILE *fp, int first_block, int last_block, ECAT63_scanheader *h, float **fdata)
int ecat63ReadAttnMatrix(FILE *fp, int first_block, int last_block, ECAT63_attnheader *h, float **fdata)
int ecat63ReadMainheader(FILE *fp, ECAT63_mainheader *h)
int ecat63WriteScanMatrix(FILE *fp, int matnum, ECAT63_scanheader *h, float *fdata)
FILE * ecat63Create(const char *fname, ECAT63_mainheader *h)
Header file for libtpcimgio.
Header file for libtpcmisc.
int tpcProcessStdOptions(const char *s, int *print_usage, int *print_version, int *verbose_level)
size_t strlcpy(char *dst, const char *src, size_t dstsize)
int tpcHtmlUsage(const char *program, char *text[], const char *path)
void tpcPrintBuild(const char *program, FILE *fp)
void tpcPrintUsage(const char *program, char *text[], FILE *fp)