TPCCLIB
Loading...
Searching...
No Matches
image.c
Go to the documentation of this file.
1
6/*****************************************************************************/
7#include "tpcclibConfig.h"
8/*****************************************************************************/
9#include "tpcimage.h"
10/*****************************************************************************/
11
12/*****************************************************************************/
16static const char *img_modality[] = {
17 "Unknown", // IMG_MODALITY_UNKNOWN
18 "PET", // IMG_MODALITY_PET
19 "SPECT", // IMG_MODALITY_SPECT
20 "CT", // IMG_MODALITY_CT
21 "MRI", // IMG_MODALITY_MRI
220};
30) {
31 if(c<IMG_MODALITY_UNKNOWN || c>=IMG_MODALITY_LAST) return NULL;
32 return (char*)img_modality[c];
33}
34/*****************************************************************************/
35
36/*****************************************************************************/
40static const char *img_content[] = {
41 "Unknown", // IMG_CONTENT_UNKNOWN
42 "image", // IMG_CONTENT_IMAGE
43 "raw", // IMG_CONTENT_RAW
44 "attenuation", // IMG_CONTENT_ATTN
45 "polarmap", // IMG_CONTENT_POLARMAP
460};
54) {
55 if(c<IMG_CONTENT_UNKNOWN || c>=IMG_CONTENT_LAST) return NULL;
56 return (char*)img_content[c];
57}
58/*****************************************************************************/
59
60/*****************************************************************************/
66 IMG *img
67) {
68 if(img==NULL) return;
69 img->dimt=img->dimx=img->dimy=img->dimz=0;
70 iftInit(&img->ih);
71 iftInit(&img->oh);
75
76 for(int i=0; i<20; i++) img->scanStart[i]=(char)0;
77 for(int i=0; i<MAX_STUDYNR_LEN+1; i++) img->studyNr[i]=(char)0;
78
79
80 img->sizex=img->sizey=img->sizez=0.0;
81 img->gapx=img->gapy=img->gapz=0.0;
82 img->xform[0]=img->xform[1]=0;
83 for(int i=0; i<6; i++) img->quatern[i]=0.0;
84 for(int i=0; i<12; i++) img->srow[i]=0.0;
85 for(int i=0; i<6; i++) img->iop[i]=0.0;
86 for(int i=0; i<3; i++) img->ipp[i]=0.0;
87 for(int i=0; i<12; i++) img->mt[i]=0.0;
88
91
93 img->weight=img->prompts=img->randoms=NULL;
94
95 img->cunit=img->tunit=UNIT_UNKNOWN;
96
97 img->x1=img->x2=img->x=NULL;
98 img->m=(float****)0; img->p=0;
99 img->_z=(float****)0; img->_y=(float***)0; img->_x=(float**)0; img->_t=(float*)0;
100}
101/*****************************************************************************/
102
103/*****************************************************************************/
109 IMG *img
110) {
111 if(img==NULL) return;
112 iftFree(&img->ih);
113 iftFree(&img->oh);
114 free(img->weight); free(img->prompts); free(img->randoms);
115 free(img->x1); free(img->x2); free(img->x);
116 free(img->_t); free(img->_z); free(img->_x); free(img->_y);
117 imgInit(img);
118}
119/*****************************************************************************/
120
121/*****************************************************************************/
129 IMG *img,
131 const unsigned int dimz,
133 const unsigned int dimy,
135 const unsigned int dimx,
137 const unsigned int dimt,
139 TPCSTATUS *status
140) {
141 int verbose=0; if(status!=NULL) verbose=status->verbose;
142 if(verbose>0) {
143 printf("%s(img, %u, %u, %u, %u)\n", __func__, dimz, dimy, dimx, dimt); fflush(stdout);}
144
145 if(img==NULL || dimz<1 || dimy<1 || dimx<1 || dimt<1) {
146 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_FAIL);
147 return(TPCERROR_FAIL);
148 }
149
150 /* Remove any previous contents */
151 imgFree(img);
152
153 /* Memory for frame times */
154 int ret=0; {img->x1=calloc(dimt, sizeof(float)); if(img->x1==NULL) ret++;}
155 if(!ret) {img->x2=calloc(dimt, sizeof(float)); if(img->x2==NULL) ret++;}
156 if(!ret) {img->x=calloc(dimt, sizeof(float)); if(img->x==NULL) ret++;}
157 if(ret) {
158 imgFree(img);
159 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_OUT_OF_MEMORY);
161 }
162
163 /* Memory for weights */
164 ret=0; {img->weight=calloc(dimt, sizeof(float)); if(img->weight==NULL) ret++;}
165 if(!ret) {img->prompts=calloc(dimt, sizeof(float)); if(img->prompts==NULL) ret++;}
166 if(!ret) {img->randoms=calloc(dimt, sizeof(float)); if(img->randoms==NULL) ret++;}
167 if(ret) {
168 imgFree(img);
169 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_OUT_OF_MEMORY);
171 }
172
173 /* Memory for pixel matrix */
174 ret=0; {img->_t=(float*)malloc((size_t)dimz*dimy*dimx*dimt*sizeof(float)); if(img->_t==NULL) ret++;}
175 if(!ret) {img->_x=(float**)malloc((size_t)dimz*dimy*dimx*sizeof(float*)); if(img->_x==NULL) ret++;}
176 if(!ret) {img->_y=(float***)malloc((size_t)dimz*dimy*sizeof(float**)); if(img->_y==NULL) ret++;}
177 if(!ret) {img->_z=(float****)malloc((size_t)dimz*sizeof(float***)); if(img->_z==NULL) ret++;}
178 if(ret) {
179 imgFree(img);
180 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_OUT_OF_MEMORY);
182 }
183 /* Set matrix data pointers */
184 {
185 float ***yptr, **xptr, *tptr;
186 yptr=img->_y; xptr=img->_x; tptr=img->_t;
187 for(unsigned int zi=0; zi<dimz; zi++) {
188 img->_z[zi]=yptr;
189 for(unsigned int yi=0; yi<dimy; yi++) {
190 *yptr++=xptr;
191 for(unsigned int xi=0; xi<dimx; xi++) {
192 *xptr++=tptr; tptr+=dimt;
193 }
194 }
195 }
196 }
197 img->m=img->_z;
198 img->p=img->_t;
199 /* Set all pixel values to zero */
200 for(unsigned int zi=0; zi<dimz; zi++)
201 for(unsigned int yi=0; yi<dimy; yi++)
202 for(unsigned int xi=0; xi<dimx; xi++)
203 for(unsigned int ti=0; ti<dimt; ti++)
204 img->m[zi][yi][xi][ti]=(float)0.0;
205 /* Set matrix dimensions */
206 img->dimz=dimz; img->dimy=dimy; img->dimx=dimx; img->dimt=dimt;
207
208 statusSet(status, __func__, __FILE__, __LINE__, TPCERROR_OK);
209 return(TPCERROR_OK);
210}
211/*****************************************************************************/
212
213/*****************************************************************************/
220 IMG *img
221) {
222 if(img==NULL) return(0);
223 if(img->dimz<1 || img->dimy<1 || img->dimx<1 || img->dimz<1) return(0);
224 if(img->m==NULL || img->p==NULL) return(0);
225 if(img->x1==NULL || img->x2==NULL) return(0);
226 return(1);
227}
228/******************************************************************************/
229
230/******************************************************************************/
237 IMG *img
238) {
239 if(imgHasData(img)==0) return(0);
240 for(int i=0; i<img->dimt; i++) if(img->x2[i]>0.00000001) return(1);
241 return(0);
242}
243/******************************************************************************/
244
245/******************************************************************************/
253 IMG *img
254) {
255 if(img==NULL || img->dimt<1) return(0);
256 int p=0, r=0;
257 /* If image has only one frame, then any value > 0 is fine */
258 if(img->dimt==1) {
259 if(img->prompts[0]>0.000000001) p=1;
260 if(img->randoms[0]>0.000000001) r=2;
261 return(p+r);
262 }
263 /* When more frames, we check that frames have different count level */
264 for(unsigned short int i=1; i<img->dimt; i++) {
265 if(fabsf(img->prompts[i]-img->prompts[i-1])>0.001) p=1;
266 if(fabsf(img->randoms[i]-img->randoms[i-1])>0.001) r=2;
267 if((p+r)>2) break;
268 }
269 return(p+r);
270}
271/******************************************************************************/
272
273/******************************************************************************/
280 IMG *img
281) {
282 if(img==NULL || img->dimt<1) return(0);
283 if(img->weighting==WEIGHTING_UNKNOWN || img->weighting==WEIGHTING_OFF) return(0);
284 if(img->weighting<WEIGHTING_LAST) return(1);
285 return(0);
286}
287/*****************************************************************************/
288
289/*****************************************************************************/
295 IMG *img,
297 FILE *fp
298) {
299 if(fp==NULL) return;
300 if(img==NULL) {fprintf(fp, "IMG pointer is NULL\n"); fflush(fp); return;}
301
302 fprintf(fp, "modality: %s\n", imgModalityDescr(img->modality));
303 fprintf(fp, "content: %s\n", imgContentDescr(img->content));
304 fprintf(fp, "format: %s\n", imgFormatDescr(img->format));
306 fprintf(fp, "output_format: %s\n", imgFormatDescr(img->oformat));
307
308 fprintf(fp, "hasData := %d\n", imgHasData(img));
309 fprintf(fp, "hasTimes := %d\n", imgHasTimes(img));
310 fprintf(fp, "hasCounts := %d\n", imgHasCounts(img));
311
312 if(img->scanStart[0]) fprintf(fp, "scanStart: %s\n", img->scanStart);
313
314 fprintf(fp, "dimensions: %u x %u x %u x %u\n", img->dimx, img->dimy, img->dimz, img->dimt);
315 if(img->sizex!=0.0 || img->sizey!=0.0 || img->sizez!=0.0)
316 fprintf(fp, "voxel_size: %g x %g x %g\n", img->sizex, img->sizey, img->sizez);
317 if(img->gapx!=0.0 || img->gapy!=0.0 || img->gapz!=0.0)
318 fprintf(fp, "voxel_gaps: %g x %g x %g\n", img->gapx, img->gapy, img->gapz);
319
320 fprintf(fp, "qform := %d\n", img->xform[0]);
321 fprintf(fp, "sform := %d\n", img->xform[1]);
322 if(floatNonzeroes(img->quatern, 6)>0) {
323 fprintf(fp, "quatern_b := %g\n", img->quatern[0]);
324 fprintf(fp, "quatern_c := %g\n", img->quatern[1]);
325 fprintf(fp, "quatern_d := %g\n", img->quatern[2]);
326 fprintf(fp, "quatern_x_shift := %g\n", img->quatern[3]);
327 fprintf(fp, "quatern_y_shift := %g\n", img->quatern[4]);
328 fprintf(fp, "quatern_z_shift := %g\n", img->quatern[5]);
329 }
330 if(floatNonzeroes(img->srow, 12)>0) {
331 for(int i=0; i<4; i++) fprintf(fp, "srow_x[%d] := %g\n", i, img->srow[i]);
332 for(int i=0; i<4; i++) fprintf(fp, "srow_y[%d] := %g\n", i, img->srow[4+i]);
333 for(int i=0; i<4; i++) fprintf(fp, "srow_z[%d] := %g\n", i, img->srow[8+i]);
334 }
335 if(floatNonzeroes(img->iop, 6)>0) {
336 fprintf(fp, "image_orientation_patient := %g", img->iop[0]);
337 for(int i=1; i<6; i++) fprintf(fp, ", %g", img->iop[i]);
338 fprintf(fp, "\n");
339 }
340 if(floatNonzeroes(img->ipp, 3)>0) {
341 fprintf(fp, "image_position_patient := %g", img->ipp[0]);
342 for(int i=1; i<3; i++) fprintf(fp, ", %g", img->ipp[i]);
343 fprintf(fp, "\n");
344 }
345 if(floatNonzeroes(img->mt, 3)>0) {
346 fprintf(fp, "image_matrix_transformation_parameters := %g", img->mt[0]);
347 for(int i=1; i<12; i++) fprintf(fp, ", %g", img->mt[i]);
348 fprintf(fp, "\n");
349 }
350
351 if(img->isot!=ISOTOPE_UNKNOWN) fprintf(fp, "isotope: %s\n", isotopeName(img->isot));
352 if(img->decayCorrection==DECAY_CORRECTED) fprintf(fp, "physical_decay: corrected\n");
353 else if(img->decayCorrection==DECAY_NOTCORRECTED) fprintf(fp, "physical_decay: not corrected\n");
354
355 if(imgHasWeights(img)) fprintf(fp, "weighting: no\n");
356 else fprintf(fp, "weighting: yes\n");
357
358 if(img->cunit!=UNIT_UNKNOWN) fprintf(fp, "pixel_unit := %s\n", unitName(img->cunit));
359 if(img->tunit!=UNIT_UNKNOWN) fprintf(fp, "time_unit := %s\n", unitName(img->tunit));
360
361 fprintf(fp, "original header: %d items\n", img->ih.keyNr);
362
363 fflush(fp);
364 return;
365}
366/*****************************************************************************/
367
368/*****************************************************************************/
373unsigned long long imgNaNs(
375 IMG *img,
377 int fix
378) {
379 if(img==NULL) return(0);
380 unsigned long long i, n=0, pxlNr=img->dimt*img->dimz*img->dimy*img->dimx;
381 for(i=0; i<pxlNr; i++) {
382 if(!isfinite(img->p[i])) {
383 n++;
384 if(fix!=0) img->p[i]=0.0;
385 }
386 }
387 return(n);
388}
389/*****************************************************************************/
390
391/*****************************************************************************/
398 IMG *img,
400 float *minvalue,
402 float *maxvalue
403) {
404 if(img==NULL || !imgHasData(img)) return(TPCERROR_FAIL);
405 float f1, f2;
406 f1=f2=nanf("");
407 if(minvalue!=NULL) *minvalue=f1;
408 if(maxvalue!=NULL) *maxvalue=f2;
409 unsigned long long i, n=img->dimt*img->dimz*img->dimy*img->dimx;
410 // search first valid number
411 for(i=0; i<n; i++) if(isfinite(img->p[i])) break;
412 if(i==n) return(TPCERROR_MISSING_DATA);
413 f1=f2=img->p[i++];
414 for(; i<n; i++) {
415 if(img->p[i]>f2) f2=img->p[i];
416 else if(img->p[i]<f1) f1=img->p[i];
417 }
418 if(minvalue!=NULL) *minvalue=f1;
419 if(maxvalue!=NULL) *maxvalue=f2;
420 return(TPCERROR_OK);
421}
422/*****************************************************************************/
423
424/*****************************************************************************/
432 IMG *img,
434 double *xmin,
436 double *xmax
437) {
438 if(xmin!=NULL) *xmin=nan("");
439 if(xmax!=NULL) *xmax=nan("");
440 if(img==NULL || !imgHasData(img)) return(TPCERROR_FAIL);
441 float f1=nanf(""), f2=nanf("");
442 for(int i=0; i<img->dimt; i++) {
443 if(isfinite(img->x1[i])) {
444 if(isnan(f1) || img->x1[i]<f1) f1=img->x1[i];
445 }
446 if(isfinite(img->x2[i])) {
447 if(isnan(f2) || img->x2[i]>f2) f2=img->x2[i];
448 }
449 }
450 if(xmin!=NULL) *xmin=f1;
451 if(xmax!=NULL) *xmax=f2;
452 if(isnan(f1) || isnan(f2)) return(TPCERROR_FAIL);
453 return(TPCERROR_OK);
454}
455/*****************************************************************************/
456
457/*****************************************************************************/
unsigned int floatNonzeroes(float *a, const unsigned int n)
Definition floatutil.c:247
void iftFree(IFT *ift)
Definition ift.c:37
void iftInit(IFT *ift)
Definition ift.c:21
int imgHasData(IMG *img)
Definition image.c:218
char * imgModalityDescr(imgmodality c)
Definition image.c:27
void imgContents(IMG *img, FILE *fp)
Definition image.c:293
void imgFree(IMG *img)
Definition image.c:107
unsigned long long imgNaNs(IMG *img, int fix)
Definition image.c:373
int imgHasWeights(IMG *img)
Definition image.c:278
char * imgContentDescr(imgcontent c)
Definition image.c:51
int imgHasTimes(IMG *img)
Definition image.c:235
int imgHasCounts(IMG *img)
Definition image.c:251
int imgMinMax(IMG *img, float *minvalue, float *maxvalue)
Definition image.c:396
void imgInit(IMG *img)
Definition image.c:64
int imgAllocate(IMG *img, const unsigned int dimz, const unsigned int dimy, const unsigned int dimx, const unsigned int dimt, TPCSTATUS *status)
Definition image.c:126
int imgXRange(IMG *img, double *xmin, double *xmax)
Definition image.c:430
char * imgFormatDescr(imgformat c)
Definition imageio.c:36
char * isotopeName(int isotope_code)
Definition isotope.c:101
void statusSet(TPCSTATUS *s, const char *func, const char *srcfile, int srcline, tpcerror error)
Definition statusmsg.c:142
int keyNr
Definition tpcift.h:47
Definition tpcimage.h:82
float sizex
Definition tpcimage.h:119
unsigned short int dimx
Definition tpcimage.h:112
float * x1
Definition tpcimage.h:180
imgmodality modality
Definition tpcimage.h:100
unit cunit
Definition tpcimage.h:203
float gapx
Definition tpcimage.h:126
float **** m
Definition tpcimage.h:161
imgformat format
Definition tpcimage.h:103
float ipp[3]
Definition tpcimage.h:141
float * x2
Definition tpcimage.h:182
short int xform[2]
Definition tpcimage.h:133
float quatern[6]
Definition tpcimage.h:135
float iop[6]
Definition tpcimage.h:139
float srow[12]
Definition tpcimage.h:137
float * prompts
Definition tpcimage.h:195
unsigned short int dimt
Definition tpcimage.h:110
float sizey
Definition tpcimage.h:121
float * weight
Definition tpcimage.h:193
weights weighting
Definition tpcimage.h:191
IFT ih
Definition tpcimage.h:208
imgcontent content
Definition tpcimage.h:97
char scanStart[20]
Definition tpcimage.h:94
unsigned short int dimz
Definition tpcimage.h:116
unsigned short int dimy
Definition tpcimage.h:114
float * p
Definition tpcimage.h:174
float mt[12]
Definition tpcimage.h:144
float * x
Definition tpcimage.h:184
decaycorrection decayCorrection
Definition tpcimage.h:91
IFT oh
Definition tpcimage.h:210
char studyNr[MAX_STUDYNR_LEN+1]
Definition tpcimage.h:85
float gapy
Definition tpcimage.h:128
float * randoms
Definition tpcimage.h:197
isotope isot
Definition tpcimage.h:88
float gapz
Definition tpcimage.h:130
imgformat oformat
Definition tpcimage.h:105
float sizez
Definition tpcimage.h:123
unit tunit
Definition tpcimage.h:205
int verbose
Verbose level, used by statusPrint() etc.
@ WEIGHTING_OFF
Not weighted or weights not available (weights for all included samples are 1.0).
@ WEIGHTING_UNKNOWN
Not known; usually assumed that not weighted.
@ UNIT_UNKNOWN
Unknown unit.
@ TPCERROR_FAIL
General error.
@ TPCERROR_OUT_OF_MEMORY
Cannot allocate memory.
@ TPCERROR_OK
No error.
@ TPCERROR_MISSING_DATA
File contains missing values.
char * unitName(int unit_code)
Definition units.c:143
#define MAX_STUDYNR_LEN
Define max study number length.
Header file for libtpcimage.
imgmodality
Definition tpcimage.h:56
@ IMG_MODALITY_LAST
End of list.
Definition tpcimage.h:62
@ IMG_MODALITY_UNKNOWN
Unknown modality.
Definition tpcimage.h:57
@ IMG_FORMAT_UNKNOWN
Unknown format.
Definition tpcimage.h:33
imgcontent
Definition tpcimage.h:70
@ IMG_CONTENT_LAST
End of list.
Definition tpcimage.h:76
@ IMG_CONTENT_UNKNOWN
Unknown data content.
Definition tpcimage.h:71
@ DECAY_UNKNOWN
Not known; usually assumed that data is corrected.
Definition tpcisotope.h:79
@ DECAY_NOTCORRECTED
Data is not corrected for physical decay.
Definition tpcisotope.h:80
@ DECAY_CORRECTED
Data is corrected for physical decay.
Definition tpcisotope.h:81
@ ISOTOPE_UNKNOWN
Unknown.
Definition tpcisotope.h:51