TPCCLIB
Loading...
Searching...
No Matches
e63mreg.c
Go to the documentation of this file.
1
7/*****************************************************************************/
8#include "tpcclibConfig.h"
9/*****************************************************************************/
10#include <stdio.h>
11#include <stdlib.h>
12#include <unistd.h>
13#include <math.h>
14#include <string.h>
15#include <time.h>
16/*****************************************************************************/
17#include "libtpcmisc.h"
18#include "libtpcimgio.h"
19/*****************************************************************************/
20
21/*****************************************************************************/
22static char *info[] = {
23 "Regularize ECAT 6.3 image with missing matrices by adding planes/frames",
24 "with zero pixel values.",
25 " ",
26 "Usage: @P [Options] imgfile outputfile ",
27 " ",
28 "Options:",
29 " -stdoptions", // List standard options like --help, -v, etc
30 " ",
31 "Example:",
32 " @P a2345dy1.img a2345dy1_fixed.img ",
33 " ",
34 "See also: esplit, imgdelfr, lmlist, eframe, efixplnr, e63mdel",
35 " ",
36 "Keywords: ECAT, matrixlist, header, tool",
37 0};
38/*****************************************************************************/
39
40/*****************************************************************************/
41/* Turn on the globbing of the command line, since it is disabled by default in
42 mingw-w64 (_dowildcard=0); in MinGW32 define _CRT_glob instead, if necessary;
43 In Unix&Linux wildcard command line processing is enabled by default. */
44/*
45#undef _CRT_glob
46#define _CRT_glob -1
47*/
48int _dowildcard = -1;
49/*****************************************************************************/
50
51/*****************************************************************************/
55int main(int argc, char **argv)
56{
57 int ai, help=0, version=0, verbose=1;
58 int ret;
59 char ecatfile[FILENAME_MAX], outfile[FILENAME_MAX];
60 ECAT63_mainheader mainheader63;
61 MATRIXLIST mlist63;
62
63
64 /*
65 * Get arguments
66 */
67 if(argc==1) {tpcPrintUsage(argv[0], info, stderr); return(1);}
68 ecatfile[0]=outfile[0]=(char)0;
69 ecat63InitMatlist(&mlist63);
70 /* Options */
71 for(ai=1; ai<argc; ai++) if(*argv[ai]=='-') { /* options */
72 if(tpcProcessStdOptions(argv[ai], &help, &version, &verbose)==0) continue;
73 //char *cptr=argv[ai]+1; if(*cptr=='-') cptr++; if(cptr==NULL) continue;
74 fprintf(stderr, "Error: invalid option '%s'.\n", argv[ai]);
75 return(1);
76 } else break;
77
78 /* Print help or version? */
79 if(help==2) {tpcHtmlUsage(argv[0], info, ""); return(0);}
80 if(help) {tpcPrintUsage(argv[0], info, stdout); return(0);}
81 if(version) {tpcPrintBuild(argv[0], stdout); return(0);}
82
83 /* Process other arguments, starting from the first non-option */
84 if(ai<argc) {strlcpy(ecatfile, argv[ai++], FILENAME_MAX);}
85 if(ai<argc) {strlcpy(outfile, argv[ai++], FILENAME_MAX);}
86 if(ai<argc) {
87 fprintf(stderr, "Error: extra argument '%s'.\n", argv[ai]);
88 return(1);
89 }
90
91 /* Is something missing? */
92 if(!outfile[0]) {
93 fprintf(stderr, "Error: missing command-line argument; try %s --help\n", argv[0]);
94 return(1);
95 }
96
97 /* Check output filename */
98 if(strcasecmp(ecatfile, outfile)==0) {
99 fprintf(stderr, "Error: same name for input and output file.\n");
100 return(1);
101 }
102
103 /* In verbose mode print arguments and options */
104 if(verbose>1) {
105 printf("ecatfile := %s\n", ecatfile);
106 printf("outputfile := %s\n", outfile);
107 fflush(stdout);
108 }
109
110
111 /*
112 * Read main header and matrix list
113 */
114 if(verbose>1) {fprintf(stdout, "reading %s\n", ecatfile); fflush(stdout);}
115
116 /* Open file for read */
117 FILE *fp;
118 if((fp=fopen(ecatfile, "rb")) == NULL) {
119 fprintf(stderr, "Error: cannot read file %s\n", ecatfile);
120 return(2);
121 }
122
123 /* Try to read ECAT 6.3 main header */
124 if(verbose>2) {fprintf(stdout, "reading main header\n"); fflush(stdout);}
125 ret=ecat63ReadMainheader(fp, &mainheader63);
126 if(ret) {
127 fprintf(stderr, "Error: cannot read main header.\n");
128 if(verbose>1) printf(" ret := %d\n", ret);
129 fclose(fp); return(2);
130 }
131
132
133 /* Read matrix list */
134 ret=ecat63ReadMatlist(fp, &mlist63, verbose-5);
135 if(ret!=0) {
136 fprintf(stderr, "Error: cannot read matrix list.\n");
137 if(verbose>1) printf(" ret := %d\n", ret);
138 fclose(fp); return(2);
139 }
140 if(mlist63.matrixNr<1) {
141 fprintf(stderr, "Error: matrix list is empty.\n");
142 fclose(fp); return(2);
143 }
144 if(verbose>1) {printf("matrixNr := %d\n", mlist63.matrixNr); fflush(stdout);}
145 ret=ecat63CheckMatlist(&mlist63);
146 if(ret!=0) {
147 fprintf(stderr, "Warning: matrix list fails testing (%d).\n", ret); fflush(stderr);
148 if(verbose>2) ecat63PrintMatlist(&mlist63);
149 } else {
150 if(verbose>100) ecat63PrintMatlist(&mlist63);
151 }
152 /* Trim extra frames */
153 if(mainheader63.num_frames>0) {
154 int del_nr=ecat63DeleteLateFrames(&mlist63, mainheader63.num_frames);
155 if(verbose>1 && del_nr>0)
156 printf(" %d entries in matrix list will not be used.\n", del_nr);
157 }
158
159 /* Get matrix values */
160 Matval *matval;
161 /* Allocate memory for matrix values */
162 matval=(Matval*)calloc(mlist63.matrixNr, sizeof(Matval));
163 if(matval==NULL) {
164 fprintf(stderr, "Error: cannot allocate memory for matrix values.\n");
165 fclose(fp); ecat63EmptyMatlist(&mlist63);
166 return(3);
167 }
168 /* ... and get the matrix values from valid matrices */
169 ECAT63_imageheader image_header;
170 char errmsg[128];
171 int validMatrixNr=0;
172 for(int i=0; i<mlist63.matrixNr; i++) {
173 /* check matrix status */
174 if(mlist63.matdir[i].matstat!=1) continue;
175 /* check that sub header can be read */
176 if(ecat63ReadImageheader(fp, mlist63.matdir[i].strtblk, &image_header, verbose-10, errmsg)) {
177 if(verbose>1) {
178 printf(" cannot read subheader for matrix %d: %s\n", mlist63.matdir[i].matnum, errmsg);
179 fflush(stdout);
180 }
181 mlist63.matdir[i].matstat=0; // mark it as failed
182 continue;
183 }
184 mat_numdoc(mlist63.matdir[i].matnum, matval+validMatrixNr);
185 validMatrixNr++;
186 }
187 if(verbose>1) {printf("validMatrixNr := %d\n", validMatrixNr); fflush(stdout);}
188 if(validMatrixNr<4) {
189 if(validMatrixNr==0) fprintf(stderr, "Error: no valid content in any matrix.\n");
190 else fprintf(stderr, "Error: valid content in only %d matrices; not processed.\n", validMatrixNr);
191 fclose(fp); ecat63EmptyMatlist(&mlist63); free(matval);
192 return(4);
193 }
194
195 /* Check that there is only one gate and bed */
196 int gate, bed, matdata;
197 {
198 if(verbose>2) {fprintf(stdout, "checking for gates and bed positions\n"); fflush(stdout);}
199 gate=matval[0].gate;
200 for(int i=1; i<validMatrixNr; i++)
201 if(matval[i].gate!=gate) {
202 fprintf(stderr, "Error: more than one gate.\n");
203 fclose(fp); ecat63EmptyMatlist(&mlist63); free(matval);
204 return(5);
205 }
206 bed=matval[0].bed;
207 for(int i=1; i<validMatrixNr; i++)
208 if(matval[i].bed!=bed) {
209 fprintf(stderr, "Error: more than one bed position.\n");
210 fclose(fp); ecat63EmptyMatlist(&mlist63); free(matval);
211 return(5);
212 }
213 matdata=matval[0].data;
214 for(int i=1; i<validMatrixNr; i++)
215 if(matval[i].data!=matdata) {
216 fprintf(stderr, "Error: more than one data.\n");
217 fclose(fp); ecat63EmptyMatlist(&mlist63); free(matval);
218 return(5);
219 }
220 }
221
222 /* Make list of existing plane numbers */
223 INTEGER_LIST planes; integerListInit(&planes);
224 for(int i=0; i<validMatrixNr; i++) integerListAdd(&planes, matval[i].plane, 1);
225 integerListSort(&planes);
226 if(verbose>3 && planes.nr>0) {
227 printf("planes: %d", planes.list[0]);
228 for(int i=1; i<planes.nr; i++) printf(", %d", planes.list[i]);
229 printf("\n"); fflush(stdout);
230 }
231 if(planes.nr<1) {
232 fprintf(stderr, "Error: invalid plane numbers.\n");
233 fclose(fp); ecat63EmptyMatlist(&mlist63); free(matval); integerListEmpty(&planes);
234 return(6);
235 }
236
237 /* Make list of frames for each plane */
238 if(verbose>2) {fprintf(stdout, "listing each plane for its frames\n"); fflush(stdout);}
239 INTEGER_LIST *plframes=(INTEGER_LIST*)malloc(planes.nr*sizeof(INTEGER_LIST));
240 if(plframes==NULL) {
241 fprintf(stderr, "Error: cannot allocate memory for frame numbers.\n");
242 fclose(fp); ecat63EmptyMatlist(&mlist63); free(matval); integerListEmpty(&planes);
243 return(6);
244 }
245 for(int pi=0; pi<planes.nr; pi++) integerListInit(plframes+pi);
246 for(int pi=0; pi<planes.nr; pi++) {
247 for(int mi=0; mi<validMatrixNr; mi++) {
248 if(matval[mi].plane!=planes.list[pi]) continue;
249 integerListAdd(plframes+pi, matval[mi].frame, 1);
250 }
251 integerListSort(plframes+pi);
252 }
253 if(verbose>1) {
254 printf("\nPlane\tFrames\n");
255 for(int pi=0; pi<planes.nr; pi++) {
256 printf("%d:", planes.list[pi]);
257 for(int fi=0; fi<plframes[pi].nr; fi++)
258 printf(" %d", plframes[pi].list[fi]);
259 printf("\n");
260 }
261 }
262
263 /* Make list of planes and frames that we should have */
264 INTEGER_LIST keepplanes; integerListInit(&keepplanes);
265 int maxfrnr=0, fullestplanei=0;
266 {
267 /* How many frames there are on planes on average? */
268 int fnr=0;
269 for(int pi=0; pi<planes.nr; pi++) {
270 fnr+=plframes[pi].nr;
271 if(plframes[pi].nr>maxfrnr) {maxfrnr=plframes[pi].nr; fullestplanei=pi;}
272 }
273 fnr/=planes.nr;
274 if(verbose>2) printf("%d frames in each plane on average.\n", fnr);
275 for(int pi=0; pi<planes.nr; pi++)
276 if(plframes[pi].nr>2*fnr/3)
277 integerListAdd(&keepplanes, planes.list[pi], 0);
278 if(verbose>3) {
279 printf("keeping planes:");
280 for(int i=0; i<keepplanes.nr; i++) printf(" %d", keepplanes.list[i]);
281 printf("\n"); fflush(stdout);
282 }
283 }
284 INTEGER_LIST keepframes; integerListInit(&keepframes);
285 {
286 int f, fnr;
287 /* Keep frames that are found on most planes */
288 for(int fi=0; fi<plframes[fullestplanei].nr; fi++) {
289 f=plframes[fullestplanei].list[fi];
290 /* on how many planes this frame exists? */
291 fnr=0;
292 for(int pi=0; pi<planes.nr; pi++) {
293 for(int fj=0; fj<plframes[pi].nr; fj++)
294 if(f==plframes[pi].list[fi]) {fnr++; break;}
295 }
296 if(fnr>3*planes.nr/4)
297 integerListAdd(&keepframes, f, 0);
298 }
299 if(verbose>3) {
300 printf("keeping frames:");
301 for(int i=0; i<keepframes.nr; i++) printf(" %d", keepframes.list[i]);
302 printf("\n"); fflush(stdout);
303 }
304 }
305
306 /* No need for original lists */
307 for(int pi=0; pi<planes.nr; pi++) integerListEmpty(plframes+pi);
308 free(plframes);
309 integerListEmpty(&planes);
310
311
312 /*
313 * Write output file
314 */
315 if(verbose>1) {fprintf(stdout, "writing %s\n", outfile); fflush(stdout);}
316 /* edit the matrix numbers in the main header */
317 {
318 int i, m=0;
319 for(i=0; i<keepplanes.nr; i++) if(keepplanes.list[i]>m) m=keepplanes.list[i];
320 mainheader63.num_planes=m;
321 m=0;
322 for(i=0; i<keepframes.nr; i++) if(keepframes.list[i]>m) m=keepframes.list[i];
323 mainheader63.num_frames=m;
324 }
325 /* Open output file */
326 FILE *fp2;
327 fp2=ecat63Create(outfile, &mainheader63);
328 if(fp2==NULL) {
329 fprintf(stderr, "Error: cannot write ECAT file.\n");
330 ecat63EmptyMatlist(&mlist63); free(matval); fclose(fp);
331 integerListEmpty(&keepframes); integerListEmpty(&keepplanes);
332 return(11);
333 }
334 /* Read and save each frame and plane that we want to keep */
335 for(int fi=0; fi<keepframes.nr; fi++) {
336 int frame=keepframes.list[fi];
337 for(int pi=0; pi<keepplanes.nr; pi++) {
338 int plane=keepplanes.list[pi];
339 /* Compute matnum */
340 int matnum=mat_numcod(frame, plane, gate, matdata, bed);
341 if(verbose>4) printf("frame %d plane %d -> matnum %d\n", frame, plane, matnum);
342 /* Try to find this matnum in the original image */
343 int omi=-1;
344 for(int mi=0; mi<mlist63.matrixNr; mi++)
345 if(mlist63.matdir[mi].matstat==1 && matnum==mlist63.matdir[mi].matnum) {omi=mi; break;}
346 if(omi>=0) {
347 /* Try to read this matrix from the original image */
348 float *fptr;
349 ret=ecat63ReadImageMatrix(fp, mlist63.matdir[omi].strtblk, mlist63.matdir[omi].endblk, &image_header, &fptr);
350 if(ret==0) {
351 if(verbose>5) printf("copying matrix\n");
352 ret=ecat63WriteImageMatrix(fp2, matnum, &image_header, fptr);
353 free(fptr);
354 }
355 if(ret) omi=-1;
356 }
357 if(omi<0) {
358 /* Not found in original image, thus we must save a zero matrix */
359 if(verbose>5) printf("creating zero contents\n");
360 /* Read sub headers from the same frame and another from the same plane to be used as
361 template; using the list that contains only valid matrices */
362 int fmatnum=0, pmatnum=0;
363 for(int mi=0; mi<validMatrixNr; mi++)
364 if(matval[mi].plane!=plane) {
365 pmatnum=mat_numcod(matval[mi].frame, plane, gate, matdata, bed); break;}
366 for(int mi=0; mi<validMatrixNr; mi++)
367 if(matval[mi].frame!=frame) {
368 fmatnum=mat_numcod(frame, matval[mi].plane, gate, matdata, bed); break;}
369 ECAT63_imageheader pih, fih;
370 int fmi=0, pmi=0;
371 for(int mi=0; mi<mlist63.matrixNr; mi++)
372 if(mlist63.matdir[mi].matstat==1 && matnum==fmatnum) {fmi=mi; break;}
373 for(int mi=0; mi<mlist63.matrixNr; mi++)
374 if(mlist63.matdir[mi].matstat==1 && matnum==pmatnum) {pmi=mi; break;}
375 ecat63ReadImageheader(fp, mlist63.matdir[fmi].strtblk, &fih, verbose-10, NULL);
376 ecat63ReadImageheader(fp, mlist63.matdir[pmi].strtblk, &pih, verbose-10, NULL);
377 /* Copy plane-related stuff into frame header */
378 fih.slice_width=pih.slice_width;
381 /* Set some to zero */
382 fih.quant_scale=0.0;
383 fih.image_min=fih.image_max=0;
384 int pxlNr=fih.dimension_1*fih.dimension_2;
385 float *fdata=malloc(pxlNr*sizeof(float));
386 for(int i=0; i<pxlNr; i++) fdata[i]=0.0;
387 if(verbose>5) printf("writing matrix\n");
388 ret=ecat63WriteImageMatrix(fp2, matnum, &fih, fdata);
389 free(fdata);
390 if(ret!=0) {
391 fprintf(stderr, "Error: cannot write image matrix.\n");
392 ecat63EmptyMatlist(&mlist63); free(matval); fclose(fp); fclose(fp2);
393 integerListEmpty(&keepframes); integerListEmpty(&keepplanes);
394 return(13);
395 }
396 }
397 }
398 }
399 integerListEmpty(&keepframes);
400 integerListEmpty(&keepplanes);
401
402
403 /* Close files */
404 fclose(fp); fclose(fp2);
405 ecat63EmptyMatlist(&mlist63);
406 free(matval);
407
408 if(verbose>0) fprintf(stdout, "done.\n");
409
410 return(0);
411}
412/*****************************************************************************/
413
414/*****************************************************************************/
int ecat63ReadMatlist(FILE *fp, MATRIXLIST *ml, int verbose)
Definition ecat63ml.c:46
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 ecat63DeleteLateFrames(MATRIXLIST *ml, int frame_nr)
Definition ecat63ml.c:342
void ecat63PrintMatlist(MATRIXLIST *ml)
Definition ecat63ml.c:130
int ecat63CheckMatlist(MATRIXLIST *ml)
Definition ecat63ml.c:324
void mat_numdoc(int matnum, Matval *matval)
Definition ecat63ml.c:254
int ecat63ReadImageMatrix(FILE *fp, int first_block, int last_block, ECAT63_imageheader *h, float **fdata)
Definition ecat63r.c:627
int ecat63ReadImageheader(FILE *fp, int blk, ECAT63_imageheader *h, int verbose, char *errmsg)
Definition ecat63r.c:187
int ecat63ReadMainheader(FILE *fp, ECAT63_mainheader *h)
Definition ecat63r.c:25
int ecat63WriteImageMatrix(FILE *fp, int matnum, ECAT63_imageheader *h, float *fdata)
Definition ecat63w.c:697
FILE * ecat63Create(const char *fname, ECAT63_mainheader *h)
Definition ecat63w.c:365
int integerListEmpty(INTEGER_LIST *l)
Definition intex.c:175
int integerListInit(INTEGER_LIST *l)
Definition intex.c:161
int integerListSort(INTEGER_LIST *l)
Definition intex.c:219
int integerListAdd(INTEGER_LIST *l, int v, int ifnew)
Definition intex.c:190
Header file for libtpcimgio.
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 slice_location
MatDir * matdir
int matstat
int endblk
int matnum
int strtblk