Applying a unique name to TObject::Clone

Hi,

I have code that depends on cloning a base histogram using multiple calls to TTree::Draw. I’m using the syntax:

TTree::Draw("branch_name>>hist_name","cuts") where the “cuts” string is a series of cuts applied. I’ve been doing this:

base_hist->Clone("hist_name")
where I generate the hist_name from the cuts applied. This works, but it creates really long internal names. It also breaks if I call the same branch, sample, and set of cuts for another plot. My question is: is there a way to generate a unique name to clone from?

Maybe a more elegant solution would be to avoid the problematic “branch_name>>hist_name” syntax, and use a different drawing function? I’m unaware of such a thing though.

I’ve resorted to appending the system time in nanoseconds in order to get unique clones on each function call, but I have a strong feeling that this is a symptom of a greater problem in the way I’m organizing my calls to TTree::Draw.

Hi,

Instead of nanoseconds, you could also use a static counter.

Alternatively you could use a staging directory:TDirectory *staging = gROOT->mkdir("staging"); .... { TDirectory::TContext ctxt(staging); // Set staging to be the current directory, return to the previous current directory at the end of the scope TH1 *hist = (TH1*)base_hist->Clone("hist_name"); TTree::Draw("branch_name>>hist_name","cuts"); hist->SetDirectory(0); // Detach histo from staging directory; return hist; }

Cheers,
Philippe.

Ah, I didn’t think of a static counter. Slightly more elegant I suppose.

I never would have thought of the staging directory construct. Since the histogram is made in the staging directory and then detached, does that mean that ROOT will reliably write into the newly cloned histogram with the same name? As I understand it now, the issue is that TTree::Draw(“foo>>bar”) will create an empty “bar” histogram if TTree::Draw is called after the original histogram named “bar” is out of scope.

If I were to re-write your example more in context of my application I would write something like:

draw_hist(/*appropriate arguments */){
    TDirectory *staging = gROOT->mkdir("staging"); //Makes a directory in whatever TFile has scope, or in memory if no TFile is open for writing
    TDirectory::TContext ctxt(staging); //how is this different thant staging->cd() ?
    TH1 *hist = (TH1*)base_hist->Clone("hist_name");
    TTree::Draw("branch_name>>hist_name","cuts");
    hist->SetDirectory(0); //Detached, and not associated with any TFiles
    staging->rmdir(); //Clean up the staging directory for the next time this function is called
    return hist;
}

does that mean that ROOT will reliably write into the newly cloned histogram with the same name?

Yes, because it will be the only one with that name in the ‘current directory’.

TDirectory::TContext ctxt(staging); //how is this different thant staging->cd() ?

It will also set the current directory back to what it was before that call (i.e. TDirectory *sav = gDirectory; staging->cd(); and at the end of the scope sav->cd() … which additional protection for sav being null, etc.)

now, the issue is that TTree::Draw(“foo>>bar”) will create an empty “bar” histogram if TTree::Draw is called after the original histogram named “bar” is out of scope.

I am not sure what you mean.

Cheers,
Philippe.