Modules/FdSimulation/TelescopeSimulatorKG2/Camera.cc
Go to the documentation of this file.
1 
9 //#define DEBUG
10 
11 #include "Camera.h"
12 #include "RTFunctions.h"
13 #include "RayTracer.h"
14 
15 #include <utl/MathConstants.h>
16 #include <utl/AugerUnits.h>
17 #include <utl/ErrorLogger.h>
18 #include <utl/Photon.h>
19 #include <utl/Point.h>
20 #include <utl/Vector.h>
21 #include <utl/CoordinateSystemPtr.h>
22 #include <utl/AugerException.h>
23 #include <utl/RandomEngine.h>
24 #include <utl/Math.h>
25 
26 #include <CLHEP/Random/Randomize.h>
27 
28 #include <det/Detector.h>
29 
30 #include <fdet/FDetector.h>
31 #include <fdet/Eye.h>
32 #include <fdet/Telescope.h>
33 #include <fdet/Camera.h>
34 #include <fdet/Pixel.h>
35 #include <fdet/Channel.h>
36 #include <fdet/Mirror.h> // for check of photons inside camera bay
37 
38 #include <TPolyLine3D.h>
39 #include <TLine.h>
40 #include <TMarker.h>
41 #include <TLatex.h>
42 #include <TPolyMarker3D.h>
43 #include <TCanvas.h>
44 #include <TView.h>
45 #include <TPad.h>
46 #include <TObjArray.h>
47 
48 #include <sstream>
49 #include <iostream>
50 #include <iomanip>
51 #include <vector>
52 #include <utility>
53 
54 using namespace std;
55 using namespace TelescopeSimulatorKG2;
56 using namespace utl;
57 
58 using CLHEP::RandFlat;
59 
60 
61 Camera::Camera(RandomEngine& rndm,
62  const fdet::Telescope& tel,
63  const bool plotPhotonTracksAtMercedes,
64  const bool simulateMercedesStars,
65  const bool simulateHaloEffects,
66  const bool simulateGhostEffects,
67  const double pmt_n) :
68  fRandom(rndm),
69  fTel(tel),
70  fPlotPhotonTracksAtMercedes(plotPhotonTracksAtMercedes),
71  fSimulateMercedesStars(simulateMercedesStars),
72  fSimulateHaloEffects(simulateHaloEffects),
73  fSimulateGhostEffects(simulateGhostEffects),
74  fPMT_n(pmt_n),
75  fTelCS(tel.GetTelescopeCoordinateSystem()),
76  fOrigin(0, 0, 0, fTelCS),
77  fRFocal(tel.GetCamera().GetRadiusFocal()),
78  fMercedesEff(tel.GetCamera().GetMercedesEfficiency()),
79  fSigma(tel.GetCamera().GetSigmaNormal()),
80  fRCurv2(Sqr(tel.GetMirror().GetRadiusOfCurvature())) // need this only to check for photons to stay in mirror bay
81 {
82  // Camera SetMercedesParameter
83  // Find the position of the vertex in the reference frame of the
84  // hexagon. See picture.
85  /*
86  ^ /\
87  n \ / \
88  \ / \
89  \/ \ height
90  / \
91  ^ / \
92  z| / \
93  | --------------
94  | 2xwidth
95  <----
96  t
97  */
98  // Set mercedes parameters
99  const fdet::Camera& camera = tel.GetCamera();
100  fHMerc = camera.GetMercedesHeight(); // height of mercedes ~ 17.91 mm
101 
102  const double ddmerc = camera.GetMercedesBase(); // ~ 4.8 mm = half base length (full 9.2mm)
103  const double dTheta = 1.5*deg; // For numbers see e.g. GAP1999_027
104  const double dPhi = dTheta * cos(30*deg); // ~1.3*deg
105  fR2 = fRFocal * sin(2 * dPhi / 3); // pixel side length ~ 26.34*mm;
106  fD2 = fRFocal * sin(dTheta); // horizontal full pixel width ~ 45.6*mm
107  fD1 = fD2 - 2 * ddmerc; // horizontal pixel width (inside mercedes)
108  fR1 = fD1 / utl::kSqrt3; // hexagon side length (inside mercedes) [Srqt(3) = 2 * cos(30*deg)]
109  fNz = 0.5 * (fD2 - fD1); // = ddmerc; mercedes width
110  fNt = fHMerc; // mercedes height
111  const double aux = sqrt(fNz * fNz + fNt * fNt);
112  fNz /= aux; // (Nz, Nt) : normal on mercedes CHECK !! Seems to be wrong
113  fNt /= aux;
114 
115  //CalculateCameraSupportCoordinateSystem
116  const double theta = 16*deg;
117  const double shift = fRFocal - 50*cm;
118  //const double shift = fRFocal - 30 * cm;
119  const Vector vShift(0, 0, -1, fTelCS);
120  const CoordinateSystemPtr& auxCS = CoordinateSystem::Translation(vShift * shift, fTelCS);
121  fCameraSupportCoordinateSystem = CoordinateSystem::RotationY(theta, auxCS);
122 }
123 
124 
125 RTNext
126 Camera::Trace(const Photon& photonIn,
127  Photon& photonOut,
128  int& nreflections,
129  int& nbackscattered,
130  int& col,
131  int& row)
132 {
133  // simulate camera, including/excluding the mercedes
134 
135  const bool backwards = photonIn.GetDirection().GetZ(fTelCS) < 0 ; // towards the mirror
136 
137  utl::Photon photonCamera;
138  if (!TraceSurf(photonIn, photonCamera)) {
139  // missed camera sphere
140  photonOut = photonIn;
141  return fSimulateGhostEffects ? backwards ? eMirror : eCameraShadow : eLost;
142  }
143 
144  // theoretical incidence direction of the photon - use just to find the pixelId
145  const Vector incidentPhotonDir = Normalized(photonCamera.GetPosition() - fOrigin);
146  if (!FindPixelId(incidentPhotonDir, row, col)) {
147  // camera missed ...
148  photonOut = photonCamera;
149  return fSimulateGhostEffects ? backwards ? eMirror : eCameraShadow : eLost;
150  }
151 
152  const CoordinateSystemPtr& pxlCS = fTel.GetPixel(row, col).GetPixelCoordinateSystem();
153 
155  // simulate mercedes
156  const RTResult mercStatus = TraceMerc(pxlCS, photonCamera, photonOut, nreflections);
157  if (mercStatus == eInvalidMercedes)
158  return eDrawAndExit;
159 
160  if (fSimulateHaloEffects &&
161  (mercStatus == eBackscattered ||
162  mercStatus == eInvalidHitMercedes)) {
163  ++nbackscattered;
164  return eMirror;
165  }
166 
167  if (mercStatus == eOK)
168  return eDetected;
169 
170  } else { // no mercedes
171 
172  // measurements in 2010 showed that the PMT reflectivity is ~20%
173  // the PMT refractive index can be set in the TelescopeSimulatorKG2.xml.in, default is 2.58 -> R=19.5%
174  const double r_index_12 = fAir_n / fPMT_n;
175  RTFunctions::PhotonList photonsHittingPhotocathode;
176  const Vector normalPMT(0, 0, -1, pxlCS);
177 
178  RTFunctions::Refraction(r_index_12,
179  photonCamera,
180  normalPMT,
181  photonsHittingPhotocathode);
182  const utl::Photon& photonRefracted = photonsHittingPhotocathode[0];
183  // photonsHittingPhotocathode[0] ist refracted
184  // photonsHittingPhotocathode[1] ist reflected
185 
186  if (fSimulateHaloEffects) {
187 
188  const double tmpRandNr = RandFlat::shoot(&fRandom.GetEngine(), 0, 1);
189 
190  // photonRefracted.GetWeight() = photonPMT.GetWeight() * T
191  // => T = photonRefracted.GetWeight()/photonPMT.GetWeight()
192 
193  const double weight = photonCamera.GetWeight();
194  if (tmpRandNr > photonRefracted.GetWeight() / weight) {
195  // photon bunch is considered as reflected
196  photonOut = photonsHittingPhotocathode[1];
197  photonOut.SetWeight(weight);
198  // debug
199  //cout << "reflected at camera (no mercedes)" << endl;
200  return eMirror;
201  } else {
202  // photon bunch is refracted
203  photonOut = photonRefracted;
204  photonOut.SetWeight(weight);
205  return eDetected;
206  }
207  }
208 
209  // photonOut is not correct (should be photonRefracted) but was
210  // implemented like this in the previous TelescopeSimulatorKG
211  // -> remove some day
212  photonOut = photonRefracted; // the reflected component is killed at this point, the weight of reflected photons is lost
213  return eDetected; // absorbed by photo-cathode
214  } // end: no mercedes
215 
216  return eLost;
217 }
218 
219 
220 bool
221 Camera::FindPixelId(const Vector& incidentDir, int& row, int& col) const
222 {
223  const double fNx0 = 10;
224  const double fNy0 = 35 / 3; //=11.66666666666667; // optical axis
225  const double dOmega = fTel.GetCamera().GetEta();
226  const double dPhi = 0.5 * kSqrt3 * dOmega;
227  const int nCols = fTel.GetLastColumn() - fTel.GetFirstColumn() + 1; // 20
228  const int nRows = fTel.GetLastRow() - fTel.GetFirstRow() + 1; // 22
229 
230  const double x = incidentDir.GetX(fTelCS);
231  const double y = incidentDir.GetY(fTelCS);
232  const double z = incidentDir.GetZ(fTelCS);
233 
234  const double omegap = asin(y);
235  const double phip = atan2(-x, -z);
236 
237  // find nx and ny from angles omegap, phip.
238  // -------------------------------------------------------------------
239  // ------ algorit. developed by Ronald Shellard, in the FDSim --------
240  // ------------------ (FORTRAN version) ------------------------------
241  // -------------------------------------------------------------------
242  double nxl = 2 * (omegap / dOmega) + 2 * fNx0;
243  double nyl = fNy0 - phip / dPhi;
244 
245  if (nxl < 0 || nxl > 2 * nCols + 1 ||
246  nyl < 0 || nyl > nRows + 1)
247  return false; // the ray of light does not reach any pmt
248 
249  col = int(nxl);
250  row = int(nyl);
251  nxl -= col;
252  nyl -= row;
253 
254  const double f1 = 3 * nyl - nxl - 1;
255  const double f2 = 3 * nyl + nxl - 2;
256  double f = 0;
257 
258  if (col % 2) { // col is odd
259  col = (col + 1) / 2;
260  f = (row % 2) ? f1 : f2;
261  } else {
262  if (!(row % 2)) {
263  f = f1;
264  col = col / 2 + (f > 0 ? 0 : 1);
265  } else {
266  f = f2;
267  col = col / 2 + (f > 0 ? 1 : 0);
268  }
269  }
270 
271  if (f >= 0)
272  ++row;
273 
274  return col >= 1 && row >= 1 && col <= nCols && row <= nRows;
275 }
276 
277 
278 RTNext
280  utl::Photon& photonOut,
281  const bool simulateCameraSupport)
282 {
283  // simulate shadow effect of the camera
284 
285  const bool backwards = photonIn.GetDirection().GetZ(fTelCS) > 0 ; // towards the aperture !!
286 
287  RTFunctions::IntersectionList intersections;
288 
289  const bool debug = false;
290 
291  // Warning: the values of SIN_?? may need some changes to simulate
292  // correctly the camera (shadow and trace_surf).
293  // side, top and down limits
294 /*
295  const double fSinAx = 0.2491262;
296  const double fSinBx = 0.25646528973;
297  const double fSinAy = 0.27966724;
298  const double fSinBy = 0.26704475;
299  const double rCam = fRFocal;
300 */
301 
302  bool absorbedByCameraBody = false;
303  const double rCamIn = 1.641*m; // see GAP_1999_027
304  Point pp;
305  if (RTFunctions::Sphere(fOrigin, rCamIn, photonIn, intersections)) {
306  if (intersections.size() != 2)
307  return backwards ? eLens : eMirror;
308  // select the intersection point with NEGATIVE z-coordinate -> location of camera !
309  const bool firstIntersection = intersections.front().first.GetPosition().GetZ(fTelCS) < 0;
310 /*
311  const Vector normal(firstIntersection ? intersections.front().second : intersections.back().second);
312  const double x = normal.GetX(fTelCS);
313  const double y = normal.GetY(fTelCS);
314 
315  if (-fSinAx < x && x < fSinBx &&
316  -fSinAy < y && y < fSinBy) {
317  photonOut = firstIntersection ? intersections.front().first : intersections.back().first;
318  return eLost; // the light hit the PMT camera back
319  }
320 */
321  Photon p(firstIntersection ? intersections.front().first : intersections.back().first);
322  pp = p.GetPosition();
323  const double x = abs(pp.GetX(fTelCS)); // symetric
324  const double y = abs(pp.GetY(fTelCS)); // symetric
325  if (x <= (0.86*m / 2) && y <= (0.93*m / 2))
326  absorbedByCameraBody = true;
327  }
328 
329 /*
330  const double rCamOut = 1.701*m; // see GAP_1999_027
331  if (!absorbedByCameraBody && RTFunctions::Sphere(fOrigin, rCamOut, photonIn, intersections)) {
332  if (intersections.size() != 2)
333  return backwards ? eLens : eMirror;
334  const bool firstIntersection = intersections.front().first.GetPosition().GetZ(fTelCS) < 0;
335  Photon p(firstIntersection ? intersections.front().first : intersections.back().first);
336  pp = p.GetPosition();
337  const double x = abs(pp.GetX(fTelCS)); // symetric
338  const double y = abs(pp.GetY(fTelCS)); // symetric
339  if (x <= (0.86*m / 2) && y <= (0.93*m / 2))
340  absorbedByCameraBody = true;
341  }
342 */
343 
344  if (absorbedByCameraBody) {
345  if (debug)
346  cout << pp.GetX(fTelCS)/mm << ',' << pp.GetY(fTelCS)/mm << ',' << pp.GetZ(fTelCS)/mm << '\n';
347  return eLost; // the light hit the camera back
348  }
349 
350 
351  if (simulateCameraSupport) {
352  const Point pCamera(0,0,0, fCameraSupportCoordinateSystem);
353  const Vector nSupport(0,0,1, fCameraSupportCoordinateSystem);
354  bool absorbedByCamSupport = false;
355  if (RTFunctions::Plane(pCamera, nSupport, photonIn, photonOut)) {
356  const Point& pPlane = photonOut.GetPosition();
357  const double x = pPlane.GetX(fCameraSupportCoordinateSystem);
358  const double y = abs(pPlane.GetY(fCameraSupportCoordinateSystem)); // symetric
359  // check if photons on camera-support-plane are still within bay (within mirror sphere)
360  const double rPhoton2 = (pPlane - fOrigin).GetMag2();
361  if (rPhoton2 > fRCurv2)
362  return eLost;
363  if (x < 0) // camera support is only below the camera !
364  return backwards ? eLens : eMirror;
365 
366  const double ySupportBegin = 35*cm;
367  const double ySupportEnd = ySupportBegin + 5*cm;
368  const double zSupportDepth = 10*cm;
369  if (y >= ySupportBegin && y <= ySupportEnd)
370  absorbedByCamSupport = true;
371 
372  /*
373  Each leg has the size of 100x50mm ( C-shaped )
374  Longer side is parallel to telescope axis! (See GAP-1999-027)
375  */
376  const Vector nLongerSideSupport(0, 1, 0, fCameraSupportCoordinateSystem);
377  Photon dummyPhoton = photonOut;
378  // right bar left
379  const Point pLongerSideSupport1(0, ySupportBegin, 0, fCameraSupportCoordinateSystem);
380  if (!absorbedByCamSupport && RTFunctions::Plane(pLongerSideSupport1, nLongerSideSupport, photonIn, dummyPhoton)) {
381  const double z = dummyPhoton.GetPosition().GetZ(fCameraSupportCoordinateSystem);
382  if (z <= 0*cm && z >= -zSupportDepth)
383  absorbedByCamSupport = true;
384  }
385  // right bar right
386  const Point pLongerSideSupport2(0, ySupportEnd, 0, fCameraSupportCoordinateSystem);
387  if (!absorbedByCamSupport && RTFunctions::Plane(pLongerSideSupport2, nLongerSideSupport, photonIn, dummyPhoton)) {
388  const double z = dummyPhoton.GetPosition().GetZ(fCameraSupportCoordinateSystem);
389  if (z <= 0*cm && z >= -zSupportDepth)
390  absorbedByCamSupport = true;
391  }
392  // left bar right
393  const Point pLongerSideSupport3(0, -ySupportBegin, 0, fCameraSupportCoordinateSystem);
394  if (!absorbedByCamSupport && RTFunctions::Plane(pLongerSideSupport3, nLongerSideSupport, photonIn, dummyPhoton)) {
395  const double z = dummyPhoton.GetPosition().GetZ(fCameraSupportCoordinateSystem);
396  if (z <= 0*cm && z >= -zSupportDepth)
397  absorbedByCamSupport = true;
398  }
399  // left bar left
400  const Point pLongerSideSupport4(0, -ySupportEnd, 0, fCameraSupportCoordinateSystem);
401  if (!absorbedByCamSupport && RTFunctions::Plane(pLongerSideSupport4, nLongerSideSupport, photonIn, dummyPhoton)) {
402  const double z = dummyPhoton.GetPosition().GetZ(fCameraSupportCoordinateSystem);
403  if (z <= 0*cm && z >= -zSupportDepth)
404  absorbedByCamSupport = true;
405  }
406  if (absorbedByCamSupport) {
407  if (debug) {
408  const Point p = dummyPhoton.GetPosition();
409  cout << p.GetX(fTelCS)/mm << ',' << p.GetY(fTelCS)/mm << ',' << p.GetZ(fTelCS)/mm << '\n';
410  }
411  return eLost;
412  }
413  }
414  } else { // do not simulate the camera support
415  const bool firstIntersection = intersections.front().first.GetPosition().GetZ(fTelCS) < 0;
416  photonOut = firstIntersection ? intersections.front().first : intersections.back().first;
417  }
418  return backwards ? eLens : eMirror;
419 }
420 
421 
422 // find the point that the light hit the focal surface
423 bool
424 Camera::TraceSurf(const utl::Photon& photonIn, utl::Photon& photonOut)
425 {
426  RTFunctions::IntersectionList intersections;
427  if (RTFunctions::Sphere(fOrigin, fRFocal, photonIn, intersections)) {
428  photonOut = intersections.front().first;
429  return true; // hit the camera sphere
430  }
431  return false; // miss the camera sphere
432 }
433 
434 
435 // simulate Mercedes/PMT system
436 RTResult
438  const utl::Photon& photonIn, utl::Photon& photonOut,
439  int& nreflections)
440 {
441  //const Vector& dir = photonIn.GetDirection();
442 
443  //const Point pp = photonIn.GetPosition();
444  //cout << pp.GetX(fTelCS)/mm << ',' << pp.GetY(fTelCS)/mm << ',' << pp.GetZ(fTelCS)/mm << '\n';
445 
446  utl::Photon photon = photonIn; // starting point
447 
448 #ifdef DEBUG
449  cout << "TraceMerc: photon-in"
450  " x=" << setprecision(3) << setw(6) << photon.GetPosition().GetX(pxlCS)
451  << " y=" << setprecision(3) << setw(6) << photon.GetPosition().GetY(pxlCS)
452  << " z=" << setprecision(3) << setw(6) << photon.GetPosition().GetZ(pxlCS)
453  << " nx=" << setprecision(3) << setw(6) << photon.GetDirection().GetX(pxlCS)
454  << " ny=" << setprecision(3) << setw(6) << photon.GetDirection().GetY(pxlCS)
455  << " nz=" << setprecision(3) << setw(6) << photon.GetDirection().GetZ(pxlCS)
456  << endl;
457 #endif
458 
459  // simulate reflections at the mercedes
460  utl::Photon point_next; // the next point of ray-tracing
461  int iPlanePrev = 7; // coming from focal plane !
462 
463  do { // loop until the light hits photo cathode
464 
465  bool firstPlane = true;
466  double closestDist = 0;
467  int closestPlane = 0;
468  Vector nClosestPlane;
469 
470  const double eps = 0*mm;
471 
472  // find the closest plane that light hits (cathode, six merce-walls, focal plane)
473  for (int iPlane = 0; iPlane <= 7; ++iPlane) {
474 
475  if (iPlane == iPlanePrev)
476  continue;
477 
478  // 0 to photo cathode surface and 1,2,3,4,5 or 6 to mercedes, 7 focal plane (pixel exit)
479 
480 #warning cache planes for better performance
481  Point pPlane;
482  Vector nPlane;
483  ConstructPlane(iPlane, nPlane, pPlane, pxlCS);
484 
485  Photon testPhoton;
486  const double dist = RTFunctions::Plane(pPlane, nPlane, photon, testPhoton);
487 
488  if (dist < -eps)
489  continue;
490 
491  if (firstPlane) {
492  firstPlane = false;
493  closestDist = dist;
494  closestPlane = iPlane;
495  nClosestPlane = nPlane;
496  point_next = testPhoton;
497 
498  } else if (dist < closestDist) {
499 
500  closestDist = dist;
501  closestPlane = iPlane;
502  nClosestPlane = nPlane;
503  point_next = testPhoton;
504 
505  }
506  } // plane loop
507 
508  // debug
509  //cout << "closestPlane = " << closestPlane << endl;
510 
511 #ifdef DEBUG
512  cout << "TraceMerc: nmerc=" << setw(3) << nreflections
513  << " x=" << setprecision(3) << setw(6) << point_next.GetPosition().GetX(pxlCS)
514  << " y=" << setprecision(3) << setw(6) << point_next.GetPosition().GetY(pxlCS)
515  << " z=" << setprecision(3) << setw(6) << point_next.GetPosition().GetZ(pxlCS)
516  << " nx=" << setprecision(3) << setw(6) << point_next.GetDirection().GetX(pxlCS)
517  << " ny=" << setprecision(3) << setw(6) << point_next.GetDirection().GetY(pxlCS)
518  << " nz=" << setprecision(3) << setw(6) << point_next.GetDirection().GetZ(pxlCS)
519  << " " << iPlanePrev << " -> " << closestPlane
520  << endl;
521 #endif
522 
523  iPlanePrev = closestPlane;
524 
526  fPhotonTrack->AddPoint(point_next.GetPosition());
527 
528  if (firstPlane) {
529  ostringstream err;
530  err << " RT::Camera> NO MERCEDES OR PMT HIT! PHOTON invalid! w=" << photonIn.GetWeight()
531  << " closestDist=" << closestDist/mm << " mm";
532  ERROR(err);
533  photonOut = photonIn;
534  photonOut.SetPosition(photonOut.GetPosition() + photonOut.GetDirection()*0.5*m);
535  return eInvalidHitMercedes;
536  }
537 
538  if (closestPlane == 0) { // hit PMT
539 
540  // measurements in 2010 showed that the PMT reflectivity is ~20%
541  // the PMT refractive index can be set in the TelescopeSimulatorKG2.xml.in, default is 2.58 -> R=19.5%
542  const double r_index_12 = fAir_n / fPMT_n;
543  RTFunctions::PhotonList photonsHittingPhotocathode;
544  RTFunctions::Refraction(r_index_12, point_next, nClosestPlane, photonsHittingPhotocathode);
545  const utl::Photon& photonRefracted = photonsHittingPhotocathode[0];
546  // photonsHittingPhotocathode[0] ist refracted
547  // photonsHittingPhotocathode[1] ist reflected
548 
549  if (false) { // photons get absorbed by photo-cathod
550  // for estimating the camera surface backreflection
551  photonOut = photonRefracted;
552  return eOK;
553  }
554 
555  if (fSimulateHaloEffects) {
556 
557  const double tmpRandNr = RandFlat::shoot(&fRandom.GetEngine(), 0, 1);
558 
559  // photonRefracted.GetWeight() = photonPMT.GetWeight() * T
560  // => T = photonRefracted.GetWeight()/photonPMT.GetWeight()
561 
562  const double weight = point_next.GetWeight();
563  if (tmpRandNr > photonRefracted.GetWeight() / weight) {
564  // photon bunch is considered as reflected
565  photon = photonsHittingPhotocathode[1];
566  photon.SetWeight(weight); // backscattered from cathode
567  // diffusive component
568  //double amountOfStrayLight = 0.05; // 5% of the light will go in "lambertian directions"
569  double amountOfStrayLight = 0; // 0% of the light will go in "lambertian directions"
570  if (amountOfStrayLight > 0) {
571  const double maxTheta = 25 * degree;
572  const Vector lambertdiffusion =
573  RTFunctions::LambertDiffusion(fRandom, photon.GetDirection(), nClosestPlane, amountOfStrayLight, maxTheta);
574  photon.SetDirection(lambertdiffusion);
575  }
576  } else {
577  // photon bunch is refracted
578  photonOut = photonRefracted;
579  photonOut.SetWeight(weight);
580  return eOK;
581  }
582 
583  } else { // no halo:
584 
585  photonOut = photonRefracted; // the reflected component is killed at this point, the weight of reflected photons is lost
586  return eOK; // absorbed by photo-cathode
587  }
588 
589  } else if (closestPlane == 7) { // hit focal surface (upper range of mercedes, leaving pixel towards mirror)
590 
591  // only when we hit the surface from the INSIDE
592  if (point_next.GetDirection() * nClosestPlane <= 0) {
593  photonOut = point_next;
594  if (photonOut.GetDirection().GetZ(fTelCS) > 0) {
595  ostringstream err;
596  err << "Photon backscattered from focal surface towards aperture! ";
597  INFO(err);
598  }
599  return eBackscattered;
600  }
601 
602  photon = point_next;
603 
604  } else { // -> We hit a mercedes
605 
606  RTFunctions::Reflection(point_next,
607  nClosestPlane, // normal vector of plane
608  photon); // reflected photon
609  photon.SetWeight(point_next.GetWeight() * fMercedesEff);
610  // diffusive component
611  //double amountOfStrayLight = 0.05; // 5% of the light will go in "lambertian directions"
612  double amountOfStrayLight = 0; // 0% of the light will go in "lambertian directions"
613  if (amountOfStrayLight > 0 ) {
614  const double maxTheta = 25*degree;
615  const Vector lambertdiffusion =
616  RTFunctions::LambertDiffusion(fRandom, photon.GetDirection(), nClosestPlane, amountOfStrayLight, maxTheta);
617  //const Vector lambertdiffusion = RTFunctions::LambertDiffusion( fRandom, photon.GetDirection(), photon.GetDirection(), amountOfStrayLight, maxTheta);
618  //cout << "carefull!!!!!, amountOfStrayLight = 45%, maxTheta = 5degr, distribution peaked around outgoing photon direction (instead of surface normal)" << endl;
619  photon.SetDirection(lambertdiffusion);
620  }
621 
622  ++nreflections; // Do next reflection
623  /* // mercedes black
624  #warning mercedes is black -> photons should be lost, here weight = 0
625  photon.SetWeight(0.);
626  */
627 
628  }
629 
630  } while (true); // WHILE we hit the PMT
631 }
632 
633 
634 /*
635  /\
636  / \
637  / \
638  R/ \R
639  / \
640  / 2 1 \
641  | |
642  | |
643  R| 3 . 6 |R
644  | |
645  | |
646  \ 4 5 /
647  \ /
648  R\ /R
649  Y^ \ /
650  | \ /
651  | \/
652  |____>
653  X
654 
655  R: length of vertex
656  */
657 
659 Camera::Hexagon(const double x, const double y, const double r)
660 {
661  // verify if position x,y is inside or outside of a hexagon,
662  // which the distance from the center (0,0) to the vertex
663  // is smaller than r (see picture)
664  // ***************
665  // 0 -> inside the hexagon
666  // from 1 to 6 -> outside the hexagon
667 
668  const double xl = std::fabs(x);
669  const double yl = std::fabs(y);
670  const double xm = 0.5 * utl::kSqrt3 * r; // cos(30)*r
671  const double tmp = 1 / utl::kSqrt3; // tan(30)
672 
673  // inside hexagon check
674  if (xl <= xm && yl <= r - tmp * xl)
675  return eInside;
676 
677  if (yl < tmp * xl) // left and right slice
678  return (x > 0) ? eRight : eLeft;
679  else // upper right half
680  return (y > 0) ? (x > 0 ? eTopRight:eTopLeft) : (x > 0 ? eBottomRight:eBottomLeft);
681 }
682 
683 
684 void
685 Camera::ConstructPlane(const int id, Vector& n, Point& p, const CoordinateSystemPtr& pxlCS)
686 {
687  // define the plane surfaces to simulate the mercedes
688  // --------------------------
689  // id=0 -> photo-cathode surface
690  // 7 -> focal surface
691  // 1,2,3,4,5 and 6 -> mercedes surfaces (see picture)
692  // ++++++++++++++++++++++++++
693  // n -> normal vector of the surface
694  // o -> a point of the plane surface
695  // *************************
696  // 0 -> there is no plane identified by id
697  // 1 -> ok
698 
699  if (id == 0 || id == 7) {
700  p = Point(0, 0, id == 0 ? 0 : fHMerc, pxlCS);
701  n = Vector(0, 0, id == 0 ? 1 : -1 , pxlCS);
702  return;
703  }
704 
705  if (id > 0 && id < 7) {
706  const double dTheta = 60 * deg;
707  const double theta = dTheta * id;
708  const double sinTheta = sin(theta); // y
709  const double cosTheta = cos(theta); // x
710  n = Vector(-fNt * cosTheta, -fNt * sinTheta, fNz, pxlCS);
711  p = Point(0.5 * cosTheta * fD1, 0.5 * sinTheta * fD1, 0, pxlCS);
712  return;
713  }
714 
715  ostringstream err;
716  err << "This can never happen! Fix TelescopeSimulator. There is no such plane as defined by id=" << id;
717  ERROR(err);
718  throw utl::AugerException(err.str());
719 }
720 
721 
722 TObjArray*
723 Camera::Draw(const bool do3D)
724 {
725  TObjArray* const objs = new TObjArray();
726 
727  double xMin = 0; // <-- TODO: replace with utl::MinMax<double>
728  double xMax = 0;
729  double yMin = 0;
730  double yMax = 0;
731  double zMin = 0;
732  double zMax = 0;
733  bool first = true;
734 
735  const int nCols = fTel.GetLastColumn() - fTel.GetFirstColumn() + 1; // 20
736  const int nRows = fTel.GetLastRow() - fTel.GetFirstRow() + 1; // 22
737 
738  // int color = 0;
739  for (int col = 1; col <= nCols; ++col) {
740 
741  for (int row = 1; row <= nRows; ++row) {
742 
743  const int pixelId = (col - 1) * nRows + row;
744  const CoordinateSystemPtr& pxlCS = fTel.GetPixel(row, col).GetPixelCoordinateSystem();
745 
746  const double r_in = fR1;
747  const double r_out = fR2;
748 
749  for (int i = 0; i < 6; ++i) {
750 
751  const double theta1 = 30*deg + 60*deg * i;
752  const double theta2 = theta1 + 60*deg;
753 
754  const double s1 = sin(theta1);
755  const double c1 = cos(theta1);
756  const Point p1_in(c1 * r_in, s1 * r_in, 0, pxlCS);
757 
758  const double s2 = sin(theta2);
759  const double c2 = cos(theta2);
760  const Point p2_in(c2 * r_in, s2 * r_in, 0, pxlCS);
761 
762  const Point p1_out(c1 * r_out, s1 * r_out, fHMerc, pxlCS);
763  const Point p2_out(c2 * r_out, s2 * r_out, fHMerc, pxlCS);
764 
765  // pixel position in telCS
766  const Point zeroPx(0,0,0, pxlCS);
767  const double pxl_x = zeroPx.GetX(fTelCS);
768  const double pxl_y = zeroPx.GetY(fTelCS);
769  const double pxl_z = zeroPx.GetZ(fTelCS);
770 
771  if (first) {
772  first = false;
773  xMin = pxl_x;
774  xMax = pxl_x;
775  yMin = pxl_y;
776  yMax = pxl_y;
777  zMin = pxl_z;
778  zMax = pxl_z;
779  } else {
780  if (pxl_x > xMax)
781  xMax = pxl_x;
782  if (pxl_y > yMax)
783  yMax = pxl_y;
784  if (pxl_z > zMax)
785  zMax = pxl_z;
786  if (pxl_x < xMin)
787  xMin = pxl_x;
788  if (pxl_y < yMin)
789  yMin = pxl_y;
790  if (pxl_z < zMin)
791  zMin = pxl_z;
792  }
793 
794  if (do3D) {
795 
796  /*TPolyMarker3D *p_pos = new TPolyMarker3D(1);
797  p_pos->SetPoint(0, pxl_x, pxl_y, pxl_z);
798  p_pos->SetMarkerColor(color++);
799  p_pos->SetMarkerStyle(20);
800  p_pos->SetMarkerSize(.3);
801  p_pos->Draw();
802  objs->AddLast(p_pos);*/
803 
804  } else {
805  //double w, h;
806  ostringstream pxl_txt;
807  pxl_txt << pixelId;
808  TLatex* const p_pos = new TLatex(pxl_x, pxl_y, pxl_txt.str().c_str());
809  p_pos->SetX(pxl_x - p_pos->GetXsize() / 6.);
810  p_pos->SetY(pxl_y - p_pos->GetYsize() / 6.);
811  p_pos->SetTextColor(1);
812  p_pos->SetTextSize(0.01);
813  p_pos->SetTextAngle(0);
814  p_pos->Draw();
815  objs->AddLast(p_pos);
816  }
817 
818  if (do3D) { // DO THE 3D PLOT
819 
820  TPolyLine3D* const l_in = new TPolyLine3D(1);
821  l_in->SetLineColor(2);
822  l_in->SetPoint(0, p1_in.GetX(fTelCS), p1_in.GetY(fTelCS), p1_in.GetZ(fTelCS));
823  l_in->SetPoint(1, p2_in.GetX(fTelCS), p2_in.GetY(fTelCS), p2_in.GetZ(fTelCS));
824  l_in->Draw();
825  objs->AddLast(l_in);
826 
827  TPolyLine3D* const l_out = new TPolyLine3D(1);
828  l_out->SetLineColor(1);
829  l_out->SetLineStyle(2);
830 
831  l_out->SetPoint(0, p1_out.GetX(fTelCS), p1_out.GetY(fTelCS), p1_out.GetZ(fTelCS));
832  l_out->SetPoint(1, p2_out.GetX(fTelCS), p2_out.GetY(fTelCS), p2_out.GetZ(fTelCS));
833  l_out->Draw();
834  objs->AddLast(l_out);
835 
836  TPolyLine3D* const l_corner = new TPolyLine3D(1);
837  l_corner->SetLineColor(1);
838  l_corner->SetLineStyle(2);
839 
840  l_corner->SetPoint(0, p1_in.GetX(fTelCS), p1_in.GetY(fTelCS), p1_in.GetZ(fTelCS));
841  l_corner->SetPoint(1, p1_out.GetX(fTelCS), p1_out.GetY(fTelCS), p1_out.GetZ(fTelCS));
842  l_corner->Draw();
843  objs->AddLast(l_corner);
844 
845  } else { // DO THE 2D PLOT
846 
847  TLine* const l_in = new TLine(p1_in.GetX(fTelCS), p1_in.GetY(fTelCS),
848  p2_in.GetX(fTelCS), p2_in.GetY(fTelCS));
849  l_in->SetLineColor(2);
850 
851  TLine* const l_out = new TLine(p1_out.GetX(fTelCS), p1_out.GetY(fTelCS),
852  p2_out.GetX(fTelCS), p2_out.GetY(fTelCS));
853  l_out->SetLineColor(1);
854  l_out->SetLineStyle(2);
855 
856  l_in->Draw();
857  l_out->Draw();
858  objs->AddLast(l_in);
859  objs->AddLast(l_out);
860 
861  }
862  }
863  }
864  }
865 
866  // the camera support
867 
868  const Point pS(0. ,0. ,0. , fCameraSupportCoordinateSystem);
869 
870  const double dx = 5*cm;
871  //double dy = 10*cm;
872  const double length = 2*m;
873 
874  for (int i = 0; i < 2; ++i) {
875 
876  const double y1 = 30*cm;
877  const double y2 = 30*cm + dx;
878  const double z1 = 0*cm;
879  const double z2 = 10*cm;
880  const double x1 = 0*cm;
881  const double x2 = length;
882 
883  TPolyLine3D* const up = new TPolyLine3D(4);
884  TPolyLine3D* const down = new TPolyLine3D(4);
885  up->SetLineColor(1);
886  up->SetLineWidth(2);
887  down->SetLineColor(1);
888  down->SetLineWidth(2);
889 
890  double y = 0;
891  double z = 0;
892  for (int iy = 0; iy < 2; ++iy) {
893 
894  if (iy == 0)
895  y = y1;
896  else
897  y = y2;
898 
899  if (i == 0)
900  y *= -1;
901 
902  for (int iz = 0; iz < (do3D ? 2 : 1); ++iz) {
903 
904  if (iz == 0)
905  z = z1;
906  else
907  z = z2;
908 
909  const Point p1(x1, y, z, fCameraSupportCoordinateSystem);
910  const Point p2(x2, y, z, fCameraSupportCoordinateSystem);
911 
912  if (do3D) { // DO THE 3D PLOT
913 
914  TPolyLine3D* const l = new TPolyLine3D(1);
915  l->SetLineColor(1);
916  l->SetLineWidth(2);
917  l->SetPoint(0, p1.GetX(fTelCS), p1.GetY(fTelCS), p1.GetZ(fTelCS));
918  l->SetPoint(1, p2.GetX(fTelCS), p2.GetY(fTelCS), p2.GetZ(fTelCS));
919  l->Draw();
920  objs->AddLast(l);
921 
922  up->SetPoint((1 - iy) * 2 + 1 - iz, p1.GetX(fTelCS), p1.GetY(fTelCS), p1.GetZ(fTelCS));
923  down->SetPoint((1 - iy) * 2 + 1 - iz, p2.GetX(fTelCS), p2.GetY(fTelCS), p2.GetZ(fTelCS));
924 
925  } else { // DO THE 2D PLOT
926 
927  TLine* const l = new TLine(p1.GetX(fTelCS), p1.GetY(fTelCS),
928  p2.GetX(fTelCS), p2.GetY(fTelCS));
929  l->SetLineColor(1);
930  l->SetLineWidth(1);
931  l->Draw();
932  objs->AddLast(l);
933 
934  //up = new TLine();
935  //down = new TLine();
936 
937  }
938 
939  }
940  }
941 
942  if (do3D) { // DO THE 3D PLOT
943  up->Draw();
944  objs->AddLast(up);
945  down->Draw();
946  objs->AddLast(down);
947  } else { // DO THE 2D PLOT
948  //up->Draw();
949  //down->Draw();
950  }
951  }
952 
953  return objs;
954 }
955 
std::vector< PhotonNormalPair > IntersectionList
Definition: /RTFunctions.h:47
constexpr double mm
Definition: AugerUnits.h:113
bool TraceSurf(const utl::Photon &photonIn, utl::Photon &photonOut)
HexagonDirection Hexagon(const double x, const double y, const double r)
const double degree
constexpr T Sqr(const T &x)
Point object.
Definition: Point.h:32
RTNext TraceShadow(const utl::Photon &photonIn, utl::Photon &photonOut, const bool doSupport=true)
Base class for all exceptions used in the auger offline code.
RandomEngineType & GetEngine()
Definition: RandomEngine.h:32
void Reflection(const utl::Photon &photonIn, const Vector &normal, utl::Photon &photonOut)
Definition: /RTFunctions.cc:33
double GetEta() const
Camera angular pixel spacing.
RTNext Trace(const utl::Photon &photonIn, utl::Photon &photonOut, int &nreflections, int &nbackscattered, int &col, int &row)
#define INFO(message)
Macro for logging informational messages.
Definition: ErrorLogger.h:161
double GetWeight() const
weight assigned to the photon
Definition: Photon.h:21
int debug
Definition: dump1090.h:276
double GetMercedesHeight() const
Height of the Mercedes.
void SetPosition(const utl::Point &p)
Definition: Photon.h:33
int Refraction(const double n12, const utl::Photon &photonIn, const Vector &normal, PhotonList &photonsOut)
const Camera & GetCamera() const
Get the Camera object that belongs to the telescope.
unsigned int GetFirstColumn() const
RTResult TraceMerc(const utl::CoordinateSystemPtr &pxlCS, const utl::Photon &photonIn, utl::Photon &photonOut, int &nreflections)
const Pixel & GetPixel(const unsigned int pixelId) const
Get Pixel by id, throw utl::NonExistentComponentException if n.a.
constexpr double deg
Definition: AugerUnits.h:140
boost::shared_ptr< const CoordinateTransformer > CoordinateSystemPtr
Shared pointer for coordinate systems.
void AddPoint(const utl::Point &p)
Definition: /RayTracer.cc:34
double GetX(const CoordinateSystemPtr &coordinateSystem) const
Definition: BasicVector.h:206
Wraps the random number engine used to generate distributions.
Definition: RandomEngine.h:27
void ConstructPlane(const int id, utl::Vector &n, utl::Point &p, const utl::CoordinateSystemPtr &pxlCS)
double abs(const SVector< n, T > &v)
constexpr double kSqrt3
Definition: MathConstants.h:31
void SetWeight(const double w)
source of the photons. Should use Eye::LightSource enum types
Definition: Photon.h:31
unsigned int GetLastRow() const
double eps
AxialVector Normalized(const AxialVector &v)
Definition: AxialVector.h:81
const utl::Vector & GetDirection() const
Definition: Photon.h:26
const utl::CoordinateSystemPtr & GetPixelCoordinateSystem() const
double GetMercedesBase() const
Base of the Mercedes.
double GetY(const CoordinateSystemPtr &coordinateSystem) const
Definition: BasicVector.h:209
double Plane(const utl::Point &point, const utl::Vector &normal, const utl::Photon &photonIn, utl::Photon &photonOut)
Definition: /RTFunctions.cc:81
Detector description interface for Telescope-related data.
Vector LambertDiffusion(utl::RandomEngine &rndm, const Vector &rayIn, const Vector &normal, const double amountOfStrayLight, const double MaxTheta)
constexpr double cm
Definition: AugerUnits.h:117
Vector object.
Definition: Vector.h:30
bool Sphere(const Point &origin, const double radius, const utl::Photon &photonIn, IntersectionList &intersection)
unsigned int GetLastColumn() const
std::vector< utl::Photon > PhotonList
Definition: /RTFunctions.h:35
double GetZ(const CoordinateSystemPtr &coordinateSystem) const
Definition: BasicVector.h:212
bool FindPixelId(const utl::Vector &incidentDir, int &row, int &col) const
#define ERROR(message)
Macro for logging error messages.
Definition: ErrorLogger.h:165
constexpr double m
Definition: AugerUnits.h:121
unsigned int GetFirstRow() const
void SetDirection(const utl::Vector &v)
Definition: Photon.h:34
Description of a camera.
const utl::Point & GetPosition() const
Definition: Photon.h:25

, generated on Tue Sep 26 2023.