Reading a TString TBranch from a TTree


ROOT Version: 6.18/04
Platform: Ubuntu 18.04
Compiler: gcc 7.5.0 (Ubuntu 7.5.0-3ubuntu1~18.04)


Dear co-rooters,

I’ve got a TTree which has a couple TString TBranches. That’s the Print() from the TTree with the relevant TBranches and a Scan() of the first 5 entries

******************************************************************************
*Tree    :DICER     : A test TTree for DICER                                 *
*Entries :  5563134 : Total =       452144078 bytes  File  Size =  417002919 *
*        :          : Tree compression factor =   1.08                       *
*............................................................................*
*Br    8 :paddle    : TString                                                *
*Entries :  5563134 : Total  Size=   39137774 bytes  File Size  =   39099132 *
*Baskets :     1917 : Basket Size=      32000 bytes  Compression=   1.00     *
*............................................................................*
*Br    9 :beam_blocker : TString                                             *
*Entries :  5563134 : Total  Size=   78223106 bytes  File Size  =   78160020 *
*Baskets :     3138 : Basket Size=      32000 bytes  Compression=   1.00     *
*............................................................................*

************************************************************************************************************************************************************************
*    Row   * ntof.ntof * detn.detn * event_ID. * Q_short.Q * Q_long.Q_ * RunNumber * ntof0.nto *       PSD *    paddle * beam_bloc * baseline. * std_basel *    dt_min *
************************************************************************************************************************************************************************
*        0 * 1890288.6 *       200 *       322 *      2150 *     65535 *     40019 * 1890288.6 * 0.9671931 *        Cd * both_open * 11343.299 * 27.544561 *    -2e+12 *
*        1 * 762.66200 *         5 *        23 *     32767 *       182 *     40019 * 1890288.6 * -179.0384 *        Cd * both_open * 14856.400 * 1.2608654 *    -5e+10 *
*        2 * 846.82607 *         6 *        46 *       107 *       325 *     40019 * 1890288.6 * 0.6707692 *        Cd * both_open * 14938.599 * 0.8239548 *      1000 *
*        3 * 4871.6034 *         4 *        24 *      5003 *     12836 *     40019 * 1890288.6 * 0.6102368 *        Cd * both_open * 14910.900 * 0.0881507 *    -4e+10 *
*        4 * 4876.4667 *         3 *         0 *      9961 *     24830 *     40019 * 1890288.6 * 0.5988320 *        Cd * both_open *     14756 * 0.0367038 * -4.273437 *

I’m trying to read the TString TBranches but I’m having the following issues.

  1. If I declare my parsing variables as TString, I’m able to compile my code.

    TString  paddle, beam_blocker;
    TTree *t      = (TTree*)f_root->Get("DICER");
    t->SetBranchAddress("paddle"      , &paddle);
    t->SetBranchAddress("beam_blocker", &beam_blocker);
    

    However, when I’m executing it, I get the following error

    Error in <TTree::SetBranchAddress>: The address for "paddle" should be the address of a pointer!
    Error in <TTree::SetBranchAddress>: The address for "beam_blocker" should be the address of a pointer!
    
  2. If I declare the parsing variables as pointers, I’m able to successfully compile, but once it reads the first entry, root crashes without any error message apart from “Break segmentation violation”

    TString  *paddle, *beam_blocker;
    TTree *t      = (TTree*)f_root->Get("DICER");
    t->SetBranchAddress("paddle"      , &paddle);
    t->SetBranchAddress("beam_blocker", &beam_blocker);
    
  3. I tried declaring my parsing variable as TString, but when getting the TBRanchAddress I used the GetPointer() function.

    TString  paddle, beam_blocker;
    TTree *t      = (TTree*)f_root->Get("DICER");
    t->SetBranchAddress("paddle"      , paddle.GetPointer() );
    t->SetBranchAddress("beam_blocker", beam_blocker.GetPointer() );
    

    The code compiles, but when I run it, I get the following error

    Error in <TTree::SetBranchAddress>: The pointer type given "Char_t" (1) does not correspond to the type needed "TString" by the branch: paddle
    Error in <TTree::SetBranchAddress>: The pointer type given "Char_t" (1) does not correspond to the type needed "TString" by the branch: beam_blocker
    

Any idea on how to parse the TBranches?

Thanks in advance!

In principle, this should be the right way:

TString *paddle = nullptr;
TString *beam_blocker = nullptr;
TTree *t = (TTree*)f_root->Get("DICER");
if (t) {
   t->SetBranchAddress("paddle"      , &paddle);
   t->SetBranchAddress("beam_blocker", &beam_blocker);
}

[edited to add the required pointer initialization]

TString *paddle = 0, *beam_blocker = 0;

I tried both but I get the same thing

