20#include "BDSException.hh"
21#include "BDSHistBinMapper.hh"
22#include "BDSScorerConversionLoader.hh"
23#include "BDSPSPopulationScaled.hh"
24#include "BDSUtilities.hh"
26#include "G4IonTable.hh"
27#include "G4PhysicsVector.hh"
31#include "G4VPVParameterisation.hh"
40#include "src-external/gzstream/gzstream.h"
45 G4VPrimitiveScorer(scorerName, depth),
51 const G4String& pathname,
56 if (directory.back() !=
'/')
59 std::vector<G4String> dirsAngle;
60 std::vector<G4String> filesParticle;
62 dirsAngle = LoadDirectoryContents(directory);
64 G4cout <<
"Scorer \"" << GetName() <<
"\" - adding conversionFiles from: " + directory << G4endl;
66 for (
const auto& dirnameAng : dirsAngle)
68 G4String dirAng = directory + dirnameAng;
69 filesParticle = LoadDirectoryContents(dirAng);
73 G4double ang = (G4double)std::stod(dirnameAng);
74 angles.push_back(ang);
75 G4int angleIndex = (G4int)angles.size() - 1;
77 std::vector<G4int> ionPIDs;
79 for (
const auto& filePDG : filesParticle)
81 G4String filepathPDG = dirAng +
'/' + filePDG;
82 G4int pid = (G4int)std::stoi(filePDG);
84 if (filePDG.substr((filePDG.find_last_of(
".") + 1)) ==
"gz" &&
BDS::FileExists(filepathPDG))
88 conversionFactors[angleIndex][pid] = loaderC.
Load(filepathPDG,
true);
90 throw BDSException(__METHOD_NAME__,
"Compressed file loading - but BDSIM not compiled with ZLIB.");
94 {conversionFactors[angleIndex][pid] = loader.
Load(filepathPDG,
true);}
97 {ionPIDs.push_back(pid);}
99 ionParticleIDs[angleIndex] = ionPIDs;
102 G4cout <<
"Scorer \"" << GetName() <<
" Loaded data for " << angles.size() <<
" angles: [";
103 for (
auto a : angles)
106 if (a == angles.back())
110 G4cout <<
"]*rad" << G4endl;
113BDSPSPopulationScaled::~BDSPSPopulationScaled()
115 for (
const auto& af : conversionFactors)
117 for (
auto cf : af.second)
122void BDSPSPopulationScaled::Initialize(G4HCofThisEvent* HCE)
126 {HCID = GetCollectionID(0);}
128 HCE->AddHitsCollection(HCID, EvtMap);
131void BDSPSPopulationScaled::EndOfEvent(G4HCofThisEvent* )
133 fCellTrackLogger.clear();
136void BDSPSPopulationScaled::clear()
139 fCellTrackLogger.clear();
142G4bool BDSPSPopulationScaled::ProcessHits(G4Step* aStep, G4TouchableHistory*)
144 G4double stepLength = aStep->GetStepLength();
149 G4double radiationQuantity = 0;
150 G4int index = GetIndex(aStep);
151 G4TrackLogger& tlog = fCellTrackLogger[index];
153 if (tlog.FirstEnterance(aStep->GetTrack()->GetTrackID()))
155 const G4VTouchable* touchable = aStep->GetPreStepPoint()->GetTouchable();
156 auto rot = touchable->GetRotation();
157 G4ThreeVector unitZ = G4ThreeVector(0, 0, 1);
158 G4ThreeVector blmUnitZ = unitZ.transform(*rot);
160 auto momDirection = aStep->GetPreStepPoint()->GetMomentumDirection();
163 G4double angle = std::fmod(std::abs(momDirection.angle(blmUnitZ)), CLHEP::pi);
164 if (angle > CLHEP::pi/2.)
165 {angle = CLHEP::pi - angle;}
167 G4double kineticEnergy = aStep->GetPreStepPoint()->GetKineticEnergy();
168 G4double weight = aStep->GetPreStepPoint()->GetWeight();
169 G4double factor = GetConversionFactor(aStep->GetTrack()->GetDefinition()->GetPDGEncoding(),
172 radiationQuantity = weight * factor;
174 EvtMap->add(index, radiationQuantity);
180G4double BDSPSPopulationScaled::GetConversionFactor(G4int particleID,
181 G4double kineticEnergy,
182 G4double angle)
const
184 G4double angleNearestIndex = NearestNeighbourAngleIndex(angles, angle);
186 if (angleNearestIndex < 0)
189 std::map<G4int, G4PhysicsVector*> conversionFactorsPart;
190 auto searchAngle = conversionFactors.find(angleNearestIndex);
191 if (searchAngle != conversionFactors.end())
192 {conversionFactorsPart = searchAngle->second;}
196 if (particleID < 1e7)
198 auto search = conversionFactorsPart.find(particleID);
199 if (search != conversionFactorsPart.end())
200 {
return search->second->Value(kineticEnergy);}
207 G4int particleIDNearest = NearestNeighbourIonPID(ionParticleIDs.find(angleNearestIndex)->second, particleID);
208 if (particleIDNearest < 0)
212 G4double nearestIonZ = (G4double)GetZFromParticleID(particleID);
214 auto searchIon = conversionFactorsPart.find(particleIDNearest);
215 if (searchIon != conversionFactorsPart.end())
216 {
return searchIon->second->Value(kineticEnergy / nearestIonZ);}
222std::vector<G4String> BDSPSPopulationScaled::LoadDirectoryContents(
const G4String& dirname)
224 std::vector<G4String> contents;
226 struct dirent* entry =
nullptr;
229 dp = opendir(dirname.c_str());
231 {
throw BDSException(__METHOD_NAME__,
"Cannot open directory " + dirname);}
234 while ((entry = readdir(dp)) !=
nullptr)
236 std::string name_string(entry->d_name);
237 if (name_string.front() !=
'.')
238 {contents.emplace_back(name_string);}
245G4int BDSPSPopulationScaled::NearestNeighbourAngleIndex(
const std::vector<G4double>& vec, G4double value)
const
250 G4double nearestNeighbourAngle;
252 auto const it = std::upper_bound(vec.begin(), vec.end(), value) - 1;
254 {nearestNeighbourAngle = vec.back();}
256 {nearestNeighbourAngle = *it;}
258 auto const itr = std::find(vec.begin(), vec.end(), nearestNeighbourAngle);
259 auto index = (G4int) std::distance(vec.begin(), itr);
264G4int BDSPSPopulationScaled::NearestNeighbourIonPID(
const std::vector<G4int>& vec, G4int value)
const
267 std::vector<G4int> vecZ;
269 {vecZ.push_back(GetZFromParticleID(pid));}
274 G4int nearestNeighbourZ;
276 auto const it = std::upper_bound(vecZ.begin(), vecZ.end(), GetZFromParticleID(value)) - 1;
277 if (it == vecZ.end())
278 {nearestNeighbourZ = vecZ.back();}
280 {nearestNeighbourZ = *it;}
283 auto const itr = std::find(vecZ.begin(), vecZ.end(), nearestNeighbourZ);
284 int index = (int)std::distance(vecZ.begin(), itr);
286 return vec.at(index);
289G4int BDSPSPopulationScaled::GetZFromParticleID(G4int particleID)
const
295 G4IonTable::GetNucleusByEncoding(particleID, Z, A, E, lvl);
299void BDSPSPopulationScaled::PrintAll()
301 G4cout <<
" MultiFunctionalDet " << detector->GetName() << G4endl;
302 G4cout <<
" PrimitiveScorer " <<
GetName() << G4endl;
303 G4cout <<
" Number of entries " << EvtMap->entries() << G4endl;
304 auto itr = EvtMap->GetMap()->begin();
305 for (; itr != EvtMap->GetMap()->end(); itr++)
307 G4cout <<
" copy no.: " << itr->first
308 <<
" population: " << *(itr->second) / GetUnitValue()
General exception with possible name of object and message.
Primitive scorer for population in a volume with a conversion factor based on angle and kinetic energ...
BDSPSPopulationScaled(const G4String &name, G4int depth=0)
Loader for scoring conversion tables as function of energy.
G4PhysicsVector * Load(const G4String &fileName, G4bool silent=false)
Load the file.
G4String GetFullPath(G4String filename, bool excludeNameFromPath=false, bool useCWDForPrefix=false)
G4bool FileExists(const G4String &filename)
Checks if filename exists.
G4bool IsFinite(G4double value, G4double tolerance=std::numeric_limits< double >::epsilon())
const char * GetName(int)
Name of element.