TPCCLIB
Loading...
Searching...
No Matches
img_e7.c File Reference

ECAT 7 I/O routines for IMG data. More...

#include "libtpcimgio.h"

Go to the source code of this file.

Functions

int imgReadEcat7 (const char *fname, IMG *img)
int imgWriteEcat7 (const char *fname, IMG *img)
int imgWrite2DEcat7 (const char *fname, IMG *img)
int imgWritePolarmap (const char *fname, IMG *img)
void imgGetEcat7MHeader (IMG *img, ECAT7_mainheader *h)
void imgSetEcat7MHeader (IMG *img, ECAT7_mainheader *h)
int imgGetEcat7Fileformat (ECAT7_mainheader *h)
int imgReadEcat7Header (const char *fname, IMG *img)
int imgEcat7Supported (ECAT7_mainheader *h)
int imgReadEcat7FirstFrame (const char *fname, IMG *img)
int imgReadEcat7Frame (const char *fname, int frame_to_read, IMG *img, int frame_index)
int imgWriteEcat7Frame (const char *fname, int frame_to_write, IMG *img, int frame_index)
void imgSetEcat7SHeader (IMG *img, void *h)

Detailed Description

ECAT 7 I/O routines for IMG data.

Author
Vesa Oikonen

Definition in file img_e7.c.

Function Documentation

◆ imgEcat7Supported()

int imgEcat7Supported ( ECAT7_mainheader * h)

Check whether read functions in IMG library support this ECAT 7.x file_type.

Parameters
hEcat7 main header
Returns
1 if supported, 0 if not.

Definition at line 1036 of file img_e7.c.

1036 {
1037 if(h==NULL) return(0);
1038 if(h->file_type==ECAT7_VOLUME8) return(1);
1039 if(h->file_type==ECAT7_VOLUME16) return(1);
1040 if(h->file_type==ECAT7_IMAGE8) return(1);
1041 if(h->file_type==ECAT7_IMAGE16) return(1);
1042 if(h->file_type==ECAT7_2DSCAN) return(1);
1043 if(h->file_type==ECAT7_3DSCAN) return(1);
1044 if(h->file_type==ECAT7_3DSCAN8) return(1);
1045 if(h->file_type==ECAT7_3DSCANFIT) return(1);
1046 if(h->file_type==ECAT7_POLARMAP) return(1);
1047 return(0);
1048}
#define ECAT7_VOLUME8
#define ECAT7_3DSCAN
#define ECAT7_3DSCAN8
#define ECAT7_IMAGE16
#define ECAT7_3DSCANFIT
#define ECAT7_VOLUME16
#define ECAT7_IMAGE8
#define ECAT7_POLARMAP
#define ECAT7_2DSCAN
short int file_type

Referenced by imgRead(), imgReadEcat7(), imgReadEcat7Frame(), and imgReadEcat7Header().

◆ imgGetEcat7Fileformat()

int imgGetEcat7Fileformat ( ECAT7_mainheader * h)

Return the IMG fileformat based on ECAT7 file_type.

Parameters
hEcat7 main header
Returns
IMG._fileFormat code value

Definition at line 827 of file img_e7.c.

827 {
828 int fileFormat=IMG_UNKNOWN;
829 switch(h->file_type) {
830 case ECAT7_IMAGE8:
831 case ECAT7_IMAGE16:
832 fileFormat=IMG_E7_2D; break;
833 case ECAT7_VOLUME8:
834 case ECAT7_VOLUME16:
835 fileFormat=IMG_E7; break;
836 case ECAT7_2DSCAN:
837 fileFormat=IMG_E7_2D; break;
838 case ECAT7_3DSCAN:
839 case ECAT7_3DSCAN8:
840 case ECAT7_3DSCANFIT:
841 fileFormat=IMG_E7; break;
842 case ECAT7_POLARMAP:
843 fileFormat=IMG_POLARMAP; break;
844 default:
845 fileFormat=IMG_UNKNOWN; break;
846 }
847 return fileFormat;
848}
#define IMG_E7
#define IMG_UNKNOWN
#define IMG_E7_2D
#define IMG_POLARMAP

Referenced by imgReadEcat7Header().

◆ imgGetEcat7MHeader()

void imgGetEcat7MHeader ( IMG * img,
ECAT7_mainheader * h )

Copy ECAT 7 main header information into IMG

Parameters
imgtarget structure
hsource structure

Definition at line 742 of file img_e7.c.

743{
744 img->scanner=h->system_type;
745 imgUnitFromEcat7(img, h);
749 img->axialFOV=10.0*h->distance_scanned;
750 img->transaxialFOV=10.0*h->transaxial_fov;
752 strlcpy(img->patientName, h->patient_name, 32);
753 strncpy(img->patientID, h->patient_id, 16);
754 img->sizez=10.0*h->plane_separation;
755 switch(h->file_type) {
756 case ECAT7_IMAGE8:
757 case ECAT7_IMAGE16:
758 case ECAT7_VOLUME8:
759 case ECAT7_VOLUME16: img->type=IMG_TYPE_IMAGE; break;
760 case ECAT7_POLARMAP: img->type=IMG_TYPE_POLARMAP; break;
761 default: img->type=IMG_TYPE_RAW;
762 }
765 strncpy(img->userProcessCode, h->user_process_code, 10);
766 img->userProcessCode[10]=(char)0;
767 /* If valid study number is found in user_process_code, then take it */
771}
void imgUnitFromEcat7(IMG *img, ECAT7_mainheader *h)
Definition imgunits.c:149
#define IMG_TYPE_RAW
#define IMG_TYPE_POLARMAP
#define IMG_TYPE_IMAGE
size_t strlcpy(char *dst, const char *src, size_t dstsize)
Definition strext.c:245
#define MAX_STUDYNR_LEN
Definition libtpcmisc.h:163
int studynr_validity_check(char *studynr)
Definition studynr.c:196
short int system_type
char study_type[12]
char user_process_code[10]
char patient_name[32]
char study_description[32]
char patient_id[16]
char radiopharmaceutical[32]
short int patient_orientation
float branchingFraction
char type
char patientName[32]
char studyDescription[32]
float transaxialFOV
time_t scanStart
char userProcessCode[11]
char patientID[16]
int scanner
int orientation
char radiopharmaceutical[32]
float isotopeHalflife
char studyNr[MAX_STUDYNR_LEN+1]
float axialFOV
float sizez

Referenced by imgReadEcat7(), and imgReadEcat7Header().

◆ imgReadEcat7()

int imgReadEcat7 ( const char * fname,
IMG * img )

Read ECAT 7 image, volume or 2D sinogram.

Returns
0 if ok, 1 invalid input, 2 image status is not 'initialized', 3 failed to open file field for reading, 4 recognize file, 5 file type not supported, 6 invalid matrix list, 7 invalid number of matrices/frames, 8 variable matrix size, 9 failed to read header, 11 failed to allocate memory for data, 13 failed to read data.
Parameters
fnameName of the input ECAT 7 file.
imgData structure in which the file is read; must be initialized before using this function.

Definition at line 19 of file img_e7.c.

