Classes | Public Member Functions | Protected Member Functions | Protected Attributes | Private Member Functions | Static Private Member Functions | Private Attributes | List of all members
larg4::OpFastScintillation Class Reference

#include <OpFastScintillation.hh>

Inheritance diagram for larg4::OpFastScintillation:

Classes

struct  Dims
 
struct  OpticalDetector
 

Public Member Functions

 OpFastScintillation (const G4String &processName="Scintillation", G4ProcessType type=fElectromagnetic)
 
 ~OpFastScintillation ()
 
virtual G4bool IsApplicable (const G4ParticleDefinition &aParticleType)
 
G4double GetMeanFreePath (const G4Track &aTrack, G4double, G4ForceCondition *)
 
G4double GetMeanLifeTime (const G4Track &aTrack, G4ForceCondition *)
 
virtual G4VParticleChange * PostStepDoIt (const G4Track &aTrack, const G4Step &aStep)
 
virtual G4VParticleChange * AtRestDoIt (const G4Track &aTrack, const G4Step &aStep)
 
void SetTrackSecondariesFirst (const G4bool state)
 
void SetFiniteRiseTime (const G4bool state)
 
G4bool GetTrackSecondariesFirst () const
 
G4bool GetFiniteRiseTime () const
 
void SetScintillationYieldFactor (const G4double yieldfactor)
 
G4double GetScintillationYieldFactor () const
 
void SetScintillationExcitationRatio (const G4double excitationratio)
 
G4double GetScintillationExcitationRatio () const
 
G4PhysicsTable * GetFastIntegralTable () const
 
G4PhysicsTable * GetSlowIntegralTable () const
 
void AddSaturation (G4EmSaturation *sat)
 
void RemoveSaturation ()
 
G4EmSaturation * GetSaturation () const
 
void SetScintillationByParticleType (const G4bool)
 
G4bool GetScintillationByParticleType () const
 
void DumpPhysicsTable () const
 
void getVUVTimes (std::vector< double > &arrivalTimes, const double distance_in_cm, const size_t angle_bin)
 
void generateParam (const size_t index, const size_t angle_bin)
 
void getVISTimes (std::vector< double > &arrivalTimes, const TVector3 &ScintPoint, const TVector3 &OpDetPoint)
 
void detectedDirectHits (std::map< size_t, int > &DetectedNum, const double Num, geo::Point_t const &ScintPoint) const
 
void detectedReflecHits (std::map< size_t, int > &ReflDetectedNum, const double Num, geo::Point_t const &ScintPoint) const
 

Protected Member Functions

void BuildThePhysicsTable ()
 
bool RecordPhotonsProduced (const G4Step &aStep, double N)
 

Protected Attributes

std::unique_ptr< G4PhysicsTable > theSlowIntegralTable
 
std::unique_ptr< G4PhysicsTable > theFastIntegralTable
 
G4bool fTrackSecondariesFirst
 
G4bool fFiniteRiseTime
 
G4double YieldFactor
 
G4double ExcitationRatio
 
G4bool scintillationByParticleType
 

Private Member Functions

bool usesSemiAnalyticModel () const
 Returns whether the semi-analytic visibility parametrization is being used. More...
 
int VUVHits (const double Nphotons_created, geo::Point_t const &ScintPoint, OpticalDetector const &opDet) const
 
int VISHits (geo::Point_t const &ScintPoint, OpticalDetector const &opDet, const double cathode_hits_rec, const std::array< double, 3 > hotspot) const
 
G4double single_exp (const G4double t, const G4double tau2) const
 
G4double bi_exp (const G4double t, const G4double tau1, const G4double tau2) const
 
G4double scint_time (const G4Step &aStep, G4double ScintillationTime, G4double ScintillationRiseTime) const
 
void propagationTime (std::vector< double > &arrival_time_dist, G4ThreeVector x0, const size_t OpChannel, bool Reflected=false)
 
G4double sample_time (const G4double tau1, const G4double tau2) const
 
double reemission_energy () const
 
void average_position (G4Step const &aStep, double *xzyPos) const
 
double Rectangle_SolidAngle (const double a, const double b, const double d) const
 
double Rectangle_SolidAngle (Dims const &o, const std::array< double, 3 > v) const
 
double Disk_SolidAngle (const double d, const double h, const double b) const
 
double Omega_Dome_Model (const double distance, const double theta) const
 
G4double Gaisser_Hillas (const double x, const double *par) const
 
void ProcessStep (const G4Step &step)
 
bool isOpDetInSameTPC (geo::Point_t const &ScintPoint, geo::Point_t const &OpDetPoint) const
 
bool isScintInActiveVolume (geo::Point_t const &ScintPoint)
 
double interpolate (const std::vector< double > &xData, const std::vector< double > &yData, double x, bool extrapolate, size_t i=0) const
 
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
 

Static Private Member Functions

static std::vector< geo::BoxBoundedGeoextractActiveVolumes (geo::GeometryCore const &geom)
 

Private Attributes

std::map< double, double > tpbemission
 
std::unique_ptr< CLHEP::RandGeneral > fTPBEm
 
G4EmSaturation * emSaturation
 
phot::MappedFunctions_t ParPropTimeTF1
 
phot::MappedT0s_t ReflT0s
 
double fstep_size
 
double fmin_d
 
double fmax_d
 
double fvuv_vgroup_mean
 
double fvuv_vgroup_max
 
double finflexion_point_distance
 
double fangle_bin_timing_vuv
 
std::vector< std::vector< double > > fparameters [7]
 
std::vector< std::vector< TF1 > > VUV_timing
 
std::vector< std::vector< double > > VUV_max
 
std::vector< std::vector< double > > VUV_min
 
double fvis_vmean
 
double fangle_bin_timing_vis
 
std::vector< double > fdistances_refl
 
std::vector< double > fradial_distances_refl
 
std::vector< std::vector< std::vector< double > > > fcut_off_pars
 
std::vector< std::vector< std::vector< double > > > ftau_pars
 
double fdelta_angulo_vuv
 
bool fIsFlatPDCorr
 
std::vector< std::vector< double > > fGHvuvpars_flat
 
std::vector< double > fborder_corr_angulo_flat
 
std::vector< std::vector< double > > fborder_corr_flat
 
bool fIsDomePDCorr
 
std::vector< std::vector< double > > fGHvuvpars_dome
 
std::vector< double > fborder_corr_angulo_dome
 
std::vector< std::vector< double > > fborder_corr_dome
 
bool fStoreReflected
 
double fdelta_angulo_vis
 
std::vector< double > fvis_distances_x_flat
 
std::vector< double > fvis_distances_r_flat
 
std::vector< std::vector< std::vector< double > > > fvispars_flat
 
std::vector< double > fvis_distances_x_dome
 
std::vector< double > fvis_distances_r_dome
 
std::vector< std::vector< std::vector< double > > > fvispars_dome
 
double fplane_depth
 
double fcathode_zdimension
 
double fcathode_ydimension
 
TVector3 fcathode_centre
 
std::vector< geo::BoxBoundedGeo > const fActiveVolumes
 
double fradius
 
Dims fcathode_plane
 
int fL_abs_vuv
 
std::vector< geo::Point_tfOpDetCenter
 
std::vector< int > fOpDetType
 
std::vector< double > fOpDetLength
 
std::vector< double > fOpDetHeight
 
bool const bPropagate
 Whether propagation of photons is enabled. More...
 
phot::PhotonVisibilityService const *const fPVS
 Photon visibility service instance. More...
 
bool const fUseNhitsModel = false
 Whether the semi-analytic model is being used for photon visibility. More...
 
bool const fOnlyActiveVolume = false
 Whether photon propagation is performed only from active volumes. More...
 
bool const fOnlyOneCryostat = false
 
bool const fOpaqueCathode = false
 Whether the cathodes are fully opaque; currently hard coded "no". More...
 

Detailed Description

Definition at line 130 of file OpFastScintillation.hh.

Constructor & Destructor Documentation

larg4::OpFastScintillation::OpFastScintillation ( const G4String &  processName = "Scintillation",
G4ProcessType  type = fElectromagnetic 
)

Definition at line 180 of file OpFastScintillation.cxx.

181  : G4VRestDiscreteProcess(processName, type)
182  , fActiveVolumes{extractActiveVolumes(*(lar::providerFrom<geo::Geometry>()))}
183  , bPropagate(!(art::ServiceHandle<sim::LArG4Parameters const>()->NoPhotonPropagation()))
186  // for now, limit to the active volume only if semi-analytic model is used
188  {
189  SetProcessSubType(25); // TODO: unhardcode
190  fTrackSecondariesFirst = false;
191  fFiniteRiseTime = false;
192  YieldFactor = 1.0;
193  ExcitationRatio = 1.0;
194 
195  const detinfo::LArProperties* larp = lar::providerFrom<detinfo::LArPropertiesService>();
196 
198 
199  if (verboseLevel > 0) { G4cout << GetProcessName() << " is created " << G4endl; }
200 
202  emSaturation = NULL;
203 
204  if (bPropagate) {
205  assert(fPVS);
206 
207  // Loading the position of each optical channel, neccessary for the parametrizatiuons of Nhits and prop-time
208  geo::GeometryCore const& geom = *(lar::providerFrom<geo::Geometry>());
209 
210  {
211  auto log = mf::LogTrace("OpFastScintillation")
212  << "OpFastScintillation: active volume boundaries from " << fActiveVolumes.size()
213  << " volumes:";
214  for (auto const& [iCryo, box] : util::enumerate(fActiveVolumes)) {
215  log << "\n - C:" << iCryo << ": " << box.Min() << " -- " << box.Max() << " cm";
216  } // for
217  log << "\n (scintillation photons are propagated "
218  << (fOnlyActiveVolume ? "only from active volumes" : "from anywhere") << ")";
219  } // local scope
220 
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."
230  << "\n"
231  << std::string(80, '=');
232  }
233  else {
235  << "Photon propagation via semi-analytic model is not supported yet"
236  << " on detectors with more than one cryostat.";
237  }
238  } // if
239 
240  geo::Point_t const Cathode_centre{geom.TPC(0, 0).GetCathodeCenter().X(),
241  fActiveVolumes[0].CenterY(),
242  fActiveVolumes[0].CenterZ()};
243  mf::LogTrace("OpFastScintillation") << "Cathode_centre: " << Cathode_centre << " cm";
244 
245  // std::cout << "\nInitialize acos_arr with " << acos_bins+1
246  // << " hence with a resolution of " << 1./acos_bins << std::endl;
247  // for(size_t i=0; i<=acos_bins; ++i){
248  // acos_arr[i] = std::acos(i/double(acos_bins));
249  // }
250 
251  for (size_t const i : util::counter(fPVS->NOpChannels())) {
252  geo::OpDetGeo const& opDet = geom.OpDetGeoFromOpDet(i);
253  fOpDetCenter.push_back(opDet.GetCenter());
254 
255  if (dynamic_cast<TGeoSphere const*>(opDet.Shape()) != nullptr) { // sphere/dome
256  fOpDetType.push_back(1); // Dome PMTs
257  fOpDetLength.push_back(-1);
258  fOpDetHeight.push_back(-1);
259  }
260  else if (opDet.isBar()) { // box
261  fOpDetType.push_back(0); //Arapucas
262  fOpDetLength.push_back(opDet.Length());
263  fOpDetHeight.push_back(opDet.Height());
264  }
265  else { // disk
266  fOpDetType.push_back(2); // Disk PMTs
267  // std::cout<<"Radio: "<<geom.OpDetGeoFromOpDet(i).RMax()<<std::endl;
268  fOpDetLength.push_back(-1);
269  fOpDetHeight.push_back(-1);
270  }
271  }
272 
273  if (fPVS->IncludePropTime()) {
274  std::cout << "Using parameterisation of timings." << std::endl;
275  //OLD VUV time parapetrization (to be removed soon)
276  //fPVS->SetDirectLightPropFunctions(functions_vuv, fd_break, fd_max, ftf1_sampling_factor);
277  //fPVS->SetReflectedCOLightPropFunctions(functions_vis, ft0_max, ft0_break_point);
278  //New VUV time parapetrization
280  fstep_size,
281  fmax_d,
282  fmin_d,
287 
288  // create vector of empty TF1s that will be replaces with the parameterisations that are generated as they are required
289  // default TF1() constructor gives function with 0 dimensions, can then check numDim to qucikly see if a parameterisation has been generated
290  const size_t num_params = (fmax_d - fmin_d) / fstep_size; // for d < fmin_d, no parameterisaton, a delta function is used instead
291  size_t num_angles = std::round(90/fangle_bin_timing_vuv);
292  VUV_timing = std::vector(num_angles, std::vector(num_params, TF1()));
293 
294  // initialise vectors to contain range parameterisations sampled to in each case
295  // when using TF1->GetRandom(xmin,xmax), must be in same range otherwise sampling is regenerated, this is the slow part!
296  VUV_max = std::vector(num_angles, std::vector(num_params, 0.0));
297  VUV_min = std::vector(num_angles, std::vector(num_params, 0.0));
298 
299  // VIS time parameterisation
300  if (fPVS->StoreReflected()) {
301  // load parameters
305  ftau_pars,
306  fvis_vmean,
308  }
309  }
310  if (usesSemiAnalyticModel()) {
311  mf::LogVerbatim("OpFastScintillation")
312  << "OpFastScintillation: using semi-analytic model for number of hits";
313 
314  // LAr absorption length in cm
315  std::map<double, double> abs_length_spectrum =
316  lar::providerFrom<detinfo::LArPropertiesService>()->AbsLengthSpectrum();
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);
321  }
322  fL_abs_vuv =
323  std::round(interpolate(x_v, y_v, 9.7, false)); // 9.7 eV: peak of VUV emission spectrum
324 
325  // Load Gaisser-Hillas corrections for VUV semi-analytic hits
326  std::cout << "Loading the GH corrections" << std::endl;
330  fradius
331  );
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";
335  }
336  if (fIsFlatPDCorr) {
340  );
341  }
342  if (fIsDomePDCorr) {
346  );
347  }
348  // cathode center coordinates required for corrections
349  fcathode_centre = geom.TPC(0, 0).GetCathodeCenter();
350  fcathode_centre[1] = fActiveVolumes[0].CenterY();
351  fcathode_centre[2] = fActiveVolumes[0].CenterZ(); // to get full cathode dimension rather than just single tpc
352 
353 
354  if (fPVS->StoreReflected()) {
355  fStoreReflected = true;
356  // Load corrections for VIS semi-anlytic hits
357  std::cout << "Loading visible light corrections" << std::endl;
359  fradius
360  );
361  if (fIsFlatPDCorr) {
365  );
366  }
367  if (fIsDomePDCorr) {
371  );
372  }
373 
374  // cathode dimensions
375  fcathode_ydimension = fActiveVolumes[0].SizeY();
376  fcathode_zdimension = fActiveVolumes[0].SizeZ();
377 
378  // set cathode plane struct for solid angle function
382  }
383  else
384  fStoreReflected = false;
385  }
386  }
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);
392  }
393  fTPBEm = std::make_unique<CLHEP::RandGeneral>
394  (parent.data(), parent.size());
395  }
void LoadTimingsForVISPar(std::vector< double > &distances, std::vector< double > &radial_distances, std::vector< std::vector< std::vector< double >>> &cut_off, std::vector< std::vector< std::vector< double >>> &tau, double &vis_vmean, double &angle_bin_timing_vis) const
MaybeLogger_< ELseverityLevel::ELsev_info, true > LogVerbatim
std::vector< std::vector< std::vector< double > > > fvispars_dome
OpDetGeo const & OpDetGeoFromOpDet(unsigned int OpDet) const
Returns the geo::OpDetGeo object for the given detector number.
std::vector< geo::Point_t > fOpDetCenter
void LoadTimingsForVUVPar(std::vector< std::vector< double >>(&v)[7], double &step_size, double &max_d, double &min_d, double &vuv_vgroup_mean, double &vuv_vgroup_max, double &inflexion_point_distance, double &angle_bin_timing_vuv) const
std::string string
Definition: nybbler.cc:12
std::vector< double > fOpDetHeight
static std::vector< geo::BoxBoundedGeo > extractActiveVolumes(geo::GeometryCore const &geom)
bool isBar() const
Returns whether the detector shape is a bar (TGeoBBox).
Definition: OpDetGeo.h:195
bool const fOnlyActiveVolume
Whether photon propagation is performed only from active volumes.
Point GetCathodeCenter() const
Definition: TPCGeo.h:298
std::map< double, double > tpbemission
struct vector vector
std::vector< std::vector< std::vector< double > > > fvispars_flat
void LoadVisParsFlat(std::vector< double > &vis_distances_x_flat, std::vector< double > &vis_distances_r_flat, std::vector< std::vector< std::vector< double >>> &vispars_flat) const
std::vector< double > fvis_distances_r_flat
void GetCenter(double *xyz, double localz=0.0) const
Definition: OpDetGeo.cxx:40
std::vector< double > fdistances_refl
std::vector< std::vector< TF1 > > VUV_timing
std::vector< std::vector< double > > fparameters[7]
unsigned int Ncryostats() const
Returns the number of cryostats in the detector.
void LoadGHDome(std::vector< std::vector< double >> &GHvuvpars_dome, std::vector< double > &border_corr_angulo_dome, std::vector< std::vector< double >> &border_corr_dome) const
std::vector< std::vector< double > > fGHvuvpars_flat
std::vector< std::vector< double > > VUV_min
std::vector< std::vector< double > > fGHvuvpars_dome
auto enumerate(Iterables &&...iterables)
Range-for loop helper tracking the number of iteration.
Definition: enumerate.h:69
void LoadVUVSemiAnalyticProperties(bool &isFlatPDCorr, bool &isDomePDCorr, double &delta_angulo_vuv, double &radius) const
std::vector< double > fborder_corr_angulo_dome
bool const bPropagate
Whether propagation of photons is enabled.
std::vector< std::vector< double > > fborder_corr_dome
T abs(T value)
std::vector< std::vector< double > > fborder_corr_flat
std::vector< double > fvis_distances_x_flat
void LoadGHFlat(std::vector< std::vector< double >> &GHvuvpars_flat, std::vector< double > &border_corr_angulo_flat, std::vector< std::vector< double >> &border_corr_flat) const
auto counter(T begin, T end)
Returns an object to iterate values from begin to end in a range-for loop.
Definition: counter.h:285
bool usesSemiAnalyticModel() const
Returns whether the semi-analytic visibility parametrization is being used.
void LoadVisParsDome(std::vector< double > &vis_distances_x_dome, std::vector< double > &vis_distances_r_dome, std::vector< std::vector< std::vector< double >>> &vispars_dome) const
std::vector< double > fborder_corr_angulo_flat
std::vector< double > fOpDetLength
std::unique_ptr< CLHEP::RandGeneral > fTPBEm
std::vector< geo::BoxBoundedGeo > const fActiveVolumes
std::vector< std::vector< std::vector< double > > > ftau_pars
double Length() const
Definition: OpDetGeo.h:81
Description of geometry of one entire detector.
std::vector< double > fradial_distances_refl
ROOT::Math::PositionVector3D< ROOT::Math::Cartesian3D< double >, ROOT::Math::GlobalCoordinateSystemTag > Point_t
Type for representation of position in physical 3D space.
Definition: geo_vectors.h:184
std::vector< double > fvis_distances_r_dome
cet::coded_exception< errors::ErrorCodes, ExceptionDetail::translate > Exception
Definition: Exception.h:66
void LoadVisSemiAnalyticProperties(double &delta_angulo_vis, double &radius) const
std::vector< std::vector< std::vector< double > > > fcut_off_pars
bool const fUseNhitsModel
Whether the semi-analytic model is being used for photon visibility.
std::vector< double > fvis_distances_x_dome
double interpolate(const std::vector< double > &xData, const std::vector< double > &yData, double x, bool extrapolate, size_t i=0) const
MaybeLogger_< ELseverityLevel::ELsev_warning, false > LogWarning
phot::PhotonVisibilityService const *const fPVS
Photon visibility service instance.
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.
MaybeLogger_< ELseverityLevel::ELsev_success, true > LogTrace
virtual bool ScintByParticleType() const =0
double Height() const
Definition: OpDetGeo.h:83
TGeoShape const * Shape() const
Returns the geometry object as TGeoShape.
Definition: OpDetGeo.h:154
def parent(G, child, parent_type)
Definition: graph.py:67
cet::coded_exception< error, detail::translate > exception
Definition: exception.h:33
QTextStream & endl(QTextStream &s)
larg4::OpFastScintillation::~OpFastScintillation ( )

