Histogram Input Datafile Generation

Hello All,

I want to create a histogram input datafile. However, I have a couple of ambiguities in understanding histogram mode.

1- In table 2, page 34 of the documentation, what is “Amount of data in the histogram (TOF) bin” parameter? I do not know how this parameter is calculated?

2- For simplicity, let’s assume that we do not have attenuation, random, scatter and normalization factors. Only we record the crystal IDs (even no TOF). As a histogram mode, the name histogram makes me think that each data channel (i.e, the line connecting two crystals, crystal1 and crsytal2) appears only once in the datafile with the number of events (counts) for the channel. So, if we imagine that the datafile is recorded line by line, then loosely speaking, it should look like as follows where there is only one line in the whole datafile that contains “ID_crystal1 ID_crystal2”.

.
.
.
time  num_counts(=amout of data)  ID_crystal1  ID_crystal2
.
.
.

But, from table 2 and the code in “iDataFilePET.cc” (, and even since we are recording time), it looks like that the histogram datafile does not look like what I had in mind and it is written in a way that “ID_crystal1 ID_crystal2” might appear in two different lines in the datafile. Look at the code snippet below taken from “iDataFilePET.cc”.

int iDataFilePET::WriteHistoEvent(iEventHistoPET* ap_Event, int a_th)
{
 /*
some code
*/
  uint32_t time = ap_Event->GetTimeInMs();
  m2p_dataFile[a_th]->write(reinterpret_cast<char*>(&time), sizeof(uint32_t));
  
/*
  some code
*/

  for(int b=0 ; b<m_nbTOFBins ; b++)
  {
    FLTNBDATA event_value = ap_Event->GetEventValue(b);
    m2p_dataFile[a_th]->write(reinterpret_cast<char*>(&event_value), sizeof(FLTNBDATA));
    if(m_scatCorrectionFlag) 
    {
      FLTNBDATA scat_rate = ap_Event->GetEventScatRate(b);
      m2p_dataFile[a_th]->write(reinterpret_cast<char*>(&scat_rate), sizeof(FLTNBDATA));
    }
  }
  
  uint16_t nb_lines = ap_Event->GetNbLines();
  // Write the number of lines only if the m_maxNumberOfLinesPerEvent is above 1
  if (m_maxNumberOfLinesPerEvent>1) m2p_dataFile[a_th]->write(reinterpret_cast<char*>(&nb_lines), sizeof(uint16_t));

  for(int i=0 ; i<nb_lines ; i++)
  {
    uint32_t id1 = ap_Event->GetID1(i);
    uint32_t id2 = ap_Event->GetID2(i);
    m2p_dataFile[a_th]->write(reinterpret_cast<char*>(&id1), sizeof(uint32_t));
    m2p_dataFile[a_th]->write(reinterpret_cast<char*>(&id2), sizeof(uint32_t));
  }

  // Custom fields
/*
some code
*/
  return 0;
}

However, in this case except for “Amount of data in the histogram (TOF) bin”, histogram and list mode datafiles are similar. Can you please help me to understand this concept and how to write a histogram data file? I generate each event and then record its information. I do this for list-mode without any problem, however, I am not sure how to do it for the histogram mode.

Thank,
Seyyed

Greetings,

“Amount of data” is the number of coincidences detected. Thus, you simply counts the number of coincidences observed in the pair of detectors [ID_crystal1, ID_crystal2] that have a TOF within the each of the bins. If you do not have TOF, then all your coincidences are in the same bin. If you have TOF, you need to counts the coincidence following your choice of Histo TOF number of bins and Histo TOF bin size (ps). If I were to take a guess, with an even number of TOF bins, the bins are expected to be split in two at 0 ps; while with an odd number of TOF bins, the “middle” bins is expected to be centered at 0 ps. (I did try a quick ctrl+f of the documentation to make sure, but I didn’t found anything: don’t quote me on this! XD)

From the previous, I think you can see that an entry in CASToR histogram format is, assuming that there are K TOF bins, as follow:

Reminder: No TOF => T=1.

I hope it helps!

Note: I have never written an TOF histogram in CASToR, so take the previous with a grain of salt.

1 Like

Thank you for the clarification. However, I was suspicious because I thought if “Amount of data” is actually equal to “number of detected coincidences”, then why the type is “FLTNBDATA”.

So, in order to write the data in a histogram data file (one coincidence at a time), I need to check whether the pair of detectors [ID_crystal1, ID_crystal2] has already been written to the binary file, and if yes, then I need to increase “amount of data” value by one, otherwise, I will add the pair set the “amount of data” value to 1, right?

Best,
Seyyed

If I had to take a guess, I would say that the choice of type is to support pre-corrected histograms.

Yup, that is the right idea, but, just in case, let me explicit 3.5 details:

  • [ID_crystal1, ID_crystal2] and [ID_crystal2, ID_crystal1] are the same TOR: only one of them should be written as an entry in the histogram
    • Do not forget that if, e.g., you choose to write [ID_crystal1, ID_crystal2], then the TOF associated with events of [ID_crystal2, ID_crystal1] needs to be inverted.
  • I would create a dictionary of the number of coincidences per detector pair before writing any entry. Playing in memory is easier than read/write.
  • If memory serves right, when CASToR is provided a histogram, it assumes that all the relevant TOR are provided in the histogram file. Thus, you need to write an entry for every valid TOR, even if the “data” is zero.

Lastly, I would read, or re-read, all the relevant part of the documentation before attempting anything. There might have further subtleties to consider.


May CASToR build a strong foundation for your research. (Bad joke about the fact that castor is french for beaver and that they build dam)

2 Likes

Thank you, Maxime! This was really useful.

Thank you again, Maxime!

I just want to share that I actually were able to generate histogram data in my simulation. In addition, I wrote a piece of code for combining two histogram data. I want to share it here as it might be useful for someone like me. Here is the link on GitHub. It worked for what I needed. It can be implemented differently, however, I used map and set in C++. Let me know for any suggestions or for any bugs.

Note that I have used a very simple version in which there is no TOF and the time is a fixed number.

Best,
Seyyed

1 Like