CASToR  1.1
Tomographic Reconstruction (PET/SPECT)
 All Classes Files Functions Variables Typedefs Macros Groups Pages
iDataFilePET.cc
Go to the documentation of this file.
1 
9 #include "iDataFilePET.hh"
10 
11 // =====================================================================
12 // ---------------------------------------------------------------------
13 // ---------------------------------------------------------------------
14 // =====================================================================
15 
17 {
18  // Set all members to default values
21  m_maxRingDiff = -1;
22  m_isotope = "unknown";
23  m_resolutionTOF = -1.;
24  m_nbBinsTOF = -1;
25  m_binSizeTOF = -1.;
26  m_eventKindFlag = false;
27  m_atnCorrectionFlag = false;
29  m_normCorrectionFlag = false;
31  m_scatCorrectionFlag = false;
33  m_randCorrectionFlag = false;
35  m_TOFInfoFlag = false;
36  m_ignoreTOFFlag = false;
37 }
38 
39 // =====================================================================
40 // ---------------------------------------------------------------------
41 // ---------------------------------------------------------------------
42 // =====================================================================
43 
45 
46 // =====================================================================
47 // ---------------------------------------------------------------------
48 // ---------------------------------------------------------------------
49 // =====================================================================
50 
51 int iDataFilePET::ReadSpecificInfoInHeader(bool a_affectQuantificationFlag)
52 {
54  // Verbose
55  if (m_verbose>=VERBOSE_DETAIL) Cout("iDataFilePET::ReadSpecificInfoInHeader() -> Read information specific to PET" << endl);
56  // Read optional fields in the header, check if errors (issue during data reading/conversion (==1) )
57  if (ReadDataASCIIFile(m_headerFileName, "Maximum number of lines per event", &m_maxNumberOfLinesPerEvent, 1, KEYWORD_OPTIONAL)==1 ||
58  ReadDataASCIIFile(m_headerFileName, "Maximum ring difference", &m_maxRingDiff, 1, KEYWORD_OPTIONAL)==1 ||
60  ReadDataASCIIFile(m_headerFileName, "TOF correction flag", &m_TOFInfoFlag, 1, KEYWORD_OPTIONAL)==1 ||
61  ReadDataASCIIFile(m_headerFileName, "Histo TOF number of bins", &m_nbBinsTOF, 1, KEYWORD_OPTIONAL)==1 ||
62  ReadDataASCIIFile(m_headerFileName, "Histo TOF bin size", &m_binSizeTOF, 1, KEYWORD_OPTIONAL)==1 ||
63  ReadDataASCIIFile(m_headerFileName, "Coincidence kind flag", &m_eventKindFlag, 1, KEYWORD_OPTIONAL)==1 ||
64  ReadDataASCIIFile(m_headerFileName, "Attenuation correction flag", &m_atnCorrectionFlag, 1, KEYWORD_OPTIONAL)==1 ||
65  ReadDataASCIIFile(m_headerFileName, "Normalization correction flag", &m_normCorrectionFlag, 1, KEYWORD_OPTIONAL)==1 ||
66  ReadDataASCIIFile(m_headerFileName, "Scatter correction flag", &m_scatCorrectionFlag, 1, KEYWORD_OPTIONAL)==1 ||
67  ReadDataASCIIFile(m_headerFileName, "Random correction flag", &m_randCorrectionFlag, 1, KEYWORD_OPTIONAL)==1 ||
69  {
70  Cerr("***** iDataFilePET::ReadSpecificInfoInHeader() -> Error while reading optional fields in the header data file !" << endl);
71  return 1;
72  }
73  // Give the PET isotope to the oImageDimensionsAndQuantification that manages the quantification factors
74  if (a_affectQuantificationFlag && mp_ID->SetPETIsotope(m_bedIndex, m_isotope))
75  {
76  Cerr("***** iDataFilePET::ReadSpecificInfoInHeader() -> A problem occured while setting the isotope to oImageDimensionsAndQuantification !" << endl);
77  return 1;
78  }
79  // End
80  return 0;
81 }
82 
83 // =====================================================================
84 // ---------------------------------------------------------------------
85 // ---------------------------------------------------------------------
86 // =====================================================================
87 
89 {
91  // Verbose
92  if (m_verbose>=VERBOSE_DETAIL) Cout("iDataFilePET::ComputeSizeEvent() -> In bytes" << endl);
93 
94  // For MODE_LIST events
95  if (m_dataMode == MODE_LIST)
96  {
97  // Size of the mandatory element in a list-mode event: Time + max_nb_lines*2*crystalID
98  m_sizeEvent = sizeof(uint32_t) + m_maxNumberOfLinesPerEvent*2*sizeof(uint32_t);
99  // Number of lines
100  if (m_maxNumberOfLinesPerEvent>1) m_sizeEvent += sizeof(uint16_t);
101  // Optional flags
102  if (m_eventKindFlag) m_sizeEvent += sizeof(uint8_t);
103  if (m_atnCorrectionFlag) m_sizeEvent += sizeof(FLTNBDATA);
107  if (m_TOFInfoFlag) m_sizeEvent += sizeof(FLTNBDATA);
108  // POI availability in each direction
109  for (int i=0 ; i<3; i++) if (mp_POIDirectionFlag[i]) m_sizeEvent += 2*sizeof(FLTNBDATA);
110  }
111  // For MODE_HISTOGRAM events
112  else if (m_dataMode == MODE_HISTOGRAM)
113  {
114  // Size of the mandatory element in a histo event: Time + nbBinsTOF*event_value + max_nb_line*2*crystalID
115  m_sizeEvent = sizeof(uint32_t) + m_nbBinsTOF*sizeof(FLTNBDATA) + m_maxNumberOfLinesPerEvent*2*sizeof(uint32_t);
116  // Number of lines
117  if (m_maxNumberOfLinesPerEvent>1) m_sizeEvent += sizeof(uint16_t);
118  // Optional flags
119  if (m_atnCorrectionFlag) m_sizeEvent += sizeof(FLTNBDATA);
123  }
124  // For MODE_NORMALIZATION events
125  else if (m_dataMode == MODE_NORMALIZATION)
126  {
127  // max_nb_lines*2*crystalID
128  m_sizeEvent = m_maxNumberOfLinesPerEvent*2*sizeof(uint32_t);
129  // Number of lines
130  if (m_maxNumberOfLinesPerEvent>1) m_sizeEvent += sizeof(uint16_t);
131  // Optional flag for normalization
133  // Optional flag for attenuation
134  if (m_atnCorrectionFlag) m_sizeEvent += sizeof(FLTNBDATA);
135  }
136  // Unknown event type
137  else
138  {
139  Cerr("***** iDataFilePET::ComputeSizeEvent() -> Unknown event mode !" << endl);
140  return 1;
141  }
142 
143  // Check
144  if (m_sizeEvent<=0)
145  {
146  Cerr("***** iDataFilePET::ComputeSizeEvent() -> Error, the Event size in bytes should be >= 0 !" << endl;);
147  return 1;
148  }
149 
150  // Verbose
151  if (m_verbose>=VERBOSE_DETAIL) Cout(" --> Event size = " << m_sizeEvent << " bytes" << endl);
152  // End
153  return 0;
154 }
155 
156 // =====================================================================
157 // ---------------------------------------------------------------------
158 // ---------------------------------------------------------------------
159 // =====================================================================
160 
162 {
164  // Verbose
166  {
167  if (m_dataMode==MODE_HISTOGRAM) Cout("iDataFilePET::PrepareDataFile() -> Build histogram events" << endl);
168  else if (m_dataMode==MODE_LIST) Cout("iDataFilePET::PrepareDataFile() -> Build listmode events" << endl);
169  else if (m_dataMode==MODE_NORMALIZATION) Cout("iDataFilePET::PrepareDataFile() -> Build normalization events" << endl);
170  }
171 
172  // ==============================================================================
173  // Allocate event buffers (one for each thread)
174  // ==============================================================================
175  if (m_verbose>=VERBOSE_DETAIL) Cout(" --> Allocating an event buffer for each thread" << endl);
176  // Instanciation of the event buffer according to the data type
178 
179  // Allocate the events per each thread
180  for (int th=0 ; th<mp_ID->GetNbThreadsForProjection() ; th++)
181  {
182 
183  // For MODE_LIST events
184  if (m_dataMode == MODE_LIST)
185  {
186  m2p_BufferEvent[th] = new iEventListPET();
187  }
188  // For MODE_HISTOGRAM events
189  else if (m_dataMode == MODE_HISTOGRAM)
190  {
191  m2p_BufferEvent[th] = new iEventHistoPET();
192  // If we ignore the TOF information, then the event buffer will have only one TOF bin;
193  // the TOF contributions will be sum up when reading the event.
194  if (m_ignoreTOFFlag) ((iEventHistoPET*)m2p_BufferEvent[th])->SetEventNbTOFBins(1);
195  else ((iEventHistoPET*)m2p_BufferEvent[th])->SetEventNbTOFBins(m_nbBinsTOF);
196  }
197  // For MODE_NORMALIZATION events
198  else if (m_dataMode == MODE_NORMALIZATION)
199  {
200  m2p_BufferEvent[th] = new iEventNorm();
201  }
202 
203  // Set the maximum number of lines per event
205 
206  // Allocate crystal IDs
207  if (m2p_BufferEvent[th]->AllocateID())
208  {
209  Cerr("*****iDataFilePET::PrepareDataFile() -> Error while trying to allocate memory for the Event object for thread " << th << " !" << endl;);
210  return 1;
211  }
212  }
213 
214  // ==============================================================================
215  // Deal with specific corrections
216  // ==============================================================================
217 
218  // In case of attenuation correction flag, see if we ignore this correction
220  {
221  // Affect the ignored flag from the ignored corrections list processed by the oImageDimensionsAndQuantification
223  // Verbose
225  {
226  if (m_ignoreAttnCorrectionFlag) Cout(" --> Ignore attenuation correction" << endl);
227  else Cout(" --> Correct for attenuation" << endl);
228  }
229  }
230  // In case of normalization correction flag, see if we ignore this correction
232  {
233  // Affect the ignored flag from the ignored corrections list processed by the oImageDimensionsAndQuantification
235  // Verbose
237  {
238  if (m_ignoreNormCorrectionFlag) Cout(" --> Ignore normalization correction" << endl);
239  else Cout(" --> Correct for normalization" << endl);
240  }
241  }
242  // In case of scatter correction flag, see if we ignore this correction
244  {
245  // Affect the ignored flag from the ignored corrections list processed by the oImageDimensionsAndQuantification
247  // Verbose
249  {
250  if (m_ignoreScatCorrectionFlag) Cout(" --> Ignore scatter correction" << endl);
251  else Cout(" --> Correct for scatter events" << endl);
252  }
253  }
254  // In case of random correction flag, see if we ignore this correction
256  {
257  // Affect the ignored flag from the ignored corrections list processed by the oImageDimensionsAndQuantification
259  // Verbose
261  {
262  if (m_ignoreRandCorrectionFlag) Cout(" --> Ignore random correction" << endl);
263  else Cout(" --> Correct for random events" << endl);
264  }
265  }
266 
267  // Normal end
268  return 0;
269 }
270 
271 // =====================================================================
272 // ---------------------------------------------------------------------
273 // ---------------------------------------------------------------------
274 // =====================================================================
275 
276 vEvent* iDataFilePET::GetEventFromBuffer(char* ap_buffer, int a_th)
277 {
279 
280  // Work on a copy of the input pointer
281  char* file_position = ap_buffer;
282 
283  // For MODE_LIST PET data
284  if (m_dataMode == MODE_LIST)
285  {
286  // Cast the event pointer
287  iEventListPET* event = (dynamic_cast<iEventListPET*>(m2p_BufferEvent[a_th]));
288  // Mandatory time field: [uint32_t (time)]
289  event->SetTimeInMs(*reinterpret_cast<uint32_t*>(file_position));
290  file_position += sizeof(uint32_t);
291  // Optional attenuation correction field: [FLTNBDATA (attnCorrectionFactor)]
293  {
294  if (!m_ignoreAttnCorrectionFlag) event->SetAttenuationCorrectionFactor(*reinterpret_cast<FLTNBDATA*>(file_position));
295  file_position += sizeof(FLTNBDATA);
296  }
297  // Optional kind: [uint8_t kind]
298  if (m_eventKindFlag)
299  {
300  event->SetKind(*reinterpret_cast<uint8_t*>(file_position));
301  file_position += sizeof(uint8_t);
302  }
303  // Optional scatter correction field: [FLTNBDATA (scatter)]
305  {
306  if (!m_ignoreScatCorrectionFlag) event->SetScatterRate(0, *reinterpret_cast<FLTNBDATA*>(file_position));
307  file_position += sizeof(FLTNBDATA);
308  }
309  // Optional random correction field: [FLTNBDATA (random)]
311  {
312  if (!m_ignoreRandCorrectionFlag) event->SetRandomRate(*reinterpret_cast<FLTNBDATA*>(file_position));
313  file_position += sizeof(FLTNBDATA);
314  }
315  // Optional normalization correction field: [FLTNBDATA (norm)]
317  {
318  if (!m_ignoreNormCorrectionFlag) event->SetNormalizationFactor(*reinterpret_cast<FLTNBDATA*>(file_position));
319  file_position += sizeof(FLTNBDATA);
320  }
321  // Optional TOF correction field: [FLTNBDATA (TOF)]
322  if (m_TOFInfoFlag)
323  {
324  if (!m_ignoreTOFFlag) event->SetTOFMeasurement(*reinterpret_cast<FLTNBDATA*>(file_position));
325  file_position += sizeof(FLTNBDATA);
326  }
327  // Optional POI correction fields: [FLTNBDATA (POI1[3])] [FLTNBDATA (POI2[3])]
328  for (int i=0; i<3; i++)
329  {
330  if (mp_POIDirectionFlag[i])
331  {
332  if (!m_ignorePOIFlag) event->SetPOI1(i,*reinterpret_cast<FLTNBDATA*>(file_position));
333  file_position += sizeof(FLTNBDATA);
334  if (!m_ignorePOIFlag) event->SetPOI2(i,*reinterpret_cast<FLTNBDATA*>(file_position));
335  file_position += sizeof(FLTNBDATA);
336  }
337  }
338  // Mandatory nb contributing LORs if m_maxNumberOfLinesPerEvent>1: [uint16_t nbLines]
340  {
341  event->SetNbLines(*reinterpret_cast<uint16_t*>(file_position));
342  file_position += sizeof(uint16_t);
343  }
344  // Mandatory crystal IDs: [uint32_t (ID1)] [uint32_t (ID2)]
345  for (int i=0 ; i<event->GetNbLines() ; i++)
346  {
347  event->SetID1(i, *reinterpret_cast<uint32_t*>(file_position));
348  file_position += sizeof(uint32_t);
349  event->SetID2(i, *reinterpret_cast<uint32_t*>(file_position));
350  file_position += sizeof(uint32_t);
351  }
352  }
353 
354  // For MODE_HISTOGRAM PET data
355  else if (m_dataMode == MODE_HISTOGRAM)
356  {
357  // Cast the event pointer
358  iEventHistoPET* event = (dynamic_cast<iEventHistoPET*>(m2p_BufferEvent[a_th]));
359  // Mandatory time field: [uint32_t (time)]
360  event->SetTimeInMs(*reinterpret_cast<uint32_t*>(file_position));
361  file_position += sizeof(uint32_t);
362  // Optional attenuation correction field: [FLTNBDATA (attnCorrectionFactor)]
364  {
365  if (!m_ignoreAttnCorrectionFlag) event->SetAttenuationCorrectionFactor(*reinterpret_cast<FLTNBDATA*>(file_position));
366  file_position += sizeof(FLTNBDATA);
367  }
368 
369  // Optional random correction field: [FLTNBDATA (random)]
371  {
372  if (!m_ignoreRandCorrectionFlag) event->SetRandomRate(*reinterpret_cast<FLTNBDATA*>(file_position));
373  file_position += sizeof(FLTNBDATA);
374  }
375 
376  // Optional normalization correction field: [FLTNBDATA (norm)]
378  {
379  if (!m_ignoreNormCorrectionFlag) event->SetNormalizationFactor(*reinterpret_cast<FLTNBDATA*>(file_position));
380  file_position += sizeof(FLTNBDATA);
381  }
382  // If we ignore the TOF correction, then we have to sum up the bins' contributions
383  if (m_ignoreTOFFlag)
384  {
385  // Compute the total of event values and scatter rates
386  FLTNBDATA total_event_value = 0.;
387  FLTNBDATA total_scatter_rate = 0.;
388  for (int tb=0 ; tb<m_nbBinsTOF ; tb++)
389  {
390  // Mandatory bin value: [FLTNBDATA bin value]
391  total_event_value += *reinterpret_cast<FLTNBDATA*>(file_position);
392  file_position += sizeof(FLTNBDATA);
393  // Optional scatter correction field: [FLTNBDATA (scatter)]
395  {
396  total_scatter_rate += *reinterpret_cast<FLTNBDATA*>(file_position);
397  file_position += sizeof(FLTNBDATA);
398  }
399  }
400  // Affect the total to the event
401  event->SetEventValue(0,total_event_value);
402  if (!m_ignoreScatCorrectionFlag) event->SetScatterRate(0,total_scatter_rate);
403  }
404  // Otherwise we set all different TOF bin contributions
405  else
406  {
407  for (int tb=0 ; tb<m_nbBinsTOF ; tb++)
408  {
409  // Mandatory bin value: [FLTNBDATA bin value]
410  event->SetEventValue(tb, *reinterpret_cast<FLTNBDATA*>(file_position));
411  file_position += sizeof(FLTNBDATA);
412  // Optional scatter correction field: [FLTNBDATA (scatter)]
414  {
415  if (!m_ignoreScatCorrectionFlag) event->SetScatterRate(tb, *reinterpret_cast<FLTNBDATA*>(file_position));
416  file_position += sizeof(FLTNBDATA);
417  }
418  }
419  }
420  // Mandatory nb contributing LORs if m_maxNumberOfLinesPerEvent>1: [uint16_t nbLines]
422  {
423  event->SetNbLines(*reinterpret_cast<uint16_t*>(file_position));
424  file_position += sizeof(uint16_t);
425  }
426  // Mandatory crystal IDs: [uint32_t (c1)] [uint32_t (c2)]
427  for (int i=0 ; i<event->GetNbLines() ; i++)
428  {
429  event->SetID1(i, *reinterpret_cast<uint32_t*>(file_position));
430  file_position += sizeof(uint32_t);
431  event->SetID2(i, *reinterpret_cast<uint32_t*>(file_position));
432  file_position += sizeof(uint32_t);
433  }
434  }
435 
436  // For MODE_NORMALIZATION PET data
437  else if (m_dataMode == MODE_NORMALIZATION)
438  {
439  // Cast the event pointer
440  iEventNorm* event = (dynamic_cast<iEventNorm*>(m2p_BufferEvent[a_th]));
441  // Optional attenuation correction field: [FLTNBDATA (norm)]
443  {
444  if (!m_ignoreAttnCorrectionFlag) event->SetAttenuationCorrectionFactor(*reinterpret_cast<FLTNBDATA*>(file_position));
445  file_position += sizeof(FLTNBDATA);
446  }
447  // Optional normalization correction field: [FLTNBDATA (norm)]
449  {
450  if (!m_ignoreNormCorrectionFlag) event->SetNormalizationFactor(*reinterpret_cast<FLTNBDATA*>(file_position));
451  file_position += sizeof(FLTNBDATA);
452  }
453  // Mandatory nb contributing LORs if m_maxNumberOfLinesPerEvent>1: [uint16_t nbLines]
455  {
456  event->SetNbLines(*reinterpret_cast<uint16_t*>(file_position));
457  file_position += sizeof(uint16_t);
458  }
459  // Mandatory crystal IDs: [uint32_t (c1)] [uint32_t (c2)]
460  for (int i=0 ; i<event->GetNbLines() ; i++)
461  {
462  event->SetID1(i, *reinterpret_cast<uint32_t*>(file_position));
463  file_position += sizeof(uint32_t);
464  event->SetID2(i, *reinterpret_cast<uint32_t*>(file_position));
465  file_position += sizeof(uint32_t);
466  }
467  }
468 
469  // Return the updated event
470  return m2p_BufferEvent[a_th];
471 }
472 
473 // =====================================================================
474 // ---------------------------------------------------------------------
475 // ---------------------------------------------------------------------
476 // =====================================================================
477 
479 {
481  // Error if m_dataType != PET
482  if (m_dataType != TYPE_PET)
483  {
484  Cerr("***** iDataFilePET::CheckSpecificParameters() -> Data type should be PET !'" << endl);
485  return 1;
486  }
487  // Check if Maximum ring difference has been initialized, use the default value from the scanner otherwise.
488  if (m_maxRingDiff < 0)
489  {
490  if (m_verbose>VERBOSE_DETAIL) Cout("iDataFilePET::CheckSpecificParameters() -> Initialize maxRingDiff with the scanner default value" << endl);
491  m_maxRingDiff = sScannerManager::GetInstance()->GetScannerLayerNbRings(0); // TODO maybe throw error here if returned value is incorrect
492  // TODO how to deal with scanner with different layers (possibly different number of rings as well)
493  }
494  // Some checks for POI use
495  if (m_POIInfoFlag)
496  {
497  // Not compatible with histogram data
499  {
500  Cerr("***** iDataFilePET::CheckSpecificParameters() -> POI correction flag is enabled while the data are histogrammed, no sense !" << endl);
501  return 1;
502  }
503  // For each direction (radial, tangential and axial), look at the resolution. If not negative, the info should be the datafile
504  for (int i=0; i<3; i++) if (mp_POIResolution[i]>=0.) mp_POIDirectionFlag[i] = true;
505  }
506  // Some checks for TOF use
507  if (m_TOFInfoFlag)
508  {
509  // Check if the resolution was provided
510  if (m_resolutionTOF<0.)
511  {
512  Cerr("***** iDataFilePET::CheckSpecificParameters() -> TOF correction is on while there is no TOF resolution specified in the datafile header !" << endl);
513  return 1;
514  }
515  // For histogram data
517  {
518  // Check if the number of bins has been provided
519  if (m_nbBinsTOF<=1)
520  {
521  Cerr("***** iDataFilePET::CheckSpecificParameters() -> TOF correction is on while there is only one TOF bin (specified in the datafile header) !" << endl);
522  return 1;
523  }
524  // Check if the bin size has been provided
525  if (m_binSizeTOF<=0.)
526  {
527  Cerr("***** iDataFilePET::CheckSpecificParameters() -> TOF correction is on while there is no bin size specified in the datafile header !" << endl);
528  return 1;
529  }
530  }
531  // For list mode data
532  else if (m_dataMode==MODE_LIST)
533  {
534  // set the number of TOF bins to 1
535  m_nbBinsTOF = 1;
536  return 0;
537  }
538  }
539  else
540  {
541  // Set the number of TOF bins to 1
542  m_nbBinsTOF = 1;
543  }
544  // End
545  return 0;
546 }
547 
548 // =====================================================================
549 // ---------------------------------------------------------------------
550 // ---------------------------------------------------------------------
551 // =====================================================================
552 
554 {
556 
557  // Check datafile self-consistency
558  m2p_dataFile[0]->seekg(0, ios::end);
559  int64_t sizeInBytes = m2p_dataFile[0]->tellg();
560  if (m_totalNbEvents*m_sizeEvent != sizeInBytes)
561  {
562  Cerr("--------------------------------------------------------------------------------------------------------------------------------------" << endl);
563  Cerr("***** iDataFilePET::CheckFileSizeConsistency() -> Datafile size is not consistent with the information provided by the user/datafile !" << endl);
564  Cerr(" --> Expected size : "<< m_totalNbEvents*m_sizeEvent << endl);
565  Cerr(" --> Actual size : "<< sizeInBytes << endl << endl);
566  Cerr(" ADDITIONAL INFORMATION ABOUT THE DATAFILE INITIALIZATION : " << endl);
567  if (m_maxNumberOfLinesPerEvent > 1) Cerr(" --> Compression enabled. Each event should contain " << m_maxNumberOfLinesPerEvent <<
568  "LORs, or an equivalent number of LOR + garbage LORs" << endl);
569  else Cerr(" --> No compression in the data" << endl);
570  if (m_eventKindFlag) Cerr(" --> Coincidence kind term is enabled" << endl);
571  else Cerr(" --> No information about the kind of coincidences in the data" << endl);
572  if (m_normCorrectionFlag) Cerr(" --> Normalization correction term is enabled" << endl);
573  else Cerr(" --> No normalization correction term in the data" << endl);
574  if (m_atnCorrectionFlag) Cerr(" --> Attenuation correction term is enabled" << endl);
575  else Cerr(" --> No attenuation correction term in the data" << endl);
576  if (m_scatCorrectionFlag) Cerr(" --> Scatter correction term is enabled" << endl);
577  else Cerr(" --> No scatter correction term in the data" << endl);
578  if (m_randCorrectionFlag) Cerr(" --> Random correction term is enabled" << endl);
579  else Cerr(" --> No random correction term in the data" << endl);
580  if (m_TOFInfoFlag) Cerr(" --> TOF correction is enabled. Resolution is: " << m_resolutionTOF << " ps"<< endl);
581  else Cerr(" --> No TOF correction in the data" << endl);
582  Cerr(" --> Calibration factor value is: " << m_calibrationFactor << endl);
583  if (mp_POIResolution[0]<0.) Cerr(" --> No POI enabled on the radial axis" << endl);
584  else Cerr(" --> POI resolution on the radial axis is: " << mp_POIResolution[0] << endl);
585  if (mp_POIResolution[1]<0.) Cerr(" --> No POI enabled on the tangential axis" << endl);
586  else Cerr(" --> POI resolution on the tangential axis is: " << mp_POIResolution[1] << endl);
587  if (mp_POIResolution[2]<0.) Cerr(" --> No POI enabled on the axial axis" << endl);
588  else Cerr(" --> POI resolution on the axial axis is: " << mp_POIResolution[2] << endl);
589  Cerr("--------------------------------------------------------------------------------------------------------------------------------------" << endl);
590  return 1;
591  }
592 
593  // Depending on the verbosity, output all the datafile initialization information as feedback for the user
595  {
596  Cout("------------------------------------------------- Datafile initialization -------------------------------------------------" << endl);
597  if (m_maxNumberOfLinesPerEvent > 1) Cout(" --> Compression enabled. Each event should contain " << m_maxNumberOfLinesPerEvent <<
598  "LORs, or an equivalent number of LOR + garbage LORs" << endl);
599  else Cout(" --> No compression in the data" << endl);
600  if (m_eventKindFlag) Cout(" --> Coincidence kind term is enabled" << endl);
601  else Cout(" --> No information about the kind of coincidences in the data" << endl);
602  if (m_normCorrectionFlag) Cout(" --> Normalization correction term is enabled" << endl);
603  else Cout(" --> No normalization correction term in the data" << endl);
604  if (m_atnCorrectionFlag) Cout(" --> Attenuation correction term is enabled" << endl);
605  else Cout(" --> No attenuation correction term in the data" << endl);
606  if (m_scatCorrectionFlag) Cout(" --> Scatter correction term is enabled" << endl);
607  else Cout(" --> No scatter correction term in the data" << endl);
608  if (m_randCorrectionFlag) Cout(" --> Random correction term is enabled" << endl);
609  else Cout(" --> No random correction term in the data" << endl);
610  if (m_TOFInfoFlag) Cout(" --> TOF correction is enabled. Resolution is: " << m_resolutionTOF << " ps"<< endl);
611  else Cout(" --> No TOF correction in the data" << endl);
612  Cout(" --> Calibration factor value is: " << m_calibrationFactor << endl);
613  if (mp_POIResolution[0]<0.) Cout(" --> No POI enabled on the radial axis" << endl);
614  else Cout(" --> POI resolution on the radial axis is: " << mp_POIResolution[0] << endl);
615  if (mp_POIResolution[1]<0.) Cout(" --> No POI enabled on the tangential axis" << endl);
616  else Cout(" --> POI resolution on the tangential axis is: " << mp_POIResolution[1] << endl);
617  if (mp_POIResolution[2]<0.) Cout(" --> No POI enabled on the axial axis" << endl);
618  else Cout(" --> POI resolution on the axial axis is: " << mp_POIResolution[2] << endl);
619  Cout("---------------------------------------------------------------------------------------------------------------------------" << endl);
620  }
621 
622  // End
623  return 0;
624 }
625 
626 // =====================================================================
627 // ---------------------------------------------------------------------
628 // ---------------------------------------------------------------------
629 // =====================================================================
630 
632 {
634  // Dynamic cast the vDataFile to a iDataFilePET
635  iDataFilePET* p_data_file = (dynamic_cast<iDataFilePET*>(ap_Datafile));
636  // Check maximum number of lines per event
638  {
639  Cerr("***** iDataFilePET::CheckSpecificConsistencyWithAnotherDatafile() -> Maximum numbers of lines by event are inconsistent !" << endl);
640  return 1;
641  }
642  // Check maximum ring difference
643  if (m_maxRingDiff!=p_data_file->GetMaxRingDiff())
644  {
645  Cerr("***** iDataFilePET::CheckSpecificConsistencyWithAnotherDatafile() -> Maximum ring differences are inconsistent !" << endl);
646  return 1;
647  }
648  // Check isotope
649  if (m_isotope!=p_data_file->GetIsotope())
650  {
651  Cerr("***** iDataFilePET::CheckSpecificConsistencyWithAnotherDatafile() -> Isotopes are inconsistent !" << endl);
652  return 1;
653  }
654  // Check event kind flag
655  if (m_eventKindFlag!=p_data_file->GetEventKindFlag())
656  {
657  Cerr("***** iDataFilePET::CheckSpecificConsistencyWithAnotherDatafile() -> Event kind flags are inconsistent !" << endl);
658  return 1;
659  }
660  // Check attenuation correction flag
661  if (m_atnCorrectionFlag!=p_data_file->GetAtnCorrectionFlag())
662  {
663  Cerr("***** iDataFilePET::CheckSpecificConsistencyWithAnotherDatafile() -> Attenuation correction flags are inconsistent !" << endl);
664  return 1;
665  }
666  // Check normalization correction flag
667  if (m_normCorrectionFlag!=p_data_file->GetNormCorrectionFlag())
668  {
669  Cerr("***** iDataFilePET::CheckSpecificConsistencyWithAnotherDatafile() -> Normalization correction flags are inconsistent !" << endl);
670  return 1;
671  }
672  // Check scatter correction flag
673  if (m_scatCorrectionFlag!=p_data_file->GetScatCorrectionFlag())
674  {
675  Cerr("***** iDataFilePET::CheckSpecificConsistencyWithAnotherDatafile() -> Scatter correction flags are inconsistent !" << endl);
676  return 1;
677  }
678  // Check random correction flag
679  if (m_randCorrectionFlag!=p_data_file->GetRandCorrectionFlag())
680  {
681  Cerr("***** iDataFilePET::CheckSpecificConsistencyWithAnotherDatafile() -> Random correction flags are inconsistent !" << endl);
682  return 1;
683  }
684  // Check TOF info flag
685  if (m_TOFInfoFlag!=p_data_file->GetTOFInfoFlag())
686  {
687  Cerr("***** iDataFilePET::CheckSpecificConsistencyWithAnotherDatafile() -> TOF information flags are inconsistent !" << endl);
688  return 1;
689  }
690  // Check TOF resolution
691  if (m_resolutionTOF!=p_data_file->GetTOFResolution())
692  {
693  Cerr("***** iDataFilePET::CheckSpecificConsistencyWithAnotherDatafile() -> TOF resolutions are inconsistent !" << endl);
694  return 1;
695  }
696  // Check number of TOF bins
697  if (m_nbBinsTOF!=p_data_file->GetNbTOFBins())
698  {
699  Cerr("***** iDataFilePET::CheckSpecificConsistencyWithAnotherDatafile() -> Numbers of TOF bins are inconsistent !" << endl);
700  return 1;
701  }
702  // Check TOF bin size
703  if (m_binSizeTOF!=p_data_file->GetTOFBinSize())
704  {
705  Cerr("***** iDataFilePET::CheckSpecificConsistencyWithAnotherDatafile() -> TOF bin sizes are inconsistent !" << endl);
706  return 1;
707  }
708  // End
709  return 0;
710 }
711 
712 
713 
714 
715 
716 
717 
718 
719 
720 
721 
722 
723 
724 
725 //PROJECTION SCRIPT FUNCTIONS
726 // =====================================================================
727 // ---------------------------------------------------------------------
728 // ---------------------------------------------------------------------
729 // =====================================================================
730 
731 
732 /*
733  \fn PROJ_InitFile()
734  \brief Initialize the fstream objets for output writing as well as some other variables specific to the Projection script (Event-based correction flags, Estimated size of data file)
735  \todo Adapt m_maxRingDiff initialization for scanner with several layers of crystals (not necessary the same nb of rings)
736  \todo warn the user a datafile with the same name will be erased (eventually add an option to disable the warning)
737  \return 0 if success, and positive value otherwise.
738 */
740 {
741  if(m_verbose>=3) Cout("iDataFilePET::PROJ_InitFile() ..."<< endl);
742 
743  m_startTimeInSec = 0.; //Std initialization for projection
744  m_durationInSec = 1.; //Std initialization for projection
745  m_totalNbEvents = 0; //Std initialization for projection
746  m_nbBinsTOF = 1; // Initialization of this variable required for PROJ_Write functions
747  m_isotope = "unknown";
748 
749  // Instanciate a fstream datafile for each thread
750  m2p_dataFile = new fstream*[mp_ID->GetNbThreadsForProjection()];
751 
752  // Set name of the projection data header
753  sOutputManager* p_OutMgr;
754  p_OutMgr = sOutputManager::GetInstance();
755  string path_name = p_OutMgr->GetPathName();
756  string img_name = p_OutMgr->GetBaseName();
757  m_headerFileName = path_name.append(img_name).append("_CstrProj").append(".Cdh");
758 
759  for (int th=0 ; th<mp_ID->GetNbThreadsForProjection() ; th++)
760  {
761  m_dataFileName = m_headerFileName.substr(0, m_headerFileName.find_last_of(".")).append(".Cdf"); // Generate datafile name from header file
762 
763  // We'll write projeted data in several files (corresponding to the number of thread) to be concatenated at the end of the projection process.
764  stringstream ss;
765  ss << th;
766  string datafile_name = m_dataFileName;
767  datafile_name.append("_").append(ss.str());
768 
769  m2p_dataFile[th] = new fstream( datafile_name.c_str(), ios::binary | ios::out | ios::trunc);
770  }
771 
772 
773  // Check there is no existing datafile with such name. Remove it otherwise
774  ifstream fcheck(m_dataFileName.c_str());
775  if(fcheck.good())
776  {
777  fcheck.close();
778  #ifdef _WIN32
779  string dos_instruction = "del " + m_dataFileName;
780  system(dos_instruction.c_str());
781  #else
782  remove(m_dataFileName.c_str());
783  #endif
784  }
785 
786  if(m_verbose>=3) Cout("iDataFilePET::PROJ_InitFile()-> output datafile name :" << m_dataFileName << endl);
787 
788  return 0;
789 }
790 
791 
792 
793 // =====================================================================
794 // ---------------------------------------------------------------------
795 // ---------------------------------------------------------------------
796 // =====================================================================
797 /*
798  \fn PROJ_WriteEvent(vEvent* ap_Event, FLTNB fp, int a_th, uint32_t a_time)
799  \param ap_Event : event containing the data to write
800  \param a_th
801  \brief Write event according to the chosen type of data
802  \todo Depending of the RAM load FLAG, either write the data in *nbThreads* different files which will be concatenated at the end (current implementation),
803  or write data in buffers, to be flushed at the end of projection loop.
804  \todo Projection for list-mode
805  \return 0 if success, and positive value otherwise.
806 */
807 int iDataFilePET::PROJ_WriteEvent(vEvent* ap_Event, int a_th)
808 {
809  #ifdef CASTOR_VERBOSE
810  // Verbose
811  if(m_verbose>=4) Cout("iDataFilePET::PROJ_WriteEvent() ..."<< endl);
812  #endif
813 
814  if(m_dataMode == MODE_LIST)
815  {
816  if(PROJ_WriteListEvent((iEventListPET*)ap_Event, a_th))
817  {
818  Cerr("*****iDataFilePET::PROJ_WriteEvent() -> Error while trying to write projection datafile (list-mode)" << endl;);
819  return 1;
820  }
821  }
822 
824  {
825  if(PROJ_WriteHistoEvent((iEventHistoPET*)ap_Event, a_th))
826  {
827  Cerr("*****iDataFilePET::PROJ_WriteEvent() -> Error while trying to write projection datafile (histogram)" << endl;);
828  return 1;
829  }
830  }
831 
832  return 0;
833 }
834 
835 // =====================================================================
836 // ---------------------------------------------------------------------
837 // ---------------------------------------------------------------------
838 // =====================================================================
839 /*
840  \fn PROJ_WriteHistoEvent()
841  \param ap_Event : event containing the data to write
842  \param a_th : index of the thread from which the function was called
843  \brief Write a PET histogram event
844  \return 0 if success, and positive value otherwise.
845 */
847 {
848  #ifdef CASTOR_VERBOSE
849  // Verbose
850  if(m_verbose>=4) Cout("iDataFilePET::PROJ_WriteHistoEvent() ..."<< endl);
851  #endif
852 
853  // Write sequentially each field of the event according to the type of the event.
854  m2p_dataFile[a_th]->clear();
855 
856  uint32_t time = ap_Event->GetTimeInMs();
857  m2p_dataFile[a_th]->write(reinterpret_cast<char*>(&time), sizeof(uint32_t));
858 
860  {
861  FLTNB atn_corr_factor = ap_Event->GetAtnCorrFactor();
862  m2p_dataFile[a_th]->write(reinterpret_cast<char*>(&atn_corr_factor), sizeof(FLTNB));
863  }
864 
866  {
867  FLTNB rdm_rate = ap_Event->GetEventRdmRate();
868  m2p_dataFile[a_th]->write(reinterpret_cast<char*>(&rdm_rate), sizeof(FLTNB));
869  }
870 
872  {
873  FLTNB norm_corr_factor = ap_Event->GetNormFactor();
874  m2p_dataFile[a_th]->write(reinterpret_cast<char*>(&norm_corr_factor), sizeof(FLTNB));
875  }
876 
877  for(int b=0 ; b<m_nbBinsTOF ; b++)
878  {
879  FLTNB event_value = ap_Event->GetEventValue(b);
880  m2p_dataFile[a_th]->write(reinterpret_cast<char*>(&event_value), sizeof(FLTNB));
882  {
883  FLTNB scat_rate = ap_Event->GetEventScatRate(b);
884  m2p_dataFile[a_th]->write(reinterpret_cast<char*>(&scat_rate), sizeof(FLTNB));
885  }
886  }
887 
888  uint16_t nb_lines = ap_Event->GetNbLines();
889  // Write the number of lines only if the m_maxNumberOfLinesPerEvent is above 1
890  if (m_maxNumberOfLinesPerEvent>1) m2p_dataFile[a_th]->write(reinterpret_cast<char*>(&nb_lines), sizeof(uint16_t));
891 
892  for(int i=0 ; i<nb_lines ; i++)
893  {
894  uint32_t id1 = ap_Event->GetID1(i);
895  uint32_t id2 = ap_Event->GetID2(i);
896  m2p_dataFile[a_th]->write(reinterpret_cast<char*>(&id1), sizeof(uint32_t));
897  m2p_dataFile[a_th]->write(reinterpret_cast<char*>(&id2), sizeof(uint32_t));
898  }
899 
900  // 0-filling if needed (nb lines inferior to the max number for PET data with compression)
901  if(nb_lines<m_maxNumberOfLinesPerEvent)
902  for(int i=0 ; i<m_maxNumberOfLinesPerEvent-nb_lines ; i++)
903  {
904  uint32_t gbg = 0;
905  m2p_dataFile[a_th]->write(reinterpret_cast<char*>(&gbg), sizeof(uint32_t));
906  m2p_dataFile[a_th]->write(reinterpret_cast<char*>(&gbg), sizeof(uint32_t));
907  }
908 
909  return 0;
910 }
911 
912 
913 
914 
915 // =====================================================================
916 // ---------------------------------------------------------------------
917 // ---------------------------------------------------------------------
918 // =====================================================================
919 /*
920  \fn PROJ_WriteListEvent()
921  \param ap_Event : event containing the data to write
922  \param a_th : index of the thread from which the function was called
923  \brief Write a PET list-mode event
924  \return 0 if success, and positive value otherwise.
925 */
927 {
928  #ifdef CASTOR_VERBOSE
929  // Verbose
930  if(m_verbose>=4) Cout("iDataFilePET::PROJ_WriteListEvent() ..."<< endl);
931  #endif
932 
933  // Write sequentially each field of the event according to the type of the event.
934  m2p_dataFile[a_th]->clear();
935 
936  uint32_t time = ap_Event->GetTimeInMs();
937  m2p_dataFile[a_th]->write(reinterpret_cast<char*>(&time), sizeof(uint32_t));
938 
939 
941  {
942  FLTNB atn_corr_factor = ap_Event->GetAtnCorrFactor();
943  m2p_dataFile[a_th]->write(reinterpret_cast<char*>(&atn_corr_factor), sizeof(FLTNB));
944  }
945 
946  if(m_eventKindFlag)
947  {
948  uint8_t event_kind = ap_Event->GetKind();
949  m2p_dataFile[a_th]->write(reinterpret_cast<char*>(&event_kind), sizeof(uint8_t));
950  }
951 
953  {
954  FLTNB scat_rate = ap_Event->GetEventScatRate(0);
955  m2p_dataFile[a_th]->write(reinterpret_cast<char*>(&scat_rate), sizeof(FLTNB));
956  }
957 
959  {
960  FLTNB rdm_rate = ap_Event->GetEventRdmRate();
961  m2p_dataFile[a_th]->write(reinterpret_cast<char*>(&rdm_rate), sizeof(FLTNB));
962  }
963 
965  {
966  FLTNB norm_corr_factor = ap_Event->GetNormFactor();
967  m2p_dataFile[a_th]->write(reinterpret_cast<char*>(&norm_corr_factor), sizeof(FLTNB));
968  }
969 
970  if(m_TOFInfoFlag)
971  {
972  FLTNBDATA TOF_measurement = ap_Event->GetTOFMeasurement();
973  m2p_dataFile[a_th]->write(reinterpret_cast<char*>(&TOF_measurement), sizeof(FLTNBDATA));
974  }
975 
976 
977  if(mp_POIResolution[0]>0)
978  {
979  FLTNB POI_1 = ap_Event->GetPOI1(0);
980  FLTNB POI_2 = ap_Event->GetPOI2(0);
981  m2p_dataFile[a_th]->write(reinterpret_cast<char*>(&POI_1), sizeof(FLTNB));
982  m2p_dataFile[a_th]->write(reinterpret_cast<char*>(&POI_2), sizeof(FLTNB));
983  }
984  if(mp_POIResolution[1]>0)
985  {
986  FLTNB POI_1 = ap_Event->GetPOI1(1);
987  FLTNB POI_2 = ap_Event->GetPOI2(1);
988  m2p_dataFile[a_th]->write(reinterpret_cast<char*>(&POI_1), sizeof(FLTNB));
989  m2p_dataFile[a_th]->write(reinterpret_cast<char*>(&POI_2), sizeof(FLTNB));
990  }
991  if(mp_POIResolution[2]>0)
992  {
993  FLTNB POI_1 = ap_Event->GetPOI1(2);
994  FLTNB POI_2 = ap_Event->GetPOI2(2);
995  m2p_dataFile[a_th]->write(reinterpret_cast<char*>(&POI_1), sizeof(FLTNB));
996  m2p_dataFile[a_th]->write(reinterpret_cast<char*>(&POI_2), sizeof(FLTNB));
997  }
998 
999  uint16_t nb_lines = ap_Event->GetNbLines();
1000  // Write the number of lines only if the m_maxNumberOfLinesPerEvent is above 1
1001  if (m_maxNumberOfLinesPerEvent>1) m2p_dataFile[a_th]->write(reinterpret_cast<char*>(&nb_lines), sizeof(uint16_t));
1002 
1003  for(int i=0 ; i<nb_lines ; i++)
1004  {
1005  uint32_t id1 = ap_Event->GetID1(i);
1006  uint32_t id2 = ap_Event->GetID2(i);
1007  m2p_dataFile[a_th]->write(reinterpret_cast<char*>(&id1), sizeof(uint32_t));
1008  m2p_dataFile[a_th]->write(reinterpret_cast<char*>(&id2), sizeof(uint32_t));
1009  }
1010 
1011  // 0-filling if needed (nb lines inferior to the max number for PET data with compression)
1012  if(nb_lines<m_maxNumberOfLinesPerEvent)
1013  for(int i=0 ; i<m_maxNumberOfLinesPerEvent-nb_lines ; i++)
1014  {
1015  uint32_t gbg = 0;
1016  m2p_dataFile[a_th]->write(reinterpret_cast<char*>(&gbg), sizeof(uint32_t));
1017  m2p_dataFile[a_th]->write(reinterpret_cast<char*>(&gbg), sizeof(uint32_t));
1018  }
1019 
1020  return 0;
1021 }
1022 
1023 
1024 
1025 
1026 // =====================================================================
1027 // ---------------------------------------------------------------------
1028 // ---------------------------------------------------------------------
1029 // =====================================================================
1030 /*
1031  \fn PROJ_WriteHeader()
1032  \brief Generate a header file according to the projection and data output informations.
1033  Used by Projection algorithm.
1034  \todo Use Interfile format
1035  \return 0 if success, and positive value otherwise.
1036 */
1038 {
1039  if(m_verbose>=3) Cout("PROJ_WriteHeader() ..."<< endl);
1040 
1041  fstream headerFile;
1042  stringstream ss;
1043 
1044  headerFile.open(m_headerFileName.c_str(), ios::out);
1045 
1046  // ----- MANDATORY FLAGS ----- //
1047  headerFile << "Data filename:" << " " << GetFileFromPath(m_dataFileName).c_str() << endl;
1048  headerFile << "Number of events:" << " " << m_totalNbEvents << endl;
1049 
1050  //- Flag: list-mode or histogram mode
1051  headerFile << "Data mode:" << " " << m_dataMode << endl;
1052  // Flag: PET, SPECT or TRANSMISSION
1053  headerFile << "Data type: " << " " << "PET" << endl;
1054 
1055  headerFile << "Start time (s):" << " " << m_startTimeInSec << endl;
1056 
1057  headerFile << "Duration (s):" << " " << m_durationInSec << endl;
1058 
1059  sScannerManager* p_scannermanager;
1060  p_scannermanager = sScannerManager::GetInstance();
1061 
1062  headerFile << "Scanner name:" << " " << p_scannermanager->GetScannerName() << endl;
1063 
1064  headerFile << "Maximum ring difference:" << " " << m_maxRingDiff << endl;
1065 
1066  // Only write this field if different than default value
1068  headerFile << "Maximum number of lines per event:" << " " << m_maxNumberOfLinesPerEvent << endl;
1069 
1070 
1071 
1072  // ----- OPTIONNAL FLAGS ----- //
1073  headerFile << "Calibration factor:" << " " << m_calibrationFactor << endl;
1074 
1075  if (m_isotope != "unknown") headerFile << "Isotope:" << " " << m_isotope << endl;
1076 
1077 
1078 
1079  // ----- TOF info ----- //
1080  if(m_TOFInfoFlag)
1081  {
1082  if(m_dataMode == MODE_LIST)
1083  {
1084  if(m_resolutionTOF <= 0.) // Check if TOF resolution (list-mode) initialized, error otherwise
1085  {
1086  Cerr("***** iDataFilePET::PROJ_WriteHeader -> Error : TOF resolution (mm) for list-mode not initialized, while TOF correction flag is enabled!" << endl);
1087  return 1;
1088  }
1089  else
1090  headerFile << "TOF resolution:" << " " << m_resolutionTOF << endl;
1091  }
1092  else if (m_dataMode == MODE_HISTOGRAM)
1093  {
1094  if(m_binSizeTOF > 0.) // Check if TOF bin size (histogram) initialized, error otherwise
1095  {
1096  Cerr("***** iDataFilePET::PROJ_WriteHeader -> Error : TOF bin size for histogram mode not initialized, while TOF correction flag is enabled!" << endl);
1097  return 1;
1098  }
1099  else
1100  {
1101  headerFile << "Histo TOF number of bins:" << " " << m_nbBinsTOF << endl;
1102  headerFile << "Histo TOF bin size:" << " " << m_binSizeTOF << endl;
1103  }
1104  }
1105  else
1106  {
1107  Cerr("***** iDataFilePET::PROJ_WriteHeader -> Error : Datafile mode unknown (should be 0 (list-mode) or histogram (1))!" << endl);
1108  return 1;
1109  }
1110  }
1111 
1112 
1113  // ----- POI info ----- //
1114  if (mp_POIResolution[0]>0. || mp_POIResolution[1]>0. || mp_POIResolution[2]>0.)
1115  {
1116  // Error if histogram data are used
1118  {
1119  Cerr("***** iDataFilePET::PROJ_WriteHeader -> Request for writing POI resolution in histogram mode (this field is specific to list-mode) !" << endl);
1120  return 1;
1121  }
1122  else
1123  headerFile << "DOI capability:" << " " << mp_POIResolution[0] << "," << mp_POIResolution[1] << "," << mp_POIResolution[2] << endl;
1124  }
1125 
1126 
1127  // ----- Event kind ----- //
1128  if (m_eventKindFlag)
1129  {
1130  // Error if histogram data are used
1132  {
1133  Cerr("***** iDataFilePET::PROJ_WriteHeader -> Request for writing event type in histogram mode (this field is specific to list-mode) !" << endl);
1134  return 1;
1135  }
1136  else
1137  headerFile << "Coincidence kind informations flag:" << " " << m_eventKindFlag << endl;
1138  }
1139 
1140 
1141  // ----- Correction flags ----- //
1142 
1144  headerFile << "Attenuation correction flag:" << " " << m_atnCorrectionFlag << endl; //TODO Should be computed during projection
1145 
1147  headerFile << "Normalization correction flag:" << " " << m_normCorrectionFlag << endl;
1148 
1150  headerFile << "Scatter correction flag:" << " " << m_scatCorrectionFlag << endl;
1151 
1153  headerFile << "Random correction flag:" << " " << m_randCorrectionFlag << endl;
1154 
1155  headerFile.close();
1156 
1157  return 0;
1158 }
1159 
1160 
1161 
1162 
1163 // =====================================================================
1164 // ---------------------------------------------------------------------
1165 // ---------------------------------------------------------------------
1166 // =====================================================================
1167 /*
1168  \fn PROJ_GetScannerSpecificParameters()
1169  \brief Get PET specific parameters for projections from the scanner object, through the scannerManager.
1170  \return 0 if success, positive value otherwise
1171 */
1173 {
1174  if(m_verbose>=3) Cout("PROJ_GetScannerSpecificParameters() ..."<< endl);
1175  sScannerManager* p_scannermanager;
1176  p_scannermanager = sScannerManager::GetInstance();
1177 
1178  // Get pointers to SPECT specific parameters in scanner
1179  if(p_scannermanager->PROJ_GetPETSpecificParameters(&m_maxRingDiff) )
1180  {
1181  Cerr("***** iDataFilePET::PROJ_GetScannerSpecificParameters() -> An error occurred while trying to get PET geometric parameters from the scanner object !" << endl);
1182  return 1;
1183  }
1184 
1185  return 0;
1186 }
bool m_randCorrectionFlag
This class is designed to be a mother virtual class for Datafile.
Definition: vDataFile.hh:67
bool GetNormCorrectionFlag()
Simply return m_normCorrectionFlag.
int SetPETIsotope(int a_bed, const string &a_isotope)
Set the PET isotope for the provided bed.
static sScannerManager * GetInstance()
Instanciate the singleton object and Initialize member variables if not already done, return a pointer to this object otherwise.
#define VERBOSE_DEBUG_EVENT
bool GetTOFInfoFlag()
Definition: iDataFilePET.hh:84
#define MODE_HISTOGRAM
Definition: vDataFile.hh:36
#define TYPE_PET
Definition: vDataFile.hh:51
void SetNbLines(uint16_t a_value)
Set the number of lines of the Event.
Definition: vEvent.hh:134
int64_t m_sizeEvent
Definition: vDataFile.hh:528
bool mp_POIDirectionFlag[3]
Definition: vDataFile.hh:534
string m_dataFileName
Definition: vDataFile.hh:520
#define MODE_LIST
Definition: vDataFile.hh:34
int PROJ_GetScannerSpecificParameters()
Get PET specific parameters for projections from the scanner object, through the scannerManager.
#define FLTNB
Definition: gVariables.hh:55
#define MODE_NORMALIZATION
Definition: vDataFile.hh:38
FLTNB m_binSizeTOF
bool m_ignoreNormCorrectionFlag
bool m_ignoreTOFFlag
FLTNB GetEventScatRate(int a_bin)
uint32_t GetID2(int a_line)
Definition: vEvent.hh:88
#define VERBOSE_DETAIL
int PROJ_GetPETSpecificParameters(int *a_maxRingDiff)
Transfer addresses to each geometric parameter of the PET scanner objets to the corresponding pointer...
FLTNB m_durationInSec
Definition: vDataFile.hh:525
iDataFilePET()
iDataFilePET constructor. Initialize the member variables to their default values.
Definition: iDataFilePET.cc:16
bool GetIgnoreAttnCorrectionFlag()
Get the boolean that says if the attenuation correction is ignored or not.
int ReadSpecificInfoInHeader(bool a_affectQuantificationFlag)
Read through the header file and gather specific PET information.
Definition: iDataFilePET.cc:51
int CheckSpecificConsistencyWithAnotherDatafile(vDataFile *ap_Datafile)
Check consistency between 'this' and the provided datafile, for specific characteristics.
string m_headerFileName
Definition: vDataFile.hh:519
int CheckSpecificParameters()
Check parameters specific to PET data.
int m_dataMode
Definition: vDataFile.hh:522
static sOutputManager * GetInstance()
Instanciate the singleton object and Initialize member variables if not already done, return a pointer to this object otherwise.
bool m_ignoreScatCorrectionFlag
int ComputeSizeEvent()
Computation of the size of each event according to the mandatory/optional correction fields...
Definition: iDataFilePET.cc:88
Declaration of class iDataFilePET.
FLTNB m_startTimeInSec
Definition: vDataFile.hh:524
bool m_eventKindFlag
int PROJ_WriteHistoEvent(iEventHistoPET *ap_Event, int a_th)
Write a PET histogram event.
string GetFileFromPath(const string &a_pathToFile)
Simply return the file from a path string passed in parameter.
Definition: gOptions.cc:1119
string GetIsotope()
bool GetIgnoreNormCorrectionFlag()
Get the boolean that says if the normalization correction is ignored or not.
bool GetIgnoreRandCorrectionFlag()
Get the boolean that says if the random correction is ignored or not.
#define FLTNBDATA
Definition: gVariables.hh:59
FLTNB GetTOFMeasurement()
void SetAttenuationCorrectionFactor(FLTNBDATA a_value)
Cast the FLTNBDATA value passed as parameter in FLTNB, and set it to the attenuation correction facto...
Definition: iEventNorm.hh:75
Inherit from iEventPET. Class for PET list-mode events.
FLTNB GetEventValue(int a_bin)
#define Cerr(MESSAGE)
const string & GetPathName()
Inherit from iEventPET. Class for PET histogram mode events.
#define VERBOSE_DEBUG_LIGHT
bool m_ignorePOIFlag
Definition: vDataFile.hh:533
~iDataFilePET()
iDataFilePET destructor.
Definition: iDataFilePET.cc:44
FLTNB GetTOFResolution()
Definition: iDataFilePET.hh:96
int PROJ_WriteEvent(vEvent *ap_Event, int a_th)
Write event according to the chosen type of data.
Singleton class that manages output writing on disk (images, sinograms, etc). It also manages loggi...
FLTNB m_resolutionTOF
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:111
Singleton class that Instantiate and initialize the scanner object.
bool m_ignoreAttnCorrectionFlag
int m_dataType
Definition: vDataFile.hh:523
bool GetScatCorrectionFlag()
Simply return m_scatCorrectionFlag.
oImageDimensionsAndQuantification * mp_ID
Definition: vDataFile.hh:514
uint16_t GetMaxNumberOfLinesPerEvent()
fstream ** m2p_dataFile
Definition: vDataFile.hh:518
bool GetEventKindFlag()
Simply return m_eventKindFlag.
#define VERBOSE_NORMAL
uint8_t GetKind()
FLTNB GetNormFactor()
Definition: iEventPET.hh:66
int m_bedIndex
Definition: vDataFile.hh:527
int PROJ_InitFile()
Initialize the fstream objets for output writing as well as some other variables specific to the Proj...
int PROJ_WriteHeader()
Generate a header file according to the projection and data output informations. Used by Projection...
#define KEYWORD_OPTIONAL
Definition: gOptions.hh:27
FLTNB * GetPOI2()
int GetMaxRingDiff()
vEvent * GetEventFromBuffer(char *ap_buffer, int a_th)
Read an event from the position pointed by 'ap_buffer', parse the generic or modality-specific inform...
Inherit from vEvent. Used for normalization events for sensitivity computation.
Definition: iEventNorm.hh:27
int PrepareDataFile()
Store different kind of information inside arrays (data relative to specific correction as well as ba...
FLTNB mp_POIResolution[3]
Definition: vDataFile.hh:535
const string & GetBaseName()
uint16_t GetNbLines()
Definition: vEvent.hh:74
void SetTimeInMs(uint32_t a_value)
Set the timestamp of the Event.
Definition: vEvent.hh:119
Mother class for the Event objects.
Definition: vEvent.hh:23
FLTNB GetTOFBinSize()
string m_isotope
FLTNB GetAtnCorrFactor()
Definition: iEventPET.hh:72
int PROJ_WriteListEvent(iEventListPET *ap_Event, int a_th)
Write a PET list-mode event.
vEvent ** m2p_BufferEvent
Definition: vDataFile.hh:538
bool GetRandCorrectionFlag()
Simply return m_randCorrectionFlag.
bool m_POIInfoFlag
Definition: vDataFile.hh:532
uint32_t GetID1(int a_line)
Definition: vEvent.hh:81
FLTNB * GetPOI1()
int GetNbThreadsForProjection()
Get the number of threads used for projections.
int GetScannerLayerNbRings(int a_layer)
Ask the number of rings to the scanner object for a specific layer. Returns an error if this inform...
bool GetIgnoreScatCorrectionFlag()
Get the boolean that says if the scatter correction is ignored or not.
int GetNbTOFBins()
#define DEBUG_VERBOSE(IGNORED1, IGNORED2)
int CheckFileSizeConsistency()
This function is implemented in child classes Check if file size is consistent. ...
#define Cout(MESSAGE)
FLTNB m_calibrationFactor
Definition: vDataFile.hh:526
FLTNB GetEventRdmRate()
Definition: iEventPET.hh:60
bool m_atnCorrectionFlag
bool m_normCorrectionFlag
uint16_t m_maxNumberOfLinesPerEvent
bool GetAtnCorrectionFlag()
Simply return m_atnCorrectionFlag.
Inherit from vDataFile. Class that manages the reading of a PET input file (header + data)...
Definition: iDataFilePET.hh:26
bool m_scatCorrectionFlag
FLTNB GetEventScatRate(int a_bin)
int m_verbose
Definition: vDataFile.hh:515
uint32_t GetTimeInMs()
Definition: vEvent.hh:68
int64_t m_totalNbEvents
Definition: vDataFile.hh:521
bool m_ignoreRandCorrectionFlag