| 1 | /* ======================================================================== *\
 | 
|---|
| 2 | !
 | 
|---|
| 3 | ! *
 | 
|---|
| 4 | ! * This file is part of CheObs, the Modular Analysis and Reconstruction
 | 
|---|
| 5 | ! * Software. It is distributed to you in the hope that it can be a useful
 | 
|---|
| 6 | ! * and timesaving tool in analysing Data of imaging Cerenkov telescopes.
 | 
|---|
| 7 | ! * It is distributed WITHOUT ANY WARRANTY.
 | 
|---|
| 8 | ! *
 | 
|---|
| 9 | ! * Permission to use, copy, modify and distribute this software and its
 | 
|---|
| 10 | ! * documentation for any purpose is hereby granted without fee,
 | 
|---|
| 11 | ! * provided that the above copyright notice appears in all copies and
 | 
|---|
| 12 | ! * that both that copyright notice and this permission notice appear
 | 
|---|
| 13 | ! * in supporting documentation. It is provided "as is" without express
 | 
|---|
| 14 | ! * or implied warranty.
 | 
|---|
| 15 | ! *
 | 
|---|
| 16 | !
 | 
|---|
| 17 | !
 | 
|---|
| 18 | !   Author(s): Thomas Bretz,  1/2009 <mailto:tbretz@astro.uni-wuerzburg.de>
 | 
|---|
| 19 | !
 | 
|---|
| 20 | !   Copyright: CheObs Software Development, 2000-2010
 | 
|---|
| 21 | !
 | 
|---|
| 22 | !
 | 
|---|
| 23 | \* ======================================================================== */
 | 
|---|
| 24 | 
 | 
|---|
| 25 | //////////////////////////////////////////////////////////////////////////////
 | 
|---|
| 26 | //
 | 
|---|
| 27 | //  MSimReflector
 | 
|---|
| 28 | //
 | 
|---|
| 29 | //  fDetectorFrame is a radius in centimeter, defining a disk in the focal
 | 
|---|
| 30 | //  plane around the focal point, in which photons are absorbed. If
 | 
|---|
| 31 | //  fDetectorFrame<=0 the virtual HitFrame function of the camera
 | 
|---|
| 32 | //  geometry container is used instead.
 | 
|---|
| 33 | //
 | 
|---|
| 34 | //  fDetectorMargin is a margin (in mm) which is given to the
 | 
|---|
| 35 | //  MGeomCam::HitDetector. It should define a margin around the area
 | 
|---|
| 36 | //  defined in HitDetector on the focal plane in which photons are kept.
 | 
|---|
| 37 | //  Usually this can be 0 because photons not hitting the detector are
 | 
|---|
| 38 | //  obsolete except they can later be "moved" inside the detector, e.g.
 | 
|---|
| 39 | //  if you use MSimPSF to emulate a PSF by moving photons randomly
 | 
|---|
| 40 | //  on the focal plane. To switch off this check set detector margin to -1.
 | 
|---|
| 41 | //
 | 
|---|
| 42 | //////////////////////////////////////////////////////////////////////////////
 | 
|---|
| 43 | #include "MSimReflector.h"
 | 
|---|
| 44 | 
 | 
|---|
| 45 | #include <TMath.h>
 | 
|---|
| 46 | #include <TRandom.h>
 | 
|---|
| 47 | 
 | 
|---|
| 48 | #include "MGeomCam.h"
 | 
|---|
| 49 | 
 | 
|---|
| 50 | #include "MLog.h"
 | 
|---|
| 51 | #include "MLogManip.h"
 | 
|---|
| 52 | 
 | 
|---|
| 53 | #include "MParList.h"
 | 
|---|
| 54 | 
 | 
|---|
| 55 | #include "MQuaternion.h"
 | 
|---|
| 56 | #include "MMirror.h"
 | 
|---|
| 57 | #include "MReflector.h"
 | 
|---|
| 58 | #include "MReflection.h"
 | 
|---|
| 59 | 
 | 
|---|
| 60 | #include "MCorsikaEvtHeader.h"
 | 
|---|
| 61 | //#include "MCorsikaRunHeader.h"
 | 
|---|
| 62 | 
 | 
|---|
| 63 | #include "MPhotonEvent.h"
 | 
|---|
| 64 | #include "MPhotonData.h"
 | 
|---|
| 65 | 
 | 
|---|
| 66 | #include "MPointingPos.h"
 | 
|---|
| 67 | 
 | 
|---|
| 68 | ClassImp(MSimReflector);
 | 
|---|
| 69 | 
 | 
|---|
| 70 | using namespace std;
 | 
|---|
| 71 | 
 | 
|---|
| 72 | // USEFUL CORSIKA OPTIONS:
 | 
|---|
| 73 | //  NOCLONG
 | 
|---|
| 74 | 
 | 
|---|
| 75 | // --------------------------------------------------------------------------
 | 
|---|
| 76 | //
 | 
|---|
| 77 | //  Default Constructor.
 | 
|---|
| 78 | //
 | 
|---|
| 79 | MSimReflector::MSimReflector(const char* name, const char *title)
 | 
|---|
| 80 |     : fEvt(0), fMirror0(0), fMirror1(0), fMirror2(0), fMirror3(0),
 | 
