source: trunk/Mars/mastro/MAstroCamera.cc@ 9969

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