Definition at line 400 of file OpFastScintillation.cxx.

401  {
402  if (theFastIntegralTable) theFastIntegralTable->clearAndDestroy();
403  if (theSlowIntegralTable) theSlowIntegralTable->clearAndDestroy();
404  }
std::unique_ptr< G4PhysicsTable > theSlowIntegralTable
std::unique_ptr< G4PhysicsTable > theFastIntegralTable

Member Function Documentation

void larg4::OpFastScintillation::AddSaturation ( G4EmSaturation *  sat)
inline

Definition at line 216 of file OpFastScintillation.hh.

217  {
218  emSaturation = sat;
219  }
G4VParticleChange * larg4::OpFastScintillation::AtRestDoIt ( const G4Track &  aTrack,
const G4Step &  aStep 
)
virtual

Definition at line 414 of file OpFastScintillation.cxx.

417  {
418  return OpFastScintillation::PostStepDoIt(aTrack, aStep);
419  }
virtual G4VParticleChange * PostStepDoIt(const G4Track &aTrack, const G4Step &aStep)
void larg4::OpFastScintillation::average_position ( G4Step const &  aStep,
double *  xzyPos 
) const
private

Definition at line 1102 of file OpFastScintillation.cxx.

1103  {
1104  CLHEP::Hep3Vector prePoint = (aStep.GetPreStepPoint())->GetPosition();
1105  CLHEP::Hep3Vector postPoint = (aStep.GetPostStepPoint())->GetPosition();
1106  xyzPos[0] = (((prePoint.getX() + postPoint.getX()) / 2.0) / CLHEP::cm);
1107  xyzPos[1] = (((prePoint.getY() + postPoint.getY()) / 2.0) / CLHEP::cm);
1108  xyzPos[2] = (((prePoint.getZ() + postPoint.getZ()) / 2.0) / CLHEP::cm);
1109  }
static constexpr double cm
Definition: Units.h:68
G4double larg4::OpFastScintillation::bi_exp ( const G4double  t,
const G4double  tau1,
const G4double  tau2 
) const
private

Definition at line 1849 of file OpFastScintillation.cxx.

1850  { // TODO: what's up with this? ... / tau2 / tau2 ...
1851  return std::exp(-1.0 * t / tau2) * (1 - std::exp(-1.0 * t / tau1)) / tau2 / tau2 *
1852  (tau1 + tau2);
1853  }
G4double tau1[100]
Definition: G4S2Light.cc:61
void larg4::OpFastScintillation::BuildThePhysicsTable ( )
protected

Definition at line 870 of file OpFastScintillation.cxx.

871  {
873 
874  const G4MaterialTable* theMaterialTable = G4Material::GetMaterialTable();
875  G4int numOfMaterials = G4Material::GetNumberOfMaterials();
876 
877  // create new physics table
879  theFastIntegralTable = std::make_unique<G4PhysicsTable>(numOfMaterials);
881  theSlowIntegralTable = std::make_unique<G4PhysicsTable>(numOfMaterials);
882 
883  // loop for materials
884  for (G4int i = 0; i < numOfMaterials; i++) {
885  G4PhysicsOrderedFreeVector* aPhysicsOrderedFreeVector = new G4PhysicsOrderedFreeVector();
886  G4PhysicsOrderedFreeVector* bPhysicsOrderedFreeVector = new G4PhysicsOrderedFreeVector();
887 
888  // Retrieve vector of scintillation wavelength intensity for
889  // the material from the material's optical properties table.
890  G4Material* aMaterial = (*theMaterialTable)[i];
891 
892  G4MaterialPropertiesTable* aMaterialPropertiesTable = aMaterial->GetMaterialPropertiesTable();
893 
894  if (aMaterialPropertiesTable) {
895 
896  G4MaterialPropertyVector* theFastLightVector =
897  aMaterialPropertiesTable->GetProperty("FASTCOMPONENT");
898 
899  if (theFastLightVector) {
900  // Retrieve the first intensity point in vector
901  // of (photon energy, intensity) pairs
902  G4double currentIN = (*theFastLightVector)[0];
903  if (currentIN >= 0.0) {
904  // Create first (photon energy, Scintillation
905  // Integral pair
906  G4double currentPM = theFastLightVector->Energy(0);
907  G4double currentCII = 0.0;
908 
909  aPhysicsOrderedFreeVector->InsertValues(currentPM, currentCII);
910 
911  // Set previous values to current ones prior to loop
912  G4double prevPM = currentPM;
913  G4double prevCII = currentCII;
914  G4double prevIN = currentIN;
915 
916  // loop over all (photon energy, intensity)
917  // pairs stored for this material
918  for (size_t i = 1; i < theFastLightVector->GetVectorLength(); i++) {
919  currentPM = theFastLightVector->Energy(i);
920  currentIN = (*theFastLightVector)[i];
921 
922  currentCII = 0.5 * (prevIN + currentIN);
923 
924  currentCII = prevCII + (currentPM - prevPM) * currentCII;
925 
926  aPhysicsOrderedFreeVector->InsertValues(currentPM, currentCII);
927 
928  prevPM = currentPM;
929  prevCII = currentCII;
930  prevIN = currentIN;
931  }
932  }
933  }
934 
935  G4MaterialPropertyVector* theSlowLightVector =
936  aMaterialPropertiesTable->GetProperty("SLOWCOMPONENT");
937  if (theSlowLightVector) {
938  // Retrieve the first intensity point in vector
939  // of (photon energy, intensity) pairs
940  G4double currentIN = (*theSlowLightVector)[0];
941  if (currentIN >= 0.0) {
942  // Create first (photon energy, Scintillation
943  // Integral pair
944  G4double currentPM = theSlowLightVector->Energy(0);
945  G4double currentCII = 0.0;
946 
947  bPhysicsOrderedFreeVector->InsertValues(currentPM, currentCII);
948 
949  // Set previous values to current ones prior to loop
950  G4double prevPM = currentPM;
951  G4double prevCII = currentCII;
952  G4double prevIN = currentIN;
953 
954  // loop over all (photon energy, intensity)
955  // pairs stored for this material
956  for (size_t i = 1; i < theSlowLightVector->GetVectorLength(); i++) {
957  currentPM = theSlowLightVector->Energy(i);
958  currentIN = (*theSlowLightVector)[i];
959 
960  currentCII = 0.5 * (prevIN + currentIN);
961 
962  currentCII = prevCII + (currentPM - prevPM) * currentCII;
963 
964  bPhysicsOrderedFreeVector->InsertValues(currentPM, currentCII);
965 
966  prevPM = currentPM;
967  prevCII = currentCII;
968  prevIN = currentIN;
969  }
970  }
971  }
972  }
973  // The scintillation integral(s) for a given material
974  // will be inserted in the table(s) according to the
975  // position of the material in the material table.
976  theFastIntegralTable->insertAt(i, aPhysicsOrderedFreeVector);
977  theSlowIntegralTable->insertAt(i, bPhysicsOrderedFreeVector);
978  }
979  }
std::unique_ptr< G4PhysicsTable > theSlowIntegralTable
std::unique_ptr< G4PhysicsTable > theFastIntegralTable
void larg4::OpFastScintillation::detectedDirectHits ( std::map< size_t, int > &  DetectedNum,
const double  Num,
geo::Point_t const &  ScintPoint 
) const

Definition at line 1499 of file OpFastScintillation.cxx.

1502  {
1503  for (size_t const OpDet : util::counter(fPVS->NOpChannels())) {
1504  if (!isOpDetInSameTPC(ScintPoint, fOpDetCenter.at(OpDet))) continue;
1505 
1506  // set detector struct for solid angle function
1507  const OpFastScintillation::OpticalDetector op{
1508  fOpDetHeight.at(OpDet), fOpDetLength.at(OpDet),
1509  fOpDetCenter.at(OpDet), fOpDetType.at(OpDet)};
1510  const int DetThis = VUVHits(Num, ScintPoint, op);
1511  if (DetThis > 0) {
1512  DetectedNum[OpDet] = DetThis;
1513  // mf::LogInfo("OpFastScintillation") << "FastScint: " <<
1514  // // it->second<<" " << Num << " " << DetThisPMT;
1515  //det_photon_ctr += DetThisPMT; // CASE-DEBUG DO NOT REMOVE THIS COMMENT
1516  }
1517  }
1518  }
std::vector< geo::Point_t > fOpDetCenter
std::vector< double > fOpDetHeight
bool isOpDetInSameTPC(geo::Point_t const &ScintPoint, geo::Point_t const &OpDetPoint) const
int VUVHits(const double Nphotons_created, geo::Point_t const &ScintPoint, OpticalDetector const &opDet) const
auto counter(T begin, T end)
Returns an object to iterate values from begin to end in a range-for loop.
Definition: counter.h:285
std::vector< double > fOpDetLength
phot::PhotonVisibilityService const *const fPVS
Photon visibility service instance.
void larg4::OpFastScintillation::detectedReflecHits ( std::map< size_t, int > &  ReflDetectedNum,
const double  Num,
geo::Point_t const &  ScintPoint 
) const

Definition at line 1521 of file OpFastScintillation.cxx.