Error in <TTree::SetBranchAddress>: The address for "paddle" should be the address of a pointer!
Error in <TTree::SetBranchAddress>: The address for "beam_blocker" should be the address of a pointer!

I event tried to print the values by using


t->GetEntry(i);
cout << beam_blocker << endl;

But I get 0 values…

Maybe it’s more useful if I post some code and a sample file?

#include "TString.h"
#include "TTree.h"
#include "TFile.h"

#include <iostream>



void reduce_data(TString filename_in){

//_____________________________________________________________________________________________________________________	
//(1) Open the root file and loop over the TTree

	//(a) Variables to read the tree
	UShort_t Q_short, Q_long;
	double   ntof, ntof0, dt_min;
	float    PSD;
	int      detn, RunNumber, event_ID;
	TString  *paddle, *beam_blocker;
	
	//(b) Open the root file and get the TTree
	TFile *f_root;
	f_root = TFile::Open(filename_in);
	
	std::cout << std::endl;
	std::cout << "Reading file " << filename_in << std::endl;
	std::cout << std::endl;
	
	TTree *t      = (TTree*)f_root->Get("DICER");
	
	//(c) Set the branch addresses to read the TBranches
	std::cout << "Reading TTree and TBranches" << std::endl;
	t->SetBranchAddress("PSD"         , &PSD);
	t->SetBranchAddress("detn"        , &detn);
	t->SetBranchAddress("ntof"        , &ntof);
	t->SetBranchAddress("ntof0"       , &ntof0);
	t->SetBranchAddress("dt_min"      , &dt_min);
	t->SetBranchAddress("paddle"      , paddle);
	t->SetBranchAddress("Q_long"      , &Q_long);
	t->SetBranchAddress("Q_short"     , &Q_short);
	t->SetBranchAddress("event_ID"    , &event_ID);
	t->SetBranchAddress("RunNumber"   , &RunNumber);
	t->SetBranchAddress("beam_blocker", beam_blocker);
	
	//(d) Calculate the entries and prepare for the progress bar
	Long64_t entries = t->GetEntries();
	std::cout << "Total entries found: " << entries << std::endl;
	
	
//_____________________________________________________________________________________________________________________
// (2) Loop over the tree

	for (Long64_t i=0; i<20; ++i){
		t->GetEntry(i);
		std::cout << i << ". Paddle = " << paddle << ", beam blocker = " << beam_blocker << std::endl;
		//if (beam_blocker=="Undefined")   continue;	
	}

}

A sample file can be found here

https://cernbox.cern.ch/index.php/s/TtsgHanoyaPb3WP

	TString  *paddle = nullptr, *beam_blocker = nullptr;

and

	t->SetBranchAddress("paddle"      , &paddle);
	t->SetBranchAddress("beam_blocker", &beam_blocker);

I get exactly the same…


Reading TTree and TBranches
Error in <TTree::SetBranchAddress>: The address for "paddle" should be the address of a pointer!
Error in <TTree::SetBranchAddress>: The address for "beam_blocker" should be the address of a pointer!
Total entries found: 5563134
0. Paddle = 0, beam blocker = 0
1. Paddle = 0, beam blocker = 0
2. Paddle = 0, beam blocker = 0
3. Paddle = 0, beam blocker = 0
4. Paddle = 0, beam blocker = 0
5. Paddle = 0, beam blocker = 0
6. Paddle = 0, beam blocker = 0
7. Paddle = 0, beam blocker = 0
8. Paddle = 0, beam blocker = 0
9. Paddle = 0, beam blocker = 0
10. Paddle = 0, beam blocker = 0
11. Paddle = 0, beam blocker = 0
12. Paddle = 0, beam blocker = 0
13. Paddle = 0, beam blocker = 0
14. Paddle = 0, beam blocker = 0
15. Paddle = 0, beam blocker = 0
16. Paddle = 0, beam blocker = 0
17. Paddle = 0, beam blocker = 0
18. Paddle = 0, beam blocker = 0
19. Paddle = 0, beam blocker = 0

Please read carefully my answer, it has been edited

That’s perfect!!! Thanks!!
I guess I can de-reference with *(paddle) to read the actual values and use them in my analysis, right?
Printing seems to work!

(BTW, that was my first answer, despite the fact that I forgot to initialize the values to nullptr)

Also why a TString has to be declared a pointer whereas an int doesn’t have to?

Why? those are pointers, you can just use them as any pointer, e.g. std::cout << paddle->Data() << std::endl;

@pcanal can give more technical details, but for complex data types (classes), a constructor has to be called (with operator new) and then its pointer is returned. Not for simple data types

Duh!
I didn’t think about that! Thanks so much for the help!

You’re very welcome

You are right.
I was mistakenly using strings assuming they’re data types, but actually they’re not.
I’ve to be more careful!