ProtoDUNEOpDetResponse_service.cc
Go to the documentation of this file.
1 // -*- mode: c++; c-basic-offset: 4; -*-
2 ////////////////////////////////////////////////////////////////////////
3 //
4 // \file ProtoDUNEOpDetResponse_service.cc
5 //
6 ////////////////////////////////////////////////////////////////////////
7 
8 
11 #include "TGeoNode.h"
12 #include "TGeoBBox.h"
16 #include "CLHEP/Random/RandFlat.h"
17 #include <boost/algorithm/string.hpp>
18 
19 namespace opdet{
20 
21 
22  //--------------------------------------------------------------------
24  art::ActivityRegistry &/*reg*/)
25  {
26  this->doReconfigure(pset);
27  }
28 
29  //--------------------------------------------------------------------
31  { }
32 
33 
34  //--------------------------------------------------------------------
36  {
37  double tempfQE = pset.get<double>("QuantumEfficiency");
38  double tempfQEAraBeam = pset.get<double>("QuantumEfficiencyArapucaBeam");
39  double tempfQEAraNonBeam = pset.get<double>("QuantumEfficiencyArapucaNonBeam");
40  fWavelengthCutLow = pset.get<double>("WavelengthCutLow");
41  fWavelengthCutHigh = pset.get<double>("WavelengthCutHigh");
42  fLightGuideAttenuation = pset.get<bool>("LightGuideAttenuation");
43  lambdaShort = pset.get<double>("LambdaShort");
44  lambdaLong = pset.get<double>("LambdaLong");
45  fracShort = pset.get<double>("FracShort");
46  fracLong = pset.get<double>("FracLong");
47  fChannelConversion = pset.get<std::string>("ChannelConversion");
48  std::string tmpAxis = pset.get<std::string>("LongAxis");
49 
50  boost::algorithm::to_lower(tmpAxis);
51 
52  if (tmpAxis == "x") fLongAxis = 0;
53  if (tmpAxis == "y") fLongAxis = 1;
54  if (tmpAxis == "z") fLongAxis = 2;
55 
56  // Only allow channel conversion once - so it must be set to happen
57  // either during full simulation (library generation) or during
58  // fast simulation (library use).
59 
60  boost::algorithm::to_lower(fChannelConversion);
61 
62  fFullSimChannelConvert = false;
63  fFastSimChannelConvert = false;
64 
65  if (fChannelConversion == "full") fFullSimChannelConvert = true;
66  if (fChannelConversion == "fast") fFastSimChannelConvert = true;
67 
68  // Correct out the prescaling applied during simulation
69  auto const *LarProp = lar::providerFrom<detinfo::LArPropertiesService>();
70  fQE = tempfQE / LarProp->ScintPreScale();
71  fQEArapucaBeam = tempfQEAraBeam / LarProp->ScintPreScale();
72  fQEArapucaNonBeam = tempfQEAraNonBeam / LarProp->ScintPreScale();
73 
74  if (fQE > 1.0001 || fQEArapucaBeam > 1.0001 || fQEArapucaNonBeam > 1.0001) {
75  mf::LogError("ProtoDUNEOpDetResponse_service") << "Quantum efficiency set in OpDetResponse_service, " << tempfQE << ", "
76  << tempfQEAraBeam << ", or " << tempfQEAraNonBeam
77  << " is too large. It is larger than the prescaling applied during simulation, "
78  << LarProp->ScintPreScale()
79  << ". Final QE must be equalt to or smaller than the QE applied at simulation time.";
80  std::abort();
81  }
82 
83  }
84 
85 
86  //--------------------------------------------------------------------
88  {
91  return geom->NOpChannels();
92  else
93  return geom->NOpDets();
94 
95  }
96 
97 
98  //--------------------------------------------------------------------
99  bool ProtoDUNEOpDetResponse::doDetected(int OpDet, const sim::OnePhoton& Phot, int &newOpChannel) const
100  {
101 
102  // Find the Optical Detector using the geometry service
104 
106  // Override default number of channels for Fiber and Plank
107  float NOpHardwareChannels = geom->NOpHardwareChannels(OpDet);
108  int hardwareChannel = (int) ( CLHEP::RandFlat::shoot(1.0) * NOpHardwareChannels );
109  newOpChannel = geom->OpChannel(OpDet, hardwareChannel);
110  }else{
111  newOpChannel = OpDet;
112  }
113 
114  // Get the length of the photon detector
115  const TGeoNode* node = geom->OpDetGeoFromOpDet(OpDet).Node();
116  TGeoBBox *box = (TGeoBBox*)node->GetVolume()->GetShape();
117  double opdetLength = 0;
118  double sipmDistance = 0;
119  if (fLongAxis == 0) {
120  opdetLength = box->GetDX();
121  sipmDistance = opdetLength - Phot.FinalLocalPosition.x();
122  }
123  else if (fLongAxis == 1) {
124  opdetLength = box->GetDY();
125  sipmDistance = opdetLength - Phot.FinalLocalPosition.y();
126  }
127  else if (fLongAxis == 2) {
128  opdetLength = box->GetDZ();
129  sipmDistance = opdetLength - Phot.FinalLocalPosition.z();
130  }
131  else {
132  mf::LogError("ProtoDUNEOpDetResponse") << "Unknown axis, fLongAxis = " << fLongAxis;
133  std::abort();
134  }
135 
136  if(opdetLength > 50){ //i.e. if this is a paddle (this is half length in units of cm)
137  // Check QE
138  if ( CLHEP::RandFlat::shoot(1.0) > fQE ) return false;
139 
140  double wavel = wavelength(Phot.Energy);
141  // Check wavelength acceptance
142  if (wavel < fWavelengthCutLow) return false;
143  if (wavel > fWavelengthCutHigh) return false;
144 
146  // Throw away some photons based on attenuation
147  double AttenuationProb = fracShort*exp(-sipmDistance/lambdaShort) + fracLong*exp(-sipmDistance/lambdaLong);
148 
149  if ( CLHEP::RandFlat::shoot(1.0) > AttenuationProb ) return false;
150  }
151  }else{ //if it is Arapuca
152  if(Phot.FinalLocalPosition.x()<0){ //beam side
153  // Check QE
154  if ( CLHEP::RandFlat::shoot(1.0) > fQEArapucaBeam ) return false;
155  }else{ //non-beam side
156  // Check QE
157  if ( CLHEP::RandFlat::shoot(1.0) > fQEArapucaNonBeam ) return false;
158  }
159  }
160  return true;
161  }
162 
163  //--------------------------------------------------------------------
164  bool ProtoDUNEOpDetResponse::doDetectedLite(int OpDet, int &newOpChannel) const
165  {
166  // Find the Optical Detector using the geometry service
168 
170  // Here OpDet must be opdet since we are introducing
171  // channel mapping here.
172  float NOpHardwareChannels = geom->NOpHardwareChannels(OpDet);
173  int hardwareChannel = (int) ( CLHEP::RandFlat::shoot(1.0) * NOpHardwareChannels );
174  newOpChannel = geom->OpChannel(OpDet, hardwareChannel);
175  }else{
176  newOpChannel = OpDet;
177  }
178 
179  double opdetLength = 0;
180  const TGeoNode* node = geom->OpDetGeoFromOpDet(OpDet).Node();
181  TGeoBBox *box = (TGeoBBox*)node->GetVolume()->GetShape();
182  opdetLength = box->GetDX();
183  if(opdetLength > 50){ //i.e. if this is a paddle (this is half length in units of cm)
184  // Check QE
185  if ( CLHEP::RandFlat::shoot(1.0) > fQE ) return false;
186  }else{ //if it is Arapuca
187  double xyz[3];
188  geom->OpDetGeoFromOpChannel(OpDet).GetCenter(xyz);
189  if(xyz[0]<0){ //beam side
190  // Check QE
191  if ( CLHEP::RandFlat::shoot(1.0) > fQEArapucaBeam ) return false;
192  }else{ //non-beam side
193  // Check QE
194  if ( CLHEP::RandFlat::shoot(1.0) > fQEArapucaNonBeam ) return false;
195  }
196  }
197 
198  return true;
199  }
200 
201  //--------------------------------------------------------------------
202  bool ProtoDUNEOpDetResponse::doDetectedLiteWithChannel(int OpDet, int &newOpChannel, int &hardwareChannel) const
203  {
204  // Find the Optical Detector using the geometry service
206 
208  // Here OpDet must be opdet since we are introducing
209  // channel mapping here.
210  float NOpHardwareChannels = geom->NOpHardwareChannels(OpDet);
211  hardwareChannel = (int) ( CLHEP::RandFlat::shoot(1.0) * NOpHardwareChannels );
212  newOpChannel = geom->OpChannel(OpDet, hardwareChannel);
213  }else{
214  newOpChannel = OpDet;
215  }
216 
217  double opdetLength = 0;
218  const TGeoNode* node = geom->OpDetGeoFromOpDet(OpDet).Node();
219  TGeoBBox *box = (TGeoBBox*)node->GetVolume()->GetShape();
220  opdetLength = box->GetDX();
221  if(opdetLength > 50){ //i.e. if this is a paddle
222  // Check QE
223  if ( CLHEP::RandFlat::shoot(1.0) > fQE ) return false;
224  }else{ //if it is Arapuca
225  double xyz[3];
226  geom->OpDetGeoFromOpChannel(OpDet).GetCenter(xyz);
227  if(xyz[0]<0){ //beam side
228  // Check QE
229  if ( CLHEP::RandFlat::shoot(1.0) > fQEArapucaBeam ) return false;
230  }else{ //non-beam side
231  // Check QE
232  if ( CLHEP::RandFlat::shoot(1.0) > fQEArapucaNonBeam ) return false;
233  }
234  }
235 
236  return true;
237  }
238 
239 
240 } // namespace
241 
243 
const TGeoNode * Node() const
Returns the ROOT object describing the detector geometry.
Definition: OpDetGeo.h:146
OpDetGeo const & OpDetGeoFromOpDet(unsigned int OpDet) const
Returns the geo::OpDetGeo object for the given detector number.
std::string string
Definition: nybbler.cc:12
All information of a photon entering the sensitive optical detector volume.
Definition: SimPhotons.h:64
virtual void doReconfigure(fhicl::ParameterSet const &p)
unsigned int NOpHardwareChannels(int opDet) const
void GetCenter(double *xyz, double localz=0.0) const
Definition: OpDetGeo.cxx:40
MaybeLogger_< ELseverityLevel::ELsev_error, false > LogError
ProtoDUNEOpDetResponse(fhicl::ParameterSet const &pset, art::ActivityRegistry &reg)
unsigned int NOpChannels() const
Number of electronics channels for all the optical detectors.
virtual bool doDetected(int OpDet, const sim::OnePhoton &Phot, int &newOpChannel) const
T get(std::string const &key) const
Definition: ParameterSet.h:271
unsigned int NOpDets() const
Number of OpDets in the whole detector.
unsigned int OpChannel(int detNum, int hardwareChannel) const
Convert detector number and hardware channel to unique channel.
Encapsulate the geometry of an optical detector.
Index NOpHardwareChannels(Index opDet)
geo::OpticalPoint_t FinalLocalPosition
Where photon enters the optical detector in local coordinates [cm].
Definition: SimPhotons.h:75
virtual bool doDetectedLite(int OpDet, int &newOpChannel) const
bool doDetectedLiteWithChannel(int OpDet, int &newOpChannel, int &hardwareChannel) const
float Energy
Scintillation photon energy [GeV].
Definition: SimPhotons.h:82
virtual float wavelength(double energy) const
OpDetGeo const & OpDetGeoFromOpChannel(unsigned int OpChannel) const
Returns the geo::OpDetGeo object for the given channel number.
#define DEFINE_ART_SERVICE_INTERFACE_IMPL(svc, iface)