Import Geant4 11.0.0 source tree

This commit is contained in:
Gabriele Cosmo
2021-12-10 14:46:44 +01:00
committed by Ben Morgan
parent 6399a014b6
commit 80e2389dd8
3932 changed files with 202519 additions and 246221 deletions
@@ -0,0 +1,59 @@
//
// ********************************************************************
// * 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 "Par04ActionInitialisation.hh"
#include <G4VUserActionInitialization.hh> // for G4VUserActionInitialization
#include "Par04EventAction.hh" // for Par04EventAction
#include "Par04PrimaryGeneratorAction.hh" // for Par04PrimaryGeneratorAction
#include "Par04RunAction.hh" // for Par04RunAction
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
Par04ActionInitialisation::Par04ActionInitialisation(Par04DetectorConstruction* aDetector)
: G4VUserActionInitialization()
, fDetector(aDetector)
{}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
Par04ActionInitialisation::~Par04ActionInitialisation() {}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void Par04ActionInitialisation::BuildForMaster() const
{
auto eventAction = new Par04EventAction(fDetector);
SetUserAction(new Par04RunAction(fDetector, eventAction));
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void Par04ActionInitialisation::Build() const
{
SetUserAction(new Par04PrimaryGeneratorAction());
auto eventAction = new Par04EventAction(fDetector);
SetUserAction(eventAction);
SetUserAction(new Par04RunAction(fDetector, eventAction));
}
@@ -0,0 +1,88 @@
//
// ********************************************************************
// * 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 "Par04DefineMeshModel.hh"
#include <G4FastTrack.hh> // for G4FastTrack
#include <G4Track.hh> // for G4Track
#include <G4VFastSimulationModel.hh> // for G4VFastSimulationModel
#include <G4VUserEventInformation.hh> // for G4VUserEventInformation
#include "G4Event.hh" // for G4Event
#include "G4EventManager.hh" // for G4EventManager
#include "Par04EventInformation.hh" // for Par04EventInformation
class G4FastStep;
class G4ParticleDefinition;
class G4Region;
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
Par04DefineMeshModel::Par04DefineMeshModel(G4String aModelName, G4Region* aEnvelope)
: G4VFastSimulationModel(aModelName, aEnvelope)
{}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
Par04DefineMeshModel::Par04DefineMeshModel(G4String aModelName)
: G4VFastSimulationModel(aModelName)
{}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
Par04DefineMeshModel::~Par04DefineMeshModel() {}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4bool Par04DefineMeshModel::IsApplicable(const G4ParticleDefinition&)
{
return true;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4bool Par04DefineMeshModel::ModelTrigger(const G4FastTrack&)
{
Par04EventInformation* info = dynamic_cast<Par04EventInformation*>(
G4EventManager::GetEventManager()->GetConstCurrentEvent()->GetUserInformation());
// check if particle direction and position were already set for this event
if(info != nullptr)
return !info->GetFlag();
else
return true;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void Par04DefineMeshModel::DoIt(const G4FastTrack& aFastTrack, G4FastStep&)
{
Par04EventInformation* info = dynamic_cast<Par04EventInformation*>(
G4EventManager::GetEventManager()->GetConstCurrentEvent()->GetUserInformation());
if(info == nullptr)
{
info = new Par04EventInformation();
G4EventManager::GetEventManager()->GetNonconstCurrentEvent()->SetUserInformation(info);
}
info->SetPosition(aFastTrack.GetPrimaryTrack()->GetPosition());
info->SetDirection(aFastTrack.GetPrimaryTrack()->GetMomentumDirection());
info->SetFlag(true);
}
@@ -0,0 +1,266 @@
//
// ********************************************************************
// * 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 "Par04DetectorConstruction.hh"
#include <G4Colour.hh> // for G4Colour
#include <G4Exception.hh> // for G4Exception
#include <G4ExceptionSeverity.hh> // for FatalException
#include <G4SystemOfUnits.hh> // for rad
#include <G4ThreeVector.hh> // for G4ThreeVector
#include <G4VUserDetectorConstruction.hh> // for G4VUserDetectorConstruction
#include <G4ios.hh> // for G4endl, G4cout
#include <algorithm> // for max
#include <numeric> // for accumulate
#include <ostream> // for operator<<, basic_ostream
#include <string> // for allocator, char_traits
#include "G4Box.hh" // for G4Box
#include "G4LogicalVolume.hh" // for G4LogicalVolume
#include "G4Material.hh" // for G4Material
#include "G4NistManager.hh" // for G4NistManager
#include "G4PVPlacement.hh" // for G4PVPlacement
#include "G4Region.hh" // for G4Region
#include "G4RegionStore.hh" // for G4RegionStore
#include "G4RunManager.hh" // for G4RunManager
#include "G4SDManager.hh" // for G4SDManager
#include "G4Tubs.hh" // for G4Tubs
#include "G4UnitsTable.hh" // for operator<<, G4BestUnit
#include "G4VisAttributes.hh" // for G4VisAttributes
#include "Par04DefineMeshModel.hh" // for Par04DefineMeshModel
#include "Par04DetectorMessenger.hh" // for Par04DetectorMessenger
#include "Par04SensitiveDetector.hh" // for Par04SensitiveDetector
class G4VPhysicalVolume;
#ifdef USE_INFERENCE
#include "Par04MLFastSimModel.hh"
#endif
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
Par04DetectorConstruction::Par04DetectorConstruction()
: G4VUserDetectorConstruction()
{
fDetectorMessenger = new Par04DetectorMessenger(this);
G4NistManager* nistManager = G4NistManager::Instance();
fAbsorberMaterial[0] = nistManager->FindOrBuildMaterial("G4_PbWO4");
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
Par04DetectorConstruction::~Par04DetectorConstruction() {}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4VPhysicalVolume* Par04DetectorConstruction::Construct()
{
//--------- Material definition ---------
G4NistManager* nistManager = G4NistManager::Instance();
G4Material* air = nistManager->FindOrBuildMaterial("G4_AIR");
//--------- Derived dimensions ---------
G4double full2Pi = 2. * CLHEP::pi * rad;
G4double layerThickness =
std::accumulate(fAbsorberThickness.begin(), fAbsorberThickness.end(), 0.);
G4double detectorOuterRadius = fDetectorInnerRadius + fNbOfLayers * layerThickness;
G4double worldSizeXY = detectorOuterRadius * 4.;
G4double worldSizeZ = fDetectorLength * 2;
// check number of materials: (1 = homogeneous calo, 2 = sampling calo)
G4int nbOfMaterials = 0;
for(const auto material : fAbsorberMaterial)
{
if(material != nullptr)
nbOfMaterials++;
}
//--------- World ---------
auto fSolidWorld = new G4Box("World", // name
worldSizeXY / 2., // half-width in X
worldSizeXY / 2., // half-width in Y
worldSizeZ / 2.); // half-width in Z
auto fLogicWorld = new G4LogicalVolume(fSolidWorld, // solid
air, // material
"World"); // name
auto fPhysicWorld = new G4PVPlacement(0, // no rotation
G4ThreeVector(), // at (0,0,0)
fLogicWorld, // logical volume
"World", // name
0, // mother volume
false, // not used
999, // copy number
true); // copy number
fLogicWorld->SetVisAttributes(G4VisAttributes::GetInvisible());
//--------- Detector envelope ---------
auto fSolidDetector = new G4Tubs("Detector", // name
fDetectorInnerRadius, // inner radius
detectorOuterRadius, // outer radius
fDetectorLength / 2., // half-width in Z
0, // start angle
full2Pi); // delta angle
auto fLogicDetector = new G4LogicalVolume(fSolidDetector, // solid
air, // material
"Detector"); // name
new G4PVPlacement(0, // no rotation
G4ThreeVector(0, 0, 0), // detector centre at (0,0,0)
fLogicDetector, // logical volume
"Detector", // name
fLogicWorld, // mother volume
false, // not used
99, // copy number
true); // check overlaps
// Region for fast simulation
auto detectorRegion = new G4Region("DetectorRegion");
detectorRegion->AddRootLogicalVolume(fLogicDetector);
//--------- Detector layers: material ---------
std::array<G4VisAttributes, 2> attribs;
attribs[0].SetColour(G4Colour(0, 0, 1, 0.1));
attribs[0].SetForceSolid(true);
attribs[1].SetColour(G4Colour(1, 0, 0, 0.1));
attribs[1].SetForceSolid(true);
/// useful variable
G4double innerRadius = fDetectorInnerRadius;
for(G4int iLayer = 0; iLayer < fNbOfLayers; iLayer++)
{
for(G4int iMaterial = 0; iMaterial < nbOfMaterials; iMaterial++)
{
auto fSolidLayer = new G4Tubs("Layer", // name
innerRadius, // inner radius
innerRadius + fAbsorberThickness[iMaterial], // outer radius
fDetectorLength / 2., // half-width in Z
0, // start angle
full2Pi); // delta angle
G4LogicalVolume* logical = new G4LogicalVolume(fSolidLayer, // solid
fAbsorberMaterial[iMaterial], // material
"Layer"); // name
new G4PVPlacement(0, // no rotation
G4ThreeVector(), // place at centre of mother volume
logical, // logical volume
"Layer", // name
fLogicDetector, // mother volume
false, // not used
iLayer * nbOfMaterials + iMaterial, // copy number
true); // check overlaps
logical->SetVisAttributes(attribs[iMaterial]);
innerRadius += fAbsorberThickness[iMaterial];
if(fAbsorberSensitivity[iMaterial])
{
fLayerLogical.push_back(logical);
}
}
}
Print();
return fPhysicWorld;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void Par04DetectorConstruction::ConstructSDandField()
{
Par04SensitiveDetector* caloSD =
new Par04SensitiveDetector("sensitiveDetector", fMeshNbOfCells, fMeshSizeOfCells);
G4SDManager::GetSDMpointer()->AddNewDetector(caloSD);
for(const auto logical : fLayerLogical)
{
SetSensitiveDetector(logical, caloSD);
}
auto detectorRegion = G4RegionStore::GetInstance()->GetRegion("DetectorRegion");
// Par04DefineMeshModel needs to be first model to call
new Par04DefineMeshModel("defineMesh", detectorRegion);
#ifdef USE_INFERENCE
new Par04MLFastSimModel("inferenceModel", detectorRegion);
#endif
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void Par04DetectorConstruction::Print() const
{
G4cout << "\n------------------------------------------------------"
<< "\n--- Detector length:\t" << G4BestUnit(fDetectorLength, "Length")
<< "\n--- Detector inner radius:\t" << G4BestUnit(fDetectorInnerRadius, "Length")
<< "\n--- Number of layers:\t" << fNbOfLayers << G4endl << "\n--- 1st layer: \t"
<< G4BestUnit(fAbsorberThickness[0], "Length") << " of "
<< (fAbsorberSensitivity[0] ? "active " : "passive ") << fAbsorberMaterial[0]->GetName()
<< G4endl;
if(fAbsorberMaterial[1] != nullptr)
G4cout << "--- 2nd layer: \t" << G4BestUnit(fAbsorberThickness[1], "Length") << " of "
<< (fAbsorberSensitivity[1] ? "active " : "passive ") << fAbsorberMaterial[1]->GetName()
<< G4endl;
G4cout << "-----------------------------------------------------" << G4endl;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void Par04DetectorConstruction::SetAbsorberMaterial(const std::size_t aLayer, const G4String& aName)
{
// search material by its name
G4Material* material = G4NistManager::Instance()->FindOrBuildMaterial(aName);
if(material)
fAbsorberMaterial[aLayer] = material;
else
G4Exception("Par04DetectorConstruction::SetAbsorberMaterial()", "InvalidSetup", FatalException,
("Unknown material name: " + aName).c_str());
G4RunManager::GetRunManager()->PhysicsHasBeenModified();
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void Par04DetectorConstruction::SetAbsorberThickness(const std::size_t aLayer, const G4double aThickness)
{
if(aLayer < fAbsorberThickness.size())
fAbsorberThickness[aLayer] = aThickness;
else
G4Exception("Par04DetectorConstruction::SetAbsorberThickness()", "InvalidSetup", FatalException,
("Requested layer " + std::to_string(aLayer) +
" is larger than number of available layers (" +
std::to_string(fAbsorberThickness.size()) + ").")
.c_str());
G4RunManager::GetRunManager()->PhysicsHasBeenModified();
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void Par04DetectorConstruction::SetAbsorberSensitivity(const std::size_t aLayer, const G4bool aSensitivity)
{
if(aLayer < fAbsorberSensitivity.size())
fAbsorberSensitivity[aLayer] = aSensitivity;
else
G4Exception(
"Par04DetectorConstruction::SetAbsorberSensitivity()", "InvalidSetup", FatalException,
("Requested layer " + std::to_string(aLayer) + " is larger than number of available layers (" +
std::to_string(fAbsorberSensitivity.size()) + ").")
.c_str());
G4RunManager::GetRunManager()->PhysicsHasBeenModified();
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void Par04DetectorConstruction::SetInnerRadius(G4double aRadius) { fDetectorInnerRadius = aRadius; }
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void Par04DetectorConstruction::SetLength(G4double aLength) { fDetectorLength = aLength; }
@@ -0,0 +1,267 @@
//
// ********************************************************************
// * 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 "Par04DetectorMessenger.hh"
#include <CLHEP/Units/SystemOfUnits.h> // for pi
#include <G4ApplicationState.hh> // for G4State_PreInit, G4State_Idle
#include <G4ThreeVector.hh> // for G4ThreeVector
#include <G4Types.hh> // for G4bool, G4double, G4int
#include <G4UIcommand.hh> // for G4UIcommand
#include <G4UImessenger.hh> // for G4UImessenger
#include <G4UIparameter.hh> // for G4UIparameter
#include <istream> // for basic_istream, basic_istream...
#include <string> // for operator>>
#include "G4UIcmdWithADoubleAndUnit.hh" // for G4UIcmdWithADoubleAndUnit
#include "G4UIcmdWithAnInteger.hh" // for G4UIcmdWithAnInteger
#include "G4UIcmdWithoutParameter.hh" // for G4UIcmdWithoutParameter
#include "G4UIdirectory.hh" // for G4UIdirectory
#include "Par04DetectorConstruction.hh" // for Par04DetectorConstruction
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
Par04DetectorMessenger::Par04DetectorMessenger(Par04DetectorConstruction* aDetector)
: G4UImessenger()
, fDetector(aDetector)
{
fExampleDir = new G4UIdirectory("/Par04/");
fExampleDir->SetGuidance("UI commands specific to this example");
fDetectorDir = new G4UIdirectory("/Par04/detector/");
fDetectorDir->SetGuidance("Detector construction UI commands");
fPrintCmd = new G4UIcmdWithoutParameter("/Par04/detector/print", this);
fPrintCmd->SetGuidance("Print current settings.");
fDetectorInnerRadiusCmd =
new G4UIcmdWithADoubleAndUnit("/Par04/detector/setDetectorInnerRadius", this);
fDetectorInnerRadiusCmd->SetGuidance("Set cylindrical detector inner radius");
fDetectorInnerRadiusCmd->SetParameterName("Size", false);
fDetectorInnerRadiusCmd->SetRange("Size>0.");
fDetectorInnerRadiusCmd->SetUnitCategory("Length");
fDetectorInnerRadiusCmd->AvailableForStates(G4State_PreInit);
fDetectorInnerRadiusCmd->SetToBeBroadcasted(false);
fDetectorLengthCmd = new G4UIcmdWithADoubleAndUnit("/Par04/detector/setDetectorLength", this);
fDetectorLengthCmd->SetGuidance("Set length of the detector (cylinder length)");
fDetectorLengthCmd->SetParameterName("Size", false);
fDetectorLengthCmd->SetRange("Size>0.");
fDetectorLengthCmd->SetUnitCategory("Length");
fDetectorLengthCmd->AvailableForStates(G4State_PreInit);
fDetectorLengthCmd->SetToBeBroadcasted(false);
fNbLayersCmd = new G4UIcmdWithAnInteger("/Par04/detector/setNbOfLayers", this);
fNbLayersCmd->SetGuidance("Set number of layers.");
fNbLayersCmd->SetParameterName("NbLayers", false);
fNbLayersCmd->SetRange("NbLayers>0");
fNbLayersCmd->AvailableForStates(G4State_PreInit);
fNbLayersCmd->SetToBeBroadcasted(false);
fAbsorCmd = new G4UIcommand("/Par04/detector/setAbsorber", this);
fAbsorCmd->SetGuidance("Set the absorber id, the material, the thickness.");
fAbsorCmd->SetGuidance(" absorber number : from 0 to 1");
fAbsorCmd->SetGuidance(" material name");
fAbsorCmd->SetGuidance(" thickness (with unit) : t>0");
fAbsorCmd->SetGuidance(" if sensitive : true/false.");
G4UIparameter* absNbPrm = new G4UIparameter("AbsorNb", 'i', false);
absNbPrm->SetGuidance("absor number : from 0 to 1");
absNbPrm->SetParameterRange("AbsorNb>-1&AbsoNb<2");
fAbsorCmd->SetParameter(absNbPrm);
G4UIparameter* matPrm = new G4UIparameter("material", 's', false);
matPrm->SetGuidance("material name");
fAbsorCmd->SetParameter(matPrm);
G4UIparameter* thickPrm = new G4UIparameter("thickness", 'd', false);
thickPrm->SetGuidance("thickness of absorber");
thickPrm->SetParameterRange("thickness>0.");
fAbsorCmd->SetParameter(thickPrm);
G4UIparameter* unitPrm = new G4UIparameter("unit", 's', false);
unitPrm->SetGuidance("unit of thickness");
G4String unitList = G4UIcommand::UnitsList(G4UIcommand::CategoryOf("mm"));
unitPrm->SetParameterCandidates(unitList);
fAbsorCmd->SetParameter(unitPrm);
G4UIparameter* sensitivePrm = new G4UIparameter("sensitive", 'b', false);
sensitivePrm->SetGuidance("if absorber is sensitive (registers energy deposits)");
fAbsorCmd->SetParameter(sensitivePrm);
fAbsorCmd->AvailableForStates(G4State_PreInit, G4State_Idle);
fAbsorCmd->SetToBeBroadcasted(false);
fMeshDir = new G4UIdirectory("/Par04/mesh/");
fMeshDir->SetGuidance("Mesh UI commands");
fMeshNbRhoCellsCmd = new G4UIcmdWithAnInteger("/Par04/mesh/setNbOfRhoCells", this);
fMeshNbRhoCellsCmd->SetGuidance("Set number of rho cells in the cylindrical mesh readout.");
fMeshNbRhoCellsCmd->SetParameterName("NbRhoCells", false);
fMeshNbRhoCellsCmd->SetRange("NbRhoCells>0");
fMeshNbRhoCellsCmd->AvailableForStates(G4State_PreInit);
fMeshNbRhoCellsCmd->SetToBeBroadcasted(false);
fMeshNbPhiCellsCmd = new G4UIcmdWithAnInteger("/Par04/mesh/setNbOfPhiCells", this);
fMeshNbPhiCellsCmd->SetGuidance("Set number of phi cells in the cylindrical mesh readout.");
fMeshNbPhiCellsCmd->SetParameterName("NbPhiCells", false);
fMeshNbPhiCellsCmd->SetRange("NbPhiCells>0");
fMeshNbPhiCellsCmd->AvailableForStates(G4State_PreInit);
fMeshNbPhiCellsCmd->SetToBeBroadcasted(false);
fMeshNbZCellsCmd = new G4UIcmdWithAnInteger("/Par04/mesh/setNbOfZCells", this);
fMeshNbZCellsCmd->SetGuidance("Set number of z cells in the cylindrical mesh readout.");
fMeshNbZCellsCmd->SetParameterName("NbZCells", false);
fMeshNbZCellsCmd->SetRange("NbZCells>0");
fMeshNbZCellsCmd->AvailableForStates(G4State_PreInit);
fMeshNbZCellsCmd->SetToBeBroadcasted(false);
fMeshSizeRhoCellsCmd = new G4UIcmdWithADoubleAndUnit("/Par04/mesh/setSizeOfRhoCells", this);
fMeshSizeRhoCellsCmd->SetGuidance("Set size of rho cells in the cylindrical readout mesh");
fMeshSizeRhoCellsCmd->SetParameterName("Size", false);
fMeshSizeRhoCellsCmd->SetRange("Size>0.");
fMeshSizeRhoCellsCmd->SetUnitCategory("Length");
fMeshSizeRhoCellsCmd->AvailableForStates(G4State_PreInit);
fMeshSizeRhoCellsCmd->SetToBeBroadcasted(false);
fMeshSizeZCellsCmd = new G4UIcmdWithADoubleAndUnit("/Par04/mesh/setSizeOfZCells", this);
fMeshSizeZCellsCmd->SetGuidance("Set size of z cells in the cylindrical readout mesh");
fMeshSizeZCellsCmd->SetParameterName("Size", false);
fMeshSizeZCellsCmd->SetRange("Size>0.");
fMeshSizeZCellsCmd->SetUnitCategory("Length");
fMeshSizeZCellsCmd->AvailableForStates(G4State_PreInit);
fMeshSizeZCellsCmd->SetToBeBroadcasted(false);
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
Par04DetectorMessenger::~Par04DetectorMessenger()
{
delete fPrintCmd;
delete fDetectorInnerRadiusCmd;
delete fDetectorLengthCmd;
delete fNbLayersCmd;
delete fAbsorCmd;
delete fDetectorDir;
delete fMeshNbRhoCellsCmd;
delete fMeshNbPhiCellsCmd;
delete fMeshNbZCellsCmd;
delete fMeshSizeRhoCellsCmd;
delete fMeshSizeZCellsCmd;
delete fMeshDir;
delete fExampleDir;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void Par04DetectorMessenger::SetNewValue(G4UIcommand* aCommand, G4String aNewValue)
{
if(aCommand == fPrintCmd)
{
fDetector->Print();
}
else if(aCommand == fDetectorInnerRadiusCmd)
{
fDetector->SetInnerRadius(fDetectorInnerRadiusCmd->GetNewDoubleValue(aNewValue));
}
else if(aCommand == fDetectorLengthCmd)
{
fDetector->SetLength(fDetectorInnerRadiusCmd->GetNewDoubleValue(aNewValue));
}
else if(aCommand == fNbLayersCmd)
{
fDetector->SetNbOfLayers(fNbLayersCmd->GetNewIntValue(aNewValue));
}
else if(aCommand == fAbsorCmd)
{
G4int num;
G4double thick;
G4String unt, mat;
G4bool sensitive;
std::istringstream is(aNewValue);
is >> num >> mat >> thick >> unt >> std::boolalpha >> sensitive;
G4String material = mat;
thick *= G4UIcommand::ValueOf(unt);
fDetector->SetAbsorberMaterial(num, material);
fDetector->SetAbsorberThickness(num, thick);
fDetector->SetAbsorberSensitivity(num, sensitive);
}
else if(aCommand == fMeshNbRhoCellsCmd)
{
fDetector->SetMeshNbOfCells(0, fMeshNbRhoCellsCmd->GetNewIntValue(aNewValue));
}
else if(aCommand == fMeshNbPhiCellsCmd)
{
fDetector->SetMeshNbOfCells(1, fMeshNbPhiCellsCmd->GetNewIntValue(aNewValue));
fDetector->SetMeshSizeOfCells(1,
2. * CLHEP::pi / fMeshNbPhiCellsCmd->GetNewIntValue(aNewValue));
}
else if(aCommand == fMeshNbZCellsCmd)
{
fDetector->SetMeshNbOfCells(2, fMeshNbZCellsCmd->GetNewIntValue(aNewValue));
}
else if(aCommand == fMeshSizeRhoCellsCmd)
{
fDetector->SetMeshSizeOfCells(0, fMeshSizeRhoCellsCmd->GetNewDoubleValue(aNewValue));
}
else if(aCommand == fMeshSizeZCellsCmd)
{
fDetector->SetMeshSizeOfCells(2, fMeshSizeZCellsCmd->GetNewDoubleValue(aNewValue));
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4String Par04DetectorMessenger::GetCurrentValue(G4UIcommand* aCommand)
{
G4String cv;
if(aCommand == fDetectorInnerRadiusCmd)
{
cv = fDetectorInnerRadiusCmd->ConvertToString(fDetector->GetInnerRadius(), "mm");
}
else if(aCommand == fDetectorLengthCmd)
{
cv = fDetectorLengthCmd->ConvertToString(fDetector->GetLength(), "mm");
}
else if(aCommand == fNbLayersCmd)
{
cv = fNbLayersCmd->ConvertToString(fDetector->GetNbOfLayers());
}
else if(aCommand == fMeshNbRhoCellsCmd)
{
cv = fMeshNbRhoCellsCmd->ConvertToString(fDetector->GetMeshNbOfCells()[0]);
}
else if(aCommand == fMeshNbPhiCellsCmd)
{
cv = fMeshNbPhiCellsCmd->ConvertToString(fDetector->GetMeshNbOfCells()[1]);
}
else if(aCommand == fMeshNbZCellsCmd)
{
cv = fMeshNbZCellsCmd->ConvertToString(fDetector->GetMeshNbOfCells()[2]);
}
else if(aCommand == fMeshSizeRhoCellsCmd)
{
cv = fMeshSizeRhoCellsCmd->ConvertToString(fDetector->GetMeshSizeOfCells()[0]);
}
else if(aCommand == fMeshSizeZCellsCmd)
{
cv = fMeshSizeZCellsCmd->ConvertToString(fDetector->GetMeshSizeOfCells()[2]);
}
return cv;
}
@@ -0,0 +1,203 @@
//
// ********************************************************************
// * 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 "Par04EventAction.hh"
#include <CLHEP/Units/SystemOfUnits.h> // for GeV
#include <CLHEP/Vector/ThreeVector.h> // for Hep3Vector
#include <stddef.h> // for size_t
#include <G4Exception.hh> // for G4Exception, G4ExceptionDesc...
#include <G4ExceptionSeverity.hh> // for FatalException
#include <G4GenericAnalysisManager.hh> // for G4GenericAnalysisManager
#include <G4PrimaryParticle.hh> // for G4PrimaryParticle
#include <G4PrimaryVertex.hh> // for G4PrimaryVertex
#include <G4SystemOfUnits.hh> // for GeV
#include <G4THitsCollection.hh> // for G4THitsCollection
#include <G4ThreeVector.hh> // for G4ThreeVector
#include <G4Timer.hh> // for G4Timer
#include <G4UserEventAction.hh> // for G4UserEventAction
#include <algorithm> // for max
#include <ostream> // for basic_ostream::operator<<
#include "G4AnalysisManager.hh" // for G4AnalysisManager
#include "G4Event.hh" // for G4Event
#include "G4EventManager.hh" // for G4EventManager
#include "G4HCofThisEvent.hh" // for G4HCofThisEvent
#include "G4SDManager.hh" // for G4SDManager
#include "Par04DetectorConstruction.hh" // for Par04DetectorConstruction
#include "Par04Hit.hh" // for Par04Hit, Par04HitsCollection
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
Par04EventAction::Par04EventAction(Par04DetectorConstruction* aDetector)
: G4UserEventAction()
, fHitCollectionID(-1)
, fTimer()
, fDetector(aDetector)
{
fCellNbRho = aDetector->GetMeshNbOfCells().x();
fCellNbPhi = aDetector->GetMeshNbOfCells().y();
fCellNbZ = aDetector->GetMeshNbOfCells().z();
fCalEdep.reserve(fCellNbRho * fCellNbPhi * fCellNbZ);
fCalRho.reserve(fCellNbRho * fCellNbPhi * fCellNbZ);
fCalPhi.reserve(fCellNbRho * fCellNbPhi * fCellNbZ);
fCalZ.reserve(fCellNbRho * fCellNbPhi * fCellNbZ);
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
Par04EventAction::~Par04EventAction() {}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void Par04EventAction::BeginOfEventAction(const G4Event*) { fTimer.Start(); }
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void Par04EventAction::EndOfEventAction(const G4Event* aEvent)
{
fTimer.Stop();
// Get hits collection ID (only once)
if(fHitCollectionID == -1)
{
fHitCollectionID = G4SDManager::GetSDMpointer()->GetCollectionID("hits");
}
// Get hits collection
auto hitsCollection =
static_cast<Par04HitsCollection*>(aEvent->GetHCofThisEvent()->GetHC(fHitCollectionID));
if(hitsCollection == nullptr)
{
G4ExceptionDescription msg;
msg << "Cannot access hitsCollection ID " << fHitCollectionID;
G4Exception("Par04EventAction::GetHitsCollection()", "MyCode0001", FatalException, msg);
}
// Get analysis manager
auto analysisManager = G4AnalysisManager::Instance();
// Retrieve only once detector dimensions
if(fCellSizeZ == 0)
{
fCellSizeZ = fDetector->GetMeshSizeOfCells().z();
fCellSizeRho = fDetector->GetMeshSizeOfCells().x();
fCellNbRho = fDetector->GetMeshNbOfCells().x();
fCellNbPhi = fDetector->GetMeshNbOfCells().y();
fCellNbZ = fDetector->GetMeshNbOfCells().z();
}
// Retrieve information from primary vertex and primary particle
// To calculate shower axis and entry point to the detector
auto primaryVertex =
G4EventManager::GetEventManager()->GetConstCurrentEvent()->GetPrimaryVertex();
auto primaryParticle = primaryVertex->GetPrimary(0);
G4double primaryEnergy = primaryParticle->GetTotalEnergy();
// Estimate from vertex and particle direction the entry point to the detector
// Calculate entrance point to the detector located at z = 0
auto primaryDirection = primaryParticle->GetMomentumDirection();
auto primaryEntrance =
primaryVertex->GetPosition() - primaryVertex->GetPosition().z() * primaryDirection;
// Resize back to initial mesh size
fCalEdep.resize(fCellNbRho * fCellNbPhi * fCellNbZ);
fCalRho.resize(fCellNbRho * fCellNbPhi * fCellNbZ);
fCalPhi.resize(fCellNbRho * fCellNbPhi * fCellNbZ);
fCalZ.resize(fCellNbRho * fCellNbPhi * fCellNbZ);
// Fill histograms
Par04Hit* hit = nullptr;
G4double hitEn = 0;
G4double totalEnergy = 0;
G4int hitZ = -1;
G4int hitRho = -1;
G4int hitPhi = -1;
G4int hitType = -1;
G4int numNonZeroThresholdCells = 0;
G4double tDistance = 0., rDistance = 0.;
G4double tFirstMoment = 0., tSecondMoment = 0.;
G4double rFirstMoment = 0., rSecondMoment = 0.;
for(size_t iHit = 0; iHit < hitsCollection->entries(); iHit++)
{
hit = static_cast<Par04Hit*>(hitsCollection->GetHit(iHit));
hitZ = hit->GetZid();
hitRho = hit->GetRhoId();
hitPhi = hit->GetPhiId();
hitEn = hit->GetEdep();
hitType = hit->GetType();
if(hitEn > 0)
{
totalEnergy += hitEn;
tDistance = hitZ * fCellSizeZ;
rDistance = hitRho * fCellSizeRho;
tFirstMoment += hitEn * tDistance;
rFirstMoment += hitEn * rDistance;
analysisManager->FillH1(4, tDistance, hitEn);
analysisManager->FillH1(5, rDistance, hitEn);
analysisManager->FillH1(10, hitType);
if(hitEn > 0.0005)
{ // e > 0.5 keV
fCalEdep[numNonZeroThresholdCells] = hitEn;
fCalRho[numNonZeroThresholdCells] = hitRho;
fCalPhi[numNonZeroThresholdCells] = hitPhi;
fCalZ[numNonZeroThresholdCells] = hitZ;
numNonZeroThresholdCells++;
}
}
}
tFirstMoment /= totalEnergy;
rFirstMoment /= totalEnergy;
analysisManager->FillH1(0, primaryEnergy / GeV);
analysisManager->FillH1(1, totalEnergy / GeV);
analysisManager->FillH1(2, totalEnergy / primaryEnergy);
analysisManager->FillH1(3, fTimer.GetRealElapsed());
analysisManager->FillH1(6, tFirstMoment);
analysisManager->FillH1(7, rFirstMoment);
// Resize to store only energy hits above threshold
fCalEdep.resize(numNonZeroThresholdCells);
fCalRho.resize(numNonZeroThresholdCells);
fCalPhi.resize(numNonZeroThresholdCells);
fCalZ.resize(numNonZeroThresholdCells);
analysisManager->FillNtupleDColumn(0, primaryEnergy);
analysisManager->FillNtupleDColumn(5, fTimer.GetRealElapsed());
// Second loop over hits to calculate second moments
for(size_t iHit = 0; iHit < hitsCollection->entries(); iHit++)
{
hit = static_cast<Par04Hit*>(hitsCollection->GetHit(iHit));
hitEn = hit->GetEdep();
hitZ = hit->GetZid();
hitRho = hit->GetRhoId();
if(hitEn > 0)
{
tDistance = hitZ * fCellSizeZ;
rDistance = hitRho * fCellSizeRho;
tSecondMoment += hitEn * std::pow(tDistance - tFirstMoment, 2);
rSecondMoment += hitEn * std::pow(rDistance - rFirstMoment, 2);
}
}
tSecondMoment /= totalEnergy;
rSecondMoment /= totalEnergy;
analysisManager->FillH1(8, tSecondMoment);
analysisManager->FillH1(9, rSecondMoment);
analysisManager->AddNtupleRow();
}
@@ -0,0 +1,50 @@
//
// ********************************************************************
// * 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 "Par04EventInformation.hh"
#include <CLHEP/Vector/ThreeVector.h> // for operator<<
#include <G4VUserEventInformation.hh> // for G4VUserEventInformation
#include <G4ios.hh> // for G4cout, G4endl
#include <ostream> // for operator<<, basic_ostream, ost...
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
Par04EventInformation::Par04EventInformation()
: G4VUserEventInformation()
, fDirection()
, fPosition()
{}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
Par04EventInformation::~Par04EventInformation() {}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void Par04EventInformation::Print() const
{
G4cout << "Event information\nPrimary particle direction = " << fDirection
<< "\nPrimary particle position = " << fPosition << G4endl;
}
@@ -0,0 +1,168 @@
//
// ********************************************************************
// * 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 "Par04Hit.hh"
#include <CLHEP/Units/SystemOfUnits.h> // for mm, pi, MeV, cm, rad
#include <CLHEP/Vector/ThreeVector.h> // for operator/, operator<<, Hep...
#include <G4RotationMatrix.hh> // for G4RotationMatrix
#include <G4String.hh> // for G4String
#include <G4ThreeVector.hh> // for G4ThreeVector
#include <G4Transform3D.hh> // for G4Transform3D
#include <G4VHit.hh> // for G4VHit
#include <algorithm> // for max
#include <iostream> // for operator<<, basic_ostream:...
#include <string> // for operator<
#include "G4AttDef.hh" // for G4AttDef
#include "G4AttDefStore.hh" // for GetInstance
#include "G4AttValue.hh" // for G4AttValue
#include "G4Colour.hh" // for G4Colour
#include "G4SystemOfUnits.hh" // for mm, MeV, cm, rad
#include "G4Tubs.hh" // for G4Tubs
#include "G4UnitsTable.hh" // for G4BestUnit
#include "G4VVisManager.hh" // for G4VVisManager
#include "G4VisAttributes.hh" // for G4VisAttributes
template <class Type> class G4Allocator;
G4ThreadLocal G4Allocator<Par04Hit>* Par04HitAllocator;
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
Par04Hit::Par04Hit()
: G4VHit()
{}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
Par04Hit::~Par04Hit() {}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
Par04Hit::Par04Hit(const Par04Hit& aRight)
: G4VHit()
{
fEdep = aRight.fEdep;
fZId = aRight.fZId;
fRhoId = aRight.fRhoId;
fPhiId = aRight.fPhiId;
fTime = aRight.fTime;
fPos = aRight.fPos;
fRot = aRight.fRot;
fType = aRight.fType;
fLogVol = aRight.fLogVol;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
const Par04Hit& Par04Hit::operator=(const Par04Hit& aRight)
{
fEdep = aRight.fEdep;
fZId = aRight.fZId;
fRhoId = aRight.fRhoId;
fPhiId = aRight.fPhiId;
fTime = aRight.fTime;
fPos = aRight.fPos;
fRot = aRight.fRot;
fType = aRight.fType;
fLogVol = aRight.fLogVol;
return *this;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
int Par04Hit::operator==(const Par04Hit& aRight) const
{
return (fRhoId == aRight.fRhoId && fPhiId == aRight.fPhiId && fZId == aRight.fZId);
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void Par04Hit::Draw()
{
/// TOFIX do not hardcode size
G4ThreeVector meshSize(2.325 * mm, 2 * CLHEP::pi / 50. * CLHEP::rad, 3.4 * mm);
G4int numPhiCells = CLHEP::pi * 2. / meshSize.y();
G4VVisManager* pVVisManager = G4VVisManager::GetConcreteInstance();
// Hits can be filtered out in visualisation
if(!pVVisManager->FilterHit(*this))
return;
// Do not draw empty hits
if(fEdep <= 0)
return;
// Do not plot if default values were not changed
if(fRhoId == -1 && fZId == -1 && fPhiId == -1)
return;
if(pVVisManager)
{
G4Transform3D trans(fRot, fPos);
G4VisAttributes attribs;
G4Tubs solid("draw", fRhoId * meshSize.x(), (fRhoId + 1) * meshSize.x(), meshSize.z() / 2.,
(-numPhiCells / 2. + fPhiId) * meshSize.y(), meshSize.y());
// Set colours depending on type of hit (full/fast sim)
G4double colR = fType == 0 ? 0 : 1;
G4double colG = fType == 0 ? 1 : 0;
G4double colB = 0;
G4Colour colour(colR, colG, colB, 0.5);
attribs.SetColour(colour);
attribs.SetForceSolid(true);
pVVisManager->Draw(solid, attribs, trans);
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
const std::map<G4String, G4AttDef>* Par04Hit::GetAttDefs() const
{
G4bool isNew;
std::map<G4String, G4AttDef>* store = G4AttDefStore::GetInstance("Par04Hit", isNew);
if(isNew)
{
(*store)["HitType"] = G4AttDef("HitType", "Hit Type", "Physics", "", "G4String");
(*store)["Energy"] =
G4AttDef("Energy", "Energy Deposited", "Physics", "G4BestUnit", "G4double");
(*store)["Time"] = G4AttDef("Time", "Time", "Physics", "G4BestUnit", "G4double");
(*store)["Pos"] = G4AttDef("Pos", "Position", "Physics", "G4BestUnit", "G4ThreeVector");
}
return store;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
std::vector<G4AttValue>* Par04Hit::CreateAttValues() const
{
std::vector<G4AttValue>* values = new std::vector<G4AttValue>;
values->push_back(G4AttValue("HitType", "HadPar04Hit", ""));
values->push_back(G4AttValue("Energy", G4BestUnit(fEdep, "Energy"), ""));
values->push_back(G4AttValue("Time", G4BestUnit(fTime, "Time"), ""));
values->push_back(G4AttValue("Pos", G4BestUnit(fPos, "Length"), ""));
return values;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void Par04Hit::Print()
{
std::cout << "\tHit " << fEdep / MeV << " MeV at " << fPos / cm << " cm (R,phi,z)= (" << fRhoId
<< ", " << fPhiId << ", " << fZId << "), " << fTime << " ns" << std::endl;
}
@@ -0,0 +1,249 @@
//
// ********************************************************************
// * 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. *
// ********************************************************************
//
#ifdef USE_INFERENCE
#include "Par04InferenceMessenger.hh"
#include "Par04InferenceSetup.hh"
#include "G4UIdirectory.hh"
#include "G4UIcmdWithoutParameter.hh"
#include "G4UIcmdWithAnInteger.hh"
#include "G4UIcmdWithADoubleAndUnit.hh"
#include "G4UIcmdWithAString.hh"
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
Par04InferenceMessenger::Par04InferenceMessenger(Par04InferenceSetup* aInference)
: G4UImessenger()
, fInference(aInference)
{
fExampleDir = new G4UIdirectory("/Par04/");
fExampleDir->SetGuidance("UI commands specific to this example");
fInferenceDir = new G4UIdirectory("/Par04/inference/");
fInferenceDir->SetGuidance("Inference construction UI commands");
fInferenceLibraryCmd = new G4UIcmdWithAString("/Par04/inference/setInferenceLibrary", this);
fInferenceLibraryCmd->SetGuidance("Inference library.");
fInferenceLibraryCmd->SetParameterName("InferenceLibrary", false);
fInferenceLibraryCmd->AvailableForStates(G4State_Idle);
fInferenceLibraryCmd->SetToBeBroadcasted(true);
fSizeLatentVectorCmd = new G4UIcmdWithAnInteger("/Par04/inference/setSizeLatentVector", this);
fSizeLatentVectorCmd->SetGuidance("Set size of the latent space vector.");
fSizeLatentVectorCmd->SetParameterName("SizeLatentVector", false);
fSizeLatentVectorCmd->SetRange("SizeLatentVector>0");
fSizeLatentVectorCmd->AvailableForStates(G4State_Idle);
fSizeLatentVectorCmd->SetToBeBroadcasted(true);
fSizeConditionVectorCmd =
new G4UIcmdWithAnInteger("/Par04/inference/setSizeConditionVector", this);
fSizeConditionVectorCmd->SetGuidance("Set size of the condition vector.");
fSizeConditionVectorCmd->SetParameterName("SizeConditionVector", false);
fSizeConditionVectorCmd->SetRange("SizeConditionVector>0");
fSizeConditionVectorCmd->AvailableForStates(G4State_Idle);
fSizeConditionVectorCmd->SetToBeBroadcasted(true);
fModelPathNameCmd = new G4UIcmdWithAString("/Par04/inference/setModelPathName", this);
fModelPathNameCmd->SetGuidance("Model path and name.");
fModelPathNameCmd->SetParameterName("Name", false);
fModelPathNameCmd->AvailableForStates(G4State_Idle);
fModelPathNameCmd->SetToBeBroadcasted(true);
fProfileFlagCmd = new G4UIcmdWithAnInteger("/Par04/inference/setProfileFlag", this);
fProfileFlagCmd->SetGuidance("Flag to save a json file for model execution profiling.");
fProfileFlagCmd->SetParameterName("ProfileFlag", false);
fProfileFlagCmd->SetRange("ProfileFlag>-1");
fProfileFlagCmd->AvailableForStates(G4State_Idle);
fProfileFlagCmd->SetToBeBroadcasted(true);
fOptimizationFlagCmd = new G4UIcmdWithAnInteger("/Par04/inference/setOptimizationFlag", this);
fOptimizationFlagCmd->SetGuidance("Set optimization flag");
fOptimizationFlagCmd->SetParameterName("OptimizationFlag", false);
fOptimizationFlagCmd->SetRange("OptimizationFlag>-1");
fOptimizationFlagCmd->AvailableForStates(G4State_Idle);
fOptimizationFlagCmd->SetToBeBroadcasted(true);
fMeshNbRhoCellsCmd = new G4UIcmdWithAnInteger("/Par04/inference/setNbOfRhoCells", this);
fMeshNbRhoCellsCmd->SetGuidance("Set number of rho cells in the cylindrical mesh readout.");
fMeshNbRhoCellsCmd->SetParameterName("NbRhoCells", false);
fMeshNbRhoCellsCmd->SetRange("NbRhoCells>0");
fMeshNbRhoCellsCmd->AvailableForStates(G4State_Idle);
fMeshNbRhoCellsCmd->SetToBeBroadcasted(true);
fMeshNbPhiCellsCmd = new G4UIcmdWithAnInteger("/Par04/inference/setNbOfPhiCells", this);
fMeshNbPhiCellsCmd->SetGuidance("Set number of phi cells in the cylindrical mesh readout.");
fMeshNbPhiCellsCmd->SetParameterName("NbPhiCells", false);
fMeshNbPhiCellsCmd->SetRange("NbPhiCells>0");
fMeshNbPhiCellsCmd->AvailableForStates(G4State_Idle);
fMeshNbPhiCellsCmd->SetToBeBroadcasted(true);
fMeshNbZCellsCmd = new G4UIcmdWithAnInteger("/Par04/inference/setNbOfZCells", this);
fMeshNbZCellsCmd->SetGuidance("Set number of z cells in the cylindrical mesh readout.");
fMeshNbZCellsCmd->SetParameterName("NbZCells", false);
fMeshNbZCellsCmd->SetRange("NbZCells>0");
fMeshNbZCellsCmd->AvailableForStates(G4State_Idle);
fMeshNbZCellsCmd->SetToBeBroadcasted(true);
fMeshSizeRhoCellsCmd = new G4UIcmdWithADoubleAndUnit("/Par04/inference/setSizeOfRhoCells", this);
fMeshSizeRhoCellsCmd->SetGuidance("Set size of rho cells in the cylindrical readout mesh");
fMeshSizeRhoCellsCmd->SetParameterName("Size", false);
fMeshSizeRhoCellsCmd->SetRange("Size>0.");
fMeshSizeRhoCellsCmd->SetUnitCategory("Length");
fMeshSizeRhoCellsCmd->AvailableForStates(G4State_Idle);
fMeshSizeRhoCellsCmd->SetToBeBroadcasted(true);
fMeshSizeZCellsCmd = new G4UIcmdWithADoubleAndUnit("/Par04/inference/setSizeOfZCells", this);
fMeshSizeZCellsCmd->SetGuidance("Set size of z cells in the cylindrical readout mesh");
fMeshSizeZCellsCmd->SetParameterName("Size", false);
fMeshSizeZCellsCmd->SetRange("Size>0.");
fMeshSizeZCellsCmd->SetUnitCategory("Length");
fMeshSizeZCellsCmd->AvailableForStates(G4State_Idle);
fMeshSizeZCellsCmd->SetToBeBroadcasted(true);
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
Par04InferenceMessenger::~Par04InferenceMessenger()
{
delete fInferenceLibraryCmd;
delete fSizeLatentVectorCmd;
delete fSizeConditionVectorCmd;
delete fModelPathNameCmd;
delete fProfileFlagCmd;
delete fOptimizationFlagCmd;
delete fMeshNbRhoCellsCmd;
delete fMeshNbPhiCellsCmd;
delete fMeshNbZCellsCmd;
delete fMeshSizeRhoCellsCmd;
delete fMeshSizeZCellsCmd;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void Par04InferenceMessenger::SetNewValue(G4UIcommand* aCommand, G4String aNewValue)
{
if(aCommand == fInferenceLibraryCmd)
{
fInference->SetInferenceLibrary(aNewValue);
}
if(aCommand == fSizeLatentVectorCmd)
{
fInference->SetSizeLatentVector(std::stoi(aNewValue));
}
if(aCommand == fSizeConditionVectorCmd)
{
fInference->SetSizeConditionVector(std::stoi(aNewValue));
}
if(aCommand == fModelPathNameCmd)
{
fInference->SetModelPathName(aNewValue);
}
if(aCommand == fProfileFlagCmd)
{
fInference->SetProfileFlag(std::stoi(aNewValue));
}
if(aCommand == fOptimizationFlagCmd)
{
fInference->SetOptimizationFlag(std::stoi(aNewValue));
}
else if(aCommand == fMeshNbRhoCellsCmd)
{
fInference->SetMeshNbOfCells(0, fMeshNbRhoCellsCmd->GetNewIntValue(aNewValue));
}
else if(aCommand == fMeshNbPhiCellsCmd)
{
fInference->SetMeshNbOfCells(1, fMeshNbPhiCellsCmd->GetNewIntValue(aNewValue));
fInference->SetMeshSizeOfCells(1,
2. * CLHEP::pi / fMeshNbPhiCellsCmd->GetNewIntValue(aNewValue));
}
else if(aCommand == fMeshNbZCellsCmd)
{
fInference->SetMeshNbOfCells(2, fMeshNbZCellsCmd->GetNewIntValue(aNewValue));
}
else if(aCommand == fMeshSizeRhoCellsCmd)
{
fInference->SetMeshSizeOfCells(0, fMeshSizeRhoCellsCmd->GetNewDoubleValue(aNewValue));
}
else if(aCommand == fMeshSizeZCellsCmd)
{
fInference->SetMeshSizeOfCells(2, fMeshSizeZCellsCmd->GetNewDoubleValue(aNewValue));
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4String Par04InferenceMessenger::GetCurrentValue(G4UIcommand* aCommand)
{
G4String cv;
if(aCommand == fInferenceLibraryCmd)
{
cv = fInferenceLibraryCmd->ConvertToString(fInference->GetInferenceLibrary());
}
if(aCommand == fSizeLatentVectorCmd)
{
cv = fSizeLatentVectorCmd->ConvertToString(fInference->GetSizeLatentVector());
}
if(aCommand == fSizeConditionVectorCmd)
{
cv = fSizeConditionVectorCmd->ConvertToString(fInference->GetSizeConditionVector());
}
if(aCommand == fModelPathNameCmd)
{
cv = fModelPathNameCmd->ConvertToString(fInference->GetModelPathName());
}
if(aCommand == fProfileFlagCmd)
{
cv = fSizeLatentVectorCmd->ConvertToString(fInference->GetProfileFlag());
}
if(aCommand == fOptimizationFlagCmd)
{
cv = fSizeLatentVectorCmd->ConvertToString(fInference->GetOptimizationFlag());
}
else if(aCommand == fMeshNbRhoCellsCmd)
{
cv = fMeshNbRhoCellsCmd->ConvertToString(fInference->GetMeshNbOfCells()[0]);
}
else if(aCommand == fMeshNbPhiCellsCmd)
{
cv = fMeshNbPhiCellsCmd->ConvertToString(fInference->GetMeshNbOfCells()[1]);
}
else if(aCommand == fMeshNbZCellsCmd)
{
cv = fMeshNbZCellsCmd->ConvertToString(fInference->GetMeshNbOfCells()[2]);
}
else if(aCommand == fMeshSizeRhoCellsCmd)
{
cv = fMeshSizeRhoCellsCmd->ConvertToString(fInference->GetMeshSizeOfCells()[0]);
}
else if(aCommand == fMeshSizeZCellsCmd)
{
cv = fMeshSizeZCellsCmd->ConvertToString(fInference->GetMeshSizeOfCells()[2]);
}
return cv;
}
#endif
@@ -0,0 +1,176 @@
//
// ********************************************************************
// * 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. *
// ********************************************************************
//
#ifdef USE_INFERENCE
#include "Par04InferenceSetup.hh"
#include "Par04InferenceInterface.hh"
#ifdef USE_INFERENCE_ONNX
#include "Par04OnnxInference.hh"
#endif
#ifdef USE_INFERENCE_LWTNN
#include "Par04LwtnnInference.hh"
#endif
#include "G4RotationMatrix.hh"
#include "CLHEP/Random/RandGauss.h"
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
Par04InferenceSetup::Par04InferenceSetup()
: fInferenceMessenger(new Par04InferenceMessenger(this))
{}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
Par04InferenceSetup::~Par04InferenceSetup() {}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4bool Par04InferenceSetup::IfTrigger(G4double aEnergy)
{
/// Energy of electrons used in training dataset
if(aEnergy > 1 * CLHEP::GeV || aEnergy < 1024 * CLHEP::GeV)
return true;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void Par04InferenceSetup::SetInferenceLibrary(G4String aName)
{
fInferenceLibrary = aName;
#ifdef USE_INFERENCE_ONNX
if(fInferenceLibrary == "ONNX")
fInferenceInterface = std::unique_ptr<Par04InferenceInterface>(
new Par04OnnxInference(fModelPathName, fProfileFlag, fOptimizationFlag, fIntraOpNumThreads));
#endif
#ifdef USE_INFERENCE_LWTNN
if(fInferenceLibrary == "LWTNN")
fInferenceInterface =
std::unique_ptr<Par04InferenceInterface>(new Par04LwtnnInference(fModelPathName));
#endif
CheckInferenceLibrary();
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void Par04InferenceSetup::CheckInferenceLibrary()
{
G4String msg = "Please choose inference library from available libraries (";
#ifdef USE_INFERENCE_ONNX
msg += "ONNX,";
#endif
#ifdef USE_INFERENCE_LWTNN
msg += "LWTNN";
#endif
if(fInferenceInterface == nullptr)
G4Exception("Par04InferenceSetup::CheckInferenceLibrary()", "InvalidSetup", FatalException,
(msg + "). Current name: " + fInferenceLibrary).c_str());
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void Par04InferenceSetup::GetEnergies(std::vector<G4double>& aEnergies, G4double aInitialEnergy,
G4float aInitialAngle)
{
// First check if inference library was set correctly
CheckInferenceLibrary();
// size represents the size of the output vector
int size = fMeshNumber.x() * fMeshNumber.y() * fMeshNumber.z();
// randomly sample from a gaussian distribution in the latent space
std::vector<G4float> genVector(fSizeLatentVector + fSizeConditionVector, 0);
for(int i = 0; i < fSizeLatentVector; ++i)
{
genVector[i] = CLHEP::RandGauss::shoot(0., 1.);
}
// Vector of condition
// this is application specific it depdens on what the model was condition on
// and it depends on how the condition values were encoded at the training time
// in this example the energy of each particle is normlaized to the highest
// energy in the considered range (1GeV-500GeV)
// the angle is also is normlaized to the highest angle in the considered range
// (0-90 in dergrees)
// the model in this example was trained on two detector geometries PBW04
// and SiW a one hot encoding vector is used to represent the geometry with
// [0,1] for PBW04 and [1,0] for SiW
// 1.energy
genVector[fSizeLatentVector] = aInitialEnergy / fMaxEnergy;
// 2. angle
genVector[fSizeLatentVector + 1] = (aInitialAngle / (CLHEP::deg)) / fMaxAngle;
// 3.geometry
genVector[fSizeLatentVector + 2] = 0;
genVector[fSizeLatentVector + 3] = 1;
// Run the inference
fInferenceInterface->RunInference(genVector, aEnergies, size);
// After the inference rescale back to the initial energy (in this example the
// energies of cells were normalized to the energy of the particle)
for(int i = 0; i < size; ++i)
{
aEnergies[i] = aEnergies[i] * aInitialEnergy;
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void Par04InferenceSetup::GetPositions(std::vector<G4ThreeVector>& aPositions, G4ThreeVector pos0,
G4ThreeVector direction)
{
aPositions.resize(fMeshNumber.x() * fMeshNumber.y() * fMeshNumber.z());
// Calculate rotation matrix along the particle momentum direction
// It will rotate the shower axes to match the incoming particle direction
G4RotationMatrix rotMatrix = G4RotationMatrix();
double particleTheta = direction.theta();
double particlePhi = direction.phi();
rotMatrix.rotateZ(-particlePhi);
rotMatrix.rotateY(-particleTheta);
G4RotationMatrix rotMatrixInv = CLHEP::inverseOf(rotMatrix);
int cpt = 0;
for(G4int iCellR = 0; iCellR < fMeshNumber.x(); iCellR++)
{
for(G4int iCellPhi = 0; iCellPhi < fMeshNumber.y(); iCellPhi++)
{
for(G4int iCellZ = 0; iCellZ < fMeshNumber.z(); iCellZ++)
{
aPositions[cpt] =
pos0 +
rotMatrixInv *
G4ThreeVector((iCellR + 0.5) * fMeshSize.x() *
std::cos((iCellPhi + 0.5) * 2 * CLHEP::pi / fMeshNumber.y() - CLHEP::pi),
(iCellR + 0.5) * fMeshSize.x() *
std::sin((iCellPhi + 0.5) * 2 * CLHEP::pi / fMeshNumber.y() - CLHEP::pi),
(iCellZ + 0.5) * fMeshSize.z());
cpt++;
}
}
}
}
#endif
@@ -0,0 +1,61 @@
//
// ********************************************************************
// * 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. *
// ********************************************************************
//
#ifdef USE_INFERENCE_LWTNN
#include "Par04InferenceInterface.hh"
#include "Par04LwtnnInference.hh"
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
Par04LwtnnInference::Par04LwtnnInference(G4String modelPath)
: Par04InferenceInterface()
{
// file to read
std::ifstream input(modelPath);
// build the graph
fGraph = std::make_unique<lwt::LightweightGraph>(lwt::parse_json_graph(input));
input.close();
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void Par04LwtnnInference::RunInference(vector<float> aGenVector, std::vector<G4double>& aEnergies,
int aSize)
{
// generation vector
fNetworkInputs inputs;
for(int i = 0; i < (unsigned) (aGenVector.size()); ++i)
{
inputs["node_0"]["variable_" + std::to_string(i)] = aGenVector[i];
}
// run the inference
fNetworkOutputs outputs = fGraph->compute(inputs);
aEnergies.assign(aSize, 0);
for(int i = 0; i < aSize; i++)
aEnergies[i] = outputs["out_" + std::to_string(i)];
}
#endif
@@ -0,0 +1,101 @@
//
// ********************************************************************
// * 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. *
// ********************************************************************
//
#ifdef USE_INFERENCE
#include "Par04MLFastSimModel.hh"
#include "G4Electron.hh"
#include "G4Positron.hh"
#include "G4Gamma.hh"
#include "G4SystemOfUnits.hh"
#include "G4UnitsTable.hh"
#include "G4FastHit.hh"
#include "G4FastSimHitMaker.hh"
#include "Randomize.hh"
#include "CLHEP/Units/SystemOfUnits.h"
#include <numeric>
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
Par04MLFastSimModel::Par04MLFastSimModel(G4String aModelName, G4Region* aEnvelope)
: G4VFastSimulationModel(aModelName, aEnvelope)
, fInference(new Par04InferenceSetup)
, fHitMaker(new G4FastSimHitMaker)
{}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
Par04MLFastSimModel::Par04MLFastSimModel(G4String aModelName)
: G4VFastSimulationModel(aModelName)
, fInference(new Par04InferenceSetup)
, fHitMaker(new G4FastSimHitMaker)
{}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
Par04MLFastSimModel::~Par04MLFastSimModel() {}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4bool Par04MLFastSimModel::IsApplicable(const G4ParticleDefinition& aParticleType)
{
return &aParticleType == G4Electron::ElectronDefinition() ||
&aParticleType == G4Positron::PositronDefinition() ||
&aParticleType == G4Gamma::GammaDefinition();
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4bool Par04MLFastSimModel::ModelTrigger(const G4FastTrack& aFastTrack)
{
return fInference->IfTrigger(aFastTrack.GetPrimaryTrack()->GetKineticEnergy());
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void Par04MLFastSimModel::DoIt(const G4FastTrack& aFastTrack, G4FastStep& aFastStep)
{
// remove particle from further processing by G4
aFastStep.KillPrimaryTrack();
aFastStep.SetPrimaryTrackPathLength(0.0);
G4double energy = aFastTrack.GetPrimaryTrack()->GetKineticEnergy();
aFastStep.SetTotalEnergyDeposited(energy);
G4ThreeVector position = aFastTrack.GetPrimaryTrack()->GetPosition();
G4ThreeVector direction = aFastTrack.GetPrimaryTrack()->GetMomentumDirection();
// calculate the incident angle
G4float angle = direction.theta();
// calculate how to deposit energy within the detector
// get it from inference model
fInference->GetEnergies(fEnergies, energy, angle);
fInference->GetPositions(fPositions, position, direction);
// deposit energy in the detector using calculated values of energy deposits
// and positions
for(size_t iHit = 0; iHit < fPositions.size(); iHit++)
{
fHitMaker->make(G4FastHit(fPositions[iHit], fEnergies[iHit]), aFastTrack);
}
}
#endif
@@ -0,0 +1,128 @@
//
// ********************************************************************
// * 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. *
// ********************************************************************
//
#ifdef USE_INFERENCE_ONNX
#include "Par04InferenceInterface.hh"
#include "G4RotationMatrix.hh"
#include "Par04OnnxInference.hh"
#include <cassert>
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
Par04OnnxInference::Par04OnnxInference(G4String modelPath, G4int profileFlag, G4int optimizeFlag,
G4int intraOpNumThreads)
: Par04InferenceInterface()
{
// initialization of the enviroment and inference session
auto envLocal = std::make_unique<Ort::Env>(ORT_LOGGING_LEVEL_WARNING, "ENV");
fEnv = std::move(envLocal);
fSessionOptions.SetIntraOpNumThreads(intraOpNumThreads);
// graph optimizations of the model
// if the flag is not set to true none of the optimizations will be applied
// if it is set to true all the optimizations will be applied
if(optimizeFlag)
{
fSessionOptions.SetOptimizedModelFilePath("opt-graph");
fSessionOptions.SetGraphOptimizationLevel(ORT_ENABLE_ALL);
// ORT_ENABLE_BASIC #### ORT_ENABLE_EXTENDED
}
else
fSessionOptions.SetGraphOptimizationLevel(ORT_DISABLE_ALL);
// save json file for model execution profiling
if(profileFlag)
fSessionOptions.EnableProfiling("opt.json");
auto sessionLocal = std::make_unique<Ort::Session>(*fEnv, modelPath, fSessionOptions);
fSession = std::move(sessionLocal);
fInfo = Ort::MemoryInfo::CreateCpu(OrtAllocatorType::OrtArenaAllocator, OrtMemTypeDefault);
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void Par04OnnxInference::RunInference(vector<float> aGenVector, std::vector<G4double>& aEnergies,
int aSize)
{
// input nodes
Ort::AllocatorWithDefaultOptions allocator;
std::vector<int64_t> input_node_dims;
size_t num_input_nodes = fSession->GetInputCount();
std::vector<const char*> input_node_names(num_input_nodes);
for(std::size_t i = 0; i < num_input_nodes; i++)
{
char* input_name = fSession->GetInputName(i, allocator);
fInames = { input_name };
input_node_names[i] = input_name;
Ort::TypeInfo type_info = fSession->GetInputTypeInfo(i);
auto tensor_info = type_info.GetTensorTypeAndShapeInfo();
ONNXTensorElementDataType type = tensor_info.GetElementType();
input_node_dims = tensor_info.GetShape();
for(int j = 0; j < input_node_dims.size(); j++)
{
if(input_node_dims[j] < 0)
input_node_dims[j] = 1;
}
}
// output nodes
std::vector<int64_t> output_node_dims;
size_t num_output_nodes = fSession->GetOutputCount();
std::vector<const char*> output_node_names(num_output_nodes);
for(std::size_t i = 0; i < num_output_nodes; i++)
{
char* output_name = fSession->GetOutputName(i, allocator);
output_node_names[i] = output_name;
Ort::TypeInfo type_info = fSession->GetOutputTypeInfo(i);
auto tensor_info = type_info.GetTensorTypeAndShapeInfo();
ONNXTensorElementDataType type = tensor_info.GetElementType();
output_node_dims = tensor_info.GetShape();
for(int j = 0; j < output_node_dims.size(); j++)
{
if(output_node_dims[j] < 0)
output_node_dims[j] = 1;
}
}
// create input tensor object from data values
float genVector[(unsigned) (aGenVector.size())];
for(int i = 0; i < (unsigned) (aGenVector.size()); i++)
genVector[i] = aGenVector[i];
int values_length = sizeof(genVector) / sizeof(genVector[0]);
std::vector<int64_t> dims = { 1, (unsigned) (aGenVector.size()) };
Ort::Value Input_noise_tensor =
Ort::Value::CreateTensor<float>(fInfo, genVector, values_length, dims.data(), dims.size());
assert(Input_noise_tensor.IsTensor());
std::vector<Ort::Value> ort_inputs;
ort_inputs.push_back(std::move(Input_noise_tensor));
// run the inference session
std::vector<Ort::Value> ort_outputs =
fSession->Run(Ort::RunOptions{ nullptr }, fInames.data(), ort_inputs.data(), ort_inputs.size(),
output_node_names.data(), output_node_names.size());
// get pointer to output tensor float values
float* floatarr = ort_outputs.front().GetTensorMutableData<float>();
aEnergies.assign(aSize, 0);
for(int i = 0; i < aSize; ++i)
aEnergies[i] = floatarr[i];
}
#endif
@@ -0,0 +1,67 @@
//
// ********************************************************************
// * 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 "Par04PrimaryGeneratorAction.hh"
#include <CLHEP/Units/SystemOfUnits.h> // for GeV
#include <G4String.hh> // for G4String
#include <G4ThreeVector.hh> // for G4ThreeVector
#include <G4Types.hh> // for G4int
#include <G4VUserPrimaryGeneratorAction.hh> // for G4VUserPrimaryGeneratorA...
#include <string> // for basic_string
#include "G4Event.hh" // for G4Event
#include "G4ParticleGun.hh" // for G4ParticleGun
#include "G4ParticleTable.hh" // for G4ParticleTable
#include "G4SystemOfUnits.hh" // for GeV
#include "Par04EventInformation.hh" // for Par04EventInformation
class G4ParticleDefinition;
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
Par04PrimaryGeneratorAction::Par04PrimaryGeneratorAction()
: G4VUserPrimaryGeneratorAction()
{
G4int n_particle = 1;
fParticleGun = new G4ParticleGun(n_particle);
// Default particle properties
G4ParticleTable* particleTable = G4ParticleTable::GetParticleTable();
G4String particleName;
G4ParticleDefinition* particle = particleTable->FindParticle(particleName = "e-");
fParticleGun->SetParticleDefinition(particle);
fParticleGun->SetParticleMomentumDirection(G4ThreeVector(0., 1., 0.));
fParticleGun->SetParticleEnergy(10. * GeV);
fParticleGun->SetParticlePosition(G4ThreeVector(0., 0., 0.));
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
Par04PrimaryGeneratorAction::~Par04PrimaryGeneratorAction() { delete fParticleGun; }
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void Par04PrimaryGeneratorAction::GeneratePrimaries(G4Event* aEvent)
{
fParticleGun->GeneratePrimaryVertex(aEvent);
aEvent->SetUserInformation(new Par04EventInformation());
}
@@ -0,0 +1,125 @@
//
// ********************************************************************
// * 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 "Par04RunAction.hh"
#include <G4GenericAnalysisManager.hh> // for G4GenericAnalysisManager
#include <G4ThreeVector.hh> // for G4ThreeVector
#include <G4Types.hh> // for G4int, G4double
#include <G4UserRunAction.hh> // for G4UserRunAction
#include "G4AnalysisManager.hh" // for G4AnalysisManager
#include "Par04DetectorConstruction.hh" // for Par04DetectorConstruction
#include "Par04EventAction.hh" // for Par04EventAction
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
Par04RunAction::Par04RunAction(Par04DetectorConstruction* aDetector, Par04EventAction* aEventAction)
: G4UserRunAction()
, fDetector(aDetector)
, fEventAction(aEventAction)
{
// Create analysis manager
G4AnalysisManager* analysisManager = G4AnalysisManager::Instance();
analysisManager->SetDefaultFileType("root");
// Default filename, can be overriden with /analysis/setFileName
analysisManager->SetFileName("Par04Output");
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
Par04RunAction::~Par04RunAction() {}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void Par04RunAction::BeginOfRunAction(const G4Run*)
{
// Get analysis manager
G4AnalysisManager* analysisManager = G4AnalysisManager::Instance();
// Create directories
analysisManager->SetNtupleMerging(false);
analysisManager->SetVerboseLevel(0);
// Get detector dimensions
G4int cellNumZ = fDetector->GetMeshNbOfCells().z();
G4int cellNumRho = fDetector->GetMeshNbOfCells().x();
G4double cellSizeZ = fDetector->GetMeshSizeOfCells().z();
G4double cellSizeRho = fDetector->GetMeshSizeOfCells().x();
// Default max value of energy stored in histogram (in GeV)
G4double maxEnergy = 1000;
// Creating control histograms
analysisManager->CreateH1("energyParticle", "Primary energy;E_{MC} (GeV);Entries", 1024, 0,
1.1 * maxEnergy);
analysisManager->CreateH1("energyDeposited", "Deposited energy;E_{MC} (GeV);Entries", 1024, 0,
1.1 * maxEnergy);
analysisManager->CreateH1(
"energyRatio", "Ratio of energy deposited to primary;E_{dep} / E_{MC};Entries", 1024, 0, 1);
analysisManager->CreateH1("time", "Simulation time; time (s);Entries", 2048, 0, 100);
analysisManager->CreateH1("longProfile", "Longitudinal profile;t (mm);#LTE#GT (MeV)", cellNumZ,
-0.5 * cellSizeZ, (cellNumZ - 0.5) * cellSizeZ);
analysisManager->CreateH1("transProfile", "Transverse profile;r (mm);#LTE#GT (MeV)", cellNumRho,
-0.5 * cellSizeRho, (cellNumRho - 0.5) * cellSizeRho);
analysisManager->CreateH1("longFirstMoment",
"First moment of longitudinal distribution;#LT#lambda#GT (mm);Entries",
1024, -0.5 * cellSizeZ,
cellNumZ * cellSizeZ / 2); // arbitrary scaling of max value on axis
analysisManager->CreateH1("transFirstMoment",
"First moment of transverse distribution;#LTr#GT "
"(mm);Entries",
1024, -0.5 * cellSizeRho,
cellNumRho * cellSizeRho /
1); // arbitrary scaling of max value on axis
analysisManager->CreateH1(
"longSecondMoment",
"Second moment of longitudinal distribution;#LT#lambda^{2}#GT "
"(mm^{2});Entries",
1024, 0, std::pow(cellNumZ * cellSizeZ, 2) / 25); // arbitrary scaling of max value on axis
analysisManager->CreateH1(
"transSecondMoment", "Second moment of transverse distribution;#LTr^{2}#GT (mm^{2});Entries",
1024, 0, std::pow(cellNumRho * cellSizeRho, 2) / 5); // arbitrary scaling of max value on axis
analysisManager->CreateH1("hitType", "hit type;type (0=full, 1= fast);Entries", 2, -0.5, 1.5);
// Creating ntuple
analysisManager->CreateNtuple("events", "per event data");
analysisManager->CreateNtupleDColumn("EnergyMC");
analysisManager->CreateNtupleDColumn("EnergyCell", fEventAction->GetCalEdep());
analysisManager->CreateNtupleIColumn("rhoCell", fEventAction->GetCalRho());
analysisManager->CreateNtupleIColumn("phiCell", fEventAction->GetCalPhi());
analysisManager->CreateNtupleIColumn("zCell", fEventAction->GetCalZ());
analysisManager->CreateNtupleDColumn("SimTime");
analysisManager->FinishNtuple();
analysisManager->OpenFile();
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void Par04RunAction::EndOfRunAction(const G4Run*)
{
auto analysisManager = G4AnalysisManager::Instance();
analysisManager->Write();
analysisManager->CloseFile();
}
@@ -0,0 +1,206 @@
//
// ********************************************************************
// * 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 "Par04SensitiveDetector.hh"
#include <CLHEP/Vector/Rotation.h> // for HepRotation
#include <CLHEP/Vector/ThreeVector.h> // for Hep3Vector
#include <cmath> // for floor
#include <G4CollectionNameVector.hh> // for G4CollectionNameVector
#include <G4FastHit.hh> // for G4FastHit
#include <G4FastTrack.hh> // for G4FastTrack
#include <G4RotationMatrix.hh> // for G4RotationMatrix
#include <G4StepPoint.hh> // for G4StepPoint
#include <G4THitsCollection.hh> // for G4THitsCollection
#include <G4ThreeVector.hh> // for G4ThreeVector
#include <G4VSensitiveDetector.hh> // for G4VSensitiveDetector
#include <G4VUserEventInformation.hh> // for G4VUserEventInformation
#include <cstddef> // for size_t
#include <vector> // for vector
#include "G4Event.hh" // for G4Event
#include "G4EventManager.hh" // for G4EventManager
#include "G4HCofThisEvent.hh" // for G4HCofThisEvent
#include "G4SDManager.hh" // for G4SDManager
#include "G4Step.hh" // for G4Step
#include "G4Track.hh" // for G4Track
#include "Par04EventInformation.hh" // for Par04EventInformation
#include "Par04Hit.hh" // for Par04Hit, Par04HitsCollection
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
Par04SensitiveDetector::Par04SensitiveDetector(G4String aName)
: G4VSensitiveDetector(aName)
{
collectionName.insert("hits");
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
Par04SensitiveDetector::Par04SensitiveDetector(G4String aName, G4ThreeVector aNb,
G4ThreeVector aSize)
: G4VSensitiveDetector(aName)
, fMeshNbOfCells(aNb)
, fMeshSizeOfCells(aSize)
{
collectionName.insert("hits");
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
Par04SensitiveDetector::~Par04SensitiveDetector() {}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void Par04SensitiveDetector::Initialize(G4HCofThisEvent* aHCE)
{
fHitsCollection = new Par04HitsCollection(SensitiveDetectorName, collectionName[0]);
if(fHitCollectionID < 0)
{
fHitCollectionID = G4SDManager::GetSDMpointer()->GetCollectionID(fHitsCollection);
}
aHCE->AddHitsCollection(fHitCollectionID, fHitsCollection);
// fill calorimeter hits with zero energy deposition
for(G4int iphi = 0; iphi < fMeshNbOfCells.y(); iphi++)
for(G4int irho = 0; irho < fMeshNbOfCells.x(); irho++)
for(G4int iz = 0; iz < fMeshNbOfCells.z(); iz++)
{
Par04Hit* hit = new Par04Hit();
fHitsCollection->insert(hit);
}
// reset entrance position
fEntrancePosition.set(-1, -1, -1);
fEntranceDirection.set(-1, -1, -1);
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4bool Par04SensitiveDetector::ProcessHits(G4Step* aStep, G4TouchableHistory*)
{
G4double edep = aStep->GetTotalEnergyDeposit();
if(edep == 0.)
return true;
auto hit = RetrieveAndSetupHit(aStep->GetPostStepPoint()->GetPosition());
if(hit == nullptr)
return true;
// Add energy deposit from G4Step
hit->AddEdep(edep);
// Fill time information from G4Step
// If it's already filled, choose hit with earliest global time
if(hit->GetTime() == -1 || hit->GetTime() > aStep->GetTrack()->GetGlobalTime())
hit->SetTime(aStep->GetTrack()->GetGlobalTime());
// Set hit type to full simulation (only if hit is not already marked as fast
// sim)
if(hit->GetType() != 1)
hit->SetType(0);
return true;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4bool Par04SensitiveDetector::ProcessHits(const G4FastHit* aHit, const G4FastTrack* aTrack,
G4TouchableHistory*)
{
G4double edep = aHit->GetEnergy();
if(edep == 0.)
return true;
auto hit = RetrieveAndSetupHit(aHit->GetPosition());
if(hit == nullptr)
return true;
// Add energy deposit from G4FastHit
hit->AddEdep(edep);
// Fill time information from G4FastTrack
// If it's already filled, choose hit with earliest global time
if(hit->GetTime() == -1 || hit->GetTime() > aTrack->GetPrimaryTrack()->GetGlobalTime())
{
hit->SetTime(aTrack->GetPrimaryTrack()->GetGlobalTime());
}
// Set hit type to fast simulation (even if hit was already marked as full
// sim, overwrite it)
hit->SetType(1);
return true;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
Par04Hit* Par04SensitiveDetector::RetrieveAndSetupHit(G4ThreeVector aGlobalPosition)
{
if(fEntrancePosition.x() == -1)
{
Par04EventInformation* info = dynamic_cast<Par04EventInformation*>(
G4EventManager::GetEventManager()->GetConstCurrentEvent()->GetUserInformation());
if(info == nullptr)
return nullptr;
fEntrancePosition = info->GetPosition();
fEntranceDirection = info->GetDirection();
}
auto delta = aGlobalPosition - fEntrancePosition;
// Calculate rotation matrix along the particle momentum direction
// It will rotate the shower axes to match the incoming particle direction
G4RotationMatrix rotMatrix = G4RotationMatrix();
double particleTheta = fEntranceDirection.theta();
double particlePhi = fEntranceDirection.phi();
rotMatrix.rotateZ(-particlePhi);
rotMatrix.rotateY(-particleTheta);
G4RotationMatrix rotMatrixInv = CLHEP::inverseOf(rotMatrix);
delta = rotMatrix * delta;
G4int rhoNo = std::floor(delta.perp() / fMeshSizeOfCells.x());
G4int phiNo = std::floor((CLHEP::pi + delta.phi()) / fMeshSizeOfCells.y());
G4int zNo = std::floor(delta.z() / fMeshSizeOfCells.z());
std::size_t hitID =
fMeshNbOfCells.x() * fMeshNbOfCells.z() * phiNo + fMeshNbOfCells.z() * rhoNo + zNo;
if(hitID >= fHitsCollection->entries() || zNo > fMeshNbOfCells.z() ||
rhoNo > fMeshNbOfCells.x() || zNo < 0)
{
return nullptr;
}
Par04Hit* hit = (*fHitsCollection)[hitID];
if(hit->GetRhoId() < 0)
{
hit->SetRhoId(rhoNo);
hit->SetPhiId(phiNo);
hit->SetZid(zNo);
hit->SetRot(rotMatrixInv);
hit->SetPos(fEntrancePosition +
rotMatrixInv * G4ThreeVector(0, 0, (zNo + 0.5) * fMeshSizeOfCells.z()));
}
return hit;
}