|---|
| 81 |     fMirror4(0), /*fRunHeader(0),*/ fEvtHeader(0), fReflector(0),
 | 
|---|
| 82 |     fGeomCam(0), fPointing(0), fNameReflector("MReflector"),
 | 
|---|
| 83 |     fDetectorFrame(0), fDetectorMargin(0)
 | 
|---|
| 84 | {
 | 
|---|
| 85 |     fName  = name  ? name  : "MSimReflector";
 | 
|---|
| 86 |     fTitle = title ? title : "Task to calculate reflection os a mirror";
 | 
|---|
| 87 | }
 | 
|---|
| 88 | 
 | 
|---|
| 89 | // --------------------------------------------------------------------------
 | 
|---|
| 90 | //
 | 
|---|
| 91 | // Search for the necessary parameter containers.
 | 
|---|
| 92 | //
 | 
|---|
| 93 | Int_t MSimReflector::PreProcess(MParList *pList)
 | 
|---|
| 94 | {
 | 
|---|
| 95 |     fMirror0 = (MPhotonEvent*)pList->FindCreateObj("MPhotonEvent", "MirrorPlane0");
 | 
|---|
| 96 |     if (!fMirror0)
 | 
|---|
| 97 |         return kFALSE;
 | 
|---|
| 98 |     fMirror1 = (MPhotonEvent*)pList->FindCreateObj("MPhotonEvent", "MirrorPlane1");
 | 
|---|
| 99 |     if (!fMirror1)
 | 
|---|
| 100 |         return kFALSE;
 | 
|---|
| 101 |     fMirror2 = (MPhotonEvent*)pList->FindCreateObj("MPhotonEvent", "MirrorPlane2");
 | 
|---|
| 102 |     if (!fMirror2)
 | 
|---|
| 103 |         return kFALSE;
 | 
|---|
| 104 |     fMirror3 = (MPhotonEvent*)pList->FindCreateObj("MPhotonEvent", "MirrorPlane3");
 | 
|---|
| 105 |     if (!fMirror3)
 | 
|---|
| 106 |         return kFALSE;
 | 
|---|
| 107 |     fMirror4 = (MPhotonEvent*)pList->FindCreateObj("MPhotonEvent", "MirrorPlane4");
 | 
|---|
| 108 |     if (!fMirror4)
 | 
|---|
| 109 |         return kFALSE;
 | 
|---|
| 110 | 
 | 
|---|
| 111 |     fReflector = (MReflector*)pList->FindObject(fNameReflector, "MReflector");
 | 
|---|
| 112 |     if (!fReflector)
 | 
|---|
| 113 |     {
 | 
|---|
| 114 |         *fLog << err << fNameReflector << " [MReflector] not found..." << endl;
 | 
|---|
| 115 |         return kFALSE;
 | 
|---|
| 116 |     }
 | 
|---|
| 117 | 
 | 
|---|
| 118 |     if (fReflector->GetNumMirrors()==0)
 | 
|---|
| 119 |     {
 | 
|---|
| 120 |         *fLog << err << "ERROR - Reflector '" << fNameReflector << "' doesn't contain a single mirror." << endl;
 | 
|---|
| 121 |         return kFALSE;
 | 
|---|
| 122 |     }
 | 
|---|
| 123 | 
 | 
|---|
| 124 |     fGeomCam = (MGeomCam*)pList->FindObject(fNameGeomCam, "MGeomCam");
 | 
|---|
| 125 |     if (!fGeomCam)
 | 
|---|
| 126 |     {
 | 
|---|
| 127 |         if (!fNameGeomCam.IsNull())
 | 
|---|
| 128 |             *fLog << inf << fNameGeomCam << " [MGeomCam] not found..." << endl;
 | 
|---|
| 129 | 
 | 
|---|
| 130 |         fGeomCam = (MGeomCam*)pList->FindObject("MGeomCam");
 | 
|---|
| 131 |         if (!fGeomCam)
 | 
|---|
| 132 |         {
 | 
|---|
| 133 |             *fLog << err << "MGeomCam not found... aborting." << endl;
 | 
|---|
| 134 |             return kFALSE;
 | 
|---|
| 135 |         }
 | 
|---|
| 136 |     }
 | 
|---|
| 137 | 
 | 
|---|
| 138 |     fEvt = (MPhotonEvent*)pList->FindObject("MPhotonEvent");
 | 
|---|
| 139 |     if (!fEvt)
 | 
|---|
| 140 |     {
 | 
|---|
| 141 |         *fLog << err << "MPhotonEvent not found... aborting." << endl;
 | 
|---|
| 142 |         return kFALSE;
 | 
|---|
| 143 |     }
 | 
|---|
| 144 |     /*
 | 
|---|
| 145 |     fRunHeader = (MCorsikaRunHeader*)pList->FindObject("MCorsikaRunHeader");
 | 
|---|
| 146 |     if (!fRunHeader)
 | 
|---|
| 147 |     {
 | 
|---|
| 148 |         *fLog << err << "MCorsikaRunHeader not found... aborting." << endl;
 | 
|---|
| 149 |         return kFALSE;
 | 
|---|
| 150 |     }
 | 
|---|
| 151 |     */
 | 
|---|
| 152 |     fEvtHeader = (MCorsikaEvtHeader*)pList->FindObject("MCorsikaEvtHeader");
 | 
|---|
| 153 |     if (!fEvtHeader)
 | 
|---|
| 154 |     {
 | 
|---|
| 155 |         *fLog << err << "MCorsikaEvtHeader not found... aborting." << endl;
 | 
|---|
| 156 |         return kFALSE;
 | 
|---|
| 157 |     }
 | 
|---|
| 158 | 
 | 
|---|
| 159 |     fPointing = (MPointingPos*)pList->FindObject(/*"PointingCorsika",*/ "MPointingPos");
 | 
|---|
| 160 |     if (!fPointing)
 | 
|---|
| 161 |     {
 | 
|---|
| 162 |         *fLog << err << "MPointingPos not found... aborting." << endl;
 | 
|---|
| 163 |         return kFALSE;
 | 
|---|
| 164 |     }
 | 
|---|
| 165 | 
 | 
|---|
| 166 |     return kTRUE;
 | 
|---|
| 167 | }
 | 
