Copy tree to new file and rename it

depending on the content of the TTree you’re dealing with, the root-cp command from Go-HEP may help you (while the one you get from ROOT/C++ is being fixed).

see:

$> root-cp -h
Usage: root-cp [options] file1.root[:REGEXP] [file2.root[:REGEXP] [...]] out.root

ex:
 $> root-cp f.root out.root
 $> root-cp f1.root f2.root f3.root out.root
 $> root-cp f1.root:hist.* f2.root:h2 out.root

options:

there’s also a root-merge command (under the same location).

$> root-merge -h
Usage: root-merge [options] file1.root [file2.root [file3.root [...]]]

ex:
 $> root-merge -o out.root ./testdata/chain.flat.1.root ./testdata/chain.flat.2.root

options:
  -o string
    	path to merged output ROOT file (default "out.root")
  -v	enable verbose mode

@pcanal I saw probably similar problem in master in my PR Testing builtin fast lzma2 in ROOT by oshadura · Pull Request #216 · root-project/rootbench · GitHub

Doesn’t work:

..
auto newtree = oldtree->CloneTree();
newfile->SetCompressionAlgorithm(algo);
newfile->SetCompressionLevel(comp_level);
..
newfile->Write();

Working version:

..
newfile->SetCompressionAlgorithm(algo);
newfile->SetCompressionLevel(comp_level);
auto newtree = oldtree->CloneTree();
..
newfile->Write();

This one worked for me and did not actually change the name of the tree in the original file.

So now get the first step done. Which means that i can take all the input files and from them produce new ones that only contain the properly renamed “nominal” trees including all cycle numbers.

However now i need to add all of these trees together. And i noticed that hadd always just takes the highest cycle. However, i need to combine all of the cycles from all of the files.

So currently i now have 2 files that contain PolSig;1 and PolSig;2.
One file that containts PolBkg;1 and one that containrs PolBkg;1 and PolBkg;2.

What i needs is one files that contains PolSig and PolBkg that are the sum of the four PolSig’s and three PolBkg’s. I do not care if they are also split into different cycles but i need all events from the input files to be in the merged one. Is there any reasonable way to do that?

See:

@Wile_E_Coyote with you chance to hsimple.C, I can reproduce the behavior …

So, the behavior is exactly as intended. The flow is:

  oldfile.GetObject("ntuple", oldtree);
  ...
  auto newtree = oldtree->CloneTree();

where the request is here “explicitly” to slow copy a TTree named “ntuple”, and which has, in the original case and the modified hsimple case, more entries that the AutoSave limit. This means that during the execution of CloneTree a cycle for the TTree named “ntuple” is (of course) created.
Calling TTree::SetObject (better version of SetNameTitle but same result here), will change the name of the live object (and we see that with the name of the key/cycle written by TFile::Write) but will not (and should not) retroactively change the name of the existing cycles in the file. So

  KEY: TNtuple	ntuple;1	Demo ntuple
  KEY: TNtuple	PolSig;1	PolSig

depicts accurately what has happened:

  1. a TNtuple named “ntuple” was auto-saved
  2. a TNtuple named “PolSig” was saved.

To modify the behavior you can change the name of the TNtuple *before* cloning it:

     oldtree->SetObject("PolSig","PolSig");
     auto newtree = oldtree->CloneTree();

*or* avoid the call to AutoSave (and save a lot of time! :slight_smile: ) by using the fast cloning.

  auto newtree = oldtree->CloneTree(-1, "fast");
  newtree->SetObject("PolSig","PolSig");

but still even in that case I would rename the object before cloning.

Cheers,
Philippe.

Yes, this is the intent. Lowest cycles are, for all the automatic tools, consider are backup backup that are to be ignored (as they contains redundant information).

So currently i now have 2 files that contain PolSig;1 and PolSig;2.

I am confused. Do you really have 2 completely distinct TNtuple with the same name and PolSig;1 is not a backup/partial-copy of PolSig;2? How did you get there? Why?

For example in the case of the extended hsimple.C from Wile, we ended up with a file containing:

TFile**		hs3.root	Demo ROOT file with histograms
 TFile*		hs3.root	Demo ROOT file with histograms
  OBJ: TNtuple	ntuple	Demo ntuple : 0 at: 0x7fb4fecd4070
  KEY: TH1F	hpx;1	This is the px distribution
  KEY: TH2F	hpxpy;1	py vs px
  KEY: TProfile	hprof;1	Profile of pz versus px
  KEY: TNtuple	ntuple;2	Demo ntuple [current cycle]
  KEY: TNtuple	ntuple;1	Demo ntuple [backup cycle]

where ntuple;1; has 1891734 entries and ntuple;2 has/points-to the exact same 1891734 entries plus an addition 608266 entries for a total of 2500000 entries.

In this case if one were to use both ntuple;1 and ntuple;2, you would be use the first 1891734 entries twice most likely rendering the result wrong.

Unless you are doing something unusual, you should ignore the lowest cycles.

If you are doing something unusual you have to weight the advantage you found in doing so with the fact that the automatic tools will be not recognized this unusual situation and ignore the lowest cycles (which contains usually duplicated/redundant information).