Home | News | Documentation | Download

Wrong Special Characters in ROOT file

You need to inspect how you define the “MC_out” tree, in particular its “ptype” and “volumeName” branches.

Try to run “MC_out->MakeClass();” and then see the “MC_out.h” file. You will find "Char_t ptype[5]; and Char_t volumeName[5];, which means that your names can be 4 characters long at most (plus the null character which ends the string, of course, hence at most 5 characters in total).

Moreover, you should also inspect the place where you fill these branches as it seems to me that they use uninitialized variables.

Note also that the “NaI_Scint” in the “G4Tubs” call is actually converted into a “G4String” which is basically a “std:string” (NOT a “char *”).

So, I inspected the way volumeName is filled in my code:
// ================
G4String VolName=aStep->GetPreStepPoint()->GetTouchableHandle()
->GetVolume()->GetName();

myRunAction->SetVolumeName(VolName);
// ============

Just now I used: “G4cout<<VolName<<G4endl;” right after above steps and the VolName is displayed fine on terminal window.

Your “VolName” is a “G4String” (so basically a “C++ std::string”). It is NOT a C character string / sequence / array.

Note: you need to check how you define and fill the branches of your tree, not how you feed geant4.

Thanks! I looked into what you mentioned and here it is:

fData->Branch(“volumeName”,&fvname,“volumeName/C”);

So it’s maybe because of “/C”

Do you recommend any way of handling this when something is expressed in G4 string and we are interested in creating a tree-branch?

And surprisingly this was not the issue on MAC OS!

And “fvname” is what?

Here:

G4String fvname;

Try: fData->Branch("volumeName", &fvname);

After I include what you mentioned, I do not see any branch with name “volumeName”

When I do MC_out->Scan(“ptype:volumeName”), I just see an empty volumeName column!

And how do you set the “fvname” value (before you fill the tree)?

inline void SetVolumeName(G4String daname){fvname=daname;}

Try to use: std::string fvname;
And if after this change your compiler complains, use: {fvname=daname.data();} (or: {fvname=daname.c_str();}).

Here are two things I tried, both gave special characters in the end.:

std::string  fvname;
inline void SetVolumeName(std::string daname){fvname=daname;}

OR
std::string fvname;
inline void SetVolumeName(std::string daname){fvname=daname.c_str();}

Both of these runs gave my special characters! Am i doing something wrong with compilation process or something?

Attach a new small root file.

I assume you use:

std::string fvname;
fData->Branch("volumeName", &fvname);
inline void SetVolumeName(const G4String &daname) { fvname = daname.c_str(); }

It worked actually ; I was messing up somewhere.

Thanks, I appreciate it a lot.

One of the things I noticed, however, is the way volumeName branch is different from the other branches. The data is visible in data() under volumeName.

My goal now is to analyze this root file and determine which events were in that volume (NaI). For example, in my earlier analysis code that worked on MAC OS, I was setting:

#include "string"

Char_t   volumeName[15]; 
TBranch   *b_volumeName;   

fChain->SetBranchAddress("volumeName", volumeName, &b_volumeName);

if(volumeName[3]== 'I'){   // desired events happening in NaI
        // then execute this loop...     
 }  // if loop ends

I now tried updating Char_t volumeName[15] to string *volumeName; volumeName=0; and fChain->SetBranchAddress("volumeName", &volumeName, &b_volumeName); based on what I have seen in MC_out.h but what I should be using to execute something like the if loop above.

Do you have any suggestions?

build.root (9.1 KB)

std::string *volumeName = 0;
MC_out->SetBranchAddress("volumeName", &volumeName);

BTW. For an event loop example, see “MC_out.C”.

Thanks. I tried analyzing my root file and I am able to analyze other branches. For example:

if(pdgNum == 22){
… // Do this
}

The above works fine. However I am not able to access the data of volumeName. In theory I want to implement:

if(volumeName[3] == ‘I’ ){ // Events happening in NaI only
… // Do this
}

When I have two volumes (e.g., NaI, and EJ230), I am interested in events happenign in NaI only by using something like the above if loop.build.root (9.1 KB)

Indices in C / C++ start from 0, not 1 (at least “usually”).

Yes, I am aware of that, you can consider that as my typo in my above comment. I basically cout
volumeName and I get

0x2a3d8e0

which is hindering me in tracking events in the volume I am interested in.

std::string *volumeName = new std::string("NaI");
std::cout << volumeName << std::endl;
std::cout << *volumeName << std::endl;
std::cout << (*volumeName)[2] << std::endl;
std::cout << volumeName->at(2) << std::endl;

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