MDetector/Scintillator.cc
Go to the documentation of this file.
1 #include <mdet/Scintillator.h>
2 
3 #include <mdet/Module.h>
4 #include <mdet/Counter.h>
5 #include <mdet/MHierarchyInfo.h>
6 //
7 #include <sdet/Station.h>
8 //
9 #include <utl/Point.h>
10 #include <utl/Line.h>
11 #include <utl/Vector.h>
12 #include <utl/ErrorLogger.h>
13 #include <utl/RandomEngine.h>
14 #include <utl/TransformationMatrix.h>
15 #include <utl/GeometryUtilities.h>
16 //
17 #include <fwk/RandomEngineRegistry.h>
18 #include <fwk/LocalCoordinateSystem.h>
19 //
20 #include <CLHEP/Random/RandExponential.h>
21 //
22 #include <cmath>
23 //
24 #include <boost/function.hpp>
25 #include <boost/lambda/lambda.hpp>
26 #include <boost/logic/tribool.hpp>
27 #include <boost/ptr_container/ptr_vector.hpp>
28 
29 #ifdef DEBUG
30 # include <iostream>
31 #endif
32 
33 
34 namespace mdet {
35 
37 
39 
40 
41  Scintillator::Scintillator(const int sId, const det::VManager::IndexMap& parentMap, const Module& parent) :
42  MDetectorComponent<Scintillator>::Type(sId, parentMap),
43  det::MPositionable<Scintillator>(*this),
44  fModule(parent)
45  {
51  }
52 
53 
56  const
57  {
59  }
60 
61 
62  const Module&
64  const
65  {
66  return fModule;
67  }
68 
69 
70  double
72  const
73  {
74  return GetData(fLength, "length");
75  }
76 
77 
78  double
80  const
81  {
82  return GetData(fWidth, "width");
83  }
84 
85 
86  double
88  const
89  {
90  return GetData(fHeight, "height");
91  }
92 
93 
94  double
96  const
97  {
98  return GetData(fLocalSoilDensity, "localSoilDensity");
99  }
100 
101 
102  double
104  const
105  {
106  return GetData(fDecayTime, "decayTime");
107  }
108 
109  double
111  const
112  {
113  return GetData(fEpsilon, "epsilon");
114  }
115 
116 
117  double
119  const
120  {
121  // This method gives sense to the bare number decay time: it's an exponential process.
122  utl::RandomEngine& rnd = fwk::RandomEngineRegistry::GetInstance().Get(fwk::RandomEngineRegistry::eDetector);
123  double decayTime = CLHEP::RandExponential::shoot(& rnd.GetEngine(), GetDecayTime());
124 
125  return decayTime;
126  }
127 
128 
129  double
131  const
132  {
133  // The mean is the parameter.
134  return GetDecayTime();
135  }
136 
137 
138  double
140  const
141  {
142  // For an exponential process the std-dev equals the mean value.
143  return GetDecayDelayMean();
144  }
145 
146 
147  bool
149  const
150  {
151  /*
152  * XXX
153  * In all these methods the Fiber position may have to be
154  * taken into account for exactness:
155  * that is, a part of the configured volume for the scintillator
156  * is, in fact, fiber, not scint.
157  */
158  /*
159  * As of the general recommendation, this logic
160  * avoid the usage of Get<Component> methods
161  * from utl::Point.
162  * Instead of that, it uses geometrical operations
163  * such as inner product between vectors.
164  */
165  /*
166  * Difference against the origin of the Scintillator, to
167  * refer against that origin.
168  */
169  const utl::Vector pLocal = p - GetPosition();
170  // Project each component & see if it lies within the boundary.
171  return InExtent(GetWidth(), pLocal, utl::Vector(1, 0, 0, GetLocalCoordinateSystem())) &&
172  InExtent(GetLength(), pLocal, utl::Vector(0, 1, 0, GetLocalCoordinateSystem())) &&
173  InExtent(GetHeight(), pLocal, utl::Vector(0, 0, 1, GetLocalCoordinateSystem()));
174  }
175 
176 
177  bool
179  const
180  {
181  // About top & bot:
182  // At first the line should touch these both planes in one point for each
183  // , at least somewhere far from the Scint.
184  // The line won't touch in a single point them if is parallel to then, which
185  // won't be a normal situation (that's an horizontal particle!?!?!)
186  // Given the current dimensions, if the line intersects the Scintillator,
187  // then it's more likely that crosses top & bot: because of that they
188  // were put first in this if-chain.
189  //--
190  // Theoretically if the line intersects the box in one point, then
191  // that should be enough to, then, intersect it in another one.
192  // Practically, it was found that, due to rounding errors, when a point
193  // should intersect inside, the result lays outside. So, let's check
194  // for two-fold intersection.
195  //--
196  // See ComputeIntersectionWith for more details.
197  // Note that we may short-cut before the two final planes of intersection
198  // are used: I mean the planes of the two final points used while
199  // computing the intersection.
200  const int limit = 2;
201  // For the first two, no need to use "if".
202  int count = OnSide(ComputeTopPlane(), l) ;
203  count += OnSide(ComputeBottomPlane(), l);
204  if (count < limit)
205  count += OnSide(ComputeLeftPlane(), l);
206  if (count < limit)
207  count += OnSide(ComputeRightPlane(), l);
208  if (count < limit)
209  count += OnSide(ComputeFrontPlane(), l);
210  if (count < limit)
211  count += OnSide(ComputeBackPlane(), l);
212  return count >= limit;
213  }
214 
215 
216  bool
217  Scintillator::OnSide(const utl::Plane& sidePlane, const utl::Line& l)
218  const
219  {
220  /*
221  * Despite being const, certain operations
222  * transform one geometry object to the
223  * coordinate system of the other: so
224  * the scint may
225  * be intertectedBy but then the computation
226  * of the intersection dies.
227  * It had to be put deep in the function hierarchy,
228  * because repeated calls to this function from
229  * another function in the class already triggered
230  * the problem. So, to avoid that, copies were made of
231  * the line. But at last, the problem was not solved by
232  * these copies, but by an increase in the epsilon.
233  */
234  // First the line must cross the given plane, and then the crossing
235  // point has to belong to the Scintillator.
236  bool b1 = Intersects(sidePlane, l);
237  // Use b1 so as to avoid further calculations (&&-shorcut).
238  bool b2 = b1 && Contains(utl::Intersection(sidePlane, l));
239  return b2; // b2 is enough given the && above.
240  }
241 
242 
245  const
246  {
247  boost::ptr_vector<utl::Point> pCross;
248  // Collect the intersecting points.
255  unsigned int index2ndPoint = 1;
256  // If there are only two, the 2nd point has to be the 2nd in the vector.
257  if (pCross.size() > 2) {
258  // In, no pun, corner cases there maybe more than two planes; for instance
259  // when the particle enters through a corner. So, the criteria is to take
260  // the first, and then the one further away, in a way to avoid taking
261  // the two of the same corner.
262  double dist = 0; // Start with 0: we're looking for a max of positives.
263  for (unsigned int i = 1; i < pCross.size(); ++i) {
264  double d = (pCross[i] - pCross[0]).GetMag();
265  if (d > dist) {
266  dist = d;
267  index2ndPoint = i;
268  }
269  }
270  }
271  /*
272  * The tail of the arrow goes closer to the ground & the end arrow closer to the scint:
273  * for that we need the ground plane and a point within it.
274  */
275  const utl::Plane ground = ComputeGroundPlane();
276  /*
277  * Retrieve the two points (here it's supposed they exist, if not the
278  * precondition of the method -over l & this - is violated by the call) and
279  * then see the distance to the ground.
280  */
281  // Note that we should have two points as of the precondition that the
282  // particle has to intersect the scint (the method IntersectedBy was
283  // modified to look for two planes, not 1 any more).
284  const double d0 = ( pCross[0] - ground.GetAnchor() ).GetMag();
285  const double d1 = ( pCross[index2ndPoint] - ground.GetAnchor() ).GetMag();
286  const bool head = d1 > d0; // true -> 1 for the head.
287  /*
288  * "If the source type is bool, the value false is converted to zero
289  * and the value true is converted to one." (4.7 (4) from C++ Standard ANSI 14882).
290  * Construct the pair with both points.
291  *
292  * The first is the head and the second is the tail.
293  */
294  return utl::Segment(pCross[ !head ], pCross[ head ]);
295  }
296 
297 
298  template<class Container>
299  void
301  utl::Plane (Scintillator::* ComputePlane)() const)
302  const
303  {
304  // Compute the plane calling the pointed method.
305  const utl::Plane p = (this->*ComputePlane)();
306  if (OnSide(p, l)) {
307  /*
308  * The container has to (and actually does, see
309  * ComputeIntersectionWith) take care of deletion.
310  */
311  v.push_back(new utl::Point(utl::Intersection(p, l)));
312  }
313  }
314 
315 
318  const
319  {
320  // With the ground...
321  const utl::Plane ground = ComputeGroundPlane();
322  const utl::Point pGround = utl::Intersection(ground, l);
323  // With the scint...
324  const utl::Segment track = ComputeIntersectionWith(l);
325  // Now the segment intersecting the ground / soil goes from the
326  // point at the ground until it reaches the scintillator.
327  return utl::Segment(pGround, track.GetBegin());
328  }
329 
330 
331  double
333  const
334  {
335  // Simple density parametrization.
337  }
338 
339 
340  utl::Plane
342  const
343  {
345  const utl::Point topAnchor(0, 0, 0, cs);
346  const utl::Vector normalZ(0, 0, 1, cs);
347  return utl::Plane(topAnchor, normalZ);
348  }
349 
350 
351 // double
352 // Scintillator::ComputeEffectiveArea(const utl::Line& /*dir*/)
353 /* const
354  {
355  // TODO Simple calculation by now: just the 2-D area.
356  // No angle involved. No height.
357  return GetLength() * GetWidth();
358  }
359 */
360 
361 
362  double
364  const
365  {
366  return GetLength() * GetWidth();
367  }
368 
369 
370  /*
371  * All these methods for computing different planes define the extent of the scintillator.
372  */
373 
374  // This method also defines how the extent is taken.
375  bool
376  Scintillator::InExtent(double ext, const utl::Vector& pLocal, const utl::Vector& normal)
377  const
378  {
379  const double c = normal * pLocal;
380  /*
381  * Comparing with these bounds (having the upper coming from one of width, length and height)
382  * defines that the origin is in the border).
383  * See also the different plane computing methods.
384  *
385  * In addition to the operator comparison, we resort to a tolerance one also, against the
386  * borders.
387  */
388  const double ext2 = ext / 2;
389  // With the abs of c we compare both sides.
390  return (-ext2 <= c && c <= ext2) || IsCloseTo(std::fabs(c), ext2);
391  }
392 
393 
394  utl::Plane
396  const
397  {
398  return ComputePlaneHelper(GetHeight() / 2, 0, 0, 1);
399  }
400 
401 
402  utl::Plane
404  const
405  {
406  return ComputePlaneHelper(- GetHeight() / 2, 0, 0, 1);
407  }
408 
409 
410  utl::Plane
412  const
413  {
414  return ComputePlaneHelper(GetLength() / 2, 0, 1, 0);
415  }
416 
417 
418  utl::Plane
420  const
421  {
422  return ComputePlaneHelper(- GetLength() / 2, 0, 1, 0);
423  }
424 
425 
426  utl::Plane
428  const
429  {
430  return ComputePlaneHelper(GetWidth() / 2, 1, 0, 0);
431  }
432 
433 
434  utl::Plane
436  const
437  {
438  return ComputePlaneHelper(- GetWidth() / 2, 1, 0, 0);
439  }
440 
441 
442  utl::Plane
443  Scintillator::ComputePlaneHelper(double ext, double x, double y, double z)
444  const
445  {
446  const utl::Point a(x * ext, y * ext, z * ext, GetLocalCoordinateSystem());
447  const utl::Vector n(x, y, z, GetLocalCoordinateSystem());
448  return utl::Plane(a, n);
449  }
450 
451 
452  bool
453  Scintillator::IsCloseTo(double a, double b)
454  const
455  {
456  return std::fabs(a - b) <= GetEpsilon() * std::max(std::fabs(a), std::fabs(b));
457  }
458 
459 
463  bool
465  const
466  {
467  /*
468  * double to bool conversion, implicit comparission with zero.
469  *
470  * This comparison is also used in the following code:
471  *
472  * ./Modules/HybridGeometryFinderOG/HybridGeometryFinder.cc:213:
473  * if(my_sdp.GetMag() == 0 ) {
474  * ./Modules/FdSDPFinderOG/FdSDPFinder.cc:306:
475  * if ( crossprod.GetMag() != 0. )
476  * ./Documentation/ExampleApplications/HReconstruction/UserModule.cc:245:
477  * if(sdp.GetMag() == 0 )
478  * ./Documentation/ExampleApplications/HReconstruction/UserModule.cc:1231:
479  * if (core_station.GetMag() != 0.0 )
480  *
481  * Explicit comparison isn't necessary: see Stroustrup's book (he didn't write
482  * a single one, but I bet you know what I'm talking about).
483  * C.6.2.5 Boolean Conversions (p. 835)
484  * Pointers, integral, and floating point values can be implicitly converted to bool (ยง4.2).
485  * A nonzero value converts to true; a zero value converts to false .
486  *
487  * (ok, let's say it: Stroustrup, Bjarne, "The C++ Programming Language", Special Edition.)
488  *
489  * 6/8/2010 - Change the comparisson == 0 (implicit or not), to a more proper floating point
490  * comparison.
491  *
492  * If the direction is perpendicual to the normal (ie dot product == 0) then the line
493  * is parallel to the plane.
494  */
495  double d = p.GetNormal() * l.GetDirection();
496  return ! IsCloseTo(d, 0);
497  }
498 
499 
500  // At last, there was already a method for this in utl.
507  /*
508  utl::Point
509  Scintillator::ComputeIntersection(const utl::Plane& p, const utl::Line& l)
510  {
511  // See:
512  // http://softsurfer.com/Archive/algorithm_0104/algorithm_0104B.htm
513  // http://en.wikipedia.org/wiki/Line-plane_intersection
514  // Calculate the parameter that solves the intesection between plane & line.
515  double alfa = (p.GetNormal() * (p.GetAnchor() - l.GetAnchor())) /
516  // quotient ____________________________________________________
517  (p.GetNormal() * l.GetDirection());
518  // Now use the parameter to compute the specific point & we're done!
519  // XXX Will the "computational representation" of this point also
520  // be in the Plane object (it should)?
521  return l.Propagate(alfa);
522  }
523  */
524 
525 }
double Plane(const utl::Point &point, const utl::Vector &normal, const utl::Photon &photonIn, utl::Photon &photonOut)
Definition: RTFunctions.cc:41
Point object.
Definition: Point.h:32
bool IntersectedBy(const utl::Line &line) const
Answers if line crosses the body of the Scintillator.
const Counter & GetCounter() const
The parent counter.
bool InExtent(double ext, const utl::Vector &pLocal, const utl::Vector &normal) const
Checks if the vector lies within Scintillator&#39;s extent for the given axis.
utl::Validated< double > fLength
bool OnSide(const utl::Plane &sidePlane, const utl::Line &line) const
Indicates whether the line hits the Scintillator on the side contained in sidePlane.
RandomEngineType & GetEngine()
Definition: RandomEngine.h:32
bool IsCloseTo(double a, double b) const
FP Comparison criteria.
utl::Plane ComputeBottomPlane() const
The plane where the bottom of the Scintillator lays.
utl::Plane ComputeBackPlane() const
The plane where the back of the Scintillator lays.
utl::Plane ComputeTopPlane() const
The plane where the top of the Scintillator lays.
bool Contains(const utl::Point &point) const
Answers if point lies within the Scintillator.
double GetDecayTime() const
Characteristic decay time.
static const char *const kComponentsNames[13]
Defines within it the common (templated) type for muon detector hierarchy components.
utl::CoordinateSystemPtr GetLocalCoordinateSystem() const
Local system based on position and configured rotations.
const Point & GetAnchor() const
Definition: Plane.h:22
static const char *const kComponentsIds[13]
utl::Plane ComputeLeftPlane() const
The plane where the left of the Scintillator lays.
void IntersectionHelper(Container &v, const utl::Line &l, utl::Plane(Scintillator::*ComputePlane)() const ) const
Helper function for another specific member.
void Register(utl::VValidated &v)
Register the field so as to allow handling it.
double GetLength() const
Return the length of the segment (ie the distance between begin and end).
Definition: Segment.h:45
T & GetData(P< T > &d, const std::string &p) const
Common utility function for configuration.
double GetWidth() const
Width of the strip (x direction in the local coordinate system).
Line Intersection(const Plane &p1, const Plane &p2)
double GetHeight() const
Height of the strip (z direction in the local coordinate system).
double GetDecayDelayStdDev() const
The standard deviation fo the delay time.
double GetEpsilon() const
FP comparison limit.
Actual muon-sensitive objects.
boost::shared_ptr< const CoordinateTransformer > CoordinateSystemPtr
Shared pointer for coordinate systems.
double GetLength() const
Length of the strip (y direction in the local coordinate system).
#define max(a, b)
Class describing a Plane object.
Definition: Plane.h:17
utl::Plane ComputeRightPlane() const
The plane where the right of the Scintillator lays.
utl::Plane ComputeGroundPlane() const
The (inifite) plane that coincides with the ground.
Wraps the random number engine used to generate distributions.
Definition: RandomEngine.h:27
const Point & GetBegin() const
Return the initial point.
Definition: Segment.h:36
Array of Scintillator.
utl::CoordinateSystemPtr GetLocalCoordinateSystem() const
Get the Auger reference system centered on the tank.
utl::Validated< double > fEpsilon
double GetArea() const
Compute Scintillator&#39;s total area in square metres.
static const char *const kComponentName
utl::Validated< double > fDecayTime
utl::Validated< double > fWidth
double GetDecayDelayMean() const
The mean value of the delay time.
utl::Segment ComputeIntersectionWith(const utl::Line &line) const
Computes the intersection of line within the Scintillator.
double ComputeUndergroundGrammageFor(const utl::Line &l) const
Computes the amount of mass transversed until reaching the Scintillator.
std::map< std::string, std::string > IndexMap
Definition: VManager.h:133
const Module & GetModule() const
Retrieve the parent mdet::Module.
Vector object.
Definition: Vector.h:30
const Vector & GetDirection() const
Definition: Line.h:22
const sdet::Station & GetAssociatedTank() const
Retrieve the associated tank.
double ComputeDecayDelay() const
Computes a delay due to decay process.
utl::Plane ComputeFrontPlane() const
The plane where the front of the Scintillator lays.
bool Intersects(const utl::Plane &p, const utl::Line &l) const
Check for intersection.
double GetLocalSoilDensity() const
Simplest density distribution: constant value.
Scintillator(int sId, const det::VManager::IndexMap &parentMap, const Module &parent)
Constructs the Scintillator (obviously!).
Type
The type of file that we are acutally opening.
Definition: IoCodes.h:33
utl::CoordinateSystemPtr GetReferenceCoordinateSystem() const
The reference is the local coordinate system of mdet::Module.
const Vector & GetNormal() const
Definition: Plane.h:23
utl::Validated< double > fHeight
utl::Segment ComputeUndergroundIntersectionOf(const utl::Line &line) const
Computes the intersection of line with the ground (until reaching the Scintillator).
utl::Validated< double > fLocalSoilDensity
utl::Plane ComputePlaneHelper(double ext, double x, double y, double z) const
Helper to construct the different planes.
Definition: Line.h:17
static const char *const kComponentId
A segment joins two points.
Definition: Segment.h:18

, generated on Tue Sep 26 2023.