Issue with Writing TH3S Histogram with Weights to TFile

I am facing an issue while working with ROOT, specifically when trying to write a large TH3S histogram to a TFile. Here’s the scenario:

  1. I have successfully created a TH3S histogram with a size of 1200x1200x240 bins.
  2. I can fill this histogram without any issues using the Fill() function.
  3. However, when I attempt to add weights to the histogram based on my analysis, I encounter difficulties in writing the histogram to a TFile. The error message is:
Fatal in <TBufferFile::AutoExpand>: Request to expand to a negative size, likely due to an integer overflow: 0xa6b8fe40 for a max of 0x7ffffffe.
aborting
  1. What could be causing the issue when adding weights to the TH3S histogram that prevents it from being written to a TFile?
  2. Are there any limitations or constraints related to the use of weights with large histograms in ROOT?

A sample code snippet that reproduces the issue I am encountering in an interactive mode:


root [0] TH3S* th3ssample=new TH3S("th", "th", 1200,-15, 15, 1200, -15, 15, 240, -3, 3 )
(TH3S *) 0x7fe2faa3b000
root [1] th3ssample->Fill(1, 3, 46)
(int) -1
root [2] TFile* outputFile = TFile::Open("test.root", "RECREATE")
(TFile *) 0x7fe3028b45b0
root [3] th3ssample->Write()
(int) 3052471
root [4] th3ssample->Fill(1, 3, 46, 0.3)
(int) -1
root [5] th3ssample->Write()

 *** Break *** segmentation violation
[/usr/lib/system/libsystem_platform.dylib] _sigtramp (no debug info)
[<unknown binary>] (no debug info)
[/usr/local/Cellar/root/6.26.06_2/lib/root/libRIO.so] TBufferFile::WriteFastArray(void*, TClass const*, int, TMemberStreamer*) (no debug info)
[/usr/local/Cellar/root/6.26.06_2/lib/root/libRIO.so] int TStreamerInfo::WriteBufferAux<char**>(TBuffer&, char** const&, TStreamerInfo::TCompInfo* const*, int, int, int, int, int) (no debug info)
[/usr/local/Cellar/root/6.26.06_2/lib/root/libRIO.so] TStreamerInfoActions::GenericWriteAction(TBuffer&, void*, TStreamerInfoActions::TConfiguration const*) (no debug info)
[/usr/local/Cellar/root/6.26.06_2/lib/root/libRIO.so] TBufferFile::ApplySequence(TStreamerInfoActions::TActionSequence const&, void*) (no debug info)
[/usr/local/Cellar/root/6.26.06_2/lib/root/libRIO.so] TBufferFile::WriteClassBuffer(TClass const*, void*) (no debug info)
[/usr/local/Cellar/root/6.26.06_2/lib/root/libCore.so] TStreamerBase::WriteBuffer(TBuffer&, char*) (no debug info)
[/usr/local/Cellar/root/6.26.06_2/lib/root/libRIO.so] int TStreamerInfo::WriteBufferAux<char**>(TBuffer&, char** const&, TStreamerInfo::TCompInfo* const*, int, int, int, int, int) (no debug info)
[/usr/local/Cellar/root/6.26.06_2/lib/root/libRIO.so] TStreamerInfoActions::GenericWriteAction(TBuffer&, void*, TStreamerInfoActions::TConfiguration const*) (no debug info)
[/usr/local/Cellar/root/6.26.06_2/lib/root/libRIO.so] TBufferFile::ApplySequence(TStreamerInfoActions::TActionSequence const&, void*) (no debug info)
[/usr/local/Cellar/root/6.26.06_2/lib/root/libRIO.so] TBufferFile::WriteClassBuffer(TClass const*, void*) (no debug info)
[/usr/local/Cellar/root/6.26.06_2/lib/root/libCore.so] TStreamerBase::WriteBuffer(TBuffer&, char*) (no debug info)
[/usr/local/Cellar/root/6.26.06_2/lib/root/libRIO.so] int TStreamerInfo::WriteBufferAux<char**>(TBuffer&, char** const&, TStreamerInfo::TCompInfo* const*, int, int, int, int, int) (no debug info)
[/usr/local/Cellar/root/6.26.06_2/lib/root/libRIO.so] TStreamerInfoActions::GenericWriteAction(TBuffer&, void*, TStreamerInfoActions::TConfiguration const*) (no debug info)
[/usr/local/Cellar/root/6.26.06_2/lib/root/libRIO.so] TBufferFile::ApplySequence(TStreamerInfoActions::TActionSequence const&, void*) (no debug info)
[/usr/local/Cellar/root/6.26.06_2/lib/root/libRIO.so] TBufferFile::WriteClassBuffer(TClass const*, void*) (no debug info)
[/usr/local/Cellar/root/6.26.06_2/lib/root/libRIO.so] TKey::TKey(TObject const*, char const*, int, TDirectory*) (no debug info)
[/usr/local/Cellar/root/6.26.06_2/lib/root/libRIO.so] TFile::CreateKey(TDirectory*, TObject const*, char const*, int) (no debug info)
[/usr/local/Cellar/root/6.26.06_2/lib/root/libRIO.so] TDirectoryFile::WriteTObject(TObject const*, char const*, char const*, int) (no debug info)
[/usr/local/Cellar/root/6.26.06_2/l```

Welcome to the ROOT forum.

Are you sur you have enough memory to store an histogram that large ? Histograms are memory resident objects.

1 Like

I do have sufficient memory for the TH3S histogram without weights, and my main concern is understanding why adding weights prevents me from writing it.

@pcanal will know.

1 Like

The maximum object size store in a single I/O operation is currently 1Gb. The error suggest that your object is larger than 2GB. And indeed. 1200 * 1200 * 240 x (2 /*sizeof(short) / + 8 / statistics */) is 3.2 GB.

The best way to store this data is to store the original data (the parameter that you pass to Fill() into a TTree and to regenerate the TH3S when you need it from that data.

1 Like

Thank you for your response and explanation of the issue I’m facing with writing the TH3S histogram. Your insight into the 1GB limitation for I/O operations and the fact that my histogram’s size exceeds 2GB due to its dimensions and statistics is quite helpful.

However, I still have a couple of questions and concerns:

  1. Writing Without Weights: You mentioned that the error suggests that my object is larger than 2GB, but you didn’t explain why I can write the TH3S histogram without weights successfully. It seems there is a discrepancy between writing with and without weights. Understanding this difference will help me grasp the root cause better.
  2. FFT and Inverse FFT: As you pointed out, storing the original data in a TTree and regenerating the TH3S when needed is a workaround. However, I require the TH3S histogram to perform Fast Fourier Transform (FFT) and Inverse FFT operations, and these operations also have memory implications. Can you provide any suggestions on how to handle memory efficiently when dealing with FFT and inverse FFT operations on large data sets?

but you didn’t explain why I can write the TH3S histogram without weights successfully.

Without the weight, the storage is “only” one short per bin (i.e. 2 bytes for a total of 0.64 Gb). With the weight there is an additional double per bin (so now 2+8 bytes per bins for a total of 3.2 Gb).

Thanks, I see.

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.