All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
PhotonLibHypothesis.cxx
Go to the documentation of this file.
1 #ifndef PHOTONLIBHYPOTHESIS_CXX
2 #define PHOTONLIBHYPOTHESIS_CXX
3 
4 #include "PhotonLibHypothesis.h"
5 
6 #include <omp.h>
7 #define NUM_THREADS 4
8 
9 #ifndef USING_LARSOFT
10 #define USING_LARSOFT 1
11 #endif
12 
13 using namespace std::chrono;
14 namespace flashmatch {
15 
17 
18  PhotonLibHypothesis::PhotonLibHypothesis(const std::string name)
19  : BaseFlashHypothesis(name)
20  , _vis(art::ServiceHandle<phot::PhotonVisibilityService const>().get())
21  {}
22 
24  {
25  #if USING_LARSOFT == 0
26  omp_set_num_threads(NUM_THREADS);
27  #endif
28 
29  _global_qe = pset.get<double>("GlobalQE");
30  _global_qe_refl = pset.get<double>("GlobalQERefl", 0);
31  _use_semi_analytical = pset.get<bool>("UseSemiAnalytical", 0);
32 
33  _qe_v.clear();
34  _qe_v = pset.get<std::vector<double> >("CCVCorrection",_qe_v);
35  if(_qe_v.empty()) _qe_v.resize(DetectorSpecs::GetME().NOpDets(),1.0);
36  if(_qe_v.size() != DetectorSpecs::GetME().NOpDets()) {
37  FLASH_CRITICAL() << "CCVCorrection factor array has size " << _qe_v.size()
38  << " != number of opdet (" << DetectorSpecs::GetME().NOpDets() << ")!" << std::endl;
39  throw OpT0FinderException();
40  }
41 
42  // By default, add all opdets to the channel mask
43  // Note that this may be overridden by the manager
44  // via the SetChannelMask() method.
45  _channel_mask.clear();
47  for (size_t i = 0; i < DetectorSpecs::GetME().NOpDets(); i++) {
48  _channel_mask[i] = i;
49  }
50  }
51 
52  //
53  // LArSoft
54  //
55  #if USING_LARSOFT == 1
56 
57  void PhotonLibHypothesis::FillEstimate(const QCluster_t& trk, Flash_t &flash) const
58  {
59 
60  for ( auto& v : flash.pe_v ) v = 0;
61 
63  FillEstimateSemiAnalytical(trk, flash);
64  } else {
65  FillEstimateLibrary(trk, flash);
66  }
67  }
68 
69 
71  {
72 
73  for ( size_t ipt = 0; ipt < trk.size(); ++ipt) {
74 
75  /// Get the 3D point in space from where photons should be propagated
76  auto const& pt = trk[ipt];
77 
78  // Get the number of photons produced in such point
79  double n_original_photons = pt.q;
80 
81  geo::Point_t const xyz = {pt.x, pt.y, pt.z};
82 
83  std::vector<double> direct_visibilities;
84  _semi_model->detectedDirectVisibilities(direct_visibilities, xyz);
85 
86  std::vector<double> reflected_visibilities;
87  _semi_model->detectedReflectedVisibilities(reflected_visibilities, xyz);
88 
89  //
90  // Fill Estimate with Direct light
91  //
92  for (size_t op_det=0; op_det<direct_visibilities.size(); ++op_det) {
93 
94  const double visibility = direct_visibilities[op_det];
95 
96  double q = n_original_photons * visibility * _global_qe / _qe_v[op_det];
97 
98  // Coated PMTs don't see direct photons
99  if (std::find(_uncoated_pmt_list.begin(), _uncoated_pmt_list.end(), op_det) != _uncoated_pmt_list.end()) {
100  q = 0;
101  }
102 
103  // std::cout << "OpDet: " << op_det << " [x,y,z] -> [q] : [" << pt.x << ", " << pt.y << ", " << pt.z << "] -> [" << q << "]" << std::endl;
104 
105  if (std::find(_channel_mask.begin(), _channel_mask.end(), op_det) != _channel_mask.end()) {
106  flash.pe_v[op_det] += q;
107  } else {
108  flash.pe_v[op_det] = 0;
109  }
110  }
111 
112  //
113  // Fill Estimate with Reflected light
114  //
115  for (size_t op_det=0; op_det<reflected_visibilities.size(); ++op_det) {
116 
117  const double visibility = reflected_visibilities[op_det];
118 
119  double q = n_original_photons * visibility * _global_qe_refl / _qe_v[op_det];
120 
121  if (std::find(_channel_mask.begin(), _channel_mask.end(), op_det) != _channel_mask.end()) {
122  flash.pe_v[op_det] += q;
123  } else {
124  flash.pe_v[op_det] = 0;
125  }
126 
127  }
128 
129  }
130  }
131 
132 
133 
135  {
136 
137  static double xyz[3] = {0.};
138 
139  size_t n_pmt = DetectorSpecs::GetME().NOpDets();
140 
141  for ( size_t ipmt = 0; ipmt < n_pmt; ++ipmt) {
142 
143  if (std::find(_channel_mask.begin(), _channel_mask.end(), ipmt) == _channel_mask.end()) {
144  continue;
145  }
146 
147  bool is_uncoated = false;
148  if (std::find(_uncoated_pmt_list.begin(), _uncoated_pmt_list.end(), ipmt) != _uncoated_pmt_list.end()) {
149  is_uncoated = true;
150  }
151 
152  for (size_t ipt = 0; ipt < trk.size(); ++ipt) {
153  auto const& pt = trk[ipt];
154 
155  double q = pt.q;
156 
157  xyz[0] = pt.x;
158  xyz[1] = pt.y;
159  xyz[2] = pt.z;
160 
161  double q_direct = 0, q_refl = 0;
162 
163  // Direct light
164  if (is_uncoated) {
165  q_direct = 0;
166  } else {
167  q_direct = q * _vis->GetVisibility(xyz, ipmt) * _global_qe / _qe_v[ipmt];
168  }
169  // std::cout << "PMT : " << ipmt << " [x,y,z] -> [q] : [" << pt.x << ", " << pt.y << ", " << pt.z << "] -> [" << q << "]" << std::endl;
170 
171  // Reflected light
172  q_refl = q * _vis->GetVisibility(xyz, ipmt, true) * _global_qe_refl / _qe_v[ipmt];
173 
174  flash.pe_v[ipmt] += q_direct;
175  flash.pe_v[ipmt] += q_refl;
176  }
177  }
178  return;
179  }
180 
181 
182  //
183  // Standalone
184  //
185  #else
186 
187  void PhotonLibHypothesis::FillEstimate(const QCluster_t& trk, Flash_t &flash) const
188  {
189 
190  static double xyz[3] = {0.};
191 
192  size_t n_pmt = DetectorSpecs::GetME().NOpDets();
193 
194  for ( auto& v : flash.pe_v ) v = 0;
195 
196 
197  size_t n_pmt = DetectorSpecs::GetME().NOpDets();//n_pmt returns 0 now, needs to be fixed
198  if(flash.pe_v.empty()) flash.pe_v.resize(n_pmt);
199  if(flash.pe_err_v.empty()) flash.pe_err_v.resize(n_pmt);
200 
201  assert(flash.pe_v.size() == n_pmt);
202  assert(flash.pe_err_v.size() == n_pmt);
203 
204  for (auto& v : flash.pe_v ) v = 0;
205  for (auto& v : flash.pe_err_v ) v = 0;
206 
207  auto det = DetectorSpecs::GetME();
208 
209  auto const& lib_data = DetectorSpecs::GetME().GetPhotonLibraryData();
210 
211  //start = high_resolution_clock::now();
212  #pragma omp parallel
213  {
214  size_t thread_id = omp_get_thread_num();
215  size_t num_threads = omp_get_num_threads();
216  size_t num_pts = trk.size() / num_threads;
217  size_t start_pt = num_pts * thread_id;
218  if(thread_id+1 == num_threads) num_pts += (trk.size() % num_threads);
219 
220  auto const& vox_def = DetectorSpecs::GetME().GetVoxelDef();
221  // auto s = vox_def.GetVoxelSize();
222  // auto s1 = vox_def.GetRegionLowerCorner();
223  // auto s2 = vox_def.GetRegionUpperCorner();
224  // std::cout << s[0] << " " << s[1] << " " << s[2] << std::endl;
225  // std::cout << s1[0] << " " << s2[1] << " " << s1[2] << std::endl;
226  // std::cout << s2[0] << " " << s2[1] << " " << s2[2] << std::endl;
227  std::vector<double> local_pe_v(n_pmt,0);
228  int vox_id;
229  for( size_t ipt = start_pt; ipt < start_pt + num_pts; ++ipt) {
230  auto const& pt = trk[ipt];
231  vox_id = vox_def.GetVoxelID(pt.x,pt.y,pt.z);
232  if (vox_id < 0) continue;
233  auto const& vis_pmt = lib_data[vox_id];
234  for ( size_t ipmt = 0; ipmt < n_pmt; ++ipmt) {
235  local_pe_v[ipmt] += pt.q * vis_pmt[ipmt];
236  }
237  }
238  #pragma omp critical
239  for(size_t ipmt = 0; ipmt < n_pmt; ++ipmt) {
240  flash.pe_v[ipmt] += local_pe_v[ipmt] * _global_qe / _qe_v[ipmt];
241  }
242 
243  }
244  return;
245 
246 
247  }
248 
249  void PhotonLibHypothesis::FillEstimateSemiAnalytical(const QCluster_t& trk, Flash_t &flash) const
250  {}
251 
252  void PhotonLibHypothesis::FillEstimateLibrary(const QCluster_t& trk, Flash_t &flash) const
253  {}
254 
255  #endif
256 
257 }
258 #endif
double _global_qe
Global QE for direct light.
void FillEstimateLibrary(const QCluster_t &, Flash_t &) const
Fills the estimate using the photon library (ICARUS, SBND)
#define NUM_THREADS
Class def header for a class PhotonLibHypothesis.
double _global_qe_refl
Global QE for reflected light.
size_t NOpDets() const
of PMTs
Definition: FMWKInterface.h:60
const std::vector< std::vector< float > > & GetPhotonLibraryData() const
Photon Library data access FIXME.
static PhotonLibHypothesisFactory __global_PhotonLibHypothesisFactory__
fhicl::ParameterSet Config_t
Configuration object.
Definition: FMWKInterface.h:31
static DetectorSpecs & GetME(std::string filename="detector_specs.cfg")
Definition: FMWKInterface.h:44
Struct to represent an optical flash.
std::vector< double > pe_v
PE distribution over photo-detectors.
#define FLASH_CRITICAL()
Compiler macro for CRITICAL message.
Collection of charge deposition 3D point (cluster)
void FillEstimateSemiAnalytical(const QCluster_t &, Flash_t &) const
Fills the estimate using the semi analytical approach (SBND)
std::vector< int > _uncoated_pmt_list
A list of opdet sensitive to visible (reflected) light.
void FillEstimate(const QCluster_t &, Flash_t &) const
Method to simply fill provided reference of flashmatch::Flash_t.
bool _use_semi_analytical
If the semi-analytical approach should be used.
std::vector< double > _qe_v
PMT-wise relative QE.
void _Configure_(const Config_t &pset)
phot::PhotonVisibilityService const *const _vis
then echo fcl name
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 > pe_err_v
PE value error.
float GetVisibility(Point const &p, unsigned int OpChannel, bool wantReflected=false) const
std::unique_ptr< SemiAnalyticalModel > _semi_model
std::vector< int > _channel_mask
The list of channels to use.