1524  {
1525  // 1). calculate total number of hits of VUV photons on
1526  // reflective foils via solid angle + Gaisser-Hillas
1527  // corrections:
1528 
1529  // set plane_depth for correct TPC:
1530  double plane_depth;
1531  if (ScintPoint.X() < 0.) { plane_depth = -fplane_depth; }
1532  else {
1533  plane_depth = fplane_depth;
1534  }
1535 
1536  // get scintpoint coords relative to centre of cathode plane
1537  std::array<double, 3> ScintPoint_relative = {std::abs(ScintPoint.X() - plane_depth),
1538  std::abs(ScintPoint.Y() - fcathode_centre[1]),
1539  std::abs(ScintPoint.Z() - fcathode_centre[2])};
1540  // calculate solid angle of cathode from the scintillation point
1541  double solid_angle_cathode = Rectangle_SolidAngle(fcathode_plane, ScintPoint_relative);
1542 
1543  // calculate distance and angle between ScintPoint and hotspot
1544  // vast majority of hits in hotspot region directly infront of scintpoint,
1545  // therefore consider attenuation for this distance and on axis GH instead of for the centre coordinate
1546  double distance_cathode = std::abs(plane_depth - ScintPoint.X());
1547  // calculate hits on cathode plane via geometric acceptance
1548  double cathode_hits_geo = std::exp(-1. * distance_cathode / fL_abs_vuv) *
1549  (solid_angle_cathode / (4. * CLHEP::pi)) * Num;
1550  // determine Gaisser-Hillas correction including border effects
1551  // use flat correction
1552  double r = std::sqrt(std::pow(ScintPoint.Y() - fcathode_centre[1], 2) + std::pow(ScintPoint.Z() - fcathode_centre[2], 2));
1553  double pars_ini[4] = {0, 0, 0, 0};
1554  double s1 = 0; double s2 = 0; double s3 = 0;
1555  if(fIsFlatPDCorr) {
1556  pars_ini[0] = fGHvuvpars_flat[0][0];
1557  pars_ini[1] = fGHvuvpars_flat[1][0];
1558  pars_ini[2] = fGHvuvpars_flat[2][0];
1559  pars_ini[3] = fGHvuvpars_flat[3][0];
1563  }
1564  else std::cout << "Error: flat optical detector VUV correction required for reflected semi-analytic hits." << std::endl;
1565 
1566  // add border correction
1567  pars_ini[0] = pars_ini[0] + s1 * r;
1568  pars_ini[1] = pars_ini[1] + s2 * r;
1569  pars_ini[2] = pars_ini[2] + s3 * r;
1570  pars_ini[3] = pars_ini[3];
1571 
1572 
1573  // calculate corrected number of hits
1574  double GH_correction = Gaisser_Hillas(distance_cathode, pars_ini);
1575  const double cathode_hits_rec = GH_correction * cathode_hits_geo;
1576 
1577  // detemine hits on each PD
1578  const std::array<double, 3> hotspot = {plane_depth, ScintPoint.Y(), ScintPoint.Z()};
1579  for (size_t const OpDet : util::counter(fPVS->NOpChannels())) {
1580  if (!isOpDetInSameTPC(ScintPoint, fOpDetCenter.at(OpDet))) continue;
1581 
1582  // set detector struct for solid angle function
1583  const OpFastScintillation::OpticalDetector op{
1584  fOpDetHeight.at(OpDet), fOpDetLength.at(OpDet),
1585  fOpDetCenter.at(OpDet), fOpDetType.at(OpDet)};
1586 
1587  int const ReflDetThis =
1588  VISHits(ScintPoint, op, cathode_hits_rec, hotspot);
1589  if (ReflDetThis > 0) { ReflDetectedNum[OpDet] = ReflDetThis; }
1590  }
1591  }
std::vector< geo::Point_t > fOpDetCenter
G4double Gaisser_Hillas(const double x, const double *par) const
std::vector< double > fOpDetHeight
int VISHits(geo::Point_t const &ScintPoint, OpticalDetector const &opDet, const double cathode_hits_rec, const std::array< double, 3 > hotspot) const
constexpr T pow(T x)
Definition: pow.h:72
bool isOpDetInSameTPC(geo::Point_t const &ScintPoint, geo::Point_t const &OpDetPoint) const
std::vector< std::vector< double > > fGHvuvpars_flat
T abs(T value)
std::vector< std::vector< double > > fborder_corr_flat
auto counter(T begin, T end)
Returns an object to iterate values from begin to end in a range-for loop.
Definition: counter.h:285
std::vector< double > fborder_corr_angulo_flat
std::vector< double > fOpDetLength
double Rectangle_SolidAngle(const double a, const double b, const double d) const
double interpolate(const std::vector< double > &xData, const std::vector< double > &yData, double x, bool extrapolate, size_t i=0) const
phot::PhotonVisibilityService const *const fPVS
Photon visibility service instance.
float pi
Definition: units.py:11
QTextStream & endl(QTextStream &s)
double larg4::OpFastScintillation::Disk_SolidAngle ( const double  d,
const double  h,
const double  b 
) const
private

Definition at line 2013 of file OpFastScintillation.cxx.

2014  {
2015  if (b <= 0. || d < 0. || h <= 0.) return 0.;
2016  const double leg2 = (b + d) * (b + d);
2017  const double aa = std::sqrt(h * h / (h * h + leg2));
2018  if (isApproximatelyZero(d)) { return 2. * CLHEP::pi * (1. - aa); }
2019  double bb = 2. * std::sqrt(b * d / (h * h + leg2));
2020  double cc = 4. * b * d / leg2;
2021 
2022  if (isDefinitelyGreaterThan(d, b)) {
2023  try {
2024  return 2. * aa *
2025  (std::sqrt(1. - cc) * boost::math::ellint_3(bb, cc, noLDoublePromote()) -
2026  boost::math::ellint_1(bb, noLDoublePromote()));
2027  }
2028  catch (std::domain_error& e) {
2029  if (isApproximatelyEqual(d, b, 1e-9)) {
2030  mf::LogWarning("OpFastScintillation")
2031  << "Elliptic Integral in Disk_SolidAngle() given parameters outside domain."
2032  << "\nbb: " << bb << "\ncc: " << cc << "\nException message: " << e.what()
2033  << "\nRelax condition and carry on.";
2034  return CLHEP::pi - 2. * aa * boost::math::ellint_1(bb, noLDoublePromote());
2035  }
2036  else {
2037  mf::LogError("OpFastScintillation")
2038  << "Elliptic Integral inside Disk_SolidAngle() given parameters outside domain.\n"
2039  << "\nbb: " << bb << "\ncc: " << cc << "Exception message: " << e.what();
2040  return 0.;
2041  }
2042  }
2043  }
2044  if (isDefinitelyLessThan(d, b)) {
2045  try {
2046  return 2. * CLHEP::pi -
2047  2. * aa *
2048  (boost::math::ellint_1(bb, noLDoublePromote()) +
2049  std::sqrt(1. - cc) * boost::math::ellint_3(bb, cc, noLDoublePromote()));
2050  }
2051  catch (std::domain_error& e) {
2052  if (isApproximatelyEqual(d, b, 1e-9)) {
2053  mf::LogWarning("OpFastScintillation")
2054  << "Elliptic Integral in Disk_SolidAngle() given parameters outside domain."
2055  << "\nbb: " << bb << "\ncc: " << cc << "\nException message: " << e.what()
2056  << "\nRelax condition and carry on.";
2057  return CLHEP::pi - 2. * aa * boost::math::ellint_1(bb, noLDoublePromote());
2058  }
2059  else {
2060  mf::LogError("OpFastScintillation")
2061  << "Elliptic Integral inside Disk_SolidAngle() given parameters outside domain.\n"
2062  << "\nbb: " << bb << "\ncc: " << cc << "Exception message: " << e.what();
2063  return 0.;
2064  }
2065  }
2066  }
2067  if (isApproximatelyEqual(d, b)) {
2068  return CLHEP::pi - 2. * aa * boost::math::ellint_1(bb, noLDoublePromote());
2069  }
2070  return 0.;
2071  }
MaybeLogger_< ELseverityLevel::ELsev_error, false > LogError
const double e
boost::math::policies::policy< boost::math::policies::promote_double< false > > noLDoublePromote
static constexpr bool isDefinitelyGreaterThan(TReal a, TReal b, TReal tolerance=std::numeric_limits< TReal >::epsilon())
static constexpr bool isApproximatelyEqual(TReal a, TReal b, TReal tolerance=std::numeric_limits< TReal >::epsilon())
MaybeLogger_< ELseverityLevel::ELsev_warning, false > LogWarning
static bool * b
Definition: config.cpp:1043
float pi
Definition: units.py:11
static constexpr bool isDefinitelyLessThan(TReal a, TReal b, TReal tolerance=std::numeric_limits< TReal >::epsilon())
static constexpr bool isApproximatelyZero(TReal a, TReal tolerance=std::numeric_limits< TReal >::epsilon())
void larg4::OpFastScintillation::DumpPhysicsTable ( ) const
inline

Definition at line 541 of file OpFastScintillation.hh.

542  {
543  if (theFastIntegralTable) {
544  G4int PhysicsTableSize = theFastIntegralTable->entries();
545  G4PhysicsOrderedFreeVector* v;
546  for (G4int i = 0; i < PhysicsTableSize; i++) {
547  v = (G4PhysicsOrderedFreeVector*)(*theFastIntegralTable)[i];
548  v->DumpValues();
549  }
550  }
551  if (theSlowIntegralTable) {
552  G4int PhysicsTableSize = theSlowIntegralTable->entries();
553  G4PhysicsOrderedFreeVector* v;
554  for (G4int i = 0; i < PhysicsTableSize; i++) {
555  v = (G4PhysicsOrderedFreeVector*)(*theSlowIntegralTable)[i];
556  v->DumpValues();
557  }
558  }
559  }
std::unique_ptr< G4PhysicsTable > theSlowIntegralTable
std::unique_ptr< G4PhysicsTable > theFastIntegralTable
std::vector< geo::BoxBoundedGeo > larg4::OpFastScintillation::extractActiveVolumes ( geo::GeometryCore const &  geom)
staticprivate

Definition at line 2172 of file OpFastScintillation.cxx.

2173  {
2174  std::vector<geo::BoxBoundedGeo> activeVolumes;
2175  activeVolumes.reserve(geom.Ncryostats());
2176 
2177  for (geo::CryostatGeo const& cryo : geom.IterateCryostats()) {
2178 
2179  // can't use it default-constructed since it would always include origin
2180  geo::BoxBoundedGeo box{cryo.TPC(0).ActiveBoundingBox()};
2181 
2182  for (geo::TPCGeo const& TPC : cryo.IterateTPCs())
2183  box.ExtendToInclude(TPC.ActiveBoundingBox());
2184 
2185  activeVolumes.push_back(std::move(box));
2186 
2187  } // for cryostats
2188 
2189  return activeVolumes;
2190  } // OpFastScintillation::extractActiveVolumes()
Geometry information for a single TPC.
Definition: TPCGeo.h:38
Geometry information for a single cryostat.
Definition: CryostatGeo.h:43
def move(depos, offset)
Definition: depos.py:107
A base class aware of world box coordinatesAn object describing a simple shape can inherit from this ...
Definition: BoxBoundedGeo.h:33
void ExtendToInclude(Coord_t x, Coord_t y, Coord_t z)
Extends the current box to also include the specified point.
G4double larg4::OpFastScintillation::Gaisser_Hillas ( const double  x,
const double *  par 
) const
private

Definition at line 1856 of file OpFastScintillation.cxx.

1857  {
1858  double X_mu_0 = par[3];
1859  double Normalization = par[0];
1860  double Diff = par[1] - X_mu_0;
1861  double Term = std::pow((x - X_mu_0) / Diff, Diff / par[2]);
1862  double Exponential = std::exp((par[1] - x) / par[2]);
1863  return (Normalization * Term * Exponential);
1864  }
constexpr T pow(T x)
Definition: pow.h:72
list x
Definition: train.py:276
void larg4::OpFastScintillation::generateParam ( const size_t  index,
const size_t  angle_bin 
)

Definition at line 1252 of file OpFastScintillation.cxx.

1253  {
1254  // get distance
1255  double distance_in_cm = (index * fstep_size) + fmin_d;
1256 
1257  // time range
1258  const double signal_t_range = 5000.; // TODO: unhardcode
1259 
1260  // parameterisation TF1
1261  TF1 fVUVTiming;
1262 
1263  // For very short distances the time correction is just a shift
1264  double t_direct_mean = distance_in_cm / fvuv_vgroup_mean;
1265  double t_direct_min = distance_in_cm / fvuv_vgroup_max;
1266 
1267  // Defining the model function(s) describing the photon transportation timing vs distance
1268  // Getting the landau parameters from the time parametrization
1269  std::array<double, 3> pars_landau;
1270  interpolate3(pars_landau,
1271  fparameters[0][0],
1272  fparameters[2][angle_bin],
1273  fparameters[3][angle_bin],
1274  fparameters[1][angle_bin],
1275  distance_in_cm,
1276  true);
1277  // Deciding which time model to use (depends on the distance)
1278  // defining useful times for the VUV arrival time shapes
1279  if (distance_in_cm >= finflexion_point_distance) {
1280  double pars_far[4] = {t_direct_min, pars_landau[0], pars_landau[1], pars_landau[2]};
1281  // Set model: Landau
1282  fVUVTiming = TF1("fVUVTiming", model_far, 0, signal_t_range, 4);
1283  fVUVTiming.SetParameters(pars_far);
1284  }
1285  else {
1286  // Set model: Landau + Exponential
1287  fVUVTiming = TF1("fVUVTiming", model_close, 0, signal_t_range, 7);
1288  // Exponential parameters
1289  double pars_expo[2];
1290  // Getting the exponential parameters from the time parametrization
1291  pars_expo[1] = interpolate(fparameters[4][0], fparameters[5][angle_bin], distance_in_cm, true);
1292  pars_expo[0] = interpolate(fparameters[4][0], fparameters[6][angle_bin], distance_in_cm, true);
1293  pars_expo[0] *= pars_landau[2];
1294  pars_expo[0] = std::log(pars_expo[0]);
1295  // this is to find the intersection point between the two functions:
1296  TF1 fint = TF1("fint", finter_d, pars_landau[0], 4 * t_direct_mean, 5);
1297  double parsInt[5] = {
1298  pars_landau[0], pars_landau[1], pars_landau[2], pars_expo[0], pars_expo[1]};
1299  fint.SetParameters(parsInt);
1300  double t_int = fint.GetMinimumX();
1301  double minVal = fint.Eval(t_int);
1302  // the functions must intersect - output warning if they don't
1303  if (minVal > 0.015) {
1304  std::cout << "WARNING: Parametrization of VUV light discontinuous for distance = "
1305  << distance_in_cm << std::endl;
1306  std::cout << "WARNING: This shouldn't be happening " << std::endl;
1307  }
1308  double parsfinal[7] = {t_int,
1309  pars_landau[0],
1310  pars_landau[1],
1311  pars_landau[2],
1312  pars_expo[0],
1313  pars_expo[1],
1314  t_direct_min};
1315  fVUVTiming.SetParameters(parsfinal);
1316  }
1317 
1318  // set the number of points used to sample parameterisation
1319  // for shorter distances, peak is sharper so more sensitive sampling required
1320  int fsampling; // TODO: unhardcode
1321  if (distance_in_cm < 50) { fsampling = 10000; }
1322  else if (distance_in_cm < 100) {
1323  fsampling = 5000;
1324  }
1325  else {
1326  fsampling = 1000;
1327  }
1328  fVUVTiming.SetNpx(fsampling);
1329 
1330  // calculate max and min distance relevant to sample parameterisation
1331  // max
1332  const size_t nq_max = 1;
1333  double xq_max[nq_max];
1334  double yq_max[nq_max];
1335  xq_max[0] = 0.995; // include 99.5%
1336  fVUVTiming.GetQuantiles(nq_max, yq_max, xq_max);
1337  double max = yq_max[0];
1338  // min
1339  double min = t_direct_min;
1340 
1341  // store TF1 and min/max, this allows identical TF1 to be used every time sampling
1342  // the first call of GetRandom generates the timing sampling and stores it in the TF1 object, this is the slow part
1343  // all subsequent calls check if it has been generated previously and are ~100+ times quicker
1344  VUV_timing[angle_bin][index] = fVUVTiming;
1345  VUV_max[angle_bin][index] = max;
1346  VUV_min[angle_bin][index] = min;
1347  }
double finter_d(double *x, double *par)
double model_far(double *x, double *par)
std::vector< std::vector< TF1 > > VUV_timing
std::vector< std::vector< double > > fparameters[7]
double model_close(double *x, double *par)
std::vector< std::vector< double > > VUV_min
static int max(int a, int b)
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
T min(sqlite3 *const db, std::string const &table_name, std::string const &column_name)
Definition: statistics.h:55
double interpolate(const std::vector< double > &xData, const std::vector< double > &yData, double x, bool extrapolate, size_t i=0) const
std::vector< std::vector< double > > VUV_max
QTextStream & endl(QTextStream &s)
G4PhysicsTable * larg4::OpFastScintillation::GetFastIntegralTable ( ) const
inline

