All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
MixedWeightRayTraceBox_tool.cc
Go to the documentation of this file.
1 /**
2  *
3  */
4 
5 // Framework Includes
6 #include "art/Framework/Principal/Event.h"
7 #include "art/Framework/Principal/Handle.h"
8 #include "art/Framework/Services/Registry/ServiceHandle.h"
9 #include "art/Persistency/Common/PtrMaker.h"
10 #include "art/Utilities/ToolMacros.h"
11 #include "cetlib/cpu_timer.h"
12 #include "fhiclcpp/ParameterSet.h"
13 #include "messagefacility/MessageLogger/MessageLogger.h"
14 
15 // local includes
16 #include "IRayTrace.h"
19 
20 // LArSoft includes
25 
26 // std includes
27 #include <string>
28 #include <iostream>
29 #include <memory>
30 
31 //------------------------------------------------------------------------------------------------------------------------------------------
32 // implementation follows
33 
34 namespace evgen {
35 namespace ldm {
36 
37 
38 // Helper struct retruned by some internal functions
39 struct RayWeightInfo {
40  std::vector<std::vector<TVector3>> allIntersections;
41  std::vector<TLorentzVector> allPrtlMom;
42  double weight;
43  bool pass;
44 };
45 
46 /**
47  * @brief MixedWeightRayTraceBox class definiton
48  */
50 {
51 public:
52  /**
53  * @brief Constructor
54  */
55  MixedWeightRayTraceBox(fhicl::ParameterSet const &pset);
56 
57  /**
58  * @brief Destructor
59  */
61 
62  void configure(const fhicl::ParameterSet&) override;
63 
64  bool IntersectDetector(MeVPrtlFlux &flux, std::array<TVector3, 2> &intersection, double &weight) override;
65 
66  // always thrown at least once
67  double MaxWeight() override {
68  return fMaxWeight;
69  }
70 
71 private:
78 
79  unsigned fNThrow;
80  unsigned fNSuccess;
82 
83  double fMaxWeight;
84 
85  void CalculateMaxWeight();
86  std::pair<double, double> DeltaPhi(TVector3 origin, TRotation &R);
87  TLorentzVector ThrowMeVPrtlMomentum(const MeVPrtlFlux &flux, TRotation &RInv, double phi);
88  RayWeightInfo ThrowFixedSuccess(const MeVPrtlFlux &flux, TRotation &RInv, double phi);
89  RayWeightInfo ThrowFixedThrows(const MeVPrtlFlux &flux, TRotation &RInv, double phi);
90 
91 };
92 
93 // Helpers
94 //
95 // Minimum Variance Unbiased Estimator for the Negative Binomial Distribution
96 double QEstimator(unsigned nsuccess, unsigned nfail, unsigned r) {
97  if (nsuccess < r) return 0.;
98 
99  return ((double)(r - 1) / (r+nfail-1));
100 }
101 
102 MixedWeightRayTraceBox::MixedWeightRayTraceBox(fhicl::ParameterSet const &pset):
103  IMeVPrtlStage("MixedWeightRayTraceBox")
104 {
105  this->configure(pset);
106 }
107 
108 //------------------------------------------------------------------------------------------------------------------------------------------
109 
111 {
112 }
113 
114 //------------------------------------------------------------------------------------------------------------------------------------------
115 void MixedWeightRayTraceBox::configure(fhicl::ParameterSet const &pset)
116 {
117  if (pset.has_key("Box")) {
118  std::array<double, 6> box_config = pset.get<std::array<double, 6>>("Box");
119  // xmin, xmax, ymin, ymax, zmin, zmax
120  fBox = geo::BoxBoundedGeo(box_config[0], box_config[1], box_config[2], box_config[3], box_config[4], box_config[5]);
121  }
122  else {
123  const geo::GeometryCore *geometry = lar::providerFrom<geo::Geometry>();
124  fBox = geometry->DetectorEnclosureBox(pset.get<std::string>("Volume"));
125  }
126 
127  std::cout << "Detector Box." << std::endl;
128  std::cout << "X " << fBox.MinX() << " " << fBox.MaxX() << std::endl;
129  std::cout << "Y " << fBox.MinY() << " " << fBox.MaxY() << std::endl;
130  std::cout << "Z " << fBox.MinZ() << " " << fBox.MaxZ() << std::endl;
131 
132  fReferenceLabSolidAngle = pset.get<double>("ReferenceLabSolidAngle");
133  fReferencePrtlMass = pset.get<double>("ReferencePrtlMass");
134  fReferenceScndPDG = pset.get<int>("ReferenceScndPDG");
135  fReferenceKaonEnergy = pset.get<double>("ReferenceKaonEnergy");
136 
137  fMaxWeightFudge = pset.get<double>("MaxWeightFudge", 1.);
138 
140 
141  fNThrow = pset.get<unsigned>("NThrow");
142  fFixNSuccess = pset.get<bool>("FixNSuccess");
143  fNSuccess = pset.get<unsigned>("NSuccess", 2);
144 }
145 
147  double kplus_mass = Constants::Instance().kplus_mass;
148  double secondary_mass = secPDG2Mass(fReferenceScndPDG);
149 
150  double p = twobody_momentum(kplus_mass, secondary_mass, fReferencePrtlMass);
151  double beta = sqrt(fReferenceKaonEnergy*fReferenceKaonEnergy - kplus_mass*kplus_mass) / fReferenceKaonEnergy;
152 
153  // Doen't affect weight
154  double rand = 1.;
155 
156  // For the maxweight, make the kaon and daughter direction aligned
157  TVector3 dir(1, 0, 0);
158  TVector3 boost(beta, 0., 0.);
159 
160  double lab_frame_p, costh_rest, weight;
161  int err = calcPrtlRayWgt(p, fReferencePrtlMass, dir, boost, rand, lab_frame_p, costh_rest, weight);
162 
163  if (err) { // Shouldn't happen
164  throw cet::exception("Weighted Ray Trace: Bad max weight calculation.");
165  }
166 
167  // Normalize the weight
168  //
169  // Cap at 100% intersection probability
170  fMaxWeight = std::min(fMaxWeightFudge * weight * fReferenceLabSolidAngle / (4*M_PI), 1.);
171 }
172 
173 TLorentzVector MixedWeightRayTraceBox::ThrowMeVPrtlMomentum(const MeVPrtlFlux &flux, TRotation &RInv, double phi) {
174  // Pick a direction vector with the parent-direction along the z-axis
175  double costh = GetRandom()*2 - 1.;
176  double sinth = sqrt(1 - costh*costh);
177 
178  TVector3 dir(cos(phi)*sinth, sin(phi)*sinth, costh);
179 
180  // Rotate to the lab direction
181  dir = RInv * dir;
182 
183  // make the mevprtl momentum this
184  TLorentzVector mevprtl_mom = flux.mom;
185  mevprtl_mom.Boost(-flux.kmom.BoostVector());
186 
187  mevprtl_mom = TLorentzVector(mevprtl_mom.P() * dir, mevprtl_mom.E());
188 
189  // boost back
190  mevprtl_mom.Boost(flux.kmom.BoostVector());
191  return mevprtl_mom;
192 }
193 
194 std::pair<double, double> MixedWeightRayTraceBox::DeltaPhi(TVector3 origin, TRotation &R) {
195  // If the parent hits the detector, then delta-phi is 2Pi
196  TVector3 pdir = R.Inverse()*TVector3(0, 0, 1);
197  if (fBox.GetIntersections(origin, pdir).size()) {
198  std::cout << "Parent Direction: " << pdir.X() << " " << pdir.Y() << " " << pdir.Z() << " at location: " << origin.X() << " " << origin.Y() << " " << origin.Z() << " hits detector!\n";
199  return {-M_PI, M_PI};
200  }
201 
202  // Iterate over all corners and compute the limits of Phi
203  double phihi = -M_PI;
204  double philo = M_PI;
205 
206  for (unsigned i = 0; i < 8; i++) {
207  double X = (i & 1) ? fBox.MaxX() : fBox.MinX();
208  double Y = (i & 2) ? fBox.MaxY() : fBox.MinY();
209  double Z = (i & 4) ? fBox.MaxZ() : fBox.MinZ();
210 
211  TVector3 corner(X, Y, Z);
212 
213  double phi = (R * (corner - origin)).Phi();
214  if (phi > phihi) phihi = phi;
215  if (phi < philo) philo = phi;
216  }
217 
218  // Now figure out if the bounds should go philo -> phihi or phihi -> philo
219  //
220  // Whichever has the smaller length is correct
221  bool order_is_up = (phihi - philo) < (M_PI - phihi) + (philo + M_PI);
222 
223  // If we should go phihi -> philo switch them and re-order them around
224  if (!order_is_up) {
225  std::cout << "FLIP PHILIM! " << philo << " " << phihi << std::endl;
226  double temp = phihi;
227  phihi = philo + 2*M_PI;
228  philo = temp;
229  }
230 
231  return {philo, phihi};
232 }
233 
234 RayWeightInfo MixedWeightRayTraceBox::ThrowFixedThrows(const MeVPrtlFlux &flux, TRotation &RInv, double phi) {
235  RayWeightInfo ret;
236  unsigned ithrow = 0;
237  unsigned nfail = 0;
238  unsigned nsuccess = 0;
239 
240  while (ithrow < fNThrow) {
241  ithrow ++;
242 
243  TLorentzVector mevprtl_mom = ThrowMeVPrtlMomentum(flux, RInv, phi);
244  std::vector<TVector3> box_intersections = fBox.GetIntersections(flux.pos.Vect(), mevprtl_mom.Vect().Unit());
245 
246  // Does this ray intersect the box?
247  if (box_intersections.size() != 2) {
248  nfail ++;
249  continue;
250  }
251 
252  // if the ray points the wrong way, it doesn't intersect
253  TVector3 A = box_intersections[0];
254  if (mevprtl_mom.Vect().Unit().Dot((A - flux.pos.Vect()).Unit()) < 0.) {
255  nfail ++;
256  continue;
257  }
258 
259  // if we're here, we have a valid ray
260  ret.allIntersections.push_back(box_intersections);
261  ret.allPrtlMom.push_back(mevprtl_mom);
262  nsuccess ++;
263  }
264 
265  std::cout << "NTHROW: " << fNThrow << std::endl;
266  std::cout << "NSUCCESS: " << nsuccess << std::endl;
267  std::cout << "P: " << (((double)nsuccess) / fNThrow) << std::endl;
268 
269  ret.weight = ((double)nsuccess) / fNThrow;
270  ret.pass = nsuccess > 0;
271 
272  return ret;
273 
274 }
275 
276 RayWeightInfo MixedWeightRayTraceBox::ThrowFixedSuccess(const MeVPrtlFlux &flux, TRotation &RInv, double phi) {
277  RayWeightInfo ret;
278  unsigned ithrow = 0;
279  unsigned nfail = 0;
280  unsigned nsuccess = 0;
281  while (nsuccess < fNSuccess && ithrow < fNThrow) {
282  ithrow ++;
283 
284  TLorentzVector mevprtl_mom = ThrowMeVPrtlMomentum(flux, RInv, phi);
285  std::vector<TVector3> box_intersections = fBox.GetIntersections(flux.pos.Vect(), mevprtl_mom.Vect().Unit());
286 
287  // Does this ray intersect the box?
288  if (box_intersections.size() != 2) {
289  nfail ++;
290  continue;
291  }
292 
293  // if the ray points the wrong way, it doesn't intersect
294  TVector3 A = box_intersections[0];
295  if (mevprtl_mom.Vect().Unit().Dot((A - flux.pos.Vect()).Unit()) < 0.) {
296  nfail ++;
297  continue;
298  }
299 
300  // if we're here, we have a valid ray
301  ret.allIntersections.push_back(box_intersections);
302  ret.allPrtlMom.push_back(mevprtl_mom);
303  nsuccess ++;
304  }
305 
306  std::cout << "NFAIL: " << nfail << std::endl;
307  std::cout << "NSUCCESS: " << nsuccess << std::endl;
308  std::cout << "Q: " << QEstimator(nsuccess, nfail, fNSuccess) << std::endl;
309 
310  if (nsuccess == fNSuccess) {
311  ret.weight = QEstimator(nsuccess, nfail, fNSuccess);
312  ret.pass = true;
313  }
314  else {
315  ret.weight = 0.;
316  ret.pass = false;
317  }
318 
319  return ret;
320 }
321 
322 bool MixedWeightRayTraceBox::IntersectDetector(MeVPrtlFlux &flux, std::array<TVector3, 2> &intersection, double &weight) {
323  // We want to pick an orientation in the lab frame (th, phi)
324  // that intersects with the detector.
325  //
326  // In the lab frame, the angular distribution is not uniform. In the
327  // parent-rest-rame (th', phi'), it is. Picking directions in the
328  // parent-rest-frame until a direction which hits the detector is very inefficient.
329  //
330  // We can draw from the lab frame and weight using d(th, phi) / d(th', phi').
331  // (This is what is done for neutrino simulation). However, in the massive
332  // case there is a (integrable) singularity which leads to an unbounded max weight.
333  // This is undesirable for the Monte-Carlo and makes application of a "accept-reject"
334  // algorithm to de-weight impossible.
335  //
336  // So here we apply a mixed algorithm. We pick (phi, th'). I.e. we pick phi in the lab
337  // frame (forced to hit the detector) and th' in the parent-rest-frame. This reduces
338  // the MC to one dimension instead of two, and so should be much more efficient. And,
339  // to weight we just need dphi/dphi' = 1.
340 
341  // Setup the axes so that the parent Momentum is along the z axis
342  TVector3 parent_dir = flux.kmom.Vect().Unit();
343  TVector3 zdir(0, 0, 1);
344  TVector3 perp_parent_dir = zdir.Cross(parent_dir);
345  double angle = acos(parent_dir.Z());
346 
347  TRotation R;
348 
349  // Setup the rotation if we need to
350  if (perp_parent_dir.Mag() > 1e-4) {
351  R.Rotate(-angle, perp_parent_dir);
352  }
353  TRotation RInv = R.Inverse();
354 
355  std::cout << "PARENT DIR: " << parent_dir.X() << " " << parent_dir.Y() << " " << parent_dir.Z() << std::endl;
356  TVector3 parent_dir_rotated = R * parent_dir;
357  std::cout << "PARENT DIR ROTATED: " << parent_dir_rotated.X() << " " << parent_dir_rotated.Y() << " " << parent_dir_rotated.Z() << std::endl;
358 
359  // Compute the Delta Phi of the detector
360  std::pair<double, double> philim = DeltaPhi(flux.pos.Vect(), R);
361  double philo = philim.first;
362  double phihi = philim.second;
363 
364  std::cout << "PHILIM: " << philo << " " << phihi << std::endl;
365  std::cout << "DELTAPHI: " << (phihi - philo) << std::endl;
366 
367  // Pick a phi
368  double phi = GetRandom() * (phihi - philo) + philo;
369 
370  std::cout << "THISPHI: " << phi << std::endl;
371 
372  RayWeightInfo info = (fFixNSuccess) ? ThrowFixedSuccess(flux, RInv, phi) : ThrowFixedThrows(flux, RInv, phi);
373 
374  if (!info.pass) return false;
375 
376  unsigned ind = CLHEP::RandFlat::shootInt(fEngine, 0, info.allIntersections.size()-1); // inclusive?
377  TLorentzVector mevprtl_mom = info.allPrtlMom[ind];
378  std::vector<TVector3> box_intersections = info.allIntersections[ind];
379 
380  TVector3 A = box_intersections[0];
381  TVector3 B = box_intersections[1];
382 
383  // make sure that the flux start lies outside the detector
384  if ((flux.pos.Vect() - A).Mag() < (A-B).Mag() && (flux.pos.Vect() - B).Mag() < (A-B).Mag()) {
385  throw cet::exception("ReThrowRayTraceBox Exception", "Input mevprtl flux starts inside detector volume: "
386  "MeVPrtl start At: (" + std::to_string(flux.pos.X()) + ", " + std::to_string(flux.pos.Y()) + ", " + std::to_string(flux.pos.Z()) + "). "
387  "Intersection A At: " + std::to_string(A.X()) + ", " + std::to_string(A.Y()) + ", " + std::to_string(A.Z()) + "). "
388  "Intersection B At: " + std::to_string(B.X()) + ", " + std::to_string(B.Y()) + ", " + std::to_string(B.Z()) + ").\n"
389  );
390  }
391 
392  // weight from forcing phi
393  double phiweight = (phihi - philo) / (2*M_PI);
394  // Total weight
395  weight = phiweight * info.weight;
396 
397  std::cout << "Final WEIGHT: " << weight << std::endl;
398 
399  flux.mom = mevprtl_mom;
400  // transform to beam-coord frame
401  flux.mom_beamcoord = mevprtl_mom;
402  flux.mom_beamcoord.Boost(-flux.kmom.BoostVector()); // Boost to kaon rest frame
403  flux.mom_beamcoord.Boost(flux.kmom_beamcoord.BoostVector()); // And to beam coordinate frame
404  // Two boosts make a rotation!
405 
406  // Set the secondary 4-momentum
407  flux.sec = flux.kmom - flux.mom;
408  flux.sec_beamcoord = flux.kmom_beamcoord - flux.mom_beamcoord;
409 
410  if ((flux.pos.Vect() - A).Mag() < (flux.pos.Vect() - B).Mag()) {
411  intersection = {A, B}; // A is entry, B is exit
412  }
413  else {
414  intersection = {B, A}; // reversed
415  }
416 
417  std::cout << "Kaon 4P: " << flux.kmom.E() << " " << flux.kmom.Px() << " " << flux.kmom.Py() << " " << flux.kmom.Pz() << std::endl;
418  std::cout << "Selected Prtl 4P: " << flux.mom.E() << " " << flux.mom.Px() << " " << flux.mom.Py() << " " << flux.mom.Pz() << std::endl;
419  std::cout << "Selected Scdy 4P: " << flux.sec.E() << " " << flux.sec.Px() << " " << flux.sec.Py() << " " << flux.sec.Pz() << std::endl;
420 
421  return true;
422 }
423 
424 DEFINE_ART_CLASS_TOOL(MixedWeightRayTraceBox)
425 
426 } // namespace ldm
427 } // namespace evgen
TLorentzVector sec_beamcoord
Definition: MeVPrtlFlux.h:17
std::vector< TLorentzVector > allPrtlMom
Utilities related to art service access.
double QEstimator(unsigned nsuccess, unsigned nfail, unsigned r)
RayWeightInfo ThrowFixedSuccess(const MeVPrtlFlux &flux, TRotation &RInv, double phi)
TLorentzVector mom
Definition: MeVPrtlFlux.h:14
const geo::GeometryCore * geometry
double secPDG2Mass(int pdg)
Definition: Constants.cpp:236
TLorentzVector mom_beamcoord
Definition: MeVPrtlFlux.h:15
EResult err(const char *call)
pdgs p
Definition: selectors.fcl:22
double MinX() const
Returns the world x coordinate of the start of the box.
Definition: BoxBoundedGeo.h:88
geo::BoxBoundedGeo DetectorEnclosureBox(std::string const &name="volDetEnclosure") const
double twobody_momentum(double parent_mass, double childA_mass, double childB_mass)
Definition: Constants.cpp:73
double MaxX() const
Returns the world x coordinate of the end of the box.
Definition: BoxBoundedGeo.h:91
then echo echo For and will not be changed by echo further linking echo echo B echo The symbol is in the uninitialized data multiple common symbols may appear with the echo same name If the symbol is defined the common echo symbols are treated as undefined references For more echo details on common see the discussion of warn common echo in *Note Linker see the discussion of warn common echo in *Note Linker such as a global int variable echo as opposed to a large global array echo echo I echo The symbol is an indirect reference to another symbol This echo is a GNU extension to the a out object file format which is echo rarely used echo echo N echo The symbol is a debugging symbol echo echo R echo The symbol is in a read only data section echo echo S echo The symbol is in an uninitialized data section for small echo objects echo echo T echo The symbol is in the the normal defined echo symbol is used with no error When a weak undefined symbol echo is linked and the symbol is not the value of the echo weak symbol becomes zero with no error echo echo W echo The symbol is a weak symbol that has not been specifically echo tagged as a weak object symbol When a weak defined symbol echo is linked with a normal defined the normal defined echo symbol is used with no error When a weak undefined symbol echo is linked and the symbol is not the value of the echo weak symbol becomes zero with no error echo echo echo The symbol is a stabs symbol in an a out object file In echo this the next values printed are the stabs other echo the stabs desc and the stab type Stabs symbols are echo used to hold debugging information For more echo see *Note or object file format specific echo echo For Mac OS X
CLHEP::HepRandomEngine * fEngine
Definition: IMeVPrtlStage.h:79
Access the description of detector geometry.
TLorentzVector kmom
Definition: MeVPrtlFlux.h:13
RayWeightInfo ThrowFixedThrows(const MeVPrtlFlux &flux, TRotation &RInv, double phi)
TLorentzVector ThrowMeVPrtlMomentum(const MeVPrtlFlux &flux, TRotation &RInv, double phi)
double MinZ() const
Returns the world z coordinate of the start of the box.
MixedWeightRayTraceBox(fhicl::ParameterSet const &pset)
Constructor.
IMeVPrtlStage interface class definiton. General interface behind each stage. Provides random number ...
Definition: IMeVPrtlStage.h:36
Description of geometry of one entire detector.
IRayTrace interface class definiton.
Definition: IRayTrace.h:39
void configure(const fhicl::ParameterSet &) override
Interface for configuring the particular algorithm tool.
Provides a base class aware of world box coordinates.
double MaxY() const
Returns the world y coordinate of the end of the box.
tuple dir
Definition: dropbox.py:28
static const Constants & Instance()
Definition: Constants.h:68
std::vector< std::vector< TVector3 > > allIntersections
A base class aware of world box coordinatesAn object describing a simple shape can inherit from this ...
Definition: BoxBoundedGeo.h:33
std::string to_string(WindowPattern const &pattern)
double MaxZ() const
Returns the world z coordinate of the end of the box.
TLorentzVector pos
Definition: MeVPrtlFlux.h:11
do i e
std::vector< TVector3 > GetIntersections(TVector3 const &TrajectoryStart, TVector3 const &TrajectoryDirect) const
Calculates the entry and exit points of a trajectory on the box surface.
bool IntersectDetector(MeVPrtlFlux &flux, std::array< TVector3, 2 > &intersection, double &weight) override
MixedWeightRayTraceBox class definiton.
finds tracks best matching by angle
float A
Definition: dedx.py:137
This provides an interface for an art tool which ray traces &quot;Prtl&quot; (massive) particles from their pro...
double MinY() const
Returns the world y coordinate of the start of the box.
TLorentzVector kmom_beamcoord
Definition: MeVPrtlFlux.h:12
esac echo uname r
art framework interface to geometry description
BEGIN_PROLOG could also be cout
constexpr Point origin()
Returns a origin position with a point of the specified type.
Definition: geo_vectors.h:227
std::pair< double, double > DeltaPhi(TVector3 origin, TRotation &R)
TLorentzVector sec
Definition: MeVPrtlFlux.h:16
int calcPrtlRayWgt(double rest_frame_p, double M, TVector3 dir, TVector3 boost, double rand, double &lab_frame_p_out, double &costh_rest_out, double &wgt)
Definition: Constants.cpp:102