How to get the data for only one branch

Hello,

here is a code i write as a noob at root :

TFile f("RAW148OS_treeFF01.root");
std::unique_ptr<TTree> tv__tree(static_cast<TTree*>(f.Get("Analysis_All")));
tv__tree->Draw("Psd_All_Shift>>h1(8000,0,8000)","","colz");
TH1 *h1 = (TH1F*)gPad->GetPrimitive("h1"); 

    
    
int nbins = h1->GetNbinsX();
int nevent = 2;
for (int j = 1; j<= nevent; ++j) {
    tv__tree->GetEntry(j);
    tv__tree->Show(j);
    for (int i = 1; i <= nbins; ++i) {
            double binContent = h1->GetBinContent(i);
            // Faites quelque chose avec le contenu du bin, par exemple, l’afficher
            std::cout << "Contenu du bin " << i << " : " << binContent << std::endl;
        }
    }

I’m kinda stuck here, i would like this code to navigate in one particuliar branch, let’s assume (“Psd_All_Shift”) , and get every values of it for each event. I have no idea about how to do that in C++.

Could you help me ? I’ll be thanksfull.

Dear @KillianUB ,

Thanks for your question. I believe this is very similar to another question you posted. You have the exact answer on our manual, precisely here.

Cheers,
Vincenzo

Hello, I tried this ;

TFile f{"RAW148OS_treeFF01.root"};
auto tree = myFile->Get<TTree>("Analysis_All");   
std::unique_ptr<TFile> myFile(TFile::Open("RAW148OS_treeFF01.root", "READ"));


int variable;
tree->SetBranchAddress("Fragment_Velocity", &variable);

for (int iEntry = 0; tree->LoadTree(iEntry) >= 0; ++iEntry) {
   // Load the data for the given tree entry
   tree->GetEntry(iEntry);

   // Now, `variable` is set to the value of the branch
   // "branchName" in tree entry `iEntry`
   std::cout << variable << std::endl;
}

But it only returns me 0. I don’t really undesratnd why ?

Dear @KillianUB ,

Why are you opening the file twice with two different variable names? Also, line 2 is referencing the myFile variable which is only declared on line 3, that code will not compile.

std::unique_ptr<TFile> myFile(TFile::Open("RAW148OS_treeFF01.root", "READ"));
auto tree = myFile->Get<TTree>("Analysis_All");   


int variable;
tree->SetBranchAddress("Fragment_Velocity", &variable);

for (int iEntry = 0; tree->LoadTree(iEntry) >= 0; ++iEntry) {
   // Load the data for the given tree entry
   tree->GetEntry(iEntry);

   // Now, `variable` is set to the value of the branch
   // "branchName" in tree entry `iEntry`
   std::cout << variable << std::endl;
}

Is it better now ?

Dear @KillianUB ,

Yes that looks better. If you are still seeing only zeroes, are you sure the Fragment_Velocity branch contains elements of type int? Since you are storing them into the int variable.

Thanks ! It’s better now, but now I don’t understand the result :

std::unique_ptr<TFile> myFile( TFile::Open("RAW148OS_treeFF01.root") );
auto tree = myFile->Get<TTree>("Analysis_All");
UShort_t variable;
tree->SetBranchAddress("PsdNdRShift", &variable);

for (int iEntry = 0; tree->LoadTree(iEntry) >= 0; ++iEntry) {
   tree->GetEntry(iEntry);
   std::cout << "Entrée " << iEntry << ": " << variable << std::endl;
}

And since UShort_s is senced to get me array, why does the value printed is 0 and not an array ?
The array should represent my number of bins ( if it was on a hist ) so it should be an array full of 0 exepted for 1 to 34 bins wish are the number of my detectors. Of course, all the detctor will not detecte the sale event so there should have 1,2,3 or 4 1 per array .I’m strarting thinking it is not possible to get what i want without getting a hist per entry.

Dear @KillianUB ,

I will repeat the same question. Are you sure the PsdNdRShift from your tree actually contains UShort_t data? Keep in mind that you cannot in general read data of type A into data of type B, and this is true for any programming language and any programming tool (unless of course you or somebody else provided some conversion machinery).

