Hello,
I am writing a C++ program that reads in an ASCII file containing the output of a micro black hole simulation run under the program BlackMax (projects.hepforge.org/blackmax/) and stores it as a TTree within a root TFile.
A simplified version ot the tree would be as follows:
Tree Name: BlackMaxData
-Branch: Event_
–Leaf: fEvent_Number (Integer) – Identifies black hole to which a particle belongs.
–Leaf: fNumber_Particles (Integer) – Identifies the number of particles produced by each event/black hole.
–Leaf: fPbhMass (Float) – Mass of the black hole determined from the black holes momentum.
–Sub-branch: fParticle – Contains information on the individual particles emitted per event/black hole.
—Leaf: fType (String) – Type of particle (Parent: Particle that produces bh; —Leaf: fPDGid (Integer) – Particle type using the Particle Data Group Naming system
—Leaf: fColor_Charge[3] (Integer Array) – Colour charge of the particle.
—Leaf: fEnergy_Momentum (Pointer toFloat Array) – Energy-Momentum vector of the particle.
—Leaf: fEPArraySize (Integer) – Magnitude of the fEnergy_Momentum array consisting of at least 4 components (1 Energy + 3 Momentum: Px, Py, Pz) Plus optional additional dimentions.
The details of the above listed structure are not relevant, but merely provided to give context to my problem and code.
My code succeeds in transferring the data from the ASCII format input file to the above described TTree, but creates surplice entries within the fParticle branch. I suspect this is due to my inability to correctly use/write the class destructor that corresponds to the Particle class I have written to describe the structure of this sub-branch. I have tried to synthesize the program as much as possible whilst having it remain fully operational so as to post it here.
I have provides an example of the input file the program reads, it is counter intuitively named “output.txt” as that is how the files are named when generate by BlackMax. The sample file contains 5 events and 61 particles. My code however creates a tree with 5 entries within “Event_”, but 68 entries within “fParticle”.
Any help would be appreciated as there is nobody at my university department with sufficient knowledge of root to help me resolve this issue.
Thank you in advance,
Aitzol Casado
//Event.h////////////////////////////////////////////////////////////
#ifndef Event_H
#define Event_H
#include <fstream>
#include <cstring>
#include <TObject.h>
#include <TTree.h>
#include <TClonesArray.h>
using namespace std;
//Particle
class Particle : public TObject{
private :
string fType;
Int_t fPDGid;
Int_t fColor_Charge[3];
Int_t fEPArraySize;
Double_t *fEnergy_Momentum; // [fEPArraySize]
public:
Particle();
Particle(Int_t, ifstream &, string, Double_t &);
virtual ~Particle();
void ParentBuild(ifstream &);
void PbhBuild(Int_t, ifstream &, Double_t &);
void PemBuild(Int_t, ifstream &);
void ElastBuild(ifstream &);
ClassDef(Particle,1)
};
//Event
class Event : public TObject{
private :
Int_t fEvent_Number;
Int_t fNumber_Particles;
Double_t fPbhMass;
TClonesArray *fParticle;
static TClonesArray *fgParticles;
public:
Event();
virtual ~Event();
void Build(Int_t, TTree *, ifstream &);
ClassDef(Event,1)
};
#endif
//Event.cc///////////////////////////////////////////////////////////
#include <TObject.h>
#include <TTree.h>
#include <iostream>
#include <fstream>
#include <cstring>
#include <cmath>
#include "Event.h"
ClassImp(Particle)
ClassImp(Event)
TClonesArray *Event::fgParticles = 0;
using namespace std;
// Particle
Particle::Particle()
{
fType = "";
fPDGid = 0;
for(int i=0; i<3; i++){
fColor_Charge[i] = 0;
}
fEnergy_Momentum = NULL;
}
Particle::Particle(Int_t EPArraySize, ifstream &in, string inType, Double_t &fPbhMass) : TObject()
{
if(inType == "Pbh"){
PbhBuild(EPArraySize, in, fPbhMass);
}else if(inType == "Parent"){
ParentBuild(in);
}else if(inType == "Pem"){
PemBuild(EPArraySize, in);
}else if(inType == "Elast"){
ElastBuild(in);
}
}
Particle::~Particle(){
delete [] fEnergy_Momentum;
fEnergy_Momentum=0;
printf(" Particle REPORT: Class Destructor Called\n");
}
void Particle::ParentBuild(ifstream & in)
{
fEPArraySize = 4;
fEnergy_Momentum = new Double_t[fEPArraySize];
fType = "Parent";
in >> fPDGid;
for(int i=0; i<3; i++){
in >> fColor_Charge[i];
}
for(int i=0; i<fEPArraySize; i++){
in >> fEnergy_Momentum[i];
}
}
void Particle::PbhBuild(Int_t EPArraySize, ifstream & in, Double_t & fPbhMass)
{
fEPArraySize = EPArraySize+1;
fEnergy_Momentum = new Double_t[fEPArraySize];
fType = "Pbh";
in >> fPDGid;
for(int i=0; i<3; i++){
in >> fColor_Charge[i];
}
for(int i=0; i<fEPArraySize; i++){
in >> fEnergy_Momentum[i];
if(i==0){
fPbhMass = fEnergy_Momentum[i]*fEnergy_Momentum[i];
}else{
fPbhMass-= fEnergy_Momentum[i]*fEnergy_Momentum[i];
}
}
cout << " Particle REPORT: Event Black Hole Mass^2:" << fPbhMass << endl;
fPbhMass = sqrt(fPbhMass);
cout << " Particle REPORT: Event Black Hole Mass :" << fPbhMass << endl;
}
void Particle::PemBuild(Int_t EPArraySize, ifstream & in)
{
fEPArraySize = EPArraySize;
fEnergy_Momentum = new Double_t[fEPArraySize];
fType = "Pem";
in >> fPDGid;
for(int i=0; i<3; i++){
in >> fColor_Charge[i];
}
cout << " Particle REPORT: Pem, fEnergy_Momentum =";
for(int i=0; i<fEPArraySize; i++){
in >> fEnergy_Momentum[i];
cout << " " << fEnergy_Momentum[i];
}
cout << endl;
}
void Particle::ElastBuild(ifstream & in)
{
fEPArraySize = 4;
fEnergy_Momentum = new Double_t[fEPArraySize];
fType = "Elast";
in >> fPDGid;
for(int i=0; i<3; i++){
in >> fColor_Charge[i];
}
cout << " Particle REPORT: Elast, fEnergy_Momentum =";
for(int i=0; i<fEPArraySize; i++){
in >> fEnergy_Momentum[i];
cout << " " << fEnergy_Momentum[i];
}
cout << endl;
}
// Event
Event::Event()
{
fEvent_Number = 0;
fNumber_Particles = 0;
if (!fgParticles) fgParticles = new TClonesArray("Particle", 1000);
fParticle = fgParticles;
}
Event::~Event(){
printf(" Event REPORT: Class Destructor Called\n");
}
void Event::Build(Int_t EPArraySize, TTree *tree, ifstream & in)
{
cout << " \n******************************************************************************\n";
cout << " Event REPORT: Event.Build(Int_t EPArraySize, TTree *tree, ifstream & in) Initiated, Event #";
string inType; in >> inType;
Int_t inEvntNmbr; in >> inEvntNmbr;
Int_t oldEvntNmbr = inEvntNmbr;
Particle *particle = 0;
cout << inEvntNmbr << endl;
while(oldEvntNmbr==inEvntNmbr && in.good()){
TClonesArray &particles = *fParticle; // &particles is the list of all particles in "THIS" event
particle = new(particles[fNumber_Particles++]) Particle(EPArraySize, in, inType, fPbhMass);
in >> inType;
in >> inEvntNmbr;
}
fEvent_Number = oldEvntNmbr;
for(int i=0; i<14; i++){in.unget();}
cout << " Event REPORT: Event contains the folowing number of particles:" << fNumber_Particles << endl;
cout << " Event REPORT: Event.Build(Int_t EPArraySize, TTree *tree, ifstream & in) Finished" << endl;
}
//treeGen.cc/////////////////////////////////////////////////////////
#include <iostream>
#include <fstream>
#include <cstring>
#include <TFile.h>
#include <TTree.h>
#include "Event.h"
#include "treeGenFunctions.h"
using namespace std;
int main(){
printBanner();
char fileName[]="bmData.root", treeName[]="BlackMaxData", branchName[]="Event_", dataName[]="output.txt";
//Generating File
TFile * file = TFile::Open(fileName, "RECREATE", "A BlackMax simulation File"); //chopo look at TFile Open
cout << " fileGen REPORT: File \"" << fileName << "\" created" << endl;
TTree * tree= new TTree(treeName,"A BlackMax simulation TTree");
cout << " fileGen REPORT: Tree \"" << treeName << "\" created" << endl;
Event * event=0;
Int_t bsize = 64000;
tree->Branch(branchName, "Event", &event, bsize, 2);
cout << " fileGen REPORT: Branch \"" << branchName << "\" created" << endl;
//This data is includes and estracted from "output.txt" in the full version
Int_t numberSimulations = 5;
Int_t EPArraySize = 5; // 1 Energy + 3 Momentum (Px, Py, Pz) + 1 Extra dimention
//Accesing BM Data
cout << " fileGen REPORT: Accessing \"" << dataName << "\" data" << endl;
ifstream bmInput;
bmInput.open(dataName);
for(Int_t i=0; i<numberSimulations && bmInput.good(); i++){
event = new Event();
event->Build(EPArraySize, tree, bmInput);
tree->Fill();
}
cout << "\n******************************************************************************\n";
cout << " fileGen REPORT: Finished populating \"" << branchName << "\" branch" << endl;
cout << " fileGen REPORT: Finished populating \"" << treeName << "\" tree" << endl;
bmInput.close();
cout << "\n******************************************************************************\n\n";
file->Write();
cout << " fileGen REPORT: Finished writing to \"" << fileName << "\" file" << endl;
file->Close();
cout << " fileGen REPORT: \"" << fileName << "\" Closed" << endl;
cout << " fileGen REPORT: job Done!\n" << endl;
return 0;
}
output.txt (5.58 KB)
treeGen.c (1.96 KB)
Event.c (3.89 KB)
Event.h (1.07 KB)