/*
* Delphes: a framework for fast simulation of a generic collider experiment
* Copyright (C) 2012-2014 Universite catholique de Louvain (UCL), Belgium
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
/** \class DelphesSTDHEPReader
*
* Reads STDHEP file
*
*
* $Date$
* $Revision$
*
*
* \author P. Demin - UCL, Louvain-la-Neuve
*
*/
#include "classes/DelphesSTDHEPReader.h"
#include
#include
#include
#include
#include
#include
#include
#include "TObjArray.h"
#include "TStopwatch.h"
#include "TDatabasePDG.h"
#include "TParticlePDG.h"
#include "TLorentzVector.h"
#include "classes/DelphesClasses.h"
#include "classes/DelphesFactory.h"
#include "ExRootAnalysis/ExRootTreeBranch.h"
using namespace std;
static const int kBufferSize = 1000000;
//---------------------------------------------------------------------------
DelphesSTDHEPReader::DelphesSTDHEPReader() :
fInputFile(0), fInputXDR(0), fBuffer(0), fPDG(0), fBlockType(-1)
{
fInputXDR = new XDR;
fBuffer = new char[kBufferSize*96 + 24];
fPDG = TDatabasePDG::Instance();
}
//---------------------------------------------------------------------------
DelphesSTDHEPReader::~DelphesSTDHEPReader()
{
if(fBuffer) delete fBuffer;
if(fInputXDR) delete fInputXDR;
}
//---------------------------------------------------------------------------
void DelphesSTDHEPReader::SetInputFile(FILE *inputFile)
{
fInputFile = inputFile;
xdrstdio_create(fInputXDR, inputFile, XDR_DECODE);
ReadFileHeader();
}
//---------------------------------------------------------------------------
void DelphesSTDHEPReader::Clear()
{
fBlockType = -1;
}
//---------------------------------------------------------------------------
bool DelphesSTDHEPReader::EventReady()
{
return (fBlockType == MCFIO_STDHEP) || (fBlockType == MCFIO_STDHEP4);
}
//---------------------------------------------------------------------------
bool DelphesSTDHEPReader::ReadBlock(DelphesFactory *factory,
TObjArray *allParticleOutputArray,
TObjArray *stableParticleOutputArray,
TObjArray *partonOutputArray)
{
if(feof(fInputFile)) return kFALSE;
xdr_int(fInputXDR, &fBlockType);
SkipBytes(4);
if(fBlockType == EVENTTABLE)
{
ReadEventTable();
}
else if(fBlockType == EVENTHEADER)
{
ReadEventHeader();
}
else if(fBlockType == MCFIO_STDHEPBEG ||
fBlockType == MCFIO_STDHEPEND)
{
ReadSTDCM1();
}
else if(fBlockType == MCFIO_STDHEP)
{
ReadSTDHEP();
AnalyzeParticles(factory, allParticleOutputArray,
stableParticleOutputArray, partonOutputArray);
}
else if(fBlockType == MCFIO_STDHEP4)
{
ReadSTDHEP();
AnalyzeParticles(factory, allParticleOutputArray,
stableParticleOutputArray, partonOutputArray);
ReadSTDHEP4();
}
else
{
throw runtime_error("Unsupported block type.");
}
return kTRUE;
}
//---------------------------------------------------------------------------
void DelphesSTDHEPReader::SkipBytes(u_int size)
{
int rc;
u_int rndup;
rndup = size % 4;
if(rndup > 0)
{
rndup = 4 - rndup;
}
rc = fseek(fInputFile, size + rndup, SEEK_CUR);
if(rc != 0 && errno == ESPIPE)
{
xdr_opaque(fInputXDR, fBuffer, size);
}
}
//---------------------------------------------------------------------------
void DelphesSTDHEPReader::SkipArray(u_int elsize)
{
u_int size;
xdr_u_int(fInputXDR, &size);
SkipBytes(size*elsize);
}
//---------------------------------------------------------------------------
void DelphesSTDHEPReader::ReadFileHeader()
{
u_int i;
enum STDHEPVersion {UNKNOWN, V1, V2, V21} version;
xdr_int(fInputXDR, &fBlockType);
if (fBlockType != FILEHEADER)
{
throw runtime_error("Header block not found. File is probably corrupted.");
}
SkipBytes(4);
// version
xdr_string(fInputXDR, &fBuffer, 100);
if(fBuffer[0] == '\0' || fBuffer[1] == '\0') version = UNKNOWN;
else if(fBuffer[0] == '1') version = V1;
else if(strncmp(fBuffer, "2.01", 4) == 0) version = V21;
else if(fBuffer[0] == '2') version = V2;
else version = UNKNOWN;
if(version == UNKNOWN)
{
throw runtime_error("Unknown file format version.");
}
SkipArray(1);
SkipArray(1);
SkipArray(1);
if(version == V21)
{
SkipArray(1);
}
// Expected number of events
SkipBytes(4);
// Number of events
xdr_u_int(fInputXDR, &fEntries);
SkipBytes(8);
// Number of blocks
u_int nBlocks = 0;
xdr_u_int(fInputXDR, &nBlocks);
// Number of NTuples
u_int nNTuples = 0;
if(version != V1)
{
xdr_u_int(fInputXDR, &nNTuples);
}
if(nNTuples != 0)
{
throw runtime_error("Files containing n-tuples are not supported.");
}
// Processing blocks extraction
if(nBlocks != 0)
{
SkipArray(4);
for(i = 0; i < nBlocks; i++)
{
SkipArray(1);
}
}
}
//---------------------------------------------------------------------------
void DelphesSTDHEPReader::ReadEventTable()
{
// version
xdr_string(fInputXDR, &fBuffer, 100);
if(strncmp(fBuffer, "1.00", 4) == 0)
{
SkipBytes(8);
SkipArray(4);
SkipArray(4);
SkipArray(4);
SkipArray(4);
SkipArray(4);
}
else if(strncmp(fBuffer, "2.00", 4) == 0)
{
SkipBytes(12);
SkipArray(4);
SkipArray(4);
SkipArray(4);
SkipArray(4);
SkipArray(8);
}
}
//---------------------------------------------------------------------------
void DelphesSTDHEPReader::ReadEventHeader()
{
bool skipNTuples = false;
u_int skipSize = 4;
// version
xdr_string(fInputXDR, &fBuffer, 100);
if(strncmp(fBuffer, "2.00", 4) == 0)
{
skipNTuples = true;
}
else if(strncmp(fBuffer, "3.00", 4) == 0)
{
skipNTuples = true;
skipSize = 8;
}
SkipBytes(20);
u_int dimBlocks = 0;
xdr_u_int(fInputXDR, &dimBlocks);
u_int dimNTuples = 0;
if(skipNTuples)
{
SkipBytes(4);
xdr_u_int(fInputXDR, &dimNTuples);
}
// Processing blocks extraction
if(dimBlocks > 0)
{
SkipArray(4);
SkipArray(skipSize);
}
// Processing blocks extraction
if(skipNTuples && dimNTuples > 0)
{
SkipArray(4);
SkipArray(skipSize);
}
}
//---------------------------------------------------------------------------
void DelphesSTDHEPReader::ReadSTDCM1()
{
// version
xdr_string(fInputXDR, &fBuffer, 100);
// skip 5*4 + 2*8 = 36 bytes
SkipBytes(36);
if((strncmp(fBuffer, "1.", 2) == 0) || (strncmp(fBuffer, "2.", 2) == 0) ||
(strncmp(fBuffer, "3.", 2) == 0) || (strncmp(fBuffer, "4.", 2) == 0) ||
(strncmp(fBuffer, "5.00", 4) == 0))
{
return;
}
SkipArray(1);
SkipArray(1);
if(strncmp(fBuffer, "5.01", 4) == 0)
{
return;
}
SkipBytes(4);
}
//---------------------------------------------------------------------------
void DelphesSTDHEPReader::ReadSTDHEP()
{
u_int idhepSize, isthepSize, jmohepSize, jdahepSize, phepSize, vhepSize;
// version
xdr_string(fInputXDR, &fBuffer, 100);
// Extracting the event number
xdr_int(fInputXDR, &fEventNumber);
// Extracting the number of particles
xdr_int(fInputXDR, &fEventSize);
if(fEventSize >= kBufferSize)
{
throw runtime_error("too many particles in event");
}
// 4*n + 4*n + 8*n + 8*n + 40*n + 32*n +
// 4 + 4 + 4 + 4 + 4 + 4 = 96*n + 24
xdr_opaque(fInputXDR, fBuffer, 96*fEventSize + 24);
idhepSize = ntohl(*(u_int*)(fBuffer));
isthepSize = ntohl(*(u_int*)(fBuffer + 4*1 + 4*1*fEventSize));
jmohepSize = ntohl(*(u_int*)(fBuffer + 4*2 + 4*2*fEventSize));
jdahepSize = ntohl(*(u_int*)(fBuffer + 4*3 + 4*4*fEventSize));
phepSize = ntohl(*(u_int*)(fBuffer + 4*4 + 4*6*fEventSize));
vhepSize = ntohl(*(u_int*)(fBuffer + 4*5 + 4*16*fEventSize));
if(fEventSize < 0 ||
fEventSize != (int)idhepSize || fEventSize != (int)isthepSize ||
(2*fEventSize) != (int)jmohepSize || (2*fEventSize) != (int)jdahepSize ||
(5*fEventSize) != (int)phepSize || (4*fEventSize) != (int)vhepSize)
{
throw runtime_error("Inconsistent size of arrays. File is probably corrupted.");
}
fWeight = 1.0;
fAlphaQED = 0.0;
fAlphaQCD = 0.0;
fScaleSize = 0;
memset(fScale, 0, 10*sizeof(double));
}
//---------------------------------------------------------------------------
void DelphesSTDHEPReader::ReadSTDHEP4()
{
u_int number;
// version
xdr_string(fInputXDR, &fBuffer, 100);
// Extracting the event weight
xdr_double(fInputXDR, &fWeight);
// Extracting alpha QED
xdr_double(fInputXDR, &fAlphaQED);
// Extracting alpha QCD
xdr_double(fInputXDR, &fAlphaQCD);
// Extracting the event scale
xdr_u_int(fInputXDR, &fScaleSize);
for(number = 0; number < fScaleSize; ++number)
{
xdr_double(fInputXDR, &fScale[number]);
}
SkipArray(8);
SkipArray(4);
SkipBytes(4);
}
//---------------------------------------------------------------------------
void DelphesSTDHEPReader::AnalyzeEvent(ExRootTreeBranch *branch, long long eventNumber,
TStopwatch *readStopWatch, TStopwatch *procStopWatch)
{
LHEFEvent *element;
element = static_cast(branch->NewEntry());
element->Number = fEventNumber;
element->ProcessID = 0;
element->Weight = fWeight;
element->ScalePDF = fScale[0];
element->AlphaQED = fAlphaQED;
element->AlphaQCD = fAlphaQCD;
element->ReadTime = readStopWatch->RealTime();
element->ProcTime = procStopWatch->RealTime();
}
//---------------------------------------------------------------------------
void DelphesSTDHEPReader::AnalyzeParticles(DelphesFactory *factory,
TObjArray *allParticleOutputArray,
TObjArray *stableParticleOutputArray,
TObjArray *partonOutputArray)
{
Candidate *candidate;
TParticlePDG *pdgParticle;
int pdgCode;
int number;
int pid, status, m1, m2, d1, d2;
double px, py, pz, e, mass;
double x, y, z, t;
XDR bufferXDR[6];
xdrmem_create(&bufferXDR[0], fBuffer + 4*1, 4*fEventSize, XDR_DECODE);
xdrmem_create(&bufferXDR[1], fBuffer + 4*2 + 4*1*fEventSize, 4*fEventSize, XDR_DECODE);
xdrmem_create(&bufferXDR[2], fBuffer + 4*3 + 4*2*fEventSize, 8*fEventSize, XDR_DECODE);
xdrmem_create(&bufferXDR[3], fBuffer + 4*4 + 4*4*fEventSize, 8*fEventSize, XDR_DECODE);
xdrmem_create(&bufferXDR[4], fBuffer + 4*5 + 4*6*fEventSize, 40*fEventSize, XDR_DECODE);
xdrmem_create(&bufferXDR[5], fBuffer + 4*6 + 4*16*fEventSize, 32*fEventSize, XDR_DECODE);
for(number = 0; number < fEventSize; ++number)
{
xdr_int(&bufferXDR[0], &status);
xdr_int(&bufferXDR[1], &pid);
xdr_int(&bufferXDR[2], &m1);
xdr_int(&bufferXDR[2], &m2);
xdr_int(&bufferXDR[3], &d1);
xdr_int(&bufferXDR[3], &d2);
xdr_double(&bufferXDR[4], &px);
xdr_double(&bufferXDR[4], &py);
xdr_double(&bufferXDR[4], &pz);
xdr_double(&bufferXDR[4], &e);
xdr_double(&bufferXDR[4], &mass);
xdr_double(&bufferXDR[5], &x);
xdr_double(&bufferXDR[5], &y);
xdr_double(&bufferXDR[5], &z);
xdr_double(&bufferXDR[5], &t);
candidate = factory->NewCandidate();
candidate->PID = pid;
pdgCode = TMath::Abs(candidate->PID);
candidate->Status = status;
candidate->M1 = m1 - 1;
candidate->M2 = m2 - 1;
candidate->D1 = d1 - 1;
candidate->D2 = d2 - 1;
pdgParticle = fPDG->GetParticle(pid);
candidate->Charge = pdgParticle ? int(pdgParticle->Charge()/3.0) : -999;
candidate->Mass = mass;
candidate->Momentum.SetPxPyPzE(px, py, pz, e);
candidate->Position.SetXYZT(x, y, z, t);
allParticleOutputArray->Add(candidate);
if(!pdgParticle) continue;
if(status == 1 && pdgParticle->Stable())
{
stableParticleOutputArray->Add(candidate);
}
else if(pdgCode <= 5 || pdgCode == 21 || pdgCode == 15)
{
partonOutputArray->Add(candidate);
}
}
}
//---------------------------------------------------------------------------