Please, study your dataset schema before going forward with any operation. You have many ways to do this, for example you can TTree::Print or even ask your supervisor about it.

Cheers,
Vincenzo

Ok, i decided first to disable all my Branchs exepeted one, Psd_All_Shift wish is an histogram of my gammas/neutrons detected in fonction of Psd. So now that I only have the Branch I want, i could have scan it :

image

image

ANT THAT !! IS EXACLTY WHAT IM LOOKING FOR !!!
The left column is my event number, the middle one is the number of my detector, the rigth one is the bin number on the event if it detcted, obviously 0 if not !
On this pic, you can see that for the event number 2289, a gamma with an energy of 2018 x gain has been detected by the detctor number 27.

Now i need to exatract those data.
Update, I know now that my data are ROOT::VecOps::RVec<UShort_t>
I’ve seen already ROOT: ROOT::VecOps::RVec< T > Class Template Reference but i would like some help becaus there is a lot of possibility and i’m a bit lost.

Dear @KillianUB ,

Psd_All_Shift wish is an histogram of my gammas/neutrons detected in fonction of Psd

Are you sure that branch contains an histogram, as in something like TH1? I really doubt it. Again, you can check the data types contained in the branches of your tree via TTree::Print

So now that I only have the Branch I want, i could have scan it

You can use TTree::Scan on as many branches as you want, you don’t need to disable any branch beforehand.

On this pic, you can see that for the event number 2289, a gamma with an energy of 2018 x gain has been detected by the detctor number 27.

Great, now you know that your branches contain arrays with multiple values at each event.

Update, I know now that my data are ROOT::VecOps::RVec<UShort_t>

Good! Now you can use the same code as How to get the data for only one branch - #5 by KillianUB . Instead of declaring an int variable, declare a ROOT::VecOps::RVec<UShort_t>.

Cheers,
Vincenzo

Thanks for your answer, so here’s my code for now ;

TFile f{"RAW148OS_treeFF01.root"};
std::unique_ptr<TTree>tree{static_cast<TTree*>(f.Get("Analysis_All"))};
ROOT::EnableImplicitMT(); // Enable ROOT's implicit multi-threading
ROOT::RDataFrame d("Analysis_All", "RAW148OS_treeFF01.root"); // Interface to TTree and TChain
ROOT::VecOps::RVec<UShort_t> variable;
tree->SetBranchAddress("Psd_All_Shift", &variable);

for (int iEntry = 0; tree->LoadTree(iEntry) >= 0; ++iEntry) {  
   tree->GetEntry(iEntry);
   std::cout << variable << std::endl;
}

But it returns me that ;
image

I would have expect something inside.

Dear @KillianUB ,

You need to read into the address of a pointer. I am surprised you don’t get this error as this should have been detected by the application. Anyway, this is a simple example that I hope will clarify

void test_tree()
{
    // Write
    {
        TFile f{"myfile.root","recreate"};
        TTree t{"mytree","mytree"};
        ROOT::VecOps::RVec<UShort_t> rvec{1,2,3,4};
        t.Branch("rvec", &rvec);
        t.Fill();
        f.Write();
    }

    // Read
    {
        TFile f{"myfile.root"};
        std::unique_ptr<TTree> t{f.Get<TTree>("mytree")};
        ROOT::VecOps::RVec<UShort_t> *rvec{nullptr};
        t->SetBranchAddress("rvec", &rvec);
        t->GetEntry(0);
        std::cout << *rvec << "\n";
    }
}

Note that a similar example is available as a tutorial ROOT: tutorials/tree/hvector.C File Reference

Also, let me stress once again the fact that none of this is really necessary if you use RDataFrame. There are simpler ways to achieve what you are trying to do.

Cheers,
Vincenzo

