My Project
ecat7w.c
Go to the documentation of this file.
1/******************************************************************************
2
3 Copyright (c) 2003-2008 Turku PET Centre
4
5 Library file: ecat7w.c
6 Description: Functions for writing ECAT 7.x format.
7
8 This program is free software; you can redistribute it and/or modify it under
9 the terms of the GNU General Public License as published by the Free Software
10 Foundation; either version 2 of the License, or (at your option) any later
11 version.
12
13 This program is distributed in the hope that it will be useful, but WITHOUT
14 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
15 FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License along with
18 this program; if not, write to the Free Software Foundation, Inc., 59 Temple
19 Place, Suite 330, Boston, MA 02111-1307 USA.
20
21 Turku PET Centre hereby disclaims all copyright interest in the program.
22 Juhani Knuuti
23 Director, Professor
24 Turku PET Centre, Turku, Finland, http://www.turkupetcentre.fi/
25
26 Modification history:
27 2003-07-24 Vesa Oikonen
28 First created.
29 2003-09-04 VO
30 Added support for 3D sinograms, ecat7WriteScanMatrix().
31 Removed functions ecat7wFloat() and ecat7wInt().
32 2003-11-30 VO
33 For now, calls temp_roundf() instead of roundf().
34 2004-01-07 VO
35 ecat7WriteImageMatrix(): corrected img min&max in header.
36 2004-09-17 VO
37 Changes in comment style.
38 Removed code that was previously commented out.
39 2004-12-28 VO
40 Included function ecat7_is_scaling_needed().
41 This function is applied to determine whether scal factor can be set to
42 one in case that all pixel values are close to integers and small enough.
43 2007-01-27 VO
44 Unsigned char pointer was corrected to signed in ecat7WriteMatrixdata().
45 2007-03-27 VO
46 Added ecat7WritePolarmapMatrix().
47 2007-09-02 VO
48 Backup file extension changed from % to .bak.
49
50******************************************************************************/
51#include <stdio.h>
52#include <stdlib.h>
53#include <math.h>
54#include <string.h>
55#include <unistd.h>
56#include <time.h>
57/*****************************************************************************/
58#include "swap.h"
59#include "petc99.h"
60#include "include/ecat7.h"
61/*****************************************************************************/
62
63/*****************************************************************************/
74 unsigned char buf[MatBLKSIZE];
75 int little;
76
77 if(ECAT7_TEST) printf("ecat7WriteMainheader()\n");
78 /* Check arguments */
79 if(fp==NULL || h==NULL) return(1);
80 little=little_endian();
81 /* Clear buf */
82 memset(buf, 0, MatBLKSIZE);
83
84 /* Copy header contents into buffer and change byte order if necessary */
85 memcpy(buf+0, &h->magic_number, 14);
86 memcpy(buf+14, &h->original_file_name, 32);
87 memcpy(buf+46, &h->sw_version, 2); if(little) swabip(buf+46, 2);
88 memcpy(buf+48, &h->system_type, 2); if(little) swabip(buf+48, 2);
89 memcpy(buf+50, &h->file_type, 2); if(little) swabip(buf+50, 2);
90 memcpy(buf+52, &h->serial_number, 10);
91 memcpy(buf+62, &h->scan_start_time, 4); if(little) swawbip(buf+62, 4);
92 memcpy(buf+66, &h->isotope_name, 8);
93 memcpy(buf+74, &h->isotope_halflife, 4); if(little) swawbip(buf+74, 4);
94 memcpy(buf+78, &h->radiopharmaceutical, 32);
95 memcpy(buf+110, &h->gantry_tilt, 4); if(little) swawbip(buf+110, 4);
96 memcpy(buf+114, &h->gantry_rotation, 4); if(little) swawbip(buf+114, 4);
97 memcpy(buf+118, &h->bed_elevation, 4); if(little) swawbip(buf+118, 4);
98 memcpy(buf+122, &h->intrinsic_tilt, 4); if(little) swawbip(buf+122, 4);
99 memcpy(buf+126, &h->wobble_speed, 2); if(little) swabip(buf+126, 2);
100 memcpy(buf+128, &h->transm_source_type, 2); if(little) swabip(buf+128, 2);
101 memcpy(buf+130, &h->distance_scanned, 4); if(little) swawbip(buf+130, 4);
102 memcpy(buf+134, &h->transaxial_fov, 4); if(little) swawbip(buf+134, 4);
103 memcpy(buf+138, &h->angular_compression, 2); if(little) swabip(buf+138, 2);
104 memcpy(buf+140, &h->coin_samp_mode, 2); if(little) swabip(buf+140, 2);
105 memcpy(buf+142, &h->axial_samp_mode, 2); if(little) swabip(buf+142, 2);
106 memcpy(buf+144, &h->ecat_calibration_factor, 4); if(little) swawbip(buf+144, 4);
107 memcpy(buf+148, &h->calibration_units, 2); if(little) swabip(buf+148, 2);
108 memcpy(buf+150, &h->calibration_units_label, 2); if(little) swabip(buf+150, 2);
109 memcpy(buf+152, &h->compression_code, 2); if(little) swabip(buf+152, 2);
110 memcpy(buf+154, &h->study_type, 12);
111 memcpy(buf+166, &h->patient_id, 16);
112 memcpy(buf+182, &h->patient_name, 32);
113 memcpy(buf+214, &h->patient_sex, 1);
114 memcpy(buf+215, &h->patient_dexterity, 1);
115 memcpy(buf+216, &h->patient_age, 4); if(little) swawbip(buf+216, 4);
116 memcpy(buf+220, &h->patient_height, 4); if(little) swawbip(buf+220, 4);
117 memcpy(buf+224, &h->patient_weight, 4); if(little) swawbip(buf+224, 4);
118 memcpy(buf+228, &h->patient_birth_date, 4); if(little) swawbip(buf+228, 4);
119 memcpy(buf+232, &h->physician_name, 32);
120 memcpy(buf+264, &h->operator_name, 32);
121 memcpy(buf+296, &h->study_description, 32);
122 memcpy(buf+328, &h->acquisition_type, 2); if(little) swabip(buf+328, 2);
123 memcpy(buf+330, &h->patient_orientation, 2); if(little) swabip(buf+330, 2);
124 memcpy(buf+332, &h->facility_name, 20);
125 memcpy(buf+352, &h->num_planes, 2); if(little) swabip(buf+352, 2);
126 memcpy(buf+354, &h->num_frames, 2); if(little) swabip(buf+354, 2);
127 memcpy(buf+356, &h->num_gates, 2); if(little) swabip(buf+356, 2);
128 memcpy(buf+358, &h->num_bed_pos, 2); if(little) swabip(buf+358, 2);
129 memcpy(buf+360, &h->init_bed_position, 4); if(little) swawbip(buf+360, 4);
130 memcpy(buf+364, h->bed_position, 15*4); if(little) swawbip(buf+364, 15*4);
131 memcpy(buf+424, &h->plane_separation, 4); if(little) swawbip(buf+424, 4);
132 memcpy(buf+428, &h->lwr_sctr_thres, 2); if(little) swabip(buf+428, 2);
133 memcpy(buf+430, &h->lwr_true_thres, 2); if(little) swabip(buf+430, 2);
134 memcpy(buf+432, &h->upr_true_thres, 2); if(little) swabip(buf+432, 2);
135 memcpy(buf+434, &h->user_process_code, 10);
136 memcpy(buf+444, &h->acquisition_mode, 2); if(little) swabip(buf+444, 2);
137 memcpy(buf+446, &h->bin_size, 4); if(little) swawbip(buf+446, 4);
138 memcpy(buf+450, &h->branching_fraction, 4); if(little) swawbip(buf+450, 4);
139 memcpy(buf+454, &h->dose_start_time, 4); if(little) swawbip(buf+454, 4);
140 memcpy(buf+458, &h->dosage, 4); if(little) swawbip(buf+458, 4);
141 memcpy(buf+462, &h->well_counter_corr_factor, 4); if(little) swawbip(buf+462, 4);
142 memcpy(buf+466, &h->data_units, 32);
143 memcpy(buf+498, &h->septa_state, 2); if(little) swabip(buf+498, 2);
144 memcpy(buf+500, &h->fill_cti, 12);
145
146 /* Write main header */
147 fseek(fp, 0*MatBLKSIZE, SEEK_SET); if(ftell(fp)!=0*MatBLKSIZE) return(4);
148 if(fwrite(buf, 1, 1*MatBLKSIZE, fp) != 1*MatBLKSIZE) return(5);
149
150 return(0);
151}
152/*****************************************************************************/
153
154/*****************************************************************************/
164int ecat7WriteImageheader(FILE *fp, int blk, ECAT7_imageheader *h) {
165 unsigned char buf[MatBLKSIZE];
166 int little; /* 1 if current platform is little endian (i386), else 0 */
167
168 if(ECAT7_TEST) printf("ecat7WriteImageheader()\n");
169 if(fp==NULL || blk<2 || h==NULL) return(1);
170 little=little_endian(); if(ECAT7_TEST) printf("little=%d\n", little);
171 /* Clear buf */
172 memset(buf, 0, MatBLKSIZE);
176
177 /* Copy the header fields and swap if necessary */
178 memcpy(buf+0, &h->data_type, 2); if(little) swabip(buf+0, 2);
179 memcpy(buf+2, &h->num_dimensions, 2); if(little) swabip(buf+2, 2);
180 memcpy(buf+4, &h->x_dimension, 2); if(little) swabip(buf+4, 2);
181 memcpy(buf+6, &h->y_dimension, 2); if(little) swabip(buf+6, 2);
182 memcpy(buf+8, &h->z_dimension, 2); if(little) swabip(buf+8, 2);
183 memcpy(buf+10, &h->x_offset, 4); if(little) swawbip(buf+10, 4);
184 memcpy(buf+14, &h->y_offset, 4); if(little) swawbip(buf+14, 4);
185 memcpy(buf+18, &h->z_offset, 4); if(little) swawbip(buf+18, 4);
186 memcpy(buf+22, &h->recon_zoom, 4); if(little) swawbip(buf+22, 4);
187 memcpy(buf+26, &h->scale_factor, 4); if(little) swawbip(buf+26, 4);
188 memcpy(buf+30, &h->image_min, 2); if(little) swabip(buf+30, 2);
189 memcpy(buf+32, &h->image_max, 2); if(little) swabip(buf+32, 2);
190 memcpy(buf+34, &h->x_pixel_size, 4); if(little) swawbip(buf+34, 4);
191 memcpy(buf+38, &h->y_pixel_size, 4); if(little) swawbip(buf+38, 4);
192 memcpy(buf+42, &h->z_pixel_size, 4); if(little) swawbip(buf+42, 4);
193 memcpy(buf+46, &h->frame_duration, 4); if(little) swawbip(buf+46, 4);
194 memcpy(buf+50, &h->frame_start_time, 4); if(little) swawbip(buf+50, 4);
195 memcpy(buf+54, &h->filter_code, 2); if(little) swabip(buf+54, 2);
196 memcpy(buf+56, &h->x_resolution, 4); if(little) swawbip(buf+56, 4);
197 memcpy(buf+60, &h->y_resolution, 4); if(little) swawbip(buf+60, 4);
198 memcpy(buf+64, &h->z_resolution, 4); if(little) swawbip(buf+64, 4);
199 memcpy(buf+68, &h->num_r_elements, 4); if(little) swawbip(buf+68, 4);
200 memcpy(buf+72, &h->num_angles, 4); if(little) swawbip(buf+72, 4);
201 memcpy(buf+76, &h->z_rotation_angle, 4); if(little) swawbip(buf+76, 4);
202 memcpy(buf+80, &h->decay_corr_fctr, 4); if(little) swawbip(buf+80, 4);
203 memcpy(buf+84, &h->processing_code, 4); if(little) swawbip(buf+84, 4);
204 memcpy(buf+88, &h->gate_duration, 4); if(little) swawbip(buf+88, 4);
205 memcpy(buf+92, &h->r_wave_offset, 4); if(little) swawbip(buf+92, 4);
206 memcpy(buf+96, &h->num_accepted_beats, 4); if(little) swawbip(buf+96, 4);
207 memcpy(buf+100, &h->filter_cutoff_frequency, 4); if(little) swawbip(buf+100, 4);
208 memcpy(buf+104, &h->filter_resolution, 4); if(little) swawbip(buf+104, 4);
209 memcpy(buf+108, &h->filter_ramp_slope, 4); if(little) swawbip(buf+108, 4);
210 memcpy(buf+112, &h->filter_order, 2); if(little) swabip(buf+112, 2);
211 memcpy(buf+114, &h->filter_scatter_fraction, 4); if(little) swawbip(buf+114, 4);
212 memcpy(buf+118, &h->filter_scatter_slope, 4); if(little) swawbip(buf+118, 4);
213 memcpy(buf+122, &h->annotation, 40);
214 memcpy(buf+162, &h->mt_1_1, 4); if(little) swawbip(buf+162, 4);
215 memcpy(buf+166, &h->mt_1_2, 4); if(little) swawbip(buf+166, 4);
216 memcpy(buf+170, &h->mt_1_3, 4); if(little) swawbip(buf+170, 4);
217 memcpy(buf+174, &h->mt_2_1, 4); if(little) swawbip(buf+174, 4);
218 memcpy(buf+178, &h->mt_2_2, 4); if(little) swawbip(buf+178, 4);
219 memcpy(buf+182, &h->mt_2_3, 4); if(little) swawbip(buf+182, 4);
220 memcpy(buf+186, &h->mt_3_1, 4); if(little) swawbip(buf+186, 4);
221 memcpy(buf+190, &h->mt_3_2, 4); if(little) swawbip(buf+190, 4);
222 memcpy(buf+194, &h->mt_3_3, 4); if(little) swawbip(buf+194, 4);
223 memcpy(buf+198, &h->rfilter_cutoff, 4); if(little) swawbip(buf+198, 4);
224 memcpy(buf+202, &h->rfilter_resolution, 4); if(little) swawbip(buf+202, 4);
225 memcpy(buf+206, &h->rfilter_code, 2); if(little) swabip(buf+206, 2);
226 memcpy(buf+208, &h->rfilter_order, 2); if(little) swabip(buf+208, 2);
227 memcpy(buf+210, &h->zfilter_cutoff, 4); if(little) swawbip(buf+210, 4);
228 memcpy(buf+214, &h->zfilter_resolution, 4); if(little) swawbip(buf+214, 4);
229 memcpy(buf+218, &h->zfilter_code, 2); if(little) swabip(buf+218, 2);
230 memcpy(buf+220, &h->zfilter_order, 2); if(little) swabip(buf+220, 2);
231 memcpy(buf+222, &h->mt_1_4, 4); if(little) swawbip(buf+222, 4);
232 memcpy(buf+226, &h->mt_2_4, 4); if(little) swawbip(buf+226, 4);
233 memcpy(buf+230, &h->mt_3_4, 4); if(little) swawbip(buf+230, 4);
234 memcpy(buf+234, &h->scatter_type, 2); if(little) swabip(buf+234, 2);
235 memcpy(buf+236, &h->recon_type, 2); if(little) swabip(buf+236, 2);
236 memcpy(buf+238, &h->recon_views, 2); if(little) swabip(buf+238, 2);
237 memcpy(buf+240, &h->fill_cti, 87);
238 memcpy(buf+414, &h->fill_user, 48);
239
240 /* Write header */
241 fseek(fp, (blk-1)*MatBLKSIZE, SEEK_SET); if(ftell(fp)!=(blk-1)*MatBLKSIZE) return(4);
242 if(fwrite(buf, 1, 1*MatBLKSIZE, fp) != 1*MatBLKSIZE) return(5);
243
244 return(0);
245}
246/*****************************************************************************/
247
248/*****************************************************************************/
258int ecat7WriteAttenheader(FILE *fp, int blk, ECAT7_attenheader *h) {
259 unsigned char buf[MatBLKSIZE];
260 int little; /* 1 if current platform is little endian (i386), else 0 */
261
262 if(ECAT7_TEST) printf("ecat7WriteAttenheader()\n");
263 if(fp==NULL || blk<2 || h==NULL) return(1);
264 little=little_endian(); if(ECAT7_TEST) printf("little=%d\n", little);
265 /* Clear buf */
266 memset(buf, 0, MatBLKSIZE);
270
271 /* Copy the header fields and swap if necessary */
272 memcpy(buf+0, &h->data_type, 2); if(little) swabip(buf+0, 2);
273 memcpy(buf+2, &h->num_dimensions, 2); if(little) swabip(buf+2, 2);
274 memcpy(buf+4, &h->attenuation_type, 2); if(little) swabip(buf+4, 2);
275 memcpy(buf+6, &h->num_r_elements, 2); if(little) swabip(buf+6, 2);
276 memcpy(buf+8, &h->num_angles, 2); if(little) swabip(buf+8, 2);
277 memcpy(buf+10, &h->num_z_elements, 2); if(little) swabip(buf+10, 2);
278 memcpy(buf+12, &h->ring_difference, 2); if(little) swabip(buf+12, 2);
279 memcpy(buf+14, &h->x_resolution, 4); if(little) swawbip(buf+14, 4);
280 memcpy(buf+18, &h->y_resolution, 4); if(little) swawbip(buf+18, 4);
281 memcpy(buf+22, &h->z_resolution, 4); if(little) swawbip(buf+22, 4);
282 memcpy(buf+26, &h->w_resolution, 4); if(little) swawbip(buf+26, 4);
283 memcpy(buf+30, &h->scale_factor, 4); if(little) swawbip(buf+30, 4);
284 memcpy(buf+34, &h->x_offset, 4); if(little) swawbip(buf+34, 4);
285 memcpy(buf+38, &h->y_offset, 4); if(little) swawbip(buf+38, 4);
286 memcpy(buf+42, &h->x_radius, 4); if(little) swawbip(buf+42, 4);
287 memcpy(buf+46, &h->y_radius, 4); if(little) swawbip(buf+46, 4);
288 memcpy(buf+50, &h->tilt_angle, 4); if(little) swawbip(buf+50, 4);
289 memcpy(buf+54, &h->attenuation_coeff, 4); if(little) swawbip(buf+54, 4);
290 memcpy(buf+58, &h->attenuation_min, 4); if(little) swawbip(buf+58, 4);
291 memcpy(buf+62, &h->attenuation_max, 4); if(little) swawbip(buf+62, 4);
292 memcpy(buf+66, &h->skull_thickness, 4); if(little) swawbip(buf+66, 4);
293 memcpy(buf+70, &h->num_additional_atten_coeff, 2); if(little) swabip(buf+70, 2);
294 memcpy(buf+72, h->additional_atten_coeff, 8*4); if(little) swawbip(buf+72, 8*4);
295 memcpy(buf+104, &h->edge_finding_threshold, 4); if(little) swawbip(buf+104, 4);
296 memcpy(buf+108, &h->storage_order, 2); if(little) swabip(buf+108, 2);
297 memcpy(buf+110, &h->span, 2); if(little) swabip(buf+110, 2);
298 memcpy(buf+112, h->z_elements, 64*2); if(little) swabip(buf+112, 64*2);
299 memcpy(buf+240, h->fill_cti, 86*2); if(little) swabip(buf+240, 86*2);
300 memcpy(buf+412, h->fill_user, 50*2); if(little) swabip(buf+412, 50*2);
301
302 /* Write header */
303 fseek(fp, (blk-1)*MatBLKSIZE, SEEK_SET);
304 if(ftell(fp)!=(blk-1)*MatBLKSIZE) return(4);
305 if(fwrite(buf, 1, 1*MatBLKSIZE, fp) != 1*MatBLKSIZE) return(5);
306
307 return(0);
308}
309/*****************************************************************************/
310
311/*****************************************************************************/
321int ecat7WritePolmapheader(FILE *fp, int blk, ECAT7_polmapheader *h) {
322 unsigned char buf[MatBLKSIZE];
323 int little; /* 1 if current platform is little endian (i386), else 0 */
324
325 if(ECAT7_TEST) printf("ecat7WritePolmapheader()\n");
326 if(fp==NULL || blk<2 || h==NULL) return(1);
327 little=little_endian(); if(ECAT7_TEST) printf("little=%d\n", little);
328 /* Clear buf */
329 memset(buf, 0, MatBLKSIZE);
333
334 /* Copy the header fields and swap if necessary */
335 memcpy(buf+0, &h->data_type, 2); if(little) swabip(buf+0, 2);
336 memcpy(buf+2, &h->polar_map_type, 2); if(little) swabip(buf+2, 2);
337 memcpy(buf+4, &h->num_rings, 2); if(little) swabip(buf+4, 2);
338 memcpy(buf+6, h->sectors_per_ring, 32*2); if(little) swabip(buf+6, 32*2);
339 memcpy(buf+70, h->ring_position, 32*4); if(little) swawbip(buf+70, 32*4);
340 memcpy(buf+198, h->ring_angle, 32*2); if(little) swabip(buf+198, 32*2);
341 memcpy(buf+262, &h->start_angle, 2); if(little) swabip(buf+262, 2);
342 memcpy(buf+264, h->long_axis_left, 3*2); if(little) swabip(buf+264, 3*2);
343 memcpy(buf+270, h->long_axis_right, 3*2); if(little) swabip(buf+270, 3*2);
344 memcpy(buf+276, &h->position_data, 2); if(little) swabip(buf+276, 2);
345 memcpy(buf+278, &h->image_min, 2); if(little) swabip(buf+278, 2);
346 memcpy(buf+280, &h->image_max, 2); if(little) swabip(buf+280, 2);
347 memcpy(buf+282, &h->scale_factor, 4); if(little) swawbip(buf+282, 4);
348 memcpy(buf+286, &h->pixel_size, 4); if(little) swawbip(buf+286, 4);
349 memcpy(buf+290, &h->frame_duration, 4); if(little) swawbip(buf+290, 4);
350 memcpy(buf+294, &h->frame_start_time, 4); if(little) swawbip(buf+294, 4);
351 memcpy(buf+298, &h->processing_code, 2); if(little) swabip(buf+298, 2);
352 memcpy(buf+300, &h->quant_units, 2); if(little) swabip(buf+300, 2);
353 memcpy(buf+302, h->annotation, 40);
354 memcpy(buf+342, &h->gate_duration, 4); if(little) swawbip(buf+342, 4);
355 memcpy(buf+346, &h->r_wave_offset, 4); if(little) swawbip(buf+346, 4);
356 memcpy(buf+350, &h->num_accepted_beats, 4); if(little) swawbip(buf+350, 4);
357 memcpy(buf+354, h->polar_map_protocol, 20);
358 memcpy(buf+374, h->database_name, 30);
359 memcpy(buf+404, h->fill_cti, 27*2); if(little) swabip(buf+404, 27*2);
360
361 /* Write header */
362 fseek(fp, (blk-1)*MatBLKSIZE, SEEK_SET);
363 if(ftell(fp)!=(blk-1)*MatBLKSIZE) return(4);
364 if(fwrite(buf, 1, 1*MatBLKSIZE, fp) != 1*MatBLKSIZE) return(5);
365
366 return(0);
367}
368/*****************************************************************************/
369
370/*****************************************************************************/
380int ecat7WriteNormheader(FILE *fp, int blk, ECAT7_normheader *h) {
381 unsigned char buf[MatBLKSIZE];
382 int little; /* 1 if current platform is little endian (i386), else 0 */
383
384 if(ECAT7_TEST) printf("ecat7WriteNormheader()\n");
385 if(fp==NULL || blk<2 || h==NULL) return(1);
386 little=little_endian(); if(ECAT7_TEST) printf("little=%d\n", little);
387 /* Clear buf */
388 memset(buf, 0, MatBLKSIZE);
392
393 /* Copy the header fields and swap if necessary */
394 memcpy(buf+0, &h->data_type, 2); if(little) swabip(buf+0, 2);
395 memcpy(buf+2, &h->num_r_elements, 2); if(little) swabip(buf+2, 2);
396 memcpy(buf+4, &h->num_transaxial_crystals, 2); if(little) swabip(buf+4, 2);
397 memcpy(buf+6, &h->num_crystal_rings, 2); if(little) swabip(buf+6, 2);
398 memcpy(buf+8, &h->crystals_per_ring, 2); if(little) swabip(buf+8, 2);
399 memcpy(buf+10, &h->num_geo_corr_planes, 2); if(little) swabip(buf+10, 2);
400 memcpy(buf+12, &h->uld, 2); if(little) swabip(buf+12, 2);
401 memcpy(buf+14, &h->lld, 2); if(little) swabip(buf+14, 2);
402 memcpy(buf+16, &h->scatter_energy, 2); if(little) swabip(buf+16, 2);
403 memcpy(buf+18, &h->norm_quality_factor, 4); if(little) swawbip(buf+18, 4);
404 memcpy(buf+22, &h->norm_quality_factor_code, 2); if(little) swabip(buf+22, 2);
405 memcpy(buf+24, h->ring_dtcor1, 32*4); if(little) swawbip(buf+24, 32*4);
406 memcpy(buf+152, h->ring_dtcor2, 32*4); if(little) swawbip(buf+152, 32*4);
407 memcpy(buf+280, h->crystal_dtcor, 8*4); if(little) swawbip(buf+280, 8*4);
408 memcpy(buf+312, &h->span, 2); if(little) swabip(buf+312, 2);
409 memcpy(buf+314, &h->max_ring_diff, 2); if(little) swabip(buf+314, 2);
410 memcpy(buf+316, h->fill_cti, 48*2); if(little) swabip(buf+316, 48*2);
411 memcpy(buf+412, h->fill_user, 50*2); if(little) swabip(buf+412, 50*2);
412
413 /* Write header */
414 fseek(fp, (blk-1)*MatBLKSIZE, SEEK_SET);
415 if(ftell(fp)!=(blk-1)*MatBLKSIZE) return(4);
416 if(fwrite(buf, 1, 1*MatBLKSIZE, fp) != 1*MatBLKSIZE) return(5);
417
418 return(0);
419}
420/*****************************************************************************/
421
422/*****************************************************************************/
433int ecat7WriteScanheader(FILE *fp, int blk, ECAT7_scanheader *h) {
434 unsigned char buf[2*MatBLKSIZE];
435 int little; /* 1 if current platform is little endian (i386), else 0 */
436
437 if(ECAT7_TEST) printf("ecat7WriteScanheader()\n");
438 if(fp==NULL || blk<2 || h==NULL) return(1);
439 little=little_endian(); if(ECAT7_TEST) printf("little=%d\n", little);
440 /* Clear buf */
441 memset(buf, 0, 2*MatBLKSIZE);
445
446 /* Copy the header fields and swap if necessary */
447 memcpy(buf+0, &h->data_type, 2); if(little) swabip(buf+0, 2);
448 memcpy(buf+2, &h->num_dimensions, 2); if(little) swabip(buf+2, 2);
449 memcpy(buf+4, &h->num_r_elements, 2); if(little) swabip(buf+4, 2);
450 memcpy(buf+6, &h->num_angles, 2); if(little) swabip(buf+6, 2);
451 memcpy(buf+8, &h->corrections_applied, 2); if(little) swabip(buf+8, 2);
452 memcpy(buf+10, h->num_z_elements, 64*2); if(little) swabip(buf+10, 64*2);
453 memcpy(buf+138, &h->ring_difference, 2); if(little) swabip(buf+138, 2);
454 memcpy(buf+140, &h->storage_order, 2); if(little) swabip(buf+140, 2);
455 memcpy(buf+142, &h->axial_compression, 2); if(little) swabip(buf+142, 2);
456 memcpy(buf+144, &h->x_resolution, 4); if(little) swawbip(buf+144, 4);
457 memcpy(buf+148, &h->v_resolution, 4); if(little) swawbip(buf+148, 4);
458 memcpy(buf+152, &h->z_resolution, 4); if(little) swawbip(buf+152, 4);
459 memcpy(buf+156, &h->w_resolution, 4); if(little) swawbip(buf+156, 4);
460 memcpy(buf+160, h->fill_gate, 6*2); if(little) swabip(buf+160, 6*2);
461 memcpy(buf+172, &h->gate_duration, 4); if(little) swawbip(buf+172, 4);
462 memcpy(buf+176, &h->r_wave_offset, 4); if(little) swawbip(buf+176, 4);
463 memcpy(buf+180, &h->num_accepted_beats, 4); if(little) swawbip(buf+180, 4);
464 memcpy(buf+184, &h->scale_factor, 4); if(little) swawbip(buf+184, 4);
465 memcpy(buf+188, &h->scan_min, 2); if(little) swabip(buf+188, 2);
466 memcpy(buf+190, &h->scan_max, 2); if(little) swabip(buf+190, 2);
467 memcpy(buf+192, &h->prompts, 4); if(little) swawbip(buf+192, 4);
468 memcpy(buf+196, &h->delayed, 4); if(little) swawbip(buf+196, 4);
469 memcpy(buf+200, &h->multiples, 4); if(little) swawbip(buf+200, 4);
470 memcpy(buf+204, &h->net_trues, 4); if(little) swawbip(buf+204, 4);
471 memcpy(buf+208, &h->tot_avg_cor, 4); if(little) swawbip(buf+208, 4);
472 memcpy(buf+212, &h->tot_avg_uncor, 4); if(little) swawbip(buf+212, 4);
473 memcpy(buf+216, &h->total_coin_rate, 4); if(little) swawbip(buf+216, 4);
474 memcpy(buf+220, &h->frame_start_time, 4); if(little) swawbip(buf+220, 4);
475 memcpy(buf+224, &h->frame_duration, 4); if(little) swawbip(buf+224, 4);
476 memcpy(buf+228, &h->deadtime_correction_factor, 4); if(little) swawbip(buf+228, 4);
477 memcpy(buf+232, h->fill_cti, 90*2); if(little) swabip(buf+232, 90*2);
478 memcpy(buf+412, h->fill_user, 50*2); if(little) swabip(buf+412, 50*2);
479 memcpy(buf+512, h->uncor_singles, 128*4); if(little) swawbip(buf+512, 128*4);
480
481 /* Write 3D scan header */
482 fseek(fp, (blk-1)*MatBLKSIZE, SEEK_SET); if(ftell(fp)!=(blk-1)*MatBLKSIZE) return(4);
483 if(fwrite(buf, 1, 2*MatBLKSIZE, fp) != 2*MatBLKSIZE) return(5);
484
485 return(0);
486}
487/*****************************************************************************/
488
489/*****************************************************************************/
499int ecat7Write2DScanheader(FILE *fp, int blk, ECAT7_2Dscanheader *h) {
500 unsigned char buf[MatBLKSIZE];
501 int little; /* 1 if current platform is little endian (i386), else 0 */
502
503 if(ECAT7_TEST) printf("ecat7Write2DScanheader()\n");
504 if(fp==NULL || blk<2 || h==NULL) return(1);
505 little=little_endian(); if(ECAT7_TEST) printf("little=%d\n", little);
506 /* Clear buf */
507 memset(buf, 0, MatBLKSIZE);
511
512 /* Copy the header fields and swap if necessary */
513 memcpy(buf+0, &h->data_type, 2); if(little) swabip(buf+0, 2);
514 memcpy(buf+2, &h->num_dimensions, 2); if(little) swabip(buf+2, 2);
515 memcpy(buf+4, &h->num_r_elements, 2); if(little) swabip(buf+4, 2);
516 memcpy(buf+6, &h->num_angles, 2); if(little) swabip(buf+6, 2);
517 memcpy(buf+8, &h->corrections_applied, 2); if(little) swabip(buf+8, 2);
518 memcpy(buf+10, &h->num_z_elements, 2); if(little) swabip(buf+10, 2);
519 memcpy(buf+12, &h->ring_difference, 2); if(little) swabip(buf+12, 2);
520 memcpy(buf+14, &h->x_resolution, 4); if(little) swawbip(buf+14, 4);
521 memcpy(buf+18, &h->y_resolution, 4); if(little) swawbip(buf+18, 4);
522 memcpy(buf+22, &h->z_resolution, 4); if(little) swawbip(buf+22, 4);
523 memcpy(buf+26, &h->w_resolution, 4); if(little) swawbip(buf+26, 4);
524 memcpy(buf+30, h->fill_gate, 6*2); if(little) swabip(buf+30, 6*2);
525 memcpy(buf+42, &h->gate_duration, 4); if(little) swawbip(buf+42, 4);
526 memcpy(buf+46, &h->r_wave_offset, 4); if(little) swawbip(buf+46, 4);
527 memcpy(buf+50, &h->num_accepted_beats, 4); if(little) swawbip(buf+50, 4);
528 memcpy(buf+54, &h->scale_factor, 4); if(little) swawbip(buf+54, 4);
529 memcpy(buf+58, &h->scan_min, 2); if(little) swabip(buf+58, 2);
530 memcpy(buf+60, &h->scan_max, 2); if(little) swabip(buf+60, 2);
531 memcpy(buf+62, &h->prompts, 4); if(little) swawbip(buf+62, 4);
532 memcpy(buf+66, &h->delayed, 4); if(little) swawbip(buf+66, 4);
533 memcpy(buf+70, &h->multiples, 4); if(little) swawbip(buf+70, 4);
534 memcpy(buf+74, &h->net_trues, 4); if(little) swawbip(buf+74, 4);
535 memcpy(buf+78, h->cor_singles, 16*4); if(little) swawbip(buf+78, 16*4);
536 memcpy(buf+142, h->uncor_singles, 16*4); if(little) swawbip(buf+142, 16*4);
537 memcpy(buf+206, &h->tot_avg_cor, 4); if(little) swawbip(buf+206, 4);
538 memcpy(buf+210, &h->tot_avg_uncor, 4); if(little) swawbip(buf+210, 4);
539 memcpy(buf+214, &h->total_coin_rate, 4); if(little) swawbip(buf+214, 4);
540 memcpy(buf+218, &h->frame_start_time, 4); if(little) swawbip(buf+218, 4);
541 memcpy(buf+222, &h->frame_duration, 4); if(little) swawbip(buf+222, 4);
542 memcpy(buf+226, &h->deadtime_correction_factor, 4); if(little) swawbip(buf+226, 4);
543 memcpy(buf+230, h->physical_planes, 8*2); if(little) swabip(buf+230, 8*2);
544 memcpy(buf+246, h->fill_cti, 83*2); if(little) swabip(buf+246, 83*2);
545 memcpy(buf+412, h->fill_user, 50*2); if(little) swabip(buf+412, 50*2);
546
547 /* Write header */
548 fseek(fp, (blk-1)*MatBLKSIZE, SEEK_SET);
549 if(ftell(fp)!=(blk-1)*MatBLKSIZE) return(4);
550 if(fwrite(buf, 1, 1*MatBLKSIZE, fp) != 1*MatBLKSIZE) return(5);
551
552 return(0);
553}
554/*****************************************************************************/
555
556/*****************************************************************************/
566int ecat7Write2DNormheader(FILE *fp, int blk, ECAT7_2Dnormheader *h) {
567 unsigned char buf[MatBLKSIZE];
568 int little; /* 1 if current platform is little endian (i386), else 0 */
569
570 if(ECAT7_TEST) printf("ecat7Write2DNormheader()\n");
571 if(fp==NULL || blk<2 || h==NULL) return(1);
572 little=little_endian(); if(ECAT7_TEST) printf("little=%d\n", little);
573 /* Clear buf */
574 memset(buf, 0, MatBLKSIZE);
578
579 /* Copy the header fields and swap if necessary */
580 memcpy(buf+0, &h->data_type, 2); if(little) swabip(buf+0, 2);
581 memcpy(buf+2, &h->num_dimensions, 2); if(little) swabip(buf+2, 2);
582 memcpy(buf+4, &h->num_r_elements, 2); if(little) swabip(buf+4, 2);
583 memcpy(buf+6, &h->num_angles, 2); if(little) swabip(buf+6, 2);
584 memcpy(buf+8, &h->num_z_elements, 2); if(little) swabip(buf+8, 2);
585 memcpy(buf+10, &h->ring_difference, 2); if(little) swabip(buf+10, 2);
586 memcpy(buf+12, &h->scale_factor, 4); if(little) swawbip(buf+12, 4);
587 memcpy(buf+16, &h->norm_min, 4); if(little) swawbip(buf+16, 4);
588 memcpy(buf+20, &h->norm_max, 4); if(little) swawbip(buf+20, 4);
589 memcpy(buf+24, &h->fov_source_width, 4); if(little) swawbip(buf+24, 4);
590 memcpy(buf+28, &h->norm_quality_factor, 4); if(little) swawbip(buf+28, 4);
591 memcpy(buf+32, &h->norm_quality_factor_code, 2); if(little) swabip(buf+32, 2);
592 memcpy(buf+34, &h->storage_order, 2); if(little) swabip(buf+34, 2);
593 memcpy(buf+36, &h->span, 2); if(little) swabip(buf+36, 2);
594 memcpy(buf+38, h->fill_cti, 64*2); if(little) swabip(buf+38, 64*2);
595 memcpy(buf+166, h->fill_cti, 123*2); if(little) swabip(buf+166, 123*2);
596 memcpy(buf+412, h->fill_user, 50*2); if(little) swabip(buf+412, 50*2);
597
598 /* Write header */
599 fseek(fp, (blk-1)*MatBLKSIZE, SEEK_SET);
600 if(ftell(fp)!=(blk-1)*MatBLKSIZE) return(4);
601 if(fwrite(buf, 1, 1*MatBLKSIZE, fp) != 1*MatBLKSIZE) return(5);
602
603 return(0);
604}
605/*****************************************************************************/
606
607/*****************************************************************************/
616FILE *ecat7Create(const char *fname, ECAT7_mainheader *h) {
617 FILE *fp;
618 char tmp[FILENAME_MAX];
619 int buf[MatBLKSIZE/4];
620
621 if(ECAT7_TEST) printf("ecat7Create(%s, h)\n", fname);
622 /* Check the arguments */
623 if(fname==NULL || h==NULL) return(NULL);
624 /* Check if file exists; backup, if necessary */
625 if(access(fname, 0) != -1) {
626 strcpy(tmp, fname); strcat(tmp, BACKUP_EXTENSION);
627 if(access(tmp, 0) != -1) remove(tmp);
628 if(ECAT7_TEST) printf("Renaming %s -> %s\n", fname, tmp);
629 rename(fname, tmp);
630 }
631 /* Open file */
632 fp=fopen(fname, "wb+"); if(fp==NULL) return(fp);
633 /* Write main header */
634 if(ecat7WriteMainheader(fp, h)) return(NULL);
635 /* Construct an empty matrix list ; convert to little endian if necessary */
636 memset(buf, 0, MatBLKSIZE);
637 buf[0]=31; buf[1]=MatFirstDirBlk; if(little_endian()) swawbip(buf, MatBLKSIZE);
638 /* Write data buffer */
639 fseek(fp, (MatFirstDirBlk-1)*MatBLKSIZE, SEEK_SET);
640 if(ftell(fp)!=(MatFirstDirBlk-1)*MatBLKSIZE) return(NULL);
641 if(fwrite(buf, 4, MatBLKSIZE/4, fp) != MatBLKSIZE/4) return(NULL);
642 /* OK, then return file pointer */
643 return(fp);
644}
645/*****************************************************************************/
646
647/*****************************************************************************/
657int ecat7_is_scaling_needed(float amax, float *data, int nr) {
658 int i;
659 double d;
660
661 if(nr<1 || data==NULL) return(0);
662 /* scaling is necessary if all values are between -1 - 1 */
663 if(amax<0.9999) return(1);
664 /* Lets check first if at least the max value is close to integers or not */
665 if(modf(amax, &d)>0.0001) return(1);
666 /* if it is, then check all pixels */
667 for(i=0; i<nr; i++) if(modf(*data++, &d)>0.0001) return(1);
668 return(0);
669}
670/*****************************************************************************/
671
672/*****************************************************************************/
682int ecat7WriteImageMatrix(FILE *fp, int matrix_id, ECAT7_imageheader *h, float *fdata) {
683 int i, nxtblk, blkNr, data_size, pxlNr, ret;
684 float *fptr, fmin, fmax, g, f;
685 char *mdata, *mptr;
686 short int *sptr;
687
688
689 if(ECAT7_TEST) printf("ecat7WriteImageMatrix(fp, %d, h, data)\n", matrix_id);
690 if(fp==NULL || matrix_id<1 || h==NULL || fdata==NULL) {
691 sprintf(ecat7errmsg, "invalid function parameter.\n");
692 return(1);
693 }
694 if(h->data_type!=ECAT7_SUNI2) {
695 sprintf(ecat7errmsg, "invalid data_type.\n");
696 return(2);
697 }
698 /* nr of pixels */
699 pxlNr=h->x_dimension*h->y_dimension;
700 if(h->num_dimensions>2) pxlNr*=h->z_dimension;
701 if(pxlNr<1) {
702 sprintf(ecat7errmsg, "invalid matrix dimension.\n");
703 return(3);
704 }
705 /* How much memory is needed for ALL pixels */
706 data_size=pxlNr*ecat7pxlbytes(h->data_type);
707 /* block nr taken by all pixels */
708 blkNr=(data_size+MatBLKSIZE-1)/MatBLKSIZE; if(blkNr<1) {
709 sprintf(ecat7errmsg, "invalid block number.\n");
710 return(4);
711 }
712 /* Allocate memory for matrix data */
713 mdata=(char*)calloc(blkNr, MatBLKSIZE); if(mdata==NULL) {
714 sprintf(ecat7errmsg, "out of memory.\n");
715 return(5);
716 }
717 /* Search for min and max for calculation of scale factor */
718 fptr=fdata; fmin=fmax=*fptr;
719 for(i=0; i<pxlNr; i++, fptr++) {
720 if(*fptr>fmax) fmax=*fptr; else if(*fptr<fmin) fmin=*fptr;
721 }
722 if(fabs(fmin)>fabs(fmax)) g=fabs(fmin); else g=fabs(fmax);
723 if(g>0) f=32766./g; else f=1.0;
724 /* Check if pixels values can be left as such with scale_factor = 1 */
725 fptr=fdata;
726 if(f>=1.0 && ecat7_is_scaling_needed(g, fptr, pxlNr)==0) f=1.0;
727 /* Scale matrix data to shorts */
728 h->scale_factor=1.0/f;
729 sptr=(short int*)mdata; fptr=fdata;
730 for(i=0; i<pxlNr; i++, sptr++, fptr++) *sptr=(short int)temp_roundf(f*(*fptr));
731 /* Set header short min & max */
732 h->image_min=(short int)temp_roundf(f*fmin);
733 h->image_max=(short int)temp_roundf(f*fmax);
734 /* Get block number for matrix header and data */
735 nxtblk=ecat7EnterMatrix(fp, matrix_id, blkNr); if(nxtblk<1) {
736 sprintf(ecat7errmsg, "cannot determine matrix block (%d).\n", -nxtblk);
737 free(mdata); return(8);
738 }
739 if(ECAT7_TEST>2) printf(" block=%d fmin=%g fmax=%g\n", nxtblk, fmin, fmax);
740 /* Write header */
741 ret=ecat7WriteImageheader(fp, nxtblk, h); if(ret) {
742 sprintf(ecat7errmsg, "cannot write subheader (%d).\n", ret);
743 free(mdata); return(10);
744 }
745 /* Write matrix data */
746 mptr=mdata;
747 ret=ecat7WriteMatrixdata(fp, nxtblk+1, mptr, pxlNr, ecat7pxlbytes(h->data_type));
748 free(mdata);
749 if(ret) {
750 sprintf(ecat7errmsg, "cannot write matrix data (%d).\n", ret);
751 return(13);
752 }
753 return(0);
754}
755/*****************************************************************************/
756
757/*****************************************************************************/
767int ecat7Write2DScanMatrix(FILE *fp, int matrix_id, ECAT7_2Dscanheader *h, float *fdata) {
768 int i, nxtblk, blkNr, data_size, pxlNr, ret;
769 float *fptr, fmin, fmax, g, f;
770 char *mdata, *mptr;
771 short int *sptr;
772
773
774 if(ECAT7_TEST) printf("ecat7Write2DScanMatrix(fp, %d, h, data)\n", matrix_id);
775 if(fp==NULL || matrix_id<1 || h==NULL || fdata==NULL) {
776 sprintf(ecat7errmsg, "invalid function parameter.\n");
777 return(1);
778 }
779 if(h->data_type!=ECAT7_SUNI2) {
780 sprintf(ecat7errmsg, "invalid data_type.\n");
781 return(2);
782 }
783 /* nr of pixels */
784 pxlNr=h->num_r_elements*h->num_angles;
785 if(h->num_dimensions>2) pxlNr*=h->num_z_elements;
786 if(pxlNr<1) {
787 sprintf(ecat7errmsg, "invalid matrix dimension.\n");
788 return(3);
789 }
790 /* How much memory is needed for ALL pixels */
791 data_size=pxlNr*ecat7pxlbytes(h->data_type);
792 /* block nr taken by all pixels */
793 blkNr=(data_size+MatBLKSIZE-1)/MatBLKSIZE; if(blkNr<1) {
794 sprintf(ecat7errmsg, "invalid block number.\n");
795 return(4);
796 }
797 /* Allocate memory for matrix data */
798 mdata=(char*)calloc(blkNr, MatBLKSIZE); if(mdata==NULL) {
799 sprintf(ecat7errmsg, "out of memory.\n");
800 return(5);
801 }
802 /* Search for min and max for calculation of scale factor */
803 fptr=fdata; fmin=fmax=*fptr;
804 for(i=0; i<pxlNr; i++, fptr++) {
805 if(*fptr>fmax) fmax=*fptr; else if(*fptr<fmin) fmin=*fptr;
806 }
807 if(fabs(fmin)>fabs(fmax)) g=fabs(fmin); else g=fabs(fmax);
808 if(g>0) f=32766./g; else f=1.0;
809 /* Check if pixels values can be left as such with scale_factor = 1 */
810 fptr=fdata;
811 if(f>=1.0 && ecat7_is_scaling_needed(g, fptr, pxlNr)==0) f=1.0;
812 /* Scale matrix data to shorts */
813 h->scale_factor=1.0/f;
814 sptr=(short int*)mdata; fptr=fdata;
815 for(i=0; i<pxlNr; i++, sptr++, fptr++) *sptr=(short int)temp_roundf(f*(*fptr));
816 /* Set header short min & max */
817 h->scan_min=(short int)temp_roundf(f*fmin);
818 h->scan_max=(short int)temp_roundf(f*fmax);
819 /* Get block number for matrix header and data */
820 nxtblk=ecat7EnterMatrix(fp, matrix_id, blkNr); if(nxtblk<1) {
821 sprintf(ecat7errmsg, "cannot determine matrix block (%d).\n", -nxtblk);
822 free(mdata); return(8);
823 }
824 if(ECAT7_TEST>2) printf(" block=%d fmin=%g fmax=%g\n", nxtblk, fmin, fmax);
825 /* Write header */
826 ret=ecat7Write2DScanheader(fp, nxtblk, h); if(ret) {
827 sprintf(ecat7errmsg, "cannot write subheader (%d).\n", ret);
828 free(mdata); return(10);
829 }
830 /* Write matrix data */
831 mptr=mdata;
832 ret=ecat7WriteMatrixdata(fp, nxtblk+1, mptr, pxlNr, ecat7pxlbytes(h->data_type));
833 free(mdata);
834 if(ret) {
835 sprintf(ecat7errmsg, "cannot write matrix data (%d).\n", ret);
836 return(13);
837 }
838 return(0);
839}
840/*****************************************************************************/
841
842/*****************************************************************************/
852int ecat7WriteScanMatrix(FILE *fp, int matrix_id, ECAT7_scanheader *h, float *fdata) {
853 int i, nxtblk, blkNr, data_size, pxlNr, dimz, ret;
854 float *fptr, fmin, fmax, g, f;
855 char *mdata, *mptr;
856 short int *sptr;
857
858
859 if(ECAT7_TEST) printf("ecat7WriteScanMatrix(fp, %d, h, data)\n", matrix_id);
860 if(fp==NULL || matrix_id<1 || h==NULL || fdata==NULL) {
861 sprintf(ecat7errmsg, "invalid function parameter.\n");
862 return(1);
863 }
864 if(h->data_type!=ECAT7_SUNI2) {
865 sprintf(ecat7errmsg, "invalid data_type.\n");
866 return(2);
867 }
868 /* nr of pixels */
869 pxlNr=h->num_r_elements*h->num_angles;
870 for(i=dimz=0; i<64; i++) dimz+=h->num_z_elements[i]; pxlNr*=dimz;
871 if(pxlNr<1) {
872 sprintf(ecat7errmsg, "invalid matrix dimension.\n");
873 return(3);
874 }
875 /* How much memory is needed for ALL pixels */
876 data_size=pxlNr*ecat7pxlbytes(h->data_type);
877 /* block nr taken by all pixels */
878 blkNr=(data_size+MatBLKSIZE-1)/MatBLKSIZE; if(blkNr<1) {
879 sprintf(ecat7errmsg, "invalid block number.\n");
880 return(4);
881 }
882 /* Allocate memory for matrix data */
883 mdata=(char*)calloc(blkNr, MatBLKSIZE); if(mdata==NULL) {
884 sprintf(ecat7errmsg, "out of memory.\n");
885 return(5);
886 }
887 /* Search for min and max for calculation of scale factor */
888 fptr=fdata; fmin=fmax=*fptr;
889 for(i=0; i<pxlNr; i++, fptr++) {
890 if(*fptr>fmax) fmax=*fptr; else if(*fptr<fmin) fmin=*fptr;
891 }
892 if(fabs(fmin)>fabs(fmax)) g=fabs(fmin); else g=fabs(fmax);
893 if(g>0) f=32766./g; else f=1.0;
894 /* Check if pixels values can be left as such with scale_factor = 1 */
895 fptr=fdata;
896 if(f>=1.0 && ecat7_is_scaling_needed(g, fptr, pxlNr)==0) f=1.0;
897 /* Scale matrix data to shorts */
898 h->scale_factor=1.0/f;
899 sptr=(short int*)mdata; fptr=fdata;
900 for(i=0; i<pxlNr; i++, sptr++, fptr++) *sptr=(short int)temp_roundf(f*(*fptr));
901 /* Set header short min & max */
902 h->scan_min=(short int)temp_roundf(f*fmin);
903 h->scan_max=(short int)temp_roundf(f*fmax);
904 /* Get block number for matrix header and data */
905 /* Note that one extra block (blkNr+1) is needed for 3D scan header */
906 nxtblk=ecat7EnterMatrix(fp, matrix_id, blkNr+1); if(nxtblk<1) {
907 sprintf(ecat7errmsg, "cannot determine matrix block (%d).\n", -nxtblk);
908 free(mdata); return(8);
909 }
910 if(ECAT7_TEST>2) printf(" block=%d fmin=%g fmax=%g\n", nxtblk, fmin, fmax);
911 /* Write header */
912 ret=ecat7WriteScanheader(fp, nxtblk, h); if(ret) {
913 sprintf(ecat7errmsg, "cannot write subheader (%d).\n", ret);
914 free(mdata); return(10);
915 }
916 /* Write matrix data */
917 /* Note that 3D scan header takes TWO blocks */
918 mptr=mdata;
919 ret=ecat7WriteMatrixdata(fp, nxtblk+2, mptr, pxlNr, ecat7pxlbytes(h->data_type));
920 free(mdata);
921 if(ret) {
922 sprintf(ecat7errmsg, "cannot write matrix data (%d).\n", ret);
923 return(13);
924 }
925 return(0);
926}
927/*****************************************************************************/
928
929/*****************************************************************************/
939int ecat7WritePolarmapMatrix(FILE *fp, int matrix_id, ECAT7_polmapheader *h, float *fdata) {
940 int i, nxtblk, blkNr, data_size, pxlNr, ret;
941 float *fptr, fmin, fmax, g, f;
942 char *mdata, *mptr;
943 short int *sptr;
944
945
946 if(ECAT7_TEST) printf("ecat7WritePolarmapMatrix(fp, %d, h, data)\n", matrix_id);
947 if(fp==NULL || matrix_id<1 || h==NULL || fdata==NULL) {
948 sprintf(ecat7errmsg, "invalid function parameter.\n");
949 return(1);
950 }
951 if(h->data_type!=ECAT7_SUNI2) {
952 sprintf(ecat7errmsg, "invalid data_type.\n");
953 return(2);
954 }
955 /* nr of pixels */
956 for(i=pxlNr=0; i<h->num_rings; i++) pxlNr+=h->sectors_per_ring[i];
957 if(pxlNr<1) {
958 sprintf(ecat7errmsg, "invalid matrix dimension.\n");
959 return(3);
960 }
961 /* How much memory is needed for ALL pixels */
962 data_size=pxlNr*ecat7pxlbytes(h->data_type);
963 /* block nr taken by all pixels */
964 blkNr=(data_size+MatBLKSIZE-1)/MatBLKSIZE; if(blkNr<1) {
965 sprintf(ecat7errmsg, "invalid block number.\n");
966 return(4);
967 }
968 /* Allocate memory for matrix data */
969 mdata=(char*)calloc(blkNr, MatBLKSIZE); if(mdata==NULL) {
970 sprintf(ecat7errmsg, "out of memory.\n");
971 return(5);
972 }
973 /* Search for min and max for calculation of scale factor */
974 fptr=fdata; fmin=fmax=*fptr;
975 for(i=0; i<pxlNr; i++, fptr++) {
976 if(*fptr>fmax) fmax=*fptr; else if(*fptr<fmin) fmin=*fptr;
977 }
978 if(fabs(fmin)>fabs(fmax)) g=fabs(fmin); else g=fabs(fmax);
979 if(g>0) f=32766./g; else f=1.0;
980 /* Check if pixels values can be left as such with scale_factor = 1 */
981 fptr=fdata;
982 if(f>=1.0 && ecat7_is_scaling_needed(g, fptr, pxlNr)==0) f=1.0;
983 /* Scale matrix data to shorts */
984 h->scale_factor=1.0/f;
985 sptr=(short int*)mdata; fptr=fdata;
986 for(i=0; i<pxlNr; i++, sptr++, fptr++) *sptr=(short int)temp_roundf(f*(*fptr));
987 /* Set header short min & max */
988 h->image_min=(short int)temp_roundf(f*fmin);
989 h->image_max=(short int)temp_roundf(f*fmax);
990 /* Get block number for matrix header and data */
991 nxtblk=ecat7EnterMatrix(fp, matrix_id, blkNr); if(nxtblk<1) {
992 sprintf(ecat7errmsg, "cannot determine matrix block (%d).\n", -nxtblk);
993 free(mdata); return(8);
994 }
995 if(ECAT7_TEST>2) printf(" block=%d fmin=%g fmax=%g\n", nxtblk, fmin, fmax);
996 /* Write header */
997 ret=ecat7WritePolmapheader(fp, nxtblk, h); if(ret) {
998 sprintf(ecat7errmsg, "cannot write subheader (%d).\n", ret);
999 free(mdata); return(10);
1000 }
1001 /* Write matrix data */
1002 mptr=mdata;
1003 ret=ecat7WriteMatrixdata(fp, nxtblk+1, mptr, pxlNr, ecat7pxlbytes(h->data_type));
1004 free(mdata);
1005 if(ret) {
1006 sprintf(ecat7errmsg, "cannot write matrix data (%d).\n", ret);
1007 return(13);
1008 }
1009 return(0);
1010}
1011/*****************************************************************************/
1012
1013/*****************************************************************************/
1027int ecat7WriteMatrixdata(FILE *fp, int start_block, char *data, int pxl_nr, int pxl_size) {
1028 unsigned char buf[MatBLKSIZE];
1029 char *dptr;
1030 int i, blkNr, dataSize, byteNr, little;
1031
1032 if(ECAT7_TEST) printf("ecat7WriteMatrixdata(fp, %d, data, %d, %d)\n",
1033 start_block, pxl_nr, pxl_size);
1034 if(fp==NULL || start_block<1 || data==NULL || pxl_nr<1 || pxl_size<1) return(1);
1035 little=little_endian(); memset(buf, 0, MatBLKSIZE);
1036 dataSize=pxl_nr*pxl_size;
1037 /* block nr taken by all pixels */
1038 blkNr=(dataSize+MatBLKSIZE-1)/MatBLKSIZE; if(blkNr<1) return(1);
1039 if(ECAT7_TEST>2) printf(" blkNr=%d\n", blkNr);
1040 /* Search the place for writing */
1041 fseek(fp, (start_block-1)*MatBLKSIZE, SEEK_SET);
1042 if(ftell(fp)!=(start_block-1)*MatBLKSIZE) return(2);
1043 /* Save blocks one at a time */
1044 for(i=0, dptr=data; i<blkNr && dataSize>0; i++) {
1045 byteNr=(dataSize<MatBLKSIZE)?dataSize:MatBLKSIZE;
1046 memcpy(buf, dptr, byteNr);
1047 /* Change matrix byte order in little endian platforms */
1048 if(little) {
1049 if(pxl_size==2) swabip(buf, byteNr);
1050 else if(pxl_size==4) swawbip(buf, byteNr);
1051 }
1052 /* Write block */
1053 if(fwrite(buf, 1, MatBLKSIZE, fp)!=MatBLKSIZE) return(3);
1054 /* Prepare for the next block */
1055 dptr+=byteNr; dataSize-=byteNr;
1056 } /* next block */
1057 return(0);
1058}
1059/*****************************************************************************/
1060
1061/*****************************************************************************/
1062
#define BACKUP_EXTENSION
Definition analyze.h:19
#define MatFirstDirBlk
Definition ecat63.h:28
#define MatBLKSIZE
Definition ecat63.h:27
#define ECAT7_IEEER4
Definition ecat7.h:62
#define ECAT7_VAXI4
Definition ecat7.h:60
char ecat7errmsg[128]
Definition ecat7.h:99
#define ECAT7_SUNI4
Definition ecat7.h:64
#define ECAT7_VAXI2
Definition ecat7.h:59
#define ECAT7_VAXR4
Definition ecat7.h:61
int ECAT7_TEST
Definition ecat7.h:101
#define ECAT7_SUNI2
Definition ecat7.h:63
int ecat7EnterMatrix(FILE *fp, int matrix_id, int block_nr)
Definition ecat7ml.c:184
int ecat7pxlbytes(short int data_type)
Definition ecat7r.c:1055
int ecat7WriteImageMatrix(FILE *fp, int matrix_id, ECAT7_imageheader *h, float *fdata)
Definition ecat7w.c:682
int ecat7WriteScanMatrix(FILE *fp, int matrix_id, ECAT7_scanheader *h, float *fdata)
Definition ecat7w.c:852
int ecat7WriteNormheader(FILE *fp, int blk, ECAT7_normheader *h)
Definition ecat7w.c:380
int ecat7WriteScanheader(FILE *fp, int blk, ECAT7_scanheader *h)
Definition ecat7w.c:433
int ecat7WriteImageheader(FILE *fp, int blk, ECAT7_imageheader *h)
Definition ecat7w.c:164
int ecat7_is_scaling_needed(float amax, float *data, int nr)
Definition ecat7w.c:657
int ecat7WritePolarmapMatrix(FILE *fp, int matrix_id, ECAT7_polmapheader *h, float *fdata)
Definition ecat7w.c:939
int ecat7WritePolmapheader(FILE *fp, int blk, ECAT7_polmapheader *h)
Definition ecat7w.c:321
int ecat7Write2DScanheader(FILE *fp, int blk, ECAT7_2Dscanheader *h)
Definition ecat7w.c:499
int ecat7Write2DScanMatrix(FILE *fp, int matrix_id, ECAT7_2Dscanheader *h, float *fdata)
Definition ecat7w.c:767
int ecat7Write2DNormheader(FILE *fp, int blk, ECAT7_2Dnormheader *h)
Definition ecat7w.c:566
FILE * ecat7Create(const char *fname, ECAT7_mainheader *h)
Definition ecat7w.c:616
int ecat7WriteAttenheader(FILE *fp, int blk, ECAT7_attenheader *h)
Definition ecat7w.c:258
int ecat7WriteMatrixdata(FILE *fp, int start_block, char *data, int pxl_nr, int pxl_size)
Definition ecat7w.c:1027
int ecat7WriteMainheader(FILE *fp, ECAT7_mainheader *h)
Definition ecat7w.c:73
short int fill_cti[123]
Definition ecat7.h:474
short int storage_order
Definition ecat7.h:471
short int fill_user[50]
Definition ecat7.h:475
short int num_dimensions
Definition ecat7.h:460
float scale_factor
Definition ecat7.h:465
float norm_quality_factor
Definition ecat7.h:469
short int num_angles
Definition ecat7.h:462
float fov_source_width
Definition ecat7.h:468
short int num_z_elements
Definition ecat7.h:463
short int span
Definition ecat7.h:472
short int norm_quality_factor_code
Definition ecat7.h:470
short int num_r_elements
Definition ecat7.h:461
short int ring_difference
Definition ecat7.h:464
short int data_type
Definition ecat7.h:459
short int fill_user[50]
Definition ecat7.h:455
int num_accepted_beats
Definition ecat7.h:437
short int physical_planes[8]
Definition ecat7.h:453
float tot_avg_uncor
Definition ecat7.h:448
short int fill_gate[6]
Definition ecat7.h:434
short int num_dimensions
Definition ecat7.h:424
short int num_z_elements
Definition ecat7.h:428
short int ring_difference
Definition ecat7.h:429
short int scan_min
Definition ecat7.h:439
float x_resolution
Definition ecat7.h:430
float deadtime_correction_factor
Definition ecat7.h:452
short int corrections_applied
Definition ecat7.h:427
float w_resolution
Definition ecat7.h:433
short int data_type
Definition ecat7.h:423
float tot_avg_cor
Definition ecat7.h:447
float y_resolution
Definition ecat7.h:431
short int scan_max
Definition ecat7.h:440
short int num_angles
Definition ecat7.h:426
short int fill_cti[83]
Definition ecat7.h:454
short int num_r_elements
Definition ecat7.h:425
float uncor_singles[16]
Definition ecat7.h:446
float scale_factor
Definition ecat7.h:438
float z_resolution
Definition ecat7.h:432
float cor_singles[16]
Definition ecat7.h:445
short int data_type
Definition ecat7.h:480
short int num_dimensions
Definition ecat7.h:482
float edge_finding_threshold
Definition ecat7.h:526
float z_resolution
Definition ecat7.h:498
short int span
Definition ecat7.h:530
short int attenuation_type
Definition ecat7.h:484
short int num_angles
Definition ecat7.h:488
float attenuation_min
Definition ecat7.h:516
float scale_factor
Definition ecat7.h:502
short int num_z_elements
Definition ecat7.h:490
short int fill_cti[86]
Definition ecat7.h:534
float tilt_angle
Definition ecat7.h:512
float w_resolution
Definition ecat7.h:500
float y_resolution
Definition ecat7.h:496
short int ring_difference
Definition ecat7.h:492
short int num_r_elements
Definition ecat7.h:486
float additional_atten_coeff[8]
Definition ecat7.h:524
short int fill_user[50]
Definition ecat7.h:536
float attenuation_max
Definition ecat7.h:518
short int num_additional_atten_coeff
Definition ecat7.h:522
float attenuation_coeff
Definition ecat7.h:514
float x_resolution
Definition ecat7.h:494
float skull_thickness
Definition ecat7.h:520
short int storage_order
Definition ecat7.h:528
short int z_elements[64]
Definition ecat7.h:532
float num_angles
Definition ecat7.h:274
short int recon_type
Definition ecat7.h:344
short int image_max
Definition ecat7.h:252
short int filter_order
Definition ecat7.h:294
short int y_dimension
Definition ecat7.h:236
float filter_scatter_slope
Definition ecat7.h:298
short int scatter_type
Definition ecat7.h:342
float scale_factor
Definition ecat7.h:248
short int rfilter_code
Definition ecat7.h:324
short int x_dimension
Definition ecat7.h:234
float x_pixel_size
Definition ecat7.h:254
float z_pixel_size
Definition ecat7.h:258
float zfilter_cutoff
Definition ecat7.h:328
int frame_start_time
Definition ecat7.h:262
int processing_code
Definition ecat7.h:280
short int fill_cti[87]
Definition ecat7.h:348
float recon_zoom
Definition ecat7.h:246
float decay_corr_fctr
Definition ecat7.h:278
short int z_dimension
Definition ecat7.h:238
short int rfilter_order
Definition ecat7.h:326
float num_r_elements
Definition ecat7.h:272
float y_resolution
Definition ecat7.h:268
short int zfilter_order
Definition ecat7.h:334
float filter_resolution
Definition ecat7.h:290
float x_resolution
Definition ecat7.h:266
int num_accepted_beats
Definition ecat7.h:286
short int data_type
Definition ecat7.h:230
float z_resolution
Definition ecat7.h:270
float filter_ramp_slope
Definition ecat7.h:292
float zfilter_resolution
Definition ecat7.h:330
float rfilter_resolution
Definition ecat7.h:322
short int fill_user[49]
Definition ecat7.h:350
float filter_scatter_fraction
Definition ecat7.h:296
float z_rotation_angle
Definition ecat7.h:276
short int num_dimensions
Definition ecat7.h:232
short int image_min
Definition ecat7.h:250
short int filter_code
Definition ecat7.h:264
char annotation[40]
Definition ecat7.h:300
short int recon_views
Definition ecat7.h:346
short int zfilter_code
Definition ecat7.h:332
float y_pixel_size
Definition ecat7.h:256
float rfilter_cutoff
Definition ecat7.h:320
float filter_cutoff_frequency
Definition ecat7.h:288
char serial_number[10]
Definition ecat7.h:115
char patient_name[32]
Definition ecat7.h:158
char study_description[32]
Definition ecat7.h:178
float well_counter_corr_factor
Definition ecat7.h:219
short int compression_code
Definition ecat7.h:152
char physician_name[32]
Definition ecat7.h:174
short int patient_orientation
Definition ecat7.h:183
short int file_type
Definition ecat7.h:113
char isotope_name[8]
Definition ecat7.h:119
int scan_start_time
Definition ecat7.h:117
float distance_scanned
Definition ecat7.h:137
char original_file_name[32]
Definition ecat7.h:107
char facility_name[20]
Definition ecat7.h:185
char patient_id[16]
Definition ecat7.h:156
float transaxial_fov
Definition ecat7.h:139
short int sw_version
Definition ecat7.h:109
short int num_gates
Definition ecat7.h:191
short int upr_true_thres
Definition ecat7.h:205
short int angular_compression
Definition ecat7.h:141
short int calibration_units
Definition ecat7.h:148
short int fill_cti[6]
Definition ecat7.h:225
float patient_weight
Definition ecat7.h:168
float gantry_tilt
Definition ecat7.h:125
short int transm_source_type
Definition ecat7.h:135
short int wobble_speed
Definition ecat7.h:133
char magic_number[14]
Definition ecat7.h:105
float plane_separation
Definition ecat7.h:199
int dose_start_time
Definition ecat7.h:215
short int num_frames
Definition ecat7.h:189
float gantry_rotation
Definition ecat7.h:127
float init_bed_position
Definition ecat7.h:195
short int coin_samp_mode
Definition ecat7.h:143
short int acquisition_type
Definition ecat7.h:181
float bed_elevation
Definition ecat7.h:129
float isotope_halflife
Definition ecat7.h:121
char user_process_code[10]
Definition ecat7.h:207
short int axial_samp_mode
Definition ecat7.h:145
char operator_name[32]
Definition ecat7.h:176
short int calibration_units_label
Definition ecat7.h:150
char data_units[32]
Definition ecat7.h:221
short int num_planes
Definition ecat7.h:187
short int acquisition_mode
Definition ecat7.h:209
float patient_height
Definition ecat7.h:166
char radiopharmaceutical[32]
Definition ecat7.h:123
int patient_birth_date
Definition ecat7.h:172
short int septa_state
Definition ecat7.h:223
float bin_size
Definition ecat7.h:211
float intrinsic_tilt
Definition ecat7.h:131
float branching_fraction
Definition ecat7.h:213
char patient_dexterity
Definition ecat7.h:162
short int num_bed_pos
Definition ecat7.h:193
float patient_age
Definition ecat7.h:164
float ecat_calibration_factor
Definition ecat7.h:146
short int lwr_true_thres
Definition ecat7.h:203
short int lwr_sctr_thres
Definition ecat7.h:201
short int system_type
Definition ecat7.h:111
char patient_sex
Definition ecat7.h:160
char study_type[12]
Definition ecat7.h:154
float bed_position[15]
Definition ecat7.h:197
short int num_crystal_rings
Definition ecat7.h:546
short int lld
Definition ecat7.h:553
float norm_quality_factor
Definition ecat7.h:557
short int norm_quality_factor_code
Definition ecat7.h:559
short int scatter_energy
Definition ecat7.h:555
short int num_geo_corr_planes
Definition ecat7.h:549
short int max_ring_diff
Definition ecat7.h:569
short int span
Definition ecat7.h:567
float ring_dtcor1[32]
Definition ecat7.h:561
short int num_transaxial_crystals
Definition ecat7.h:544
short int uld
Definition ecat7.h:551
short int crystals_per_ring
Definition ecat7.h:547
short int fill_user[50]
Definition ecat7.h:573
float ring_dtcor2[32]
Definition ecat7.h:563
float crystal_dtcor[8]
Definition ecat7.h:565
short int fill_cti[48]
Definition ecat7.h:571
short int num_r_elements
Definition ecat7.h:542
short int data_type
Definition ecat7.h:540
short int fill_cti[27]
Definition ecat7.h:601
short int processing_code
Definition ecat7.h:593
short int polar_map_type
Definition ecat7.h:578
float ring_position[32]
Definition ecat7.h:581
short int image_max
Definition ecat7.h:588
short int num_rings
Definition ecat7.h:579
char database_name[30]
Definition ecat7.h:600
short int sectors_per_ring[32]
Definition ecat7.h:580
short int data_type
Definition ecat7.h:577
char annotation[40]
Definition ecat7.h:595
short int quant_units
Definition ecat7.h:594
short int long_axis_left[3]
Definition ecat7.h:584
int num_accepted_beats
Definition ecat7.h:598
char polar_map_protocol[20]
Definition ecat7.h:599
short int image_min
Definition ecat7.h:587
float scale_factor
Definition ecat7.h:589
short int start_angle
Definition ecat7.h:583
short int position_data
Definition ecat7.h:586
short int ring_angle[32]
Definition ecat7.h:582
short int long_axis_right[3]
Definition ecat7.h:585
short int corrections_applied
Definition ecat7.h:363
float z_resolution
Definition ecat7.h:377
float uncor_singles[128]
Definition ecat7.h:419
float w_resolution
Definition ecat7.h:379
float v_resolution
Definition ecat7.h:375
float x_resolution
Definition ecat7.h:373
short int fill_cti[90]
Definition ecat7.h:415
short int num_dimensions
Definition ecat7.h:357
short int num_angles
Definition ecat7.h:361
int gate_duration
Definition ecat7.h:383
short int scan_max
Definition ecat7.h:393
short int num_z_elements[64]
Definition ecat7.h:365
int frame_start_time
Definition ecat7.h:409
float scale_factor
Definition ecat7.h:389
float tot_avg_uncor
Definition ecat7.h:405
short int fill_user[50]
Definition ecat7.h:417
float deadtime_correction_factor
Definition ecat7.h:413
float tot_avg_cor
Definition ecat7.h:403
short int data_type
Definition ecat7.h:355
short int axial_compression
Definition ecat7.h:371
short int fill_gate[6]
Definition ecat7.h:381
short int ring_difference
Definition ecat7.h:367
int r_wave_offset
Definition ecat7.h:385
int frame_duration
Definition ecat7.h:411
int num_accepted_beats
Definition ecat7.h:387
short int scan_min
Definition ecat7.h:391
short int num_r_elements
Definition ecat7.h:359
short int storage_order
Definition ecat7.h:369
int total_coin_rate
Definition ecat7.h:407