25 {
26 ECAT7_mainheader main_header;
27 ECAT7_imageheader image_header;
28 ECAT7_2Dscanheader scan2d_header;
29 ECAT7_scanheader scan_header;
30 ECAT7_polmapheader polmap_header;
31 ECAT7_MATRIXLIST mlist;
32 ECAT7_Matval matval;
33 float *fdata=NULL, *fptr;
34 int blkNr=0;
35
36
37 if(IMG_TEST) printf("imgReadEcat7(%s, *img)\n", fname);
38 /* Check the arguments */
39 if(fname==NULL) return(1);
40 if(img==NULL || img->status!=IMG_STATUS_INITIALIZED) {
41 imgSetStatus(img, STATUS_FAULT); return(2);}
42
43 /* Open file for read */
44 FILE *fp;
45 if((fp=fopen(fname, "rb"))==NULL) {imgSetStatus(img,STATUS_NOFILE); return(3);}
46
47 /* Read main header */
48 int ret=ecat7ReadMainheader(fp, &main_header);
49 if(ret) {fclose(fp); imgSetStatus(img, STATUS_UNKNOWNFORMAT); return(4);}
50 /* Check for magic number */
51 if(strncmp(main_header.magic_number, ECAT7V_MAGICNR, 7)!=0) {
52 fclose(fp); imgSetStatus(img, STATUS_UNKNOWNFORMAT); return(4);
53 }
54
55 /* Check if file_type is supported */
56 if(imgEcat7Supported(&main_header)==0) {
57 fclose(fp); imgSetStatus(img, STATUS_UNSUPPORTED); return(5);
58 }
59
60 /* Read matrix list */
61 ecat7InitMatlist(&mlist);
62 ret=ecat7ReadMatlist(fp, &mlist, IMG_TEST-1);
63 if(ret || mlist.matrixNr<1 || ecat7CheckMatlist(&mlist)) {
64 if(IMG_TEST) printf(" ret=%d mlist.matrixNr=%d\n", ret, mlist.matrixNr);
65 fclose(fp); imgSetStatus(img, STATUS_INVALIDMATLIST); return(6);}
67 if(IMG_TEST>2) ecat7PrintMatlist(&mlist);
68
69 /* Calculate the number of planes, frames and gates */
70 /* Check that all planes have equal nr of frames (gates) */
71 /* and check that frames (gates) are consequentally numbered */
72 int frame, plane, prev_frame, prev_plane, planeNr, frameNr;
73 prev_plane=plane=-1; prev_frame=frame=-1; frameNr=planeNr=0; ret=0;
74 for(int m=0; m<mlist.matrixNr; m++) {
75 ecat7_id_to_val(mlist.matdir[m].id, &matval); plane=matval.plane;
76 if(main_header.num_frames>=main_header.num_gates) frame=matval.frame;
77 else frame=matval.gate;
78 if(plane!=prev_plane) {frameNr=1; planeNr++;}
79 else {frameNr++; if(prev_frame>0 && frame!=prev_frame+1) {ret=1; break;}}
80 prev_plane=plane; prev_frame=frame;
81 /* Calculate and check the size of one data matrix */
82 if(m==0) {
83 blkNr=mlist.matdir[m].endblk-mlist.matdir[m].strtblk;
84 } else if(blkNr!=mlist.matdir[m].endblk-mlist.matdir[m].strtblk) {
85 ret=2; break;
86 }
87 } /* next matrix */
88 if(IMG_TEST>2) printf("frameNr=%d planeNr=%d\n", frameNr, planeNr);
89 if(ret==1 || (frameNr*planeNr != mlist.matrixNr)) {
90 fclose(fp); imgSetStatus(img, STATUS_MISSINGMATRIX);
91 ecat7EmptyMatlist(&mlist); return(7);
92 }
93 if(ret==2) {
94 fclose(fp); imgSetStatus(img, STATUS_VARMATSIZE);
95 ecat7EmptyMatlist(&mlist); return(8);
96 }
97
98 /* Read the first subheader to get planeNr from volumes and to get x&y dim */
99 int m=0, dimx, dimy, dimz=1;
100 imgSetStatus(img, STATUS_NOSUBHEADER);
101 switch(main_header.file_type) {
102 case ECAT7_IMAGE8:
103 case ECAT7_IMAGE16:
104 case ECAT7_VOLUME8:
105 case ECAT7_VOLUME16:
106 img->type=IMG_TYPE_IMAGE;
107 ret=ecat7ReadImageheader(fp, mlist.matdir[m].strtblk, &image_header);
108 dimx=image_header.x_dimension; dimy=image_header.y_dimension;
109 if(image_header.num_dimensions>2 && image_header.z_dimension>1)
110 planeNr=dimz=image_header.z_dimension;
111 break;
112 case ECAT7_2DSCAN:
113 img->type=IMG_TYPE_RAW;
114 ret=ecat7Read2DScanheader(fp, mlist.matdir[m].strtblk, &scan2d_header);
115 dimx=scan2d_header.num_r_elements; dimy=scan2d_header.num_angles;
116 if(scan2d_header.num_dimensions>2 && scan2d_header.num_z_elements>1)
117 planeNr=dimz=scan2d_header.num_z_elements;
118 break;
119 case ECAT7_3DSCAN:
120 case ECAT7_3DSCAN8:
121 case ECAT7_3DSCANFIT:
122 img->type=IMG_TYPE_RAW;
123 ret=ecat7ReadScanheader(fp, mlist.matdir[m].strtblk, &scan_header);
124 dimx=scan_header.num_r_elements; dimy=scan_header.num_angles;
125 dimz=0;
126 for(int i=0; i<64; i++) dimz+=scan_header.num_z_elements[i];
127 planeNr=dimz;
128 /*if(scan_header.axial_compression!=0) {
129 img->statmsg=imgmsg[STATUS_UNSUPPORTEDAXIALCOMP]; ret=-1;}*/
130 break;
131 case ECAT7_POLARMAP:
133 ret=ecat7ReadPolmapheader(fp, mlist.matdir[m].strtblk, &polmap_header);
134 planeNr=dimz=dimy=1; dimx=0;
135 for(int i=0; i<polmap_header.num_rings; i++)
136 dimx+=polmap_header.sectors_per_ring[i];
137 break;
138 default: dimx=dimy=dimz=planeNr=0; ret=-1;
139 }
140 long long pxlNr=dimx*dimy;
141 if(ret || pxlNr<1 || planeNr<1) {
142 fclose(fp); ecat7EmptyMatlist(&mlist); return(9);}
143 imgSetStatus(img, STATUS_OK);
144
145 /* Allocate memory for IMG data */
146 ret=imgAllocate(img, planeNr, dimy, dimx, frameNr);
147 if(ret) {
148 fclose(fp); imgSetStatus(img, STATUS_NOMEMORY);
149 ecat7EmptyMatlist(&mlist); return(11);
150 }
151 /* Copy information from mainheader */
152 imgGetEcat7MHeader(img, &main_header);
153 /* Set fileFormat */
154 switch(main_header.file_type) {
155 case ECAT7_IMAGE8:
156 case ECAT7_IMAGE16:
157 img->_fileFormat=IMG_E7_2D; break;
158 case ECAT7_VOLUME8:
159 case ECAT7_VOLUME16:
160 img->_fileFormat=IMG_E7; break;
161 case ECAT7_2DSCAN:
162 img->_fileFormat=IMG_E7_2D; break;
163 case ECAT7_3DSCAN:
164 case ECAT7_3DSCAN8:
165 case ECAT7_3DSCANFIT:
166 img->_fileFormat=IMG_E7; break;
167 case ECAT7_POLARMAP:
168 img->_fileFormat=IMG_POLARMAP; break;
169 default:
170 img->_fileFormat=IMG_UNKNOWN; break;
171 }
172
173 if(dimz>1) {
174 /* Read ECAT volume matrices */
175 int fi=0;
176 for(int m=0; m<mlist.matrixNr; m++) {
177 /* Get matrix values */
178 ecat7_id_to_val(mlist.matdir[m].id, &matval);
179 /* Read subheader and data */
180 if(img->type==IMG_TYPE_IMAGE)
181 ret=ecat7ReadImageMatrix(fp, mlist.matdir[m].strtblk,
182 mlist.matdir[m].endblk, &image_header, &fdata);
183 else
184 ret=ecat7ReadScanMatrix(fp, mlist.matdir[m].strtblk,
185 mlist.matdir[m].endblk, &scan_header, &fdata);
186 if(ret || fdata==NULL) {
187 if(IMG_TEST) printf("ecat7ReadXMatrix()=%d\n%s\n", ret, ecat7errmsg);
188 fclose(fp); imgSetStatus(img, STATUS_NOMATRIX);
189 ecat7EmptyMatlist(&mlist); return(13);
190 }
191 /* Copy subheader information */
192 if(img->type==IMG_TYPE_POLARMAP) {
193 img->_dataType=polmap_header.data_type;
194 img->start[fi]=polmap_header.frame_start_time/1000.;
195 img->end[fi]=img->start[fi]+polmap_header.frame_duration/1000.;
196 img->mid[fi]=0.5*(img->start[fi]+img->end[fi]);
197 img->sizex=0.001*polmap_header.pixel_size;
198 } else if(img->type==IMG_TYPE_IMAGE) {
199 img->_dataType=image_header.data_type;
200 img->start[fi]=image_header.frame_start_time/1000.;
201 img->end[fi]=img->start[fi]+image_header.frame_duration/1000.;
202 img->mid[fi]=0.5*(img->start[fi]+img->end[fi]);
203 if(image_header.decay_corr_fctr>1.0) {
204 img->decayCorrFactor[fi]=image_header.decay_corr_fctr;
206 } else {
207 img->decayCorrFactor[fi]=0.0;
209 }
210 img->zoom=image_header.recon_zoom;
211 img->sizex=10.*image_header.x_pixel_size;
212 img->sizey=10.*image_header.y_pixel_size;
213 img->sizez=10.*image_header.z_pixel_size;
214 img->resolutionx=10.*image_header.x_resolution;
215 img->resolutiony=10.*image_header.y_resolution;
216 img->resolutionz=10.*image_header.z_resolution;
217 img->xform[0]=NIFTI_XFORM_UNKNOWN; // qform
218 img->xform[1]=NIFTI_XFORM_SCANNER_ANAT; // sform
219 img->quatern[6]=img->sizex; img->quatern[9]=img->sizex;
220 img->quatern[11]=img->sizey; img->quatern[13]=img->sizey;
221 img->quatern[16]=img->sizez; img->quatern[17]=img->sizez;
222 img->mt[0]=image_header.mt_1_1;
223 img->mt[1]=image_header.mt_1_2;
224 img->mt[2]=image_header.mt_1_3;
225 img->mt[3]=image_header.mt_1_4;
226 img->mt[4]=image_header.mt_2_1;
227 img->mt[5]=image_header.mt_2_2;
228 img->mt[6]=image_header.mt_2_3;
229 img->mt[7]=image_header.mt_2_4;
230 img->mt[8]=image_header.mt_3_1;
231 img->mt[9]=image_header.mt_3_2;
232 img->mt[10]=image_header.mt_3_3;
233 img->mt[11]=image_header.mt_3_4;
234 } else {
235 img->_dataType=scan_header.data_type;
236 img->start[fi]=scan_header.frame_start_time/1000.;
237 img->end[fi]=img->start[fi]+scan_header.frame_duration/1000.;
238 img->mid[fi]=0.5*(img->start[fi]+img->end[fi]);
239 if(scan_header.x_resolution>0.0)
240 img->sampleDistance=10.0*scan_header.x_resolution;
241 else
242 img->sampleDistance=10.0*main_header.bin_size;
243 /* also, correct for dead-time */
244 if(scan_header.deadtime_correction_factor>0.0) {
245 fptr=fdata;
246 for(long long i=0; i<dimz*pxlNr; i++, fptr++)
247 *fptr*=scan_header.deadtime_correction_factor;
248 }
249 img->prompts[fi]=(float)scan_header.prompts;
250 img->randoms[fi]=scan_header.delayed;
251 }
252 /* Copy matrix data through volume planes */
253 for(int pi=0; pi<dimz; pi++) {
254 fptr=fdata+pi*pxlNr;
255 for(int yi=0; yi<dimy; yi++)
256 for(int xi=0; xi<dimx; xi++)
257 img->m[pi][yi][xi][fi]= *fptr++;
258 }
259 free(fdata); fi++;
260 } /* next matrix */
261 /* Set plane numbers */
262 for(int pi=0; pi<dimz; pi++) img->planeNumber[pi]=pi+1;
263 } else {
264 /* Read separate matrices */
265 prev_plane=plane=-1; prev_frame=frame=-1;
266 int pi=-1, fi=-1;
267 for(int m=0; m<mlist.matrixNr; m++) {
268 ecat7_id_to_val(mlist.matdir[m].id, &matval); plane=matval.plane;
269 if(main_header.num_frames>=main_header.num_gates) frame=matval.frame;
270 else frame=matval.gate;
271 if(plane!=prev_plane) {fi=0; pi++;} else fi++;
272 /* Read subheader and data */
273 if(img->type==IMG_TYPE_POLARMAP)
274 ret=ecat7ReadPolarmapMatrix(fp, mlist.matdir[m].strtblk,
275 mlist.matdir[m].endblk, &polmap_header, &fdata);
276 else if(img->type==IMG_TYPE_IMAGE)
277 ret=ecat7ReadImageMatrix(fp, mlist.matdir[m].strtblk,
278 mlist.matdir[m].endblk, &image_header, &fdata);
279 else
280 ret=ecat7Read2DScanMatrix(fp, mlist.matdir[m].strtblk,
281 mlist.matdir[m].endblk, &scan2d_header, &fdata);
282 if(ret || fdata==NULL) {
283 fclose(fp); imgSetStatus(img, STATUS_NOMATRIX);
284 ecat7EmptyMatlist(&mlist); return(13);
285 }
286 /* Copy subheader information */
287 if(fi==0) img->planeNumber[pi]=plane;
288 if(img->type==IMG_TYPE_POLARMAP) {
289 img->_dataType=polmap_header.data_type;
290 img->start[fi]=polmap_header.frame_start_time/1000.;
291 img->end[fi]=img->start[fi]+polmap_header.frame_duration/1000.;
292 img->mid[fi]=0.5*(img->start[fi]+img->end[fi]);
293 img->sizex=0.001*polmap_header.pixel_size;
294 } else if(img->type==IMG_TYPE_IMAGE) {
295 img->_dataType=image_header.data_type;
296 img->start[fi]=image_header.frame_start_time/1000.;
297 img->end[fi]=img->start[fi]+image_header.frame_duration/1000.;
298 img->mid[fi]=0.5*(img->start[fi]+img->end[fi]);
299 if(image_header.decay_corr_fctr>1.0) {
300 img->decayCorrFactor[fi]=image_header.decay_corr_fctr;
302 } else {
303 img->decayCorrFactor[fi]=0.0;
305 }
306 img->zoom=image_header.recon_zoom;
307 img->sizex=10.*image_header.x_pixel_size;
308 img->sizey=10.*image_header.y_pixel_size;
309 img->sizez=10.*image_header.z_pixel_size;
310 img->resolutionx=10.*image_header.x_resolution;
311 img->resolutiony=10.*image_header.y_resolution;
312 img->resolutionz=10.*image_header.z_resolution;
313 img->xform[0]=NIFTI_XFORM_UNKNOWN; // qform
314 img->xform[1]=NIFTI_XFORM_SCANNER_ANAT; // sform
315 img->quatern[6]=img->sizex; img->quatern[9]=img->sizex;
316 img->quatern[11]=img->sizey; img->quatern[13]=img->sizey;
317 img->quatern[16]=img->sizez; img->quatern[17]=img->sizez;
318 img->mt[0]=image_header.mt_1_1;
319 img->mt[1]=image_header.mt_1_2;
320 img->mt[2]=image_header.mt_1_3;
321 img->mt[3]=image_header.mt_1_4;
322 img->mt[4]=image_header.mt_2_1;
323 img->mt[5]=image_header.mt_2_2;
324 img->mt[6]=image_header.mt_2_3;
325 img->mt[7]=image_header.mt_2_4;
326 img->mt[8]=image_header.mt_3_1;
327 img->mt[9]=image_header.mt_3_2;
328 img->mt[10]=image_header.mt_3_3;
329 img->mt[11]=image_header.mt_3_4;
330 } else {
331 img->_dataType=scan2d_header.data_type;
332 img->start[fi]=scan2d_header.frame_start_time/1000.;
333 img->end[fi]=img->start[fi]+scan2d_header.frame_duration/1000.;
334 img->mid[fi]=0.5*(img->start[fi]+img->end[fi]);
335 if(scan_header.x_resolution>0.0)
336 img->sampleDistance=10.0*scan_header.x_resolution;
337 else
338 img->sampleDistance=10.0*main_header.bin_size;
339 /* also, correct for dead-time */
340 if(scan2d_header.deadtime_correction_factor>0.0) {
341 fptr=fdata;
342 for(long long i=0; i<pxlNr; i++, fptr++)
343 *fptr*=scan2d_header.deadtime_correction_factor;
344 }
345 img->prompts[fi]=(float)scan_header.prompts;
346 img->randoms[fi]=scan_header.delayed;
347 }
348 /* Copy matrix data */
349 fptr=fdata;
350 for(int yi=0; yi<dimy; yi++) for(int xi=0; xi<dimx; xi++)
351 img->m[pi][yi][xi][fi]= *fptr++;
352 free(fdata);
353 /* prepare for the next matrix */
354 prev_plane=plane; prev_frame=frame;
355 } /* next matrix */
356 }
357 fclose(fp); ecat7EmptyMatlist(&mlist);
358
359 /* Calibrate */
360 if(main_header.ecat_calibration_factor>0.0)
361 for(int pi=0; pi<img->dimz; pi++)
362 for(int yi=0; yi<img->dimy; yi++) for(int xi=0; xi<img->dimx; xi++)
363 for(int fi=0; fi<img->dimt; fi++)
364 img->m[pi][yi][xi][fi]*=main_header.ecat_calibration_factor;
365
366 imgSetStatus(img, STATUS_OK);
367 return(0);
368}
char ecat7errmsg[128]
Definition ecat7h.c:7
void ecat7InitMatlist(ECAT7_MATRIXLIST *mlist)
Definition ecat7ml.c:15
void ecat7SortMatlistByPlane(ECAT7_MATRIXLIST *ml)
Definition ecat7ml.c:277
void ecat7_id_to_val(int matrix_id, ECAT7_Matval *matval)
Definition ecat7ml.c:262
int ecat7ReadMatlist(FILE *fp, ECAT7_MATRIXLIST *ml, int verbose)
Definition ecat7ml.c:41
void ecat7EmptyMatlist(ECAT7_MATRIXLIST *mlist)
Definition ecat7ml.c:26
void ecat7PrintMatlist(ECAT7_MATRIXLIST *ml)
Definition ecat7ml.c:112
int ecat7CheckMatlist(ECAT7_MATRIXLIST *ml)
Definition ecat7ml.c:329
int ecat7Read2DScanMatrix(FILE *fp, int first_block, int last_block, ECAT7_2Dscanheader *h, float **fdata)
Definition ecat7r.c:959
int ecat7ReadScanheader(FILE *fp, int blk, ECAT7_scanheader *h)
Definition ecat7r.c:536
int ecat7ReadPolmapheader(FILE *fp, int blk, ECAT7_polmapheader *h)
Definition ecat7r.c:397
int ecat7ReadMainheader(FILE *fp, ECAT7_mainheader *h)
Definition ecat7r.c:15
int ecat7ReadPolarmapMatrix(FILE *fp, int first_block, int last_block, ECAT7_polmapheader *h, float **fdata)
Definition ecat7r.c:1154
int ecat7Read2DScanheader(FILE *fp, int blk, ECAT7_2Dscanheader *h)
Definition ecat7r.c:631
int ecat7ReadImageMatrix(FILE *fp, int first_block, int last_block, ECAT7_imageheader *h, float **fdata)
Definition ecat7r.c:858
int ecat7ReadImageheader(FILE *fp, int blk, ECAT7_imageheader *h)
Definition ecat7r.c:162
int ecat7ReadScanMatrix(FILE *fp, int first_block, int last_block, ECAT7_scanheader *h, float **fdata)
Definition ecat7r.c:1055
int IMG_TEST
Definition img.c:6
int imgAllocate(IMG *image, int planes, int rows, int columns, int frames)
Definition img.c:194
void imgSetStatus(IMG *img, int status_index)
Definition img.c:345
void imgGetEcat7MHeader(IMG *img, ECAT7_mainheader *h)
Definition img_e7.c:742
int imgEcat7Supported(ECAT7_mainheader *h)
Definition img_e7.c:1036
#define NIFTI_XFORM_UNKNOWN
#define IMG_DC_UNKNOWN
#define IMG_DC_CORRECTED
#define IMG_STATUS_INITIALIZED
#define NIFTI_XFORM_SCANNER_ANAT
float deadtime_correction_factor
short int num_z_elements
short int num_r_elements
short int num_dimensions
ECAT7_MatDir * matdir
short int y_dimension
short int z_dimension
short int num_dimensions
short int x_dimension
short int data_type
short int num_frames
char magic_number[14]
short int num_gates
float ecat_calibration_factor
short int sectors_per_ring[32]
short int num_r_elements
short int num_angles
short int data_type
float deadtime_correction_factor
short int num_z_elements[64]
float sizex
unsigned short int dimx
float resolutionx
float resolutiony
float sampleDistance
float **** m
char decayCorrection
short int xform[2]
char status
int _fileFormat
float * prompts
unsigned short int dimt
int _dataType
int * planeNumber
float sizey
float * start
unsigned short int dimz
unsigned short int dimy
float * end
float mt[12]
float quatern[18]
float zoom
float * decayCorrFactor
float * randoms
float * mid
float resolutionz