{
	TFile f{"TEST.root","recreate"};
    TTree t{"mytree","mytree"};
    ROOT::VecOps::RVec<UShort_t> rvec{1,2,3,4};
    t.Branch("rvec", &rvec);
    t.Fill();
    f.Write();
}
{
    TFile f{"TEST.root"};
    std::unique_ptr<TTree> t{f.Get<TTree>("mytree")};
    ROOT::VecOps::RVec<UShort_t> *rvec{nullptr};
    t->SetBranchAddress("rvec", &rvec);
    t->GetEntry(0);
    std::cout << *rvec << "\n";
}

Ok i can understand we are here creating a new tree with the branch rvec. And now should i fill this branch with my Psd values ?

Dear @KillianUB ,

That’s just an example to give you inspiration. You can practically use the reading section of the example almost exactly the same for your file. Clearly the first part is just meant to demonstrate a simple writing of a TTree.

Error in TTree::SetBranchAddress: The pointer type given “ROOT::VecOps::RVec” does not correspond to the type needed “UShort_t” (12) by the branch: Psd_All_Shift

I don’t really get it. ROOT told me it was VecOps… and now he said it dosnt fit with my branch.

I tried this,

TFile f{"RAW148OS_treeFF01.root"};
std::unique_ptr<TTree> t{f.Get<TTree>("Analysis_All")};
UShort_t *rvec{nullptr};
t->SetBranchAddress("Psd_All_Shift", &rvec); // Nom de la branche corrigé
int nEntries = t->GetEntries();
for (int iEntry = 0; iEntry < nEntries; ++iEntry) {
    t->GetEntry(iEntry);
    if (rvec) {
        std::cout << *rvec << std::endl;
    } else {
        std::cerr << "Error: rvec is null" << std::endl;
    }
}

But it start then crash so I don’t know.

Dear @KillianUB ,

Have you tried checking the real types contained in the tree via TTree::Print as I suggested? What is the output?

Cheers,
Vincenzo

Here is the output;

image

I tried this at first but it don’t give ME any usefull informations, am I missing somthing ?
I tried this to ;

root [15] auto colType = d.GetColumnType("Psd_All_Shift");
root [16] //Print column type
root [17] std::cout << "Column " << colType << " has type " << colType << std::endl;
Column ROOT::VecOps::RVec<UShort_t> has type ROOT::VecOps::RVec<UShort_t>
TFile f("RAW148OS_treeFF01.root");
std::unique_ptr<TTree> tree(dynamic_cast<TTree*>(f.Get("Analysis_All")));
ROOT::EnableImplicitMT(); // Enable ROOT's implicit multi-threading
ROOT::RDataFrame d("Analysis_All", "RAW148OS_treeFF01.root"); // Interface to TTree and TChain

// Obtention d'un vecteur de données à partir de l'élément "Psd_All_Shift" de l'arbre
auto rvec = d.Take<ROOT::RVec<UShort_t>>("Psd_All_Shift");
// Affichage des valeurs de rvec
for (const auto& value : rvec) {
    std::cout << value << std::endl;
}

I’ve tried this, it returns me that ;

wish is super close of what i’m looking for, but those value ? I don’t know what is this bu it dosnt fit with TTree::Scan(“Psd_All_Shift”)

Hello,

Did you stop responding because you don’t see any solutions?

Sincerely.

Dear @KillianUB ,

I was giving you some time to analyse the situation better. Just by looking at your latest snippet, I can see the following misconceptions

  1. You are yet again opening the TFile and creating a unique_ptr to the tree on lines 1,2 even though on line 4 you create an RDataFrame. Effectively, the first two lines are useless.
  2. On line 3 you are activating the implicit multithreading capabilities of ROOT. Be aware that this does not guarantee the order of extraction of events, thus you might see results that you would not expect otherwise, especially in the case of using Take as you are doing.
  3. The printed result is exactly what you ask for. You asked to take the entire column Psd_All_Shift, then in the for loop you are printing each ROOT::RVec one at a time. Every RVec represents the elements of that column for that event. Thus, this is exactly what TTree::Scan is showing you as you reported in this other post How to get the data for only one branch - #10 by KillianUB

What else do you need exactly?

Cheers,
Vincenzo