Streamers and TBufferFile without files

Hi all,

  My analysis framework is set up such that there is an Event class which contains event data, and the various analysis classes inherit from it. The normal operation is that for every event the analysis class's base Event class gets cleared and the ntuple data is loaded into it.

The Event class is persistable–at the moment I am writing it to a file using the copy constructor, as I am unaware of a way to tell ROOT I only want to save a base class (i.e., only call Event::Streamer when writing):

Event* evt = new Event((Event)derivedclass);
evt->Write();

If there is a better way please let me know. My real problem is in reading it back. I can load it from the file fine, but I would like to be able to easily replace the members of the analysis class’s Event base class with the one I loaded from the disk. I can probably do this by writing an assignment operator for Event, but it would be better if it was something automatically maintained/generated, like Streamer().

Should it be possible to do something like this? I keep getting version errors and other errors when I try it.

root [0] Event* evt = new Event()
root [1] TBufferFile* buf = new TBufferFile(TBuffer::kWrite)
root [2] evt->Streamer(buf)
root [3] buf->SetReadMode()
root [4] Event
evt2 = new Event()
root [5] evt2->Streamer(*buf)

I can’t get it to work. Does TBufferFile only work with reading and writing from files?

-Bart

After writing this I realized that C++ gives me a default assignment operator, so that solves that problem. Still, I am curious why the Streamer thing I did didn’t work for copying a class.

Hi,

When using the TBufferFile, you omitted to ‘rewind’ the buffer so that the reading would start at the beginning of the buffer rather than at the end. i.e. to switch to reading use:buf->SetReadMode(); buf->Reset();

Cheers,
Philippe.

Hmmm, that certainly helped, but it still fails with:

Error in TBufferFile::ReadVersion: Could not find the StreamerInfo with a checksum of 0x301 for the class “MomentObj” (buffer with no parent)
Error in TBufferFile::ReadClassBuffer: Could not find the StreamerInfo for version 0 of the class MomentObj, object skipped at offset 8

This is probably due to the TBufferFile not being attached to an actual file, right?

[quote]This is probably due to the TBufferFile not being attached to an actual file, right?[/quote]humm … no. For example TObject::Clone is implemented pretty much the same way you used TBufferFile. And if you class inherit from TObject, doing: Event* evt = new Event() Event *ev2 = (Event*)evt->Clone();does the same as your code (plus handle several possible complication in the hierarchy).

[quote]Hmmm, that certainly helped, but it still fails with:[/quote]This is strange. Can you send me the actual code that is failing?

Cheers,
Philippe.

Hi Philippe,

I found time to try to devise an example I could send you, and it worked fine. I have no idea what was wrong before…very odd. So thanks!

Last question…would there be an obvious reason why using TObject->Clone() would be significantly slower that the corresponding class’s copy constructor? I ask because I had a method which would clone a vector of TObjects on-by-one, but every time I used it it was painfully slow, but using the copy constructor it was fast.

-Bart

Hi Bart,

Yes, TObject::Clone has a large overhead compare to the copy constructor ; it needs to creates a TBufferFile object, it needs to stream/write the original object in the buffer and then stream/read out into the new object while the copy constructor just needs to do the minimal set of assignment. Clone is most useful when in the code you do not know the exact type of the source object (for example you have a heterogeneous collection of objects).

Cheers,
Philippe.