Definition at line 535 of file OpFastScintillation.hh.

536  {
537  return theFastIntegralTable.get();
538  }
std::unique_ptr< G4PhysicsTable > theFastIntegralTable
G4bool larg4::OpFastScintillation::GetFiniteRiseTime ( ) const
inline

Definition at line 499 of file OpFastScintillation.hh.

500  {
501  return fFiniteRiseTime;
502  }
G4double larg4::OpFastScintillation::GetMeanFreePath ( const G4Track &  aTrack,
G4double  ,
G4ForceCondition *  condition 
)

Definition at line 997 of file OpFastScintillation.cxx.

998  {
999  *condition = StronglyForced;
1000  return DBL_MAX;
1001  }
G4double larg4::OpFastScintillation::GetMeanLifeTime ( const G4Track &  aTrack,
G4ForceCondition *  condition 
)

Definition at line 1004 of file OpFastScintillation.cxx.

1005  {
1006  *condition = Forced;
1007  return DBL_MAX;
1008  }
G4EmSaturation* larg4::OpFastScintillation::GetSaturation ( ) const
inline

Definition at line 230 of file OpFastScintillation.hh.

231  {
232  return emSaturation;
233  }
G4bool larg4::OpFastScintillation::GetScintillationByParticleType ( ) const
inline

Definition at line 241 of file OpFastScintillation.hh.

242  {
244  }
G4double larg4::OpFastScintillation::GetScintillationExcitationRatio ( ) const
inline

Definition at line 523 of file OpFastScintillation.hh.

524  {
525  return ExcitationRatio;
526  }
G4double larg4::OpFastScintillation::GetScintillationYieldFactor ( ) const
inline

Definition at line 511 of file OpFastScintillation.hh.

512  {
513  return YieldFactor;
514  }
G4PhysicsTable * larg4::OpFastScintillation::GetSlowIntegralTable ( ) const
inline

Definition at line 529 of file OpFastScintillation.hh.

530  {
531  return theSlowIntegralTable.get();
532  }
std::unique_ptr< G4PhysicsTable > theSlowIntegralTable
G4bool larg4::OpFastScintillation::GetTrackSecondariesFirst ( ) const
inline

Definition at line 493 of file OpFastScintillation.hh.

494  {
495  return fTrackSecondariesFirst;
496  }
void larg4::OpFastScintillation::getVISTimes ( std::vector< double > &  arrivalTimes,
const TVector3 &  ScintPoint,
const TVector3 &  OpDetPoint 
)

Definition at line 1374 of file OpFastScintillation.cxx.

1377  {
1378  // *************************************************************************************************
1379  // Calculation of earliest arrival times and corresponding unsmeared distribution
1380  // *************************************************************************************************
1381 
1382  // set plane_depth for correct TPC:
1383  double plane_depth;
1384  if (ScintPoint[0] < 0) { plane_depth = -fplane_depth; }
1385  else {
1386  plane_depth = fplane_depth;
1387  }
1388 
1389  // calculate point of reflection for shortest path
1390  TVector3 bounce_point(plane_depth,ScintPoint[1],ScintPoint[2]);
1391 
1392  // calculate distance travelled by VUV light and by vis light
1393  double VUVdist = (bounce_point - ScintPoint).Mag();
1394  double Visdist = (OpDetPoint - bounce_point).Mag();
1395 
1396  // calculate times taken by VUV part of path
1397  int angle_bin_vuv = 0; // on-axis by definition
1398  getVUVTimes(arrivalTimes, VUVdist, angle_bin_vuv);
1399 
1400  // add visible direct path transport time
1401  for (size_t i = 0; i < arrivalTimes.size(); ++i) {
1402  arrivalTimes[i] += Visdist / fvis_vmean;
1403  }
1404 
1405  // *************************************************************************************************
1406  // Smearing of arrival time distribution
1407  // *************************************************************************************************
1408  // calculate fastest time possible
1409  // vis part
1410  double vis_time = Visdist / fvis_vmean;
1411  // vuv part
1412  double vuv_time;
1413  if (VUVdist < fmin_d) {
1414  vuv_time = VUVdist / fvuv_vgroup_max;
1415  }
1416  else {
1417  // find index of required parameterisation
1418  const size_t index = std::round((VUVdist - fmin_d) / fstep_size);
1419  // find shortest time
1420  vuv_time = VUV_min[angle_bin_vuv][index];
1421  }
1422  // sum
1423  double fastest_time = vis_time + vuv_time;
1424 
1425  // calculate angle theta between bound_point and optical detector
1426  double cosine_theta = std::abs(OpDetPoint[0] - bounce_point[0]) / Visdist;
1427  double theta = fast_acos(cosine_theta) * 180. / CLHEP::pi;
1428 
1429  // determine smearing parameters using interpolation of generated points:
1430  // 1). tau = exponential smearing factor, varies with distance and angle
1431  // 2). cutoff = largest smeared time allowed, preventing excessively large
1432  // times caused by exponential distance to cathode
1433  double distance_cathode_plane = std::abs(plane_depth - ScintPoint[0]);
1434  // angular bin
1435  size_t theta_bin = theta / fangle_bin_timing_vis;
1436  // radial distance from centre of TPC (y,z plane)
1437  double r = std::sqrt(std::pow(ScintPoint[1] - fcathode_centre[1], 2) + std::pow(ScintPoint[2] - fcathode_centre[2], 2));
1438 
1439  // cut-off and tau
1440  // cut-off
1441  // interpolate in d_c for each r bin
1442  std::vector<double> interp_vals(fcut_off_pars[theta_bin].size(), 0.0);
1443  for (size_t i = 0; i < fcut_off_pars[theta_bin].size(); i++){
1444  interp_vals[i] = interpolate(fdistances_refl, fcut_off_pars[theta_bin][i], distance_cathode_plane, true);
1445  }
1446  // interpolate in r
1447  double cutoff = interpolate(fradial_distances_refl, interp_vals, r, true);
1448 
1449  // tau
1450  // interpolate in x for each r bin
1451  std::vector<double> interp_vals_tau(ftau_pars[theta_bin].size(), 0.0);
1452  for (size_t i = 0; i < ftau_pars[theta_bin].size(); i++){
1453  interp_vals_tau[i] = interpolate(fdistances_refl, ftau_pars[theta_bin][i], distance_cathode_plane, true);
1454  }
1455  // interpolate in r
1456  double tau = interpolate(fradial_distances_refl, interp_vals_tau, r, true);
1457 
1458  if (tau < 0) { tau = 0; } // failsafe if tau extrapolate goes wrong
1459 
1460  // apply smearing:
1461  for (size_t i = 0; i < arrivalTimes.size(); ++i) {
1462  double arrival_time_smeared;
1463  // if time is already greater than cutoff, do not apply smearing
1464  if (arrivalTimes[i] >= cutoff) { continue; }
1465  // otherwise smear
1466  else {
1467  unsigned int counter = 0;
1468  // loop until time generated is within cutoff limit
1469  // most are within single attempt, very few take more than two
1470  do {
1471  // don't attempt smearings too many times
1472  if (counter >= 10) { // TODO: unhardcode
1473  arrival_time_smeared = arrivalTimes[i]; // don't smear
1474  break;
1475  }
1476  else {
1477  // generate random number in appropriate range
1478  double x = gRandom->Uniform(0.5, 1.0); // TODO: unhardcode
1479  // apply the exponential smearing
1480  arrival_time_smeared =
1481  arrivalTimes[i] + (arrivalTimes[i] - fastest_time) * (std::pow(x, -tau) - 1);
1482  }
1483  counter++;
1484  } while (arrival_time_smeared > cutoff);
1485  }
1486  arrivalTimes[i] = arrival_time_smeared;
1487  }
1488  }
constexpr T pow(T x)
Definition: pow.h:72
std::vector< double > fdistances_refl
std::vector< std::vector< double > > VUV_min
decltype(auto) constexpr size(T &&obj)
ADL-aware version of std::size.
Definition: StdUtils.h:92
T abs(T value)
std::vector< std::vector< std::vector< double > > > ftau_pars
std::vector< double > fradial_distances_refl
std::vector< std::vector< std::vector< double > > > fcut_off_pars
void getVUVTimes(std::vector< double > &arrivalTimes, const double distance_in_cm, const size_t angle_bin)
double interpolate(const std::vector< double > &xData, const std::vector< double > &yData, double x, bool extrapolate, size_t i=0) const
list x
Definition: train.py:276
float pi
Definition: units.py:11
double fast_acos(double x)
void larg4::OpFastScintillation::getVUVTimes ( std::vector< double > &  arrivalTimes,
const double  distance_in_cm,
const size_t  angle_bin 
)

Definition at line 1351 of file OpFastScintillation.cxx.

1352  {
1353  if (distance < fmin_d) {
1354  // times are fixed shift i.e. direct path only
1355  double t_prop_correction = distance / fvuv_vgroup_mean;
1356  for (size_t i = 0; i < arrivalTimes.size(); ++i) {
1357  arrivalTimes[i] = t_prop_correction;
1358  }
1359  }
1360  else { // distance >= fmin_d
1361  // determine nearest parameterisation in discretisation
1362  int index = std::round((distance - fmin_d) / fstep_size);
1363  // check whether required parameterisation has been generated, generating if not
1364  if (VUV_timing[angle_bin][index].GetNdim() == 0) { generateParam(index, angle_bin); }
1365  // randomly sample parameterisation for each photon
1366  for (size_t i = 0; i < arrivalTimes.size(); ++i) {
1367  arrivalTimes[i] = VUV_timing[angle_bin][index].GetRandom(VUV_min[angle_bin][index], VUV_max[angle_bin][index]);
1368  }
1369  }
1370  }
std::vector< std::vector< TF1 > > VUV_timing
std::vector< std::vector< double > > VUV_min
double distance(double x1, double y1, double z1, double x2, double y2, double z2)
void generateParam(const size_t index, const size_t angle_bin)
std::vector< std::vector< double > > VUV_max
double larg4::OpFastScintillation::interpolate ( const std::vector< double > &  xData,
const std::vector< double > &  yData,
double  x,
bool  extrapolate,
size_t  i = 0 
) const
private

Definition at line 1932 of file OpFastScintillation.cxx.

1937  {
1938  if (i == 0) {
1939  size_t size = xData.size();
1940  if (x >= xData[size - 2]) { // special case: beyond right end
1941  i = size - 2;
1942  }
1943  else {
1944  while (x > xData[i + 1])
1945  i++;
1946  }
1947  }
1948  double xL = xData[i];
1949  double xR = xData[i + 1];
1950  double yL = yData[i];
1951  double yR = yData[i + 1]; // points on either side (unless beyond ends)
1952  if (!extrapolate) { // if beyond ends of array and not extrapolating
1953  if (x < xL) return yL;
1954  if (x > xR) return yL;
1955  }
1956  const double dydx = (yR - yL) / (xR - xL); // gradient
1957  return yL + dydx * (x - xL); // linear interpolation
1958  }
decltype(auto) constexpr size(T &&obj)
ADL-aware version of std::size.
Definition: StdUtils.h:92
list x
Definition: train.py:276
void larg4::OpFastScintillation::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
private

Definition at line 1961 of file OpFastScintillation.cxx.

1968  {
1969  size_t size = xData.size();
1970  size_t i = 0; // find left end of interval for interpolation
1971  if (x >= xData[size - 2]) { // special case: beyond right end
1972  i = size - 2;
1973  }
1974  else {
1975  while (x > xData[i + 1])
1976  i++;
1977  }
1978  double xL = xData[i];
1979  double xR = xData[i + 1]; // points on either side (unless beyond ends)
1980  double yL1 = yData1[i];
1981  double yR1 = yData1[i + 1];
1982  double yL2 = yData2[i];
1983  double yR2 = yData2[i + 1];
1984  double yL3 = yData3[i];
1985  double yR3 = yData3[i + 1];
1986 
1987  if (!extrapolate) { // if beyond ends of array and not extrapolating
1988  if (x < xL) {
1989  inter[0] = yL1;
1990  inter[1] = yL2;
1991  inter[2] = yL3;
1992  return;
1993  }
1994  if (x > xR) {
1995  inter[0] = yL1;
1996  inter[1] = yL2;
1997  inter[2] = yL3;
1998  return;
1999  }
2000  }
2001  const double m = (x - xL) / (xR - xL);
2002  inter[0] = m * (yR1 - yL1) + yL1;
2003  inter[1] = m * (yR2 - yL2) + yL2;
2004  inter[2] = m * (yR3 - yL3) + yL3;
2005  }
decltype(auto) constexpr size(T &&obj)
ADL-aware version of std::size.
Definition: StdUtils.h:92
list x
Definition: train.py:276
G4bool larg4::OpFastScintillation::IsApplicable ( const G4ParticleDefinition &  aParticleType)
inlinevirtual

Definition at line 472 of file OpFastScintillation.hh.

473  {
474  if (aParticleType.GetParticleName() == "opticalphoton") return false;
475  if (aParticleType.IsShortLived()) return false;
476 
477  return true;
478  }
bool larg4::OpFastScintillation::isOpDetInSameTPC ( geo::Point_t const &  ScintPoint,
geo::Point_t const &  OpDetPoint 
) const
private

Definition at line 1822 of file OpFastScintillation.cxx.

1824  {
1825  // check optical channel is in same TPC as scintillation light, if not return 0 hits
1826  // temporary method working for SBND, uBooNE, DUNE 1x2x6; to be replaced to work in full DUNE geometry
1827  // check x coordinate has same sign or is close to zero, otherwise return 0 hits
1828  if (((ScintPoint.X() < 0.) != (OpDetPoint.X() < 0.)) &&
1829  std::abs(OpDetPoint.X()) > 10.) { // TODO: unhardcode
1830  return false;
1831  }
1832  return true;
1833  }
T abs(T value)
bool larg4::OpFastScintillation::isScintInActiveVolume ( geo::Point_t const &  ScintPoint)
private

