Files
geant4/examples/advanced/xray_fluorescence/src/XrayFluoAnalysisManager.cc
T
2021-12-10 16:15:15 +00:00

465 lines
15 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. *
// ********************************************************************
//
//
//
// Author: Elena Guardincerri (Elena.Guardincerri@ge.infn.it)
//
// History:
// -----------
// 20 Jul 2007 A.Mantero, code cleaning and update. Replaced histos with tuple
// 11 Jul 2003 A.Mantero, code cleaning / Plotter-XML addiction
// Sep 2002 A.Mantero, AIDA3.0 Migration
// 06 Dec 2001 A.Pfeiffer updated for singleton
// 30 Nov 2001 Guy Barrand : migrate to AIDA-2.2.
// 28 Nov 2001 Elena Guardincerri Created
//
// -------------------------------------------------------------------
#include "G4AnalysisManager.hh"
#include "G4RootAnalysisReader.hh"
#include "G4VProcess.hh"
#include "XrayFluoAnalysisManager.hh"
#include "G4Step.hh"
#include "XrayFluoDetectorConstruction.hh"
#include "G4VPhysicalVolume.hh"
#include "G4Gamma.hh"
#include "G4Electron.hh"
#include "G4Proton.hh"
#include "G4SystemOfUnits.hh"
using G4AnalysisReader = G4RootAnalysisReader;
XrayFluoAnalysisManager* XrayFluoAnalysisManager::instance = 0;
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
namespace {
//Mutex to acquire access to singleton instance check/creation
G4Mutex instanceMutex = G4MUTEX_INITIALIZER;
//Mutex to acquire accss to histograms creation/access
//It is also used to control all operations related to histos
//File writing and check analysis
G4Mutex dataManipulationMutex = G4MUTEX_INITIALIZER;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
XrayFluoAnalysisManager::XrayFluoAnalysisManager()
:outputFileName("xrayfluo"), phaseSpaceFlag(false), physicFlag (false),
gunParticleEnergies(0), gunParticleTypes(0)
{
dataLoaded = false;
fParticleEnergyAndTypeIndex = 0;
//creating the messenger
analisysMessenger = new XrayFluoAnalysisMessenger(this);
//Instantiate the analysis manager
G4AnalysisManager::Instance();
G4cout << "XrayFluoAnalysisManager created" << G4endl;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
XrayFluoAnalysisManager::~XrayFluoAnalysisManager()
{
if ( gunParticleEnergies ) delete gunParticleEnergies;
gunParticleEnergies = 0;
if ( gunParticleTypes ) delete gunParticleTypes;
gunParticleTypes = 0;
delete instance;
instance = 0;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
XrayFluoAnalysisManager* XrayFluoAnalysisManager::getInstance()
{
G4AutoLock l(&instanceMutex);
if (instance == 0) {instance = new XrayFluoAnalysisManager;}
return instance;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void XrayFluoAnalysisManager::book()
{
G4AutoLock l(&dataManipulationMutex);
// Get analysis manager
G4AnalysisManager* man = G4AnalysisManager::Instance();
man->SetDefaultFileType("root");
// Open an output file
man->OpenFile(outputFileName);
man->SetVerboseLevel(1);
man->SetFirstHistoId(1);
man->SetFirstNtupleId(1);
G4cout << "Open output file: " << outputFileName << G4endl;
if (phaseSpaceFlag)
{
// Book output Tuple (ID = 1)
man->CreateNtuple("101","OutputNTuple");
man->CreateNtupleIColumn("particle");
man->CreateNtupleDColumn("energies");
man->CreateNtupleDColumn("momentumTheta");
man->CreateNtupleDColumn("momentumPhi");
man->CreateNtupleIColumn("processes");
man->CreateNtupleIColumn("material");
man->CreateNtupleIColumn("origin");
man->CreateNtupleDColumn("depth");
man->FinishNtuple();
G4cout << "Created ntuple for phase space" << G4endl;
}
else {
// Book histograms
man->CreateH1("h1","Energy Deposit", 500,0.,10.); //20eV def.
man->CreateH1("h2","Gamma born in the sample", 100,0.,10.);
man->CreateH1("h3","Electrons born in the sample", 100,0.,10.);
man->CreateH1("h4","Gammas leaving the sample", 300,0.,10.);
man->CreateH1("h5","Electrons leaving the sample ",200000 ,0.,10.0); // .05 eV def.
man->CreateH1("h6","Gammas reaching the detector", 100,0.,10.);
man->CreateH1("h7","Spectrum of the incident particles", 100,0.,10.);
man->CreateH1("h8","Protons reaching the detector", 100,0.,10.);
man->CreateH1("h9","Protons leaving the sample", 100,0.,10.);
G4cout << "Created histos" << G4endl;
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void XrayFluoAnalysisManager::LoadGunData(G4String fileName, G4bool raileighFlag)
{
G4AutoLock l(&dataManipulationMutex);
//Do not allow more than one thread to trigger the file reading
if (dataLoaded)
return;
// Get analysis reader manager
G4AnalysisReader* analysisReader = G4AnalysisReader::Instance();
analysisReader->SetVerboseLevel(1);
//This is for testing purposes
G4int ntupleId = analysisReader->GetNtuple("101",fileName);
G4cout << "Got ntupleId: " << ntupleId << G4endl;
gunParticleEnergies = new std::vector<G4double>;
gunParticleTypes = new std::vector<G4String>;
G4int particleID, processID;
G4double energy;
analysisReader->SetNtupleIColumn("processes", processID);
analysisReader->SetNtupleDColumn("energies", energy);
analysisReader->SetNtupleIColumn("particles", particleID);
while (analysisReader->GetNtupleRow() )
{
if (raileighFlag ^ (!raileighFlag && (processID == 1 ||
processID == 2)) )
{
gunParticleEnergies->push_back(energy*MeV);
if (particleID == 1)
gunParticleTypes->push_back("gamma");
else if (particleID == 0)
gunParticleTypes->push_back("e-");
}
}
G4cout << "Maximum mumber of events: "<< gunParticleEnergies->size() <<G4endl;
dataLoaded= true;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
const std::pair<G4double,G4String> XrayFluoAnalysisManager::GetEmittedParticleEnergyAndType()
{
G4AutoLock l(&dataManipulationMutex);
std::pair<G4double,G4String> result;
if(fParticleEnergyAndTypeIndex < (G4int) gunParticleEnergies->size())
{
G4double energy = gunParticleEnergies->at(fParticleEnergyAndTypeIndex);
G4String name = gunParticleTypes->at(fParticleEnergyAndTypeIndex);
result.first = energy;
result.second = name;
}
fParticleEnergyAndTypeIndex++;
return result;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void XrayFluoAnalysisManager::finish()
{
G4AutoLock l(&dataManipulationMutex);
G4cout << "Going to save histograms" << G4endl;
// Save histograms
G4AnalysisManager* man = G4AnalysisManager::Instance();
man->Write();
man->CloseFile();
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void XrayFluoAnalysisManager::SetPhysicFlag(G4bool val)
{
physicFlag = val;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void XrayFluoAnalysisManager::analyseStepping(const G4Step* aStep)
{
G4AutoLock l(&dataManipulationMutex);
G4AnalysisManager* man = G4AnalysisManager::Instance();
if (phaseSpaceFlag){
G4ParticleDefinition* particleType= 0;
G4String parentProcess="";
G4ThreeVector momentum(0.,0.,0.);
G4double particleEnergy=0;
G4String sampleMaterial="";
G4double particleDepth=0;
G4int isBornInTheSample=0;
XrayFluoDetectorConstruction* detector = XrayFluoDetectorConstruction::GetInstance();
// Select volume from which the step starts
if(aStep->GetPreStepPoint()->GetPhysicalVolume()->GetName()=="Sample"){
G4ThreeVector creationPos = aStep->GetTrack()->GetVertexPosition();
// qua serve ancora una selezione: deve essere interno al sample
//codice "a mano" per controllare il volume di orgine della traccia
G4VPhysicalVolume* creationPosVolume = detector->GetGeometryNavigator()->LocateGlobalPointAndSetup(creationPos);
// if physicflag is on, I record all the data of all the particle born in the sample.
// If it is off (but phase space production is on) I record data
// only for particles creted inside the sample and exiting it.
if (physicFlag ^ (!physicFlag &&
(aStep->GetPostStepPoint()->GetStepStatus() == fGeomBoundary)
))
{
// extracting information needed
particleType = aStep->GetTrack()->GetDynamicParticle()->GetDefinition();
momentum = aStep->GetTrack()->GetDynamicParticle()->GetMomentum();
particleEnergy = aStep->GetPreStepPoint()->GetKineticEnergy();
if (creationPosVolume->GetName() == "Sample" ) {
isBornInTheSample = 1;
particleDepth = creationPosVolume->GetLogicalVolume()->GetSolid()
->DistanceToOut(creationPos, G4ThreeVector(0,0,-1));
}
else {
particleDepth = -1;
}
// metodo per ottenere la profondita' "a mano"
// particleDepth = std::abs(creationPos.z() - detector->GetSampleIlluminatedFaceCoord());
G4int parent=0;
if(aStep->GetTrack()->GetCreatorProcess())
{
parentProcess = aStep->GetTrack()->GetCreatorProcess()->GetProcessName();
parent = 5;
// hack for HBK
if (parentProcess == "") parent = 0;
if (parentProcess == "ioni") parent = 1;
if (parentProcess == "LowEnPhotoElec") parent = 2;
if (parentProcess == "Transportation") parent = 3;// should never happen
if (parentProcess == "initStep") parent = 4;// should never happen
}
else {
parentProcess = "Not Known -- (primary generator + Rayleigh)";
parent = 5;
}
G4int sampleMat=0;
if(aStep->GetTrack()){
sampleMaterial = aStep->GetTrack()->GetMaterial()->GetName();
if (sampleMaterial == "Dolorite"
|| sampleMaterial == "Anorthosite"
|| sampleMaterial == "Mars1"
|| sampleMaterial == "IceBasalt"
|| sampleMaterial == "HPGe") sampleMat=1;
}
G4int part = -1 ;
if (particleType == G4Gamma::Definition()) part =1;
if (particleType == G4Electron::Definition()) part = 0;
if (particleType == G4Proton::Definition()) part = 2;
//Fill ntuple
man->FillNtupleIColumn(1,0, part);
man->FillNtupleDColumn(1,1,particleEnergy);
man->FillNtupleDColumn(1,2,momentum.theta());
man->FillNtupleDColumn(1,3,momentum.phi());
man->FillNtupleIColumn(1,4,parent);
man->FillNtupleIColumn(1,5,sampleMat);
man->FillNtupleIColumn(1,6,isBornInTheSample);
man->FillNtupleDColumn(1,7,particleDepth);
man->AddNtupleRow(1);
}
}
}
// Normal behaviour, without creation of phase space
else
{
// Filling the histograms with data, passing thru stepping.
// Select volume from wich the step starts
if(aStep->GetPreStepPoint()->GetPhysicalVolume()->GetName()=="Sample"){
// Select volume from wich the step ends
if(aStep->GetTrack()->GetNextVolume()->GetName() == "World" ) {
// Select the particle type
if ((aStep->GetTrack()->GetDynamicParticle()
->GetDefinition()) == G4Gamma::Definition() )
{
G4double gammaLeavingSample =
aStep->GetPreStepPoint()->GetKineticEnergy();
man->FillH1(4,gammaLeavingSample/keV);
}
else if ((aStep->GetTrack()->GetDynamicParticle()
->GetDefinition()) == G4Electron::Definition() )
{
G4double eleLeavingSample =
aStep->GetPreStepPoint()->GetKineticEnergy();
man->FillH1(5,eleLeavingSample/keV);
}
else if ((aStep->GetTrack()->GetDynamicParticle()
->GetDefinition()) == G4Proton::Definition() )
{
G4double
protonsLeavSam = aStep->GetPreStepPoint()->GetKineticEnergy();
man->FillH1(9,protonsLeavSam/keV);
}
}
}
if((aStep->GetTrack()->GetDynamicParticle()
->GetDefinition()) == G4Gamma::Definition() )
{
if(aStep->GetTrack()->GetCurrentStepNumber() == 1)
{
if(aStep->GetTrack()->GetParentID() != 0)
{
if(aStep->GetTrack()->GetVolume()->GetName() == "Sample")
{
G4double gammaBornInSample =
aStep->GetPreStepPoint()->GetKineticEnergy();
man->FillH1(2,gammaBornInSample/keV);
}
}
}
}
else if ((aStep->GetTrack()->GetDynamicParticle()
->GetDefinition() ) == G4Electron::Definition() )
{
if(aStep->GetTrack()->GetCurrentStepNumber() == 1)
{
if(aStep->GetTrack()->GetParentID() != 0)
{
if(aStep->GetTrack()->GetVolume()->GetName() == "Sample")
{
G4double eleBornInSample =
aStep->GetPreStepPoint()->GetKineticEnergy();
man->FillH1(3,eleBornInSample/keV);
}
}
}
}
if(aStep->GetTrack()->GetNextVolume())
{
if(aStep->GetTrack()->GetNextVolume()->GetName() == "HPGeDetector")
{
if ((aStep->GetTrack()->GetDynamicParticle()
->GetDefinition()) == G4Gamma::Definition() )
{
G4double gammaAtTheDetPre =
aStep->GetPreStepPoint()->GetKineticEnergy();
man->FillH1(6,gammaAtTheDetPre/keV);
}
else if ((aStep->GetTrack()->GetDynamicParticle()
->GetDefinition() ) == G4Proton::Definition() )
{
G4double protonsAtTheDetPre =
aStep->GetPreStepPoint()->GetKineticEnergy();
man->FillH1(8,protonsAtTheDetPre);
}
}
}
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void XrayFluoAnalysisManager::analyseEnergyDep(G4double energyDep)
{
G4AutoLock l(&dataManipulationMutex);
// Filling of Energy Deposition, called by XrayFluoEventAction
G4AnalysisManager* man = G4AnalysisManager::Instance();
if (!phaseSpaceFlag)
man->FillH1(1,energyDep/keV);
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void XrayFluoAnalysisManager::analysePrimaryGenerator(G4double energy)
{
G4AutoLock l(&dataManipulationMutex);
// Filling of energy spectrum histogram of the primary generator
G4AnalysisManager* man = G4AnalysisManager::Instance();
if (!phaseSpaceFlag)
man->FillH1(7,energy/keV);
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void XrayFluoAnalysisManager::SetOutputFileName(G4String newName)
{
outputFileName = newName;
}