|---|
| 168 | 
 | 
|---|
| 169 | // --------------------------------------------------------------------------
 | 
|---|
| 170 | //
 | 
|---|
| 171 | // The main point of calculating the reflection is to determine the
 | 
|---|
| 172 | // coincidence point of the particle trajectory on the mirror surface.
 | 
|---|
| 173 | //
 | 
|---|
| 174 | // If the position and the trajectory of a particle is known it is enough
 | 
|---|
| 175 | // to calculate the z-value of coincidence. x and y are then well defined.
 | 
|---|
| 176 | //
 | 
|---|
| 177 | //  Since the problem (mirror) has a rotational symmetry we only have to care
 | 
|---|
| 178 | //  about the distance from the z-axis.
 | 
|---|
| 179 | //
 | 
|---|
| 180 | // Given:
 | 
|---|
| 181 | //
 | 
|---|
| 182 | //    p:  position  vector of particle (z=0)
 | 
|---|
| 183 | //    u:  direction vector of particle
 | 
|---|
| 184 | //    F:  Focal distance of the mirror
 | 
|---|
| 185 | //
 | 
|---|
| 186 | //  We define:
 | 
|---|
| 187 | //
 | 
|---|
| 188 | //    q   :=   (px,    py   )
 | 
|---|
| 189 | //    v   :=   (ux/uz, uy/uz)
 | 
|---|
| 190 | //    r^2 := x^2 + y^2
 | 
|---|
| 191 | //
 | 
|---|
| 192 | //
 | 
|---|
| 193 | // Distance from z-axis:
 | 
|---|
| 194 | // ---------------------
 | 
|---|
| 195 | //
 | 
|---|
| 196 | //          q'        =  q - z*v        (z>0)
 | 
|---|
| 197 | //
 | 
|---|
| 198 | //    Calculate distance r (|q|)
 | 
|---|
| 199 | //
 | 
|---|
| 200 | //          r^2       = (px-z*ux)^2 + (py-z*uy)^2
 | 
|---|
| 201 | //          r^2       = px^2+py^2 + z^2*(ux^2+uy^2) - 2*z*(px*ux+py*uy)
 | 
|---|
| 202 | //          r^2       =   |q|^2   + z^2*|v|^2       - 2*z* q*v
 | 
|---|
| 203 | //
 | 
|---|
| 204 | //
 | 
|---|
| 205 | // Spherical Mirror Surface:  (distance of surface point from 0/0/0)
 | 
|---|
| 206 | // -------------------------
 | 
|---|
| 207 | //
 | 
|---|
| 208 | //   Sphere:  r^2 +   z^2    = R^2               | Parabola: z = p*r^2
 | 
|---|
| 209 | //   Mirror:  r^2 +  (z-R)^2 = R^2               | Mirror:   z = p*r^2
 | 
|---|
| 210 | //                                               |
 | 
|---|
| 211 | //    Focal length: F=R/2                        |  Focal length: F = 1/4p
 | 
|---|
| 212 | //                                               |
 | 
|---|
| 213 | //   r^2 + (z-2*F)^2 = (2*F)^2                   |           z = r^2/4F
 | 
|---|
| 214 | //                                               |
 | 
|---|
| 215 | //          z        = -sqrt(4*F*F - r*r) + 2*F  |
 | 
|---|
| 216 | //          z-2*F    = -sqrt(4*F*F - r*r)        |
 | 
|---|
| 217 | //         (z-2*F)^2 = 4*F*F - r*r               |
 | 
|---|
| 218 | //   z^2-4*F*z+4*F^2 = 4*F*F - r*r  (4F^2-r^2>0) |  z - r^2/4F = 0
 | 
|---|
| 219 | //   z^2-4*F*z+r^2   = 0
 | 
|---|
| 220 | //
 | 
|---|
| 221 | //    Find the z for which our particle has the same distance from the z-axis
 | 
|---|
| 222 | //    as the mirror surface.
 | 
|---|
| 223 | //
 | 
|---|
| 224 | //    substitute r^2
 | 
|---|
| 225 | //
 | 
|---|
| 226 | //
 | 
|---|
| 227 | // Equation to solve:
 | 
|---|
| 228 | // ------------------
 | 
|---|
| 229 | //
 | 
|---|
| 230 | //   z^2*(1+|v|^2) - 2*z*(2*F+q*v) + |q|^2 =  0  |  z^2*|v|^2 - 2*z*(2*F+q*v) + |q|^2 = 0
 | 