Referenced by imgRead().

◆ imgReadEcat7FirstFrame()

int imgReadEcat7FirstFrame ( const char * fname,
IMG * img )

Read the first frame from an ECAT 7 file into IMG data structure.

Parameters
fnamename of file from which IMG contents will be read
imgpointer to the initiated but not preallocated IMG data
Returns
errstatus, which is STATUS_OK (0) when call was successful, and >0 in case of an error.

Definition at line 1060 of file img_e7.c.

1060 {
1061 int ret=0;
1062
1063 if(IMG_TEST) printf("\nimgReadEcat7FirstFrame(%s, *img)\n", fname);
1064 /* Check the input */
1065 if(img==NULL) return STATUS_FAULT;
1066 if(img->status!=IMG_STATUS_INITIALIZED) return STATUS_FAULT;
1067 imgSetStatus(img, STATUS_FAULT);
1068 if(fname==NULL) return STATUS_FAULT;
1069
1070 /* Read header information from file */
1071 ret=imgReadEcat7Header(fname, img); if(ret) return(ret);
1072 if(IMG_TEST>3) imgInfo(img);
1073
1074 /* Allocate memory for one frame */
1075 img->dimt=1;
1076 ret=imgAllocate(img, img->dimz, img->dimy, img->dimx, img->dimt);
1077 if(ret) return STATUS_NOMEMORY;
1078
1079 /* Read the first frame */
1080 ret=imgReadEcat7Frame(fname, 1, img, 0); if(ret) return(ret);
1081
1082 /* All went well */
1083 imgSetStatus(img, STATUS_OK);
1084 return STATUS_OK;
1085}
void imgInfo(IMG *image)
Definition img.c:359
int imgReadEcat7Frame(const char *fname, int frame_to_read, IMG *img, int frame_index)
Definition img_e7.c:1103
int imgReadEcat7Header(const char *fname, IMG *img)
Definition img_e7.c:860

◆ imgReadEcat7Frame()

int imgReadEcat7Frame ( const char * fname,
int frame_to_read,
IMG * img,
int frame_index )

Read a specified frame from an ECAT 7 file into preallocated IMG data structure. IMG header is assumed to be filled correctly before calling this function, except for information concerning separate planes and this frame, which is filled here. If frame does not exist, then and only then STATUS_NOMATRIX is returned.

Parameters
fnamename of file from which IMG contents will be read
frame_to_readframe which will be read [1..frameNr]
imgpointer to the IMG data. Place for the frame must be preallocated
frame_indexIMG frame index [0..dimt-1] where data will be placed
Returns
errstatus, which is STATUS_OK (0) when call was successful, and >0 in case of an error.

Definition at line 1103 of file img_e7.c.

