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

Last change on this file since 2126 was 2122, checked in by tbretz, 22 years ago
*** empty log message ***
File size: 19.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. The Pixels are displayed in
31// contents/area [somthing/mm^2]
32//
33////////////////////////////////////////////////////////////////////////////
34#include "MCamDisplay.h"
35
36#include <fstream.h>
37#include <iostream.h>
38
39#include <TBox.h>
40#include <TArrow.h>
41#include <TLatex.h>
42#include <TStyle.h>
43#include <TCanvas.h>
44#include <TClonesArray.h>
45
46#include "MH.h"
47#include "MHexagon.h"
48
49#include "MGeomCam.h"
50
51#include "MCerPhotPix.h"
52#include "MCerPhotEvt.h"
53
54#include "MPedestalPix.h"
55#include "MPedestalCam.h"
56
57#include "MImgCleanStd.h"
58
59#define kItemsLegend 50 // see SetPalette(1,0)
60
61ClassImp(MCamDisplay);
62
63// ------------------------------------------------------------------------
64//
65// Default Constructor. To be used by the root system ONLY.
66//
67MCamDisplay::MCamDisplay()
68 : fGeomCam(NULL), fAutoScale(kTRUE), fW(0), fH(0)
69{
70 fNumPixels = 0;
71 fRange = 0;
72
73 fPixels = NULL;
74 fLegend = NULL;
75 fLegText = NULL;
76 fArrowX = NULL;
77 fArrowY = NULL;
78 fLegRadius = NULL;
79 fLegDegree = NULL;
80}
81
82// ------------------------------------------------------------------------
83//
84// Constructor. Makes a clone of MGeomCam.
85//
86MCamDisplay::MCamDisplay(MGeomCam *geom)
87 : fGeomCam(NULL), fAutoScale(kTRUE), fW(0), fH(0)
88{
89 fGeomCam = (MGeomCam*)geom->Clone();
90
91 //
92 // create the hexagons of the display
93 //
94 fNumPixels = fGeomCam->GetNumPixels();
95 fRange = fGeomCam->GetMaxRadius();
96
97 // root 3.02
98 // * base/inc/TObject.h:
99 // register BIT(8) as kNoContextMenu. If an object has this bit set it will
100 // not get an automatic context menu when clicked with the right mouse button.
101
102 //
103 // Construct all hexagons. Use new-operator with placement
104 //
105 fPixels = new TClonesArray("MHexagon", fNumPixels);
106 for (UInt_t i=0; i<fNumPixels; i++)
107 {
108 MHexagon &pix = *new ((*fPixels)[i]) MHexagon((*fGeomCam)[i]);
109#if ROOT_VERSION_CODE > ROOT_VERSION(3,01,06)
110 pix.SetBit(/*kNoContextMenu|*/kCannotPick);
111#endif
112 pix.SetFillColor(16);
113 }
114
115 //
116 // set up the Legend
117 //
118 const Float_t H = 0.9*fRange;
119 const Float_t h = 2./kItemsLegend;
120
121 const Float_t w = fRange/sqrt(fNumPixels);
122
123 fLegend = new TClonesArray("TBox", kItemsLegend);
124 fLegText = new TClonesArray("TText", kItemsLegend);
125
126 for (Int_t i = 0; i<kItemsLegend; i++)
127 {
128 TBox &newbox = *new ((*fLegend)[i]) TBox;
129 TText &newtxt = *new ((*fLegText)[i]) TText;
130
131 newbox.SetX1(fRange);
132 newbox.SetX2(fRange+w);
133 newbox.SetY1(H*( i *h - 1.));
134 newbox.SetY2(H*((i+1)*h - 1.));
135 newbox.SetFillColor(16);
136#if ROOT_VERSION_CODE > ROOT_VERSION(3,01,06)
137 newbox.SetBit(/*kNoContextMenu|*/kCannotPick);
138#endif
139
140 newtxt.SetTextSize(0.025);
141 newtxt.SetTextAlign(12);
142 newtxt.SetX(fRange+1.5*w);
143 newtxt.SetY(H*((i+0.5)*h - 1.));
144#if ROOT_VERSION_CODE > ROOT_VERSION(3,01,06)
145 newtxt.SetBit(/*kNoContextMenu|*/kCannotPick);
146#endif
147 }
148
149 fArrowX = new TArrow(-fRange*.9, -fRange*.9, -fRange*.6, -fRange*.9, 0.025);
150 fArrowY = new TArrow(-fRange*.9, -fRange*.9, -fRange*.9, -fRange*.6, 0.025);
151
152 TString text;
153 text += (int)(fRange*.3);
154 text += "mm";
155
156 fLegRadius = new TText(-fRange*.85, -fRange*.85, text);
157 text = "";
158 text += (float)((int)(fRange*.3*fGeomCam->GetConvMm2Deg()*10))/10;
159 text += "\\circ";
160 text = text.Strip(TString::kLeading);
161 fLegDegree = new TLatex(-fRange*.85, -fRange*.75, text);
162 fLegRadius->SetTextSize(0.04);
163 fLegDegree->SetTextSize(0.04);
164
165#if ROOT_VERSION_CODE < ROOT_VERSION(3,01,06)
166 SetPalette(1, 0);
167#else
168 SetPalette(51, 0);
169#endif
170
171}
172
173// ------------------------------------------------------------------------
174//
175// Destructor. Deletes TClonesArrays for hexagons and legend elements.
176//
177MCamDisplay::~MCamDisplay()
178{
179 fPixels->Delete();
180 fLegend->Delete();
181 fLegText->Delete();
182
183 delete fPixels;
184 delete fLegend;
185 delete fLegText;
186
187 delete fArrowX;
188 delete fArrowY;
189
190 delete fLegRadius;
191 delete fLegDegree;
192
193 delete fGeomCam;
194}
195
196inline void MCamDisplay::SetPixColor(const MCerPhotPix &pix, const UInt_t i, Float_t min, Float_t max)
197{
198 if (i>=fNumPixels)
199 return;
200
201 //
202 // Fixme: Use absolute value per mm^2. Needs another scaling algorithm.
203 //
204 const Float_t ratio = fGeomCam->GetPixRatio(i);
205 const Float_t pnum = ratio*pix.GetNumPhotons();
206
207 (*this)[pix.GetPixId()].SetFillColor(GetColor(pnum, min, max));
208}
209
210inline void MCamDisplay::SetPixColorPedestal(const MPedestalPix &pix, const UInt_t i, Float_t min, Float_t max)
211{
212 if (i>=fNumPixels)
213 return;
214
215 //
216 // Fixme: Use absolute value per mm^2. Needs another scaling algorithm.
217 //
218 const Float_t ratio = fGeomCam->GetPixRatio(i);
219 const Float_t pnum = ratio*pix.GetMean();
220
221 (*this)[i].SetFillColor(GetColor(pnum, min, max));
222}
223
224inline void MCamDisplay::SetPixColorError(const MCerPhotPix &pix, const UInt_t i, Float_t min, Float_t max)
225{
226 if (i>=fNumPixels)
227 return;
228
229 //
230 // Fixme: Use absolute value per mm^2. Needs another scaling algorithm.
231 //
232 const Float_t ratio = fGeomCam->GetPixRatio(i);
233 const Float_t pnum = sqrt(ratio)*pix.GetErrorPhot();
234
235 (*this)[pix.GetPixId()].SetFillColor(GetColor(pnum, min, max));
236}
237
238inline void MCamDisplay::SetPixColorRatio(const MCerPhotPix &pix, Float_t min, Float_t max)
239{
240 //
241 // Fixme: Use absolute value per mm^2. Needs another scaling algorithm.
242 //
243 const Float_t pnum = pix.GetNumPhotons()/pix.GetErrorPhot();
244 (*this)[pix.GetPixId()].SetFillColor(GetColor(pnum, min, max));
245}
246
247inline void MCamDisplay::SetPixColorLevel(const MCerPhotPix &pix, Float_t lvl1, Float_t lvl2)
248{
249 const Int_t maxcolidx = kItemsLegend-1;
250
251 MHexagon &hex = (*this)[pix.GetPixId()];
252
253 const Float_t r = pix.GetNumPhotons()/pix.GetErrorPhot();
254
255 if (r>lvl1)
256 hex.SetFillColor(fColors[4*maxcolidx/5]);
257 else
258 if (r>lvl2)
259 hex.SetFillColor(fColors[maxcolidx/2]);
260 else
261 hex.SetFillColor(fColors[maxcolidx/5]);
262}
263
264// ------------------------------------------------------------------------
265//
266// Call this function to draw the camera layout into your canvas.
267// Setup a drawing canvas. Add this object and all child objects
268// (hexagons, etc) to the current pad. If no pad exists a new one is
269// created.
270//
271void MCamDisplay::Draw(Option_t *option)
272{
273 // root 3.02:
274 // gPad->SetFixedAspectRatio()
275
276 TVirtualPad *pad = gPad ? gPad : MH::MakeDefCanvas("CamDisplay", "Mars Camera Display", 750, 600);
277 pad->SetBorderMode(0);
278 pad->SetFillColor(16);
279
280 AppendPad("");
281}
282
283
284void MCamDisplay::SetRange()
285{
286 //
287 // Maintain aspect ratio
288 //
289 const float ratio = 1.15;
290
291 const float w = gPad->GetWw();
292 const float h = gPad->GetWh()*ratio;
293
294 gPad->Range(-fRange, -fRange, (2*ratio-1)*fRange, fRange);
295
296 if (h<w)
297 gPad->SetPad((1.-h/w)/2, 0, (h/w+1)/2, 0.9999999);
298 else
299 gPad->SetPad(0, (1.-w/h)/2, 1, (w/h+1)/2);
300}
301
302// ------------------------------------------------------------------------
303//
304// This is called at any time the canvas should get repainted.
305// Here we maintain an aspect ratio of 1.15. This makes sure,
306// that the camera image doesn't get distorted by resizing the canvas.
307//
308void MCamDisplay::Paint(Option_t *opt)
309{
310 if (!fPixels)
311 return;
312
313 //
314 // Maintain aspect ratio
315 //
316 SetRange();
317
318 //
319 // Maintain colors
320 //
321 SetPalette();
322
323 //
324 // Paint primitives
325 //
326 for (UInt_t i=0; i<fNumPixels; i++)
327 (*this)[i].Paint();
328
329 for (Int_t i=0; i<kItemsLegend; i++)
330 {
331 GetBox(i)->Paint();
332 GetText(i)->Paint();
333 }
334
335 fArrowX->Paint(">");
336 fArrowY->Paint(">");
337
338 fLegRadius->Paint();
339 fLegDegree->Paint();
340}
341
342// ------------------------------------------------------------------------
343//
344// With this function you can change the color palette. For more
345// information see TStyle::SetPalette. Only palettes with 50 colors
346// are allowed.
347// In addition you can use SetPalette(52, 0) to create an inverse
348// deep blue sea palette
349//
350void MCamDisplay::SetPalette(Int_t ncolors, Int_t *colors)
351{
352 //
353 // If not enough colors are specified skip this.
354 //
355 if (ncolors>1 && ncolors<50)
356 {
357 cout << "MCamDisplay::SetPalette: Only default palettes with 50 colors are allowed... ignored." << endl;
358 return;
359 }
360
361 //
362 // If ncolors==52 create a reversed deep blue sea palette
363 //
364 if (ncolors==52)
365 {
366 gStyle->SetPalette(51, NULL);
367 Int_t c[50];
368 for (int i=0; i<50; i++)
369 c[49-i] = gStyle->GetColorPalette(i);
370 gStyle->SetPalette(50, c);
371 }
372 else
373 gStyle->SetPalette(ncolors, colors);
374
375 //
376 // Change the colors of the pixels
377 //
378 for (unsigned int i=0; i<fNumPixels; i++)
379 {
380 //
381 // Get the old color index and check whether it is
382 // background or transparent
383 //
384 Int_t col = (*this)[i].GetFillColor();
385 if (col==10 || col==16)
386 continue;
387
388 //
389 // Search for the color index (level) in the color table
390 //
391 int idx;
392 for (idx=0; idx<kItemsLegend; idx++)
393 if (col==fColors[idx])
394 break;
395
396 //
397 // Should not happen
398 //
399 if (idx==kItemsLegend)
400 {
401 cout << "MCamDisplay::SetPalette: Strange... FIXME!" << endl;
402 continue;
403 }
404
405 //
406 // Convert the old color index (level) into the new one
407 //
408 (*this)[i].SetFillColor(gStyle->GetColorPalette(idx));
409 }
410
411 //
412 // Store the color palette used for a leter reverse lookup
413 //
414 for (int i=0; i<kItemsLegend; i++)
415 {
416 fColors[i] = gStyle->GetColorPalette(i);
417 GetBox(i)->SetFillColor(fColors[i]);
418 }
419}
420
421void MCamDisplay::SetPrettyPalette()
422{
423 SetPalette(1, 0);
424}
425
426void MCamDisplay::SetDeepBlueSeaPalette()
427{
428 SetPalette(51, 0);
429}
430
431void MCamDisplay::SetInvDeepBlueSeaPalette()
432{
433 SetPalette(52, 0);
434}
435
436void MCamDisplay::SetPalette()
437{
438 for (int i=0; i<kItemsLegend; i++)
439 GetBox(i)->SetFillColor(fColors[i]);
440}
441
442void MCamDisplay::DrawPixelNumbers()
443{
444 for (int i=0; i<kItemsLegend; i++)
445 fColors[i] = 16;
446
447 if (!gPad)
448 Draw();
449
450 TText txt;
451 txt.SetTextFont(122);
452 txt.SetTextAlign(22); // centered/centered
453
454 for (UInt_t i=0; i<fNumPixels; i++)
455 {
456 TString num;
457 num += i;
458
459 const MHexagon &h = (*this)[i];
460 TText *nt = txt.DrawText(h.GetX(), h.GetY(), num);
461 nt->SetTextSize(0.3*h.GetD()/fGeomCam->GetMaxRadius());
462 }
463}
464
465// ------------------------------------------------------------------------
466//
467// Call this function to fill the number of photo electron into the
468// camera.
469//
470void MCamDisplay::FillPhotNum(const MCerPhotEvt &event)
471{
472 //
473 // Reset pixel colors to default value
474 //
475 Reset();
476
477 //
478 // if the autoscale is true, set the values for the range for
479 // each event
480 //
481 Float_t min = 0;
482 Float_t max = 50;
483 if (fAutoScale)
484 {
485 min = event.GetNumPhotonsMin(fGeomCam);
486 max = event.GetNumPhotonsMax(fGeomCam);
487
488 if (max==min)
489 max = min +1;
490
491 UpdateLegend(min, max);
492 }
493
494 //
495 // update the colors in the picture
496 //
497 const Int_t entries = event.GetNumPixels();
498
499 for (Int_t i=0; i<entries; i++)
500 {
501 const MCerPhotPix &pix = event[i];
502
503 if (!pix.IsPixelUsed())
504 continue;
505
506 SetPixColor(pix, i, min, max);
507 }
508}
509
510// ------------------------------------------------------------------------
511//
512// Call this function to fill the number of photo electron into the
513// camera.
514//
515void MCamDisplay::FillPedestals(const MPedestalCam &event)
516{
517 //
518 // Reset pixel colors to default value
519 //
520 Reset();
521
522 //
523 // if the autoscale is true, set the values for the range for
524 // each event
525 //
526 Float_t min = 0;
527 Float_t max = 50;
528 if (fAutoScale)
529 {
530 min = event.GetMeanMin(fGeomCam);
531 max = event.GetMeanMax(fGeomCam);
532
533 if (max==min)
534 max = min +1;
535
536 UpdateLegend(min, max);
537 }
538
539 //
540 // update the colors in the picture
541 //
542 const Int_t entries = event.GetSize();
543
544 for (Int_t i=0; i<entries; i++)
545 SetPixColorPedestal(event[i], i, min, max);
546}
547
548// ------------------------------------------------------------------------
549//
550// Call this function to fill the error of number of photo electron
551// into the camera.
552//
553void MCamDisplay::FillErrorPhot(const MCerPhotEvt &event)
554{
555 //
556 // Reset pixel colors to default value
557 //
558 Reset();
559
560 //
561 // if the autoscale is true, set the values for the range for
562 // each event
563 //
564 Float_t min = 0;
565 Float_t max = 50;
566 if (fAutoScale)
567 {
568 min = event.GetErrorPhotMin(fGeomCam);
569 max = event.GetErrorPhotMax(fGeomCam);
570
571 if (max==min)
572 max = min +1;
573
574 UpdateLegend(min, max);
575 }
576
577 //
578 // update the colors in the picture
579 //
580 const Int_t entries = event.GetNumPixels();
581
582 for (Int_t i=0; i<entries; i++)
583 {
584 const MCerPhotPix &pix = event[i];
585
586 if (!pix.IsPixelUsed())
587 continue;
588
589 SetPixColorError(pix, i, min, max);
590 }
591}
592
593// ------------------------------------------------------------------------
594//
595// Call this function to fill the ratio of the number of photons
596// divided by its error
597//
598void MCamDisplay::FillRatio(const MCerPhotEvt &event)
599{
600 //
601 // Reset pixel colors to default value
602 //
603 Reset();
604
605 //
606 // if the autoscale is true, set the values for the range for
607 // each event
608 //
609 Float_t min = 0;
610 Float_t max = 20;
611 if (fAutoScale)
612 {
613 min = event.GetRatioMin();
614 max = event.GetRatioMax();
615
616 UpdateLegend(min, max);
617 }
618
619 //
620 // update the colors in the picture
621 //
622 const Int_t entries = event.GetNumPixels();
623
624 for (Int_t i=0; i<entries; i++)
625 {
626 const MCerPhotPix &pix = event[i];
627
628 if (!pix.IsPixelUsed())
629 continue;
630
631 SetPixColorRatio(pix, min, max);
632 }
633}
634
635// ------------------------------------------------------------------------
636//
637// Fill the colors in respect to the cleaning levels
638//
639void MCamDisplay::FillLevels(const MCerPhotEvt &event, Float_t lvl1, Float_t lvl2)
640{
641 //
642 // Reset pixel colors to default value
643 //
644 Reset();
645
646 //
647 // update the colors in the picture
648 //
649 const Int_t entries = event.GetNumPixels();
650
651 for (Int_t i=0; i<entries; i++)
652 {
653 const MCerPhotPix &pix = event[i];
654
655 if (!pix.IsPixelUsed())
656 continue;
657
658 SetPixColorLevel(pix, lvl1, lvl2);
659 }
660}
661
662// ------------------------------------------------------------------------
663//
664// Fill the colors in respect to the cleaning levels
665//
666void MCamDisplay::FillLevels(const MCerPhotEvt &event, const MImgCleanStd &clean)
667{
668 FillLevels(event, clean.GetCleanLvl1(), clean.GetCleanLvl2());
669}
670
671// ------------------------------------------------------------------------
672//
673// Reset the all pixel colors to a default value
674//
675void MCamDisplay::Reset()
676{
677 for (UInt_t i=0; i<fNumPixels; i++)
678 (*this)[i].SetFillColor(10);
679}
680
681// ------------------------------------------------------------------------
682//
683// Here we calculate the color index for the current value.
684// The color index is defined with the class TStyle and the
685// Color palette inside. We use the command gStyle->SetPalette(1,0)
686// for the display. So we have to convert the value "wert" into
687// a color index that fits the color palette.
688// The range of the color palette is defined by the values fMinPhe
689// and fMaxRange. Between this values we have 50 color index, starting
690// with 0 up to 49.
691//
692Int_t MCamDisplay::GetColor(Float_t val, Float_t min, Float_t max)
693{
694 //
695 // first treat the over- and under-flows
696 //
697 const Int_t maxcolidx = kItemsLegend-1;
698
699 if (val >= max)
700 return fColors[maxcolidx];
701
702 if (val <= min)
703 return fColors[0];
704
705 //
706 // calculate the color index
707 //
708 const Float_t ratio = (val-min) / (max-min);
709 const Int_t colidx = (Int_t)(ratio*maxcolidx + .5);
710
711 return fColors[colidx];
712}
713
714// ------------------------------------------------------------------------
715//
716// Change the text on the legend according to the range of the Display
717//
718void MCamDisplay::UpdateLegend(Float_t minphe, Float_t maxphe)
719{
720 for (Int_t i=0; i<kItemsLegend; i+=3)
721 {
722 const Float_t val = minphe + (Float_t)i/kItemsLegend * (maxphe-minphe) ;
723
724 TText &txt = *GetText(i);
725 txt.SetText(txt.GetX(), txt.GetY(), Form(val<1e6?"%5.1f":"%5.1e", val));
726 }
727}
728
729// ------------------------------------------------------------------------
730//
731// Save primitive as a C++ statement(s) on output stream out
732//
733void MCamDisplay::SavePrimitive(ofstream &out, Option_t *opt)
734{
735 cout << "MCamDisplay::SavePrimitive: Must be rewritten!" << endl;
736 /*
737 if (!gROOT->ClassSaved(TCanvas::Class()))
738 fDrawingPad->SavePrimitive(out, opt);
739
740 out << " " << fDrawingPad->GetName() << "->SetWindowSize(";
741 out << fDrawingPad->GetWw() << "," << fDrawingPad->GetWh() << ");" << endl;
742 */
743}
744
745// ------------------------------------------------------------------------
746//
747// compute the distance of a point (px,py) to the Camera
748// this functions needed for graphical primitives, that
749// means without this function you are not able to interact
750// with the graphical primitive with the mouse!!!
751//
752// All calcutations are running in pixel coordinates
753//
754Int_t MCamDisplay::DistancetoPrimitive(Int_t px, Int_t py)
755{
756 Int_t dist = 999999;
757
758 for (UInt_t i=0; i<fNumPixels; i++)
759 {
760 Int_t d = (*fPixels)[i]->DistancetoPrimitive(px, py);
761
762 if (d<dist)
763 dist=d;
764 }
765 return dist==0?0:999999;
766}
767
768// ------------------------------------------------------------------------
769//
770// Execute a mouse event on the camera
771//
772/*
773 void MCamDisplay::ExecuteEvent(Int_t event, Int_t px, Int_t py)
774 {
775 cout << "Execute Event Camera " << event << " @ " << px << " " << py << endl;
776 }
777 */
778
779
780// ------------------------------------------------------------------------
781//
782// Function introduced (31-01-03)
783//
784void MCamDisplay::SetPix(const Int_t pixnum, const Int_t color, Float_t min, Float_t max)
785{
786 (*this)[pixnum].SetFillColor(GetColor(color, min, max));
787}
788
789// ------------------------------------------------------------------------
790//
791// Returns string containing info about the object at position (px,py).
792// Returned string will be re-used (lock in MT environment).
793//
794char *MCamDisplay::GetObjectInfo(Int_t px, Int_t py) const
795{
796 static char info[64];
797
798 UInt_t i;
799 for (i=0; i<fNumPixels; i++)
800 {
801 if ((*fPixels)[i]->DistancetoPrimitive(px, py)>0)
802 continue;
803
804 sprintf(info, "Pixel Id: %d", i);
805 return info;
806 }
807 return TObject::GetObjectInfo(px, py);
808}
Note: See TracBrowser for help on using the repository browser.