Definition at line 1836 of file OpFastScintillation.cxx.

1837  {
1838  //semi-analytic approach only works in the active volume
1839  return fActiveVolumes[0].ContainsPosition(ScintPoint);
1840  }
std::vector< geo::BoxBoundedGeo > const fActiveVolumes
double larg4::OpFastScintillation::Omega_Dome_Model ( const double  distance,
const double  theta 
) const
private

Definition at line 2140 of file OpFastScintillation.cxx.

2140  {
2141  // this function calculates the solid angle of a semi-sphere of radius b,
2142  // as a correction to the analytic formula of the on-axix solid angle,
2143  // as we move off-axis an angle theta. We have used 9-angular bins
2144  // with delta_theta width.
2145 
2146  // par0 = Radius correction close
2147  // par1 = Radius correction far
2148  // par2 = breaking distance betwween "close" and "far"
2149 
2150  double par0[9] = {0., 0., 0., 0., 0., 0.597542, 1.00872, 1.46993, 2.04221};
2151  double par1[9] = {0, 0, 0.19569, 0.300449, 0.555598, 0.854939, 1.39166, 2.19141, 2.57732};
2152  const double delta_theta = 10.;
2153  int j = int(theta/delta_theta);
2154  // PMT radius
2155  const double b = fradius; // cm
2156  // distance form which the model parameters break (empirical value)
2157  const double d_break = 5*b; //par2
2158 
2159  if(distance >= d_break) {
2160  double R_apparent_far = b - par1[j];
2161  return (2*CLHEP::pi * (1 - std::sqrt(1 - std::pow(R_apparent_far/distance,2))));
2162 
2163  }
2164  else {
2165  double R_apparent_close = b - par0[j];
2166  return (2*CLHEP::pi * (1 - std::sqrt(1 - std::pow(R_apparent_close/distance,2))));
2167  }
2168 }
constexpr T pow(T x)
Definition: pow.h:72
double distance(double x1, double y1, double z1, double x2, double y2, double z2)
static bool * b
Definition: config.cpp:1043
float pi
Definition: units.py:11
G4VParticleChange * larg4::OpFastScintillation::PostStepDoIt ( const G4Track &  aTrack,
const G4Step &  aStep 
)
virtual

Definition at line 425 of file OpFastScintillation.cxx.

430  {
431  aParticleChange.Initialize(aTrack);
432  // Check that we are in a material with a properties table, if not
433  // just return
434  const G4Material* aMaterial = aTrack.GetMaterial();
435  G4MaterialPropertiesTable* aMaterialPropertiesTable = aMaterial->GetMaterialPropertiesTable();
436  if (!aMaterialPropertiesTable) return G4VRestDiscreteProcess::PostStepDoIt(aTrack, aStep);
437 
438  G4StepPoint* pPreStepPoint = aStep.GetPreStepPoint();
439  G4ThreeVector x0 = pPreStepPoint->GetPosition();
440  G4ThreeVector p0 = aStep.GetDeltaPosition().unit();
441 
442  ///////////////////////////////////////////////////////////////////////////////////
443  // This is the old G4 way - but we do things differently - Ben J, Oct Nov 2012.
444  ///////////////////////////////////////////////////////////////////////////////////
445  //
446  // if (MeanNumberOfPhotons > 10.)
447  // {
448  // G4double sigma = ResolutionScale * std::sqrt(MeanNumberOfPhotons);
449  // NumPhotons = G4int(G4RandGauss::shoot(MeanNumberOfPhotons,sigma)+0.5);
450  // }
451  // else
452  // {
453  // NumPhotons = G4int(G4Poisson(MeanNumberOfPhotons));
454  // }
455  //
456  //
457  //
458  // if (NumPhotons <= 0)
459  // {
460  // // return unchanged particle and no secondaries
461  //
462  // aParticleChange.SetNumberOfSecondaries(0);
463  //
464  // return G4VRestDiscreteProcess::PostStepDoIt(aTrack, aStep);
465  // }
466  //
467  //
468  // aParticleChange.SetNumberOfSecondaries(NumPhotons);
469  //
470  //
471  // if (fTrackSecondariesFirst) {
472  // if (aTrack.GetTrackStatus() == fAlive )
473  // aParticleChange.ProposeTrackStatus(fSuspend);
474  // }
475  //
476  //
477  //
478  //
479  ////////////////////////////////////////////////////////////////////////////////////
480  //
481 
482  ////////////////////////////////////////////////////////////////////////////////////
483  // The fast sim way - Ben J, Nov 2012
484  ////////////////////////////////////////////////////////////////////////////////////
485  //
486  //
487  // We don't want to produce any trackable G4 secondaries
488  aParticleChange.SetNumberOfSecondaries(0);
489 
490  // Retrieve the Scintillation Integral for this material
491  // new G4PhysicsOrderedFreeVector allocated to hold CII's
492 
493  // Some explanation for later improvements to scint yield code:
494  //
495  // What does G4 do here?
496  // It produces light in 2 steps, fast (scnt=1) then slow (scnt=2)
497  //
498  // The ratio of slow photons to fast photons is related by the yieldratio
499  // parameter. G4's poisson fluctuating scheme is a bit different to ours
500  // - we should check that they are equivalent.
501  //
502  // G4 poisson fluctuates the number of initial photons then divides them
503  // with a constant factor between fast + slow, whereas we poisson
504  // fluctuate separateyly the fast and slow detection numbers.
505  //
506 
507  // get the number of photons produced from the IonizationAndScintillation
508  // singleton
510  double MeanNumberOfPhotons =
512  // double stepEnergy = larg4::IonizationAndScintillation::Instance()->VisibleEnergyDeposit()/CLHEP::MeV;
513  RecordPhotonsProduced(aStep, MeanNumberOfPhotons); //, stepEnergy);
514  if (verboseLevel > 0) {
515  G4cout << "\n Exiting from OpFastScintillation::DoIt -- NumberOfSecondaries = "
516  << aParticleChange.GetNumberOfSecondaries() << G4endl;
517  }
518  return G4VRestDiscreteProcess::PostStepDoIt(aTrack, aStep);
519  }
bool RecordPhotonsProduced(const G4Step &aStep, double N)
static IonizationAndScintillation * Instance()
void larg4::OpFastScintillation::ProcessStep ( const G4Step &  step)
private

Definition at line 522 of file OpFastScintillation.cxx.

523  {
524  if (step.GetTotalEnergyDeposit() <= 0) return;
525 
527  -1,
528  -1,
529  1.0, //scintillation yield
530  (double)(step.GetTotalEnergyDeposit() / CLHEP::MeV), //energy in 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()),
539  //step.GetTrack()->GetTrackID(),
541  step.GetTrack()->GetParticleDefinition()->GetPDGEncoding(),
542  step.GetPreStepPoint()->GetPhysicalVolume()->GetName());
543  }
static constexpr double cm
Definition: Units.h:68
static constexpr double MeV
Definition: Units.h:129
static OpDetPhotonTable * Instance(bool LitePhotons=false)
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, std::string const &vol="EMPTY")
void larg4::OpFastScintillation::propagationTime ( std::vector< double > &  arrival_time_dist,
G4ThreeVector  x0,
const size_t  OpChannel,
bool  Reflected = false 
)
private

Definition at line 1028 of file OpFastScintillation.cxx.

1032  {
1033  assert(fPVS);
1035  throw cet::exception("OpFastScintillation")
1036  << "Cannot have both propagation time models simultaneously.";
1037  }
1038  else if (fPVS->IncludeParPropTime() &&
1039  !(ParPropTimeTF1 && (ParPropTimeTF1[OpChannel].GetNdim() == 1))) {
1040  //Warning: TF1::GetNdim()==1 will tell us if the TF1 is really defined or it is the default one.
1041  //This will fix a segfault when using timing and interpolation.
1042  G4cout << "WARNING: Requested parameterized timing, but no function found. Not applying "
1043  "propagation time."
1044  << G4endl;
1045  }
1046  else if (fPVS->IncludeParPropTime()) {
1047  if (Reflected)
1048  throw cet::exception("OpFastScintillation")
1049  << "No parameterized propagation time for reflected light";
1050  for (size_t i = 0; i < arrival_time_dist.size(); ++i) {
1051  arrival_time_dist[i] = ParPropTimeTF1[OpChannel].GetRandom();
1052  }
1053  }
1054  else if (fPVS->IncludePropTime()) {
1055  // Get VUV photons arrival time distribution from the parametrization
1056  geo::Point_t const& opDetCenter = fOpDetCenter.at(OpChannel);
1057  if (!Reflected) {
1058  const G4ThreeVector OpDetPoint(
1059  opDetCenter.X() * CLHEP::cm, opDetCenter.Y() * CLHEP::cm, opDetCenter.Z() * CLHEP::cm);
1060  double distance_in_cm = (x0 - OpDetPoint).mag() / CLHEP::cm; // this must be in CENTIMETERS!
1061  double cosine = std::abs(x0[0]*CLHEP::cm - OpDetPoint[0]*CLHEP::cm) / distance_in_cm;
1062  double theta = fast_acos(cosine)*180./CLHEP::pi;
1063  int angle_bin = theta/fangle_bin_timing_vuv;
1064  getVUVTimes(arrival_time_dist, distance_in_cm, angle_bin); // in ns
1065  }
1066  else {
1067  TVector3 const ScintPoint(x0[0] / CLHEP::cm, x0[1] / CLHEP::cm, x0[2] / CLHEP::cm); // in cm
1068  getVISTimes(arrival_time_dist, ScintPoint, geo::vect::toTVector3(opDetCenter)); // in ns
1069  }
1070  }
1071  }
static constexpr double cm
Definition: Units.h:68
Index OpChannel(Index detNum, Index channel)
std::vector< geo::Point_t > fOpDetCenter
void getVISTimes(std::vector< double > &arrivalTimes, const TVector3 &ScintPoint, const TVector3 &OpDetPoint)
T abs(T value)
ROOT::Math::PositionVector3D< ROOT::Math::Cartesian3D< double >, ROOT::Math::GlobalCoordinateSystemTag > Point_t
Type for representation of position in physical 3D space.
Definition: geo_vectors.h:184
void getVUVTimes(std::vector< double > &arrivalTimes, const double distance_in_cm, const size_t angle_bin)
TVector3 toTVector3(Vector const &v)
Converts a vector into a TVector3.
phot::PhotonVisibilityService const *const fPVS
Photon visibility service instance.
float pi
Definition: units.py:11
phot::MappedFunctions_t ParPropTimeTF1
cet::coded_exception< error, detail::translate > exception
Definition: exception.h:33
double fast_acos(double x)
bool larg4::OpFastScintillation::RecordPhotonsProduced ( const G4Step &  aStep,
double  N 
)
protected

Definition at line 545 of file OpFastScintillation.cxx.

