source: trunk/MagicSoft/Mars/mgui/MCamDisplay.cc@ 1406

Last change on this file since 1406 was 1406, checked in by tbretz, 22 years ago
*** empty log message ***
File size: 14.9 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 05/2002 <mailto:tbretz@astro.uni-wuerzburg.de>
19! Author(s): Harald Kornmayer 1/2001
20!
21! Copyright: MAGIC Software Development, 2000-2002
22!
23!
24\* ======================================================================== */
25
26/////////////////////////////////////////////////////////////////////////////
27//
28// MCamDisplay
29//
30// Camera Display
31//
32////////////////////////////////////////////////////////////////////////////
33#include "MCamDisplay.h"
34
35#include <math.h>
36#include <fstream.h>
37#include <iostream.h>
38
39#include <TClonesArray.h>
40#include <TCanvas.h>
41#include <TStyle.h>
42#include <TBox.h>
43#include <TText.h>
44#include <TButton.h>
45
46#include "MHexagon.h"
47
48#include "MGeomPix.h"
49#include "MGeomCam.h"
50
51#include "MCerPhotPix.h"
52#include "MCerPhotEvt.h"
53
54#define kItemsLegend 50 // see SetPalette(1,0)
55
56ClassImp(MCamDisplay);
57
58// ------------------------------------------------------------------------
59//
60// default constructor
61//
62MCamDisplay::MCamDisplay(MGeomCam *geom)
63 : fAutoScale(kTRUE), fMinPhe(-2), fMaxPhe(50), fW(0), fH(0), fDrawingPad(NULL), fIsAllocated(kFALSE)
64{
65 fGeomCam = (MGeomCam*)geom; // FIXME: Clone doesn't work! (MGeomCam*)geom->Clone();
66
67 //
68 // create the hexagons of the display
69 //
70 fNumPixels = geom->GetNumPixels();
71 fRange = geom->GetMaxRadius();
72
73 //
74 // Construct all hexagons. Use new-operator with placement
75 //
76
77 // root 3.02
78 // * base/inc/TObject.h:
79 // register BIT(8) as kNoContextMenu. If an object has this bit set it will
80 // not get an automatic context menu when clicked with the right mouse button.
81
82 fPixels = new TClonesArray("MHexagon", fNumPixels);
83 for (UInt_t i=0; i<fNumPixels; i++)
84 new ((*fPixels)[i]) MHexagon((*geom)[i]);
85
86 //
87 // set the color palette for the TBox elements
88 //
89#if ROOT_VERSION_CODE < ROOT_VERSION(3,01,06)
90 SetPalette(1, 0);
91#else
92 SetPalette(51, 0);
93#endif
94
95 //
96 // set up the Legend
97 //
98 fLegend = new TClonesArray("TBox", kItemsLegend);
99 fLegText = new TClonesArray("TText", kItemsLegend);
100
101 for (Int_t i = 0; i<kItemsLegend; i++)
102 {
103 TBox *newbox = new ((*fLegend)[i]) TBox;
104 TText *newtxt = new ((*fLegText)[i]) TText;
105
106 newbox->SetFillColor(fColors[i]);
107
108 newtxt->SetTextSize(0.025);
109 newtxt->SetTextAlign(12);
110 }
111}
112
113// ------------------------------------------------------------------------
114//
115// Destructor. Deletes TClonesArrays for hexagons and legend elements.
116//
117MCamDisplay::~MCamDisplay()
118{
119 fPixels->Delete();
120 fLegend->Delete();
121 fLegText->Delete();
122
123 delete fPixels;
124 delete fLegend;
125 delete fLegText;
126
127 // delete fGeomCam;
128
129 // if (fIsAllocated)
130 // delete fDrawingPad;
131}
132
133inline void MCamDisplay::SetPixColor(const MCerPhotPix &pix, const Int_t i)
134{
135 //
136 // Fixme: Divide pnum by the (real) area of the pixel
137 //
138 const Float_t ratio = (*fGeomCam)[0].GetA()/(*fGeomCam)[i].GetA();
139 const Float_t pnum = ratio*pix.GetNumPhotons();
140
141 (*this)[pix.GetPixId()].SetFillColor(GetColor(pnum));
142}
143
144// ------------------------------------------------------------------------
145//
146// This is called at any time the canvas should get repainted.
147// Here we maintain an aspect ratio of 5/4=1.15. This makes sure,
148// that the camera image doesn't get distorted by resizing the canvas.
149//
150void MCamDisplay::Paint(Option_t *opt)
151{
152 const UInt_t w = (UInt_t)(gPad->GetWw()*gPad->GetAbsWNDC());
153 const UInt_t h = (UInt_t)(gPad->GetWh()*gPad->GetAbsHNDC());
154
155 //
156 // Check for a change in width or height, and make sure, that the
157 // first call also sets the range
158 //
159 if (w*fH == h*fW && fW && fH)
160 return;
161
162 //
163 // Calculate aspect ratio (5/4=1.25 recommended)
164 //
165 const Double_t ratio = (Double_t)w/h;
166
167 Float_t x;
168 Float_t y;
169
170 if (ratio>1.25)
171 {
172 x = (ratio*2-1)*fRange;
173 y = fRange;
174 }
175 else
176 {
177 x = fRange*1.5;
178 y = fRange*1.25/ratio;
179 }
180
181 fH = h;
182 fW = w;
183
184 //
185 // Set new range
186 //
187 gPad->Range(-fRange, -y, x, y);
188}
189
190// ------------------------------------------------------------------------
191//
192// With this function you can change the color palette. For more
193// information see TStyle::SetPalette. Only palettes with 50 colors
194// are allowed.
195// In addition you can use SetPalette(52, 0) to create an inverse
196// deep blue sea palette
197//
198void MCamDisplay::SetPalette(Int_t ncolors, Int_t *colors)
199{
200 //
201 // If not enough colors are specified skip this.
202 //
203 if (ncolors>1 && ncolors<50)
204 {
205 cout << "MCamDisplay::SetPalette: Only default palettes with 50 colors are allowed... ignored." << endl;
206 return;
207 }
208
209 //
210 // If ncolors==52 create a reversed deep blue sea palette
211 //
212 if (ncolors==52)
213 {
214 gStyle->SetPalette(51, NULL);
215 Int_t c[50];
216 for (int i=0; i<50; i++)
217 c[49-i] = gStyle->GetColorPalette(i);
218 gStyle->SetPalette(50, c);
219 }
220 else
221 gStyle->SetPalette(ncolors, colors);
222
223 if (fDrawingPad)
224 {
225 //
226 // Set the colors of the legend
227 //
228 for (int i=0; i<kItemsLegend; i++)
229 {
230 Int_t col = GetBox(i)->GetFillColor();
231
232 //
233 // Make sure, that the legend is already colored
234 //
235 if (col==10 || col==22)
236 continue;
237 GetBox(i)->SetFillColor(gStyle->GetColorPalette(i));
238 }
239
240 //
241 // Change the colors of the pixels
242 //
243 for (unsigned int i=0; i<fNumPixels; i++)
244 {
245 //
246 // Get the old color index and check whether it is
247 // background or transparent
248 //
249 Int_t col = (*this)[i].GetFillColor();
250 if (col==10 || col==22)
251 continue;
252
253 //
254 // Search for the color index (level) in the color table
255 //
256 int idx;
257 for (idx=0; idx<kItemsLegend; idx++)
258 if (col==fColors[idx])
259 break;
260 //
261 // Should not happen
262 //
263 if (idx==kItemsLegend)
264 {
265 cout << "MCamDisplay::SetPalette: Strange... FIXME!" << endl;
266 continue;
267 }
268
269 //
270 // Convert the old color index (level) into the new one
271 //
272 (*this)[i].SetFillColor(gStyle->GetColorPalette(idx));
273 }
274
275 //
276 // Update the pad on the screen
277 //
278 fDrawingPad->Modified();
279 fDrawingPad->Update();
280 }
281
282 //
283 // Store the color palette used for a leter reverse lookup
284 //
285 for (int i=0; i<kItemsLegend; i++)
286 fColors[i] = gStyle->GetColorPalette(i);
287}
288
289// ------------------------------------------------------------------------
290//
291// Call this function to draw the camera layout into your canvas.
292// Setup a drawing canvas. Add this object and all child objects
293// (hexagons, etc) to the current pad. If no pad exists a new one is
294// created.
295//
296void MCamDisplay::Draw(Option_t *option)
297{
298 // root 3.02:
299 // gPad->SetFixedAspectRatio()
300
301 if (fDrawingPad)
302 return;
303
304 //
305 // if no canvas is yet existing to draw into, create a new one
306 //
307 if (!gPad)
308 {
309 fDrawingPad = new TCanvas("CamDisplay", "Magic Camera Display", 0, 0, 750, 600);
310 fIsAllocated = kTRUE;
311 }
312 else
313 {
314 fDrawingPad = gPad;
315 fIsAllocated = kFALSE;
316 }
317
318 //
319 // Setup the correct environment
320 //
321 fDrawingPad->SetBorderMode(0);
322 fDrawingPad->SetFillColor(22);
323
324 //
325 // Set the initial coordinate range
326 //
327 Paint();
328
329 //
330 // Create and draw the buttons which allows changing the
331 // color palette of the display
332 //
333 TButton *but;
334 char txt[100];
335 sprintf(txt, "((MCamDisplay*)%p)->SetPalette(1,0);", this);
336 but = new TButton("Pretty", txt, 0.01, 0.95, 0.15, 0.99);
337 but->Draw();
338 sprintf(txt, "((MCamDisplay*)%p)->SetPalette(51,0);", this);
339 but = new TButton("Deap Sea", txt, 0.16, 0.95, 0.30, 0.99);
340 but->Draw();
341 sprintf(txt, "((MCamDisplay*)%p)->SetPalette(52,0);", this);
342 but = new TButton("Blue Inv", txt, 0.31, 0.95, 0.45, 0.99);
343 but->Draw();
344
345 //
346 // Draw all pixels of the camera
347 // (means apend all pixelobjects to the current pad)
348 //
349 for (UInt_t i=0; i<fNumPixels; i++)
350 {
351#if ROOT_VERSION_CODE > ROOT_VERSION(3,01,06)
352 (*this)[i].SetBit(kNoContextMenu|kCannotPick);
353#endif
354 (*this)[i].SetFillColor(22);
355 (*this)[i].Draw();
356 }
357
358 //
359 // initialize and draw legend
360 //
361 const Float_t H = 0.9*fRange;
362 const Float_t h = 2./kItemsLegend;
363
364 const Float_t w = fRange/sqrt(fNumPixels);
365
366 for (Int_t i=0; i<kItemsLegend; i++)
367 {
368 TBox *box = GetBox(i);
369 box->SetX1(fRange);
370 box->SetX2(fRange+w);
371 box->SetY1(H*( i *h - 1.));
372 box->SetY2(H*((i+1)*h - 1.));
373 box->SetFillColor(22);
374#if ROOT_VERSION_CODE > ROOT_VERSION(3,01,06)
375 box->SetBit(kNoContextMenu|kCannotPick);
376#endif
377 box->Draw();
378
379 TText *txt = GetText(i);
380 txt->SetX(fRange+1.5*w);
381 txt->SetY(H*((i+0.5)*h - 1.));
382#if ROOT_VERSION_CODE > ROOT_VERSION(3,01,06)
383 txt->SetBit(kNoContextMenu|kCannotPick);
384#endif
385 txt->Draw();
386 }
387
388 //
389 // Append this object, so that the aspect ratio is maintained
390 // (Paint-function is called)
391 // Add it here so that root will have it first in the internal list:
392 // This means, that root 'sees' the whole camera instead of all the
393 // single hexagons.
394 //
395 AppendPad(option);
396
397 //fDrawingPad->SetEditable(kFALSE);
398}
399
400void MCamDisplay::DrawPixelNumbers()
401{
402 if (!fDrawingPad)
403 Draw();
404
405 fDrawingPad->cd();
406
407 TText txt;
408 txt.SetTextFont(122);
409 txt.SetTextAlign(22); // centered/centered
410
411 for (UInt_t i=0; i<fNumPixels; i++)
412 {
413 TString num;
414 num += i;
415
416 const MHexagon &h = (*this)[i];
417 TText *nt = txt.DrawText(h.GetX(), h.GetY(), num);
418 nt->SetTextSize(0.3*h.GetD()/fGeomCam->GetMaxRadius());
419 }
420}
421
422// ------------------------------------------------------------------------
423//
424// Call this function to draw the number of photo electron into the
425// camera.
426//
427void MCamDisplay::DrawPhotNum(const MCerPhotEvt *event)
428{
429 if (!event)
430 return;
431
432 if (!fDrawingPad)
433 Draw();
434
435 fDrawingPad->cd();
436
437 for (int i=0; i<kItemsLegend; i++)
438 GetBox(i)->SetFillColor(fColors[i]);
439
440 //
441 // Reset pixel colors to default value
442 //
443 Reset();
444
445 //
446 // if the autoscale is true, set the values for the range for
447 // each event
448 //
449 if (fAutoScale)
450 {
451 fMinPhe = event->GetNumPhotonsMin(fGeomCam);
452 fMaxPhe = event->GetNumPhotonsMax(fGeomCam);
453
454 if (fMaxPhe < 20.)
455 fMaxPhe = 20.;
456
457 UpdateLegend();
458 }
459
460 //
461 // update the colors in the picture
462 //
463 const Int_t entries = event->GetNumPixels();
464
465 for (Int_t i=0; i<entries; i++)
466 {
467 const MCerPhotPix &pix = (*event)[i];
468
469 if (!pix.IsPixelUsed())
470 continue;
471
472 SetPixColor(pix, i);
473 }
474
475 //
476 // Update display physically
477 //
478 fDrawingPad->Modified();
479 fDrawingPad->Update();
480}
481
482// ------------------------------------------------------------------------
483//
484// reset the all pixel colors to a default value
485//
486void MCamDisplay::Reset()
487{
488 for (UInt_t i=0; i<fNumPixels; i++)
489 (*this)[i].SetFillColor(10);
490}
491
492// ------------------------------------------------------------------------
493//
494// Here we calculate the color index for the current value.
495// The color index is defined with the class TStyle and the
496// Color palette inside. We use the command gStyle->SetPalette(1,0)
497// for the display. So we have to convert the value "wert" into
498// a color index that fits the color palette.
499// The range of the color palette is defined by the values fMinPhe
500// and fMaxRange. Between this values we have 50 color index, starting
501// with 0 up to 49.
502//
503Int_t MCamDisplay::GetColor(Float_t val)
504{
505 //
506 // first treat the over- and under-flows
507 //
508 const Int_t maxcolidx = kItemsLegend-1;
509
510 if (val >= fMaxPhe)
511 return fColors[maxcolidx];
512
513 if (val <= fMinPhe)
514 return fColors[0];
515
516 //
517 // calculate the color index
518 //
519 const Float_t ratio = (val-fMinPhe) / (fMaxPhe-fMinPhe);
520 const Int_t colidx = (Int_t)(ratio*maxcolidx + .5);
521
522 return fColors[colidx];
523}
524
525// ------------------------------------------------------------------------
526//
527// change the text on the legend according to the range of the
528// Display
529//
530void MCamDisplay::UpdateLegend()
531{
532 char text[10];
533
534 for (Int_t i=0; i<kItemsLegend; i+=3)
535 {
536 const Float_t val = fMinPhe + (Float_t)i/kItemsLegend * (fMaxPhe-fMinPhe) ;
537
538 sprintf(text, "%5.1f", val);
539
540 TText &txt = *GetText(i);
541
542 txt.SetText(txt.GetX(), txt.GetY(), text);
543 }
544}
545
546// ------------------------------------------------------------------------
547//
548// Save primitive as a C++ statement(s) on output stream out
549//
550void MCamDisplay::SavePrimitive(ofstream &out, Option_t *opt)
551{
552 if (!gROOT->ClassSaved(TCanvas::Class()))
553 fDrawingPad->SavePrimitive(out, opt);
554
555 out << " " << fDrawingPad->GetName() << "->SetWindowSize(";
556 out << fDrawingPad->GetWw() << "," << fDrawingPad->GetWh() << ");" << endl;
557}
558
559// ------------------------------------------------------------------------
560//
561// compute the distance of a point (px,py) to the Camera
562// this functions needed for graphical primitives, that
563// means without this function you are not able to interact
564// with the graphical primitive with the mouse!!!
565//
566// All calcutations are running in pixel coordinates
567//
568Int_t MCamDisplay::DistancetoPrimitive(Int_t px, Int_t py)
569{
570 Int_t dist = 999999;
571
572 for (UInt_t i=0; i<fNumPixels; i++)
573 {
574 Int_t d = (*fPixels)[i]->DistancetoPrimitive(px, py);
575
576 if (d<dist)
577 dist=d;
578 }
579 return dist==0?0:999999;
580}
581
582// ------------------------------------------------------------------------
583//
584// Execute a mouse event on the camera
585//
586/*
587 void MCamDisplay::ExecuteEvent(Int_t event, Int_t px, Int_t py)
588 {
589 cout << "Execute Event Camera " << event << " @ " << px << " " << py << endl;
590 }
591 */
Note: See TracBrowser for help on using the repository browser.