TPCCLIB
Loading...
Searching...
No Matches
mrp.c
Go to the documentation of this file.
1
9/*****************************************************************************/
10#include "libtpcrec.h"
11/*****************************************************************************/
12
13/*****************************************************************************/
21 IMG *scn,
23 IMG *img,
25 int imgDim,
27 float zoom,
29 float shiftX,
31 float shiftY,
33 float rotation,
35 int maxIterNr,
37 int skipPriorNr,
39 float beta,
41 int maskDim,
43 int osSetNr,
45 int verbose
46) {
47 if(verbose>1)
48 printf("imgMRP(scn, img, %d, %g, %g, %g, %g, %d, %d, %g, %d, %d)\n",
49 imgDim, zoom, shiftX, shiftY, rotation, maxIterNr, skipPriorNr, beta,
50 maskDim, osSetNr);
51
52
53 /* Check the arguments */
54 if(scn->status!=IMG_STATUS_OCCUPIED) return(1);
55 if(imgDim<2 || imgDim>4096 || imgDim%2) return(1);
56 if(zoom<0.01 || zoom>1000.) return(1);
57 if(scn->dimx<=1 || scn->dimx>16384) return(1);
58 if(beta<0.0) return(1);
59 if(maskDim!=3 && maskDim!=5) return(1);
60
61
62 /*
63 * Allocate output image
64 */
65 if(verbose>1) printf("allocating memory for the image\n");
66 imgEmpty(img);
67 if(imgAllocate(img, scn->dimz, imgDim, imgDim, scn->dimt)!=0) return(3);
68
69 /* Set image "header" information */
70 if(verbose>1) printf("setting image header\n");
72 img->unit=CUNIT_CPS; /* (cnts/sec) */
73 img->scanStart=scn->scanStart;
74 img->axialFOV=scn->axialFOV;
76 img->sizez=scn->sizez;
77 strcpy(img->studyNr, scn->studyNr);
79 if(scn->sampleDistance<=0.0) {
80 if(scn->dimx==281) { // GE Advance
81 img->sizez=4.25;
82 scn->sampleDistance=1.95730;
83 scn->axialFOV=150.; scn->transaxialFOV=550.;
84 } else { // ECAT 931
85 img->sizez=6.75;
86 scn->sampleDistance=3.12932;
87 scn->axialFOV=108.; scn->transaxialFOV=600.829;
88 }
89 }
90 float pixSize; /* note that pixSize is in cm in the ECAT image */
91 pixSize=scn->sampleDistance*(float)scn->dimx/((float)imgDim*zoom);
92 img->sizex=img->sizey=pixSize;
93 int plane, frame;
94 for(plane=0; plane<scn->dimz; plane++)
95 img->planeNumber[plane]=scn->planeNumber[plane];
99 for(frame=0; frame<scn->dimt; frame++) {
100 img->start[frame]=scn->start[frame]; img->end[frame]=scn->end[frame];
101 img->mid[frame]=0.5*(img->start[frame]+img->end[frame]);
102 }
103 img->isWeight=0;
104
105 /*
106 * Preparations for reconstruction
107 */
108
109 /* Pre-compute the sine tables for back-projection (note the rotation!) */
110 if(verbose>1) printf("computing sine tables for back-projection\n");
111 float sinB[3*scn->dimy/2];
112 float sinBrot[3*scn->dimy/2];
113 recSinTables(scn->dimy, sinB, sinBrot, rotation);
114
115 /* Set the backprojection zoom and inverse (globals) */
116 float bpZoom, bpZoomInv;
117 bpZoom=zoom*(float)imgDim/(float)scn->dimx;
118 bpZoomInv=1.0/bpZoom;
119 if(verbose>2) printf("bpZoom=%g bpZoomInv=%g\n", bpZoom, bpZoomInv);
120
121 /* Initialize variables used by back-projection */
122 if(verbose>1) printf("initialize variables for back-projection\n");
123 float offsX, offsY;
124 int halfDim;
125 halfDim=imgDim/2;
126 offsX=shiftX/pixSize; offsY=shiftY/pixSize;
127 for(int i=0; i<3*(scn->dimy)/2; i++) {
128 sinB[i]*=bpZoomInv;
129 sinBrot[i]*=bpZoomInv;
130 }
131 if(verbose>2) {
132 printf("halfDim=%d offsX=%g offsY=%g\n", halfDim, offsX, offsY);
133 }
134
135
136 /*
137 * Reconstruct one matrix at a time
138 */
139 if(verbose>1) printf("reconstruct one matrix at a time...\n");
140 int failed=0;
141#pragma omp parallel for private(frame)
142 for(plane=0; plane<scn->dimz; plane++) {
143 for(frame=0; frame<scn->dimt; frame++) {
144 if(failed) break;
145
146 if(verbose>3) {
147 printf("reconstructing plane %d frame %d\n",
148 scn->planeNumber[plane], frame+1);
149 fflush(stdout);
150 }
151 int i, j, k, ret;
152
153 /* Copy scan data into the array */
154 float scnData[scn->dimx*scn->dimy];
155 float imgData[img->dimx*img->dimy];
156 //float *imgOrigin=imgData+imgDim*(halfDim-1)+halfDim;
157
158 for(i=0, k=0; i<scn->dimy; i++)
159 for(j=0; j<scn->dimx; j++)
160 scnData[k++]=scn->m[plane][i][j][frame];
161 /* Initiate image buffer */
162 for(i=0; i<imgDim*imgDim; i++) imgData[i]=0.0;
163
164 /* Reconstruct */
165 ret=mrp(scnData, scn->dimx, scn->dimy, maxIterNr, osSetNr, maskDim, zoom,
166 beta, skipPriorNr, imgDim, imgData, verbose-3);
167 if(ret!=0) {
168 if(verbose>0) fprintf(stderr, "mrp() return value %d\n", ret);
169 failed=ret; break;
170 }
171
172 /* Copy the image array to matrix data */
173 /* At the same time, correct for the frame length */
174 float f;
175 f=img->end[frame]-img->start[frame];
176 if(f<1.0) f=1.0;
177 f=1.0/f;
178 for(i=0, k=0; i<img->dimy; i++)
179 for(j=0; j<img->dimx; j++)
180 img->m[plane][i][j][frame] = imgData[k++]*f;
181 if(verbose==1) {fprintf(stdout, "."); fflush(stdout);}
182 } /* next frame */
183 } /* next plane */
184 if(verbose==1) {fprintf(stdout, "\n"); fflush(stdout);}
185 if(failed) return(8);
186
187 if(verbose>1) printf("imgMRP() done.\n");
188 return(0);
189}
190/*****************************************************************************/
191
192/*****************************************************************************/
200 float *coef,
202 float *img,
204 float *oimg,
206 int n
207) {
208 for(int i=0; i<n; i++) {
209 oimg[i]=coef[i]*img[i];
210 if(oimg[i]<0.0) oimg[i]=0.0;
211 }
212}
213/*****************************************************************************/
214
215/*****************************************************************************/
228 float *measured,
230 float *proj,
232 float *correct,
234 int os_sets,
236 int rays,
238 int views
239) {
240 for(int i=0; i<rays*views/os_sets; i++) {
241 if(fabs(proj[i])>1.0E-40) {
242 correct[i]=(float)os_sets*measured[i]/proj[i];
243 if(correct[i]>100.) correct[i]=100.;
244 else if(correct[i]<0.0) correct[i]=0.0;
245 } else {
246 correct[i]=0.0;
247 }
248 }
249}
250/*****************************************************************************/
251
252/*****************************************************************************/
259int mrp(
262 float *sinogram,
264 int rays,
266 int views,
268 int iter,
270 int os_sets,
272 int maskdim,
274 float zoom,
276 float beta,
278 int skip_prior,
282 int dim,
284 float *image,
286 int verbose
287) {
288 if(verbose>0)
289 printf("mrp(%d, %d, %d, %d, %d, %g, %g, %d, %d)\n",
290 rays, views, iter, os_sets, maskdim, zoom, beta, skip_prior, dim);
291 if(sinogram==NULL || image==NULL) return(1);
292 if(rays<2 || views<2 || iter<1 || os_sets<1 || dim<2) return(1);
293 if(dim%2 || zoom<0.05) return(2);
294 if(maskdim!=3 && maskdim!=5) return(2);
295
296 int i, k;
297 int imgsize=dim*dim;
298 int halfdim=dim/2;
299 int views_in_set=views/os_sets;
300
301 /* Set scale */
302 int recrays;
303 float scale, bp_zoom;
304 recrays=(int)((float)dim*zoom);
305 bp_zoom=zoom*(float)dim/(float)recrays;
306 scale=((float)recrays/(float)rays)*bp_zoom*bp_zoom/(float)views;
307 if(verbose>1) {
308 printf(" recrays := %d\n", recrays);
309 printf(" bp_zoom := %g\n", bp_zoom);
310 printf(" scale := %g\n", scale);
311 }
312
313 /* Make the Ordered Subset process order (bit-reversed sequence) */
314 int seq[os_sets]; set_os_set(os_sets, seq);
315 if(verbose>2) {
316 printf("os_sets :=");
317 for(i=0; i<os_sets; i++) printf(" %d", seq[i]);
318 printf("\n"); fflush(stdout);
319 }
320
321 /* Arrange the sinogram and interpolate so that
322 bin width equals pixel width */
323 float sino[recrays*views];
324 {
325 float scnset[rays*views];
326 /* arrange */
327 for(int s=0; s<os_sets; s++) {
328 for(int j=0; j<views/os_sets; j++) {
329 memcpy((char*)(scnset + s*rays*views/os_sets + j*rays),
330 (char*)(sinogram + j*rays*os_sets + s*rays), rays*sizeof(float));
331 }
332 }
333 /* interpolate */
334 recInterpolateSinogram(scnset, sino, rays, recrays, views);
335 }
336
337 /* Get some statistics from the sinogram matrix */
338 int scnsize=recrays*views;
339 int nonzeroNr;
340 float counts;
341 nonzeroNr=recGetStatistics(sino, scnsize, &counts, NULL, NULL, 1);
342 if(verbose>1) {
343 printf(" total_counts := %g\n", counts);
344 printf(" non-zeroes := %d/%d\n", nonzeroNr, scnsize);
345 }
346
347
348 /* Make an initial image: an uniform disk enclosed by rays with a value
349 matching the total count */
350 if(verbose>1) printf("creating initial %dx%d image\n", dim, dim);
351 float current_img[imgsize];
352 for(i=0; i<imgsize; i++) image[i]=current_img[i]=0.0;
353 float init;
354 k=0;
355 init=counts/(M_PI*(float)((halfdim-1)*(halfdim-1)));
356 for(int j=halfdim-1; j>=-halfdim; j--) {
357 for(i=-halfdim; i<halfdim; i++) {
358 if((int)hypot((double)i, (double)j) < halfdim-1)
359 current_img[k]=init;
360 k++;
361 }
362 }
363
364
365 /* Pre-compute the sine tables for back-projection */
366 if(verbose>1) printf("computing sine table\n");
367 float sinB[3*views/2];
368 recSinTables(views, sinB, NULL, 0.0);
369 for(i=0; i<3*views/2; i++) sinB[i]/=bp_zoom;
370
371 /* Iterations */
372 if(verbose>1) {printf("iterations\n"); fflush(stdout);}
373 float current_proj[recrays*views_in_set+1];
374 float correction[recrays*views/os_sets];
375 float medcoefs[imgsize], mlcoefs[imgsize];
376 int s, itercount=1, view;
377 do {
378 if(verbose>3) {printf(" iteration %d\n", itercount); fflush(stdout);}
379
380 for(s=0; s<os_sets; s++) {
381 if(verbose>4) {
382 printf(" os_set %d; seq=%d\n", 1+s, seq[s]);
383 fflush(stdout);
384 }
385 /* Image reprojection */
386 for(i=0; i<recrays*views_in_set; i++) current_proj[i]=0.0;
387 for(i=0; i<views_in_set; i++) {
388 view=seq[s]+i*os_sets;
389 viewReprojection(current_img, current_proj+i*recrays, view, dim,
390 views, recrays, sinB, sinB, 0.0, 0.0, bp_zoom);
391 }
392 /* Calculate correction = measured / re-projected */
393 mrpProjectionCorrection(sino+seq[s]*recrays*views_in_set, current_proj,
394 correction, os_sets, recrays, views);
395 /* Make the ML coefficients */
396 for(i=0; i<imgsize; i++) mlcoefs[i]=0.0;
397 for(i=0; i<views_in_set; i++)
398 viewBackprojection(correction+i*recrays, mlcoefs, dim,
399 seq[s]+i*os_sets, views, recrays, sinB, sinB, 0.0, 0.0, bp_zoom);
400 /* Make the prior coefficients */
401 if(skip_prior<=0 && beta>0.0) {
402 if(verbose>3) {printf(" applying prior\n"); fflush(stdout);}
403 float maxv, maxm;
404 fMinMaxFin(current_img, imgsize, NULL, &maxv);
405 do_prior(current_img, beta, medcoefs, dim,
406 1.0E-08*maxv, maskdim, &maxm);
407 if(verbose>3) {
408 printf(" max value in current image := %g\n", maxv);
409 printf(" max median coefficient := %g\n", maxm);
410 }
411 /* Adjust ML coefficients */
412 mrpUpdate(medcoefs, mlcoefs, mlcoefs, imgsize);
413 }
414
415 /* Calculate next image */
416 mrpUpdate(mlcoefs, current_img, current_img, imgsize);
417
418 } // next set
419 itercount++; skip_prior--;
420 if(verbose>3) {printf(" -> next iteration maybe\n"); fflush(stdout);}
421 } while(itercount<iter);
422 if(verbose>2) {printf(" iterations done.\n"); fflush(stdout);}
423
424 for(i=0; i<imgsize; i++) image[i]=current_img[i]*=scale;
425
426 if(verbose>1) {printf("mrp() done.\n"); fflush(stdout);}
427 return(0);
428} // mrp()
429/*****************************************************************************/
430
431/*****************************************************************************/
int imgAllocate(IMG *image, int planes, int rows, int columns, int frames)
Definition img.c:194
void imgEmpty(IMG *image)
Definition img.c:121
void fMinMaxFin(float *data, long long int n, float *fmin, float *fmax)
Definition imgminmax.c:649
#define IMG_STATUS_OCCUPIED
#define IMG_DC_NONCORRECTED
#define IMG_TYPE_IMAGE
Header file for libtpcrec.
void recSinTables(int views, float *sinB, float *sinBrot, float rotation)
Definition recutil.c:12
int mrp(float *sinogram, int rays, int views, int iter, int os_sets, int maskdim, float zoom, float beta, int skip_prior, int dim, float *image, int verbose)
Definition mrp.c:259
void viewBackprojection(float *prj, float *idata, int dim, int view, int viewNr, int rayNr, float *sinB, float *sinBrot, float offsX, float offsY, float bpZoom)
void viewReprojection(float *idata, float *sdata, int view, int dim, int viewNr, int rayNr, float *sinB, float *sinBrot, float offsX, float offsY, float bpZoom)
void recInterpolateSinogram(float *srcsino, float *newsino, int srcrays, int newrays, int views)
Definition recutil.c:37
int imgMRP(IMG *scn, IMG *img, int imgDim, float zoom, float shiftX, float shiftY, float rotation, int maxIterNr, int skipPriorNr, float beta, int maskDim, int osSetNr, int verbose)
Definition mrp.c:18
void set_os_set(int os_sets, int *set_seq)
Definition recutil.c:113
int recGetStatistics(float *buf, int n, float *osum, float *omin, float *omax, int skip_zero_mins)
Definition recutil.c:154
void do_prior(float *img, float beta, float *med_coef, int dim, float small, int maskdim, float *maxm)
Definition mrprior.c:77
void mrpProjectionCorrection(float *measured, float *proj, float *correct, int os_sets, int rays, int views)
Definition mrp.c:226
void mrpUpdate(float *coef, float *img, float *oimg, int n)
Definition mrp.c:198
float sizex
unsigned short int dimx
char type
float sampleDistance
float **** m
char decayCorrection
float transaxialFOV
char unit
char status
time_t scanStart
unsigned short int dimt
int * planeNumber
float sizey
float * start
unsigned short int dimz
unsigned short int dimy
float * end
char radiopharmaceutical[32]
float isotopeHalflife
char studyNr[MAX_STUDYNR_LEN+1]
float axialFOV
float * mid
char isWeight
float sizez