97 #include "Geant4/G4Alpha.hh"
98 #include "Geant4/G4DynamicParticle.hh"
99 #include "Geant4/G4Electron.hh"
100 #include "Geant4/G4ExceptionSeverity.hh"
101 #include "Geant4/G4Gamma.hh"
102 #include "Geant4/G4KaonMinus.hh"
103 #include "Geant4/G4KaonPlus.hh"
104 #include "Geant4/G4Material.hh"
105 #include "Geant4/G4MaterialPropertiesTable.hh"
106 #include "Geant4/G4MaterialPropertyVector.hh"
107 #include "Geant4/G4MaterialTable.hh"
108 #include "Geant4/G4MuonMinus.hh"
109 #include "Geant4/G4MuonPlus.hh"
110 #include "Geant4/G4ParticleChange.hh"
111 #include "Geant4/G4PhysicsVector.hh"
112 #include "Geant4/G4PionMinus.hh"
113 #include "Geant4/G4PionPlus.hh"
114 #include "Geant4/G4Poisson.hh"
115 #include "Geant4/G4Proton.hh"
116 #include "Geant4/G4Step.hh"
117 #include "Geant4/G4StepPoint.hh"
118 #include "Geant4/G4Track.hh"
119 #include "Geant4/G4VPhysicalVolume.hh"
120 #include "Geant4/G4ios.hh"
121 #include "Geant4/Randomize.hh"
122 #include "Geant4/globals.hh"
142 #include "cetlib_except/exception.h"
143 #include "messagefacility/MessageLogger/MessageLogger.h"
146 #include "TRandom3.h"
147 #include "TGeoSphere.h"
153 #include "boost/math/special_functions/ellint_1.hpp"
154 #include "boost/math/special_functions/ellint_3.hpp"
157 typedef boost::math::policies::policy<
159 boost::math::policies::promote_double<false>>
181 : G4VRestDiscreteProcess(processName, type)
183 , bPropagate(!(art::ServiceHandle<sim::LArG4Parameters const>()->NoPhotonPropagation()))
184 , fPVS(bPropagate ? art::ServiceHandle<phot::PhotonVisibilityService const>().
get() :
nullptr)
185 , fUseNhitsModel(fPVS && fPVS->UseNhitsModel())
187 , fOnlyActiveVolume(usesSemiAnalyticModel())
189 SetProcessSubType(25);
190 fTrackSecondariesFirst =
false;
191 fFiniteRiseTime =
false;
193 ExcitationRatio = 1.0;
199 if (verboseLevel > 0) { G4cout << GetProcessName() <<
" is created " << G4endl; }
201 BuildThePhysicsTable();
211 auto log = mf::LogTrace(
"OpFastScintillation")
212 <<
"OpFastScintillation: active volume boundaries from " << fActiveVolumes.size()
215 log <<
"\n - C:" << iCryo <<
": " << box.Min() <<
" -- " << box.Max() <<
" cm";
217 log <<
"\n (scintillation photons are propagated "
218 << (fOnlyActiveVolume ?
"only from active volumes" :
"from anywhere") <<
")";
221 if (usesSemiAnalyticModel() && (geom.
Ncryostats() > 1U)) {
222 if (fOnlyOneCryostat) {
223 mf::LogWarning(
"OpFastScintillation")
224 << std::string(80,
'=') <<
"\nA detector with " << geom.
Ncryostats()
225 <<
" cryostats is configured"
226 <<
" , and semi-analytic model is requested for scintillation photon propagation."
227 <<
" THIS CONFIGURATION IS NOT SUPPORTED and it is open to bugs"
228 <<
" (e.g. scintillation may be detected only in cryostat #0)."
229 <<
"\nThis would be normally a fatal error, but it has been forcibly overridden."
231 << std::string(80,
'=');
234 throw art::Exception(art::errors::Configuration)
235 <<
"Photon propagation via semi-analytic model is not supported yet"
236 <<
" on detectors with more than one cryostat.";
241 fActiveVolumes[0].CenterY(),
242 fActiveVolumes[0].CenterZ()};
243 mf::LogTrace(
"OpFastScintillation") <<
"Cathode_centre: " << Cathode_centre <<
" cm";
253 fOpDetCenter.push_back(opDet.
GetCenter());
255 if (dynamic_cast<TGeoSphere const*>(opDet.
Shape()) !=
nullptr) {
256 fOpDetType.push_back(1);
257 fOpDetLength.push_back(-1);
258 fOpDetHeight.push_back(-1);
260 else if (opDet.
isBar()) {
261 fOpDetType.push_back(0);
262 fOpDetLength.push_back(opDet.
Length());
263 fOpDetHeight.push_back(opDet.
Height());
266 fOpDetType.push_back(2);
268 fOpDetLength.push_back(-1);
269 fOpDetHeight.push_back(-1);
273 if (fPVS->IncludePropTime()) {
274 std::cout <<
"Using parameterisation of timings." << std::endl;
279 fPVS->LoadTimingsForVUVPar(fparameters,
285 finflexion_point_distance,
286 fangle_bin_timing_vuv);
290 const size_t num_params = (fmax_d - fmin_d) / fstep_size;
291 size_t num_angles = std::round(90/fangle_bin_timing_vuv);
300 if (fPVS->StoreReflected()) {
302 fPVS->LoadTimingsForVISPar( fdistances_refl,
303 fradial_distances_refl,
307 fangle_bin_timing_vis);
310 if (usesSemiAnalyticModel()) {
311 mf::LogVerbatim(
"OpFastScintillation")
312 <<
"OpFastScintillation: using semi-analytic model for number of hits";
315 std::map<double, double> abs_length_spectrum =
317 std::vector<double> x_v, y_v;
318 for (
auto elem : abs_length_spectrum) {
319 x_v.push_back(elem.first);
320 y_v.push_back(elem.second);
323 std::round(interpolate(x_v, y_v, 9.7,
false));
326 std::cout <<
"Loading the GH corrections" << std::endl;
327 fPVS->LoadVUVSemiAnalyticProperties(fIsFlatPDCorr,
332 if (!fIsFlatPDCorr && !fIsDomePDCorr) {
333 throw cet::exception(
"OpFastScintillation")
334 <<
"Both isFlatPDCorr and isDomePDCorr parameters are false, at least one type of parameterisation is required for the semi-analytic light simulation." <<
"\n";
337 fPVS->LoadGHFlat(fGHvuvpars_flat,
338 fborder_corr_angulo_flat,
343 fPVS->LoadGHDome(fGHvuvpars_dome,
344 fborder_corr_angulo_dome,
350 fcathode_centre[1] = fActiveVolumes[0].CenterY();
351 fcathode_centre[2] = fActiveVolumes[0].CenterZ();
354 if (fPVS->StoreReflected()) {
355 fStoreReflected =
true;
357 std::cout <<
"Loading visible light corrections" << std::endl;
358 fPVS->LoadVisSemiAnalyticProperties(fdelta_angulo_vis,
362 fPVS->LoadVisParsFlat(fvis_distances_x_flat,
363 fvis_distances_r_flat,
368 fPVS->LoadVisParsDome(fvis_distances_x_dome,
369 fvis_distances_r_dome,
375 fcathode_ydimension = fActiveVolumes[0].SizeY();
376 fcathode_zdimension = fActiveVolumes[0].SizeZ();
379 fcathode_plane.h = fcathode_ydimension;
380 fcathode_plane.w = fcathode_zdimension;
381 fplane_depth =
std::abs(fcathode_centre[0]);
384 fStoreReflected =
false;
387 tpbemission = lar::providerFrom<detinfo::LArPropertiesService>()->TpbEm();
388 std::vector<double> parent;
389 parent.reserve(tpbemission.size());
390 for (
auto iter = tpbemission.begin(); iter != tpbemission.end(); ++iter) {
391 parent.push_back(iter->second);
393 fTPBEm = std::make_unique<CLHEP::RandGeneral>
394 (parent.data(), parent.size());
431 aParticleChange.Initialize(aTrack);
434 const G4Material* aMaterial = aTrack.GetMaterial();
435 G4MaterialPropertiesTable* aMaterialPropertiesTable = aMaterial->GetMaterialPropertiesTable();
436 if (!aMaterialPropertiesTable)
return G4VRestDiscreteProcess::PostStepDoIt(aTrack, aStep);
438 G4StepPoint* pPreStepPoint = aStep.GetPreStepPoint();
439 G4ThreeVector x0 = pPreStepPoint->GetPosition();
440 G4ThreeVector p0 = aStep.GetDeltaPosition().unit();
488 aParticleChange.SetNumberOfSecondaries(0);
510 double MeanNumberOfPhotons =
514 if (verboseLevel > 0) {
515 G4cout <<
"\n Exiting from OpFastScintillation::DoIt -- NumberOfSecondaries = "
516 << aParticleChange.GetNumberOfSecondaries() << G4endl;
518 return G4VRestDiscreteProcess::PostStepDoIt(aTrack, aStep);
524 if (step.GetTotalEnergyDeposit() <= 0)
return;
530 (
double)(step.GetTotalEnergyDeposit() /
CLHEP::MeV),
531 (
float)(step.GetPreStepPoint()->GetPosition().x() / CLHEP::cm),
532 (
float)(step.GetPreStepPoint()->GetPosition().y() / CLHEP::cm),
533 (
float)(step.GetPreStepPoint()->GetPosition().z() / CLHEP::cm),
534 (
float)(step.GetPostStepPoint()->GetPosition().x() / CLHEP::cm),
535 (
float)(step.GetPostStepPoint()->GetPosition().y() / CLHEP::cm),
536 (
float)(step.GetPostStepPoint()->GetPosition().z() / CLHEP::cm),
537 (
double)(step.GetPreStepPoint()->GetGlobalTime()),
538 (
double)(step.GetPostStepPoint()->GetGlobalTime()),
541 step.GetTrack()->GetParticleDefinition()->GetPDGEncoding(),
543 step.GetPreStepPoint()->GetPhysicalVolume()->GetName());
547 double MeanNumberOfPhotons)
550 art::ServiceHandle<sim::LArG4Parameters const> lgp;
551 if (lgp->FillSimEnergyDeposits())
ProcessStep(aStep);
556 const G4Track* aTrack = aStep.GetTrack();
558 G4StepPoint
const* pPreStepPoint = aStep.GetPreStepPoint();
561 const G4DynamicParticle* aParticle = aTrack->GetDynamicParticle();
562 const G4Material* aMaterial = aTrack->GetMaterial();
564 G4int materialIndex = aMaterial->GetIndex();
565 G4int tracknumber = aStep.GetTrack()->GetTrackID();
567 G4ThreeVector x0 = pPreStepPoint->GetPosition();
568 G4ThreeVector p0 = aStep.GetDeltaPosition().unit();
570 G4double
t0 = pPreStepPoint->GetGlobalTime();
572 G4MaterialPropertiesTable* aMaterialPropertiesTable = aMaterial->GetMaterialPropertiesTable();
574 G4MaterialPropertyVector* Fast_Intensity =
575 aMaterialPropertiesTable->GetProperty(
"FASTCOMPONENT");
576 G4MaterialPropertyVector* Slow_Intensity =
577 aMaterialPropertiesTable->GetProperty(
"SLOWCOMPONENT");
579 if (!Fast_Intensity && !Slow_Intensity)
return 1;
587 if (Fast_Intensity && Slow_Intensity) nscnt = 2;
590 double YieldRatio = 0;
592 if (scintillationByParticleType) {
597 G4ParticleDefinition* pDef = aParticle->GetDefinition();
604 if (pDef == G4Proton::ProtonDefinition()) {
605 YieldRatio = aMaterialPropertiesTable->GetConstProperty(
"PROTONYIELDRATIO");
608 else if (pDef == G4MuonPlus::MuonPlusDefinition() ||
609 pDef == G4MuonMinus::MuonMinusDefinition()) {
610 YieldRatio = aMaterialPropertiesTable->GetConstProperty(
"MUONYIELDRATIO");
613 else if (pDef == G4PionPlus::PionPlusDefinition() ||
614 pDef == G4PionMinus::PionMinusDefinition()) {
615 YieldRatio = aMaterialPropertiesTable->GetConstProperty(
"PIONYIELDRATIO");
618 else if (pDef == G4KaonPlus::KaonPlusDefinition() ||
619 pDef == G4KaonMinus::KaonMinusDefinition()) {
620 YieldRatio = aMaterialPropertiesTable->GetConstProperty(
"KAONYIELDRATIO");
623 else if (pDef == G4Alpha::AlphaDefinition()) {
624 YieldRatio = aMaterialPropertiesTable->GetConstProperty(
"ALPHAYIELDRATIO");
628 else if (pDef == G4Electron::ElectronDefinition() || pDef == G4Gamma::GammaDefinition()) {
629 YieldRatio = aMaterialPropertiesTable->GetConstProperty(
"ELECTRONYIELDRATIO");
633 YieldRatio = aMaterialPropertiesTable->GetConstProperty(
"ELECTRONYIELDRATIO");
638 if (YieldRatio == 0) {
639 YieldRatio = aMaterialPropertiesTable->GetConstProperty(
"ELECTRONYIELDRATIO");
643 geo::Point_t const ScintPoint = {x0[0] / CLHEP::cm, x0[1] / CLHEP::cm, x0[2] / CLHEP::cm};
682 for (G4int scnt = 1; scnt <= nscnt; scnt++) {
683 G4double ScintillationTime = 0. * CLHEP::ns;
684 G4double ScintillationRiseTime = 0. * CLHEP::ns;
685 G4PhysicsOrderedFreeVector* ScintillationIntegral = NULL;
688 if (Fast_Intensity) {
689 ScintillationTime = aMaterialPropertiesTable->GetConstProperty(
"FASTTIMECONSTANT");
691 ScintillationRiseTime =
692 aMaterialPropertiesTable->GetConstProperty(
"FASTSCINTILLATIONRISETIME");
694 ScintillationIntegral =
697 if (Slow_Intensity) {
698 ScintillationTime = aMaterialPropertiesTable->GetConstProperty(
"SLOWTIMECONSTANT");
700 ScintillationRiseTime =
701 aMaterialPropertiesTable->GetConstProperty(
"SLOWSCINTILLATIONRISETIME");
703 ScintillationIntegral =
709 YieldRatio = aMaterialPropertiesTable->GetConstProperty(
"YIELDRATIO");
711 if (
ExcitationRatio == 1.0) { Num = std::min(YieldRatio, 1.0) * MeanNumberOfPhotons; }
715 ScintillationTime = aMaterialPropertiesTable->GetConstProperty(
"FASTTIMECONSTANT");
717 ScintillationRiseTime =
718 aMaterialPropertiesTable->GetConstProperty(
"FASTSCINTILLATIONRISETIME");
720 ScintillationIntegral =
726 Num = MeanNumberOfPhotons - Num;
727 ScintillationTime = aMaterialPropertiesTable->GetConstProperty(
"SLOWTIMECONSTANT");
729 ScintillationRiseTime =
730 aMaterialPropertiesTable->GetConstProperty(
"SLOWSCINTILLATIONRISETIME");
732 ScintillationIntegral =
736 if (!ScintillationIntegral)
continue;
751 std::map<size_t, int> DetectedNum;
755 int const DetThis = std::round(G4Poisson(Visibilities[OpDet] * Num));
756 if (DetThis > 0) DetectedNum[OpDet] = DetThis;
764 std::map<size_t, int> ReflDetectedNum;
769 int const ReflDetThis = std::round(G4Poisson(ReflVisibilities[OpDet] * Num));
770 if (ReflDetThis > 0) ReflDetectedNum[OpDet] = ReflDetThis;
778 std::vector<double> arrival_time_dist;
780 for (
size_t Reflected = 0; Reflected <= 1; ++Reflected) {
784 std::map<size_t, int>::const_iterator itstart;
785 std::map<size_t, int>::const_iterator itend;
787 itstart = ReflDetectedNum.begin();
788 itend = ReflDetectedNum.end();
791 itstart = DetectedNum.begin();
792 itend = DetectedNum.end();
794 for (
auto itdetphot = itstart; itdetphot != itend; ++itdetphot) {
795 const size_t OpChannel = itdetphot->first;
796 const int NPhotons = itdetphot->second;
803 double Edeposited = 0;
804 if (scintillationByParticleType) {
806 Edeposited = aStep.GetTotalEnergyDeposit();
815 Edeposited = aStep.GetTotalEnergyDeposit();
819 arrival_time_dist.resize(NPhotons);
823 Edeposited = Edeposited / double(NPhotons);
826 for (G4int i = 0; i < NPhotons; ++i) {
828 G4double Time = t0 +
scint_time(aStep, ScintillationTime, ScintillationRiseTime) +
829 arrival_time_dist[i] * CLHEP::ns;
835 if (lgp->UseLitePhotons()) {
836 fst->
AddLitePhoton(OpChannel, static_cast<int>(Time), 1, Reflected);
840 TVector3 PhotonPosition(x0[0], x0[1], x0[2]);
842 float PhotonEnergy = 0;
846 PhotonEnergy = 9.7 * CLHEP::eV;
851 PhotToAdd.
Energy = PhotonEnergy;
852 PhotToAdd.
Time = Time;
856 fst->
AddPhoton(OpChannel, std::move(PhotToAdd), Reflected);
875 const G4MaterialTable* theMaterialTable = G4Material::GetMaterialTable();
876 G4int numOfMaterials = G4Material::GetNumberOfMaterials();
885 for (G4int i = 0; i < numOfMaterials; i++) {
886 G4PhysicsOrderedFreeVector* aPhysicsOrderedFreeVector =
new G4PhysicsOrderedFreeVector();
887 G4PhysicsOrderedFreeVector* bPhysicsOrderedFreeVector =
new G4PhysicsOrderedFreeVector();
891 G4Material* aMaterial = (*theMaterialTable)[i];
893 G4MaterialPropertiesTable* aMaterialPropertiesTable = aMaterial->GetMaterialPropertiesTable();
895 if (aMaterialPropertiesTable) {
897 G4MaterialPropertyVector* theFastLightVector =
898 aMaterialPropertiesTable->GetProperty(
"FASTCOMPONENT");
900 if (theFastLightVector) {
903 G4double currentIN = (*theFastLightVector)[0];
904 if (currentIN >= 0.0) {
907 G4double currentPM = theFastLightVector->Energy(0);
908 G4double currentCII = 0.0;
910 aPhysicsOrderedFreeVector->InsertValues(currentPM, currentCII);
913 G4double prevPM = currentPM;
914 G4double prevCII = currentCII;
915 G4double prevIN = currentIN;
919 for (
size_t i = 1; i < theFastLightVector->GetVectorLength(); i++) {
920 currentPM = theFastLightVector->Energy(i);
921 currentIN = (*theFastLightVector)[i];
923 currentCII = 0.5 * (prevIN + currentIN);
925 currentCII = prevCII + (currentPM - prevPM) * currentCII;
927 aPhysicsOrderedFreeVector->InsertValues(currentPM, currentCII);
930 prevCII = currentCII;
936 G4MaterialPropertyVector* theSlowLightVector =
937 aMaterialPropertiesTable->GetProperty(
"SLOWCOMPONENT");
938 if (theSlowLightVector) {
941 G4double currentIN = (*theSlowLightVector)[0];
942 if (currentIN >= 0.0) {
945 G4double currentPM = theSlowLightVector->Energy(0);
946 G4double currentCII = 0.0;
948 bPhysicsOrderedFreeVector->InsertValues(currentPM, currentCII);
951 G4double prevPM = currentPM;
952 G4double prevCII = currentCII;
953 G4double prevIN = currentIN;
957 for (
size_t i = 1; i < theSlowLightVector->GetVectorLength(); i++) {
958 currentPM = theSlowLightVector->Energy(i);
959 currentIN = (*theSlowLightVector)[i];
961 currentCII = 0.5 * (prevIN + currentIN);
963 currentCII = prevCII + (currentPM - prevPM) * currentCII;
965 bPhysicsOrderedFreeVector->InsertValues(currentPM, currentCII);
968 prevCII = currentCII;
988 G4Exception(
"OpFastScintillation::SetScintillationByParticleType",
991 "Redefinition: Birks Saturation is replaced by ScintillationByParticleType!");
994 scintillationByParticleType = scintType;
1000 *condition = StronglyForced;
1007 *condition = Forced;
1013 G4double ScintillationTime,
1014 G4double ScintillationRiseTime)
const
1016 G4StepPoint
const* pPreStepPoint = aStep.GetPreStepPoint();
1017 G4StepPoint
const* pPostStepPoint = aStep.GetPostStepPoint();
1018 G4double avgVelocity = (pPreStepPoint->GetVelocity() + pPostStepPoint->GetVelocity()) / 2.;
1019 G4double deltaTime = aStep.GetStepLength() / avgVelocity;
1020 if (ScintillationRiseTime == 0.0) {
1021 deltaTime = deltaTime - ScintillationTime * std::log(G4UniformRand());
1024 deltaTime = deltaTime +
sample_time(ScintillationRiseTime, ScintillationTime);
1031 const size_t OpChannel,
1036 throw cet::exception(
"OpFastScintillation")
1037 <<
"Cannot have both propagation time models simultaneously.";
1043 G4cout <<
"WARNING: Requested parameterized timing, but no function found. Not applying "
1049 throw cet::exception(
"OpFastScintillation")
1050 <<
"No parameterized propagation time for reflected light";
1051 for (
size_t i = 0; i < arrival_time_dist.size(); ++i) {
1059 const G4ThreeVector OpDetPoint(
1060 opDetCenter.X() * CLHEP::cm, opDetCenter.Y() * CLHEP::cm, opDetCenter.Z() * CLHEP::cm);
1061 double distance_in_cm = (x0 - OpDetPoint).mag() / CLHEP::cm;
1062 double cosine =
std::abs(x0[0]*CLHEP::cm - OpDetPoint[0]*CLHEP::cm) / distance_in_cm;
1065 getVUVTimes(arrival_time_dist, distance_in_cm, angle_bin);
1068 TVector3
const ScintPoint(x0[0] / CLHEP::cm, x0[1] / CLHEP::cm, x0[2] / CLHEP::cm);
1080 G4double ran1 = G4UniformRand();
1081 G4double ran2 = G4UniformRand();
1085 G4double d = (tau1 + tau2) / tau2;
1088 G4double t = -1.0 * tau2 * std::log(1 - ran1);
1090 if (ran2 <=
bi_exp(t, tau1, tau2) / g)
return t;
1105 CLHEP::Hep3Vector prePoint = (aStep.GetPreStepPoint())->GetPosition();
1106 CLHEP::Hep3Vector postPoint = (aStep.GetPostStepPoint())->GetPosition();
1107 xyzPos[0] = (((prePoint.getX() + postPoint.getX()) / 2.0) / CLHEP::cm);
1108 xyzPos[1] = (((prePoint.getY() + postPoint.getY()) / 2.0) / CLHEP::cm);
1109 xyzPos[2] = (((prePoint.getZ() + postPoint.getZ()) / 2.0) / CLHEP::cm);
1259 const double signal_t_range = 5000.;
1270 std::array<double, 3> pars_landau;
1281 double pars_far[4] = {t_direct_min, pars_landau[0], pars_landau[1], pars_landau[2]};
1283 fVUVTiming = TF1(
"fVUVTiming",
model_far, 0, signal_t_range, 4);
1284 fVUVTiming.SetParameters(pars_far);
1288 fVUVTiming = TF1(
"fVUVTiming",
model_close, 0, signal_t_range, 7);
1290 double pars_expo[2];
1294 pars_expo[0] *= pars_landau[2];
1295 pars_expo[0] = std::log(pars_expo[0]);
1297 TF1 fint = TF1(
"fint",
finter_d, pars_landau[0], 4 * t_direct_mean, 5);
1298 double parsInt[5] = {
1299 pars_landau[0], pars_landau[1], pars_landau[2], pars_expo[0], pars_expo[1]};
1300 fint.SetParameters(parsInt);
1301 double t_int = fint.GetMinimumX();
1302 double minVal = fint.Eval(t_int);
1304 if (minVal > 0.015) {
1305 std::cout <<
"WARNING: Parametrization of VUV light discontinuous for distance = "
1306 << distance_in_cm << std::endl;
1307 std::cout <<
"WARNING: This shouldn't be happening " << std::endl;
1309 double parsfinal[7] = {t_int,
1316 fVUVTiming.SetParameters(parsfinal);
1322 if (distance_in_cm < 50) { fsampling = 10000; }
1323 else if (distance_in_cm < 100) {
1329 fVUVTiming.SetNpx(fsampling);
1333 const size_t nq_max = 1;
1334 double xq_max[nq_max];
1335 double yq_max[nq_max];
1337 fVUVTiming.GetQuantiles(nq_max, yq_max, xq_max);
1338 double max = yq_max[0];
1340 double min = t_direct_min;
1346 VUV_max[angle_bin][index] = max;
1347 VUV_min[angle_bin][index] = min;
1357 for (
size_t i = 0; i < arrivalTimes.size(); ++i) {
1358 arrivalTimes[i] = t_prop_correction;
1367 for (
size_t i = 0; i < arrivalTimes.size(); ++i) {
1376 const TVector3 &ScintPoint,
1377 const TVector3 &OpDetPoint)
1385 if (ScintPoint[0] < 0) { plane_depth = -
fplane_depth; }
1391 TVector3 bounce_point(plane_depth,ScintPoint[1],ScintPoint[2]);
1394 double VUVdist = (bounce_point - ScintPoint).Mag();
1395 double Visdist = (OpDetPoint - bounce_point).Mag();
1398 int angle_bin_vuv = 0;
1399 getVUVTimes(arrivalTimes, VUVdist, angle_bin_vuv);
1402 for (
size_t i = 0; i < arrivalTimes.size(); ++i) {
1421 vuv_time =
VUV_min[angle_bin_vuv][index];
1424 double fastest_time = vis_time + vuv_time;
1427 double cosine_theta =
std::abs(OpDetPoint[0] - bounce_point[0]) / Visdist;
1434 double distance_cathode_plane =
std::abs(plane_depth - ScintPoint[0]);
1444 for (
size_t i = 0; i <
fcut_off_pars[theta_bin].size(); i++){
1452 std::vector<double> interp_vals_tau(
ftau_pars[theta_bin].
size(), 0.0);
1453 for (
size_t i = 0; i <
ftau_pars[theta_bin].size(); i++){
1459 if (tau < 0) { tau = 0; }
1462 for (
size_t i = 0; i < arrivalTimes.size(); ++i) {
1463 double arrival_time_smeared;
1465 if (arrivalTimes[i] >= cutoff) {
continue; }
1473 if (counter >= 10) {
1474 arrival_time_smeared = arrivalTimes[i];
1479 double x = gRandom->Uniform(0.5, 1.0);
1481 arrival_time_smeared =
1482 arrivalTimes[i] + (arrivalTimes[i] - fastest_time) * (std::pow(x, -tau) - 1);
1485 }
while (arrival_time_smeared > cutoff);
1487 arrivalTimes[i] = arrival_time_smeared;
1511 const int DetThis =
VUVHits(Num, ScintPoint, op);
1513 DetectedNum[OpDet] = DetThis;
1532 if (ScintPoint.X() < 0.) { plane_depth = -
fplane_depth; }
1538 std::array<double, 3> ScintPoint_relative = {
std::abs(ScintPoint.X() - plane_depth),
1547 double distance_cathode =
std::abs(plane_depth - ScintPoint.X());
1550 (solid_angle_cathode / (4. *
CLHEP::pi)) * Num;
1554 double pars_ini[4] = {0, 0, 0, 0};
1555 double s1 = 0;
double s2 = 0;
double s3 = 0;
1565 else std::cout <<
"Error: flat optical detector VUV correction required for reflected semi-analytic hits." << std::endl;
1568 pars_ini[0] = pars_ini[0] + s1 *
r;
1569 pars_ini[1] = pars_ini[1] + s2 *
r;
1570 pars_ini[2] = pars_ini[2] + s3 *
r;
1571 pars_ini[3] = pars_ini[3];
1575 double GH_correction =
Gaisser_Hillas(distance_cathode, pars_ini);
1576 const double cathode_hits_rec = GH_correction * cathode_hits_geo;
1579 const std::array<double, 3> hotspot = {plane_depth, ScintPoint.Y(), ScintPoint.Z()};
1588 int const ReflDetThis =
1589 VISHits(ScintPoint, op, cathode_hits_rec, hotspot);
1590 if (ReflDetThis > 0) { ReflDetectedNum[OpDet] = ReflDetThis; }
1601 std::array<double, 3U> ScintPoint;
1602 std::array<double, 3U> OpDetPoint;
1607 double distance =
dist(&ScintPoint[0], &OpDetPoint[0], 3);
1613 double solid_angle = 0;
1615 if (opDet.
type == 0) {
1617 std::array<double, 3> ScintPoint_rel = {
std::abs(ScintPoint[0] - OpDetPoint[0]),
1618 std::abs(ScintPoint[1] - OpDetPoint[1]),
1619 std::abs(ScintPoint[2] - OpDetPoint[2])};
1624 else if (opDet.
type == 1) {
1628 else if (opDet.
type == 2) {
1630 double d =
dist(&ScintPoint[1], &OpDetPoint[1], 2);
1632 double h =
std::abs(ScintPoint[0] - OpDetPoint[0]);
1637 std::cout <<
"Error: Invalid optical detector type. 0 = rectangular, 1 = dome, 2 = disk" << std::endl;
1650 double pars_ini[4] = {0, 0, 0, 0};
1651 double s1 = 0;
double s2 = 0;
double s3 = 0;
1672 else std::cout <<
"Error: Invalid optical detector type. 0 = rectangular, 1 = dome, 2 = disk. Or corrections for chosen optical detector type missing." << std::endl;
1675 pars_ini[0] = pars_ini[0] + s1 *
r;
1676 pars_ini[1] = pars_ini[1] + s2 *
r;
1677 pars_ini[2] = pars_ini[2] + s3 *
r;
1678 pars_ini[3] = pars_ini[3];
1684 double hits_rec = GH_correction * hits_geo / cosine;
1685 int hits_vuv = std::round(G4Poisson(hits_rec));
1694 const double cathode_hits_rec,
1695 const std::array<double, 3> hotspot)
const
1703 if (ScintPoint_v.X() < 0.) { plane_depth = -
fplane_depth; }
1712 std::array<double, 3U> ScintPoint;
1713 std::array<double, 3U> OpDetPoint;
1719 double distance_vis =
dist(&hotspot[0], &OpDetPoint[0], 3);
1721 double cosine_vis =
std::abs(hotspot[0] - OpDetPoint[0]) / distance_vis;
1726 double solid_angle_detector = 0;
1728 if (opDet.
type == 0) {
1730 std::array<double, 3> emission_relative = {
std::abs(hotspot[0] - OpDetPoint[0]),
1731 std::abs(hotspot[1] - OpDetPoint[1]),
1732 std::abs(hotspot[2] - OpDetPoint[2])};
1737 else if (opDet.
type == 1) {
1741 else if (opDet.
type == 2) {
1743 double d =
dist(&hotspot[1], &OpDetPoint[1], 2);
1745 double h =
std::abs(hotspot[0] - OpDetPoint[0]);
1750 std::cout <<
"Error: Invalid optical detector type. 0 = rectangular, 1 = dome, 2 = disk" << std::endl;
1754 double hits_geo = (solid_angle_detector / (2. *
CLHEP::pi)) * cathode_hits_rec;
1759 double d_c =
std::abs(ScintPoint[0] - plane_depth);
1760 double border_correction = 0;
1765 std::vector<double> interp_vals(nbins_r, 0.0);
1775 for (
size_t i = 0; i < nbins_r; ++i) {
1790 std::vector<double> interp_vals(nbins_r, 0.0);
1800 for (
size_t i = 0; i < nbins_r; ++i) {
1812 std::cout <<
"Error: Invalid optical detector type. 0 = rectangular, 1 = dome, 2 = disk. Or corrections for chosen optical detector type missing." << std::endl;
1816 double hits_rec = border_correction * hits_geo / cosine_vis;
1817 double hits_vis = std::round(G4Poisson(hits_rec));
1829 if (((ScintPoint.X() < 0.) != (OpDetPoint.X() < 0.)) &&
1846 return std::exp(-1.0 * t / tau2) / tau2;
1852 return std::exp(-1.0 * t / tau2) * (1 -
std::exp(-1.0 * t / tau1)) / tau2 / tau2 *
1859 double X_mu_0 = par[3];
1860 double Normalization = par[0];
1861 double Diff = par[1] - X_mu_0;
1862 double Term = std::pow((x - X_mu_0) / Diff, Diff / par[2]);
1863 double Exponential =
std::exp((par[1] - x) / par[2]);
1864 return (Normalization * Term * Exponential);
1870 double y1 = par[2] * TMath::Landau(x[0], par[0], par[1]);
1871 double y2 = TMath::Exp(par[3] + x[0] * par[4]);
1872 return TMath::Abs(y1 - y2);
1884 double y1 = par[3] * TMath::Landau(x[0], par[1], par[2]);
1885 double y2 = TMath::Exp(par[4] + x[0] * par[5]);
1886 if (x[0] > par[0]) y1 = 0.;
1887 if (x[0] < par[0]) y2 = 0.;
1894 double y1 = par[2] * TMath::Landau(x[0], par[0], par[1]);
1895 double y2 = par[5] * TMath::Landau(x[0], par[3], par[4]);
1896 return TMath::Abs(y1 - y2);
1909 double y1 = par[3] * TMath::Landau(x[0], par[1], par[2]);
1910 double y2 = TMath::Exp(par[4] + x[0] * par[5]);
1911 if (x[0] <= par[6] || x[0] > par[0]) y1 = 0.;
1912 if (x[0] < par[0]) y2 = 0.;
1923 double y = par[3] * TMath::Landau(x[0], par[1], par[2]);
1924 if (x[0] <= par[0]) y = 0.;
1934 const std::vector<double>& yData,
1940 size_t size = xData.size();
1941 if (x >= xData[size - 2]) {
1945 while (x > xData[i + 1])
1949 double xL = xData[i];
1950 double xR = xData[i + 1];
1951 double yL = yData[i];
1952 double yR = yData[i + 1];
1954 if (x < xL)
return yL;
1955 if (x > xR)
return yL;
1957 const double dydx = (yR - yL) / (xR - xL);
1958 return yL + dydx * (x - xL);
1963 const std::vector<double>& xData,
1964 const std::vector<double>& yData1,
1965 const std::vector<double>& yData2,
1966 const std::vector<double>& yData3,
1968 bool extrapolate)
const
1970 size_t size = xData.size();
1972 if (x >= xData[size - 2]) {
1976 while (x > xData[i + 1])
1979 double xL = xData[i];
1980 double xR = xData[i + 1];
1981 double yL1 = yData1[i];
1982 double yR1 = yData1[i + 1];
1983 double yL2 = yData2[i];
1984 double yR2 = yData2[i + 1];
1985 double yL3 = yData3[i];
1986 double yR3 = yData3[i + 1];
2002 const double m = (x - xL) / (xR - xL);
2003 inter[0] = m * (yR1 - yL1) + yL1;
2004 inter[1] = m * (yR2 - yL2) + yL2;
2005 inter[2] = m * (yR3 - yL3) + yL3;
2016 if (b <= 0. || d < 0. || h <= 0.)
return 0.;
2017 const double leg2 = (b + d) * (b + d);
2018 const double aa = std::sqrt(h * h / (h * h + leg2));
2019 if (isApproximatelyZero(d)) {
return 2. *
CLHEP::pi * (1. - aa); }
2020 double bb = 2. * std::sqrt(b * d / (h * h + leg2));
2021 double cc = 4. * b * d / leg2;
2023 if (isDefinitelyGreaterThan(d, b)) {
2029 catch (std::domain_error&
e) {
2030 if (isApproximatelyEqual(d, b, 1e-9)) {
2031 mf::LogWarning(
"OpFastScintillation")
2032 <<
"Elliptic Integral in Disk_SolidAngle() given parameters outside domain."
2033 <<
"\nbb: " << bb <<
"\ncc: " << cc <<
"\nException message: " << e.what()
2034 <<
"\nRelax condition and carry on.";
2038 mf::LogError(
"OpFastScintillation")
2039 <<
"Elliptic Integral inside Disk_SolidAngle() given parameters outside domain.\n"
2040 <<
"\nbb: " << bb <<
"\ncc: " << cc <<
"Exception message: " << e.what();
2045 if (isDefinitelyLessThan(d, b)) {
2052 catch (std::domain_error&
e) {
2053 if (isApproximatelyEqual(d, b, 1e-9)) {
2054 mf::LogWarning(
"OpFastScintillation")
2055 <<
"Elliptic Integral in Disk_SolidAngle() given parameters outside domain."
2056 <<
"\nbb: " << bb <<
"\ncc: " << cc <<
"\nException message: " << e.what()
2057 <<
"\nRelax condition and carry on.";
2061 mf::LogError(
"OpFastScintillation")
2062 <<
"Elliptic Integral inside Disk_SolidAngle() given parameters outside domain.\n"
2063 <<
"\nbb: " << bb <<
"\ncc: " << cc <<
"Exception message: " << e.what();
2068 if (isApproximatelyEqual(d, b)) {
2078 double aa = a / (2. * d);
2079 double bb = b / (2. * d);
2080 double aux = (1. + aa * aa + bb * bb) / ((1. + aa * aa) * (1. + bb * bb));
2093 if (isApproximatelyZero(v[1]) && isApproximatelyZero(v[2])) {
2096 if (isDefinitelyGreaterThan(v[1], o.
h * .5) && isDefinitelyGreaterThan(v[2], o.
w * .5)) {
2097 double A = v[1] - o.
h * .5;
2098 double B = v[2] - o.
w * .5;
2106 if ((v[1] <= o.
h * .5) && (v[2] <= o.
w * .5)) {
2107 double A = -v[1] + o.
h * .5;
2108 double B = -v[2] + o.
w * .5;
2116 if (isDefinitelyGreaterThan(v[1], o.
h * .5) && (v[2] <= o.
w * .5)) {
2117 double A = v[1] - o.
h * .5;
2118 double B = -v[2] + o.
w * .5;
2126 if ((v[1] <= o.
h * .5) && isDefinitelyGreaterThan(v[2], o.
w * .5)) {
2127 double A = -v[1] + o.
h * .5;
2128 double B = v[2] - o.
w * .5;
2151 double par0[9] = {0., 0., 0., 0., 0., 0.597542, 1.00872, 1.46993, 2.04221};
2152 double par1[9] = {0, 0, 0.19569, 0.300449, 0.555598, 0.854939, 1.39166, 2.19141, 2.57732};
2153 const double delta_theta = 10.;
2154 int j = int(theta/delta_theta);
2158 const double d_break = 5*b;
2160 if(distance >= d_break) {
2161 double R_apparent_far = b - par1[j];
2162 return (2*
CLHEP::pi * (1 - std::sqrt(1 - std::pow(R_apparent_far/distance,2))));
2166 double R_apparent_close = b - par0[j];
2167 return (2*
CLHEP::pi * (1 - std::sqrt(1 - std::pow(R_apparent_close/distance,2))));
2172 std::vector<geo::BoxBoundedGeo>
2175 std::vector<geo::BoxBoundedGeo> activeVolumes;
2186 activeVolumes.push_back(std::move(box));
2190 return activeVolumes;
2198 double negate = double(x < 0);
2200 x -= double(x > 1.0) * (x - 1.0);
2201 double ret = -0.0187293;
2203 ret = ret + 0.0742610;
2205 ret = ret - 0.2121144;
2207 ret = ret + 1.5707288;
2208 ret = ret * std::sqrt(1.0 - x);
2209 ret = ret - 2. * negate * ret;
2210 return negate * 3.14159265358979 + ret;
Store parameters for running LArG4.
bool IncludePropTime() const
std::vector< std::vector< std::vector< double > > > fvispars_dome
Specializations of geo_vectors_utils.h for ROOT old vector types.
void detectedDirectHits(std::map< size_t, int > &DetectedNum, const double Num, geo::Point_t const &ScintPoint) const
OpDetGeo const & OpDetGeoFromOpDet(unsigned int OpDet) const
Returns the geo::OpDetGeo object for the given detector number.
void detectedReflecHits(std::map< size_t, int > &ReflDetectedNum, const double Num, geo::Point_t const &ScintPoint) const
void average_position(G4Step const &aStep, double *xzyPos) const
Utilities related to art service access.
bool isScintInActiveVolume(geo::Point_t const &ScintPoint)
std::vector< geo::Point_t > fOpDetCenter
static int GetCurrentOrigTrackID()
G4double bi_exp(const G4double t, const G4double tau1, const G4double tau2) const
double VisibleEnergyDeposit() const
double finflexion_point_distance
process_name opflash particleana ie x
Definition of util::enumerate().
G4double Gaisser_Hillas(const double x, const double *par) const
std::vector< double > fOpDetHeight
static std::vector< geo::BoxBoundedGeo > extractActiveVolumes(geo::GeometryCore const &geom)
void propagationTime(std::vector< double > &arrival_time_dist, G4ThreeVector x0, const size_t OpChannel, bool Reflected=false)
bool isBar() const
Returns whether the detector shape is a bar (TGeoBBox).
bool const fOnlyActiveVolume
Whether photon propagation is performed only from active volumes.
int VISHits(geo::Point_t const &ScintPoint, OpticalDetector const &opDet, const double cathode_hits_rec, const std::array< double, 3 > hotspot) const
Point GetCathodeCenter() const
std::map< double, double > tpbemission
Geometry information for a single TPC.
All information of a photon entering the sensitive optical detector volume.
std::vector< std::vector< std::vector< double > > > fvispars_flat
bool isOpDetInSameTPC(geo::Point_t const &ScintPoint, geo::Point_t const &OpDetPoint) const
MappedFunctions_t GetTimingTF1(Point const &p) const
std::vector< double > fvis_distances_r_flat
std::size_t size(FixedBins< T, C > const &) noexcept
void ProcessStep(const G4Step &step)
void GetCenter(double *xyz, double localz=0.0) const
double finter_d(double *x, double *par)
std::vector< double > fdistances_refl
std::unique_ptr< G4PhysicsTable > theSlowIntegralTable
double model_far(double *x, double *par)
std::vector< std::vector< TF1 > > VUV_timing
std::vector< std::vector< double > > fparameters[7]
std::vector< int > fOpDetType
Geometry information for a single cryostat.
unsigned int Ncryostats() const
Returns the number of cryostats in the detector.
double model_close(double *x, double *par)
std::vector< std::vector< double > > fGHvuvpars_flat
double finter_r(double *x, double *par)
std::vector< std::vector< double > > VUV_min
G4double scint_time(const G4Step &aStep, G4double ScintillationTime, G4double ScintillationRiseTime) const
util::quantities::megaelectronvolt MeV
tuple m
now if test mode generate materials, CRT shell, world, gdml header else just generate CRT shell for u...
double fangle_bin_timing_vis
Energy deposited on a readout Optical Detector by simulated tracks.
void getVISTimes(std::vector< double > &arrivalTimes, const TVector3 &ScintPoint, const TVector3 &OpDetPoint)
geo::Point_t InitialPosition
Scintillation position in world coordinates [cm].
OpFastScintillation(const G4String &processName="Scintillation", G4ProcessType type=fElectromagnetic)
void Reset(const G4Step *step)
std::vector< std::vector< double > > fGHvuvpars_dome
auto enumerate(Iterables &&...iterables)
Range-for loop helper tracking the number of iteration.
int VUVHits(const double Nphotons_created, geo::Point_t const &ScintPoint, OpticalDetector const &opDet) const
unsigned int fillCoords(Coords &dest, Vector const &src)
Fills a coordinate array with the coordinates of a vector.
std::vector< double > fborder_corr_angulo_dome
bool StoreReflected() const
virtual G4VParticleChange * AtRestDoIt(const G4Track &aTrack, const G4Step &aStep)
auto vector(Vector const &v)
Returns a manipulator which will print the specified array.
bool const bPropagate
Whether propagation of photons is enabled.
std::vector< std::vector< double > > fborder_corr_dome
std::vector< std::vector< double > > fborder_corr_flat
Simulation objects for optical detectors.
void BuildThePhysicsTable()
std::vector< double > fvis_distances_x_flat
BEGIN_PROLOG AbsLengthSpectrum
auto counter(T begin, T end)
Returns an object to iterate values from begin to end in a range-for loop.
Use Geant4's user "hooks" to maintain a list of particles generated by Geant4.
bool usesSemiAnalyticModel() const
Returns whether the semi-analytic visibility parametrization is being used.
MappedT0s_t GetReflT0s(Point const &p) const
process_name opflash particleana ie ie y
double distance(geo::Point_t const &point, CathodeDesc_t const &cathode)
Returns the distance of a point from the cathode.
std::vector< double > fborder_corr_angulo_flat
void AddPhoton(size_t opchannel, sim::OnePhoton &&photon, bool Reflected=false)
std::vector< double > fOpDetLength
void SetScintillationByParticleType(const G4bool)
bool RecordPhotonsProduced(const G4Step &aStep, double N)
boost::math::policies::policy< boost::math::policies::promote_double< false > > noLDoublePromote
std::unique_ptr< CLHEP::RandGeneral > fTPBEm
std::vector< geo::BoxBoundedGeo > const fActiveVolumes
std::vector< std::vector< std::vector< double > > > ftau_pars
static IonizationAndScintillation * Instance()
Utilities to extend the interface of geometry vectors.
void AddOpDetBacktrackerRecord(sim::OpDetBacktrackerRecord soc, bool Reflected=false)
Test of util::counter and support utilities.
void AddLitePhoton(int opchannel, int time, int nphotons, bool Reflected=false)
Description of geometry of one entire detector.
MappedCounts_t GetAllVisibilities(Point const &p, bool wantReflected=false) const
G4double sample_time(const G4double tau1, const G4double tau2) const
void AddScintillationPhotons(TrackID_t trackID, timePDclock_t timePDclock, double numberPhotons, double const *xyz, double energy)
Add scintillation photons and energy to this OpticalDetector.
std::vector< double > fradial_distances_refl
Encapsulate the geometry of an optical detector.
IteratorBox< cryostat_iterator,&GeometryCore::begin_cryostat,&GeometryCore::end_cryostat > IterateCryostats() const
Enables ranged-for loops on all cryostats of the detector.
std::vector< double > fvis_distances_r_dome
static OpDetPhotonTable * Instance(bool LitePhotons=false)
void interpolate3(std::array< double, 3 > &inter, const std::vector< double > &xData, const std::vector< double > &yData1, const std::vector< double > &yData2, const std::vector< double > &yData3, double x, bool extrapolate) const
std::vector< std::vector< std::vector< double > > > fcut_off_pars
A base class aware of world box coordinatesAn object describing a simple shape can inherit from this ...
bool const fUseNhitsModel
Whether the semi-analytic model is being used for photon visibility.
A container for photon visibility mapping data.
std::vector< double > fvis_distances_x_dome
double Rectangle_SolidAngle(const double a, const double b, const double d) const
bool SetInSD
Whether the photon reaches the sensitive detector.
void getVUVTimes(std::vector< double > &arrivalTimes, const double distance_in_cm, const size_t angle_bin)
constexpr double dist(const TReal *x, const TReal *y, const unsigned int dimension)
double Omega_Dome_Model(const double distance, const double theta) const
Singleton to access a unified treatment of ionization and scintillation in LAr.
TVector3 toTVector3(Vector const &v)
Converts a vector into a TVector3.
double reemission_energy() const
double Disk_SolidAngle(const double d, const double h, const double b) const
double interpolate(const std::vector< double > &xData, const std::vector< double > &yData, double x, bool extrapolate, size_t i=0) const
phot::MappedT0s_t ReflT0s
static int GetCurrentTrackID()
void generateParam(const size_t index, const size_t angle_bin)
virtual G4VParticleChange * PostStepDoIt(const G4Track &aTrack, const G4Step &aStep)
void ExtendToInclude(Coord_t x, Coord_t y, Coord_t z)
Extends the current box to also include the specified point.
phot::PhotonVisibilityService const *const fPVS
Photon visibility service instance.
bool const fOpaqueCathode
Whether the cathodes are fully opaque; currently hard coded "no".
std::vector< std::vector< double > > VUV_max
TPCGeo const & TPC(unsigned int const tpc=0, unsigned int const cstat=0) const
Returns the specified TPC.
double NumberScintillationPhotons() const
G4EmSaturation * emSaturation
bool IncludeParPropTime() const
virtual bool ScintByParticleType() const =0
float Energy
Scintillation photon energy [GeV].
G4double GetMeanFreePath(const G4Track &aTrack, G4double, G4ForceCondition *)
G4double GetMeanLifeTime(const G4Track &aTrack, G4ForceCondition *)
size_t NOpChannels() const
phot::MappedFunctions_t ParPropTimeTF1
ROOT::Math::PositionVector3D< ROOT::Math::Cartesian3D< double >, ROOT::Math::GlobalCoordinateSystemTag > Point_t
Type for representation of position in physical 3D space.
double fangle_bin_timing_vuv
void AddEnergyDeposit(int n_photon, int n_elec, double scint_yield, double energy, float start_x, float start_y, float start_z, float end_x, float end_y, float end_z, double start_time, double end_time, int trackid, int pdgcode, int g4trackid, std::string const &vol="EMPTY")
TGeoShape const * Shape() const
Returns the geometry object as TGeoShape.
art framework interface to geometry description
BEGIN_PROLOG could also be cout
G4double single_exp(const G4double t, const G4double tau2) const
double LandauPlusExpoFinal(double *x, double *par)
double fast_acos(double x)
std::unique_ptr< G4PhysicsTable > theFastIntegralTable
int MotherTrackID
ID of the GEANT4 track causing the scintillation.