58 #include "cetlib_except/exception.h" 68 #include "CLHEP/Random/RandPoissonQ.h" 87 Comment(
"SimEnergyDeposit label.")};
89 Comment(
"Simulate slow scintillation light, default true"),
92 Comment(
"Simulate slow scintillation light")};
94 Comment(
"Simulate reflected visible light")};
96 Name(
"IncludeAnodeReflections"),
97 Comment(
"Simulate anode reflections, default false"),
100 Comment(
"Simulate light propagation time")};
102 Name(
"GeoPropTimeOnly"),
103 Comment(
"Simulate light propagation time geometric approximation, default false"),
106 Name(
"UseLitePhotons"),
107 Comment(
"Store SimPhotonsLite/OpDetBTRs instead of SimPhotons")};
109 Comment(
"Photons cannot cross the cathode")};
111 Name(
"OnlyActiveVolume"),
112 Comment(
"PAR fast sim usually only for active volume, default true"),
115 Comment(
"Set to true if light is only supported in C:1")};
117 Comment(
"Tool describing scintillation time structure")};
119 Name(
"UseXeAbsorption"),
120 Comment(
"Use Xe absorption length instead of Ar, default false"),
124 Comment(
"Configuration for visible timing parameterization")};
127 Comment(
"Configuration for visibile visibility parameterization")};
136 const std::vector<double>& OpDetVisibilities,
137 const int NumPhotons)
const;
139 void AddOpDetBTR(std::vector<sim::OpDetBacktrackerRecord>& opbtr,
140 std::vector<int>& ChannelMap,
198 ,
fGeom(*(lar::providerFrom<geo::Geometry>()))
204 ,
fSimTag(config().SimulationLabel())
217 mf::LogInfo(
"PDFastSimPAR") <<
"Initializing PDFastSimPAR." << std::endl;
229 <<
"Propagation time simulation requested, but VUVTiming not specified." 235 <<
"Reflected light or anode reflections simulation requested, but VisHits not specified." 241 <<
"Reflected light propagation time simulation requested, but VISTiming not specified." 248 <<
" cryostats is configured" 249 <<
" , and semi-analytic model is requested for scintillation photon propagation." 250 <<
" THIS CONFIGURATION IS NOT SUPPORTED and it is open to bugs" 251 <<
" (e.g. scintillation may be detected only in cryostat #0)." 252 <<
"\nThis would be normally a fatal error, but it has been forcibly overridden." 254 << std::string(80,
'=');
258 <<
"Photon propagation via semi-analytic model is not supported yet" 259 <<
" on detectors with more than one cryostat.";
276 auto log =
mf::LogTrace(
"PDFastSimPAR") <<
"PDFastSimPAR: active volume boundaries from " 279 log <<
"\n - C:" << iCryo <<
": " << box.Min() <<
" -- " << box.Max() <<
" cm";
284 mf::LogInfo(
"PDFastSimPAR") <<
"Using Lite Photons";
285 produces<std::vector<sim::SimPhotonsLite>>();
286 produces<std::vector<sim::OpDetBacktrackerRecord>>();
287 if (fDoReflectedLight) {
288 mf::LogInfo(
"PDFastSimPAR") <<
"Storing Reflected Photons";
289 produces<std::vector<sim::SimPhotonsLite>>(
"Reflected");
290 produces<std::vector<sim::OpDetBacktrackerRecord>>(
"Reflected");
294 mf::LogInfo(
"PDFastSimPAR") <<
"Using Sim Photons";
295 produces<std::vector<sim::SimPhotons>>();
296 if (fDoReflectedLight) {
297 mf::LogInfo(
"PDFastSimPAR") <<
"Storing Reflected Photons";
298 produces<std::vector<sim::SimPhotons>>(
"Reflected");
301 mf::LogInfo(
"PDFastSimPAR") <<
"PDFastSimPAR Initialization finish.\n" 302 <<
"Simulate using semi-analytic model for number of hits." 309 mf::LogTrace(
"PDFastSimPAR") <<
"PDFastSimPAR Module Producer" 310 <<
"EventID: " <<
event.event();
312 std::vector<int> PDChannelToSOCMapDirect(
fNOpChannels, -1);
313 std::vector<int> PDChannelToSOCMapReflect(
fNOpChannels, -1);
316 auto phlit = std::make_unique<std::vector<sim::SimPhotonsLite>>();
317 auto opbtr = std::make_unique<std::vector<sim::OpDetBacktrackerRecord>>();
318 auto phlit_ref = std::make_unique<std::vector<sim::SimPhotonsLite>>();
319 auto opbtr_ref = std::make_unique<std::vector<sim::OpDetBacktrackerRecord>>();
320 auto& dir_phlitcol(*phlit);
321 auto& ref_phlitcol(*phlit_ref);
323 auto phot = std::make_unique<std::vector<sim::SimPhotons>>();
324 auto phot_ref = std::make_unique<std::vector<sim::SimPhotons>>();
325 auto& dir_photcol(*
phot);
326 auto& ref_photcol(*phot_ref);
331 dir_phlitcol[i].OpChannel = i;
332 ref_phlitcol[i].OpChannel = i;
339 dir_photcol[i].fOpChannel = i;
340 ref_photcol[i].fOpChannel = i;
350 auto const& edeps = edepHandle;
358 for (
auto const& edepi : *edeps) {
361 int nphot_fast = edepi.NumFPhotons();
362 int nphot_slow = edepi.NumSPhotons();
364 num_fastph += nphot_fast;
365 num_slowph += nphot_slow;
369 int trackID = edepi.TrackID();
370 int nphot = edepi.NumPhotons();
371 double edeposit = edepi.Energy() / nphot;
372 double pos[3] = {edepi.MidPointX(), edepi.MidPointY(), edepi.MidPointZ()};
373 geo::Point_t const ScintPoint = {pos[0], pos[1], pos[2]};
381 std::vector<double> OpDetVisibilities;
382 fVisibilityModel->detectedDirectVisibilities(OpDetVisibilities, ScintPoint);
390 std::vector<double> OpDetVisibilitiesAnode;
391 fVisibilityModel->detectedReflectedVisibilities(OpDetVisibilitiesAnode, ScintPoint,
true);
396 for (
size_t i = 0; i < AnodeDetectedNumFast.size(); ++i) {
397 DetectedNumFast[i] += AnodeDetectedNumFast[i];
399 for (
size_t i = 0; i < AnodeDetectedNumSlow.size(); ++i) {
400 DetectedNumSlow[i] += AnodeDetectedNumSlow[i];
408 std::vector<double> OpDetVisibilitiesRefl;
409 fVisibilityModel->detectedReflectedVisibilities(OpDetVisibilitiesRefl, ScintPoint,
false);
416 for (
size_t Reflected = 0; Reflected <= DoReflected; ++Reflected) {
417 for (
size_t channel = 0; channel <
fNOpChannels; channel++) {
421 int ndetected_fast = DetectedNumFast[channel];
422 int ndetected_slow = DetectedNumSlow[channel];
424 ndetected_fast = ReflDetectedNumFast[channel];
425 ndetected_slow = ReflDetectedNumSlow[channel];
432 std::vector<double> transport_time;
434 transport_time.resize(ndetected_fast + ndetected_slow);
435 fPropTimeModel->propagationTime(transport_time, ScintPoint, channel, Reflected);
442 int n = ndetected_fast;
444 for (
int i = 0; i <
n; ++i) {
446 double dtime = edepi.StartT() +
fScintTime->fastScintTime();
448 int time =
static_cast<int>(std::round(dtime));
450 ++ref_phlitcol[channel].DetectedPhotons[time];
452 ++dir_phlitcol[channel].DetectedPhotons[time];
457 int n = ndetected_slow;
459 for (
int i = 0; i <
n; ++i) {
460 double dtime = edepi.StartT() +
fScintTime->slowScintTime();
462 int time =
static_cast<int>(std::round(dtime));
464 ++ref_phlitcol[channel].DetectedPhotons[time];
466 ++dir_phlitcol[channel].DetectedPhotons[time];
471 AddOpDetBTR(*opbtr_ref, PDChannelToSOCMapReflect, tmpbtr);
473 AddOpDetBTR(*opbtr, PDChannelToSOCMapDirect, tmpbtr);
482 photon.
Energy = 2.9 * CLHEP::eV;
484 photon.
Energy = 9.7 * CLHEP::eV;
487 int n = ndetected_fast;
489 for (
int i = 0; i <
n; ++i) {
491 double dtime = edepi.StartT() +
fScintTime->fastScintTime();
493 int time =
static_cast<int>(std::round(dtime));
496 ref_photcol[channel].insert(ref_photcol[channel].
end(), 1, photon);
498 dir_photcol[channel].insert(dir_photcol[channel].
end(), 1, photon);
502 int n = ndetected_slow;
504 for (
int i = 0; i <
n; ++i) {
505 double dtime = edepi.StartT() +
fScintTime->slowScintTime();
507 int time =
static_cast<int>(std::round(dtime));
510 ref_photcol[channel].insert(ref_photcol[channel].
end(), 1, photon);
512 dir_photcol[channel].insert(dir_photcol[channel].
end(), 1, photon);
520 mf::LogTrace(
"PDFastSimPAR") <<
"Total points: " << num_points
521 <<
", total fast photons: " << num_fastph
522 <<
", total slow photons: " << num_slowph
523 <<
"\ndetected fast photons: " << num_fastdp
524 <<
", detected slow photons: " << num_slowdp;
527 event.put(move(phlit));
528 event.put(move(opbtr));
530 event.put(move(phlit_ref),
"Reflected");
531 event.put(move(opbtr_ref),
"Reflected");
535 event.put(move(
phot));
544 std::vector<int>& ChannelMap,
548 if (ChannelMap[iChan] < 0) {
549 ChannelMap[iChan] = opbtr.size();
550 opbtr.emplace_back(std::move(btr));
553 size_t idtest = ChannelMap[iChan];
555 for (
auto const& timePDclockSDP : timePDclockSDPsMap) {
556 for (
auto const& sdp : timePDclockSDP.second) {
557 double xyz[3] = {sdp.x, sdp.y, sdp.z};
558 opbtr.at(idtest).AddScintillationPhotons(
559 sdp.trackID, timePDclockSDP.first, sdp.numPhotons, xyz, sdp.energy);
568 const std::vector<double>& OpDetVisibilities,
569 const int NumPhotons)
const 571 for (
size_t i = 0; i < OpDetVisibilities.size(); ++i) {
572 DetectedNumPhotons[i] =
fRandPoissPhot->fire(OpDetVisibilities[i] * NumPhotons);
584 if (((ScintPoint.X() < 0.) != (OpDetPoint.X() < 0.)) &&
std::abs(OpDetPoint.X()) > 10. &&
593 std::vector<geo::Point_t> opDetCenter;
596 opDetCenter.push_back(opDet.
GetCenter());
const bool fGeoPropTimeOnly
const std::vector< geo::BoxBoundedGeo > fActiveVolumes
base_engine_t & createEngine(seed_t seed)
bool isOpDetInSameTPC(geo::Point_t const &ScintPoint, geo::Point_t const &OpDetPoint) const
unsigned int NTPC(CryostatID const &cryoid=cryostat_zero) const
Returns the total number of TPCs in the specified cryostat.
const size_t fNOpChannels
void AddOpDetBTR(std::vector< sim::OpDetBacktrackerRecord > &opbtr, std::vector< int > &ChannelMap, const sim::OpDetBacktrackerRecord &btr) const
OpDetGeo const & OpDetGeoFromOpDet(unsigned int OpDet) const
Returns the geo::OpDetGeo object for the given detector number.
static std::vector< geo::BoxBoundedGeo > extractActiveLArVolume(geo::GeometryCore const &geom)
Utilities related to art service access.
Definition of util::enumerate().
MaybeLogger_< ELseverityLevel::ELsev_info, false > LogInfo
const bool fUseLitePhotons
std::unique_ptr< PropagationTimeModel > fPropTimeModel
fhicl::Atom< bool > DoSlowComponent
EDProducer(fhicl::ParameterSet const &pset)
PDFastSimPAR(Parameters const &config)
All information of a photon entering the sensitive optical detector volume.
fhicl::Atom< bool > DoReflectedLight
constexpr auto abs(T v)
Returns the absolute value of the argument.
std::unique_ptr< ScintTime > fScintTime
const bool fOnlyActiveVolume
MaybeLogger_< ELseverityLevel::ELsev_error, false > LogError
const bool fIncludePropTime
unsigned int Ncryostats() const
Returns the number of cryostats in the detector.
const bool fUseXeAbsorption
const bool fOpaqueCathode
Energy deposited on a readout Optical Detector by simulated tracks.
geo::Point_t InitialPosition
Scintillation position in world coordinates [cm].
auto enumerate(Iterables &&...iterables)
Range-for loop helper tracking the number of iteration.
const bool fDoReflectedLight
fhicl::Atom< bool > UseLitePhotons
decltype(auto) constexpr end(T &&obj)
ADL-aware version of std::end.
std::unique_ptr< CLHEP::RandPoissonQ > fRandPoissPhot
CLHEP::HepRandomEngine & fScintTimeEngine
Simulation objects for optical detectors.
int OpDetNum() const
Returns the readout Optical Detector this object describes.
auto counter(T begin, T end)
Returns an object to iterate values from begin to end in a range-for loop.
const bool fDoFastComponent
#define DEFINE_ART_MODULE(klass)
const std::vector< geo::Point_t > fOpDetCenter
Definitions of geometry vector data types.
std::unique_ptr< SemiAnalyticalModel > fVisibilityModel
fhicl::Atom< bool > OpaqueCathode
T get(std::string const &key) const
fhicl::Atom< bool > IncludeAnodeReflections
void produce(art::Event &) override
Test of util::counter and support utilities.
Description of geometry of one entire detector.
const art::InputTag fSimTag
const bool fDoSlowComponent
An art service to assist in the distribution of guaranteed unique seeds to all engines within an art ...
unsigned int NOpDets() const
Number of OpDets in the whole detector.
Provides a base class aware of world box coordinates.
void AddScintillationPhotons(TrackID_t trackID, timePDclock_t timePDclock, double numberPhotons, double const *xyz, double energy)
Add scintillation photons and energy to this OpticalDetector.
Encapsulate the geometry of an optical detector.
geo::Point_t const & GetCenter() const
cet::coded_exception< errors::ErrorCodes, ExceptionDetail::translate > Exception
ROOT::Math::PositionVector3D< ROOT::Math::Cartesian3D< double >, ROOT::Math::GlobalCoordinateSystemTag > Point_t
Type for representation of position in physical 3D space.
fhicl::Atom< bool > UseXeAbsorption
General LArSoft Utilities.
fhicl::Atom< bool > GeoPropTimeOnly
CLHEP::HepRandomEngine & fPhotonEngine
bool getByLabel(std::string const &label, std::string const &instance, Handle< PROD > &result) const
std::vector< geo::Point_t > opDetCenters() const
bool SetInSD
Whether the photon reaches the sensitive detector.
contains information for a single step in the detector simulation
void detectedNumPhotons(std::vector< int > &DetectedNumPhotons, const std::vector< double > &OpDetVisibilities, const int NumPhotons) const
MaybeLogger_< ELseverityLevel::ELsev_warning, false > LogWarning
fhicl::Atom< art::InputTag > SimulationLabel
MaybeLogger_< ELseverityLevel::ELsev_success, true > LogTrace
fhicl::Atom< bool > IncludePropTime
float Energy
Scintillation photon energy [GeV].
fhicl::Atom< bool > OnlyActiveVolume
bool isScintInActiveVolume(geo::Point_t const &ScintPoint)
const bool fIncludeAnodeReflections
timePDclockSDPs_t const & timePDclockSDPsMap() const
Returns all the deposited energy information as stored.
fhicl::Atom< bool > OnlyOneCryostat
art framework interface to geometry description
geo::GeometryCore const & fGeom
fhicl::Atom< bool > DoFastComponent
Event finding and building.
int MotherTrackID
ID of the GEANT4 track causing the scintillation.
const bool fOnlyOneCryostat