|---|
| 231 | //
 | 
|---|
| 232 | //                                   z = (-b +- sqrt(b*b - 4ac))/(2*a)
 | 
|---|
| 233 | //
 | 
|---|
| 234 | //              a =   1+|v|^2                    |             a = |v|^2
 | 
|---|
| 235 | //              b = - 2*b'  with  b' = 2*F+q*v   |             b = - 2*b'  with  b' = 2*F+q*v
 | 
|---|
| 236 | //              c =   |q|^2                      |             c = |q|^2
 | 
|---|
| 237 | //                                               |
 | 
|---|
| 238 | //
 | 
|---|
| 239 | //                                        substitute b := 2*b'
 | 
|---|
| 240 | //
 | 
|---|
| 241 | //                            z = (2*b' +- 2*sqrt(b'*b' - ac))/(2*a)
 | 
|---|
| 242 | //                            z = (  b' +-   sqrt(b'*b' - ac))/a
 | 
|---|
| 243 | //                            z = (b'/a +-   sqrt(b'*b' - ac))/a
 | 
|---|
| 244 | //
 | 
|---|
| 245 | //                                        substitute f := b'/a
 | 
|---|
| 246 | //
 | 
|---|
| 247 | //                                      z = f +- sqrt(f^2 - c/a)
 | 
|---|
| 248 | //
 | 
|---|
| 249 | // =======================================================================================
 | 
|---|
| 250 | //
 | 
|---|
| 251 | // After z of the incident point has been determined the position p is
 | 
|---|
| 252 | // propagated along u to the plane with z=z. Now it is checked if the
 | 
|---|
| 253 | // mirror was really hit (this is implemented in HasHit).
 | 
|---|
| 254 | // From the position on the surface and the mirrors curvature we can
 | 
|---|
| 255 | // now calculate the normal vector at the incident point.
 | 
|---|
| 256 | // This normal vector is smeared out with MMirror::PSF (basically a
 | 
|---|
| 257 | // random gaussian) and then the trajectory is reflected on the
 | 
|---|
| 258 | // resulting normal vector.
 | 
|---|
| 259 | //
 | 
|---|
| 260 | Bool_t MMirror::ExecuteReflection(MQuaternion &p, MQuaternion &u) const
 | 
|---|
| 261 | {
 | 
|---|
| 262 |     // If the z-componenet of the direction vector is normalized to 1
 | 
|---|
| 263 |     // the calculation of the incident points becomes very simple and
 | 
|---|
| 264 |     // the resulting z is just the z-coordinate of the incident point.
 | 
|---|
| 265 |     const TVector2 v(u.XYvector()/u.Z());
 | 
|---|
| 266 |     const TVector2 q(p.XYvector());
 | 
|---|
| 267 | 
 | 
|---|
| 268 |     // Radius of curvature
 | 
|---|
| 269 |     const Double_t G = 2*fFocalLength;
 | 
|---|
| 270 | 
 | 
|---|
| 271 |     // Find the incident point of the vector to the mirror
 | 
|---|
| 272 |     // u corresponds to downward going particles, thus we use -u here
 | 
|---|
| 273 |     const Double_t b = G - q*v;
 | 
|---|
| 274 |     const Double_t a = v.Mod2();
 | 
|---|
| 275 |     const Double_t c = q.Mod2();
 | 
|---|
| 276 | 
 | 
|---|
| 277 |     // Solution for q spherical (a+1) (parabolic mirror (a) instead of (a+1))
 | 
|---|
| 278 |     const Double_t A = fShape ? a : a+1;
 | 
|---|
| 279 | 
 | 
|---|
| 280 |     const Double_t f = b/A;
 | 
|---|
| 281 |     const Double_t g = c/A;
 | 
|---|
| 282 | 
 | 
|---|
| 283 |     // Solution of second order polynomial (transformed: a>0)
 | 
|---|
| 284 |     // (The second solution can be omitted, it is the intersection
 | 
|---|
| 285 |     //  with the upper part of the sphere)
 | 
|---|
| 286 |     const Double_t z = a==0 ? c/(2*b) : f - TMath::Sqrt(f*f - g);
 | 
|---|
| 287 | 
 | 
|---|
| 288 |     // Move the photon along its trajectory to the x/y plane of the
 | 
|---|
| 289 |     // mirror's coordinate frame. Therefor stretch the vector
 | 
|---|
| 290 |     // until its z-component is the distance from the vector origin
 | 
|---|
| 291 |     // until the vector hits the mirror surface.
 | 
|---|
| 292 |     // p += z/u.Z()*u;
 | 
|---|
| 293 |     // p is at the mirror plane and we want to propagate back to the mirror surface
 | 
|---|
| 294 |     p.PropagateZ(u, z);
 | 
|---|
| 295 | 
 | 
|---|
| 296 |     // MirrorShape: Now check if the photon really hit the mirror or just missed it
 | 
|---|
| 297 |     if (!HasHit(p))
 | 
|---|
| 298 |         return kFALSE;
 | 
|---|
| 299 | 
 | 
|---|
| 300 |     // Get normal vector for reflection by calculating the derivatives
 | 
|---|
| 301 |     // of a the mirror's surface along x and y
 | 
|---|
| 302 |     const Double_t d = fShape ? G : TMath::Sqrt(G*G - p.R2());
 | 
|---|
| 303 | 
 | 
|---|
| 304 |     // The solution for the normal vector is
 | 
|---|
| 305 |     //    TVector3 n(-p.X()/d, -p.Y()/d, 1));
 | 
|---|
| 306 |     // Since the normal vector doesn't need to be of normal
 | 
|---|
| 307 |     // length we can avoid an obsolete division
 | 
|---|
| 308 |     TVector3 n(p.X(), p.Y(), -d);
 | 
|---|
| 309 | 
 | 
|---|
| 310 |     if (fSigmaPSF>0)
 | 
|---|
| 311 |         n += SimPSF(n);
 | 
|---|
| 312 | 
 | 
|---|
| 313 |     // Changes also the sign of the z-direction of flight
 | 
|---|
| 314 |     // This is faster giving identical results
 | 
|---|
| 315 |     u *= MReflection(n);
 | 
|---|
| 316 |     //u *= MReflection(p.X(), p.Y(), -d);
 | 
|---|
| 317 | 
 | 
|---|
| 318 |     return kTRUE;
 | 
|---|
| 319 | }
 | 