1105 {
1106 FILE *fp;
1107 int ret, frame, plane, seqplane;
1108 /* int blkNr=0; */
1109 ECAT7_mainheader main_header;
1110 ECAT7_imageheader image_header;
1111 ECAT7_2Dscanheader scan2d_header;
1112 ECAT7_scanheader scan_header;
1113 ECAT7_polmapheader polmap_header;
1114 ECAT7_MATRIXLIST mlist;
1115 ECAT7_Matval matval;
1116 float *fdata=NULL, *fptr;
1117
1118
1119 if(IMG_TEST) printf("\nimgReadEcat7Frame(%s, %d, *img, %d)\n",
1120 fname, frame_to_read, frame_index);
1121
1122 /* Check the input */
1123 if(img==NULL) return STATUS_FAULT;
1124 if(img->status!=IMG_STATUS_OCCUPIED) return STATUS_FAULT;
1125 if(fname==NULL) return STATUS_FAULT;
1126 if(frame_index<0 || frame_index>img->dimt-1) return STATUS_FAULT;
1127 if(frame_to_read<1) return STATUS_FAULT;
1128
1129 /* Open file for read */
1130 if((fp=fopen(fname, "rb")) == NULL) return STATUS_NOFILE;
1131
1132 /* Read main header */
1133 ret=ecat7ReadMainheader(fp, &main_header);
1134 if(ret) {fclose(fp); return STATUS_NOMAINHEADER;}
1135 /* Check for magic number */
1136 if(strncmp(main_header.magic_number, ECAT7V_MAGICNR, 7)!=0) {
1137 fclose(fp); return STATUS_UNKNOWNFORMAT;}
1138 /* Check if file_type is supported */
1139 if(imgEcat7Supported(&main_header)==0) {
1140 fclose(fp); return STATUS_UNSUPPORTED;}
1141 /* Read matrix list and nr and sort it */
1142 ecat7InitMatlist(&mlist);
1143 ret=ecat7ReadMatlist(fp, &mlist, IMG_TEST-1);
1144 if(ret) {fclose(fp); return STATUS_NOMATLIST;}
1145 if(mlist.matrixNr<=0 || ecat7CheckMatlist(&mlist)) {
1146 fclose(fp); ecat7EmptyMatlist(&mlist); return STATUS_INVALIDMATLIST;}
1147 /* Make sure that plane and frame numbers are continuous */
1148 ecat7GatherMatlist(&mlist, 1, 1, 1, 1);
1149 ecat7SortMatlistByFrame(&mlist); /* printf("matlist sorted\n"); */
1150 /* Calculate and check the size of one data matrix */
1151 /*ret=ecat7GetMatrixBlockSize(&mlist, &blkNr);
1152 if(ret) {fclose(fp); return ret;}*/
1153
1154 /* Read all matrices that belong to the required frame */
1155 /*blkNr=-1;*/
1156 ret=0; seqplane=-1;
1157 long long pxlNr=img->dimx*img->dimy;
1158 for(int m=0; m<mlist.matrixNr; m++) {
1159 /* get frame and plane */
1160 ecat7_id_to_val(mlist.matdir[m].id, &matval); plane=matval.plane;
1161 if(main_header.num_frames>=main_header.num_gates) frame=matval.frame;
1162 else frame=matval.gate; /* printf("frame=%d plane=%d\n", frame, plane); */
1163 if(frame!=frame_to_read) continue; /* do not process other frames */
1164 /*if(img->dimz>1) seqplane++; else seqplane=plane-1; */
1165 if(img->_fileFormat==IMG_E7_2D) seqplane=plane-1; else seqplane++;
1166
1167 /* Read subheader and data */
1168 if(IMG_TEST>4) printf("reading matrix %d,%d\n", frame, plane);
1169 if(img->type==IMG_TYPE_IMAGE) { /* 2D or 3D image */
1170 ret=ecat7ReadImageMatrix(fp, mlist.matdir[m].strtblk,
1171 mlist.matdir[m].endblk, &image_header, &fdata);
1172 } else if(img->type==IMG_TYPE_POLARMAP) { /* polarmap */
1173 ret=ecat7ReadPolarmapMatrix(fp, mlist.matdir[m].strtblk,
1174 mlist.matdir[m].endblk, &polmap_header, &fdata);
1175 } else if(img->dimz>1) { /* 3D sinogram */
1176 ret=ecat7ReadScanMatrix(fp, mlist.matdir[m].strtblk,
1177 mlist.matdir[m].endblk, &scan_header, &fdata);
1178 } else { /* 2D sinogram */
1179 ret=ecat7Read2DScanMatrix(fp, mlist.matdir[m].strtblk,
1180 mlist.matdir[m].endblk, &scan2d_header, &fdata);
1181 }
1182 if(ret || fdata==NULL) {
1183 fclose(fp); ecat7EmptyMatlist(&mlist); return STATUS_NOMATRIX;}
1184
1185 /* Copy information concerning this frame and make correction to data */
1186 if(img->type==IMG_TYPE_IMAGE) {
1187 img->start[frame_index]=image_header.frame_start_time/1000.;
1188 img->end[frame_index]=
1189 img->start[frame_index]+image_header.frame_duration/1000.;
1190 img->mid[frame_index]=0.5*(img->start[frame_index]+img->end[frame_index]);
1191 if(image_header.decay_corr_fctr>1.0) {
1192 img->decayCorrFactor[frame_index]=image_header.decay_corr_fctr;
1194 } else {
1195 img->decayCorrFactor[frame_index]=0.0;
1197 }
1198 } else if(img->type==IMG_TYPE_POLARMAP) { /* polarmap */
1199 img->start[frame_index]=polmap_header.frame_start_time/1000.;
1200 img->end[frame_index]=
1201 img->start[frame_index]+polmap_header.frame_duration/1000.;
1202 img->mid[frame_index]=0.5*(img->start[frame_index]+img->end[frame_index]);
1203 } else if(img->dimz>1) {
1204 img->start[frame_index]=scan_header.frame_start_time/1000.;
1205 img->end[frame_index]=
1206 img->start[frame_index]+scan_header.frame_duration/1000.;
1207 img->mid[frame_index]=0.5*(img->start[frame_index]+img->end[frame_index]);
1208 /* also, correct for dead-time */
1209 if(scan_header.deadtime_correction_factor>0.0) {
1210 fptr=fdata;
1211 for(long long i=0; i<img->dimz*pxlNr; i++, fptr++)
1212 *fptr*=scan_header.deadtime_correction_factor;
1213 }
1214 img->prompts[frame_index]=(float)scan_header.prompts;
1215 img->randoms[frame_index]=scan_header.delayed;
1216 } else {
1217 img->start[frame_index]=scan2d_header.frame_start_time/1000.;
1218 img->end[frame_index]=
1219 img->start[frame_index]+scan2d_header.frame_duration/1000.;
1220 img->mid[frame_index]=0.5*(img->start[frame_index]+img->end[frame_index]);
1221 /* also, correct for dead-time */
1222 if(scan2d_header.deadtime_correction_factor>0.0) {
1223 fptr=fdata;
1224 for(long long i=0; i<pxlNr; i++, fptr++)
1225 *fptr*=scan2d_header.deadtime_correction_factor;
1226 }
1227 img->prompts[frame_index]=(float)scan2d_header.prompts;
1228 img->randoms[frame_index]=scan2d_header.delayed;
1229 }
1230 /* Copy matrix data through volume planes */
1231 if(img->_fileFormat!=IMG_E7_2D) {
1232 /* if(img->dimz>1) { */
1233 for(int pi=0; pi<img->dimz; pi++) {
1234 if(IMG_TEST>5)
1235 printf(" putting data into m[%d][][][%d]\n", pi, frame_index);
1236 fptr=fdata+pi*pxlNr;
1237 for(int yi=0; yi<img->dimy; yi++)
1238 for(int xi=0; xi<img->dimx; xi++)
1239 img->m[pi][yi][xi][frame_index]= *fptr++;
1240 }
1241 } else {
1242 if(IMG_TEST>5)
1243 printf(" putting data into m[%d][][][%d]\n", seqplane, frame_index);
1244 fptr=fdata;
1245 for(int yi=0; yi<img->dimy; yi++)
1246 for(int xi=0; xi<img->dimx; xi++)
1247 img->m[seqplane][yi][xi][frame_index]= *fptr++;
1248 img->planeNumber[seqplane]=plane;
1249 }
1250 free(fdata);
1251 /* Calibrate */
1252 if(main_header.ecat_calibration_factor>0.0)
1253 for(int pi=0; pi<img->dimz; pi++)
1254 for(int yi=0; yi<img->dimy; yi++) for(int xi=0; xi<img->dimx; xi++)
1255 img->m[pi][yi][xi][frame_index]*=main_header.ecat_calibration_factor;
1256 } /* next matrix */
1257 if(IMG_TEST>3) printf("end of matrices.\n");
1258 ecat7EmptyMatlist(&mlist);
1259 fclose(fp);
1260
1261 /* seqplane is <0 only if this frame did not exist at all; return -1 */
1262 if(IMG_TEST>4) printf("last_seqplane := %d.\n", seqplane);
1263 if(seqplane<0) return STATUS_NOMATRIX;
1264
1265 /* check that correct number of planes was read */
1266 if(seqplane>0 && (seqplane+1 != img->dimz)) return STATUS_MISSINGMATRIX;
1267
1268 /* All went well */
1269 imgSetStatus(img, STATUS_OK);
1270 return STATUS_OK;
1271}
void ecat7SortMatlistByFrame(ECAT7_MATRIXLIST *ml)
Definition ecat7ml.c:303
int ecat7GatherMatlist(ECAT7_MATRIXLIST *ml, short int do_planes, short int do_frames, short int do_gates, short int do_beds)
Definition ecat7ml.c:535
#define IMG_STATUS_OCCUPIED

Referenced by imgReadEcat7FirstFrame(), and imgReadFrame().

◆ imgReadEcat7Header()

int imgReadEcat7Header ( const char * fname,
IMG * img )

Fill IMG struct header information from an image or sinogram file in ECAT 7 format. Information concerning separate frames or planes is not filled.

Parameters
fnameimage or sinogram filename
imgpointer to initialized IMG structure
Returns
errstatus, which is STATUS_OK (0) when call was successful, and >0 in case of an error.

Definition at line 860 of file img_e7.c.

