source: trunk/MagicSoft/Mars/mastro/MAstroCamera.cc@ 4071

Last change on this file since 4071 was 4058, checked in by tbretz, 20 years ago
*** empty log message ***
File size: 16.1 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, 3/2004 <mailto:tbretz@astro.uni-wuerzburg.de>
19!
20! Copyright: MAGIC Software Development, 2000-2004
21!
22!
23\* ======================================================================== */
24
25/////////////////////////////////////////////////////////////////////////////
26//
27// MAstroCamera
28// ============
29//
30// A tools displaying stars from a catalog in the camera display.
31// PRELIMINARY!!
32//
33//
34// Usage:
35// ------
36// For a usage example see macros/starfield.C
37//
38// To be able to reflect the star-light you need the geometry of the
39// mirror and the distance of the plain screen.
40//
41// You can get the mirror geometry from a MC file and the distance of
42// the screen from MGeomCam.
43//
44//
45// Algorithm:
46// ----------
47// The caluclation of the position of the reflection in the camera is
48// done by:
49// - Rotation of the star-field such that the camera is looking into
50// the pointing direction
51// - Calculation of the reflected star-light vector by calling
52// MGeomMirror::GetReflection (which returns the point at which
53// the vector hits the camera plain)
54// - Depending on the draw-option you get each reflected point, the
55// reflection on a virtual ideal mirror or the reflection on each
56// individual mirror
57//
58//
59// GUI:
60// ----
61// * You can use the the cursor keys to change the pointing position
62// and plus/minus to change the time by a quarter of an hour.
63//
64// ToDo:
65// -----
66// * possibility to overwrite distance from mirror to screen
67// * read the mirror geometry directly from the MC input file
68//
69/////////////////////////////////////////////////////////////////////////////
70#include "MAstroCamera.h"
71
72#include <errno.h> // strerror
73#include <fstream> // ifstream
74
75#include <KeySymbols.h> // kKey_*
76
77#include <TH2.h> // TH2D
78#include <TMarker.h> // TMarker
79#include <TVirtualPad.h> // gPad
80
81#include "MLog.h"
82#include "MLogManip.h"
83
84#include "MGeomCam.h"
85#include "MGeomMirror.h"
86
87#include "MTime.h"
88#include "MAstroSky2Local.h"
89#include "MObservatory.h"
90
91#include "../mhist/MHCamera.h" // FIXME: This dependancy is very bad!
92 // HOW TO GET RID OF IT? Move MHCamera to mgeom?
93
94//#include "MStarLocalPos.h"
95
96ClassImp(MAstroCamera);
97
98using namespace std;
99
100// --------------------------------------------------------------------------
101//
102// Create a virtual MGeomMirror which is in the center of the coordinate
103// system and has a normal vector in z-direction.
104//
105MAstroCamera::MAstroCamera() : fGeom(0), fMirrors(0)
106{
107 fMirror0 = new MGeomMirror;
108 fMirror0->SetMirrorContent(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1);
109}
110
111// --------------------------------------------------------------------------
112//
113// Delete fGeom, fMirrors and the virtual 0-Mirror fMirror0
114//
115MAstroCamera::~MAstroCamera()
116{
117 if (fGeom)
118 delete fGeom;
119 if (fMirrors)
120 delete fMirrors;
121
122 delete fMirror0;
123
124}
125
126// --------------------------------------------------------------------------
127//
128// Set a list of mirrors. The Mirrors must be of type MGeomMirror and
129// stored in a TClonesArray
130//
131void MAstroCamera::SetMirrors(TClonesArray &arr)
132{
133 if (arr.GetClass()!=MGeomMirror::Class())
134 {
135 cout << "ERROR - TClonesArray doesn't contain objects of type MGeomMirror... ignored." << endl;
136 return;
137 }
138
139 const Int_t n = arr.GetSize();
140
141 if (!fMirrors)
142 fMirrors = new TClonesArray(MGeomMirror::Class(), n);
143
144 fMirrors->ExpandCreate(n);
145
146 for (int i=0; i<n; i++)
147 memcpy((*fMirrors)[i], arr[i], sizeof(MGeomMirror));
148
149}
150
151// --------------------------------------------------------------------------
152//
153// Read the mirror geometry from a MC .def file. The following
154// structure is expected:
155//
156// #* TYPE=1 (MAGIC)
157// #* i f sx sy x y z thetan phin
158// #*
159// #* i : number of the mirror
160// #* f : focal distance of that mirror
161// #* sx : curvilinear coordinate of mirror's center in X[cm]
162// #* sy : curvilinear coordinate of mirror's center in X[cm]
163// #* x : x coordinate of the center of the mirror [cm]
164// #* y : y coordinate of the center of the mirror [cm]
165// #* z : z coordinate of the center of the mirror [cm]
166// #* thetan : polar theta angle of the direction where the mirror points to
167// #* phin : polar phi angle of the direction where the mirror points to
168// #* xn : xn coordinate of the normal vector in the center (normalized)
169// #* yn : yn coordinate of the normal vector in the center (normalized)
170// #* zn : zn coordinate of the normal vector in the center (normalized)
171// #
172// define_mirrors
173// 1 1700.9200 25.0002 75.0061 25.0000 75.0000 0.9207 0.02328894 1.24904577 -0.00736394 -0.02209183 0.99972882
174// 2 ...
175//
176void MAstroCamera::SetMirrors(const char *fname)
177{
178 ifstream fin(fname);
179 if (!fin)
180 {
181 gLog << err << "Cannot open file " << fname << ": ";
182 gLog << strerror(errno) << endl;
183 return;
184 }
185
186 TString line;
187 while (1)
188 {
189 line.ReadLine(fin);
190 if (!fin)
191 return;
192
193 line = line.Strip(TString::kBoth);
194
195 if (line.BeginsWith("n_mirrors"))
196 {
197 Int_t n;
198 sscanf(line.Data(), "%*s %d", &n);
199
200 if (!fMirrors)
201 fMirrors = new TClonesArray(MGeomMirror::Class(), n);
202
203 fMirrors->ExpandCreate(n);
204 continue;
205 }
206
207
208 Int_t id;
209 Float_t f, sx, sy, x, y, z, thetan, phin, xn, yn, zn;
210
211 const Int_t n = sscanf(line.Data(), "%d %f %f %f %f %f %f %f %f %f %f %f",
212 &id, &f, &sx, &sy, &x, &y, &z, &thetan,
213 &phin, &xn, &yn, &zn);
214 if (n!=12)
215 continue;
216
217 new ((*fMirrors)[id-1]) MGeomMirror;
218 ((MGeomMirror*)(*fMirrors)[id-1])->SetMirrorContent(id, f, sx, sy, x, y, z, thetan, phin, xn, yn, zn);
219 }
220}
221
222// --------------------------------------------------------------------------
223//
224// Set the camera geometry. The MGeomCam object is cloned.
225//
226void MAstroCamera::SetGeom(const MGeomCam &cam)
227{
228 if (fGeom)
229 delete fGeom;
230
231 fGeom = (MGeomCam*)cam.Clone();
232}
233
234// --------------------------------------------------------------------------
235//
236// Convert To Pad coordinates (see MAstroCatalog)
237//
238Int_t MAstroCamera::ConvertToPad(const TVector3 &w, TVector2 &v) const
239{
240 /*
241 --- Use this to plot the 'mean grid' instead of the grid of a
242 theoretical central mirror ---
243
244 TVector3 spot;
245 const Int_t num = fConfig->GetNumMirror();
246 for (int i=0; i<num; i++)
247 spot += fConfig->GetMirror(i).GetReflection(w, fGeom->GetCameraDist())*1000;
248 spot *= 1./num;
249 */
250
251 const TVector3 spot = fMirror0->GetReflection(w, fGeom->GetCameraDist())*1000;
252 v.Set(spot(0), spot(1));
253
254 const Float_t max = fGeom->GetMaxRadius()*0.70;
255 return v.X()>-max && v.Y()>-max && v.X()<max && v.Y()<max;
256}
257
258// --------------------------------------------------------------------------
259//
260// Find an object with a given name in the list of primitives of this pad.
261//
262TObject *FindObjectInPad(const char *name, TVirtualPad *pad)
263{
264 if (!pad)
265 pad = gPad;
266
267 if (!pad)
268 return NULL;
269
270 TObject *o;
271
272 TIter Next(pad->GetListOfPrimitives());
273 while ((o=Next()))
274 {
275 if (o->InheritsFrom(gROOT->GetClass(name)))
276 return o;
277
278 if (o->InheritsFrom("TPad"))
279 if ((o = FindObjectInPad(name, (TVirtualPad*)o)))
280 return o;
281 }
282 return NULL;
283}
284
285// --------------------------------------------------------------------------
286//
287// Options:
288//
289// '*' Draw the mean of the reflections on all mirrors
290// '.' Draw a dot for the reflection on each individual mirror
291// 'h' To create a TH2D of the star-light which is displayed
292// 'c' Use the underlaying MHCamera as histogram
293// '0' Draw the reflection on a virtual perfect mirror
294// '=' Draw '0' or '*' propotional to the star magnitude
295//
296// If the Pad contains an object MHCamera of type MHCamera it is used.
297// Otherwise a new object is created.
298//
299void MAstroCamera::AddPrimitives(TString o)
300{
301 if (!fTime || !fObservatory || !fMirrors)
302 {
303 cout << "Missing data..." << endl;
304 return;
305 }
306
307 if (o.IsNull())
308 o = "*.";
309
310 const Bool_t hasnull = o.Contains("0", TString::kIgnoreCase);
311 const Bool_t hashist = o.Contains("h", TString::kIgnoreCase);
312 const Bool_t hasmean = o.Contains("*", TString::kIgnoreCase);
313 const Bool_t hasdot = o.Contains(".", TString::kIgnoreCase);
314 const Bool_t usecam = o.Contains("c", TString::kIgnoreCase);
315 const Bool_t resize = o.Contains("=", TString::kIgnoreCase);
316
317 // Get camera
318 MHCamera *camera=(MHCamera*)FindObjectInPad("MHCamera", gPad);
319 if (camera)
320 {
321 if (!camera->GetGeometry() || camera->GetGeometry()->IsA()!=fGeom->IsA())
322 camera->SetGeometry(*fGeom);
323 }
324 else
325 {
326 camera = new MHCamera(*fGeom);
327 camera->SetName("MHCamera");
328 camera->SetStats(0);
329 camera->SetInvDeepBlueSeaPalette();
330 camera->SetBit(kCanDelete);
331 camera->Draw();
332 }
333
334 camera->SetTitle(GetPadTitle());
335
336 gPad->cd(1);
337
338 if (!usecam)
339 {
340 if (camera->GetEntries()==0)
341 camera->SetBit(MHCamera::kNoLegend);
342 }
343 else
344 {
345 camera->Reset();
346 camera->SetYTitle("arb.cur");
347 }
348
349 TH2 *h=0;
350 if (hashist)
351 {
352 TH2F hist("","", 90, -650, 650, 90, -650, 650);
353 hist.SetMinimum(0);
354 h = (TH2*)hist.DrawCopy("samecont1");
355 }
356
357 const TRotation rot(GetGrid(kTRUE));
358
359 MVector3 *radec;
360 TIter Next(&fList);
361
362 while ((radec=(MVector3*)Next()))
363 {
364 const Double_t mag = radec->Magnitude();
365 if (mag>GetLimMag())
366 continue;
367
368 TVector3 star(*radec);
369
370 // Rotate Star into telescope system
371 star *= rot;
372
373 TVector3 mean;
374
375 Int_t num = 0;
376
377 MGeomMirror *mirror = 0;
378 TIter NextM(fMirrors);
379 while ((mirror=(MGeomMirror*)NextM()))
380 {
381 const TVector3 spot = mirror->GetReflection(star, fGeom->GetCameraDist())*1000;
382
383 // calculate mean of all 'stars' hitting the camera plane
384 // by taking the sum of the intersection points between
385 // the light vector and the camera plane
386 mean += spot;
387
388 if (hasdot)
389 {
390 TMarker *m=new TMarker(spot(0), spot(1), 1);
391 m->SetMarkerColor(kMagenta);
392 m->SetMarkerStyle(kDot);
393 fMapG.Add(m);
394 }
395 if (h)
396 h->Fill(spot(0), spot(1), pow(10, -mag/2.5));
397
398 if (usecam)
399 camera->Fill(spot(0), spot(1), pow(10, -mag/2.5));
400
401 num++;
402 }
403
404 // transform meters into millimeters (camera display works with mm)
405 mean *= 1./num;
406 DrawStar(mean(0), mean(1), *radec, hasmean?kBlack:-1, Form("x=%.1fmm y=%.1fmm", mean(0), mean(1)), resize);
407
408 if (hasnull)
409 {
410 TVector3 star(*radec);
411 star *= rot;
412 const TVector3 spot = fMirror0->GetReflection(star, fGeom->GetCameraDist())*1000;
413 DrawStar(spot(0), spot(1), *radec, hasmean?kBlack:-1, Form("x=%.1fmm y=%.1fmm", mean(0), mean(1)), resize);
414 // This can be used to get the abberation...
415 //cout << TMath::Hypot(spot(0), spot(1)) << " " << TMath::Hypot(mean(0)-spot(0), mean(1)-spot(1)) << endl;
416 }
417 }
418}
419
420// --------------------------------------------------------------------------
421//
422// Options:
423//
424// '*' Draw the mean of the reflections on all mirrors
425// '.' Draw a dot for the reflection on each individual mirror
426// 'h' To create a TH2D of the star-light which is displayed
427// 'c' Use the underlaying MHCamera as histogram
428// '0' Draw the reflection on a virtual perfect mirror
429//
430// If the Pad contains an object MHCamera of type MHCamera it is used.
431// Otherwise a new object is created.
432//
433/*void MAstroCamera::FillStarList(TList *list)
434{
435 list->SetOwner();
436 list->Delete();
437
438 if (!fTime || !fObservatory || !fMirrors || !list)
439 {
440 cout << "Missing data..." << endl;
441 return;
442 }
443
444 const MAstroSky2Local s2l(*fTime, *fObservatory);
445 const TRotation trans(AlignCoordinates(rot*fRaDec));
446
447 // Return the correct rotation matrix
448 const TRotation rot = trans*s2l;
449
450 MVector3 *radec;
451 TIter Next(&fList);
452
453 while ((radec=(MVector3*)Next()))
454 {
455 const Double_t mag = radec->Magnitude();
456
457 TVector3 mean;
458 TVector3 star(*radec);
459 star *= rot;
460 const TVector3 spot = fMirror0->GetReflection(star, fGeom->GetCameraDist())*1000;
461
462 MStarLocalPos *starpos = new MStarLocalPos;
463 starpos->SetExpValues(mag,mean(0),mean(1));
464 list->Add(starpos);
465 }
466 // For MAGIC the distance of the mean of the light distribution
467 // to the Mirror0 reflection of the star (Abberation) can be
468 // expressed as: dr = (0.0713 +/- 0.0002) * r = r/14.03
469 // with r = hypot(mean(0), mean(1))
470}
471*/
472
473// ------------------------------------------------------------------------
474//
475// Uses fRaDec as a reference point.
476//
477// Return dZd and dAz corresponding to the distance from x,y to fRaDec
478//
479// Before calling this function you should correct for abberation. In
480// case of MAGIC you can do this by:
481// x /= 1.0713;
482// y /= 1.0713;
483//
484// x [mm]: x coordinate in the camera plane (assuming a perfect mirror)
485// y [mm]: y coordinate in the camera plane (assuming a perfect mirror)
486//
487// We assume (0, 0) to be the center of the FOV
488//
489// dzd [deg]: Delta Zd
490// daz [deg]: Delta Az
491//
492void MAstroCamera::GetDiffZdAz(Double_t x, Double_t y, Double_t &dzd, Double_t &daz)
493{
494 // Reflect the corrected pixel on a perfect mirror
495 TVector3 v(x, y, fGeom->GetCameraDist()*1000);
496 TVector3 spot = fMirror0->GetReflection(v);
497
498 // Derotate into the local coordinate system
499 const MAstroSky2Local rot(*fTime, *fObservatory);
500 const TRotation align(AlignCoordinates(rot*fRaDec).Inverse());
501 spot *= align;
502
503 cout << "Zd="<<spot.Theta()*TMath::RadToDeg() << " ";
504 cout << "Az="<<spot.Phi() *TMath::RadToDeg()+360 << endl;
505
506 // Derotatet the center of the camera
507 TVector3 c(0, 0, 1);
508 c *= align;
509
510 dzd = (spot.Theta()-c.Theta())*TMath::RadToDeg();
511 daz = (spot.Phi() -c.Phi()) *TMath::RadToDeg();
512
513 if (daz> 180) daz -= 360;
514 if (daz<-180) daz += 360;
515}
516
517// ------------------------------------------------------------------------
518//
519// Execute a gui event on the camera
520//
521void MAstroCamera::ExecuteEvent(Int_t event, Int_t mp1, Int_t mp2)
522{
523 // if (mp1>0 && mp2>0)
524 // {
525 // // Calculate World coordinates from pixel
526 // Double_t x = gPad->AbsPixeltoX(mp1);
527 // Double_t y = gPad->AbsPixeltoY(mp2);
528 //
529 // // Correct for abberation
530 // x /= 1.0713;
531 // y /= 1.0713;
532 //
533 // Double_t dzd, daz;
534 // GetDiffZdAz(x, y, dzd, daz);
535 //
536 // cout << "dZd="<< dzd << " " << "dAz="<< daz << endl;
537 // }
538 //
539 // For MAGIC the distance of the mean of the light distribution
540 // to the Mirror0 reflection of the star (Abberation) can be
541 // expressed as: dr = 0.0713*r = r/14.03
542 // +-0.0002
543
544 if (event==kKeyPress && fTime)
545 switch (mp2)
546 {
547 case kKey_Plus:
548 fTime->SetMjd(fTime->GetMjd()+0.25/24);
549 Update(kTRUE);
550 return;
551
552 case kKey_Minus:
553 fTime->SetMjd(fTime->GetMjd()-0.25/24);
554 Update(kTRUE);
555 return;
556 }
557
558 MAstroCatalog::ExecuteEvent(event, mp1, mp2);
559}
Note: See TracBrowser for help on using the repository browser.