|---|
| 320 | 
 | 
|---|
| 321 | // --------------------------------------------------------------------------
 | 
|---|
| 322 | //
 | 
|---|
| 323 | // Converts the coordinates into the coordinate frame of the mirror.
 | 
|---|
| 324 | // Executes the reflection calling ExecuteReflection and converts
 | 
|---|
| 325 | // the coordinates back.
 | 
|---|
| 326 | // Depending on whether the mirror was hit kTRUE or kFALSE is returned.
 | 
|---|
| 327 | // It the mirror was not hit the result coordinates are wrong.
 | 
|---|
| 328 | //
 | 
|---|
| 329 | Bool_t MMirror::ExecuteMirror(MQuaternion &p, MQuaternion &u) const
 | 
|---|
| 330 | {
 | 
|---|
| 331 |     // Move the mirror to the point of origin and rotate the position into
 | 
|---|
| 332 |     // the individual mirrors coordinate frame.
 | 
|---|
| 333 |     // Rotate the direction vector into the mirror's coordinate frame
 | 
|---|
| 334 |     p -= fPos;
 | 
|---|
| 335 |     p *= fTilt;
 | 
|---|
| 336 |     u *= fTilt;
 | 
|---|
| 337 | 
 | 
|---|
| 338 |     // Move the photon along its trajectory to the x/y plane of the
 | 
|---|
| 339 |     // mirror's coordinate frame. Therefor stretch the vector
 | 
|---|
| 340 |     // until its z-component vanishes.
 | 
|---|
| 341 |     //p -= p.Z()/u.Z()*u;
 | 
|---|
| 342 | 
 | 
|---|
| 343 |     // p is at the reflector plane and we want to propagate back to the mirror plane
 | 
|---|
| 344 |     p.PropagateZ0(u);
 | 
|---|
| 345 | 
 | 
|---|
| 346 |     // Now try to  propagate the photon from the plane to the mirror
 | 
|---|
| 347 |     // and reflect its direction vector on the mirror.
 | 
|---|
| 348 |     if (!ExecuteReflection(p, u))
 | 
|---|
| 349 |         return kFALSE;
 | 
|---|
| 350 | 
 | 
|---|
| 351 |     // Derotate from mirror coordinates and shift the photon back to
 | 
|---|
| 352 |     // reflector coordinates.
 | 
|---|
| 353 |     // Derotate the direction vector
 | 
|---|
| 354 |     u *= fTilt.Inverse();
 | 
|---|
| 355 |     p *= fTilt.Inverse();
 | 
|---|
| 356 |     p += fPos;
 | 
|---|
| 357 | 
 | 
|---|
| 358 |     return kTRUE;
 | 
|---|
| 359 | }
 | 
|---|
| 360 | 
 | 
|---|
| 361 | // Jeder Spiegel sollte eine Liste aller andern Spiegel in der
 | 
|---|
| 362 | // reihenfolge Ihrer Entfernung enthalten. Wir starten mit der Suche
 | 
|---|
| 363 | // immer beim zuletzt getroffenen Spiegel!
 | 
|---|
| 364 | //
 | 
|---|
| 365 | // --------------------------------------------------------------------------
 | 
|---|
| 366 | //
 | 
|---|
| 367 | // Loops over all mirrors of the reflector. After doing a rough check
 | 
|---|
| 368 | // whether the mirror can be hit at all the reflection is executed
 | 
|---|
| 369 | // calling the ExecuteMirror function of the mirrors.
 | 
|---|
| 370 | //
 | 
|---|
| 371 | // If a mirror was hit its index is retuened, -1 otherwise.
 | 
|---|
| 372 | //
 | 
|---|
| 373 | // FIXME: Do to lopping over all mirrors for all photons this is the
 | 
|---|
| 374 | // most time consuming function in teh reflector simulation. By a more
 | 
|---|
| 375 | // intelligent way of finding the right mirror then just testing all
 | 
|---|
| 376 | // this could be accelerated a lot.
 | 
|---|
| 377 | //
 | 
|---|
| 378 | Int_t MReflector::ExecuteReflector(MQuaternion &p, MQuaternion &u) const
 | 