547  {
548  // make sure that whatever happens afterwards, the energy deposition is stored
550  if (lgp->FillSimEnergyDeposits()) ProcessStep(aStep);
551 
552  // Get the pointer to the fast scintillation table
553  OpDetPhotonTable* fst = OpDetPhotonTable::Instance();
554 
555  const G4Track* aTrack = aStep.GetTrack();
556 
557  G4StepPoint const* pPreStepPoint = aStep.GetPreStepPoint();
558  // unused G4StepPoint const* pPostStepPoint = aStep.GetPostStepPoint();
559 
560  const G4DynamicParticle* aParticle = aTrack->GetDynamicParticle();
561  const G4Material* aMaterial = aTrack->GetMaterial();
562 
563  G4int materialIndex = aMaterial->GetIndex();
564  G4int tracknumber = aStep.GetTrack()->GetTrackID();
565 
566  G4ThreeVector x0 = pPreStepPoint->GetPosition();
567  G4ThreeVector p0 = aStep.GetDeltaPosition().unit();
568  //G4double t0 = pPreStepPoint->GetGlobalTime() - fGlobalTimeOffset;
569  G4double t0 = pPreStepPoint->GetGlobalTime();
570 
571  G4MaterialPropertiesTable* aMaterialPropertiesTable = aMaterial->GetMaterialPropertiesTable();
572 
573  G4MaterialPropertyVector* Fast_Intensity =
574  aMaterialPropertiesTable->GetProperty("FASTCOMPONENT");
575  G4MaterialPropertyVector* Slow_Intensity =
576  aMaterialPropertiesTable->GetProperty("SLOWCOMPONENT");
577 
578  if (!Fast_Intensity && !Slow_Intensity) return 1;
579 
580  if (!bPropagate) return 0;
581 
582  // Get the visibility vector for this point
583  assert(fPVS);
584 
585  G4int nscnt = 1;
586  if (Fast_Intensity && Slow_Intensity) nscnt = 2;
587 
588  double Num = 0;
589  double YieldRatio = 0;
590 
592  // The scintillation response is a function of the energy
593  // deposited by particle types.
594 
595  // Get the definition of the current particle
596  G4ParticleDefinition* pDef = aParticle->GetDefinition();
597 
598  // Obtain the G4MaterialPropertyVectory containing the
599  // scintillation light yield as a function of the deposited
600  // energy for the current particle type
601 
602  // Protons
603  if (pDef == G4Proton::ProtonDefinition()) {
604  YieldRatio = aMaterialPropertiesTable->GetConstProperty("PROTONYIELDRATIO");
605  }
606  // Muons
607  else if (pDef == G4MuonPlus::MuonPlusDefinition() ||
608  pDef == G4MuonMinus::MuonMinusDefinition()) {
609  YieldRatio = aMaterialPropertiesTable->GetConstProperty("MUONYIELDRATIO");
610  }
611  // Pions
612  else if (pDef == G4PionPlus::PionPlusDefinition() ||
613  pDef == G4PionMinus::PionMinusDefinition()) {
614  YieldRatio = aMaterialPropertiesTable->GetConstProperty("PIONYIELDRATIO");
615  }
616  // Kaons
617  else if (pDef == G4KaonPlus::KaonPlusDefinition() ||
618  pDef == G4KaonMinus::KaonMinusDefinition()) {
619  YieldRatio = aMaterialPropertiesTable->GetConstProperty("KAONYIELDRATIO");
620  }
621  // Alphas
622  else if (pDef == G4Alpha::AlphaDefinition()) {
623  YieldRatio = aMaterialPropertiesTable->GetConstProperty("ALPHAYIELDRATIO");
624  }
625  // Electrons (must also account for shell-binding energy
626  // attributed to gamma from standard PhotoElectricEffect)
627  else if (pDef == G4Electron::ElectronDefinition() || pDef == G4Gamma::GammaDefinition()) {
628  YieldRatio = aMaterialPropertiesTable->GetConstProperty("ELECTRONYIELDRATIO");
629  }
630  // Default for particles not enumerated/listed above
631  else {
632  YieldRatio = aMaterialPropertiesTable->GetConstProperty("ELECTRONYIELDRATIO");
633  }
634  // If the user has not specified yields for (p,d,t,a,carbon)
635  // then these unspecified particles will default to the
636  // electron's scintillation yield
637  if (YieldRatio == 0) {
638  YieldRatio = aMaterialPropertiesTable->GetConstProperty("ELECTRONYIELDRATIO");
639  }
640  }
641 
642  geo::Point_t const ScintPoint = {x0[0] / CLHEP::cm, x0[1] / CLHEP::cm, x0[2] / CLHEP::cm};
643  if (fOnlyActiveVolume && !isScintInActiveVolume(ScintPoint)) return 0;
644  const phot::MappedCounts_t& Visibilities = fPVS->GetAllVisibilities(ScintPoint);
645 
646  phot::MappedCounts_t ReflVisibilities;
647 
648  // Store timing information in the object for use in propagationTime method
649  if (fPVS->StoreReflected()) {
650  ReflVisibilities = fPVS->GetAllVisibilities(ScintPoint, true);
651  if (fPVS->StoreReflT0()) ReflT0s = fPVS->GetReflT0s(ScintPoint);
652  }
653  if (fPVS->IncludeParPropTime()) { ParPropTimeTF1 = fPVS->GetTimingTF1(ScintPoint); }
654 
655  /*
656  // For Kazu to debug # photons generated using csv file, by default should be commented out
657  // but don't remove as it's useful. Separated portion of code relevant to this block
658  // is labeled as "CASE-DEBUG DO NOT REMOVE THIS COMMENT"
659  // (2017 May 2nd ... "kazuhiro at nevis dot columbia dot edu")
660  //
661  static bool first_time=false;
662  if(!first_time) {
663  std::cout<<"LOGMEid,pdg,mass,ke,te,de,x,y,z,t,dr,mean_npe,gen_npe,det_npe"<<std::endl;
664  first_time=true;
665  }
666 
667  std::cout<<"LOGME"
668  <<aStep.GetTrack()->GetTrackID()<<","
669  <<aParticle->GetDefinition()->GetPDGEncoding()<<","
670  <<aParticle->GetDefinition()->GetPDGMass()/CLHEP::MeV<<","
671  <<pPreStepPoint->GetKineticEnergy()<<","
672  <<pPreStepPoint->GetTotalEnergy()<<","
673  <<aStep.GetTotalEnergyDeposit()<<","
674  <<ScintPoint<<","<<t0<<","
675  <<aStep.GetDeltaPosition().mag()<<","
676  <<MeanNumberOfPhotons<<","<<std::flush;
677 
678  double gen_photon_ctr=0;
679  double det_photon_ctr=0;
680  */
681  for (G4int scnt = 1; scnt <= nscnt; scnt++) {
682  G4double ScintillationTime = 0. * CLHEP::ns;
683  G4double ScintillationRiseTime = 0. * CLHEP::ns;
684  G4PhysicsOrderedFreeVector* ScintillationIntegral = NULL;
685  if (scnt == 1) {
686  if (nscnt == 1) {
687  if (Fast_Intensity) {
688  ScintillationTime = aMaterialPropertiesTable->GetConstProperty("FASTTIMECONSTANT");
689  if (fFiniteRiseTime) {
690  ScintillationRiseTime =
691  aMaterialPropertiesTable->GetConstProperty("FASTSCINTILLATIONRISETIME");
692  }
693  ScintillationIntegral =
694  (G4PhysicsOrderedFreeVector*)((*theFastIntegralTable)(materialIndex));
695  }
696  if (Slow_Intensity) {
697  ScintillationTime = aMaterialPropertiesTable->GetConstProperty("SLOWTIMECONSTANT");
698  if (fFiniteRiseTime) {
699  ScintillationRiseTime =
700  aMaterialPropertiesTable->GetConstProperty("SLOWSCINTILLATIONRISETIME");
701  }
702  ScintillationIntegral =
703  (G4PhysicsOrderedFreeVector*)((*theSlowIntegralTable)(materialIndex));
704  }
705  } //endif nscnt=1
706  else {
707  if (YieldRatio == 0)
708  YieldRatio = aMaterialPropertiesTable->GetConstProperty("YIELDRATIO");
709 
710  if (ExcitationRatio == 1.0) { Num = std::min(YieldRatio, 1.0) * MeanNumberOfPhotons; }
711  else {
712  Num = std::min(ExcitationRatio, 1.0) * MeanNumberOfPhotons;
713  }
714  ScintillationTime = aMaterialPropertiesTable->GetConstProperty("FASTTIMECONSTANT");
715  if (fFiniteRiseTime) {
716  ScintillationRiseTime =
717  aMaterialPropertiesTable->GetConstProperty("FASTSCINTILLATIONRISETIME");
718  }
719  ScintillationIntegral =
720  (G4PhysicsOrderedFreeVector*)((*theFastIntegralTable)(materialIndex));
721  } //endif nscnt!=1
722  } //end scnt=1
723 
724  else {
725  Num = MeanNumberOfPhotons - Num;
726  ScintillationTime = aMaterialPropertiesTable->GetConstProperty("SLOWTIMECONSTANT");
727  if (fFiniteRiseTime) {
728  ScintillationRiseTime =
729  aMaterialPropertiesTable->GetConstProperty("SLOWSCINTILLATIONRISETIME");
730  }
731  ScintillationIntegral =
732  (G4PhysicsOrderedFreeVector*)((*theSlowIntegralTable)(materialIndex));
733  }
734 
735  if (!ScintillationIntegral) continue;
736  //gen_photon_ctr += Num; // CASE-DEBUG DO NOT REMOVE THIS COMMENT
737  // Max Scintillation Integral
738  // G4double CIImax = ScintillationIntegral->GetMaxValue();
739  //std::cout << "++++++++++++" << Num << "++++++++++" << std::endl;
740 
741  // here we go: now if visibilities are invalid, we are in trouble
742  //if (!Visibilities && (fPVS->NOpChannels() > 0)) {
743  // throw cet::exception("OpFastScintillator")
744  // << "Photon library does not cover point " << ScintPoint << " cm.\n";
745  //}
746 
747  if (!Visibilities && !usesSemiAnalyticModel()) continue;
748 
749  // detected photons from direct light
750  std::map<size_t, int> DetectedNum;
751  if (Visibilities && !usesSemiAnalyticModel()) {
752  for (size_t const OpDet : util::counter(fPVS->NOpChannels())) {
753  if (fOpaqueCathode && !isOpDetInSameTPC(ScintPoint, fOpDetCenter.at(OpDet))) continue;
754  int const DetThis = std::round(G4Poisson(Visibilities[OpDet] * Num));
755  if (DetThis > 0) DetectedNum[OpDet] = DetThis;
756  }
757  }
758  else {
759  detectedDirectHits(DetectedNum, Num, ScintPoint);
760  }
761 
762  // detected photons from reflected light
763  std::map<size_t, int> ReflDetectedNum;
764  if (fPVS->StoreReflected()) {
765  if (!usesSemiAnalyticModel()) {
766  for (size_t const OpDet : util::counter(fPVS->NOpChannels())) {
767  if (fOpaqueCathode && !isOpDetInSameTPC(ScintPoint, fOpDetCenter.at(OpDet))) continue;
768  int const ReflDetThis = std::round(G4Poisson(ReflVisibilities[OpDet] * Num));
769  if (ReflDetThis > 0) ReflDetectedNum[OpDet] = ReflDetThis;
770  }
771  }
772  else {
773  detectedReflecHits(ReflDetectedNum, Num, ScintPoint);
774  }
775  }
776 
777  std::vector<double> arrival_time_dist;
778  // Now we run through each PMT figuring out num of detected photons
779  for (size_t Reflected = 0; Reflected <= 1; ++Reflected) {
780  // Only do the reflected loop if we have reflected visibilities
781  if (Reflected && !fPVS->StoreReflected()) continue;
782 
785  if (Reflected) {
786  itstart = ReflDetectedNum.begin();
787  itend = ReflDetectedNum.end();
788  }
789  else {
790  itstart = DetectedNum.begin();
791  itend = DetectedNum.end();
792  }
793  for (auto itdetphot = itstart; itdetphot != itend; ++itdetphot) {
794  const size_t OpChannel = itdetphot->first;
795  const int NPhotons = itdetphot->second;
796 
797  // Set up the OpDetBTR information
798  sim::OpDetBacktrackerRecord tmpOpDetBTRecord(OpChannel);
799  int thisG4TrackID = ParticleListAction::GetCurrentTrackID();
800  double xyzPos[3];
801  average_position(aStep, xyzPos);
802  double Edeposited = 0;
804  //We use this when it is the only sensical information. It may be of limited use to end users.
805  Edeposited = aStep.GetTotalEnergyDeposit();
806  }
807  else if (emSaturation) {
808  //If Birk Coefficient used, log VisibleEnergies.
809  Edeposited =
811  }
812  else {
813  //We use this when it is the only sensical information. It may be of limited use to end users.
814  Edeposited = aStep.GetTotalEnergyDeposit();
815  }
816 
817  // Get the transport time distribution
818  arrival_time_dist.resize(NPhotons);
819  propagationTime(arrival_time_dist, x0, OpChannel, Reflected);
820 
821  //We need to split the energy up by the number of photons so that we never try to write a 0 energy.
822  Edeposited = Edeposited / double(NPhotons);
823 
824  // Loop through the photons
825  for (G4int i = 0; i < NPhotons; ++i) {
826  //std::cout<<"VUV time correction: "<<arrival_time_dist[i]<<std::endl;
827  G4double Time = t0 + scint_time(aStep, ScintillationTime, ScintillationRiseTime) +
828  arrival_time_dist[i] * CLHEP::ns;
829 
830  // Always store the BTR
831  tmpOpDetBTRecord.AddScintillationPhotons(thisG4TrackID, Time, 1, xyzPos, Edeposited);
832 
833  // Store as lite photon or as OnePhoton
834  if (lgp->UseLitePhotons()) {
835  fst->AddLitePhoton(OpChannel, static_cast<int>(Time), 1, Reflected);
836  }
837  else {
838  // The sim photon in this case stores its production point and time
839  TVector3 PhotonPosition(x0[0], x0[1], x0[2]);
840 
841  float PhotonEnergy = 0;
842  if (Reflected)
843  PhotonEnergy = reemission_energy() * CLHEP::eV;
844  else
845  PhotonEnergy = 9.7 * CLHEP::eV; // 9.7 eV peak of VUV emission spectrum
846 
847  // Make a photon object for the collection
848  sim::OnePhoton PhotToAdd;
849  PhotToAdd.InitialPosition = PhotonPosition;
850  PhotToAdd.Energy = PhotonEnergy;
851  PhotToAdd.Time = Time;
852  PhotToAdd.SetInSD = false;
853  PhotToAdd.MotherTrackID = tracknumber;
854 
855  fst->AddPhoton(OpChannel, std::move(PhotToAdd), Reflected);
856  }
857  }
858  fst->AddOpDetBacktrackerRecord(tmpOpDetBTRecord, Reflected);
859  }
860  }
861  }
862  //std::cout<<gen_photon_ctr<<","<<det_photon_ctr<<std::endl; // CASE-DEBUG DO NOT REMOVE THIS COMMENT
863  return 0;
864  }
static constexpr double cm
Definition: Units.h:68
code to link reconstructed objects back to the MC truth information
Index OpChannel(Index detNum, Index channel)
void detectedDirectHits(std::map< size_t, int > &DetectedNum, const double Num, geo::Point_t const &ScintPoint) const
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
bool isScintInActiveVolume(geo::Point_t const &ScintPoint)
std::vector< geo::Point_t > fOpDetCenter
void propagationTime(std::vector< double > &arrival_time_dist, G4ThreeVector x0, const size_t OpChannel, bool Reflected=false)
bool const fOnlyActiveVolume
Whether photon propagation is performed only from active volumes.
All information of a photon entering the sensitive optical detector volume.
Definition: SimPhotons.h:64
bool isOpDetInSameTPC(geo::Point_t const &ScintPoint, geo::Point_t const &OpDetPoint) const
MappedFunctions_t GetTimingTF1(Point const &p) const
void ProcessStep(const G4Step &step)
std::unique_ptr< G4PhysicsTable > theSlowIntegralTable
intermediate_table::const_iterator const_iterator
static constexpr double MeV
Definition: Units.h:129
G4double scint_time(const G4Step &aStep, G4double ScintillationTime, G4double ScintillationRiseTime) const
Energy deposited on a readout Optical Detector by simulated tracks.
geo::Point_t InitialPosition
Scintillation position in world coordinates [cm].
Definition: SimPhotons.h:67
bool const bPropagate
Whether propagation of photons is enabled.
auto counter(T begin, T end)
Returns an object to iterate values from begin to end in a range-for loop.
Definition: counter.h:285
bool usesSemiAnalyticModel() const
Returns whether the semi-analytic visibility parametrization is being used.
MappedT0s_t GetReflT0s(Point const &p) const
static constexpr double eV
Definition: Units.h:127
def move(depos, offset)
Definition: depos.py:107
static IonizationAndScintillation * Instance()
bool FillSimEnergyDeposits() const
MappedCounts_t GetAllVisibilities(Point const &p, bool wantReflected=false) const
ROOT::Math::PositionVector3D< ROOT::Math::Cartesian3D< double >, ROOT::Math::GlobalCoordinateSystemTag > Point_t
Type for representation of position in physical 3D space.
Definition: geo_vectors.h:184
static OpDetPhotonTable * Instance(bool LitePhotons=false)
A container for photon visibility mapping data.
T min(sqlite3 *const db, std::string const &table_name, std::string const &column_name)
Definition: statistics.h:55
bool SetInSD
Whether the photon reaches the sensitive detector.
Definition: SimPhotons.h:88
phot::PhotonVisibilityService const *const fPVS
Photon visibility service instance.
bool const fOpaqueCathode
Whether the cathodes are fully opaque; currently hard coded "no".
float Energy
Scintillation photon energy [GeV].
Definition: SimPhotons.h:82
phot::MappedFunctions_t ParPropTimeTF1
QAsciiDict< Entry > ns
bool UseLitePhotons() const
std::unique_ptr< G4PhysicsTable > theFastIntegralTable
int MotherTrackID
ID of the GEANT4 track causing the scintillation.
Definition: SimPhotons.h:85
double larg4::OpFastScintillation::Rectangle_SolidAngle ( const double  a,
const double  b,
const double  d 
) const
private

Definition at line 2075 of file OpFastScintillation.cxx.

2076  {
2077  double aa = a / (2. * d);
2078  double bb = b / (2. * d);
2079  double aux = (1. + aa * aa + bb * bb) / ((1. + aa * aa) * (1. + bb * bb));
2080  // return 4 * std::acos(std::sqrt(aux));
2081  return 4. * fast_acos(std::sqrt(aux));
2082  }
const double a
static bool * b
Definition: config.cpp:1043
double fast_acos(double x)
double larg4::OpFastScintillation::Rectangle_SolidAngle ( Dims const &  o,
const std::array< double, 3 >  v 
) const
private

Definition at line 2086 of file OpFastScintillation.cxx.

