Files
geant4/examples/advanced/HGCal_testbeam/src/PrimaryGeneratorAction.cc
T
2020-12-04 12:30:43 +01:00

231 lines
9.0 KiB
C++

//
// ********************************************************************
// * License and Disclaimer *
// * *
// * The Geant4 software is copyright of the Copyright Holders of *
// * the Geant4 Collaboration. It is provided under the terms and *
// * conditions of the Geant4 Software License, included in the file *
// * LICENSE and available at http://cern.ch/geant4/license . These *
// * include a list of copyright holders. *
// * *
// * Neither the authors of this software system, nor their employing *
// * institutes,nor the agencies providing financial support for this *
// * work make any representation or warranty, express or implied, *
// * regarding this software system or assume any liability for its *
// * use. Please see the license in the file LICENSE and URL above *
// * for the full disclaimer and the limitation of liability. *
// * *
// * This code implementation is the result of the scientific and *
// * technical work of the GEANT4 collaboration. *
// * By using, copying, modifying or distributing the software (or *
// * any work based on the software) you agree to acknowledge its *
// * use in resulting scientific publications, and indicate your *
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
#include "PrimaryGeneratorAction.hh"
#include "PrimaryGeneratorMessenger.hh"
#include "G4Box.hh"
#include "G4LogicalVolume.hh"
#include "G4LogicalVolumeStore.hh"
#include "G4ParticleGun.hh"
#include "G4ParticleTable.hh"
#include "G4RunManager.hh"
#include "Randomize.hh"
#ifdef WITHROOT
#include "G4MTRunManager.hh"
#include "G4Run.hh"
#include "TFile.h"
#include "TTreeReader.h"
#include "TTreeReaderValue.h"
#endif
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
PrimaryGeneratorAction::PrimaryGeneratorAction()
: G4VUserPrimaryGeneratorAction(), fParticleGun(nullptr),
fEnvelopeBox(nullptr) {
G4int n_particle = 1;
fParticleGun = new G4ParticleGun(n_particle);
// default particle kinematic
G4ParticleTable *particleTable = G4ParticleTable::GetParticleTable();
G4String particleName;
G4ParticleDefinition *particle =
particleTable->FindParticle(particleName = "e+");
fParticleGun->SetParticleDefinition(particle);
fParticleGun->SetParticleMomentumDirection(G4ThreeVector(0., 0., 1.));
fParticleGun->SetParticleEnergy(30. * CLHEP::GeV);
fParticleGun->SetParticlePosition(G4ThreeVector(0., 0., 0.));
fMessenger = new PrimaryGeneratorMessenger(this);
#ifdef WITHROOT
if (fReadInputFile)
OpenInput();
#endif
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
#ifdef WITHROOT
void PrimaryGeneratorAction::OpenInput() {
if (fInputFile != nullptr) {
delete fInputFile;
fInputFile = nullptr;
}
fInputFile = new TFile(fPathInputFile, "READ");
if (fInputFile == nullptr || fInputFile->IsZombie()) {
G4ExceptionDescription msg;
msg << "Input file '" << fPathInputFile << "' cannot be opened.\n";
G4Exception("PrimaryGeneratorAction::GeneratePrimaries()", "WrongInputName",
FatalErrorInArgument, msg);
}
auto fileDirectory =
dynamic_cast<TDirectory *>(fInputFile->Get("VirtualDetector"));
if (fileDirectory == nullptr) {
G4ExceptionDescription msg;
msg << "Input file '" << fPathInputFile
<< "' does not contain 'VirtualDetector' directory.\n";
G4Exception("PrimaryGeneratorAction::GeneratePrimaries()",
"WrongInputDirectory", FatalErrorInArgument, msg);
}
fHgcalReader = new TTreeReader("HGCAL", fileDirectory);
fHgcalEventId = new TTreeReaderValue<Float_t>(*fHgcalReader, "EventID");
fHgcalPdgId = new TTreeReaderValue<Float_t>(*fHgcalReader, "PDGid");
fHgcalPosX = new TTreeReaderValue<Float_t>(*fHgcalReader, "x");
fHgcalPosY = new TTreeReaderValue<Float_t>(*fHgcalReader, "y");
fHgcalMomX = new TTreeReaderValue<Float_t>(*fHgcalReader, "Px");
fHgcalMomY = new TTreeReaderValue<Float_t>(*fHgcalReader, "Py");
fHgcalMomZ = new TTreeReaderValue<Float_t>(*fHgcalReader, "Pz");
return;
}
#endif
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
PrimaryGeneratorAction::~PrimaryGeneratorAction() {
delete fParticleGun;
#ifdef WITHROOT
delete fInputFile;
#endif
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void PrimaryGeneratorAction::GeneratePrimaries(G4Event *anEvent) {
#ifdef WITHROOT
if (fReadInputFile) {
// get primary particles from input file
if (fInputFile == nullptr) {
OpenInput();
}
Float_t currentEventId = -1;
while (fHgcalReader->Next()) {
// First particle - set event ID
if (currentEventId == -1) {
currentEventId = **fHgcalEventId;
fEventCounter++;
// check if event should be ignored (is before the start position)
if (fEventCounter < fStartFromEvent)
continue;
} else {
// check if event is to be skipped
if (fEventCounter < fStartFromEvent) {
if (currentEventId != **fHgcalEventId)
currentEventId = -1;
continue;
} else {
// check if current particle belongs to the next event
if (currentEventId != **fHgcalEventId)
break;
}
}
auto vertex = new G4PrimaryVertex(
G4ThreeVector(**fHgcalPosX, **fHgcalPosY, 32.5 * CLHEP::mm), 0 * CLHEP::s);
auto particleDefinition =
G4ParticleTable::GetParticleTable()->FindParticle(**fHgcalPdgId);
auto particle = new G4PrimaryParticle(particleDefinition);
G4ThreeVector momentum(**fHgcalMomX, **fHgcalMomY, **fHgcalMomZ);
particle->SetMomentumDirection(momentum.unit());
particle->SetKineticEnergy(momentum.mag());
vertex->SetPrimary(particle);
anEvent->AddPrimaryVertex(vertex);
}
// if no particles are left - terminate run
if (fEventCounter >= fStartFromEvent &&
anEvent->GetNumberOfPrimaryVertex() == 0) {
G4ExceptionDescription msg;
msg << "Input file does not contain any more events (current event ID = "
<< anEvent->GetEventID() << ").\n";
msg << "Run will be aborted with " << anEvent->GetEventID()
<< " events processed.\n";
G4Exception("PrimaryGeneratorAction::GeneratePrimaries()",
"EndOfInputFile", JustWarning, msg);
G4RunManager::GetRunManager()->AbortRun();
}
// warn if this is the last event and some events are left in the file
// unprocessed
if (G4RunManager::GetRunManager()
->GetCurrentRun()
->GetNumberOfEventToBeProcessed() == anEvent->GetEventID() + 1) {
G4ExceptionDescription msg;
msg << "Input file contains more events than requested in the run.\n";
G4Exception("PrimaryGeneratorAction::GeneratePrimaries()",
"UnusedEventsInInputFile", JustWarning, msg);
}
} else
#endif
{
// Beam position: z
// Use value set by UI command, or set it to edge of the world volume
if (fBeamZ0 == -999 * CLHEP::m) {
G4double worldDZ = 0;
if (!fEnvelopeBox) {
G4LogicalVolume *envLV =
G4LogicalVolumeStore::GetInstance()->GetVolume("World");
if (envLV)
fEnvelopeBox = dynamic_cast<G4Box *>(envLV->GetSolid());
}
if (fEnvelopeBox) {
worldDZ = fEnvelopeBox->GetZHalfLength();
fBeamZ0 = -worldDZ;
} else {
G4ExceptionDescription msg;
msg << "World volume of box shape not found.\n";
msg << "Perhaps you have changed geometry.\n";
msg << "The gun will be place at the center.";
G4Exception("PrimaryGeneratorAction::GeneratePrimaries()",
"WorldVolume", JustWarning, msg);
}
}
// Beam position: x,y
switch (fBeamType) {
case eNone:
default:
fParticleGun->SetParticlePosition(G4ThreeVector(0, 0, fBeamZ0));
break;
case eGaussian:
fParticleGun->SetParticlePosition(
G4ThreeVector(G4RandGauss::shoot(0., fSigmaBeamX),
G4RandGauss::shoot(0., fSigmaBeamY), fBeamZ0));
break;
case eFlat:
fParticleGun->SetParticlePosition(
G4ThreeVector(G4RandFlat::shoot(-fSigmaBeamX, fSigmaBeamX),
G4RandFlat::shoot(-fSigmaBeamY, fSigmaBeamY), fBeamZ0));
break;
}
// Particle momentum
if (fMomentumGaussianSpread > 0) {
double energy = fParticleGun->GetParticleEnergy();
energy += G4RandGauss::shoot(0., fMomentumGaussianSpread) * energy;
fParticleGun->SetParticleEnergy(energy);
}
fParticleGun->GeneratePrimaryVertex(anEvent);
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......