|---|
| 379 | {
 | 
|---|
| 380 |     //static const TObjArray *arr = &((MMirror*)fMirrors[0])->fNeighbors;
 | 
|---|
| 381 | 
 | 
|---|
| 382 |     // This way of access is somuch faster than the program is
 | 
|---|
| 383 |     // a few percent slower if accessed by UncheckedAt
 | 
|---|
| 384 |     const MMirror **s = GetFirstPtr();
 | 
|---|
| 385 |     const MMirror **e = s+GetNumMirrors();
 | 
|---|
| 386 |     //const MMirror **s = (const MMirror**)fMirrors.GetObjectRef(0);
 | 
|---|
| 387 |     //const MMirror **e = s+fMirrors.GetEntriesFast();
 | 
|---|
| 388 |     //const MMirror **s = (const MMirror**)arr->GetObjectRef(0);
 | 
|---|
| 389 |     //const MMirror **e = s+arr->GetEntriesFast();
 | 
|---|
| 390 | 
 | 
|---|
| 391 |     // Loop over all mirrors
 | 
|---|
| 392 |     for (const MMirror **m=s; m<e; m++)
 | 
|---|
| 393 |     {
 | 
|---|
| 394 |         const MMirror &mirror = **m;
 | 
|---|
| 395 | 
 | 
|---|
| 396 |         // FIXME: Can we speed up using lookup tables or
 | 
|---|
| 397 |         //        indexed tables?
 | 
|---|
| 398 | 
 | 
|---|
| 399 |         // MirrorShape: Check if this mirror can be hit at all
 | 
|---|
| 400 |         // This is to avoid time consuming calculation if there is no
 | 
|---|
| 401 |         // chance of a coincidence.
 | 
|---|
| 402 |         // FIXME: Inmprove search algorithm (2D Binary search?)
 | 
|---|
| 403 |         if (!mirror.CanHit(p))
 | 
|---|
| 404 |             continue;
 | 
|---|
| 405 | 
 | 
|---|
| 406 |         // Make a local copy of position and direction which can be
 | 
|---|
| 407 |         // changed by ExecuteMirror.
 | 
|---|
| 408 |         MQuaternion q(p);
 | 
|---|
| 409 |         MQuaternion v(u);
 | 
|---|
| 410 | 
 | 
|---|
| 411 |         // Check if this mirror is hit, and if it is hit return
 | 
|---|
| 412 |         // the reflected position and direction vector.
 | 
|---|
| 413 |         // If the mirror is missed we go on with the next mirror.
 | 
|---|
| 414 |         if (!mirror.ExecuteMirror(q, v))
 | 
|---|
| 415 |             continue;
 | 
|---|
| 416 | 
 | 
|---|
| 417 |         // We hit a mirror. Restore the local copy of position and
 | 
|---|
| 418 |         // direction back into p und u.
 | 
|---|
| 419 |         p = q;
 | 
|---|
| 420 |         u = v;
 | 
|---|
| 421 | 
 | 
|---|
| 422 |         //arr = &mirror->fNeighbors;
 | 
|---|
| 423 | 
 | 
|---|
| 424 |         return m-s;
 | 
|---|
| 425 |     }
 | 
|---|
| 426 | 
 | 
|---|
| 427 |     return -1;
 | 
|---|
| 428 | }
 | 
|---|
| 429 | 
 | 
|---|
| 430 | // --------------------------------------------------------------------------
 | 
|---|
| 431 | //
 | 
|---|
| 432 | // Converts the photons into the telscope coordinate frame using the
 | 
|---|
| 433 | // pointing position from MPointingPos.
 | 
|---|
| 434 | //
 | 
|---|
| 435 | // Reflects all photons on all mirrors and stores the final photons on
 | 
|---|
| 436 | // the focal plane. Also intermediate photons are stored for debugging.
 | 
|---|
| 437 | //
 | 
|---|
| 438 | Int_t MSimReflector::Process()
 | 
