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