54f8f7d66cce47b12657f9509ac39ad667718ab9
[ctsim.git] / libctsim / projections.cpp
1 /*****************************************************************************
2 ** FILE IDENTIFICATION
3 **
4 **   Name:         projections.cpp         Projection data classes
5 **   Programmer:   Kevin Rosenberg
6 **   Date Started: Aug 84
7 **
8 **  This is part of the CTSim program
9 **  Copyright (C) 1983-2000 Kevin Rosenberg
10 **
11 **  $Id: projections.cpp,v 1.3 2000/06/20 17:54:51 kevin Exp $
12 **
13 **  This program is free software; you can redistribute it and/or modify
14 **  it under the terms of the GNU General Public License (version 2) as
15 **  published by the Free Software Foundation.
16 **
17 **  This program is distributed in the hope that it will be useful,
18 **  but WITHOUT ANY WARRANTY; without even the implied warranty of
19 **  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20 **  GNU General Public License for more details.
21 **
22 **  You should have received a copy of the GNU General Public License
23 **  along with this program; if not, write to the Free Software
24 **  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
25 ******************************************************************************/
26
27 #include "ct.h"
28
29
30 /* NAME
31  *    Projections               Constructor for projections matrix storage 
32  *
33  * SYNOPSIS
34  *    proj = projections_create (filename, nView, nDet)
35  *    Projections& proj         Allocated projections structure & matrix
36  *    int nView                 Number of rotated view
37  *    int nDet                  Number of detectors
38  *
39  */
40
41 Projections::Projections (const Scanner& scanner)
42   : m_projData(0)
43 {
44   initFromScanner (scanner);
45 }
46
47
48 Projections::Projections (const int nView, const int nDet)
49   : m_projData(0)
50 {
51   init (nView, nDet);
52 }
53
54 Projections::Projections (void)
55   : m_projData(0)
56 {
57   init (0, 0);
58 }
59
60 Projections::~Projections (void)
61 {
62   deleteProjData();
63 }
64
65
66 void
67 Projections::init (const int nView, const int nDet)
68 {
69   m_nView = nView;
70   m_nDet = nDet;
71   newProjData ();
72 }
73
74 void
75 Projections::initFromScanner (const Scanner& scanner)
76 {
77   deleteProjData();
78   init (scanner.nView(), scanner.nDet());
79
80   m_phmLen = scanner.phmLen();
81   m_rotInc = scanner.rotInc();
82   m_detInc = scanner.detInc();
83   m_rotStart = 0;
84   m_detStart =  -scanner.radius() + (scanner.detInc() / 2);
85   m_phmLen = scanner.phmLen();
86 }
87
88 void
89 Projections::setNView (int nView)  // used by MPI to reduce # of views
90 {
91   deleteProjData();
92   init (nView, m_nDet);
93 }
94
95 // NAME
96 // newProjData
97
98 void 
99 Projections::newProjData (void)
100 {
101   if (m_projData)
102     sys_error(ERR_WARNING, "m_projData != NULL [newProjData]");
103
104   if (m_nView > 0 && m_nDet) {
105     m_projData = new DetectorArray* [m_nView];
106
107     for (int i = 0; i < m_nView; i++)
108       m_projData[i] = new DetectorArray (m_nDet);
109   }
110 }
111
112
113 /* NAME
114  *   projections_free                   Free memory allocated to projections
115  *
116  * SYNOPSIS
117  *   projections_free(proj)
118  *   Projections& proj                          Projectionss to be deallocated
119  */
120
121 void 
122 Projections::deleteProjData (void)
123 {
124   if (m_projData != NULL) {
125     for (int i = 0; i < m_nView; i++)
126       delete m_projData[i];
127
128     delete m_projData;
129     m_projData = NULL;
130   }
131 }
132
133
134 /* NAME
135  *    projections_write_header         Write data header for projections file
136  *
137  */
138
139 bool 
140 Projections::headerWrite (fnetorderstream& fs)
141 {
142   kuint32 _hsize = m_headerSize;
143   kuint32 _nView = m_nView;
144   kuint32 _nDet = m_nDet;
145   kuint32 _geom = m_geometry;
146   kuint32 _remarksize = m_remark.length();
147   kfloat64 _calcTime = m_calcTime;
148   kfloat64 _rotStart = m_rotStart;
149   kfloat64 _rotInc = m_rotInc;
150   kfloat64 _detStart = m_detStart;
151   kfloat64 _detInc = m_detInc;
152   kfloat64 _phmLen = m_phmLen;
153   
154   fs.seekp(0);
155   if (! fs)
156     return false;
157
158   fs.writeInt32 (_hsize);
159   fs.writeInt32 (_nView);
160   fs.writeInt32 (_nDet);
161   fs.writeInt32 (_geom);
162   fs.writeFloat64 (_calcTime);
163   fs.writeFloat64 (_rotStart);
164   fs.writeFloat64 (_rotInc);
165   fs.writeFloat64 (_detStart);
166   fs.writeFloat64 (_detInc);
167   fs.writeFloat64 (_phmLen);
168   fs.writeInt32 (_remarksize);
169   fs.write (m_remark.c_str(), _remarksize);
170
171   m_headerSize = fs.tellp();
172   _hsize = m_headerSize;
173   fs.seekp(0);
174   fs.writeInt32 (_hsize);
175   if (! fs)
176       return false;
177   
178   return true;
179 }
180
181 /* NAME
182  *    projections_read_header         Read data header for projections file
183  *
184  */
185 bool
186 Projections::headerRead (fnetorderstream& fs)
187 {
188   kuint32 _hsize;
189   kuint32 _nView;
190   kuint32 _nDet;
191   kuint32 _geom;
192   kuint32 _remarksize = 0;
193   kfloat64 _calcTime;
194   kfloat64 _rotStart;
195   kfloat64 _rotInc;
196   kfloat64 _detStart;
197   kfloat64 _detInc;
198   kfloat64 _phmLen;
199   
200   fs.seekg(0);
201   if (! fs)
202       return false;
203
204   off_t testPos;
205   fs.readInt32 (_hsize);
206   fs.readInt32 (_nView);
207   fs.readInt32 (_nDet);
208   fs.readInt32 (_geom);
209   fs.readFloat64 (_calcTime);
210   fs.readFloat64 (_rotStart);
211   fs.readFloat64 (_rotInc);
212   fs.readFloat64 (_detStart);
213   fs.readFloat64 (_detInc);
214   fs.readFloat64 (_phmLen);
215   fs.readInt32 (_remarksize);
216   if (_remarksize > 100000) {
217     sys_error (ERR_SEVERE, "Insane _remarksize %d [projections::headerRead]", _remarksize);
218     return false;
219   }
220
221   if (! fs) {
222       sys_error (ERR_SEVERE, "Error reading header information , _remarksize=%d [projections_read_header]", _remarksize);
223       return false;
224   }
225
226   char remarkStorage[_remarksize+1];
227   fs.read (remarkStorage, _remarksize);
228   if (! fs) {
229     sys_error (ERR_SEVERE, "Error reading remark, _remarksize = %d", _remarksize);
230     return false;
231   }
232   remarkStorage[_remarksize] = 0;
233   m_remark = remarkStorage;
234
235   off_t _hsizeread = fs.tellg();
236   if (!fs || _hsizeread != _hsize) {
237       sys_error (ERR_WARNING, "File header size read %ld != file header size stored %ld [read_projections_header]\n_remarksize=%ld", (long int) _hsizeread, _hsize, _remarksize);
238       return false;
239   }
240   
241   m_headerSize = _hsize;
242   m_nView = _nView;
243   m_nDet = _nDet;
244   m_geometry = _geom;
245   m_calcTime = _calcTime;
246   m_rotStart = _rotStart;
247   m_rotInc = _rotInc;
248   m_detStart = _detStart;
249   m_detInc = _detInc;
250   m_phmLen = _phmLen;
251
252   return true;
253 }
254
255 bool
256 Projections::read (const char* filename)
257 {
258   frnetorderstream fileRead (filename, ios::in | ios::binary);
259
260   if (! fileRead)
261     return false;
262
263   if (! headerRead (fileRead))
264     return false;
265
266   deleteProjData ();
267   newProjData();
268
269   for (int i = 0; i < m_nView; i++) {
270     if (! detarrayRead (fileRead, *m_projData[i], i))
271       break;
272   }
273
274   fileRead.close();
275   return true;
276 }
277
278
279 bool
280 Projections::write (const char* filename)
281 {
282   frnetorderstream fs (filename, ios::out | ios::binary | ios::trunc | ios::ate);
283
284   if (! fs) {
285     sys_error (ERR_SEVERE, "Error opening file %s for output [projections_create]", filename);
286     return false;
287   }
288   if (! headerWrite (fs))
289       return false;
290
291   if (m_projData != NULL) {
292     for (int i = 0; i < m_nView; i++) {
293       if (! detarrayWrite (fs, *m_projData[i], i))
294         break;
295     }
296   }
297   if (! fs)
298     return false;
299
300  fs.close();
301
302   return true;
303 }
304
305 /* NAME
306  *   detarrayRead               Read a Detector Array structure from the disk
307  *
308  * SYNOPSIS
309  *   detarrayRead (proj, darray, view_num)
310  *   DETARRAY *darray           Detector array storage location to be filled
311  *   int      view_num          View number to read
312  */
313
314 bool
315 Projections::detarrayRead (fnetorderstream& fs, DetectorArray& darray, const int iview)
316 {
317   const int detval_bytes = darray.nDet() * sizeof(kfloat32);
318   const int detheader_bytes = sizeof(kfloat64) /* view_angle */ + sizeof(kint32) /* nDet */;
319   const int view_bytes = detheader_bytes + detval_bytes;
320   const off_t start_data = m_headerSize + (iview * view_bytes);
321   DetectorValue* detval_ptr = darray.detValues();  
322   kfloat64 view_angle;
323   kuint32 nDet;
324
325   fs.seekg (start_data);
326
327   fs.readFloat64 (view_angle);
328   fs.readInt32 (nDet);
329   darray.setViewAngle (view_angle);
330   //  darray.setNDet ( nDet);
331   
332   for (int i = 0; i < nDet; i++) {
333       kfloat32 detval;
334       fs.readFloat32 (detval);
335       detval_ptr[i] = detval;
336   }
337   if (! fs)
338     return false;
339
340   return true;
341 }
342
343
344 /* NAME
345  *   detarrayWrite                      Write detector array data to the disk
346  *
347  * SYNOPSIS
348  *   detarrayWrite (darray, view_num)
349  *   DETARRAY *darray                   Detector array data to be written
350  *   int      view_num                  View number to write
351  *
352  * DESCRIPTION
353  *       This routine writes the detarray data from the disk sequentially to
354  *    the file that was opened with open_projections().  Data is written in
355  *    binary format.
356  */
357
358 bool
359 Projections::detarrayWrite (fnetorderstream& fs, const DetectorArray& darray, const int iview)
360 {
361   const int detval_bytes = darray.nDet() * sizeof(float);
362   const int detheader_bytes = sizeof(kfloat64) /* view_angle */ + sizeof(kint32) /* nDet */;
363   const int view_bytes = detheader_bytes + detval_bytes;
364   const off_t start_data = m_headerSize + (iview * view_bytes);
365   const DetectorValue* const detval_ptr = darray.detValues();  
366   kfloat64 view_angle = darray.viewAngle();
367   kuint32 nDet = darray.nDet();
368   
369   fs.seekp (start_data);
370   if (! fs) {
371     sys_error (ERR_SEVERE, "Error seeking detectory array [detarrayWrite]");
372     return false;
373   }
374
375   fs.writeFloat64 (view_angle);
376   fs.writeInt32 (nDet);
377
378   for (int i = 0; i < nDet; i++) {
379     kfloat32 detval = detval_ptr[i];
380     fs.writeFloat32 (detval);
381   }
382
383   if (! fs)
384     return (false);
385
386   return true;
387 }
388
389 /* NAME
390  *   prt_projections                    Print projections data
391  *
392  * SYNOPSIS
393  *   prt_projections (proj)
394  *   Projections& proj                  Projection data to be printed
395  */
396
397 void
398 Projections::printProjectionData (void)
399 {
400   printf("Projections Print\n\n");
401   printf("Description: %s\n", m_remark.c_str());
402   printf("nView = %d  nDet = %d\n", m_nView, m_nDet);
403   printf("rotStart = %8.4f   rotInc = %8.4f\n", m_rotStart, m_rotInc);
404   printf("detStart = %8.4f   detInc = %8.4f\n", m_detStart, m_detInc);
405
406   if (m_projData != NULL) {
407       for (int ir = 0; ir < m_nView; ir++) {
408           DetectorValue* detval = m_projData[ir]->detValues();
409           for (int id = 0; id < m_projData[ir]->nDet(); id++)
410               printf("%8.4f  ", detval[id]);
411           printf("\n");
412       }
413   }
414 }
415
416 void 
417 Projections::printScanInfo (void) const
418 {
419   printf ("Number of detectors: %d\n", m_nDet);
420   printf ("    Number of views: %d\n", m_nView);
421   printf ("             Remark: %s\n", m_remark.c_str());
422   printf ("             phmLen: %f\n", m_phmLen);
423   printf ("           detStart: %f\n", m_detStart);
424   printf ("             detInc: %f\n", m_detInc);
425   printf ("           rotStart: %f\n", m_rotStart);
426   printf ("             rotInc: %f\n", m_rotInc);
427 }
428
429