|---|
| 439 | {
 | 
|---|
| 440 |     // Get arrays from event container
 | 
|---|
| 441 |     TClonesArray &arr  = fEvt->GetArray();
 | 
|---|
| 442 | 
 | 
|---|
| 443 |     // Because we knwo in advance what the maximum storage space could
 | 
|---|
| 444 |     // be we allocated it in advance (or shrink it if it was extremely
 | 
|---|
| 445 |     // huge before)
 | 
|---|
| 446 |     // Note, that the drawback is that an extremly large event
 | 
|---|
| 447 |     //       will take about five times its storage space
 | 
|---|
| 448 |     //       for a moment even if a lot from it is unused.
 | 
|---|
| 449 |     //       It will be freed in the next step.
 | 
|---|
| 450 |     fMirror0->Resize(arr.GetEntriesFast()); // Free memory of allocated MPhotonData
 | 
|---|
| 451 |     fMirror2->Resize(arr.GetEntriesFast()); // Free memory of allocated MPhotonData
 | 
|---|
| 452 |     fMirror3->Resize(arr.GetEntriesFast()); // Free memory of allocated MPhotonData
 | 
|---|
| 453 |     fMirror4->Resize(arr.GetEntriesFast()); // Free memory of allocated MPhotonData
 | 
|---|
| 454 | 
 | 
|---|
| 455 |     // Initialize mirror properties
 | 
|---|
| 456 |     const Double_t F = fGeomCam->GetCameraDist()*100; // Focal length [cm]
 | 
|---|
| 457 | 
 | 
|---|
| 458 |     // Local sky coordinates (direction of telescope axis)
 | 
|---|
| 459 |     const Double_t zd = fPointing->GetZdRad();  // x==north
 | 
|---|
| 460 |     const Double_t az = fPointing->GetAzRad();
 | 
|---|
| 461 | 
 | 
|---|
| 462 |     // Rotation matrix to derotate sky
 | 
|---|
| 463 |     // For the new coordinate system see the Wiki
 | 
|---|
| 464 |     TRotation rot;    // The signs are positive because we align the incident point on ground to the telescope axis
 | 
|---|
| 465 |     rot.RotateZ( az); // Rotate point on ground to align it with the telescope axis
 | 
|---|
| 466 |     rot.RotateX(-zd); // tilt the point from ground to make it parallel to the mirror plane
 | 
|---|
| 467 | 
 | 
|---|
| 468 |     // Now get the impact point from Corsikas output
 | 
|---|
| 469 |     const TVector3 impact(fEvtHeader->GetX(), fEvtHeader->GetY(), 0);
 | 
|---|
| 470 | 
 | 
|---|
| 471 |     // Counter for number of total and final events
 | 
|---|
| 472 |     UInt_t cnt[6] = { 0, 0, 0, 0, 0, 0 };
 | 
|---|
| 473 | 
 | 
|---|
| 474 |     const Int_t num = arr.GetEntriesFast();
 | 
|---|
| 475 |     for (Int_t idx=0; idx<num; idx++)
 | 
|---|
| 476 |     {
 | 
|---|
| 477 |         MPhotonData *dat = static_cast<MPhotonData*>(arr.UncheckedAt(idx));
 | 
|---|
| 478 | 
 | 
|---|
| 479 |         // w is pointing away from the direction the photon comes from
 | 
|---|
| 480 |         // CORSIKA-orig: x(north), y(west),  z(up), t(time)
 | 
|---|
| 481 |         // NOW:          x(east),  y(north), z(up), t(time)
 | 
|---|
| 482 |         MQuaternion p(dat->GetPosQ());  // z=0
 | 
|---|
| 483 |         MQuaternion w(dat->GetDirQ());  // z<0
 | 
|---|
| 484 | 
 | 
|---|
| 485 |         // Shift the coordinate system to the telescope. Corsika's
 | 
|---|
| 486 |         // coordinate system is always w.r.t. to the particle axis
 | 
|---|
| 487 |         p -= impact;
 | 
|---|
| 488 | 
 | 
|---|
| 489 |         // Rotate the coordinates into the reflector's coordinate system.
 | 
|---|
| 490 |         // It is assumed that the z-plane is parallel to the focal plane.
 | 
|---|
| 491 |         // (The reflector coordinate system is defined by the telescope orientation)
 | 
|---|
| 492 |         p *= rot;
 | 
|---|
| 493 |         w *= rot;
 | 
|---|
| 494 | 
 | 
|---|
| 495 |         // ---> Simulate star-light!
 | 
|---|
| 496 |         // w.fVectorPart.SetXYZ(0.2/17, 0.2/17, -(1-TMath::Hypot(0.3, 0.2)/17));
 | 
|---|
| 497 | 
 | 
|---|
| 498 |         // Now propagate the photon to the z-plane in the new coordinate system
 | 
|---|
| 499 |         p.PropagateZ0(w);
 | 
|---|
| 500 | 
 | 
|---|
| 501 |         // Store new position and direction in the reflector's coordinate frame
 | 
|---|
| 502 |         dat->SetPosition(p); 
 | 
|---|
| 503 |         dat->SetDirection(w);
 | 
|---|
| 504 | 
 | 
|---|
| 505 |         (*fMirror0)[cnt[0]++] = *dat;
 | 
|---|
| 506 |         //*static_cast<MPhotonData*>(cpy0.UncheckedAt(cnt[0]++)) = *dat;
 | 
|---|
| 507 | 
 | 
|---|
| 508 |         // Check if the photon has hit the camera housing and holding
 | 
|---|
| 509 |         if (fGeomCam->HitFrame(p, w, fDetectorFrame))
 | 
|---|
| 510 |             continue;
 | 
|---|
| 511 | 
 | 
|---|
| 512 |         // FIXME: Do we really need this one??
 | 
|---|
| 513 |         //(*fMirror1)[cnt[1]++] = *dat;
 | 
|---|
| 514 |         //*static_cast<MPhotonData*>(cpy1.UncheckedAt(cnt[1]++)) = *dat;
 | 
|---|
| 515 | 
 | 
|---|
| 516 |         // Check if the reflector can be hit at all
 | 
|---|
| 517 |         if (!fReflector->CanHit(p))
 | 
|---|
| 518 |             continue;
 | 
|---|
| 519 | 
 | 
|---|
| 520 |         (*fMirror2)[cnt[2]++] = *dat;
 | 
|---|
| 521 |         //*static_cast<MPhotonData*>(cpy2.UncheckedAt(cnt[2]++)) = *dat;
 | 
|---|
| 522 | 
 | 
|---|
| 523 |         // Now execute the reflection of the photon on the mirrors' surfaces
 | 
|---|
| 524 |         const Int_t num = fReflector->ExecuteReflector(p, w);
 | 
|---|
| 525 |         if (num<0)
 | 
|---|
| 526 |             continue;
 | 
|---|
| 527 | 
 | 
|---|
| 528 |         // Set new position and direction (w.r.t. to the reflector's coordinate system)
 | 
|---|
| 529 |         // Set also the index of the mirror which was hit as tag.
 | 
|---|
| 530 |         dat->SetTag(num);
 | 
|---|
| 531 |         dat->SetPosition(p);
 | 
|---|
| 532 |         dat->SetDirection(w);
 | 
|---|
| 533 | 
 | 
|---|
| 534 |         (*fMirror3)[cnt[3]++] = *dat;
 | 
|---|
| 535 |         //*static_cast<MPhotonData*>(cpy3.UncheckedAt(cnt[3]++)) = *dat;
 | 
|---|
| 536 | 
 | 
|---|
| 537 |         // Propagate the photon along its trajectory to the focal plane z=F
 | 
|---|
| 538 |         p.PropagateZ(w, F);
 | 
|---|
| 539 | 
 | 
|---|
| 540 |         // Store new position
 | 
|---|
| 541 |         dat->SetPosition(p);
 | 
|---|
| 542 | 
 | 
|---|
| 543 |         (*fMirror4)[cnt[4]++] = *dat;
 | 
|---|
| 544 |         //*static_cast<MPhotonData*>(cpy4.UncheckedAt(cnt[4]++)) = *dat;
 | 
|---|
| 545 | 
 | 
|---|
| 546 |         // FIXME: It make make sense to move this out of this class
 | 
|---|
| 547 |         // It is detector specific not reflector specific
 | 
|---|
| 548 |         // Discard all photons which definitly can not hit the detector surface
 | 
|---|
| 549 |         if (fDetectorMargin>=0 && !fGeomCam->HitDetector(p, fDetectorMargin))
 | 
|---|
| 550 |             continue;
 | 
|---|
| 551 | 
 | 
|---|
| 552 |         // Copy this event to the next 'new' in the list
 | 
|---|
| 553 |         *static_cast<MPhotonData*>(arr.UncheckedAt(cnt[5]++)) = *dat;
 | 
|---|
| 554 |     }
 | 
|---|
| 555 | 
 | 
|---|
| 556 |     // Now we shrink the array to a storable size (for details see
 | 
|---|
| 557 |     // MPhotonEvent::Shrink).
 | 
|---|
| 558 |     fMirror0->Shrink(cnt[0]);
 | 
|---|
| 559 |     //fMirror1->Shrink(cnt[1]);
 | 
|---|
| 560 |     fMirror2->Shrink(cnt[2]);
 | 
|---|
| 561 |     fMirror3->Shrink(cnt[3]);
 | 
|---|
| 562 |     fMirror4->Shrink(cnt[4]);
 | 
|---|
| 563 |     fEvt->Shrink(cnt[5]);
 | 
|---|
| 564 | 
 | 
|---|
| 565 |     // Doesn't seem to be too time consuming. But we could also sort later!
 | 
|---|
| 566 |     //  (after cones, inside the camera)
 | 
|---|
| 567 |     fEvt->Sort(kTRUE);
 | 
|---|
| 568 | 
 | 
|---|
| 569 |     // FIXME FIXME FIXME: Set maxindex, first and last time.
 | 
|---|
| 570 |     // SetMaxIndex(fReflector->GetNumMirrors()-1)
 | 
|---|
| 571 |     // if (fEvt->GetNumPhotons())
 | 
|---|
| 572 |     // {
 | 
|---|
| 573 |     //    SetTime(fEvt->GetFirst()->GetTime(), fEvt->GetLast()->GetTime());
 | 
|---|
| 574 |     // }
 | 
|---|
| 575 | 
 | 
|---|
| 576 |     return kTRUE;
 | 
|---|
| 577 | }
 | 
