CASToR  2.0
Tomographic Reconstruction (PET/SPECT/CT)
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
iDataFileCT.cc
Go to the documentation of this file.
1 /*
2 This file is part of CASToR.
3 
4  CASToR is free software: you can redistribute it and/or modify it under the
5  terms of the GNU General Public License as published by the Free Software
6  Foundation, either version 3 of the License, or (at your option) any later
7  version.
8 
9  CASToR is distributed in the hope that it will be useful, but WITHOUT ANY
10  WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11  FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
12  details.
13 
14  You should have received a copy of the GNU General Public License along with
15  CASToR (in file GNU_GPL.TXT). If not, see <http://www.gnu.org/licenses/>.
16 
17 Copyright 2017-2018 all CASToR contributors listed below:
18 
19  --> current contributors: Thibaut MERLIN, Simon STUTE, Didier BENOIT, Claude COMTAT, Marina FILIPOVIC, Mael MILLARDET
20  --> past contributors: Valentin VIELZEUF
21 
22 This is CASToR version 2.0.
23 */
24 
32 #include "iDataFileCT.hh"
33 
34 // =====================================================================
35 // ---------------------------------------------------------------------
36 // ---------------------------------------------------------------------
37 // =====================================================================
38 
40 {
41  // Set all members to default values
45  mp_angles = NULL;
46  m_eventKindFlag = false;
47  m_blankCorrectionFlag = false;
49  m_scatCorrectionFlag = false;
52 }
53 
54 // =====================================================================
55 // ---------------------------------------------------------------------
56 // ---------------------------------------------------------------------
57 // =====================================================================
58 
60 {
61  if (mp_angles) delete[] mp_angles;
62 }
63 
64 // =====================================================================
65 // ---------------------------------------------------------------------
66 // ---------------------------------------------------------------------
67 // =====================================================================
68 
69 int iDataFileCT::ReadSpecificInfoInHeader(bool a_affectQuantificationFlag)
70 {
71  // Verbose
73  if (m_verbose>=VERBOSE_DETAIL) Cout("iDataFileCT::ReadSpecificInfoInHeader() -> Read information specific to CT" << endl);
74 
75  // Create pointers dedicated to recover the addresses of the member variables of the scanner object
76  FLTNB* p_angles = NULL;
77 
78  // Get Geometric parameters recovered from the scanner object
79  sScannerManager* p_scannermanager;
80  p_scannermanager = sScannerManager::GetInstance();
81  p_scannermanager->GetCTSpecificParameters(&m_nbOfProjections,
82  p_angles,
84 
85  // Check m_nbOfProjections first before allocating projection angles and radius using this variable
86  if (m_nbOfProjections==0)
87  {
88  Cerr("***** iDataFileCT::ReadSpecificInfoInHeader() -> Number of projections should be strictly positive !" << endl);
89  return 1;
90  }
91 
92  // Allocation and initialization of Projection angles
94 
95  // Recover values
96  for (int a=0 ; a<m_nbOfProjections ; a++) mp_angles[a] = p_angles[a];
97 
98  // Feedback to user
100  {
101  Cout(" --> Provided projection angles" << endl);
102  for (int a=0 ; a<m_nbOfProjections ; a++) Cout(" " << mp_angles[a] << endl);
103  }
104 
105  // Read optional fields in the header, check if errors (issue during data reading/conversion (==1) )
106  if (ReadDataASCIIFile(m_headerFileName, "Event kind flag", &m_eventKindFlag, 1, 0) == 1 ||
107  ReadDataASCIIFile(m_headerFileName, "Blank correction flag", &m_blankCorrectionFlag, 1, 0) == 1 ||
108  ReadDataASCIIFile(m_headerFileName, "Scatter correction flag", &m_scatCorrectionFlag, 1, 0) == 1 )
109  {
110  Cerr("***** iDataFileCT::ReadSpecificInfoInHeader() -> Error while reading optional fields in the header data file !" << endl);
111  return 1;
112  }
113 
114  // Normal end
115  return 0;
116 }
117 
118 // =====================================================================
119 // ---------------------------------------------------------------------
120 // ---------------------------------------------------------------------
121 // =====================================================================
122 
124 {
125  iDataFileCT* p_DataFileCT = (dynamic_cast<iDataFileCT*>(ap_DataFile));
126  m_nbOfProjections = p_DataFileCT->GetNbProjections();
127  mp_angles = p_DataFileCT->GetAngles();
128  m_eventKindFlag = p_DataFileCT->GetEventKindFlag();
132  // End
133  return 0;
134 }
135 
136 // =====================================================================
137 // ---------------------------------------------------------------------
138 // ---------------------------------------------------------------------
139 // =====================================================================
140 
142 {
143  // Verbose
145  if (m_verbose>=VERBOSE_DETAIL) Cout("iDataFileCT::ComputeSizeEvent() -> In bytes" << endl);
146 
147  // For MODE_LIST events
148  if (m_dataMode == MODE_LIST)
149  {
150  // Size of the mandatory element in a list-mode event: Time + 2*eventID
151  m_sizeEvent = sizeof(uint32_t) + 2*sizeof(uint32_t);
152  // Optional flags
153  if (m_eventKindFlag) m_sizeEvent += sizeof(FLTNBDATA);
156  }
157  // For MODE_HISTOGRAM events
159  {
160  // Size of the mandatory element in a histo event: Time + event_value + 2*eventID
161  m_sizeEvent = sizeof(uint32_t) + sizeof(FLTNBDATA) + 2*sizeof(uint32_t);
162  // Optional flags
165  }
166  // Unknown event type
167  else
168  {
169  Cerr("***** iDataFileCT::ComputeSizeEvent() -> Unknown event mode !" << endl);
170  return 1;
171  }
172 
173  // Check
174  if (m_sizeEvent<=0)
175  {
176  Cerr("***** iDataFileCT::ComputeSizeEvent() -> Error, the Event size in bytes should be >= 0 !" << endl;);
177  return 1;
178  }
179 
180  // Verbose
181  if (m_verbose>=VERBOSE_DETAIL) Cout(" --> Event size: " << m_sizeEvent << " bytes" << endl);
182 
183  // End
184  return 0;
185 }
186 
187 // =====================================================================
188 // ---------------------------------------------------------------------
189 // ---------------------------------------------------------------------
190 // =====================================================================
191 
193 {
194  // Verbose
197  {
198  if (m_dataMode==MODE_HISTOGRAM) Cout("iDataFileCT::PrepareDataFile() -> Build histogram events" << endl);
199  else if (m_dataMode==MODE_LIST) Cout("iDataFileCT::PrepareDataFile() -> Build listmode events" << endl);
200  else if (m_dataMode==MODE_NORMALIZATION) Cout("iDataFileCT::PrepareDataFile() -> Build normalization events" << endl);
201  }
202 
203  // ==============================================================================
204  // Allocate event buffers (one for each thread)
205  // ==============================================================================
206 
207  if (m_verbose>=VERBOSE_DETAIL) Cout(" --> Allocate an event buffer for each thread" << endl);
208  // Instanciation of the event buffer according to the data type
210 
211  // Allocate the events per each thread
212  for (int th=0 ; th<mp_ID->GetNbThreadsForProjection() ; th++)
213  {
214  // For MODE_LIST events
215  if (m_dataMode == MODE_LIST)
216  {
217  m2p_BufferEvent[th] = new iEventListCT();
218  }
219  // For MODE_HISTOGRAM events
220  if (m_dataMode == MODE_HISTOGRAM)
221  {
222  m2p_BufferEvent[th] = new iEventHistoCT();
223  }
224  // Allocate pixel/view IDs
225  if (m2p_BufferEvent[th]->AllocateID())
226  {
227  Cerr("*****iDataFileCT::PrepareDataFile() -> Error while trying to allocate memory for the Event object!" << endl);
228  return 1;
229  }
230  }
231 
232  // ==============================================================================
233  // Deal with specific corrections
234  // ==============================================================================
235 
236  // In case of normalization correction flag, see if we ignore this correction
238  {
239  // Affect the ignored flag from the ignored corrections list processed by the oImageDimensionsAndQuantification.
240  // Note that we interpret the option to ignore the normalization as ignoring the blank correction for CT reconstructions
242  // Verbose
244  {
245  if (m_ignoreBlankCorrectionFlag) Cout(" --> Ignore blank correction" << endl);
246  else Cout(" --> Correct for blank" << endl);
247  }
248  }
249  // In case of scatter correction flag, see if we ignore this correction
251  {
252  // Affect the ignored flag from the ignored corrections list processed by the oImageDimensionsAndQuantification
254  // Verbose
256  {
257  if (m_ignoreScatCorrectionFlag) Cout(" --> Ignore scatter correction" << endl);
258  else Cout(" --> Correct for scatter events" << endl);
259  }
260  }
261 
262  // Normal end
263  return 0;
264 }
265 
266 // =====================================================================
267 // ---------------------------------------------------------------------
268 // ---------------------------------------------------------------------
269 // =====================================================================
270 
271 vEvent* iDataFileCT::GetEventSpecific(char* ap_buffer, int a_th)
272 {
274 
275  // Work on a copy of the input pointer
276  char* file_position = ap_buffer;
277 
278  // For MODE_LIST CT data
279  if (m_dataMode == MODE_LIST)
280  {
281  // Cast the event pointer
282  iEventListCT* event = (dynamic_cast<iEventListCT*>(m2p_BufferEvent[a_th]));
283  // Mandatory time field: [uint32_t (time)]
284  event->SetTimeInMs(*reinterpret_cast<uint32_t*>(file_position));
285  file_position += sizeof(uint32_t);
286  // Optional kind: [uint8_t kind]
287  if (m_eventKindFlag)
288  {
289  event->SetKind(*reinterpret_cast<uint8_t*>(file_position));
290  file_position += sizeof(uint8_t);
291  }
292  // Optional scatter correction field: [FLTNBDATA (scatter)]
294  {
295  if (!m_ignoreScatCorrectionFlag) event->SetScatterRate(*reinterpret_cast<FLTNBDATA*>(file_position));
296  file_position += sizeof(FLTNBDATA);
297  }
298  // Optional blank correction field: [FLTNBDATA (blank)]
300  {
301  if (!m_ignoreBlankCorrectionFlag) event->SetBlankValue(*reinterpret_cast<FLTNBDATA*>(file_position));
302  file_position += sizeof(FLTNBDATA);
303  }
304  // Mandatory angular projection ID: [uint32_t (ID1)]
305  event->SetID1(0, *reinterpret_cast<uint32_t*>(file_position));
306  file_position += sizeof(uint32_t);
307  // Mandatory pixel ID: [uint32_t (ID2)]
308  event->SetID2(0, *reinterpret_cast<uint32_t*>(file_position));
309  file_position += sizeof(uint32_t);
310  }
311 
312  // For MODE_HISTOGRAM CT DATA
313  if (m_dataMode == MODE_HISTOGRAM)
314  {
315  // Cast the event pointer
316  iEventHistoCT* event = (dynamic_cast<iEventHistoCT*>(m2p_BufferEvent[a_th]));
317  // Mandatory time field: [uint32_t (time)]
318  event->SetTimeInMs(*reinterpret_cast<uint32_t*>(file_position));
319  file_position += sizeof(uint32_t);
320  // Mandatory bin value: [FLTNBDATA bin value]
321  event->SetEventValue(0, *reinterpret_cast<FLTNBDATA*>(file_position));
322  file_position += sizeof(FLTNBDATA);
323  // Optional scatter correction field: [FLTNBDATA (scatter)]
325  {
326  if (!m_ignoreScatCorrectionFlag) event->SetScatterRate(*reinterpret_cast<FLTNBDATA*>(file_position));
327  file_position += sizeof(FLTNBDATA);
328  }
329  // Optional blank correction field: [FLTNBDATA (blank)]
331  {
332  if (!m_ignoreBlankCorrectionFlag) event->SetBlankValue(*reinterpret_cast<FLTNBDATA*>(file_position));
333  file_position += sizeof(FLTNBDATA);
334  }
335  // Mandatory angular projection ID: [uint32_t (ID1)]
336  event->SetID1(0, *reinterpret_cast<uint32_t*>(file_position));
337  file_position += sizeof(uint32_t);
338  // Mandatory pixel ID: [uint32_t (ID2)]
339  event->SetID2(0, *reinterpret_cast<uint32_t*>(file_position));
340  file_position += sizeof(uint32_t);
341  }
342 
343  // Return the updated event
344  return m2p_BufferEvent[a_th];
345 }
346 
347 // =====================================================================
348 // ---------------------------------------------------------------------
349 // ---------------------------------------------------------------------
350 // =====================================================================
351 
353 {
355  if (m_verbose==0) return;
356  // Describe the datafile
357  Cout("iDataFileCT::DescribeSpecific() -> Here is some specific content of the CT datafile" << endl);
358  if (m_dataMode==MODE_LIST && m_eventKindFlag) Cout(" --> Event kind is present" << endl);
359  if (m_blankCorrectionFlag) Cout(" --> Blank correction is present" << endl);
360  if (m_scatCorrectionFlag) Cout(" --> Scatter correction is present" << endl);
361  if (m_detectorRotDirection==GEO_ROT_CW) Cout(" --> Detector rotation is clockwise" << endl);
362  else if (m_detectorRotDirection==GEO_ROT_CCW) Cout(" --> Detector rotation is counter-clockwise" << endl);
363  else Cout(" --> Detector rotation is undefined !!!" << endl);
364  Cout(" --> Number of acquisition projections: " << m_nbOfProjections << endl);
365  for (uint16_t p=0; p<m_nbOfProjections; p++) Cout(" | Projection " << p << " at " << mp_angles[p] << " deg" << endl);
366 }
367 
368 // =====================================================================
369 // ---------------------------------------------------------------------
370 // ---------------------------------------------------------------------
371 // =====================================================================
372 
374 {
376  // Error if m_dataType != CT
377  if (m_dataType != TYPE_CT)
378  {
379  Cerr("***** iDataFileCT::CheckSpecificParameters() -> Data type should be CT !'" << endl);
380  return 1;
381  }
382  // Check number of projections
383  if (m_nbOfProjections == 0)
384  {
385  Cerr("***** iDataFileCT::CheckSpecificParameters() -> Number of projections not initialized (should be >0) !" << endl);
386  return 1;
387  }
388  // Check projection angles
389  if (mp_angles == NULL)
390  {
391  Cerr("***** iDataFileCT::CheckSpecificParameters() -> Projection angles not initialized !" << endl);
392  return 1;
393  }
394  // End
395  return 0;
396 }
397 
398 // =====================================================================
399 // ---------------------------------------------------------------------
400 // ---------------------------------------------------------------------
401 // =====================================================================
402 
404 {
406 
407  // Create the stream
408  fstream* p_file = new fstream( m_dataFileName.c_str(), ios::binary| ios::in );
409  // Check that datafile exists
410  if (!p_file->is_open())
411  {
412  Cerr("***** iDataFilePET::CheckFileSizeConsistency() -> Failed to open input file '" << m_dataFileName.c_str() << "' !" << endl);
413  Cerr(" (Provided in the data file header: " << m_headerFileName << ")" << endl);
414  return 1;
415  }
416  // Get file size in bytes
417  p_file->seekg(0, ios::end);
418  int64_t sizeInBytes = p_file->tellg();
419  // Close stream and delete it
420  p_file->close();
421  delete p_file;
422  // Check datafile self-consistency
423  if (m_nbEvents*m_sizeEvent != sizeInBytes)
424  {
425  Cerr("-------------------------------------------------------------------------------------------------------------------------------------" << endl);
426  Cerr("***** iDataFileCT::CheckFileSizeConsistency() -> DataFile size is not consistent with the information provided by the user/datafile !" << endl);
427  Cerr(" --> Expected size: "<< m_nbEvents*m_sizeEvent << endl);
428  Cerr(" --> Actual size: "<< sizeInBytes << endl << endl);
429  Cerr(" ADDITIONAL INFORMATION ABOUT THE DATAFILE INITIALIZATION" << endl);
430  if (m_eventKindFlag) Cerr(" --> Event kind term is enabled" << endl);
431  else Cerr(" --> No information about the kind of events in the data" << endl);
432  if (m_blankCorrectionFlag) Cerr(" --> Blank correction term is enabled" << endl);
433  else Cerr(" --> No blank correction term in the data" << endl);
434  if (m_scatCorrectionFlag) Cerr(" --> Scatter correction term is enabled" << endl);
435  else Cerr(" --> No scatter correction term in the data" << endl);
436  Cerr(" --> Calibration factor value is: " << m_calibrationFactor << endl);
437  Cerr("----------------------------------------------------------------------------------------------------------------------------------------" << endl);
438  return 1;
439  }
440  // End
441  return 0;
442 }
443 
444 // =====================================================================
445 // ---------------------------------------------------------------------
446 // ---------------------------------------------------------------------
447 // =====================================================================
448 
450 {
452  // Dynamic cast the vDataFile to a iDataFilePET
453  iDataFileCT* p_data_file = (dynamic_cast<iDataFileCT*>(ap_DataFile));
454  // Check event kind flag
455  if (m_eventKindFlag!=p_data_file->GetEventKindFlag())
456  {
457  Cerr("***** iDataFileCT::CheckSpecificConsistencyWithAnotherDataFile() -> Event kind flags are inconsistent !" << endl);
458  return 1;
459  }
460  // Check blank correction flag
461  if (m_blankCorrectionFlag!=p_data_file->GetBlankCorrectionFlag())
462  {
463  Cerr("***** iDataFileCT::CheckSpecificConsistencyWithAnotherDataFile() -> Blank correction flags are inconsistent !" << endl);
464  return 1;
465  }
466  // Check scatter correction flag
467  if (m_scatCorrectionFlag!=p_data_file->GetScatCorrectionFlag())
468  {
469  Cerr("***** iDataFileCT::CheckSpecificConsistencyWithAnotherDataFile() -> Scatter correction flags are inconsistent !" << endl);
470  return 1;
471  }
472  // Check data mode
473  if (m_dataMode!=p_data_file->GetDataMode())
474  {
475  Cerr("***** iDataFileCT::CheckSpecificConsistencyWithAnotherDataFile() -> Data modes are inconsistent (list-mode or histogram) !" << endl);
476  return 1;
477  }
478  // End
479  return 0;
480 }
481 
482 // =====================================================================
483 // ---------------------------------------------------------------------
484 // ---------------------------------------------------------------------
485 // =====================================================================
486 
488 {
490  // Check
491  if (m_nbOfProjections == 0)
492  {
493  Cerr("***** iDataFileCT::InitAngles() -> Number of projection angles not initialized !'" << endl);
494  return 1;
495  }
496  // Allocate
498  // Affect
499  for (uint16_t a=0 ; a<m_nbOfProjections ; a++) mp_angles[a] = ap_angles[a];
500  // End
501  return 0;
502 }
503 
504 // =====================================================================
505 // ---------------------------------------------------------------------
506 // ---------------------------------------------------------------------
507 // =====================================================================
508 
510 {
511  // Verbose
513  if (m_verbose>=VERBOSE_DETAIL) Cout("iDataFileCT::PROJ_InitFile() -> Initialize datafile for writing" << endl);
514 
515  m_startTimeInSec = 0.; //Std initialization for projection
516  m_durationInSec = 1.; //Std initialization for projection
517  m_nbEvents = 0; //Std initialization for projection
518  m_calibrationFactor = 1.;
519  m_scatCorrectionFlag = false;
520  m_blankCorrectionFlag = false;
521 
522  // Instanciate a fstream datafile for each thread
523  m2p_dataFile = new fstream*[mp_ID->GetNbThreadsForProjection()];
524 
525  // Set name of the projection data header
526  sOutputManager* p_OutMgr;
527  p_OutMgr = sOutputManager::GetInstance();
528  string path_name = p_OutMgr->GetPathName();
529  string img_name = p_OutMgr->GetBaseName();
530  m_headerFileName = path_name.append(img_name).append("_CstrProj").append(".Cdh");
531 
532  for (int th=0 ; th<mp_ID->GetNbThreadsForProjection() ; th++)
533  {
534  m_dataFileName = m_headerFileName.substr(0, m_headerFileName.find_last_of(".")).append(".Cdf"); // Generate datafile name from header file
535 
536  // Projeted data will be written in several files (corresponding to the number of thread) to be concatenated at the end of the projection process.
537  stringstream ss;
538  ss << th;
539 
540  string datafile_name = m_dataFileName;
541  datafile_name.append("_").append(ss.str());
542 
543  m2p_dataFile[th] = new fstream( datafile_name.c_str(), ios::binary | ios::out | ios::trunc);
544  }
545 
546  //remove content from the output data file, in case it already exists
547  //todo warn the user a datafile with the same name will be erased (eventually add an option to disable the warning)
548  ofstream output_file(m_dataFileName.c_str(), ios::out | ios::trunc);
549  output_file.close();
550 
551  if (m_verbose>=VERBOSE_DETAIL) Cout(" --> Output datafile name :" << m_dataFileName << endl);
552 
553  return 0;
554 }
555 
556 // =====================================================================
557 // ---------------------------------------------------------------------
558 // ---------------------------------------------------------------------
559 // =====================================================================
560 
561 int iDataFileCT::WriteEvent(vEvent* ap_Event, int a_th)
562 {
564 
565  if (m_dataMode == MODE_LIST)
566  {
567  // TODO should create as many vEvent as (int)fp.
568  if (WriteListEvent((iEventListCT*)ap_Event, a_th))
569  {
570  Cerr("*****iDataFileCT::WriteEvent() -> Error while trying to write projection datafile (list-mode)" << endl);
571  return 1;
572  }
573  }
574 
575  if (m_dataMode == MODE_HISTOGRAM)
576  {
577  if (WriteHistoEvent((iEventHistoCT*)ap_Event, a_th))
578  {
579  Cerr("*****iDataFileCT::WriteEvent() -> Error while trying to write projection datafile (histogram)" << endl);
580  return 1;
581  }
582  }
583 
584  return 0;
585 }
586 
587 // =====================================================================
588 // ---------------------------------------------------------------------
589 // ---------------------------------------------------------------------
590 // =====================================================================
591 
593 {
595 
596  // Write sequentially each field of the event according to the type of the event.
597  m2p_dataFile[a_th]->clear();
598 
599  uint32_t time = ap_Event->GetTimeInMs();
600  m2p_dataFile[a_th]->write(reinterpret_cast<char*>(&time), sizeof(uint32_t));
601 
602  FLTNB event_value = ap_Event->GetEventValue(0);
603  m2p_dataFile[a_th]->write(reinterpret_cast<char*>(&event_value), sizeof(FLTNB));
604 
606  {
607  FLTNB scat_rate = ap_Event->GetEventScatRate();
608  m2p_dataFile[a_th]->write(reinterpret_cast<char*>(&scat_rate), sizeof(FLTNB));
609  }
610 
612  {
613  FLTNB blank_corr_factor = ap_Event->GetBlankValue();
614  m2p_dataFile[a_th]->write(reinterpret_cast<char*>(&blank_corr_factor), sizeof(FLTNB));
615  }
616 
617  uint32_t id1 = ap_Event->GetID1(0);
618  uint32_t id2 = ap_Event->GetID2(0);
619  m2p_dataFile[a_th]->write(reinterpret_cast<char*>(&id1), sizeof(uint32_t));
620  m2p_dataFile[a_th]->write(reinterpret_cast<char*>(&id2), sizeof(uint32_t));
621 
622  return 0;
623 }
624 
625 // =====================================================================
626 // ---------------------------------------------------------------------
627 // ---------------------------------------------------------------------
628 // =====================================================================
629 
631 {
633 
634  // Write sequentially each field of the event according to the type of the event.
635  m2p_dataFile[a_th]->clear();
636 
637  uint32_t time = ap_Event->GetTimeInMs();
638  m2p_dataFile[a_th]->write(reinterpret_cast<char*>(&time), sizeof(uint32_t));
639 
640  if(m_eventKindFlag)
641  {
642  uint8_t event_kind = ap_Event->GetKind();
643  m2p_dataFile[a_th]->write(reinterpret_cast<char*>(&event_kind), sizeof(uint8_t));
644  }
645 
647  {
648  FLTNB scat_rate = ap_Event->GetEventScatRate();
649  m2p_dataFile[a_th]->write(reinterpret_cast<char*>(&scat_rate), sizeof(FLTNB));
650  }
651 
653  {
654  FLTNB blank_corr_factor = ap_Event->GetBlankValue();
655  m2p_dataFile[a_th]->write(reinterpret_cast<char*>(&blank_corr_factor), sizeof(FLTNB));
656  }
657 
658  uint32_t id1 = ap_Event->GetID1(0);
659  uint32_t id2 = ap_Event->GetID2(0);
660  m2p_dataFile[a_th]->write(reinterpret_cast<char*>(&id1), sizeof(uint32_t));
661  m2p_dataFile[a_th]->write(reinterpret_cast<char*>(&id2), sizeof(uint32_t));
662 
663  return 0;
664 }
665 
666 // =====================================================================
667 // ---------------------------------------------------------------------
668 // ---------------------------------------------------------------------
669 // =====================================================================
670 
672 {
673  // Verbose
675  if (m_verbose>=VERBOSE_NORMAL) Cout("iDataFileCT::WriteHeader() -> Write header file '" << m_headerFileName << "'" << endl);
676  // Open file
677  fstream headerFile;
678  headerFile.open(m_headerFileName.c_str(), ios::out);
679  if (!headerFile.is_open())
680  {
681  Cerr("***** iDataFileCT::WriteHeader() -> Failed to open output header file '" << m_headerFileName << "' !" << endl);
682  return 1;
683  }
684  // Data file name
685  headerFile << "Data filename: " << GetFileFromPath(m_dataFileName) << endl;
686  // Number of events
687  headerFile << "Number of events: " << m_nbEvents << endl;
688  // Data mode
689  if (m_dataMode==MODE_HISTOGRAM) headerFile << "Data mode: histogram" << endl;
690  else if (m_dataMode==MODE_LIST) headerFile << "Data mode: list-mode" << endl;
691  else if (m_dataMode==MODE_NORMALIZATION) headerFile << "Data mode: normalization" << endl;
692  // CT data type
693  headerFile << "Data type: CT" << endl;
694  // Acquisition start time in seconds
695  headerFile << "Start time (s): " << m_startTimeInSec << endl;
696  // Acquisition duration in seconds
697  headerFile << "Duration (s): " << m_durationInSec << endl;
698  // Scanner name
699  headerFile << "Scanner name:" << " " << sScannerManager::GetInstance()->GetScannerName() << endl;
700  // Number of projections
701  headerFile << "Number of projections: " << m_nbOfProjections << endl;
702  // Projection angles
703  headerFile << "Projection angles: " << mp_angles[0];
704  for (int a=1 ; a<m_nbOfProjections ; a++) headerFile << ", " << mp_angles[a];
705  headerFile << endl;
706  // Blank correction flag
707  headerFile << "Blank correction flag: " << m_blankCorrectionFlag << endl;
708  // Scatter correction flag
709  headerFile << "Scatter correction flag: " << m_scatCorrectionFlag << endl;
710  // Scanner rotation direction
711  string rot_direction = (m_detectorRotDirection == GEO_ROT_CCW) ? "CCW" : "CW";
712  headerFile << "Scanner rotation direction: " << rot_direction << endl;
713  // Close file
714  headerFile.close();
715  // End
716  return 0;
717 }
718 
719 // =====================================================================
720 // ---------------------------------------------------------------------
721 // ---------------------------------------------------------------------
722 // =====================================================================
723 
725 {
726  // Verbose
728  if (m_verbose>=VERBOSE_DETAIL) Cout("iDataFileCT::PROJ_GetScannerSpecificParameters() ..."<< endl);
729  // Create pointers dedicated to recover the addresses of the member variables of the scanner object
730  FLTNB* p_angles = NULL;
731  // Get pointers to CT specific parameters in scanner
732  if(sScannerManager::GetInstance()->GetCTSpecificParameters(&m_nbOfProjections, p_angles, &m_detectorRotDirection) )
733  {
734  Cerr("*****iDataFileCT::PROJ_GetScannerSpecificParameters() -> An error occurred while trying to get CT geometric parameters from the scanner object !" << endl);
735  return 1;
736  }
737  // Retrieve projection angles
739  for(int a=0 ; a<m_nbOfProjections ; a++)
740  mp_angles[a] = p_angles[a];
741  // End
742  return 0;
743 }
744 
745 // =====================================================================
746 // ---------------------------------------------------------------------
747 // ---------------------------------------------------------------------
748 // =====================================================================
This class is designed to be a mother virtual class for DataFile.
Definition: vDataFile.hh:103
static sScannerManager * GetInstance()
Instanciate the singleton object and Initialize member variables if not already done, return a pointer to this object otherwise.
bool GetScatCorrectionFlag()
Simply return m_scatCorrectionFlag.
Definition: iDataFileCT.hh:195
#define VERBOSE_DEBUG_EVENT
#define MODE_HISTOGRAM
Definition: vDataFile.hh:59
int64_t m_sizeEvent
Definition: vDataFile.hh:598
string m_dataFileName
Definition: vDataFile.hh:578
#define MODE_LIST
Definition: vDataFile.hh:57
#define FLTNB
Definition: gVariables.hh:81
#define MODE_NORMALIZATION
Definition: vDataFile.hh:61
FLTNB * mp_angles
Definition: iDataFileCT.hh:261
int GetDetectorRotDirection()
Simply return m_detectorRotDirection.
Definition: iDataFileCT.hh:174
int InitAngles(FLTNB *ap_angles)
allocate memory for the mp_angles variable using m_nbProjections and initialize the projection angles...
Definition: iDataFileCT.cc:487
int SetSpecificParametersFrom(vDataFile *ap_DataFile)
Initialize all parameters specific to CT from the provided datafile.
Definition: iDataFileCT.cc:123
uint32_t GetID2(int a_line)
Definition: vEvent.hh:108
uint8_t GetKind()
Definition: iEventListCT.hh:79
bool m_blankCorrectionFlag
Definition: iDataFileCT.hh:256
#define VERBOSE_DETAIL
#define GEO_ROT_CCW
Definition: vScanner.hh:49
FLTNB m_durationInSec
Definition: vDataFile.hh:584
Inherit from iEventCT. Class for CT list-mode events.
Definition: iEventListCT.hh:41
iDataFileCT()
iDataFileCT constructor. Initialize the member variables to their default values. ...
Definition: iDataFileCT.cc:39
string m_headerFileName
Definition: vDataFile.hh:577
bool m_ignoreScatCorrectionFlag
Definition: iDataFileCT.hh:259
uint16_t m_nbOfProjections
Definition: iDataFileCT.hh:260
int ReadSpecificInfoInHeader(bool a_affectQuantificationFlag)
Read through the header file and recover specific CT information.
Definition: iDataFileCT.cc:69
FLTNB GetEventScatRate()
Definition: iEventCT.hh:86
int m_dataMode
Definition: vDataFile.hh:580
static sOutputManager * GetInstance()
Instanciate the singleton object and Initialize member variables if not already done, return a pointer to this object otherwise.
Declaration of class iDataFileCT.
bool m_ignoreBlankCorrectionFlag
Definition: iDataFileCT.hh:257
#define TYPE_CT
Definition: vDataFile.hh:78
int m_dataSpec
Definition: vDataFile.hh:582
FLTNB m_startTimeInSec
Definition: vDataFile.hh:583
bool m_scatCorrectionFlag
Definition: iDataFileCT.hh:258
string GetFileFromPath(const string &a_pathToFile)
Simply return the file from a path string passed in parameter.
Definition: gOptions.cc:1141
int WriteHeader()
Generate a header file according to the data output information.
Definition: iDataFileCT.cc:671
bool GetIgnoreNormCorrectionFlag()
Get the boolean that says if the normalization correction is ignored or not.
#define FLTNBDATA
Definition: gVariables.hh:87
int WriteListEvent(iEventListCT *ap_Event, int a_th)
Write a CT list-mode event.
Definition: iDataFileCT.cc:630
#define Cerr(MESSAGE)
const string & GetPathName()
int ComputeSizeEvent()
Computation of the size of each event according to the mandatory/optional correction fields...
Definition: iDataFileCT.cc:141
#define VERBOSE_DEBUG_LIGHT
Singleton class that manages output writing on disk (images, sinograms, etc). It also manages loggi...
vEvent * GetEventSpecific(char *ap_buffer, int a_th)
Read an event from the position pointed by 'ap_buffer', parse the generic or modality-specific inform...
Definition: iDataFileCT.cc:271
FLTNB * GetAngles()
Definition: iDataFileCT.hh:153
int ReadDataASCIIFile(const string &a_file, const string &a_keyword, T *ap_return, int a_nbElts, bool a_mandatoryFlag)
Look for "a_nbElts" elts in the "a_file" file matching the "a_keyword" string passed as parameter a...
Definition: gOptions.cc:123
Singleton class that Instantiate and initialize the scanner object.
int m_dataType
Definition: vDataFile.hh:581
int64_t m_nbEvents
Definition: vDataFile.hh:579
oImageDimensionsAndQuantification * mp_ID
Definition: vDataFile.hh:573
fstream ** m2p_dataFile
Definition: vDataFile.hh:599
#define VERBOSE_NORMAL
int PROJ_GetScannerSpecificParameters()
Get SPECT specific parameters for projections from the scanner object, through the scannerManager...
Definition: iDataFileCT.cc:724
int CheckSpecificParameters()
Check parameters specific to CT data.
Definition: iDataFileCT.cc:373
void DescribeSpecific()
Implementation of the pure virtual eponym function that simply prints info about the datafile...
Definition: iDataFileCT.cc:352
Inherit from iEventCT. Class for CT histogram mode events.
int PROJ_InitFile()
Initialize the fstream objets for output writing as well as some other variables specific to the Proj...
Definition: iDataFileCT.cc:509
bool GetBlankCorrectionFlag()
Simply return m_blankCorrectionFlag.
Definition: iDataFileCT.hh:202
#define SPEC_TRANSMISSION
Definition: vDataFile.hh:93
bool GetEventKindFlag()
Simply return m_eventKindFlag.
Definition: iDataFileCT.hh:188
int m_detectorRotDirection
Definition: iDataFileCT.hh:262
int CheckSpecificConsistencyWithAnotherDataFile(vDataFile *ap_DataFile)
Check consistency between 'this' and the provided datafile, for specific characteristics.
Definition: iDataFileCT.cc:449
uint16_t GetNbProjections()
Definition: iDataFileCT.hh:147
FLTNB GetBlankValue()
Definition: iEventCT.hh:80
const string & GetBaseName()
void SetTimeInMs(uint32_t a_value)
Set the timestamp of the Event.
Definition: vEvent.hh:139
int WriteEvent(vEvent *ap_Event, int a_th=0)
Write event according to the chosen type of data.
Definition: iDataFileCT.cc:561
Mother class for the Event objects.
Definition: vEvent.hh:43
int GetDataMode()
Definition: vDataFile.hh:300
vEvent ** m2p_BufferEvent
Definition: vDataFile.hh:600
Inherit from vDataFile. Class that manages the reading of a CT input file (header + data)...
Definition: iDataFileCT.hh:48
uint32_t GetID1(int a_line)
Definition: vEvent.hh:101
int GetNbThreadsForProjection()
Get the number of threads used for projections.
bool GetIgnoreScatCorrectionFlag()
Get the boolean that says if the scatter correction is ignored or not.
#define DEBUG_VERBOSE(IGNORED1, IGNORED2)
#define Cout(MESSAGE)
FLTNB m_calibrationFactor
Definition: vDataFile.hh:585
~iDataFileCT()
iDataFileCT destructor.
Definition: iDataFileCT.cc:59
int GetCTSpecificParameters(uint16_t *ap_nbOfProjections, FLTNB *&ap_angles, int *ap_headRotDirection)
Transfer geometric information recovered from the datafile to the scanner object. ...
bool m_eventKindFlag
Definition: iDataFileCT.hh:255
int WriteHistoEvent(iEventHistoCT *ap_Event, int a_th)
Write a CT histogram event.
Definition: iDataFileCT.cc:592
int PrepareDataFile()
Store different kind of information inside arrays (data relative to specific correction as well as ba...
Definition: iDataFileCT.cc:192
int m_verbose
Definition: vDataFile.hh:574
int CheckFileSizeConsistency()
This function is implemented in child classes Check if file size is consistent. ...
Definition: iDataFileCT.cc:403
uint32_t GetTimeInMs()
Definition: vEvent.hh:88
#define GEO_ROT_CW
Definition: vScanner.hh:47
FLTNB GetEventValue(int a_bin)