CASToR  3.2
Tomographic Reconstruction (PET/SPECT/CT)
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  // Add optional custom data
153 
154  // Check
155  if (m_sizeEvent<=0)
156  {
157  Cerr("***** iDataFileCT::ComputeSizeEvent() -> Error, the Event size in bytes should be >= 0 !" << endl;);
158  return 1;
159  }
160 
161  // Verbose
162  if (m_verbose>=VERBOSE_DETAIL) Cout(" --> Event size: " << m_sizeEvent << " bytes" << endl);
163 
164  // End
165  return 0;
166 }
167 
168 // =====================================================================
169 // ---------------------------------------------------------------------
170 // ---------------------------------------------------------------------
171 // =====================================================================
172 
174 {
175  // Verbose
178  {
179  if (m_dataMode==MODE_HISTOGRAM) Cout("iDataFileCT::PrepareDataFile() -> Build histogram events" << endl);
180  else if (m_dataMode==MODE_LIST) Cout("iDataFileCT::PrepareDataFile() -> Build listmode events" << endl);
181  else if (m_dataMode==MODE_NORMALIZATION) Cout("iDataFileCT::PrepareDataFile() -> Build normalization events" << endl);
182  }
183 
184  // ==============================================================================
185  // Allocate event buffers (one for each thread)
186  // ==============================================================================
187 
188  if (m_verbose>=VERBOSE_DETAIL) Cout(" --> Allocate an event buffer for each thread" << endl);
189  // Instanciation of the event buffer according to the data type
191 
192  // Allocate the events per each thread
193  for (int th=0 ; th<mp_ID->GetNbThreadsForProjection() ; th++)
194  {
195  // For MODE_LIST events
196  if (m_dataMode == MODE_LIST)
197  {
198  m2p_BufferEvent[th] = new iEventListCT();
199  }
200  // For MODE_HISTOGRAM events
201  if (m_dataMode == MODE_HISTOGRAM)
202  {
203  m2p_BufferEvent[th] = new iEventHistoCT();
204  }
205  // Allocate pixel/view IDs
206  if (m2p_BufferEvent[th]->AllocateID())
207  {
208  Cerr("*****iDataFileCT::PrepareDataFile() -> Error while trying to allocate memory for the Event object!" << endl);
209  return 1;
210  }
211 
212  // Allocate memory for optional custom fields
215 
216  if (m2p_BufferEvent[th]->GetNbCustomINTData()>0)
217  {
218  if(m2p_BufferEvent[th]->AllocateCustomINTData() >0)
219  {
220  Cerr("*****iDataFilePET::PrepareDataFile() -> Error while trying to allocate memory for the custom Event fields for thread " << th << " !" << endl;);
221  return 1;
222  }
223  }
224  if (m2p_BufferEvent[th]->GetNbCustomFLTData()>0)
225  {
226  if(m2p_BufferEvent[th]->AllocateCustomFLTData() >0)
227  {
228  Cerr("*****iDataFilePET::PrepareDataFile() -> Error while trying to allocate memory for the custom Event fields for thread " << th << " !" << endl;);
229  return 1;
230  }
231  }
232  }
233 
234  // ==============================================================================
235  // Deal with specific corrections
236  // ==============================================================================
237 
238  // In case of normalization correction flag, see if we ignore this correction
240  {
241  // Affect the ignored flag from the ignored corrections list processed by the oImageDimensionsAndQuantification.
242  // Note that we interpret the option to ignore the normalization as ignoring the blank correction for CT reconstructions
244  // Verbose
246  {
247  if (m_ignoreBlankCorrectionFlag) Cout(" --> Ignore blank correction" << endl);
248  else Cout(" --> Correct for blank" << endl);
249  }
250  }
251  // In case of scatter correction flag, see if we ignore this correction
253  {
254  // Affect the ignored flag from the ignored corrections list processed by the oImageDimensionsAndQuantification
256  // Verbose
258  {
259  if (m_ignoreScatCorrectionFlag) Cout(" --> Ignore scatter correction" << endl);
260  else Cout(" --> Correct for scatter events" << endl);
261  }
262  }
263 
264  // Normal end
265  return 0;
266 }
267 
268 // =====================================================================
269 // ---------------------------------------------------------------------
270 // ---------------------------------------------------------------------
271 // =====================================================================
272 
273 vEvent* iDataFileCT::GetEventSpecific(char* ap_buffer, int a_th)
274 {
276 
277  // Work on a copy of the input pointer
278  char* file_position = ap_buffer;
279 
280  // For MODE_LIST CT data
281  if (m_dataMode == MODE_LIST)
282  {
283  // Cast the event pointer
284  iEventListCT* event = (dynamic_cast<iEventListCT*>(m2p_BufferEvent[a_th]));
285  // Mandatory time field: [uint32_t (time)]
286  event->SetTimeInMs(*reinterpret_cast<uint32_t*>(file_position));
287  file_position += sizeof(uint32_t);
288  // Optional kind: [uint8_t kind]
289  if (m_eventKindFlag)
290  {
291  event->SetKind(*reinterpret_cast<uint8_t*>(file_position));
292  file_position += sizeof(uint8_t);
293  }
294  // Optional scatter correction field: [FLTNBDATA (scatter)]
296  {
297  if (!m_ignoreScatCorrectionFlag) event->SetScatterRate(*reinterpret_cast<FLTNBDATA*>(file_position));
298  file_position += sizeof(FLTNBDATA);
299  }
300  // Optional blank correction field: [FLTNBDATA (blank)]
302  {
303  if (!m_ignoreBlankCorrectionFlag) event->SetBlankValue(*reinterpret_cast<FLTNBDATA*>(file_position));
304  file_position += sizeof(FLTNBDATA);
305  }
306  // Mandatory angular projection ID: [uint32_t (ID1)]
307  event->SetID1(0, *reinterpret_cast<uint32_t*>(file_position));
308  file_position += sizeof(uint32_t);
309  // Mandatory pixel ID: [uint32_t (ID2)]
310  event->SetID2(0, *reinterpret_cast<uint32_t*>(file_position));
311  file_position += sizeof(uint32_t);
312 
313  // Custom fields
314  if(m_nbCustomFLTData>0)
315  {
316  for(int i=0 ; i<m_nbCustomFLTData ; i++)
317  {
318  event->SetCustomFLTData(i, *reinterpret_cast<EVTFLTDATA*>(file_position));
319  file_position += sizeof(EVTFLTDATA);
320  }
321  }
322 
323  if(m_nbCustomINTData>0)
324  {
325  for(int i=0 ; i<m_nbCustomINTData ; i++)
326  {
327  event->SetCustomINTData(i, *reinterpret_cast<EVTINTDATA*>(file_position));
328  file_position += sizeof(EVTINTDATA);
329  }
330  }
331  }
332 
333  // For MODE_HISTOGRAM CT DATA
334  if (m_dataMode == MODE_HISTOGRAM)
335  {
336  // Cast the event pointer
337  iEventHistoCT* event = (dynamic_cast<iEventHistoCT*>(m2p_BufferEvent[a_th]));
338  // Mandatory time field: [uint32_t (time)]
339  event->SetTimeInMs(*reinterpret_cast<uint32_t*>(file_position));
340  file_position += sizeof(uint32_t);
341  // Mandatory bin value: [FLTNBDATA bin value]
342  event->SetEventValue(0, *reinterpret_cast<FLTNBDATA*>(file_position));
343  file_position += sizeof(FLTNBDATA);
344  // Optional scatter correction field: [FLTNBDATA (scatter)]
346  {
347  if (!m_ignoreScatCorrectionFlag) event->SetScatterRate(*reinterpret_cast<FLTNBDATA*>(file_position));
348  file_position += sizeof(FLTNBDATA);
349  }
350  // Optional blank correction field: [FLTNBDATA (blank)]
352  {
353  if (!m_ignoreBlankCorrectionFlag) event->SetBlankValue(*reinterpret_cast<FLTNBDATA*>(file_position));
354  file_position += sizeof(FLTNBDATA);
355  }
356  // Mandatory angular projection ID: [uint32_t (ID1)]
357  event->SetID1(0, *reinterpret_cast<uint32_t*>(file_position));
358  file_position += sizeof(uint32_t);
359  // Mandatory pixel ID: [uint32_t (ID2)]
360  event->SetID2(0, *reinterpret_cast<uint32_t*>(file_position));
361  file_position += sizeof(uint32_t);
362 
363  // Custom fields
364  if(m_nbCustomINTData>0)
365  {
366  for(int i=0 ; i<m_nbCustomINTData ; i++)
367  {
368  event->SetCustomINTData(i, *reinterpret_cast<EVTINTDATA*>(file_position));
369  file_position += sizeof(EVTINTDATA);
370  }
371  }
372  if(m_nbCustomFLTData>0)
373  {
374  for(int i=0 ; i<m_nbCustomFLTData ; i++)
375  {
376  event->SetCustomFLTData(i, *reinterpret_cast<EVTFLTDATA*>(file_position));
377  file_position += sizeof(EVTFLTDATA);
378  }
379  }
380  }
381 
382  // Return the updated event
383  return m2p_BufferEvent[a_th];
384 }
385 
386 // =====================================================================
387 // ---------------------------------------------------------------------
388 // ---------------------------------------------------------------------
389 // =====================================================================
390 
392 {
394  if (m_verbose==0) return;
395  // Describe the datafile
396  Cout("iDataFileCT::DescribeSpecific() -> Here is some specific content of the CT datafile" << endl);
397  if (m_dataMode==MODE_LIST && m_eventKindFlag) Cout(" --> Event kind is present" << endl);
398  if (m_blankCorrectionFlag) Cout(" --> Blank correction is present" << endl);
399  if (m_scatCorrectionFlag) Cout(" --> Scatter correction is present" << endl);
400  if (m_detectorRotDirection==GEO_ROT_CW) Cout(" --> Detector rotation is clockwise" << endl);
401  else if (m_detectorRotDirection==GEO_ROT_CCW) Cout(" --> Detector rotation is counter-clockwise" << endl);
402  else Cout(" --> Detector rotation is undefined !!!" << endl);
403  Cout(" --> Number of acquisition projections: " << m_nbOfProjections << endl);
404  for (uint16_t p=0; p<m_nbOfProjections; p++) Cout(" | Projection " << p << " at " << mp_angles[p] << " deg" << endl);
405 }
406 
407 // =====================================================================
408 // ---------------------------------------------------------------------
409 // ---------------------------------------------------------------------
410 // =====================================================================
411 
413 {
415  // Error if m_dataType != CT
416  if (m_dataType != TYPE_CT)
417  {
418  Cerr("***** iDataFileCT::CheckSpecificParameters() -> Data type should be CT !'" << endl);
419  return 1;
420  }
421  // Check number of projections
422  if (m_nbOfProjections == 0)
423  {
424  Cerr("***** iDataFileCT::CheckSpecificParameters() -> Number of projections not initialized (should be >0) !" << endl);
425  return 1;
426  }
427  // Check projection angles
428  if (mp_angles == NULL)
429  {
430  Cerr("***** iDataFileCT::CheckSpecificParameters() -> Projection angles not initialized !" << endl);
431  return 1;
432  }
433  // End
434  return 0;
435 }
436 
437 // =====================================================================
438 // ---------------------------------------------------------------------
439 // ---------------------------------------------------------------------
440 // =====================================================================
441 
443 {
445 
446  // Create the stream
447  fstream* p_file = new fstream( m_dataFileName.c_str(), ios::binary| ios::in );
448  // Check that datafile exists
449  if (!p_file->is_open())
450  {
451  Cerr("***** iDataFilePET::CheckFileSizeConsistency() -> Failed to open input file '" << m_dataFileName.c_str() << "' !" << endl);
452  Cerr(" (Provided in the data file header: " << m_headerFileName << ")" << endl);
453  return 1;
454  }
455  // Get file size in bytes
456  p_file->seekg(0, ios::end);
457  int64_t sizeInBytes = p_file->tellg();
458  // Close stream and delete it
459  p_file->close();
460  delete p_file;
461  // Check datafile self-consistency
462  if (m_nbEvents*m_sizeEvent != sizeInBytes)
463  {
464  Cerr("-------------------------------------------------------------------------------------------------------------------------------------" << endl);
465  Cerr("***** iDataFileCT::CheckFileSizeConsistency() -> DataFile size is not consistent with the information provided by the user/datafile !" << endl);
466  Cerr(" --> Expected size: "<< m_nbEvents*m_sizeEvent << endl);
467  Cerr(" --> Actual size: "<< sizeInBytes << endl << endl);
468  Cerr(" ADDITIONAL INFORMATION ABOUT THE DATAFILE INITIALIZATION" << endl);
469  if (m_eventKindFlag) Cerr(" --> Event kind term is enabled" << endl);
470  else Cerr(" --> No information about the kind of events in the data" << endl);
471  if (m_blankCorrectionFlag) Cerr(" --> Blank correction term is enabled" << endl);
472  else Cerr(" --> No blank correction term in the data" << endl);
473  if (m_scatCorrectionFlag) Cerr(" --> Scatter correction term is enabled" << endl);
474  else Cerr(" --> No scatter correction term in the data" << endl);
475  Cerr(" --> Calibration factor value is: " << m_calibrationFactor << endl);
476  Cerr("----------------------------------------------------------------------------------------------------------------------------------------" << endl);
477  return 1;
478  }
479  // End
480  return 0;
481 }
482 
483 // =====================================================================
484 // ---------------------------------------------------------------------
485 // ---------------------------------------------------------------------
486 // =====================================================================
487 
489 {
491  // Dynamic cast the vDataFile to a iDataFilePET
492  iDataFileCT* p_data_file = (dynamic_cast<iDataFileCT*>(ap_DataFile));
493  // Check event kind flag
494  if (m_eventKindFlag!=p_data_file->GetEventKindFlag())
495  {
496  Cerr("***** iDataFileCT::CheckSpecificConsistencyWithAnotherDataFile() -> Event kind flags are inconsistent !" << endl);
497  return 1;
498  }
499  // Check blank correction flag
500  if (m_blankCorrectionFlag!=p_data_file->GetBlankCorrectionFlag())
501  {
502  Cerr("***** iDataFileCT::CheckSpecificConsistencyWithAnotherDataFile() -> Blank correction flags are inconsistent !" << endl);
503  return 1;
504  }
505  // Check scatter correction flag
506  if (m_scatCorrectionFlag!=p_data_file->GetScatCorrectionFlag())
507  {
508  Cerr("***** iDataFileCT::CheckSpecificConsistencyWithAnotherDataFile() -> Scatter correction flags are inconsistent !" << endl);
509  return 1;
510  }
511  // Check data mode
512  if (m_dataMode!=p_data_file->GetDataMode())
513  {
514  Cerr("***** iDataFileCT::CheckSpecificConsistencyWithAnotherDataFile() -> Data modes are inconsistent (list-mode or histogram) !" << endl);
515  return 1;
516  }
517  // End
518  return 0;
519 }
520 
521 // =====================================================================
522 // ---------------------------------------------------------------------
523 // ---------------------------------------------------------------------
524 // =====================================================================
525 
526 int iDataFileCT::InitAngles(FLTNB* ap_angles)
527 {
529  // Check
530  if (m_nbOfProjections == 0)
531  {
532  Cerr("***** iDataFileCT::InitAngles() -> Number of projection angles not initialized !'" << endl);
533  return 1;
534  }
535  // Allocate
537  // Affect
538  for (uint16_t a=0 ; a<m_nbOfProjections ; a++) mp_angles[a] = ap_angles[a];
539  // End
540  return 0;
541 }
542 
543 // =====================================================================
544 // ---------------------------------------------------------------------
545 // ---------------------------------------------------------------------
546 // =====================================================================
547 
549 {
550  // Verbose
552  if (m_verbose>=VERBOSE_DETAIL) Cout("iDataFileCT::PROJ_InitFile() -> Initialize datafile for writing" << endl);
553 
554  m_startTimeInSec = 0.; //Std initialization for projection
555  m_durationInSec = 1.; //Std initialization for projection
556  m_nbEvents = 0; //Std initialization for projection
557  m_calibrationFactor = 1.;
558  m_scatCorrectionFlag = false;
559  m_blankCorrectionFlag = false;
560 
561  // Instanciate a fstream datafile for each thread
562  m2p_dataFile = new fstream*[mp_ID->GetNbThreadsForProjection()];
563 
564  // Set name of the projection data header
565  sOutputManager* p_OutMgr;
566  p_OutMgr = sOutputManager::GetInstance();
567  string path_name = p_OutMgr->GetPathName();
568  string img_name = p_OutMgr->GetBaseName();
569  m_headerFileName = path_name.append(img_name).append("_df").append(".Cdh");
570 
571  for (int th=0 ; th<mp_ID->GetNbThreadsForProjection() ; th++)
572  {
573  m_dataFileName = m_headerFileName.substr(0, m_headerFileName.find_last_of(".")).append(".Cdf"); // Generate datafile name from header file
574 
575  // Projeted data will be written in several files (corresponding to the number of thread) to be concatenated at the end of the projection process.
576  stringstream ss;
577  ss << th;
578 
579  string datafile_name = m_dataFileName;
580  datafile_name.append("_").append(ss.str());
581 
582  m2p_dataFile[th] = new fstream( datafile_name.c_str(), ios::binary | ios::out | ios::trunc);
583  }
584 
585  //remove content from the output data file, in case it already exists
586  //todo warn the user a datafile with the same name will be erased (eventually add an option to disable the warning)
587  ofstream output_file(m_dataFileName.c_str(), ios::out | ios::trunc);
588  output_file.close();
589 
590  if (m_verbose>=VERBOSE_DETAIL) Cout(" --> Output datafile name :" << m_dataFileName << endl);
591 
592  return 0;
593 }
594 
595 // =====================================================================
596 // ---------------------------------------------------------------------
597 // ---------------------------------------------------------------------
598 // =====================================================================
599 
600 int iDataFileCT::WriteEvent(vEvent* ap_Event, int a_th)
601 {
603 
604  if (m_dataMode == MODE_LIST)
605  {
606  // TODO should create as many vEvent as (int)fp.
607  if (WriteListEvent((iEventListCT*)ap_Event, a_th))
608  {
609  Cerr("*****iDataFileCT::WriteEvent() -> Error while trying to write projection datafile (list-mode)" << endl);
610  return 1;
611  }
612  }
613 
614  if (m_dataMode == MODE_HISTOGRAM)
615  {
616  if (WriteHistoEvent((iEventHistoCT*)ap_Event, a_th))
617  {
618  Cerr("*****iDataFileCT::WriteEvent() -> Error while trying to write projection datafile (histogram)" << endl);
619  return 1;
620  }
621  }
622 
623  return 0;
624 }
625 
626 // =====================================================================
627 // ---------------------------------------------------------------------
628 // ---------------------------------------------------------------------
629 // =====================================================================
630 
631 int iDataFileCT::WriteHistoEvent(iEventHistoCT* ap_Event, int a_th)
632 {
634 
635  // Write sequentially each field of the event according to the type of the event.
636  m2p_dataFile[a_th]->clear();
637 
638  uint32_t time = ap_Event->GetTimeInMs();
639  m2p_dataFile[a_th]->write(reinterpret_cast<char*>(&time), sizeof(uint32_t));
640 
641  FLTNBDATA event_value = ap_Event->GetEventValue(0);
642  m2p_dataFile[a_th]->write(reinterpret_cast<char*>(&event_value), sizeof(FLTNBDATA));
643 
645  {
646  FLTNBDATA scat_rate = ap_Event->GetEventScatRate();
647  m2p_dataFile[a_th]->write(reinterpret_cast<char*>(&scat_rate), sizeof(FLTNBDATA));
648  }
649 
651  {
652  FLTNBDATA blank_corr_factor = ap_Event->GetBlankValue();
653  m2p_dataFile[a_th]->write(reinterpret_cast<char*>(&blank_corr_factor), sizeof(FLTNBDATA));
654  }
655 
656  uint32_t id1 = ap_Event->GetID1(0);
657  uint32_t id2 = ap_Event->GetID2(0);
658  m2p_dataFile[a_th]->write(reinterpret_cast<char*>(&id1), sizeof(uint32_t));
659  m2p_dataFile[a_th]->write(reinterpret_cast<char*>(&id2), sizeof(uint32_t));
660 
661  // Custom fields
662  if(m_nbCustomINTData>0)
663  {
664  for(int i=0 ; i<m_nbCustomINTData ; i++)
665  {
666  EVTINTDATA cst_data = ap_Event->GetCustomINTData( i );
667  m2p_dataFile[a_th]->write(reinterpret_cast<char*>(&cst_data), sizeof(EVTINTDATA));
668  }
669  }
670 
671  if(m_nbCustomFLTData>0)
672  {
673  for(int i=0 ; i<m_nbCustomFLTData ; i++)
674  {
675  EVTFLTDATA cst_data = ap_Event->GetCustomFLTData( i );
676  m2p_dataFile[a_th]->write(reinterpret_cast<char*>(&cst_data), sizeof(EVTINTDATA));
677  }
678  }
679 
680  return 0;
681 }
682 
683 // =====================================================================
684 // ---------------------------------------------------------------------
685 // ---------------------------------------------------------------------
686 // =====================================================================
687 
688 int iDataFileCT::WriteListEvent(iEventListCT* ap_Event, int a_th)
689 {
691 
692  // Write sequentially each field of the event according to the type of the event.
693  m2p_dataFile[a_th]->clear();
694 
695  uint32_t time = ap_Event->GetTimeInMs();
696  m2p_dataFile[a_th]->write(reinterpret_cast<char*>(&time), sizeof(uint32_t));
697 
698  if(m_eventKindFlag)
699  {
700  uint8_t event_kind = ap_Event->GetKind();
701  m2p_dataFile[a_th]->write(reinterpret_cast<char*>(&event_kind), sizeof(uint8_t));
702  }
703 
705  {
706  FLTNBDATA scat_rate = ap_Event->GetEventScatRate();
707  m2p_dataFile[a_th]->write(reinterpret_cast<char*>(&scat_rate), sizeof(FLTNBDATA));
708  }
709 
711  {
712  FLTNBDATA blank_corr_factor = ap_Event->GetBlankValue();
713  m2p_dataFile[a_th]->write(reinterpret_cast<char*>(&blank_corr_factor), sizeof(FLTNBDATA));
714  }
715 
716  uint32_t id1 = ap_Event->GetID1(0);
717  uint32_t id2 = ap_Event->GetID2(0);
718  m2p_dataFile[a_th]->write(reinterpret_cast<char*>(&id1), sizeof(uint32_t));
719  m2p_dataFile[a_th]->write(reinterpret_cast<char*>(&id2), sizeof(uint32_t));
720 
721  // Custom fields
722  if(m_nbCustomINTData>0)
723  {
724  for(int i=0 ; i<m_nbCustomINTData ; i++)
725  {
726  EVTINTDATA cst_data = ap_Event->GetCustomINTData( i );
727  m2p_dataFile[a_th]->write(reinterpret_cast<char*>(&cst_data), sizeof(EVTINTDATA));
728  }
729  }
730 
731  if(m_nbCustomFLTData>0)
732  {
733  for(int i=0 ; i<m_nbCustomFLTData ; i++)
734  {
735  EVTFLTDATA cst_data = ap_Event->GetCustomFLTData( i );
736  m2p_dataFile[a_th]->write(reinterpret_cast<char*>(&cst_data), sizeof(EVTINTDATA));
737  }
738  }
739 
740  return 0;
741 }
742 
743 // =====================================================================
744 // ---------------------------------------------------------------------
745 // ---------------------------------------------------------------------
746 // =====================================================================
747 
749 {
750  // Verbose
752  if (m_verbose>=VERBOSE_NORMAL) Cout("iDataFileCT::WriteHeader() -> Write header file '" << m_headerFileName << "'" << endl);
753  // Open file
754  fstream headerFile;
755  headerFile.open(m_headerFileName.c_str(), ios::out);
756  if (!headerFile.is_open())
757  {
758  Cerr("***** iDataFileCT::WriteHeader() -> Failed to open output header file '" << m_headerFileName << "' !" << endl);
759  return 1;
760  }
761  // Data file name
762  headerFile << "Data filename: " << GetFileFromPath(m_dataFileName) << endl;
763  // Number of events
764  headerFile << "Number of events: " << m_nbEvents << endl;
765  // Data mode
766  if (m_dataMode==MODE_HISTOGRAM) headerFile << "Data mode: histogram" << endl;
767  else if (m_dataMode==MODE_LIST) headerFile << "Data mode: list-mode" << endl;
768  else if (m_dataMode==MODE_NORMALIZATION) headerFile << "Data mode: normalization" << endl;
769  // CT data type
770  headerFile << "Data type: CT" << endl;
771  // Acquisition start time in seconds
772  headerFile << "Start time (s): " << m_startTimeInSec << endl;
773  // Acquisition duration in seconds
774  headerFile << "Duration (s): " << m_durationInSec << endl;
775  // Scanner name
776  headerFile << "Scanner name:" << " " << sScannerManager::GetInstance()->GetScannerName() << endl;
777  // Number of projections
778  headerFile << "Number of projections: " << m_nbOfProjections << endl;
779  // Projection angles
780  headerFile << "Projection angles: " << mp_angles[0];
781  for (int a=1 ; a<m_nbOfProjections ; a++) headerFile << ", " << mp_angles[a];
782  headerFile << endl;
783  // Blank correction flag
784  headerFile << "Blank correction flag: " << m_blankCorrectionFlag << endl;
785  // Scatter correction flag
786  headerFile << "Scatter correction flag: " << m_scatCorrectionFlag << endl;
787  // Scanner rotation direction
788  string rot_direction = (m_detectorRotDirection == GEO_ROT_CCW) ? "CCW" : "CW";
789  headerFile << "Scanner rotation direction: " << rot_direction << endl;
790  // Close file
791  headerFile.close();
792  // End
793  return 0;
794 }
795 
796 // =====================================================================
797 // ---------------------------------------------------------------------
798 // ---------------------------------------------------------------------
799 // =====================================================================
800 
802 {
803  // Verbose
805  if (m_verbose>=VERBOSE_DETAIL) Cout("iDataFileCT::PROJ_GetScannerSpecificParameters() ..."<< endl);
806  // Create pointers dedicated to recover the addresses of the member variables of the scanner object
807  FLTNB* p_angles = NULL;
808  // Get pointers to CT specific parameters in scanner
809  if(sScannerManager::GetInstance()->GetCTSpecificParameters(&m_nbOfProjections, p_angles, &m_detectorRotDirection) )
810  {
811  Cerr("*****iDataFileCT::PROJ_GetScannerSpecificParameters() -> An error occurred while trying to get CT geometric parameters from the scanner object !" << endl);
812  return 1;
813  }
814  // Retrieve projection angles
815  mp_angles = new FLTNB[m_nbOfProjections];
816  for(int a=0 ; a<m_nbOfProjections ; a++)
817  mp_angles[a] = p_angles[a];
818  // End
819  return 0;
820 }
821 
822 // =====================================================================
823 // ---------------------------------------------------------------------
824 // ---------------------------------------------------------------------
825 // =====================================================================
virtual EVTFLTDATA * GetCustomFLTData()
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 EVTINTDATA
#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)
virtual void SetNbCustomFLTData(int a_value)
initialize the number of custom INT data with a_value
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)
#define EVTFLTDATA
void SetTimeInMs(uint32_t a_value)
virtual void SetNbCustomINTData(int a_value)
initialize the number of custom INT data with 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.
virtual EVTINTDATA * GetCustomINTData()
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