|---|
| 578 | 
 | 
|---|
| 579 | // --------------------------------------------------------------------------
 | 
|---|
| 580 | //
 | 
|---|
| 581 | // DetectorMargin: 0
 | 
|---|
| 582 | //
 | 
|---|
| 583 | Int_t MSimReflector::ReadEnv(const TEnv &env, TString prefix, Bool_t print)
 | 
|---|
| 584 | {
 | 
|---|
| 585 |     Bool_t rc = kFALSE;
 | 
|---|
| 586 |     if (IsEnvDefined(env, prefix, "DetectorFrame", print))
 | 
|---|
| 587 |     {
 | 
|---|
| 588 |         rc = kTRUE;
 | 
|---|
| 589 |         fDetectorFrame = GetEnvValue(env, prefix, "DetectorFrame", 0);
 | 
|---|
| 590 |     }
 | 
|---|
| 591 |     if (IsEnvDefined(env, prefix, "DetectorMargin", print))
 | 
|---|
| 592 |     {
 | 
|---|
| 593 |         rc = kTRUE;
 | 
|---|
| 594 |         fDetectorMargin = GetEnvValue(env, prefix, "DetectorMargin", 0);
 | 
|---|
| 595 |     }
 | 
|---|
| 596 | 
 | 
|---|
| 597 |     return rc;
 | 
|---|
| 598 | }
 | 
|---|