source: trunk/MagicSoft/Mars/msimreflector/MSimReflector.cc@ 9243

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