Reading strings from ntuple

_Geant4 Version:_v11.2.1

Hi all,
I’m having trouble understanding where I’m going wrong with my datasets. The short version is I’m writing to a root file and everything looks good from Geant, but reading from the file produces gibberish (to me). Here are the details:

I define an ntuple in my histomanager by:

G4int id = analysisManager->CreateNtuple("SecondaryParticles","N_0_title");
    analysisManager->CreateNtupleSColumn(id,"name");
    analysisManager->CreateNtupleDColumn(id,"Energy");
    analysisManager->CreateNtupleSColumn(id,"CreatorProcess");
    analysisManager->FinishNtuple(id);
}

and fill it in PreUserTrackingAction():

if(track->GetTrackID() != 1 ){
  
  G4String name = track->GetParticleDefinition()->GetParticleName();
  G4double KE = track->GetKineticEnergy();
  G4String proc = track->GetCreatorProcess()->GetProcessName();
  G4cout<<name<<"| |"<<proc<<"| |"<<KE<<G4endl;

  analysisManager->FillNtupleSColumn(0, 0, name);
  analysisManager->FillNtupleDColumn(0, 1,KE);
  analysisManager->FillNtupleSColumn(0, 2,proc);
  analysisManager->AddNtupleRow(0);
}

The geant print statements look good for a test run:

e-| |e-_G4DNAIonisation| |8.04625e-06

but reading from the root file is completely messed up. Here is the macro and an example output:

void readSecondaries()
{
    TFile *f = TFile::Open("output.root");
    

    TTree *tree = (TTree*)f->Get("SecondaryParticles");

    Char_t *name;
    Char_t *proc;
    double Energy = 0.0;

    tree->SetBranchAddress("name", &name);
    tree->SetBranchAddress("Energy", &Energy);
    tree->SetBranchAddress("CreatorProcess", &proc);

    Long64_t nentries = tree->GetEntries();
    for(Long64_t i=0; i<nentries && i<10; ++i)
    {
        tree->GetEntry(i);
        std::cout<<"Name: "<<name<<std::endl
                 <<"Proc: "<<proc<<std::endl
                 <<"KE  : "<<Energy<<std::endl
                 <<"---------------------------------"<<std::endl
                 <<"---------------------------------"<<std::endl;
    }

    f->Close();
}
root [34] .x readSecondaries.C
Name: include "TNeuron.h"
#include "TSynapse.h"



Proc: @����|
KE  : 0.00237574
---------------------------------
---------------------------------
Name: include "TNeuron.h"
#include "TSynapse.h"



Proc: @����|
KE  : 4.43678e-07
---------------------------------
---------------------------------

has anyone come across this? I am a bit unfamiliar with debugging root scripts so any insight would be helpful.

Thanks!

I think your Char_t pointer is just pointing to random memory. Usually you would preallocate the size and then write directly in the buffer. Far easier is to just use std::string i.e.

std::string *name = nullptr; 
std::string *proc = nullptr;

...

      std::cout << "Name: " << *name << std::endl
                  << "Proc: " << *proc << std::endl
                  << "KE  : " << Energy << std::endl
                  << "---------------------------------" << std::endl;

You can also use a ROOT viewer to make sure the data itself is being saved correctly.

Thank you for taking the time to respond. I originally used std::string and it gave the following output:

Name: 0x651ba6652bf0
Proc: 0x651ba6283340
KE  : 1.18113e-05

or just 0 for Name and Proc if I initialize them to nullptrs.tree->Print() labeled the name and proc as Char_t types so I tried that after. When I look at the TBrowser, it has histograms with expected x values for both (Name shows “e-” and Proc shows “compt” and “G4DNAIonisation”).

For the sake of completing this topic: I changed

Char_t *name;
Char_t *proc;

to

Char_t name[100];
Char_t proc[100];

and it now prints correctly:

---------------------------------
Name: e-
Proc: e-_G4DNAIonisation
KE  : 1.18113e-05
---------------------------------

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.