19#include "BDSException.hh"
20#include "BDSHistBinMapper.hh"
21#include "BDSScorerConversionLoader.hh"
22#include "BDSPSPopulationScaled.hh"
23#include "BDSUtilities.hh"
25#include "G4IonTable.hh"
26#include "G4PhysicsVector.hh"
30#include "G4VPVParameterisation.hh"
39#include "src-external/gzstream/gzstream.h"
44 G4VPrimitiveScorer(scorerName, depth),
50 const G4String& pathname,
55 if (directory.back() !=
'/')
58 std::vector<G4String> dirsAngle;
59 std::vector<G4String> filesParticle;
61 dirsAngle = LoadDirectoryContents(directory);
63 G4cout <<
"Scorer \"" << GetName() <<
"\" - adding conversionFiles from: " + directory << G4endl;
65 for (
const auto& dirnameAng : dirsAngle)
67 G4String dirAng = directory + dirnameAng;
68 filesParticle = LoadDirectoryContents(dirAng);
72 G4double ang = (G4double)std::stod(dirnameAng);
73 angles.push_back(ang);
74 G4int angleIndex = (G4int)angles.size() - 1;
76 std::vector<G4int> ionPIDs;
78 for (
const auto& filePDG : filesParticle)
80 G4String filepathPDG = dirAng +
'/' + filePDG;
81 G4int pid = (G4int)std::stoi(filePDG);
83 if (filePDG.substr((filePDG.find_last_of(
".") + 1)) ==
"gz" &&
BDS::FileExists(filepathPDG))
87 conversionFactors[angleIndex][pid] = loaderC.
Load(filepathPDG,
true);
89 throw BDSException(__METHOD_NAME__,
"Compressed file loading - but BDSIM not compiled with ZLIB.");
93 {conversionFactors[angleIndex][pid] = loader.
Load(filepathPDG,
true);}
96 {ionPIDs.push_back(pid);}
98 ionParticleIDs[angleIndex] = ionPIDs;
101 G4cout <<
"Scorer \"" << GetName() <<
" Loaded data for " << angles.size() <<
" angles: [";
102 for (
auto a : angles)
105 if (a == angles.back())
109 G4cout <<
"]*rad" << G4endl;
112BDSPSPopulationScaled::~BDSPSPopulationScaled()
114 for (
const auto& af : conversionFactors)
116 for (
auto cf : af.second)
121void BDSPSPopulationScaled::Initialize(G4HCofThisEvent* HCE)
125 {HCID = GetCollectionID(0);}
127 HCE->AddHitsCollection(HCID, EvtMap);
130void BDSPSPopulationScaled::EndOfEvent(G4HCofThisEvent* )
132 fCellTrackLogger.clear();
135void BDSPSPopulationScaled::clear()
138 fCellTrackLogger.clear();
141G4bool BDSPSPopulationScaled::ProcessHits(G4Step* aStep, G4TouchableHistory*)
143 G4double stepLength = aStep->GetStepLength();
148 G4double radiationQuantity = 0;
149 G4int index = GetIndex(aStep);
150 G4TrackLogger& tlog = fCellTrackLogger[index];
152 if (tlog.FirstEnterance(aStep->GetTrack()->GetTrackID()))
154 const G4VTouchable* touchable = aStep->GetPreStepPoint()->GetTouchable();
155 auto rot = touchable->GetRotation();
156 G4ThreeVector unitZ = G4ThreeVector(0, 0, 1);
157 G4ThreeVector blmUnitZ = unitZ.transform(*rot);
159 auto momDirection = aStep->GetPreStepPoint()->GetMomentumDirection();
162 G4double angle = std::fmod(std::abs(momDirection.angle(blmUnitZ)), CLHEP::pi);
163 if (angle > CLHEP::pi/2.)
164 {angle = CLHEP::pi - angle;}
166 G4double kineticEnergy = aStep->GetPreStepPoint()->GetKineticEnergy();
167 G4double weight = aStep->GetPreStepPoint()->GetWeight();
168 G4double factor = GetConversionFactor(aStep->GetTrack()->GetDefinition()->GetPDGEncoding(),
171 radiationQuantity = weight * factor;
173 EvtMap->add(index, radiationQuantity);
179G4double BDSPSPopulationScaled::GetConversionFactor(G4int particleID,
180 G4double kineticEnergy,
181 G4double angle)
const
183 G4double angleNearestIndex = NearestNeighbourAngleIndex(angles, angle);
185 if (angleNearestIndex < 0)
188 std::map<G4int, G4PhysicsVector*> conversionFactorsPart;
189 auto searchAngle = conversionFactors.find(angleNearestIndex);
190 if (searchAngle != conversionFactors.end())
191 {conversionFactorsPart = searchAngle->second;}
195 if (particleID < 1e7)
197 auto search = conversionFactorsPart.find(particleID);
198 if (search != conversionFactorsPart.end())
199 {
return search->second->Value(kineticEnergy);}
206 G4int particleIDNearest = NearestNeighbourIonPID(ionParticleIDs.find(angleNearestIndex)->second, particleID);
207 if (particleIDNearest < 0)
211 G4double nearestIonZ = (G4double)GetZFromParticleID(particleID);
213 auto searchIon = conversionFactorsPart.find(particleIDNearest);
214 if (searchIon != conversionFactorsPart.end())
215 {
return searchIon->second->Value(kineticEnergy / nearestIonZ);}
221std::vector<G4String> BDSPSPopulationScaled::LoadDirectoryContents(
const G4String& dirname)
223 std::vector<G4String> contents;
225 struct dirent* entry =
nullptr;
228 dp = opendir(dirname.c_str());
230 {
throw BDSException(__METHOD_NAME__,
"Cannot open directory " + dirname);}
233 while ((entry = readdir(dp)) !=
nullptr)
235 std::string name_string(entry->d_name);
236 if (name_string.front() !=
'.')
237 {contents.emplace_back(name_string);}
244G4int BDSPSPopulationScaled::NearestNeighbourAngleIndex(
const std::vector<G4double>& vec, G4double value)
const
249 G4double nearestNeighbourAngle;
251 auto const it = std::upper_bound(vec.begin(), vec.end(), value) - 1;
253 {nearestNeighbourAngle = vec.back();}
255 {nearestNeighbourAngle = *it;}
257 auto const itr = std::find(vec.begin(), vec.end(), nearestNeighbourAngle);
258 auto index = (G4int) std::distance(vec.begin(), itr);
263G4int BDSPSPopulationScaled::NearestNeighbourIonPID(
const std::vector<G4int>& vec, G4int value)
const
266 std::vector<G4int> vecZ;
268 {vecZ.push_back(GetZFromParticleID(pid));}
273 G4int nearestNeighbourZ;
275 auto const it = std::upper_bound(vecZ.begin(), vecZ.end(), GetZFromParticleID(value)) - 1;
276 if (it == vecZ.end())
277 {nearestNeighbourZ = vecZ.back();}
279 {nearestNeighbourZ = *it;}
282 auto const itr = std::find(vecZ.begin(), vecZ.end(), nearestNeighbourZ);
283 int index = (int)std::distance(vecZ.begin(), itr);
285 return vec.at(index);
288G4int BDSPSPopulationScaled::GetZFromParticleID(G4int particleID)
const
294 G4IonTable::GetNucleusByEncoding(particleID, Z, A, E, lvl);
298void BDSPSPopulationScaled::PrintAll()
300 G4cout <<
" MultiFunctionalDet " << detector->GetName() << G4endl;
301 G4cout <<
" PrimitiveScorer " <<
GetName() << G4endl;
302 G4cout <<
" Number of entries " << EvtMap->entries() << G4endl;
303 auto itr = EvtMap->GetMap()->begin();
304 for (; itr != EvtMap->GetMap()->end(); itr++)
306 G4cout <<
" copy no.: " << itr->first
307 <<
" 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.