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

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