860 {
861 FILE *fp;
862 int ret, m;
863 int planeNr, frameNr, blkNr=0;
864 ECAT7_mainheader main_header;
865 ECAT7_imageheader image_header;
866 ECAT7_2Dscanheader scan2d_header;
867 ECAT7_scanheader scan_header;
868 ECAT7_polmapheader polmap_header;
869 ECAT7_MATRIXLIST mlist;
870
871
872 if(IMG_TEST) printf("\nimgReadEcat7Header(%s, *img)\n", fname);
873
874 /* Check the arguments */
875 if(img==NULL) return STATUS_FAULT;
876 if(img->status!=IMG_STATUS_INITIALIZED) return STATUS_FAULT;
877 imgSetStatus(img, STATUS_FAULT);
878 if(fname==NULL) return STATUS_FAULT;
879
880 /* Open the file */
881 if((fp=fopen(fname, "rb")) == NULL) return STATUS_NOFILE;
882
883 /* Read main header */
884 ret=ecat7ReadMainheader(fp, &main_header);
885 if(ret) {fclose(fp); return STATUS_NOMAINHEADER;}
886 /* Check for magic number */
887 if(strncmp(main_header.magic_number, ECAT7V_MAGICNR, 7)!=0) {
888 fclose(fp); return STATUS_UNKNOWNFORMAT;}
889 /* Check if file_type is supported */
890 if(imgEcat7Supported(&main_header)==0) {fclose(fp); return STATUS_UNSUPPORTED;}
891 /* Copy main header information into IMG; sets also img.type */
892 imgGetEcat7MHeader(img, &main_header);
893 if(IMG_TEST>7) printf("img.type := %d\n", img->type);
894 img->_fileFormat=imgGetEcat7Fileformat(&main_header);
895 if(IMG_TEST>7) printf("img._fileFormat := %d\n", img->_fileFormat);
896 if(img->_fileFormat==IMG_UNKNOWN) {fclose(fp); return STATUS_UNSUPPORTED;}
897
898 /* Read matrix list */
899 ecat7InitMatlist(&mlist);
900 ret=ecat7ReadMatlist(fp, &mlist, IMG_TEST-1);
901 if(ret || mlist.matrixNr<1 || ecat7CheckMatlist(&mlist)) {
902 fclose(fp); return STATUS_INVALIDMATLIST;}
903 /* Make sure that plane and frame numbers are continuous */
904 ecat7GatherMatlist(&mlist, 1, 1, 1, 1);
905 /* Get plane and frame numbers and check that volume is full */
906 ret=ecat7GetPlaneAndFrameNr(&mlist, &main_header, &planeNr, &frameNr);
907 if(ret) {ecat7EmptyMatlist(&mlist); fclose(fp); return ret;}
908 img->dimz=planeNr;
909 img->dimt=frameNr;
910 /* Get and check the size of data matrices */
911 ret=ecat7GetMatrixBlockSize(&mlist, &blkNr);
912 if(ret) {ecat7EmptyMatlist(&mlist); fclose(fp); return ret;}
913
914 /* Read one subheader */
915 if(IMG_TEST>5) printf("main_header.file_type := %d\n", main_header.file_type);
916 m=0;
917 switch(main_header.file_type) {
918 case ECAT7_IMAGE8:
919 case ECAT7_IMAGE16:
920 case ECAT7_VOLUME8:
921 case ECAT7_VOLUME16:
922 ret=ecat7ReadImageheader(fp, mlist.matdir[m].strtblk, &image_header);
923 break;
924 case ECAT7_2DSCAN:
925 ret=ecat7Read2DScanheader(fp, mlist.matdir[m].strtblk, &scan2d_header);
926 break;
927 case ECAT7_3DSCAN:
928 case ECAT7_3DSCAN8:
929 case ECAT7_3DSCANFIT:
930 ret=ecat7ReadScanheader(fp, mlist.matdir[m].strtblk, &scan_header);
931 break;
932 case ECAT7_POLARMAP:
933 ret=ecat7ReadPolmapheader(fp, mlist.matdir[m].strtblk, &polmap_header);
934 break;
935 default: ret=-1;
936 }
937 /* Free locally allocated memory and close the file */
938 ecat7EmptyMatlist(&mlist); fclose(fp);
939 /* Check whether subheader was read */
940 if(ret) return STATUS_NOSUBHEADER;
941
942 /* Get the following information in the subheader:
943 dimensions x, y and z; datatype;
944 image decay correction on/off, zoom, pixel size and resolution;
945 sinogram sample distance; matrix transformation parameters.
946 */
947 switch(main_header.file_type) {
948 case ECAT7_IMAGE8:
949 case ECAT7_IMAGE16:
950 case ECAT7_VOLUME8:
951 case ECAT7_VOLUME16:
952 img->dimx=image_header.x_dimension; img->dimy=image_header.y_dimension;
953 if(image_header.num_dimensions>2 && image_header.z_dimension>1)
954 /*planeNr=*/ img->dimz=image_header.z_dimension;
955 img->_dataType=image_header.data_type;
956 if(image_header.decay_corr_fctr>1.0) img->decayCorrection=IMG_DC_CORRECTED;
957 img->zoom=image_header.recon_zoom;
958 img->sizex=10.*image_header.x_pixel_size;
959 img->sizey=10.*image_header.y_pixel_size;
960 img->sizez=10.*image_header.z_pixel_size;
961 img->resolutionx=10.*image_header.x_resolution;
962 img->resolutiony=10.*image_header.y_resolution;
963 img->resolutionz=10.*image_header.z_resolution;
966 img->quatern[6]=img->sizex; img->quatern[9]=img->sizex;
967 img->quatern[11]=img->sizey; img->quatern[13]=img->sizey;
968 img->quatern[16]=img->sizez; img->quatern[17]=img->sizez;
969 img->mt[0]=image_header.mt_1_1;
970 img->mt[1]=image_header.mt_1_2;
971 img->mt[2]=image_header.mt_1_3;
972 img->mt[3]=image_header.mt_1_4;
973 img->mt[4]=image_header.mt_2_1;
974 img->mt[5]=image_header.mt_2_2;
975 img->mt[6]=image_header.mt_2_3;
976 img->mt[7]=image_header.mt_2_4;
977 img->mt[8]=image_header.mt_3_1;
978 img->mt[9]=image_header.mt_3_2;
979 img->mt[10]=image_header.mt_3_3;
980 img->mt[11]=image_header.mt_3_4;
981 break;
982 case ECAT7_2DSCAN:
983 img->dimx=scan2d_header.num_r_elements;
984 img->dimy=scan2d_header.num_angles;
985 if(scan2d_header.num_dimensions>2 && scan2d_header.num_z_elements>1)
986 planeNr=img->dimz=scan2d_header.num_z_elements;
987 img->_dataType=scan2d_header.data_type;
988 if(scan2d_header.x_resolution>0.0)
989 img->sampleDistance=10.0*scan2d_header.x_resolution;
990 else
991 img->sampleDistance=10.0*main_header.bin_size;
992 break;
993 case ECAT7_3DSCAN:
994 case ECAT7_3DSCAN8:
995 case ECAT7_3DSCANFIT:
996 img->dimx=scan_header.num_r_elements; img->dimy=scan_header.num_angles;
997 for(int i=img->dimz=0; i<64; i++) img->dimz+=scan_header.num_z_elements[i];
998 /* planeNr=img->dimz; */
999 img->_dataType=scan_header.data_type;
1000 if(scan_header.x_resolution>0.0)
1001 img->sampleDistance=10.0*scan_header.x_resolution;
1002 else
1003 img->sampleDistance=10.0*main_header.bin_size;
1004 break;
1005 case ECAT7_POLARMAP:
1006 img->dimy=img->dimz=1;
1007 img->polarmap_num_rings=polmap_header.num_rings;
1009 return STATUS_INVALIDPOLARMAP;
1010 for(int i=0; i<img->polarmap_num_rings; i++) {
1011 img->polarmap_sectors_per_ring[i]=polmap_header.sectors_per_ring[i];
1012 img->polarmap_ring_position[i]=polmap_header.ring_position[i];
1013 img->polarmap_ring_angle[i]=polmap_header.ring_angle[i];
1014 }
1015 img->polarmap_start_angle=polmap_header.start_angle;
1016 img->dimx=0;
1017 for(int i=0; i<img->polarmap_num_rings; i++)
1018 img->dimx+=img->polarmap_sectors_per_ring[i];
1019 /* pixel_size actually contains volume, in cubic cm */
1020 img->sizex=img->sizey=img->sizez=0.001*polmap_header.pixel_size;
1021 break;
1022 }
1023
1024 imgSetStatus(img, STATUS_OK);
1025 return STATUS_OK;
1026}
int ecat7GetPlaneAndFrameNr(ECAT7_MATRIXLIST *mlist, ECAT7_mainheader *h, int *plane_nr, int *frame_nr)
Definition ecat7ml.c:372
int ecat7GetMatrixBlockSize(ECAT7_MATRIXLIST *mlist, int *blk_nr)
Definition ecat7ml.c:418
int imgGetEcat7Fileformat(ECAT7_mainheader *h)
Definition img_e7.c:827
#define MAX_POLARMAP_NUM_RINGS
short int ring_angle[32]
short int start_angle
float ring_position[32]
int polarmap_num_rings
short int polarmap_start_angle
int polarmap_sectors_per_ring[MAX_POLARMAP_NUM_RINGS]
short int polarmap_ring_angle[MAX_POLARMAP_NUM_RINGS]
float polarmap_ring_position[MAX_POLARMAP_NUM_RINGS]

Referenced by imgFormatDetermine(), imgReadEcat7FirstFrame(), imgReadHeader(), and imgWriteEcat7Frame().

◆ imgSetEcat7MHeader()

void imgSetEcat7MHeader ( IMG * img,
ECAT7_mainheader * h )

Copy information from IMG to ECAT 7 main header

Parameters
imgsource structure
htarget structure

Definition at line 781 of file img_e7.c.

782{
783 h->sw_version=72;
784 if(img->type==IMG_TYPE_POLARMAP) {
785 strcpy(h->magic_number, ECAT7V_MAGICNR);
787 } else if(img->type==IMG_TYPE_RAW) {
788 strcpy(h->magic_number, ECAT7S_MAGICNR);
790 else h->file_type=ECAT7_3DSCAN;
791 } else {
792 strcpy(h->magic_number, ECAT7V_MAGICNR);
795 }
796 h->system_type=img->scanner;
799 imgUnitToEcat7(img, h);
801 h->transaxial_fov=img->transaxialFOV/10.0;
802 h->num_planes=img->dimz; /* h->num_planes=1; */
803 h->num_frames=img->dimt;
804 h->num_gates=1;
805 h->num_bed_pos=0;
806 h->distance_scanned=img->axialFOV/10.0;
807 h->plane_separation=img->sizez/10.0;
808 strncpy(h->radiopharmaceutical, img->radiopharmaceutical, 32);
809 strcpy(h->isotope_name, imgIsotope(img));
810 strlcpy(h->study_type, img->studyNr, 12);
811 strcpy(h->patient_name, img->patientName);
812 strcpy(h->patient_id, img->patientID);
814 strcpy(h->study_description, img->studyDescription);
817}
char * imgIsotope(IMG *img)
Definition imgdecayc.c:76
void imgUnitToEcat7(IMG *img, ECAT7_mainheader *h)
Definition imgunits.c:209
short int num_planes
short int num_bed_pos
short int sw_version

Referenced by imgWrite2DEcat7(), imgWriteEcat7(), imgWriteEcat7Frame(), and imgWritePolarmap().

◆ imgSetEcat7SHeader()

void imgSetEcat7SHeader ( IMG * img,
void * h )

Set ECAT7 subheader based on IMG contents

Parameters
imgimage structure
hEcat7 image, scan, 2D scan or polar map header

Definition at line 1482 of file img_e7.c.

