Import Geant4 10.7.0 source tree
This commit is contained in:
@@ -0,0 +1,55 @@
|
||||
//
|
||||
// ********************************************************************
|
||||
// * 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 "Par03ActionInitialisation.hh"
|
||||
#include "Par03PrimaryGeneratorAction.hh"
|
||||
#include "Par03EventAction.hh"
|
||||
#include "Par03RunAction.hh"
|
||||
|
||||
Par03ActionInitialisation::Par03ActionInitialisation(
|
||||
Par03DetectorConstruction* aDetector)
|
||||
: G4VUserActionInitialization()
|
||||
, fDetector(aDetector)
|
||||
{}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
Par03ActionInitialisation::~Par03ActionInitialisation() {}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
void Par03ActionInitialisation::BuildForMaster() const
|
||||
{
|
||||
SetUserAction(new Par03RunAction(fDetector));
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
void Par03ActionInitialisation::Build() const
|
||||
{
|
||||
SetUserAction(new Par03PrimaryGeneratorAction());
|
||||
SetUserAction(new Par03EventAction(fDetector));
|
||||
SetUserAction(new Par03RunAction(fDetector));
|
||||
}
|
||||
@@ -0,0 +1,284 @@
|
||||
//
|
||||
// ********************************************************************
|
||||
// * 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 "Par03DetectorConstruction.hh"
|
||||
#include "Par03DetectorMessenger.hh"
|
||||
#include "Par03SensitiveDetector.hh"
|
||||
#include "Par03EMShowerModel.hh"
|
||||
|
||||
#include "G4NistManager.hh"
|
||||
#include "G4Material.hh"
|
||||
#include "G4Box.hh"
|
||||
#include "G4Tubs.hh"
|
||||
#include "G4LogicalVolume.hh"
|
||||
#include "G4PVPlacement.hh"
|
||||
#include "G4PVReplica.hh"
|
||||
#include "G4VisAttributes.hh"
|
||||
#include "G4RunManager.hh"
|
||||
|
||||
#include "G4SDManager.hh"
|
||||
|
||||
#include "G4UnitsTable.hh"
|
||||
|
||||
#include "G4Region.hh"
|
||||
#include "G4RegionStore.hh"
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
Par03DetectorConstruction::Par03DetectorConstruction()
|
||||
: G4VUserDetectorConstruction()
|
||||
{
|
||||
fDetectorMessenger = new Par03DetectorMessenger(this);
|
||||
|
||||
G4NistManager* nistManager = G4NistManager::Instance();
|
||||
fDetectorMaterial = nistManager->FindOrBuildMaterial("G4_Fe");
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
Par03DetectorConstruction::~Par03DetectorConstruction() {}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
G4VPhysicalVolume* Par03DetectorConstruction::Construct()
|
||||
{
|
||||
//--------- Material definition ---------
|
||||
G4NistManager* nistManager = G4NistManager::Instance();
|
||||
G4Material* air = nistManager->FindOrBuildMaterial("G4_AIR");
|
||||
|
||||
//--------- Derived dimensions ---------
|
||||
G4double full2Pi = 2. * CLHEP::pi * rad;
|
||||
G4double layerThickness = fDetectorLength / fNbOfLayers;
|
||||
G4double cellPhi = full2Pi / fNbOfPhiCells;
|
||||
G4double cellDR = fDetectorRadius / fNbOfRhoCells;
|
||||
|
||||
//--------- World ---------
|
||||
auto fSolidWorld = new G4Box("World", // name
|
||||
fWorldSize / 2., // half-width in X
|
||||
fWorldSize / 2., // half-width in Y
|
||||
fWorldSize / 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
|
||||
|
||||
//--------- Detector envelope ---------
|
||||
auto fSolidDetector = new G4Tubs("Detector", // name
|
||||
0, // inner radius
|
||||
fDetectorRadius, // outer radius
|
||||
fDetectorLength / 2., // half-width in Z
|
||||
0, // start angle
|
||||
full2Pi); // delta angle
|
||||
auto fLogicDetector = new G4LogicalVolume(fSolidDetector, // solid
|
||||
fDetectorMaterial, // material
|
||||
"Detector"); // name
|
||||
new G4PVPlacement(
|
||||
0, // no rotation
|
||||
G4ThreeVector(0, 0,
|
||||
fDetectorLength / 2), // detector face starts 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);
|
||||
|
||||
//--------- Readout geometry ---------
|
||||
// Layers (along z)
|
||||
auto fSolidLayer = new G4Tubs("Layer", // name
|
||||
0, // inner radius
|
||||
fDetectorRadius, // outer radius
|
||||
layerThickness / 2., // half-width in Z
|
||||
0, // start angle
|
||||
full2Pi); // delta angle
|
||||
auto fLogicLayer = new G4LogicalVolume(fSolidLayer, // solid
|
||||
air, // material
|
||||
"Layer"); // name
|
||||
if(fNbOfLayers > 1)
|
||||
new G4PVReplica("Layer", // name
|
||||
fLogicLayer, // logical volume
|
||||
fLogicDetector, // mother volume
|
||||
kZAxis, // axis of replication
|
||||
fNbOfLayers, // number of replicas
|
||||
layerThickness); // width of single replica
|
||||
else
|
||||
new G4PVPlacement(0, // no rotation
|
||||
G4ThreeVector(), // place at centre of mother volume
|
||||
fLogicLayer, // logical volume
|
||||
"Layer", // name
|
||||
fLogicDetector, // mother volume
|
||||
false, // not used
|
||||
0, // copy number
|
||||
true); // check overlaps
|
||||
|
||||
// Layer segment (division in phi)
|
||||
auto fSolidRow = new G4Tubs("Row", // name
|
||||
0, // inner radius
|
||||
fDetectorRadius, // outer radius
|
||||
layerThickness / 2., // half-width in Z
|
||||
0, // start angle
|
||||
cellPhi); // delta angle
|
||||
|
||||
auto fLogicRow = new G4LogicalVolume(fSolidRow, // solid
|
||||
air, // material
|
||||
"Segment"); // name
|
||||
if(fNbOfPhiCells > 1)
|
||||
new G4PVReplica("Segment", // name
|
||||
fLogicRow, // logical volume
|
||||
fLogicLayer, // mother volume
|
||||
kPhi, // axis of replication
|
||||
fNbOfPhiCells, // number of replicas
|
||||
cellPhi); // width of single replica
|
||||
else
|
||||
new G4PVPlacement(0, // no rotation
|
||||
G4ThreeVector(), // place at centre of mother volume
|
||||
fLogicRow, // logical volume
|
||||
"Row", // name
|
||||
fLogicLayer, // mother volume
|
||||
false, // not used
|
||||
0, // copy number
|
||||
true); // check overlaps
|
||||
|
||||
// Final cells (segment slices in radius)
|
||||
// No volume can be placed inside a radial replication
|
||||
auto fSolidCell = new G4Tubs("Cell", // name
|
||||
0, // inner radius
|
||||
cellDR, // outer radius
|
||||
layerThickness / 2., // half-width in Z
|
||||
0, // start angle
|
||||
cellPhi); // delta angle
|
||||
|
||||
fLogicCell = new G4LogicalVolume(fSolidCell, // solid
|
||||
fDetectorMaterial, // material
|
||||
"Cell"); // name
|
||||
if(fNbOfRhoCells > 1)
|
||||
new G4PVReplica("Cell", // name
|
||||
fLogicCell, // logical volume
|
||||
fLogicRow, // mother volume
|
||||
kRho, // axis of replication
|
||||
fNbOfRhoCells, // number of replicas
|
||||
cellDR); // width of single replica
|
||||
else
|
||||
new G4PVPlacement(0, // no rotation
|
||||
G4ThreeVector(), // place at centre of mother volume
|
||||
fLogicCell, // logical volume
|
||||
"Cell", // name
|
||||
fLogicRow, // mother volume
|
||||
false, // not used
|
||||
0, // copy number
|
||||
true); // check overlaps
|
||||
|
||||
//--------- Visualisation settings ---------
|
||||
fLogicWorld->SetVisAttributes(G4VisAttributes::GetInvisible());
|
||||
fLogicLayer->SetVisAttributes(G4VisAttributes::GetInvisible());
|
||||
fLogicRow->SetVisAttributes(G4VisAttributes::GetInvisible());
|
||||
G4VisAttributes attribs;
|
||||
attribs.SetColour(G4Colour(0, 0, 1, 0.3));
|
||||
attribs.SetForceSolid(true);
|
||||
fLogicCell->SetVisAttributes(attribs);
|
||||
|
||||
Print();
|
||||
return fPhysicWorld;
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
void Par03DetectorConstruction::ConstructSDandField()
|
||||
{
|
||||
Par03SensitiveDetector* caloSD = new Par03SensitiveDetector(
|
||||
"sensitiveDetector", fNbOfLayers, fNbOfPhiCells, fNbOfRhoCells);
|
||||
G4SDManager::GetSDMpointer()->AddNewDetector(caloSD);
|
||||
SetSensitiveDetector(fLogicCell, caloSD);
|
||||
|
||||
auto detectorRegion =
|
||||
G4RegionStore::GetInstance()->GetRegion("DetectorRegion");
|
||||
new Par03EMShowerModel("model", detectorRegion);
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
void Par03DetectorConstruction::Print() const
|
||||
{
|
||||
G4cout << "\n------------------------------------------------------"
|
||||
<< "\n--- Detector material:\t" << fDetectorMaterial->GetName()
|
||||
<< "\n--- Detector length:\t" << G4BestUnit(fDetectorLength, "Length")
|
||||
<< "\n--- Detector radius:\t" << G4BestUnit(fDetectorRadius, "Length")
|
||||
<< "\n--- Number of layers:\t" << fNbOfLayers
|
||||
<< "\n--- Number of R-cells:\t" << fNbOfRhoCells
|
||||
<< "\n--- Number of phi-cells:\t" << fNbOfPhiCells << G4endl;
|
||||
G4cout << "-----------------------------------------------------" << G4endl;
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
void Par03DetectorConstruction::SetMaterial(const G4String& aName)
|
||||
{
|
||||
// search material by its name
|
||||
G4Material* material = G4NistManager::Instance()->FindOrBuildMaterial(aName);
|
||||
if(material)
|
||||
fDetectorMaterial = material;
|
||||
else
|
||||
G4Exception("Par03DetectorConstruction::SetMaterial()", "InvalidSetup",
|
||||
FatalException, ("Unknown material name: " + aName).c_str());
|
||||
G4RunManager::GetRunManager()->PhysicsHasBeenModified();
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
void Par03DetectorConstruction::SetRadius(G4double aRadius)
|
||||
{
|
||||
// check if fits within world volume
|
||||
if(aRadius >= fWorldSize / 2.)
|
||||
G4Exception("Par03DetectorConstruction::SetRadius()", "InvalidSetup",
|
||||
FatalException,
|
||||
("Detector radius cannot be larger than the world size (" +
|
||||
G4String(G4BestUnit(fWorldSize / 2., "Length")) + ")")
|
||||
.c_str());
|
||||
fDetectorRadius = aRadius;
|
||||
}
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
void Par03DetectorConstruction::SetLength(G4double aLength)
|
||||
{
|
||||
// check if fits within world volume
|
||||
if(aLength >= fWorldSize / 2.)
|
||||
G4Exception("Par03DetectorConstruction::SetLength()", "InvalidSetup",
|
||||
FatalException,
|
||||
("Detector length cannot be larger than the world size (" +
|
||||
G4String(G4BestUnit(fWorldSize / 2., "Length")) + ")")
|
||||
.c_str());
|
||||
fDetectorLength = aLength;
|
||||
}
|
||||
@@ -0,0 +1,184 @@
|
||||
//
|
||||
// ********************************************************************
|
||||
// * 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 "Par03DetectorMessenger.hh"
|
||||
#include "Par03DetectorConstruction.hh"
|
||||
|
||||
#include "G4UIdirectory.hh"
|
||||
#include "G4UIcmdWithoutParameter.hh"
|
||||
#include "G4UIcmdWithAnInteger.hh"
|
||||
#include "G4UIcmdWithADoubleAndUnit.hh"
|
||||
#include "G4UIcmdWithAString.hh"
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
Par03DetectorMessenger::Par03DetectorMessenger(
|
||||
Par03DetectorConstruction* aDetector)
|
||||
: G4UImessenger()
|
||||
, fDetector(aDetector)
|
||||
{
|
||||
fExampleDir = new G4UIdirectory("/Par03/");
|
||||
fExampleDir->SetGuidance("UI commands specific to this example");
|
||||
|
||||
fDetectorDir = new G4UIdirectory("/Par03/detector/");
|
||||
fDetectorDir->SetGuidance("Detector construction UI commands");
|
||||
|
||||
fPrintCmd = new G4UIcmdWithoutParameter("/Par03/detector/print", this);
|
||||
fPrintCmd->SetGuidance("Print current settings.");
|
||||
|
||||
fDetectorRadiusCmd =
|
||||
new G4UIcmdWithADoubleAndUnit("/Par03/detector/setDetectorRadius", this);
|
||||
fDetectorRadiusCmd->SetGuidance(
|
||||
"Set tranverse size of the detector (cylinder radius)");
|
||||
fDetectorRadiusCmd->SetParameterName("Size", false);
|
||||
fDetectorRadiusCmd->SetRange("Size>0.");
|
||||
fDetectorRadiusCmd->SetUnitCategory("Length");
|
||||
fDetectorRadiusCmd->AvailableForStates(G4State_PreInit);
|
||||
fDetectorRadiusCmd->SetToBeBroadcasted(false);
|
||||
|
||||
fDetectorLengthCmd =
|
||||
new G4UIcmdWithADoubleAndUnit("/Par03/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);
|
||||
|
||||
fDetectorMaterialCmd =
|
||||
new G4UIcmdWithAString("/Par03/detector/setDetectorMaterial", this);
|
||||
fDetectorMaterialCmd->SetGuidance("Material of the detector.");
|
||||
fDetectorMaterialCmd->SetParameterName("Name", false);
|
||||
fDetectorMaterialCmd->AvailableForStates(G4State_PreInit);
|
||||
fDetectorMaterialCmd->SetToBeBroadcasted(false);
|
||||
|
||||
fNbLayersCmd =
|
||||
new G4UIcmdWithAnInteger("/Par03/detector/setNbOfLayers", this);
|
||||
fNbLayersCmd->SetGuidance("Set number of layers.");
|
||||
fNbLayersCmd->SetParameterName("NbLayers", false);
|
||||
fNbLayersCmd->SetRange("NbLayers>0");
|
||||
fNbLayersCmd->AvailableForStates(G4State_PreInit);
|
||||
fNbLayersCmd->SetToBeBroadcasted(false);
|
||||
|
||||
fNbRhoCellsCmd =
|
||||
new G4UIcmdWithAnInteger("/Par03/detector/setNbOfRhoCells", this);
|
||||
fNbRhoCellsCmd->SetGuidance("Set number of cells along radius.");
|
||||
fNbRhoCellsCmd->SetParameterName("NbRhoCells", false);
|
||||
fNbRhoCellsCmd->SetRange("NbRhoCells>0");
|
||||
fNbRhoCellsCmd->AvailableForStates(G4State_PreInit);
|
||||
fNbRhoCellsCmd->SetToBeBroadcasted(false);
|
||||
|
||||
fNbPhiCellsCmd =
|
||||
new G4UIcmdWithAnInteger("/Par03/detector/setNbOfPhiCells", this);
|
||||
fNbPhiCellsCmd->SetGuidance("Set number of cells in azimuthal angle.");
|
||||
fNbPhiCellsCmd->SetParameterName("NbPhiCells", false);
|
||||
fNbPhiCellsCmd->SetRange("NbPhiCells>0");
|
||||
fNbPhiCellsCmd->AvailableForStates(G4State_PreInit);
|
||||
fNbPhiCellsCmd->SetToBeBroadcasted(false);
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
Par03DetectorMessenger::~Par03DetectorMessenger()
|
||||
{
|
||||
delete fPrintCmd;
|
||||
delete fDetectorRadiusCmd;
|
||||
delete fDetectorLengthCmd;
|
||||
delete fDetectorMaterialCmd;
|
||||
delete fNbLayersCmd;
|
||||
delete fNbRhoCellsCmd;
|
||||
delete fNbPhiCellsCmd;
|
||||
delete fDetectorDir;
|
||||
delete fExampleDir;
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
void Par03DetectorMessenger::SetNewValue(G4UIcommand* aCommand,
|
||||
G4String aNewValue)
|
||||
{
|
||||
if(aCommand == fPrintCmd)
|
||||
{
|
||||
fDetector->Print();
|
||||
}
|
||||
else if(aCommand == fDetectorRadiusCmd)
|
||||
{
|
||||
fDetector->SetRadius(fDetectorRadiusCmd->GetNewDoubleValue(aNewValue));
|
||||
}
|
||||
else if(aCommand == fDetectorLengthCmd)
|
||||
{
|
||||
fDetector->SetLength(fDetectorRadiusCmd->GetNewDoubleValue(aNewValue));
|
||||
}
|
||||
else if(aCommand == fDetectorMaterialCmd)
|
||||
{
|
||||
fDetector->SetMaterial(aNewValue);
|
||||
}
|
||||
else if(aCommand == fNbLayersCmd)
|
||||
{
|
||||
fDetector->SetNbOfLayers(fNbLayersCmd->GetNewIntValue(aNewValue));
|
||||
}
|
||||
else if(aCommand == fNbRhoCellsCmd)
|
||||
{
|
||||
fDetector->SetNbOfRhoCells(fNbRhoCellsCmd->GetNewIntValue(aNewValue));
|
||||
}
|
||||
else if(aCommand == fNbPhiCellsCmd)
|
||||
{
|
||||
fDetector->SetNbOfPhiCells(fNbPhiCellsCmd->GetNewIntValue(aNewValue));
|
||||
}
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
G4String Par03DetectorMessenger::GetCurrentValue(G4UIcommand* aCommand)
|
||||
{
|
||||
G4String cv;
|
||||
|
||||
if(aCommand == fDetectorRadiusCmd)
|
||||
{
|
||||
cv = fDetectorRadiusCmd->ConvertToString(fDetector->GetRadius(), "mm");
|
||||
}
|
||||
else if(aCommand == fDetectorLengthCmd)
|
||||
{
|
||||
cv = fDetectorLengthCmd->ConvertToString(fDetector->GetLength(), "mm");
|
||||
}
|
||||
else if(aCommand == fDetectorMaterialCmd)
|
||||
{
|
||||
cv = fDetector->GetMaterial();
|
||||
}
|
||||
else if(aCommand == fNbLayersCmd)
|
||||
{
|
||||
cv = fNbLayersCmd->ConvertToString(fDetector->GetNbOfLayers());
|
||||
}
|
||||
else if(aCommand == fNbPhiCellsCmd)
|
||||
{
|
||||
cv = fNbPhiCellsCmd->ConvertToString(fDetector->GetNbOfPhiCells());
|
||||
}
|
||||
else if(aCommand == fNbRhoCellsCmd)
|
||||
{
|
||||
cv = fNbRhoCellsCmd->ConvertToString(fDetector->GetNbOfRhoCells());
|
||||
}
|
||||
return cv;
|
||||
}
|
||||
@@ -0,0 +1,147 @@
|
||||
//
|
||||
// ********************************************************************
|
||||
// * 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 "Par03EMShowerModel.hh"
|
||||
#include "Par03EMShowerMessenger.hh"
|
||||
|
||||
#include "G4UIdirectory.hh"
|
||||
#include "G4UIcmdWithoutParameter.hh"
|
||||
#include "G4UIcmdWithADoubleAndUnit.hh"
|
||||
#include "G4UIcmdWithADouble.hh"
|
||||
#include "G4UIcmdWithAnInteger.hh"
|
||||
|
||||
Par03EMShowerMessenger::Par03EMShowerMessenger(Par03EMShowerModel* aModel)
|
||||
: fModel(aModel)
|
||||
{
|
||||
fDirectory = new G4UIdirectory("/Par03/fastSim/");
|
||||
fDirectory->SetGuidance(
|
||||
"Set mesh parameters for the example fast sim model.");
|
||||
|
||||
fPrintCmd = new G4UIcmdWithoutParameter("/Par03/fastSim/print", this);
|
||||
fPrintCmd->SetGuidance("Print current settings.");
|
||||
|
||||
fSigmaCmd = new G4UIcmdWithADoubleAndUnit(
|
||||
"/Par03/fastSim/transverseProfile/sigma", this);
|
||||
fSigmaCmd->SetGuidance("Set sigma parameter of 2D Gaussian distribution.");
|
||||
fSigmaCmd->SetParameterName("Sigma", false);
|
||||
fSigmaCmd->SetUnitCategory("Length");
|
||||
|
||||
fAlphaCmd =
|
||||
new G4UIcmdWithADouble("/Par03/fastSim/longitudinalProfile/alpha", this);
|
||||
fAlphaCmd->SetGuidance("Set alpha parameter of Gamma distribution.");
|
||||
fAlphaCmd->SetParameterName("Alpha", false);
|
||||
|
||||
fBetaCmd =
|
||||
new G4UIcmdWithADouble("/Par03/fastSim/longitudinalProfile/beta", this);
|
||||
fBetaCmd->SetGuidance("Set beta parameter of Gamma distribution.");
|
||||
fBetaCmd->SetParameterName("Beta", false);
|
||||
|
||||
fNbOfHitsCmd = new G4UIcmdWithAnInteger("/Par03/fastSim/numberOfHits", this);
|
||||
fNbOfHitsCmd->SetGuidance(
|
||||
"Set number of (same energy) energy deposits created in fast simulation. "
|
||||
"Those deposits will be scored in the detector according to the readout of "
|
||||
"the sensitive detector.");
|
||||
fNbOfHitsCmd->SetParameterName("Number", false);
|
||||
|
||||
fLongMaxDepthCmd =
|
||||
new G4UIcmdWithADouble("/Par03/fastSim/longitudinalProfile/maxDepth", this);
|
||||
fLongMaxDepthCmd->SetGuidance(
|
||||
"Set maximum shower depth used in parametrisation.");
|
||||
fLongMaxDepthCmd->SetGuidance("Expressed in units of radiation length.");
|
||||
fLongMaxDepthCmd->SetParameterName("Depth", false);
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
Par03EMShowerMessenger::~Par03EMShowerMessenger()
|
||||
{
|
||||
delete fPrintCmd;
|
||||
delete fSigmaCmd;
|
||||
delete fAlphaCmd;
|
||||
delete fBetaCmd;
|
||||
delete fNbOfHitsCmd;
|
||||
delete fLongMaxDepthCmd;
|
||||
delete fDirectory;
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
void Par03EMShowerMessenger::SetNewValue(G4UIcommand* aCommand,
|
||||
G4String aNewValues)
|
||||
{
|
||||
if(aCommand == fPrintCmd)
|
||||
{
|
||||
fModel->Print();
|
||||
}
|
||||
else if(aCommand == fSigmaCmd)
|
||||
{
|
||||
fModel->SetSigma(fSigmaCmd->GetNewDoubleValue(aNewValues));
|
||||
}
|
||||
else if(aCommand == fAlphaCmd)
|
||||
{
|
||||
fModel->SetAlpha(fAlphaCmd->GetNewDoubleValue(aNewValues));
|
||||
}
|
||||
else if(aCommand == fBetaCmd)
|
||||
{
|
||||
fModel->SetBeta(fBetaCmd->GetNewDoubleValue(aNewValues));
|
||||
}
|
||||
else if(aCommand == fNbOfHitsCmd)
|
||||
{
|
||||
fModel->SetNbOfHits(fNbOfHitsCmd->GetNewIntValue(aNewValues));
|
||||
}
|
||||
else if(aCommand == fLongMaxDepthCmd)
|
||||
{
|
||||
fModel->SetLongMaxDepth(fLongMaxDepthCmd->GetNewDoubleValue(aNewValues));
|
||||
}
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
G4String Par03EMShowerMessenger::GetCurrentValue(G4UIcommand* aCommand)
|
||||
{
|
||||
G4String cv;
|
||||
|
||||
if(aCommand == fSigmaCmd)
|
||||
{
|
||||
cv = fSigmaCmd->ConvertToString(fModel->GetSigma());
|
||||
}
|
||||
else if(aCommand == fAlphaCmd)
|
||||
{
|
||||
cv = fAlphaCmd->ConvertToString(fModel->GetAlpha());
|
||||
}
|
||||
else if(aCommand == fBetaCmd)
|
||||
{
|
||||
cv = fBetaCmd->ConvertToString(fModel->GetBeta());
|
||||
}
|
||||
else if(aCommand == fNbOfHitsCmd)
|
||||
{
|
||||
cv = fNbOfHitsCmd->ConvertToString(fModel->GetNbOfHits());
|
||||
}
|
||||
else if(aCommand == fLongMaxDepthCmd)
|
||||
{
|
||||
cv = fLongMaxDepthCmd->ConvertToString(fModel->GetLongMaxDepth());
|
||||
}
|
||||
return cv;
|
||||
}
|
||||
@@ -0,0 +1,212 @@
|
||||
//
|
||||
// ********************************************************************
|
||||
// * 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 "Par03EMShowerModel.hh"
|
||||
#include "Par03EMShowerMessenger.hh"
|
||||
|
||||
#include "G4Electron.hh"
|
||||
#include "G4Positron.hh"
|
||||
#include "G4Gamma.hh"
|
||||
#include "G4SystemOfUnits.hh"
|
||||
#include "G4UnitsTable.hh"
|
||||
#include "G4FastHit.hh"
|
||||
#include "Randomize.hh"
|
||||
#include "G4FastSimHitMaker.hh"
|
||||
|
||||
Par03EMShowerModel::Par03EMShowerModel(G4String aModelName, G4Region* aEnvelope)
|
||||
: G4VFastSimulationModel(aModelName, aEnvelope)
|
||||
, fMessenger(new Par03EMShowerMessenger(this))
|
||||
, fHitMaker(new G4FastSimHitMaker)
|
||||
{}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
Par03EMShowerModel::Par03EMShowerModel(G4String aModelName)
|
||||
: G4VFastSimulationModel(aModelName)
|
||||
, fMessenger(new Par03EMShowerMessenger(this))
|
||||
, fHitMaker(new G4FastSimHitMaker)
|
||||
{}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
Par03EMShowerModel::~Par03EMShowerModel() {}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
G4bool Par03EMShowerModel::IsApplicable(
|
||||
const G4ParticleDefinition& aParticleType)
|
||||
{
|
||||
return &aParticleType == G4Electron::ElectronDefinition() ||
|
||||
&aParticleType == G4Positron::PositronDefinition() ||
|
||||
&aParticleType == G4Gamma::GammaDefinition();
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
G4bool Par03EMShowerModel::ModelTrigger(const G4FastTrack& aFastTrack)
|
||||
{
|
||||
// Check energy
|
||||
if(aFastTrack.GetPrimaryTrack()->GetKineticEnergy() < 1 * GeV)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
// Check length of detector
|
||||
// Calculate depth of the detector along shower axis to verify if shower
|
||||
// will fit inside. Required max shower depth is defined by fLongMaxDepth, and
|
||||
// can be changed with UI command `/Par03/fastSim/longitudinalProfile/maxDepth
|
||||
G4double X0 = aFastTrack.GetPrimaryTrack()->GetMaterial()->GetRadlen();
|
||||
auto particleDirection = aFastTrack.GetPrimaryTrackLocalDirection();
|
||||
auto particlePosition = aFastTrack.GetPrimaryTrackLocalPosition();
|
||||
G4double detectorDepthInMM = aFastTrack.GetEnvelopeSolid()->DistanceToOut(
|
||||
particlePosition, particleDirection);
|
||||
G4double detectorDepthInX0 = detectorDepthInMM / X0;
|
||||
// check if detector depth is sufficient to create showers
|
||||
if(detectorDepthInX0 < fLongMaxDepth)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
void Par03EMShowerModel::DoIt(const G4FastTrack& aFastTrack,
|
||||
G4FastStep& aFastStep)
|
||||
{
|
||||
// Remove particle from further processing by G4
|
||||
aFastStep.KillPrimaryTrack();
|
||||
aFastStep.SetPrimaryTrackPathLength(0.0);
|
||||
G4double energy = aFastTrack.GetPrimaryTrack()->GetKineticEnergy();
|
||||
// No need to create any deposit, it will be handled by this model (and
|
||||
// G4FastSimHitMaker that will call the sensitive detector)
|
||||
aFastStep.SetTotalEnergyDeposited(0);
|
||||
auto particlePosition = aFastTrack.GetPrimaryTrackLocalPosition();
|
||||
auto particleDirection = aFastTrack.GetPrimaryTrackLocalDirection();
|
||||
|
||||
// Calculate how to create energy deposits
|
||||
// Following PDG 33.5 chapter
|
||||
// material calculation assumes homogeneous detector (true for Par03 example)
|
||||
auto material = aFastTrack.GetPrimaryTrack()->GetMaterial();
|
||||
G4double materialX0 = material->GetRadlen();
|
||||
G4double materialZ = material->GetZ();
|
||||
// EC estimation follows PDG fit to solids in Fig. 33.14 (rms 2.2%)
|
||||
G4double materialEc = 610 * MeV / (materialZ + 1.24);
|
||||
// RM estimation follows PDG Eq. (33.37) (rms 2.2%)
|
||||
G4double materialRM = 21.2052 * MeV * materialX0 / materialEc;
|
||||
G4double particleY = energy / materialEc;
|
||||
// Estimate shower maximum and alpha parameter of Gamma distribution
|
||||
// that describes the longitudinal profile (PDG Eq. (33.35))
|
||||
// unless alpha is specified by UI command
|
||||
if(fAlpha < 0)
|
||||
{
|
||||
// from PDG Eq. (33.36)
|
||||
G4double particleTmax = std::log(particleY);
|
||||
if(aFastTrack.GetPrimaryTrack()->GetParticleDefinition() ==
|
||||
G4Gamma::GammaDefinition())
|
||||
{
|
||||
particleTmax += 0.5;
|
||||
}
|
||||
else
|
||||
{
|
||||
particleTmax -= 0.5;
|
||||
}
|
||||
fAlpha = particleTmax * fBeta + 1;
|
||||
}
|
||||
// Unless sigma of Gaussian distribution describing the transverse profile
|
||||
// is specified by UI command, use value calculated from Moliere Radius
|
||||
if(fSigma < 0)
|
||||
{
|
||||
// 90% of shower is contained within 1 * R_M
|
||||
// 1.645 * std dev of Gaussian contains 90%
|
||||
fSigma = materialRM / 1.645;
|
||||
}
|
||||
|
||||
// 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 = particleDirection.theta();
|
||||
double particlePhi = particleDirection.phi();
|
||||
double epsilon = 1e-3;
|
||||
rotMatrix.rotateY(particleTheta);
|
||||
// do not use (random) phi if x==y==0
|
||||
if(!(std::fabs(particleDirection.x()) < epsilon &&
|
||||
std::fabs(particleDirection.y()) < epsilon))
|
||||
rotMatrix.rotateZ(particlePhi);
|
||||
|
||||
// Create hits
|
||||
// First use rejecton sampling to sample from Gamma distribution
|
||||
// then get random numbers from uniform distribution for azimuthal angle, and
|
||||
// from Gaussian for radius
|
||||
G4ThreeVector position;
|
||||
G4double gammaMax = gamma((fAlpha - 1) / fBeta, fAlpha, fBeta);
|
||||
G4int generatedHits = 0;
|
||||
while(generatedHits < fNbOfHits)
|
||||
{
|
||||
G4double random1 = G4UniformRand() * fLongMaxDepth;
|
||||
G4double random2 = G4UniformRand() * gammaMax;
|
||||
if(gamma(random1, fAlpha, fBeta) >= random2)
|
||||
{
|
||||
// Generate corresponding rho (phi) from Gaussian (flat) distribution
|
||||
G4double phiPosition = G4UniformRand() * 2 * CLHEP::pi;
|
||||
G4double rhoPosition = G4RandGauss::shoot(0, fSigma);
|
||||
position = particlePosition +
|
||||
rotMatrix * G4ThreeVector(rhoPosition * std::sin(phiPosition),
|
||||
rhoPosition * std::cos(phiPosition),
|
||||
random1 * materialX0);
|
||||
// Create energy deposit in the detector
|
||||
// This will call appropriate sensitive detector class
|
||||
fHitMaker->make(G4FastHit(position, energy / fNbOfHits), aFastTrack);
|
||||
generatedHits++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
void Par03EMShowerModel::Print() const
|
||||
{
|
||||
G4cout << "Par03EMShowerModel: " << G4endl;
|
||||
G4cout << "Gaussian distribution (transverse plane): \tmu = 0, sigma = "
|
||||
<< G4BestUnit(fSigma, "Length") << G4endl;
|
||||
if(fSigma < 0)
|
||||
G4cout << "Negative sigma value means that it will be recalculated "
|
||||
"from the value of the Moliere radius of the detector material, "
|
||||
"taking into account that 90% of the area below the Gaussian "
|
||||
"distribution (from mu - 1.645 sigma to mu + 1.645 sigma) "
|
||||
"corresponds to area within 1 Moliere radius."
|
||||
<< G4endl;
|
||||
G4cout << "Gamma distribution (along shower axis): \talpha = " << fAlpha
|
||||
<< ", beta = " << fBeta << ", max depth = " << fLongMaxDepth << " X0"
|
||||
<< G4endl;
|
||||
if(fAlpha < 0)
|
||||
G4cout << "Negative alpha value means that it will be recalculated "
|
||||
"from the critical energy of the detector material, particle "
|
||||
"type, and beta parameter.\n alpha = beta * T_max, where T_max = "
|
||||
"ln(E/E_C) + C\n where E is particle energy, E_C is critical "
|
||||
"energy in the material, and constant C = -0.5 for electrons and "
|
||||
"0.5 for photons (Eq. (33.36) from PDG)."
|
||||
<< G4endl;
|
||||
G4cout << "Number of created energy deposits: " << fNbOfHits << G4endl;
|
||||
}
|
||||
@@ -0,0 +1,159 @@
|
||||
//
|
||||
// ********************************************************************
|
||||
// * 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 "Par03EventAction.hh"
|
||||
#include "Par03Hit.hh"
|
||||
#include "Par03DetectorConstruction.hh"
|
||||
#include "g4analysis.hh"
|
||||
|
||||
#include "G4SDManager.hh"
|
||||
#include "G4HCofThisEvent.hh"
|
||||
#include "G4Event.hh"
|
||||
#include "G4EventManager.hh"
|
||||
|
||||
Par03EventAction::Par03EventAction(Par03DetectorConstruction* aDetector)
|
||||
: G4UserEventAction()
|
||||
, fHitCollectionID(-1)
|
||||
, fTimer()
|
||||
, fDetector(aDetector)
|
||||
{}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
Par03EventAction::~Par03EventAction() {}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
void Par03EventAction::BeginOfEventAction(const G4Event*) { fTimer.Start(); }
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
void Par03EventAction::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<Par03HitsCollection*>(
|
||||
aEvent->GetHCofThisEvent()->GetHC(fHitCollectionID));
|
||||
|
||||
if(hitsCollection == nullptr)
|
||||
{
|
||||
G4ExceptionDescription msg;
|
||||
msg << "Cannot access hitsCollection ID " << fHitCollectionID;
|
||||
G4Exception("Par03EventAction::GetHitsCollection()", "MyCode0001",
|
||||
FatalException, msg);
|
||||
}
|
||||
// Get analysis manager
|
||||
auto analysisManager = G4AnalysisManager::Instance();
|
||||
// Retrieve only once detector dimensions
|
||||
if(fCellSizeZ == 0)
|
||||
{
|
||||
fCellSizeZ = fDetector->GetLength() / fDetector->GetNbOfLayers();
|
||||
fCellSizeRho = fDetector->GetRadius() / fDetector->GetNbOfRhoCells();
|
||||
}
|
||||
|
||||
// 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;
|
||||
G4double cosDirection = std::cos(primaryDirection.theta());
|
||||
G4double sinDirection = std::sin(primaryDirection.theta());
|
||||
|
||||
// Fill histograms
|
||||
Par03Hit* hit = nullptr;
|
||||
G4double hitEn = 0;
|
||||
G4double totalEnergy = 0;
|
||||
G4int hitZ = -1;
|
||||
G4int hitRho = -1;
|
||||
G4int hitType = -1;
|
||||
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<Par03Hit*>(hitsCollection->GetHit(iHit));
|
||||
hitZ = hit->GetZid();
|
||||
hitRho = hit->GetRhoId();
|
||||
hitEn = hit->GetEdep();
|
||||
hitType = hit->GetType();
|
||||
if(hitEn > 0)
|
||||
{
|
||||
totalEnergy += hitEn;
|
||||
tDistance =
|
||||
hitZ * fCellSizeZ * cosDirection +
|
||||
(hitRho * fCellSizeRho - primaryEntrance.perp()) * sinDirection;
|
||||
rDistance =
|
||||
hitZ * fCellSizeZ * (-sinDirection) +
|
||||
(hitRho * fCellSizeRho - primaryEntrance.perp()) * cosDirection;
|
||||
tFirstMoment += hitEn * tDistance;
|
||||
rFirstMoment += hitEn * rDistance;
|
||||
analysisManager->FillH1(4, tDistance, hitEn);
|
||||
analysisManager->FillH1(5, rDistance, hitEn);
|
||||
analysisManager->FillH1(10, hitType);
|
||||
}
|
||||
}
|
||||
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);
|
||||
|
||||
// Second loop over hits to calculate second moments
|
||||
for(size_t iHit = 0; iHit < hitsCollection->entries(); iHit++)
|
||||
{
|
||||
hit = static_cast<Par03Hit*>(hitsCollection->GetHit(iHit));
|
||||
hitEn = hit->GetEdep();
|
||||
hitZ = hit->GetZid();
|
||||
hitRho = hit->GetRhoId();
|
||||
if(hitEn > 0)
|
||||
{
|
||||
tDistance = hitZ * fCellSizeZ * cosDirection +
|
||||
(hitRho * fCellSizeRho - primaryEntrance.r()) * sinDirection;
|
||||
rDistance = hitZ * fCellSizeZ * (-sinDirection) +
|
||||
(hitRho * fCellSizeRho - primaryEntrance.r()) * cosDirection;
|
||||
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);
|
||||
}
|
||||
@@ -0,0 +1,169 @@
|
||||
//
|
||||
// ********************************************************************
|
||||
// * 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 "Par03Hit.hh"
|
||||
|
||||
#include "G4VisAttributes.hh"
|
||||
#include "G4Tubs.hh"
|
||||
#include "G4Colour.hh"
|
||||
#include "G4AttDefStore.hh"
|
||||
#include "G4AttDef.hh"
|
||||
#include "G4AttValue.hh"
|
||||
#include "G4UnitsTable.hh"
|
||||
#include "G4SystemOfUnits.hh"
|
||||
#include "G4VVisManager.hh"
|
||||
#include "G4LogicalVolume.hh"
|
||||
|
||||
G4ThreadLocal G4Allocator<Par03Hit>* Par03HitAllocator;
|
||||
|
||||
Par03Hit::Par03Hit()
|
||||
: G4VHit()
|
||||
{}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
Par03Hit::~Par03Hit() {}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
Par03Hit::Par03Hit(const Par03Hit& 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 Par03Hit& Par03Hit::operator=(const Par03Hit& 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 Par03Hit::operator==(const Par03Hit& aRight) const
|
||||
{
|
||||
return (fRhoId == aRight.fRhoId && fPhiId == aRight.fPhiId &&
|
||||
fZId == aRight.fZId);
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
void Par03Hit::Draw()
|
||||
{
|
||||
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;
|
||||
if(pVVisManager)
|
||||
{
|
||||
G4Transform3D trans(fRot, fPos);
|
||||
G4VisAttributes attribs;
|
||||
// Create default dimensions
|
||||
G4Tubs solid("draw", 0, 1 * cm, 1 * cm, 0, 0.05 * CLHEP::pi);
|
||||
if(fLogVol)
|
||||
{
|
||||
const G4VisAttributes* pVA = fLogVol->GetVisAttributes();
|
||||
if(pVA)
|
||||
attribs = *pVA;
|
||||
// Cannot use directly fLogVol due to rho parametrisation (change of
|
||||
// solid!) Recalculation of radius is needed
|
||||
solid = *dynamic_cast<G4Tubs*>(fLogVol->GetSolid());
|
||||
double dR = solid.GetOuterRadius() - solid.GetInnerRadius();
|
||||
solid.SetInnerRadius(solid.GetInnerRadius() + fRhoId * dR);
|
||||
solid.SetOuterRadius(solid.GetOuterRadius() + fRhoId * dR);
|
||||
}
|
||||
// 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>* Par03Hit::GetAttDefs() const
|
||||
{
|
||||
G4bool isNew;
|
||||
std::map<G4String, G4AttDef>* store =
|
||||
G4AttDefStore::GetInstance("Par03Hit", 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>* Par03Hit::CreateAttValues() const
|
||||
{
|
||||
std::vector<G4AttValue>* values = new std::vector<G4AttValue>;
|
||||
values->push_back(G4AttValue("HitType", "HadPar03Hit", ""));
|
||||
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 Par03Hit::Print()
|
||||
{
|
||||
std::cout << "\tHit " << fEdep / MeV << " MeV at " << fPos / cm
|
||||
<< " cm (R,phi,z)= (" << fRhoId << ", " << fPhiId << ", " << fZId
|
||||
<< "), " << fTime << " ns" << std::endl;
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
//
|
||||
// ********************************************************************
|
||||
// * 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 "Par03PrimaryGeneratorAction.hh"
|
||||
|
||||
#include "G4ParticleGun.hh"
|
||||
#include "G4ParticleTable.hh"
|
||||
#include "G4SystemOfUnits.hh"
|
||||
|
||||
Par03PrimaryGeneratorAction::Par03PrimaryGeneratorAction()
|
||||
: G4VUserPrimaryGeneratorAction()
|
||||
, fParticleGun(nullptr)
|
||||
{
|
||||
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., 0., 1.));
|
||||
fParticleGun->SetParticleEnergy(10. * GeV);
|
||||
fParticleGun->SetParticlePosition(G4ThreeVector(0., 0., -10. * cm));
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
Par03PrimaryGeneratorAction::~Par03PrimaryGeneratorAction() { delete fParticleGun; }
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
void Par03PrimaryGeneratorAction::GeneratePrimaries(G4Event* aEvent)
|
||||
{
|
||||
fParticleGun->GeneratePrimaryVertex(aEvent);
|
||||
}
|
||||
@@ -0,0 +1,117 @@
|
||||
//
|
||||
// ********************************************************************
|
||||
// * 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 "Par03RunAction.hh"
|
||||
#include "Par03DetectorConstruction.hh"
|
||||
|
||||
#include "g4analysis.hh"
|
||||
|
||||
Par03RunAction::Par03RunAction(Par03DetectorConstruction* aDetector)
|
||||
: G4UserRunAction()
|
||||
, fDetector(aDetector)
|
||||
{
|
||||
// Create analysis manager
|
||||
G4AnalysisManager* analysisManager = G4Analysis::ManagerInstance("root");
|
||||
// Default filename, can be overriden with /analysis/setFileName
|
||||
analysisManager->SetFileName("Par03Output");
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
Par03RunAction::~Par03RunAction() { delete G4AnalysisManager::Instance(); }
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
void Par03RunAction::BeginOfRunAction(const G4Run*)
|
||||
{
|
||||
// Get detector dimensions
|
||||
G4int cellNumZ = fDetector->GetNbOfLayers();
|
||||
G4int cellNumRho = fDetector->GetNbOfRhoCells();
|
||||
G4double cellSizeZ = fDetector->GetLength() / cellNumZ;
|
||||
G4double cellSizeRho = fDetector->GetRadius() / cellNumRho;
|
||||
// Default max value of energy stored in histogram (in GeV)
|
||||
G4double maxEnergy = 100;
|
||||
|
||||
// Get analysis manager
|
||||
auto analysisManager = G4AnalysisManager::Instance();
|
||||
|
||||
// Creating control histograms
|
||||
analysisManager->CreateH1("energyParticle",
|
||||
"Primary energy;E_{MC} (GeV);Entries", 256, 0,
|
||||
1.1 * maxEnergy);
|
||||
analysisManager->CreateH1("energyDeposited",
|
||||
"Deposited energy;E_{MC} (GeV);Entries", 256, 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, 30);
|
||||
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 /
|
||||
10); // 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) /
|
||||
25); // arbitrary scaling of max value on axis
|
||||
analysisManager->CreateH1(
|
||||
"hitType", "hit type;type (0=full, 1= fast);Entries", 2, -0.5, 1.5);
|
||||
|
||||
// Open an output file
|
||||
analysisManager->OpenFile();
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
void Par03RunAction::EndOfRunAction(const G4Run*)
|
||||
{
|
||||
auto analysisManager = G4AnalysisManager::Instance();
|
||||
analysisManager->Write();
|
||||
analysisManager->CloseFile();
|
||||
}
|
||||
@@ -0,0 +1,172 @@
|
||||
//
|
||||
// ********************************************************************
|
||||
// * 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 "Par03SensitiveDetector.hh"
|
||||
#include "Par03Hit.hh"
|
||||
|
||||
#include "G4HCofThisEvent.hh"
|
||||
#include "G4TouchableHistory.hh"
|
||||
#include "G4Track.hh"
|
||||
#include "G4Step.hh"
|
||||
#include "G4SDManager.hh"
|
||||
|
||||
Par03SensitiveDetector::Par03SensitiveDetector(G4String aName)
|
||||
: G4VSensitiveDetector(aName)
|
||||
{
|
||||
collectionName.insert("hits");
|
||||
}
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
Par03SensitiveDetector::Par03SensitiveDetector(G4String aName, G4int aNumLayers,
|
||||
G4int aNumRho, G4int aNumPhi)
|
||||
: G4VSensitiveDetector(aName)
|
||||
, fCellNoZ(aNumLayers)
|
||||
, fCellNoRho(aNumRho)
|
||||
, fCellNoPhi(aNumPhi)
|
||||
{
|
||||
collectionName.insert("hits");
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
Par03SensitiveDetector::~Par03SensitiveDetector() {}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
void Par03SensitiveDetector::Initialize(G4HCofThisEvent* aHCE)
|
||||
{
|
||||
fHitsCollection =
|
||||
new Par03HitsCollection(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 < fCellNoPhi; iphi++)
|
||||
for(G4int irho = 0; irho < fCellNoRho; irho++)
|
||||
for(G4int iz = 0; iz < fCellNoZ; iz++)
|
||||
{
|
||||
Par03Hit* hit = new Par03Hit();
|
||||
fHitsCollection->insert(hit);
|
||||
}
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
G4bool Par03SensitiveDetector::ProcessHits(G4Step* aStep, G4TouchableHistory*)
|
||||
{
|
||||
G4double edep = aStep->GetTotalEnergyDeposit();
|
||||
if(edep == 0.)
|
||||
return true;
|
||||
|
||||
G4TouchableHistory* aTouchable =
|
||||
(G4TouchableHistory*) (aStep->GetPreStepPoint()->GetTouchable());
|
||||
|
||||
auto hit = RetrieveAndSetupHit(aTouchable);
|
||||
|
||||
// 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 Par03SensitiveDetector::ProcessHits(const G4FastHit* aHit,
|
||||
const G4FastTrack* aTrack,
|
||||
G4TouchableHistory* aTouchable)
|
||||
{
|
||||
G4double edep = aHit->GetEnergy();
|
||||
if(edep == 0.)
|
||||
return true;
|
||||
|
||||
auto hit = RetrieveAndSetupHit(aTouchable);
|
||||
|
||||
// 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......
|
||||
|
||||
Par03Hit* Par03SensitiveDetector::RetrieveAndSetupHit(
|
||||
G4TouchableHistory* aTouchable)
|
||||
{
|
||||
G4int rhoNo = aTouchable->GetCopyNumber(0); // cell
|
||||
G4int phiNo = aTouchable->GetCopyNumber(1); // segment
|
||||
G4int zNo = aTouchable->GetCopyNumber(2); // layer
|
||||
|
||||
std::size_t hitID = fCellNoRho * fCellNoZ * phiNo + fCellNoZ * rhoNo + zNo;
|
||||
|
||||
if(hitID >= fHitsCollection->entries())
|
||||
{
|
||||
G4Exception(
|
||||
"Par03SensitiveDetector::RetrieveAndSetupHit()", "InvalidSetup",
|
||||
FatalException,
|
||||
"Size of hit collection in Par03SensitiveDetector is smaller than the "
|
||||
"number of cells created in Par03DetectorConstruction!");
|
||||
}
|
||||
Par03Hit* hit = (*fHitsCollection)[hitID];
|
||||
|
||||
if(hit->GetRhoId() < 0)
|
||||
{
|
||||
hit->SetRhoId(rhoNo);
|
||||
hit->SetPhiId(phiNo);
|
||||
hit->SetZid(zNo);
|
||||
hit->SetLogV(aTouchable->GetVolume(0)->GetLogicalVolume());
|
||||
G4AffineTransform transform = aTouchable->GetHistory()->GetTopTransform();
|
||||
hit->SetRot(transform.NetRotation());
|
||||
transform.Invert();
|
||||
hit->SetPos(transform.NetTranslation());
|
||||
}
|
||||
return hit;
|
||||
}
|
||||
Reference in New Issue
Block a user