source: branches/MarsMoreSimulationTruth/msimreflector/MSimReflector.cc@ 18795

Last change on this file since 18795 was 18449, checked in by ftemme, 10 years ago
Added an additional mirrortag, so that the information which mirror was hit is not lost later in the process
File size: 21.1 KB
Line 
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
68ClassImp(MSimReflector);
69
70using namespace std;
71
72// USEFUL CORSIKA OPTIONS:
73// NOCLONG
74
75// --------------------------------------------------------------------------
76//
77// Default Constructor.
78//
79MSimReflector::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//
93Int_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//
260Bool_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//
329Bool_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//
378Int_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//
438Int_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 // FTemme: As dat.fTag is later changed from mirror ID to pixel ID, here
535 // also dat.fMirrorTag is set to num:
536 dat->SetMirrorTag(num);
537
538 (*fMirror3)[cnt[3]++] = *dat;
539 //*static_cast<MPhotonData*>(cpy3.UncheckedAt(cnt[3]++)) = *dat;
540
541 // Propagate the photon along its trajectory to the focal plane z=F
542 p.PropagateZ(w, F);
543
544 // Store new position
545 dat->SetPosition(p);
546
547 (*fMirror4)[cnt[4]++] = *dat;
548 //*static_cast<MPhotonData*>(cpy4.UncheckedAt(cnt[4]++)) = *dat;
549
550 // FIXME: It make make sense to move this out of this class
551 // It is detector specific not reflector specific
552 // Discard all photons which definitly can not hit the detector surface
553 if (fDetectorMargin>=0 && !fGeomCam->HitDetector(p, fDetectorMargin))
554 continue;
555
556 // Copy this event to the next 'new' in the list
557 *static_cast<MPhotonData*>(arr.UncheckedAt(cnt[5]++)) = *dat;
558 }
559
560 // Now we shrink the array to a storable size (for details see
561 // MPhotonEvent::Shrink).
562 fMirror0->Shrink(cnt[0]);
563 //fMirror1->Shrink(cnt[1]);
564 fMirror2->Shrink(cnt[2]);
565 fMirror3->Shrink(cnt[3]);
566 fMirror4->Shrink(cnt[4]);
567 fEvt->Shrink(cnt[5]);
568
569 // Doesn't seem to be too time consuming. But we could also sort later!
570 // (after cones, inside the camera)
571 fEvt->Sort(kTRUE);
572
573 // FIXME FIXME FIXME: Set maxindex, first and last time.
574 // SetMaxIndex(fReflector->GetNumMirrors()-1)
575 // if (fEvt->GetNumPhotons())
576 // {
577 // SetTime(fEvt->GetFirst()->GetTime(), fEvt->GetLast()->GetTime());
578 // }
579
580 return kTRUE;
581}
582
583// --------------------------------------------------------------------------
584//
585// DetectorMargin: 0
586//
587Int_t MSimReflector::ReadEnv(const TEnv &env, TString prefix, Bool_t print)
588{
589 Bool_t rc = kFALSE;
590 if (IsEnvDefined(env, prefix, "DetectorFrame", print))
591 {
592 rc = kTRUE;
593 fDetectorFrame = GetEnvValue(env, prefix, "DetectorFrame", 0);
594 }
595 if (IsEnvDefined(env, prefix, "DetectorMargin", print))
596 {
597 rc = kTRUE;
598 fDetectorMargin = GetEnvValue(env, prefix, "DetectorMargin", 0);
599 }
600
601 return rc;
602}
Note: See TracBrowser for help on using the repository browser.