2087  {
2088  // v is the position of the track segment with respect to
2089  // the center position of the arapuca window
2090 
2091  // arapuca plane fixed in x direction
2092  if (isApproximatelyZero(v[1]) && isApproximatelyZero(v[2])) {
2093  return Rectangle_SolidAngle(o.h, o.w, v[0]);
2094  }
2095  if (isDefinitelyGreaterThan(v[1], o.h * .5) && isDefinitelyGreaterThan(v[2], o.w * .5)) {
2096  double A = v[1] - o.h * .5;
2097  double B = v[2] - o.w * .5;
2098  double to_return = (Rectangle_SolidAngle(2. * (A + o.h), 2. * (B + o.w), v[0]) -
2099  Rectangle_SolidAngle(2. * A, 2. * (B + o.w), v[0]) -
2100  Rectangle_SolidAngle(2. * (A + o.h), 2. * B, v[0]) +
2101  Rectangle_SolidAngle(2. * A, 2. * B, v[0])) *
2102  .25;
2103  return to_return;
2104  }
2105  if ((v[1] <= o.h * .5) && (v[2] <= o.w * .5)) {
2106  double A = -v[1] + o.h * .5;
2107  double B = -v[2] + o.w * .5;
2108  double to_return = (Rectangle_SolidAngle(2. * (o.h - A), 2. * (o.w - B), v[0]) +
2109  Rectangle_SolidAngle(2. * A, 2. * (o.w - B), v[0]) +
2110  Rectangle_SolidAngle(2. * (o.h - A), 2. * B, v[0]) +
2111  Rectangle_SolidAngle(2. * A, 2. * B, v[0])) *
2112  .25;
2113  return to_return;
2114  }
2115  if (isDefinitelyGreaterThan(v[1], o.h * .5) && (v[2] <= o.w * .5)) {
2116  double A = v[1] - o.h * .5;
2117  double B = -v[2] + o.w * .5;
2118  double to_return = (Rectangle_SolidAngle(2. * (A + o.h), 2. * (o.w - B), v[0]) -
2119  Rectangle_SolidAngle(2. * A, 2. * (o.w - B), v[0]) +
2120  Rectangle_SolidAngle(2. * (A + o.h), 2. * B, v[0]) -
2121  Rectangle_SolidAngle(2. * A, 2. * B, v[0])) *
2122  .25;
2123  return to_return;
2124  }
2125  if ((v[1] <= o.h * .5) && isDefinitelyGreaterThan(v[2], o.w * .5)) {
2126  double A = -v[1] + o.h * .5;
2127  double B = v[2] - o.w * .5;
2128  double to_return = (Rectangle_SolidAngle(2. * (o.h - A), 2. * (B + o.w), v[0]) -
2129  Rectangle_SolidAngle(2. * (o.h - A), 2. * B, v[0]) +
2130  Rectangle_SolidAngle(2. * A, 2. * (B + o.w), v[0]) -
2131  Rectangle_SolidAngle(2. * A, 2. * B, v[0])) *
2132  .25;
2133  return to_return;
2134  }
2135  // error message if none of these cases, i.e. something has gone wrong!
2136  // std::cout << "Warning: invalid solid angle call." << std::endl;
2137  return 0.;
2138  }
static constexpr bool isDefinitelyGreaterThan(TReal a, TReal b, TReal tolerance=std::numeric_limits< TReal >::epsilon())
double Rectangle_SolidAngle(const double a, const double b, const double d) const
static constexpr bool isApproximatelyZero(TReal a, TReal tolerance=std::numeric_limits< TReal >::epsilon())
double larg4::OpFastScintillation::reemission_energy ( ) const
private

Definition at line 1095 of file OpFastScintillation.cxx.

1096  {
1097  return fTPBEm->fire() * ((*(--tpbemission.end())).first - (*tpbemission.begin()).first) +
1098  (*tpbemission.begin()).first;
1099  }
std::map< double, double > tpbemission
std::unique_ptr< CLHEP::RandGeneral > fTPBEm
void larg4::OpFastScintillation::RemoveSaturation ( )
inline

Definition at line 223 of file OpFastScintillation.hh.

224  {
225  emSaturation = NULL;
226  }
G4double larg4::OpFastScintillation::sample_time ( const G4double  tau1,
const G4double  tau2 
) const
private

Definition at line 1074 of file OpFastScintillation.cxx.

1075  {
1076  // tau1: rise time and tau2: decay time
1077  while (1) {
1078  // two random numbers
1079  G4double ran1 = G4UniformRand();
1080  G4double ran2 = G4UniformRand();
1081  //
1082  // exponential distribution as envelope function: very efficient
1083  //
1084  G4double d = (tau1 + tau2) / tau2;
1085  // make sure the envelope function is
1086  // always larger than the bi-exponential
1087  G4double t = -1.0 * tau2 * std::log(1 - ran1);
1088  G4double g = d * single_exp(t, tau2);
1089  if (ran2 <= bi_exp(t, tau1, tau2) / g) return t;
1090  }
1091  return -1.0;
1092  }
static constexpr double g
Definition: Units.h:144
G4double bi_exp(const G4double t, const G4double tau1, const G4double tau2) const
G4double tau1[100]
Definition: G4S2Light.cc:61
G4double single_exp(const G4double t, const G4double tau2) const
G4double larg4::OpFastScintillation::scint_time ( const G4Step &  aStep,
G4double  ScintillationTime,
G4double  ScintillationRiseTime 
) const
private

Definition at line 1011 of file OpFastScintillation.cxx.

1014  {
1015  G4StepPoint const* pPreStepPoint = aStep.GetPreStepPoint();
1016  G4StepPoint const* pPostStepPoint = aStep.GetPostStepPoint();
1017  G4double avgVelocity = (pPreStepPoint->GetVelocity() + pPostStepPoint->GetVelocity()) / 2.;
1018  G4double deltaTime = aStep.GetStepLength() / avgVelocity;
1019  if (ScintillationRiseTime == 0.0) {
1020  deltaTime = deltaTime - ScintillationTime * std::log(G4UniformRand());
1021  }
1022  else {
1023  deltaTime = deltaTime + sample_time(ScintillationRiseTime, ScintillationTime);
1024  }
1025  return deltaTime;
1026  }
G4double sample_time(const G4double tau1, const G4double tau2) const
void larg4::OpFastScintillation::SetFiniteRiseTime ( const G4bool  state)
inline

Definition at line 487 of file OpFastScintillation.hh.

488  {
489  fFiniteRiseTime = state;
490  }
void larg4::OpFastScintillation::SetScintillationByParticleType ( const G4bool  scintType)

Definition at line 984 of file OpFastScintillation.cxx.

985  {
986  if (emSaturation) {
987  G4Exception("OpFastScintillation::SetScintillationByParticleType",
988  "Scint02",
989  JustWarning,
990  "Redefinition: Birks Saturation is replaced by ScintillationByParticleType!");
992  }
993  scintillationByParticleType = scintType;
994  }
void larg4::OpFastScintillation::SetScintillationExcitationRatio ( const G4double  excitationratio)
inline

Definition at line 517 of file OpFastScintillation.hh.

518  {
519  ExcitationRatio = excitationratio;
520  }
void larg4::OpFastScintillation::SetScintillationYieldFactor ( const G4double  yieldfactor)
inline

Definition at line 505 of file OpFastScintillation.hh.

506  {
507  YieldFactor = yieldfactor;
508  }
void larg4::OpFastScintillation::SetTrackSecondariesFirst ( const G4bool  state)
inline

Definition at line 481 of file OpFastScintillation.hh.

482  {
483  fTrackSecondariesFirst = state;
484  }
G4double larg4::OpFastScintillation::single_exp ( const G4double  t,
const G4double  tau2 
) const
private

Definition at line 1843 of file OpFastScintillation.cxx.

1844  {
1845  return std::exp(-1.0 * t / tau2) / tau2;
1846  }
bool larg4::OpFastScintillation::usesSemiAnalyticModel ( ) const
private

Returns whether the semi-analytic visibility parametrization is being used.

Definition at line 1492 of file OpFastScintillation.cxx.

1493  {
1494  return fUseNhitsModel;
1495  } // OpFastScintillation::usesSemiAnalyticModel()
bool const fUseNhitsModel
Whether the semi-analytic model is being used for photon visibility.
int larg4::OpFastScintillation::VISHits ( geo::Point_t const &  ScintPoint,
OpticalDetector const &  opDet,
const double  cathode_hits_rec,
const std::array< double, 3 >  hotspot 
) const
private

Definition at line 1691 of file OpFastScintillation.cxx.

1695  {
1696  // 1). calculate total number of hits of VUV photons on reflective
1697  // foils via solid angle + Gaisser-Hillas corrections.
1698  // Done outside as it doesn't depend on OpDetPoint
1699 
1700  // set plane_depth for correct TPC:
1701  double plane_depth;
1702  if (ScintPoint_v.X() < 0.) { plane_depth = -fplane_depth; }
1703  else {
1704  plane_depth = fplane_depth;
1705  }
1706 
1707  // 2). calculate number of these hits which reach the optical
1708  // detector from the hotspot via solid angle
1709 
1710  // the interface has been converted into geo::Point_t, the implementation not yet
1711  std::array<double, 3U> ScintPoint;
1712  std::array<double, 3U> OpDetPoint;
1713  geo::vect::fillCoords(ScintPoint, ScintPoint_v);
1714  geo::vect::fillCoords(OpDetPoint, opDet.OpDetPoint);
1715 
1716  // calculate distances and angles for application of corrections
1717  // distance from hotspot to optical detector
1718  double distance_vis = dist(&hotspot[0], &OpDetPoint[0], 3);
1719  // angle between hotspot and optical detector
1720  double cosine_vis = std::abs(hotspot[0] - OpDetPoint[0]) / distance_vis;
1721  // double theta_vis = std::acos(cosine_vis) * 180. / CLHEP::pi;
1722  double theta_vis = fast_acos(cosine_vis) * 180. / CLHEP::pi;
1723 
1724  // calculate solid angle of optical detector
1725  double solid_angle_detector = 0;
1726  // rectangular aperture
1727  if (opDet.type == 0) {
1728  // get hotspot coordinates relative to opDet
1729  std::array<double, 3> emission_relative = {std::abs(hotspot[0] - OpDetPoint[0]),
1730  std::abs(hotspot[1] - OpDetPoint[1]),
1731  std::abs(hotspot[2] - OpDetPoint[2])};
1732  // calculate solid angle
1733  solid_angle_detector = Rectangle_SolidAngle(Dims{opDet.h, opDet.w}, emission_relative);
1734  }
1735  // dome aperture
1736  else if (opDet.type == 1) {
1737  solid_angle_detector = Omega_Dome_Model(distance_vis, theta_vis);
1738  }
1739  // disk aperture
1740  else if (opDet.type == 2) {
1741  // offset in z-y plane
1742  double d = dist(&hotspot[1], &OpDetPoint[1], 2);
1743  // drift distance (in x)
1744  double h = std::abs(hotspot[0] - OpDetPoint[0]);
1745  // calculate solid angle
1746  solid_angle_detector = Disk_SolidAngle(d, h, fradius);
1747  }
1748  else {
1749  std::cout << "Error: Invalid optical detector type. 0 = rectangular, 1 = dome, 2 = disk" << std::endl;
1750  }
1751 
1752  // calculate number of hits via geometeric acceptance
1753  double hits_geo = (solid_angle_detector / (2. * CLHEP::pi)) * cathode_hits_rec; // 2*pi due to presence of reflective foils
1754 
1755  // determine correction factor, depending on PD type
1756  const size_t k = (theta_vis / fdelta_angulo_vis); // off-set angle bin
1757  double r = dist(ScintPoint, fcathode_centre, 2, 1); // radial distance from centre of detector (Y-Z)
1758  double d_c = std::abs(ScintPoint[0] - plane_depth); // distance to cathode
1759  double border_correction = 0;
1760  // flat PDs
1761  if ((opDet.type == 0 || opDet.type == 2) && fIsFlatPDCorr){
1762  // interpolate in d_c for each r bin
1763  const size_t nbins_r = fvispars_flat[k].size();
1764  std::vector<double> interp_vals(nbins_r, 0.0);
1765  {
1766  size_t idx = 0;
1767  size_t size = fvis_distances_x_flat.size();
1768  if (d_c >= fvis_distances_x_flat[size - 2])
1769  idx = size - 2;
1770  else {
1771  while (d_c > fvis_distances_x_flat[idx + 1])
1772  idx++;
1773  }
1774  for (size_t i = 0; i < nbins_r; ++i) {
1775  interp_vals[i] = interpolate(fvis_distances_x_flat,
1776  fvispars_flat[k][i],
1777  d_c,
1778  false,
1779  idx);
1780  }
1781  }
1782  // interpolate in r
1783  border_correction = interpolate(fvis_distances_r_flat, interp_vals, r, false);
1784  }
1785  // dome PDs
1786  else if (opDet.type == 1 && fIsDomePDCorr) {
1787  // interpolate in d_c for each r bin
1788  const size_t nbins_r = fvispars_dome[k].size();
1789  std::vector<double> interp_vals(nbins_r, 0.0);
1790  {
1791  size_t idx = 0;
1792  size_t size = fvis_distances_x_dome.size();
1793  if (d_c >= fvis_distances_x_dome[size - 2])
1794  idx = size - 2;
1795  else {
1796  while (d_c > fvis_distances_x_dome[idx + 1])
1797  idx++;
1798  }
1799  for (size_t i = 0; i < nbins_r; ++i) {
1800  interp_vals[i] = interpolate(fvis_distances_x_dome,
1801  fvispars_dome[k][i],
1802  d_c,
1803  false,
1804  idx);
1805  }
1806  }
1807  // interpolate in r
1808  border_correction = interpolate(fvis_distances_r_dome, interp_vals, r, false);
1809  }
1810  else {
1811  std::cout << "Error: Invalid optical detector type. 0 = rectangular, 1 = dome, 2 = disk. Or corrections for chosen optical detector type missing." << std::endl;
1812  }
1813 
1814  // apply correction factor
1815  double hits_rec = border_correction * hits_geo / cosine_vis;
1816  double hits_vis = std::round(G4Poisson(hits_rec));
1817 
1818  return hits_vis;
1819  }
std::vector< std::vector< std::vector< double > > > fvispars_dome
std::vector< std::vector< std::vector< double > > > fvispars_flat
std::vector< double > fvis_distances_r_flat
unsigned int fillCoords(Coords &dest, Vector const &src)
Fills a coordinate array with the coordinates of a vector.
decltype(auto) constexpr size(T &&obj)
ADL-aware version of std::size.
Definition: StdUtils.h:92
T abs(T value)
std::vector< double > fvis_distances_x_flat
std::vector< double > fvis_distances_r_dome
std::vector< double > fvis_distances_x_dome
double Rectangle_SolidAngle(const double a, const double b, const double d) const
constexpr double dist(const TReal *x, const TReal *y, const unsigned int dimension)
double Omega_Dome_Model(const double distance, const double theta) 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
float pi
Definition: units.py:11
QTextStream & endl(QTextStream &s)
double fast_acos(double x)
int larg4::OpFastScintillation::VUVHits ( const double  Nphotons_created,
geo::Point_t const &  ScintPoint,
OpticalDetector const &  opDet 
) const
private

