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