1482 {
1483 ECAT7_imageheader *image_header;
1484 ECAT7_scanheader *scan_header;
1485 ECAT7_2Dscanheader *scan2d_header;
1486 ECAT7_polmapheader *polmap_header;
1487
1488 if(img->type==IMG_TYPE_POLARMAP) {
1489 polmap_header=(ECAT7_polmapheader*)h;
1490 polmap_header->data_type=ECAT7_SUNI2;
1491 polmap_header->num_rings=img->polarmap_num_rings;
1492 if(polmap_header->num_rings>32) polmap_header->num_rings=32;
1493 for(int i=0; i<polmap_header->num_rings; i++) {
1494 polmap_header->sectors_per_ring[i]=img->polarmap_sectors_per_ring[i];
1495 polmap_header->ring_position[i]=img->polarmap_ring_position[i];
1496 polmap_header->ring_angle[i]=img->polarmap_ring_angle[i];
1497 }
1498 polmap_header->start_angle=258;
1499 polmap_header->pixel_size=1000.0*img->sizex;
1500 polmap_header->quant_units=0; /* default, see main header */
1501 } else if(img->type==IMG_TYPE_RAW) {
1502 if(img->_fileFormat==IMG_E7_2D) {
1503 scan2d_header=(ECAT7_2Dscanheader*)h;
1504 scan2d_header->num_dimensions=2;
1505 scan2d_header->num_z_elements=1;
1506 scan2d_header->data_type=ECAT7_SUNI2;
1507 scan2d_header->num_r_elements=img->dimx;
1508 scan2d_header->num_angles=img->dimy;
1509 } else {
1510 scan_header=(ECAT7_scanheader*)h;
1511 scan_header->x_resolution=img->sampleDistance/10.0;
1512 scan_header->num_dimensions=4;
1513 if(img->dimz==239) {
1514 scan_header->num_z_elements[0]=63;
1515 scan_header->num_z_elements[1]=106;
1516 scan_header->num_z_elements[2]=70;
1517 } else {
1518 scan_header->num_z_elements[0]=img->dimz;
1519 }
1520 scan_header->storage_order=1;
1521 scan_header->data_type=ECAT7_SUNI2;
1522 scan_header->num_r_elements=img->dimx;
1523 scan_header->num_angles=img->dimy;
1524 }
1525 } else {
1526 image_header=(ECAT7_imageheader*)h;
1527 image_header->data_type=ECAT7_SUNI2;
1528 image_header->x_dimension=img->dimx;
1529 image_header->y_dimension=img->dimy;
1530 image_header->recon_zoom=img->zoom;
1531 image_header->x_pixel_size=0.1*img->sizex;
1532 image_header->y_pixel_size=0.1*img->sizey;
1533 image_header->z_pixel_size=0.1*img->sizez;
1534 image_header->x_resolution=0.1*img->resolutionx;
1535 image_header->y_resolution=0.1*img->resolutiony;
1536 image_header->z_resolution=0.1*img->resolutionz;
1537 image_header->mt_1_1=img->mt[0];
1538 image_header->mt_1_2=img->mt[1];
1539 image_header->mt_1_3=img->mt[2];
1540 image_header->mt_1_4=img->mt[3];
1541 image_header->mt_2_1=img->mt[4];
1542 image_header->mt_2_2=img->mt[5];
1543 image_header->mt_2_3=img->mt[6];
1544 image_header->mt_2_4=img->mt[7];
1545 image_header->mt_3_1=img->mt[8];
1546 image_header->mt_3_2=img->mt[9];
1547 image_header->mt_3_3=img->mt[10];
1548 image_header->mt_3_4=img->mt[11];
1549 if(img->_fileFormat==IMG_E7_2D) {
1550 image_header->num_dimensions=2;
1551 image_header->z_dimension=1;
1552 } else {
1553 image_header->num_dimensions=3;
1554 image_header->z_dimension=img->dimz;
1555 }
1556 for(int i=0; i<49; i++) image_header->fill_user[i]=0;
1557 }
1558}
#define ECAT7_SUNI2
short int fill_user[49]
short int quant_units
short int num_dimensions
short int storage_order

Referenced by imgWriteEcat7Frame(), and imgWritePolarmap().

◆ imgWrite2DEcat7()

int imgWrite2DEcat7 ( const char * fname,
IMG * img )

Write ECAT 7 2D image or 2D sinogram.

Parameters
fnameoutput filename
imgpointer to image structure
Returns
0 if ok, 1 invalid input, 2 image status is not 'occupied', 3 failed to allocate memory for data, 6 faield to create file, 7 failed to write data, 8 image type not supported, sets IMG->statmsg in case of error

Definition at line 526 of file img_e7.c.

526 {
527 ECAT7_mainheader main_header;
528 ECAT7_imageheader image_header;
529 ECAT7_2Dscanheader scan2d_header;
530 FILE *fp;
531 int matrixId, ret;
532 float *fdata, *fptr;
533
534
535 if(IMG_TEST) printf("imgWrite2DEcat7(%s, *img)\n", fname);
536 if(IMG_TEST>1 && ECAT7_TEST==0) ECAT7_TEST=1;
537 /* Check the arguments */
538 if(fname==NULL) {return(1);}
539 if(img==NULL || img->status!=IMG_STATUS_OCCUPIED) {
540 imgSetStatus(img, STATUS_FAULT); return(2);}
541
542 /* Check image size */
543 if(img->dimt>511 || img->dimz>255 || img->dimx>1024 || img->dimy>1024) {
544 imgSetStatus(img, STATUS_INVALIDHEADER); return(2);}
545
546 /* Initiate headers */
547 memset(&main_header, 0, sizeof(ECAT7_mainheader));
548 memset(&image_header,0, sizeof(ECAT7_imageheader));
549 memset(&scan2d_header, 0, sizeof(ECAT7_2Dscanheader));
550
551 /* Set main header */
552 imgSetEcat7MHeader(img, &main_header);
553 main_header.bin_size=img->sampleDistance/10.0;
554 if(img->type==IMG_TYPE_RAW) main_header.file_type=ECAT7_2DSCAN;
555 else main_header.file_type=ECAT7_IMAGE16;
556 main_header.num_planes=img->dimz;
557
558 /* Allocate memory for matrix float data */
559 long long pxlNr=img->dimx*img->dimy;
560 fdata=(float*)malloc(pxlNr*sizeof(float));
561 if(fdata==NULL) {imgSetStatus(img, STATUS_NOMEMORY); return(3);}
562
563 /* Open file, write main header and initiate matrix list */
564 fp=ecat7Create(fname, &main_header);
565 if(fp==NULL) {free(fdata); imgSetStatus(img, STATUS_NOWRITEPERM); return(6);}
566
567 /* Set (most of) subheader contents */
568 if(img->type==IMG_TYPE_RAW) {
569 scan2d_header.num_dimensions=2;
570 scan2d_header.num_z_elements=1;
571 scan2d_header.data_type=ECAT7_SUNI2;
572 scan2d_header.num_r_elements=img->dimx;
573 scan2d_header.num_angles=img->dimy;
574 } else if(img->type==IMG_TYPE_IMAGE) {
575 image_header.num_dimensions=2;
576 image_header.z_dimension=1;
577 image_header.data_type=ECAT7_SUNI2;
578 image_header.x_dimension=img->dimx;
579 image_header.y_dimension=img->dimy;
580 image_header.recon_zoom=img->zoom;
581 image_header.x_pixel_size=0.1*img->sizex;
582 image_header.y_pixel_size=0.1*img->sizey;
583 image_header.z_pixel_size=0.1*img->sizez;
584 image_header.x_resolution=0.1*img->resolutionx;
585 image_header.y_resolution=0.1*img->resolutiony;
586 image_header.z_resolution=0.1*img->resolutionz;
587 img->quatern[6]=img->sizex; img->quatern[9]=img->sizex;
588 img->quatern[11]=img->sizey; img->quatern[13]=img->sizey;
589 img->quatern[16]=img->sizez; img->quatern[17]=img->sizez;
590 image_header.mt_1_1=img->mt[0];
591 image_header.mt_1_2=img->mt[1];
592 image_header.mt_1_3=img->mt[2];
593 image_header.mt_1_4=img->mt[3];
594 image_header.mt_2_1=img->mt[4];
595 image_header.mt_2_2=img->mt[5];
596 image_header.mt_2_3=img->mt[6];
597 image_header.mt_2_4=img->mt[7];
598 image_header.mt_3_1=img->mt[8];
599 image_header.mt_3_2=img->mt[9];
600 image_header.mt_3_3=img->mt[10];
601 image_header.mt_3_4=img->mt[11];
602 }
603
604 /* Write each matrix */
605 for(int fi=0; fi<img->dimt; fi++) for(int pi=0; pi<img->dimz; pi++) {
606
607 /* Create new matrix id (i.e. matnum) */
608 matrixId=ecat7_val_to_id(fi+1, img->planeNumber[pi], 1, 0, 0);
609
610 /* Copy matrix pixel values to fdata */
611 fptr=fdata;
612 for(int yi=0; yi<img->dimy; yi++)
613 for(int xi=0; xi<img->dimx; xi++)
614 if(isfinite(img->m[pi][yi][xi][fi])) *fptr++=img->m[pi][yi][xi][fi]; else *fptr++=0.0;
615
616 /* Write subheader and data */
617 fptr=fdata;
618 if(img->type==IMG_TYPE_RAW) {
619 scan2d_header.frame_start_time=(int)temp_roundf(1000.*img->start[fi]);
620 scan2d_header.frame_duration=
621 (int)temp_roundf(1000.*(img->end[fi]-img->start[fi]));
622 scan2d_header.prompts=temp_roundf(img->prompts[fi]);
623 scan2d_header.delayed=temp_roundf(img->randoms[fi]);
624 ret=ecat7Write2DScanMatrix(fp, matrixId, &scan2d_header, fptr);
625 } else if(img->type==IMG_TYPE_IMAGE) {
626 image_header.frame_start_time=(int)temp_roundf(1000.*img->start[fi]);
627 image_header.frame_duration=
628 (int)temp_roundf(1000.*(img->end[fi]-img->start[fi]));
630 image_header.decay_corr_fctr=img->decayCorrFactor[fi];
631 else
632 image_header.decay_corr_fctr=0.0;
633 ret=ecat7WriteImageMatrix(fp, matrixId, &image_header, fptr);
634 } else {
635 free(fdata); fclose(fp); imgSetStatus(img, STATUS_UNSUPPORTED); return(8);
636 }
637 if(ret) {
638 if(IMG_TEST) {printf("matrixId=%d ret=%d\n", matrixId, ret);}
639 free(fdata); fclose(fp); imgSetStatus(img, STATUS_DISKFULL); return(7);
640 }
641
642 } /* next matrix */
643 free(fdata); fclose(fp);
644
645 imgSetStatus(img, STATUS_OK);
646 return(0);
647}
int ECAT7_TEST
Definition ecat7h.c:6
int ecat7_val_to_id(int frame, int plane, int gate, int data, int bed)
Definition ecat7ml.c:245
int ecat7WriteImageMatrix(FILE *fp, int matrix_id, ECAT7_imageheader *h, float *fdata)
Definition ecat7w.c:635
int ecat7Write2DScanMatrix(FILE *fp, int matrix_id, ECAT7_2Dscanheader *h, float *fdata)
Definition ecat7w.c:719
FILE * ecat7Create(const char *fname, ECAT7_mainheader *h)
Definition ecat7w.c:567
void imgSetEcat7MHeader(IMG *img, ECAT7_mainheader *h)
Definition img_e7.c:781
int temp_roundf(float e)
Definition petc99.c:20

Referenced by imgWrite().

◆ imgWriteEcat7()

int imgWriteEcat7 ( const char * fname,
IMG * img )

Write ECAT 7 3D image volume or 3D sinogram.

Parameters
fnameoutput filename
imgpointer to IMG data
Returns
0 if ok, 1 invalid input, 2 image status is not 'occupied', 3 failed to allocate memory for data, 6 failed to create file, 7 failed to write data, 8 unsupported image type sets IMG->statmsg in case of error

Definition at line 382 of file img_e7.c.

382 {
383 ECAT7_mainheader main_header;
384 ECAT7_imageheader image_header;
385 ECAT7_scanheader scan_header;
386 FILE *fp;
387 int matrixId, ret;
388 float *fdata, *fptr;
389
390
391 if(IMG_TEST) printf("imgWriteEcat7(%s, *img)\n", fname);
392 if(IMG_TEST>1 && ECAT7_TEST==0) ECAT7_TEST=1;
393 /* Check the arguments */
394 if(fname==NULL) return(1);
395 if(img==NULL || img->status!=IMG_STATUS_OCCUPIED) {
396 imgSetStatus(img, STATUS_FAULT); return(2);}
397 if(img->type!=IMG_TYPE_RAW && img->type!=IMG_TYPE_IMAGE) {
398 imgSetStatus(img, STATUS_FAULT); return(2);}
399
400 /* Check image size */
401 if(img->dimt>511 || img->dimz>255 || img->dimx>1024 || img->dimy>1024) {
402 imgSetStatus(img, STATUS_INVALIDHEADER); return(2);}
403
404 /* Initiate headers */
405 memset(&main_header, 0, sizeof(ECAT7_mainheader));
406 memset(&image_header,0, sizeof(ECAT7_imageheader));
407 memset(&scan_header, 0, sizeof(ECAT7_scanheader));
408
409 /* Set main header */
410 imgSetEcat7MHeader(img, &main_header);
411 main_header.bin_size=img->sampleDistance/10.0;
412
413 /* Allocate memory for matrix float data */
414 long long pxlNr=img->dimx*img->dimy*img->dimz;
415 fdata=(float*)malloc(pxlNr*sizeof(float));
416 if(fdata==NULL) {imgSetStatus(img, STATUS_NOMEMORY); return(3);}
417
418 /* Open file, write main header and initiate matrix list */
419 fp=ecat7Create(fname, &main_header);
420 if(fp==NULL) {free(fdata); imgSetStatus(img, STATUS_NOWRITEPERM); return(6);}
421
422 /* Set (most of) subheader contents */
423 if(img->type==IMG_TYPE_RAW) {
424 scan_header.x_resolution=img->sampleDistance/10.0;
425 scan_header.num_dimensions=4;
426 if(img->dimz==239) {
427 scan_header.num_z_elements[0]=63;
428 scan_header.num_z_elements[1]=106;
429 scan_header.num_z_elements[2]=70;
430 } else {
431 scan_header.num_z_elements[0]=img->dimz;
432 }
433 scan_header.storage_order=1;
434 scan_header.data_type=ECAT7_SUNI2;
435 scan_header.num_r_elements=img->dimx;
436 scan_header.num_angles=img->dimy;
437 } else if(img->type==IMG_TYPE_IMAGE) {
438 image_header.num_dimensions=3;
439 image_header.z_dimension=img->dimz;
440 image_header.data_type=ECAT7_SUNI2;
441 image_header.x_dimension=img->dimx;
442 image_header.y_dimension=img->dimy;
443 image_header.recon_zoom=img->zoom;
444 image_header.x_pixel_size=0.1*img->sizex;
445 image_header.y_pixel_size=0.1*img->sizey;
446 image_header.z_pixel_size=0.1*img->sizez;
447 image_header.x_resolution=0.1*img->resolutionx;
448 image_header.y_resolution=0.1*img->resolutiony;
449 image_header.z_resolution=0.1*img->resolutionz;
450 img->quatern[6]=img->sizex; img->quatern[9]=img->sizex;
451 img->quatern[11]=img->sizey; img->quatern[13]=img->sizey;
452 img->quatern[16]=img->sizez; img->quatern[17]=img->sizez;
453 image_header.mt_1_1=img->mt[0];
454 image_header.mt_1_2=img->mt[1];
455 image_header.mt_1_3=img->mt[2];
456 image_header.mt_1_4=img->mt[3];
457 image_header.mt_2_1=img->mt[4];
458 image_header.mt_2_2=img->mt[5];
459 image_header.mt_2_3=img->mt[6];
460 image_header.mt_2_4=img->mt[7];
461 image_header.mt_3_1=img->mt[8];
462 image_header.mt_3_2=img->mt[9];
463 image_header.mt_3_3=img->mt[10];
464 image_header.mt_3_4=img->mt[11];
465 }
466
467 /* Write each matrix */
468 for(int fi=0; fi<img->dimt; fi++) {
469
470 /* Create new matrix id (i.e. matnum) */
471 matrixId=ecat7_val_to_id(fi+1, 1, 1, 0, 0);
472
473 /* Copy matrix pixel values to fdata */
474 fptr=fdata;
475 for(int pi=0; pi<img->dimz; pi++)
476 for(int yi=0; yi<img->dimy; yi++)
477 for(int xi=0; xi<img->dimx; xi++)
478 if(isfinite(img->m[pi][yi][xi][fi])) *fptr++=img->m[pi][yi][xi][fi]; else *fptr++=0.0;
479
480 /* Write subheader and data */
481 fptr=fdata;
482 if(img->type==IMG_TYPE_RAW) {
483 scan_header.frame_start_time=(int)temp_roundf(1000.*img->start[fi]);
484 scan_header.frame_duration=
485 (int)temp_roundf(1000.*(img->end[fi]-img->start[fi]));
486 scan_header.prompts=temp_roundf(img->prompts[fi]);
487 scan_header.delayed=temp_roundf(img->randoms[fi]);
488 /*ecat7PrintScanheader(&scan_header, stdout);*/
489 ret=ecat7WriteScanMatrix(fp, matrixId, &scan_header, fptr);
490 } else if(img->type==IMG_TYPE_IMAGE) {
491 image_header.frame_start_time=(int)temp_roundf(1000.*img->start[fi]);
492 image_header.frame_duration=(int)temp_roundf(1000.*(img->end[fi]-img->start[fi]));
494 image_header.decay_corr_fctr=img->decayCorrFactor[fi];
495 else
496 image_header.decay_corr_fctr=0.0;
497 /*ecat7PrintImageheader(&image_header, stdout);*/
498 ret=ecat7WriteImageMatrix(fp, matrixId, &image_header, fptr);
499 } else {
500 free(fdata); fclose(fp); imgSetStatus(img, STATUS_UNSUPPORTED); return(8);
501 }
502 if(ret) {
503 if(IMG_TEST) {printf("matrixId=%d ret=%d\n", matrixId, ret);}
504 free(fdata); fclose(fp); imgSetStatus(img, STATUS_DISKFULL); return(7);
505 }
506
507 } /* next matrix */
508 free(fdata); fclose(fp);
509
510 imgSetStatus(img, STATUS_OK);
511 return(0);
512}
int ecat7WriteScanMatrix(FILE *fp, int matrix_id, ECAT7_scanheader *h, float *fdata)
Definition ecat7w.c:802

Referenced by imgWrite().

◆ imgWriteEcat7Frame()

int imgWriteEcat7Frame ( const char * fname,
int frame_to_write,
IMG * img,
int frame_index )

Write one PET frame from IMG data struct into ECAT 7 image or sinogram file; format is specified in IMG struct. This function can be called repeatedly to write all frames one at a time to conserve memory. However, file with just mainheader and matrix list without any previous frame is not accepted.

Parameters
fnamename of file where IMG contents will be written. If file does not exist, it is created. Make sure to delete existing file, unless you want to add data
frame_to_writePET frame number (1..frameNr) which will be written: If set to 0, frame data will be written to an existing or new PET file as a new frame, never overwriting existing data. If >0, then frame data is written as specified frame number, overwriting any data existing with the same frame number
imgpointer to the IMG data struct
frame_indexIMG frame index (0..dimt-1) which will be written
Returns
errstatus, which is STATUS_OK (0) when call was successful, and >0 in case of an error.

Definition at line 1295 of file img_e7.c.

1297 {
1298 IMG test_img;
1299 int ret=0, matrixId;
1300 ECAT7_mainheader main_header;
1301 ECAT7_imageheader image_header;
1302 ECAT7_scanheader scan_header;
1303 ECAT7_2Dscanheader scan2d_header;
1304 ECAT7_polmapheader polmap_header;
1305 void *sub_header=NULL;
1306 FILE *fp;
1307 float *fdata=NULL, *fptr;
1308
1309
1310 if(IMG_TEST) printf("\nimgWriteEcat7Frame(%s, %d, *img, %d)\n",
1311 fname, frame_to_write, frame_index);
1312
1313 /*
1314 * Check the input
1315 */
1316 if(fname==NULL) return STATUS_FAULT;
1317 if(img==NULL) return STATUS_FAULT;
1318 if(img->status!=IMG_STATUS_OCCUPIED) return STATUS_FAULT;
1319 if(frame_to_write<0) return STATUS_FAULT;
1320 if(frame_index<0 || frame_index>=img->dimt) return STATUS_FAULT;
1321 if(img->_fileFormat!=IMG_E7 &&
1322 img->_fileFormat!=IMG_POLARMAP &&
1323 img->_fileFormat!=IMG_E7_2D) return STATUS_FAULT;
1324
1325 /* Check image size */
1326 if(img->dimt>511 || img->dimz>255 || img->dimx>1024 || img->dimy>1024)
1327 return STATUS_INVALIDHEADER;
1328
1329 /* Initiate headers */
1330 memset(&main_header, 0, sizeof(ECAT7_mainheader));
1331 memset(&image_header,0, sizeof(ECAT7_imageheader));
1332 memset(&scan_header, 0, sizeof(ECAT7_scanheader));
1333 memset(&scan2d_header, 0, sizeof(ECAT7_2Dscanheader));
1334 memset(&polmap_header,0, sizeof(ECAT7_polmapheader));
1335 imgInit(&test_img);
1336
1337
1338 /*
1339 * If file does not exist, then create it with new mainheader,
1340 * and if it does exist, then read and check header information.
1341 * Create or edit mainheader to contain correct frame nr.
1342 * In any case, leave file pointer open for write.
1343 */
1344 if(access(fname, 0) == -1) { /* file does not exist */
1345
1346 /* Set main header */
1347 imgSetEcat7MHeader(img, &main_header);
1348 main_header.bin_size=img->sampleDistance/10.0;
1349 if(frame_to_write==0) frame_to_write=1;
1350 main_header.num_frames=frame_to_write;
1351
1352 /* Open file, write main header and initiate matrix list */
1353 fp=ecat7Create(fname, &main_header); if(fp==NULL) return STATUS_NOWRITEPERM;
1354
1355 } else { /* file exists */
1356
1357 /* Read header information for checking */
1358 ret=imgReadEcat7Header(fname, &test_img); if(ret!=0) return ret;
1359 /* Check that file format is the same */
1360 if(img->_fileFormat!=test_img._fileFormat || img->type!=test_img.type)
1361 return STATUS_WRONGFILETYPE;
1362 /* Check that matrix sizes are the same */
1363 if(img->dimz!=test_img.dimz || img->dimx!=test_img.dimx ||
1364 img->dimy!=test_img.dimy)
1365 return STATUS_VARMATSIZE;
1366 imgEmpty(&test_img);
1367
1368 /* Open the file for read and write */
1369 if((fp=fopen(fname, "r+b"))==NULL) return STATUS_NOWRITEPERM;
1370
1371 /* Read the mainheader, set new frame number, and write it back */
1372 if((ret=ecat7ReadMainheader(fp, &main_header))!=0)
1373 return STATUS_NOMAINHEADER;
1374 if(frame_to_write==0) frame_to_write=main_header.num_frames+1;
1375 if(main_header.num_frames<frame_to_write)
1376 main_header.num_frames=frame_to_write;
1377 if((ret=ecat7WriteMainheader(fp, &main_header))!=0)
1378 return STATUS_NOWRITEPERM;
1379
1380 }
1381 if(IMG_TEST>2) {
1382 printf("frame_to_write := %d\n", frame_to_write);
1383 }
1384
1385 /* Allocate memory for matrix float data */
1386 long long pxlNr=img->dimx*img->dimy*img->dimz; /* for 2D too! */
1387 fdata=(float*)malloc(pxlNr*sizeof(float));
1388 if(fdata==NULL) {fclose(fp); return STATUS_NOMEMORY;}
1389
1390 /* Set matrix subheader */
1391 if(img->_fileFormat==IMG_E7) {
1392 if(img->type==IMG_TYPE_RAW) sub_header=(void*)&scan_header;
1393 else sub_header=&image_header;
1394 } else if(img->_fileFormat==IMG_E7_2D) {
1395 if(img->type==IMG_TYPE_RAW) sub_header=(void*)&scan_header;
1396 else sub_header=(void*)&image_header;
1397 } else if(img->_fileFormat==IMG_POLARMAP) {
1398 sub_header=(void*)&polmap_header;
1399 } else {fclose(fp); return STATUS_FAULT;}
1400 imgSetEcat7SHeader(img, sub_header);
1401
1402 /* Copy matrix pixel values to fdata */
1403 fptr=fdata;
1404 for(int zi=0; zi<img->dimz; zi++)
1405 for(int yi=0; yi<img->dimy; yi++)
1406 for(int xi=0; xi<img->dimx; xi++)
1407 if(isfinite(img->m[zi][yi][xi][frame_index])) *fptr++=img->m[zi][yi][xi][frame_index]; else *fptr++=0.0;
1408
1409 /* Write subheader and data, and set the rest of subheader contents */
1410 fptr=fdata; ret=-1;
1411 if(img->_fileFormat==IMG_E7) {
1412 /* Create new matrix id (i.e. matnum) */
1413 matrixId=ecat7_val_to_id(frame_to_write, 1, 1, 0, 0);
1414 if(img->type==IMG_TYPE_RAW) {
1415 scan_header.frame_start_time=
1416 (int)temp_roundf(1000.*img->start[frame_index]);
1417 scan_header.frame_duration=
1418 (int)temp_roundf(1000.*(img->end[frame_index]-img->start[frame_index]));
1419 scan_header.prompts=temp_roundf(img->prompts[frame_index]);
1420 scan_header.delayed=temp_roundf(img->randoms[frame_index]);
1421 ret=ecat7WriteScanMatrix(fp, matrixId, &scan_header, fptr);
1422 } else {
1423 image_header.frame_start_time=
1424 (int)temp_roundf(1000.*img->start[frame_index]);
1425 image_header.frame_duration=
1426 (int)temp_roundf(1000.*(img->end[frame_index]-img->start[frame_index]));
1428 image_header.decay_corr_fctr=img->decayCorrFactor[frame_index];
1429 else
1430 image_header.decay_corr_fctr=0.0;
1431 /*ecat7PrintImageheader(&image_header, stdout);*/
1432 ret=ecat7WriteImageMatrix(fp, matrixId, &image_header, fptr);
1433 }
1434 } else if(img->_fileFormat==IMG_E7_2D) {
1435 for(int zi=0; zi<img->dimz; zi++, fptr+=img->dimx*img->dimy) {
1436 /* Create new matrix id (i.e. matnum) */
1437 matrixId=ecat7_val_to_id(frame_to_write, img->planeNumber[zi], 1, 0, 0);
1438 if(img->type==IMG_TYPE_RAW) {
1439 scan2d_header.frame_start_time=
1440 (int)temp_roundf(1000.*img->start[frame_index]);
1441 scan2d_header.frame_duration=
1442 (int)temp_roundf(1000.*(img->end[frame_index]-img->start[frame_index]));
1443 scan2d_header.prompts=temp_roundf(img->prompts[frame_index]);
1444 scan2d_header.delayed=temp_roundf(img->randoms[frame_index]);
1445 ret=ecat7Write2DScanMatrix(fp, matrixId, &scan2d_header, fptr);
1446 } else {
1447 image_header.frame_start_time=
1448 (int)temp_roundf(1000.*img->start[frame_index]);
1449 image_header.frame_duration=
1450 (int)temp_roundf(1000.*(img->end[frame_index]-img->start[frame_index]));
1452 image_header.decay_corr_fctr=img->decayCorrFactor[frame_index];
1453 else
1454 image_header.decay_corr_fctr=0.0;
1455 ret=ecat7WriteImageMatrix(fp, matrixId, &image_header, fptr);
1456 }
1457 if(ret!=0) break;
1458 } /* next plane */
1459 } else if(img->_fileFormat==IMG_POLARMAP) {
1460 /* Create new matrix id (i.e. matnum) */
1461 matrixId=ecat7_val_to_id(frame_to_write, 1, 1, 0, 0);
1462 polmap_header.frame_start_time=
1463 (int)temp_roundf(1000.*img->start[frame_index]);
1464 polmap_header.frame_duration=
1465 (int)temp_roundf(1000.*(img->end[frame_index]-img->start[frame_index]));
1466 ret=ecat7WritePolarmapMatrix(fp, matrixId, &polmap_header, fptr);
1467 }
1468 free(fdata); fclose(fp);
1469 if(ret) return STATUS_DISKFULL;
1470
1471 return STATUS_OK;
1472}
int ecat7WritePolarmapMatrix(FILE *fp, int matrix_id, ECAT7_polmapheader *h, float *fdata)
Definition ecat7w.c:888
int ecat7WriteMainheader(FILE *fp, ECAT7_mainheader *h)
Definition ecat7w.c:16
void imgEmpty(IMG *image)
Definition img.c:121
void imgInit(IMG *image)
Definition img.c:60
void imgSetEcat7SHeader(IMG *img, void *h)
Definition img_e7.c:1482

Referenced by imgWriteFrame().

◆ imgWritePolarmap()

int imgWritePolarmap ( const char * fname,
IMG * img )

Write ECAT 7 polar map.

Parameters
fnameoutput filename
imgpointer to image structure
Returns
0 if ok, 1 invalid input, 2 image status is not 'occupied', 3 failed to allocate memory for data, 6 faield to create file, 7 failed to write data, 8 image type not supported, sets IMG->statmsg in case of error

Definition at line 661 of file img_e7.c.

661 {
662 ECAT7_mainheader main_header;
663 ECAT7_polmapheader polmap_header;
664 FILE *fp;
665 int matrixId, ret;
666 float *fdata, *fptr;
667
668
669 if(IMG_TEST) printf("imgWritePolarmap(%s, *img)\n", fname);
670 if(IMG_TEST>1 && ECAT7_TEST==0) ECAT7_TEST=1;
671 /* Check the arguments */
672 if(fname==NULL) return(1);
673 if(img==NULL || img->status!=IMG_STATUS_OCCUPIED) {
674 imgSetStatus(img, STATUS_FAULT); return(2);}
675 if(img->type!=IMG_TYPE_POLARMAP) {
676 imgSetStatus(img, STATUS_FAULT); return(2);}
677
678 /* Check image size */
679 if(img->dimt>511 || img->dimz>255 || img->dimx>1024 || img->dimy>1024) {
680 imgSetStatus(img, STATUS_INVALIDHEADER); return(2);}
681
682 /* Initiate headers */
683 memset(&main_header, 0, sizeof(ECAT7_mainheader));
684 memset(&polmap_header,0, sizeof(ECAT7_polmapheader));
685
686 /* Set main header */
687 imgSetEcat7MHeader(img, &main_header);
688 main_header.bin_size=img->sampleDistance/10.0;
689
690 /* Allocate memory for matrix float data */
691 long long pxlNr=img->dimx*img->dimy*img->dimz;
692 fdata=(float*)malloc(pxlNr*sizeof(float));
693 if(fdata==NULL) {imgSetStatus(img, STATUS_NOMEMORY); return(3);}
694
695 /* Open file, write main header and initiate matrix list */
696 fp=ecat7Create(fname, &main_header);
697 if(fp==NULL) {free(fdata); imgSetStatus(img, STATUS_NOWRITEPERM); return(6);}
698
699 /* Set (most of) subheader contents */
700 imgSetEcat7SHeader(img, &polmap_header);
701
702 /* Write each matrix */
703 for(int fi=0; fi<img->dimt; fi++) {
704
705 /* Create new matrix id (i.e. matnum) */
706 matrixId=ecat7_val_to_id(fi+1, 1, 1, 0, 0);
707
708 /* Copy matrix pixel values to fdata */
709 fptr=fdata;
710 for(int pi=0; pi<img->dimz; pi++)
711 for(int yi=0; yi<img->dimy; yi++)
712 for(int xi=0; xi<img->dimx; xi++)
713 if(isfinite(img->m[pi][yi][xi][fi])) *fptr++=img->m[pi][yi][xi][fi]; else *fptr++=0.0;
714
715 /* Write subheader and data */
716 fptr=fdata;
717 polmap_header.frame_start_time=(int)temp_roundf(1000.*img->start[fi]);
718 polmap_header.frame_duration=
719 (int)temp_roundf(1000.*(img->end[fi]-img->start[fi]));
720 /*ecat7PrintImageheader(&image_header, stdout);*/
721 ret=ecat7WritePolarmapMatrix(fp, matrixId, &polmap_header, fptr);
722 if(ret) {
723 if(IMG_TEST) {printf("matrixId=%d ret=%d\n", matrixId, ret);}
724 free(fdata); fclose(fp); imgSetStatus(img, STATUS_DISKFULL); return(7);
725 }
726
727 } /* next matrix */
728 free(fdata); fclose(fp);
729
730 imgSetStatus(img, STATUS_OK);
731 return(0);
732}

Referenced by imgWrite().