Definition at line 1595 of file OpFastScintillation.cxx.

1598  {
1599  // the interface has been converted into geo::Point_t, the implementation not yet
1600  std::array<double, 3U> ScintPoint;
1601  std::array<double, 3U> OpDetPoint;
1602  geo::vect::fillCoords(ScintPoint, ScintPoint_v);
1603  geo::vect::fillCoords(OpDetPoint, opDet.OpDetPoint);
1604 
1605  // distance and angle between ScintPoint and OpDetPoint
1606  double distance = dist(&ScintPoint[0], &OpDetPoint[0], 3);
1607  double cosine = std::abs(ScintPoint[0] - OpDetPoint[0]) / distance;
1608  // double theta = std::acos(cosine) * 180. / CLHEP::pi;
1609  double theta = fast_acos(cosine) * 180. / CLHEP::pi;
1610 
1611  // calculate solid angle:
1612  double solid_angle = 0;
1613  // Arapucas/Bars (rectangle)
1614  if (opDet.type == 0) {
1615  // get scintillation point coordinates relative to arapuca window centre
1616  std::array<double, 3> ScintPoint_rel = {std::abs(ScintPoint[0] - OpDetPoint[0]),
1617  std::abs(ScintPoint[1] - OpDetPoint[1]),
1618  std::abs(ScintPoint[2] - OpDetPoint[2])};
1619  // calculate solid angle
1620  solid_angle = Rectangle_SolidAngle(Dims{opDet.h, opDet.w}, ScintPoint_rel);
1621  }
1622  // PMTs (dome)
1623  else if (opDet.type == 1) {
1624  solid_angle = Omega_Dome_Model(distance, theta);
1625  }
1626  // PMTs (disk approximation)
1627  else if (opDet.type == 2) {
1628  // offset in z-y plane
1629  double d = dist(&ScintPoint[1], &OpDetPoint[1], 2);
1630  // drift distance (in x)
1631  double h = std::abs(ScintPoint[0] - OpDetPoint[0]);
1632  // Solid angle of a disk
1633  solid_angle = Disk_SolidAngle(d, h, fradius);
1634  }
1635  else {
1636  std::cout << "Error: Invalid optical detector type. 0 = rectangular, 1 = dome, 2 = disk" << std::endl;
1637  }
1638 
1639  // calculate number of photons hits by geometric acceptance: accounting for solid angle and LAr absorbtion length
1640  double hits_geo = std::exp(-1. * distance / fL_abs_vuv) * (solid_angle / (4 * CLHEP::pi)) * Nphotons_created;
1641 
1642  // apply Gaisser-Hillas correction for Rayleigh scattering distance
1643  // and angular dependence offset angle bin
1644  const size_t j = (theta / fdelta_angulo_vuv);
1645 
1646  // determine GH parameters, accounting for border effects
1647  // radial distance from centre of detector (Y-Z)
1648  double r = dist(ScintPoint, fcathode_centre, 2, 1);
1649  double pars_ini[4] = {0, 0, 0, 0};
1650  double s1 = 0; double s2 = 0; double s3 = 0;
1651  // flat PDs
1652  if ((opDet.type == 0 || opDet.type == 2) && fIsFlatPDCorr){
1653  pars_ini[0] = fGHvuvpars_flat[0][j];
1654  pars_ini[1] = fGHvuvpars_flat[1][j];
1655  pars_ini[2] = fGHvuvpars_flat[2][j];
1656  pars_ini[3] = fGHvuvpars_flat[3][j];
1657  s1 = interpolate( fborder_corr_angulo_flat, fborder_corr_flat[0], theta, true);
1658  s2 = interpolate( fborder_corr_angulo_flat, fborder_corr_flat[1], theta, true);
1659  s3 = interpolate( fborder_corr_angulo_flat, fborder_corr_flat[2], theta, true);
1660  }
1661  // dome PDs
1662  else if (opDet.type == 1 && fIsDomePDCorr) {
1663  pars_ini[0] = fGHvuvpars_dome[0][j];
1664  pars_ini[1] = fGHvuvpars_dome[1][j];
1665  pars_ini[2] = fGHvuvpars_dome[2][j];
1666  pars_ini[3] = fGHvuvpars_dome[3][j];
1667  s1 = interpolate( fborder_corr_angulo_dome, fborder_corr_dome[0], theta, true);
1668  s2 = interpolate( fborder_corr_angulo_dome, fborder_corr_dome[1], theta, true);
1669  s3 = interpolate( fborder_corr_angulo_dome, fborder_corr_dome[2], theta, true);
1670  }
1671  else std::cout << "Error: Invalid optical detector type. 0 = rectangular, 1 = dome, 2 = disk. Or corrections for chosen optical detector type missing." << std::endl;
1672 
1673  // add border correction
1674  pars_ini[0] = pars_ini[0] + s1 * r;
1675  pars_ini[1] = pars_ini[1] + s2 * r;
1676  pars_ini[2] = pars_ini[2] + s3 * r;
1677  pars_ini[3] = pars_ini[3];
1678 
1679  // calculate correction
1680  double GH_correction = Gaisser_Hillas(distance, pars_ini);
1681 
1682  // calculate number photons
1683  double hits_rec = GH_correction * hits_geo / cosine;
1684  int hits_vuv = std::round(G4Poisson(hits_rec));
1685 
1686  return hits_vuv;
1687  }
G4double Gaisser_Hillas(const double x, const double *par) const
std::vector< std::vector< double > > fGHvuvpars_flat
std::vector< std::vector< double > > fGHvuvpars_dome
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
std::vector< std::vector< double > > fborder_corr_dome
T abs(T value)
std::vector< std::vector< double > > fborder_corr_flat
std::vector< double > fborder_corr_angulo_flat
double distance(double x1, double y1, double z1, double x2, double y2, double z2)
double Rectangle_SolidAngle(const double a, const double b, const double d) const
constexpr double dist(const TReal *x, const TReal *y, const unsigned int dimension)
double Omega_Dome_Model(const double distance, const double theta) 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
float pi
Definition: units.py:11
QTextStream & endl(QTextStream &s)
double fast_acos(double x)

Member Data Documentation

bool const larg4::OpFastScintillation::bPropagate
private

Whether propagation of photons is enabled.

Definition at line 425 of file OpFastScintillation.hh.

G4EmSaturation* larg4::OpFastScintillation::emSaturation
private

Definition at line 338 of file OpFastScintillation.hh.

G4double larg4::OpFastScintillation::ExcitationRatio
protected

Definition at line 290 of file OpFastScintillation.hh.

std::vector<geo::BoxBoundedGeo> const larg4::OpFastScintillation::fActiveVolumes
private

Definition at line 409 of file OpFastScintillation.hh.

double larg4::OpFastScintillation::fangle_bin_timing_vis
private

Definition at line 360 of file OpFastScintillation.hh.

double larg4::OpFastScintillation::fangle_bin_timing_vuv
private

Definition at line 351 of file OpFastScintillation.hh.

std::vector<double> larg4::OpFastScintillation::fborder_corr_angulo_dome
private

Definition at line 390 of file OpFastScintillation.hh.

std::vector<double> larg4::OpFastScintillation::fborder_corr_angulo_flat
private

Definition at line 385 of file OpFastScintillation.hh.

std::vector<std::vector<double> > larg4::OpFastScintillation::fborder_corr_dome
private

Definition at line 391 of file OpFastScintillation.hh.

std::vector<std::vector<double> > larg4::OpFastScintillation::fborder_corr_flat
private

Definition at line 386 of file OpFastScintillation.hh.

TVector3 larg4::OpFastScintillation::fcathode_centre
private

Definition at line 408 of file OpFastScintillation.hh.

Dims larg4::OpFastScintillation::fcathode_plane
private

Definition at line 415 of file OpFastScintillation.hh.

double larg4::OpFastScintillation::fcathode_ydimension
private

Definition at line 407 of file OpFastScintillation.hh.

double larg4::OpFastScintillation::fcathode_zdimension
private

Definition at line 407 of file OpFastScintillation.hh.

std::vector<std::vector<std::vector<double> > > larg4::OpFastScintillation::fcut_off_pars
private

Definition at line 363 of file OpFastScintillation.hh.

double larg4::OpFastScintillation::fdelta_angulo_vis
private

Definition at line 396 of file OpFastScintillation.hh.

double larg4::OpFastScintillation::fdelta_angulo_vuv
private

Definition at line 381 of file OpFastScintillation.hh.

std::vector<double> larg4::OpFastScintillation::fdistances_refl
private

Definition at line 361 of file OpFastScintillation.hh.

G4bool larg4::OpFastScintillation::fFiniteRiseTime
protected

Definition at line 286 of file OpFastScintillation.hh.

std::vector<std::vector<double> > larg4::OpFastScintillation::fGHvuvpars_dome
private

Definition at line 389 of file OpFastScintillation.hh.

std::vector<std::vector<double> > larg4::OpFastScintillation::fGHvuvpars_flat
private

Definition at line 384 of file OpFastScintillation.hh.

double larg4::OpFastScintillation::finflexion_point_distance
private

Definition at line 351 of file OpFastScintillation.hh.

bool larg4::OpFastScintillation::fIsDomePDCorr
private

Definition at line 388 of file OpFastScintillation.hh.

bool larg4::OpFastScintillation::fIsFlatPDCorr
private

Definition at line 383 of file OpFastScintillation.hh.

int larg4::OpFastScintillation::fL_abs_vuv
private

Definition at line 416 of file OpFastScintillation.hh.

double larg4::OpFastScintillation::fmax_d
private

Definition at line 351 of file OpFastScintillation.hh.

double larg4::OpFastScintillation::fmin_d
private

Definition at line 351 of file OpFastScintillation.hh.

bool const larg4::OpFastScintillation::fOnlyActiveVolume = false
private

Whether photon propagation is performed only from active volumes.

Definition at line 433 of file OpFastScintillation.hh.

bool const larg4::OpFastScintillation::fOnlyOneCryostat = false
private

Allows running even if light on cryostats C:1 and higher is not supported. Currently hard coded "no"

Definition at line 436 of file OpFastScintillation.hh.

bool const larg4::OpFastScintillation::fOpaqueCathode = false
private

Whether the cathodes are fully opaque; currently hard coded "no".

Definition at line 438 of file OpFastScintillation.hh.

std::vector<geo::Point_t> larg4::OpFastScintillation::fOpDetCenter
private

Definition at line 417 of file OpFastScintillation.hh.

std::vector<double> larg4::OpFastScintillation::fOpDetHeight
private

Definition at line 420 of file OpFastScintillation.hh.

std::vector<double> larg4::OpFastScintillation::fOpDetLength
private

Definition at line 419 of file OpFastScintillation.hh.

std::vector<int> larg4::OpFastScintillation::fOpDetType
private

Definition at line 418 of file OpFastScintillation.hh.

std::vector<std::vector<double> > larg4::OpFastScintillation::fparameters[7]
private

Definition at line 352 of file OpFastScintillation.hh.

double larg4::OpFastScintillation::fplane_depth
private

Definition at line 407 of file OpFastScintillation.hh.

phot::PhotonVisibilityService const* const larg4::OpFastScintillation::fPVS
private

Photon visibility service instance.

Definition at line 428 of file OpFastScintillation.hh.

std::vector<double> larg4::OpFastScintillation::fradial_distances_refl
private

Definition at line 362 of file OpFastScintillation.hh.

double larg4::OpFastScintillation::fradius
private

Definition at line 414 of file OpFastScintillation.hh.

double larg4::OpFastScintillation::fstep_size
private

Definition at line 351 of file OpFastScintillation.hh.

bool larg4::OpFastScintillation::fStoreReflected
private

Definition at line 394 of file OpFastScintillation.hh.

std::vector<std::vector<std::vector<double> > > larg4::OpFastScintillation::ftau_pars
private

Definition at line 364 of file OpFastScintillation.hh.

std::unique_ptr<CLHEP::RandGeneral> larg4::OpFastScintillation::fTPBEm
private

Definition at line 334 of file OpFastScintillation.hh.

G4bool larg4::OpFastScintillation::fTrackSecondariesFirst
protected

Definition at line 285 of file OpFastScintillation.hh.

bool const larg4::OpFastScintillation::fUseNhitsModel = false
private

Whether the semi-analytic model is being used for photon visibility.

Definition at line 431 of file OpFastScintillation.hh.

std::vector<double> larg4::OpFastScintillation::fvis_distances_r_dome
private

Definition at line 403 of file OpFastScintillation.hh.

std::vector<double> larg4::OpFastScintillation::fvis_distances_r_flat
private

Definition at line 399 of file OpFastScintillation.hh.

std::vector<double> larg4::OpFastScintillation::fvis_distances_x_dome
private

Definition at line 402 of file OpFastScintillation.hh.

std::vector<double> larg4::OpFastScintillation::fvis_distances_x_flat
private

Definition at line 398 of file OpFastScintillation.hh.

double larg4::OpFastScintillation::fvis_vmean
private

Definition at line 360 of file OpFastScintillation.hh.

std::vector<std::vector<std::vector<double> > > larg4::OpFastScintillation::fvispars_dome
private

Definition at line 404 of file OpFastScintillation.hh.

std::vector<std::vector<std::vector<double> > > larg4::OpFastScintillation::fvispars_flat
private

Definition at line 400 of file OpFastScintillation.hh.

double larg4::OpFastScintillation::fvuv_vgroup_max
private

Definition at line 351 of file OpFastScintillation.hh.

double larg4::OpFastScintillation::fvuv_vgroup_mean
private

Definition at line 351 of file OpFastScintillation.hh.

phot::MappedFunctions_t larg4::OpFastScintillation::ParPropTimeTF1
private

Definition at line 340 of file OpFastScintillation.hh.

phot::MappedT0s_t larg4::OpFastScintillation::ReflT0s
private

Definition at line 341 of file OpFastScintillation.hh.

G4bool larg4::OpFastScintillation::scintillationByParticleType
protected

Definition at line 292 of file OpFastScintillation.hh.

std::unique_ptr<G4PhysicsTable> larg4::OpFastScintillation::theFastIntegralTable
protected

Definition at line 283 of file OpFastScintillation.hh.

std::unique_ptr<G4PhysicsTable> larg4::OpFastScintillation::theSlowIntegralTable
protected

Definition at line 282 of file OpFastScintillation.hh.

std::map<double, double> larg4::OpFastScintillation::tpbemission
private

Definition at line 333 of file OpFastScintillation.hh.

std::vector<std::vector<double> > larg4::OpFastScintillation::VUV_max
private

Definition at line 356 of file OpFastScintillation.hh.

std::vector<std::vector<double> > larg4::OpFastScintillation::VUV_min
private

Definition at line 357 of file OpFastScintillation.hh.

std::vector<std::vector<TF1> > larg4::OpFastScintillation::VUV_timing
private

Definition at line 354 of file OpFastScintillation.hh.

G4double larg4::OpFastScintillation::YieldFactor
protected

Definition at line 288 of file OpFastScintillation.hh.


The documentation for this class was generated from the following files: