source: trunk/MagicSoft/Mars/mhist/MHCamera.cc@ 2377

Last change on this file since 2377 was 2377, checked in by tbretz, 21 years ago
*** empty log message ***
File size: 29.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-2003
22!
23!
24\* ======================================================================== */
25
26/////////////////////////////////////////////////////////////////////////////
27//
28// MHCamera
29//
30// Camera Display, based on a TH1D. Pleas be carefull using the
31// underlaying TH1D.
32//
33// To change the scale to a logarithmic scale SetLogy() of the Pad.
34//
35////////////////////////////////////////////////////////////////////////////
36#include "MHCamera.h"
37
38#include <fstream>
39#include <iostream>
40
41#include <TBox.h>
42#include <TArrow.h>
43#include <TLatex.h>
44#include <TStyle.h>
45#include <TCanvas.h>
46#include <TArrayF.h>
47#include <TRandom.h>
48#include <TPaveText.h>
49#include <TPaveStats.h>
50#include <TClonesArray.h>
51#include <THistPainter.h>
52
53#include "MLog.h"
54#include "MLogManip.h"
55
56#include "MH.h"
57#include "MHexagon.h"
58
59#include "MGeomPix.h"
60#include "MGeomCam.h"
61
62#include "MCerPhotPix.h"
63#include "MCerPhotEvt.h"
64
65#include "MPedestalPix.h"
66#include "MPedestalCam.h"
67
68#include "MCurrents.h"
69#include "MCamEvent.h"
70
71#include "MImgCleanStd.h"
72
73
74#define kItemsLegend 48 // see SetPalette(1,0)
75
76ClassImp(MHCamera);
77
78using namespace std;
79
80void MHCamera::Init()
81{
82 SetDirectory(NULL);
83
84 SetLineColor(kGreen);
85 SetMarkerStyle(kFullDotMedium);
86 SetXTitle("Pixel Index");
87
88 fNotify = new TList;
89
90#if ROOT_VERSION_CODE < ROOT_VERSION(3,01,06)
91 SetPalette(1, 0);
92#else
93 SetPalette(51, 0);
94#endif
95}
96
97// ------------------------------------------------------------------------
98//
99// Default Constructor. To be used by the root system ONLY.
100//
101MHCamera::MHCamera() : TH1D(), fGeomCam(NULL), fColors(kItemsLegend)
102{
103 Init();
104}
105
106// ------------------------------------------------------------------------
107//
108// Constructor. Makes a clone of MGeomCam. Removed the TH1D from the
109// current directory. Calls Sumw2(). Set the histogram line color
110// (for error bars) to Green and the marker style to kFullDotMedium.
111//
112MHCamera::MHCamera(const MGeomCam &geom, const char *name, const char *title)
113: fGeomCam(NULL), /*TH1D(name, title, geom.GetNumPixels(), -0.5, geom.GetNumPixels()-0.5),
114fUsed(geom.GetNumPixels()),*/ fColors(kItemsLegend)
115{
116 //fGeomCam = (MGeomCam*)geom.Clone();
117 SetGeometry(geom, name, title);
118 Init();
119
120 //
121 // root 3.02
122 // * base/inc/TObject.h:
123 // register BIT(8) as kNoContextMenu. If an object has this bit set it will
124 // not get an automatic context menu when clicked with the right mouse button.
125}
126
127void MHCamera::SetGeometry(const MGeomCam &geom, const char *name, const char *title)
128{
129 SetNameTitle(name, title);
130
131 TAxis &x = *GetXaxis();
132
133 SetBins(geom.GetNumPixels(), 0, 1);
134 x.Set(geom.GetNumPixels(), -0.5, geom.GetNumPixels()-0.5);
135
136 //SetBins(geom.GetNumPixels(), -0.5, geom.GetNumPixels()-0.5);
137 //Rebuild();
138
139 Sumw2(); // necessary?
140
141 if (fGeomCam)
142 delete fGeomCam;
143 fGeomCam = (MGeomCam*)geom.Clone();
144
145 fUsed.Set(geom.GetNumPixels());
146 for (Int_t i=0; i<fNcells-2; i++)
147 ResetUsed(i);
148
149}
150
151// ------------------------------------------------------------------------
152//
153// Destructor. Deletes the cloned fGeomCam and the notification list.
154//
155MHCamera::~MHCamera()
156{
157 if (fGeomCam)
158 delete fGeomCam;
159 if (fNotify)
160 delete fNotify;
161}
162
163// ------------------------------------------------------------------------
164//
165// Taken from TH1D::Fill(). Uses the argument directly as bin index.
166// Doesn't increment the number of entries.
167//
168// -*-*-*-*-*-*-*-*Increment bin with abscissa X by 1*-*-*-*-*-*-*-*-*-*-*
169// ==================================
170//
171// if x is less than the low-edge of the first bin, the Underflow bin is incremented
172// if x is greater than the upper edge of last bin, the Overflow bin is incremented
173//
174// If the storage of the sum of squares of weights has been triggered,
175// via the function Sumw2, then the sum of the squares of weights is incremented
176// by 1 in the bin corresponding to x.
177//
178// -*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
179Int_t MHCamera::Fill(Axis_t x)
180{
181
182#if ROOT_VERSION_CODE > ROOT_VERSION(3,05,00)
183 if (fBuffer) return BufferFill(x,1);
184#endif
185 const Int_t bin = (Int_t)x+1;
186 AddBinContent(bin);
187 if (fSumw2.fN)
188 fSumw2.fArray[bin]++;
189
190 if (bin<=0 || bin>fNcells-2)
191 return -1;
192
193 fTsumw++;
194 fTsumw2++;
195 fTsumwx += x;
196 fTsumwx2 += x*x;
197 return bin;
198}
199
200// ------------------------------------------------------------------------
201//
202// Taken from TH1D::Fill(). Uses the argument directly as bin index.
203// Doesn't increment the number of entries.
204//
205// -*-*-*-*-*-*Increment bin with abscissa X with a weight w*-*-*-*-*-*-*-*
206// =============================================
207//
208// if x is less than the low-edge of the first bin, the Underflow bin is incremented
209// if x is greater than the upper edge of last bin, the Overflow bin is incremented
210//
211// If the storage of the sum of squares of weights has been triggered,
212// via the function Sumw2, then the sum of the squares of weights is incremented
213// by w^2 in the bin corresponding to x.
214//
215// -*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
216Int_t MHCamera::Fill(Axis_t x, Stat_t w)
217{
218#if ROOT_VERSION_CODE > ROOT_VERSION(3,05,00)
219 if (fBuffer) return BufferFill(x,w);
220#endif
221 const Int_t bin = (Int_t)x+1;
222 AddBinContent(bin, w);
223 if (fSumw2.fN)
224 fSumw2.fArray[bin] += w*w;
225
226 if (bin<=0 || bin>fNcells-2)
227 return -1;
228
229 const Stat_t z = (w > 0 ? w : -w);
230 fTsumw += z;
231 fTsumw2 += z*z;
232 fTsumwx += z*x;
233 fTsumwx2 += z*x*x;
234 return bin;
235}
236
237// ------------------------------------------------------------------------
238//
239// Use x and y in millimeters
240//
241Int_t MHCamera::Fill(Axis_t x, Axis_t y, Stat_t w)
242{
243 if (fNcells<=1)
244 return -1;
245
246 for (Int_t idx=0; idx<fNcells-2; idx++)
247 {
248 MHexagon hex((*fGeomCam)[idx]);
249 if (hex.DistanceToPrimitive(x, y)>0)
250 continue;
251
252 SetUsed(idx);
253 return Fill(idx, w);
254 }
255 return -1;
256}
257
258Stat_t MHCamera::GetMean(Int_t axis) const
259{
260 if (fNcells<=1)
261 return 0;
262
263 Stat_t mean = 0;
264 for (int i=1; i<fNcells-1; i++)
265 mean += fArray[i];
266
267 return mean/(fNcells-2);
268}
269
270Stat_t MHCamera::GetRMS(Int_t axis) const
271{
272 if (fNcells<=1)
273 return -1;
274
275 const Int_t n = fNcells-2;
276
277 Stat_t sum = 0;
278 Stat_t sq = 0;
279 for (int i=1; i<n+1; i++)
280 {
281 sum += fArray[i];
282 sq += fArray[i]*fArray[i];
283 }
284
285 sum /= n;
286 sq /= n;
287
288 return sqrt(sq-sum*sum);
289}
290
291// ------------------------------------------------------------------------
292//
293// Return the minimum contents of all pixels (if all is set, otherwise
294// only of all 'used' pixels), fMinimum if fMinimum set
295//
296Double_t MHCamera::GetMinimum(Bool_t all) const
297{
298 if (fMinimum != -1111)
299 return fMinimum;
300
301 if (fNcells<=1)
302 return 0;
303
304 Double_t minimum=FLT_MAX;
305
306 if (all)
307 {
308 for (Int_t idx=0; idx<fNcells-2; idx++)
309 if (fArray[idx+1] < minimum)
310 minimum = fArray[idx+1];
311 }
312 else
313 {
314 for (Int_t idx=0; idx<fNcells-2; idx++)
315 if (IsUsed(idx) && fArray[idx+1] < minimum)
316 minimum = fArray[idx+1];
317 }
318 return minimum;
319}
320
321// ------------------------------------------------------------------------
322//
323// Return the maximum contents of all pixels (if all is set, otherwise
324// only of all 'used' pixels), fMaximum if fMaximum set
325//
326Double_t MHCamera::GetMaximum(Bool_t all) const
327{
328 if (fMaximum != -1111)
329 return fMaximum;
330
331 if (fNcells<=1)
332 return 1;
333
334 Double_t maximum=-FLT_MAX;
335 if (all)
336 {
337 for (Int_t idx=0; idx<fNcells-2; idx++)
338 if (fArray[idx+1] > maximum)
339 maximum = fArray[idx+1];
340 }
341 else
342 {
343 for (Int_t idx=0; idx<fNcells-2; idx++)
344 if (IsUsed(idx) && fArray[idx+1] > maximum)
345 maximum = fArray[idx+1];
346 }
347 return maximum;
348}
349
350// ------------------------------------------------------------------------
351//
352// Call this function to draw the camera layout into your canvas.
353// Setup a drawing canvas. Add this object and all child objects
354// (hexagons, etc) to the current pad. If no pad exists a new one is
355// created.
356//
357// To draw a camera into its own pad do something like:
358//
359// TCanvas *c = new TCanvas;
360// c->Divide(2,1);
361// MGeomCamMagic m;
362// MHCamera *d=new MHCamera(&m);
363// d->FillRandom();
364// c->cd(1);
365// gPad->SetBorderMode(0);
366// gPad->Divide(1,1);
367// gPad->cd(1);
368// d->Draw();
369// d->SetBit(kCanDelete);
370//
371void MHCamera::Draw(Option_t *option)
372{
373 // root 3.02:
374 // gPad->SetFixedAspectRatio()
375 Int_t col = 16;
376
377 if (gPad)
378 col = gPad->GetFillColor();
379
380 TVirtualPad *pad = gPad ? gPad : MH::MakeDefCanvas("CamDisplay", "Mars Camera Display", 656, 600);
381 pad->SetBorderMode(0);
382 pad->SetFillColor(col);
383
384 AppendPad(option);
385}
386
387// ------------------------------------------------------------------------
388//
389// Resizes the current pad so that the camera is displayed in its
390// correct aspect ratio
391//
392void MHCamera::SetRange()
393{
394 const Float_t range = fGeomCam->GetMaxRadius()*1.05;
395
396 //
397 // Maintain aspect ratio
398 //
399 const float ratio = 1.15;
400
401 //
402 // Calculate width and height of the current pad in pixels
403 //
404 Float_t w = gPad->GetWw();
405 Float_t h = gPad->GetWh()*ratio;
406
407 //
408 // This prevents the pad from resizing itself wrongly
409 //
410 if (gPad->GetMother() != gPad)
411 {
412 w *= gPad->GetMother()->GetAbsWNDC();
413 h *= gPad->GetMother()->GetAbsHNDC();
414 }
415
416 //
417 // Set Range (coordinate system) of pad
418 //
419 gPad->Range(-range, -range, (2*ratio-1)*range, range);
420
421 //
422 // Resize Pad to given ratio
423 //
424 if (h<w)
425 gPad->SetPad((1.-h/w)/2, 0, (h/w+1.)/2, 1);
426 else
427 gPad->SetPad(0, (1.-w/h)/2, 1, (w/h+1.)/2);
428}
429
430// ------------------------------------------------------------------------
431//
432// Updates the pixel colors and paints the pixels
433//
434void MHCamera::Update(Bool_t islog, Bool_t isbox, Bool_t iscol)
435{
436 Double_t min = GetMinimum(kFALSE);
437 Double_t max = GetMaximum(kFALSE);
438 if (min==FLT_MAX)
439 {
440 min = 0;
441 max = 1;
442 }
443
444 if (min==max)
445 max += 1;
446
447 UpdateLegend(min, max, islog);
448
449 MHexagon hex;
450 for (Int_t i=0; i<fNcells-2; i++)
451 {
452 if (IsUsed(i) && iscol)
453 {
454 if (TMath::IsNaN(fArray[i+1]))
455 gLog << warn << "MHCamera::Update: " << GetName() << " <" << GetTitle() << "> - Pixel Index #" << i << " contents is NaN (Not a Number)..." << endl;
456
457 hex.SetFillColor(GetColor(fArray[i+1], min, max, islog));
458 }
459 else
460 hex.SetFillColor(10);
461
462 MGeomPix &pix = (*fGeomCam)[i];
463 if (!isbox)
464 hex.PaintHexagon(pix.GetX(), pix.GetY(), pix.GetD());
465 else
466 if (IsUsed(i) && !TMath::IsNaN(fArray[i+1]))
467 {
468 Float_t size = pix.GetD()*(fArray[i+1]-min)/(max-min);
469 if (size>pix.GetD())
470 size=pix.GetD();
471 hex.PaintHexagon(pix.GetX(), pix.GetY(), size);
472 }
473 }
474}
475
476// ------------------------------------------------------------------------
477//
478// Print minimum and maximum
479//
480void MHCamera::Print(Option_t *) const
481{
482 cout << "Minimum: " << GetMinimum();
483 if (fMinimum==-1111)
484 cout << " <autoscaled>";
485 cout << endl;
486 cout << "Maximum: " << GetMaximum();
487 if (fMaximum==-1111)
488 cout << " <autoscaled>";
489 cout << endl;
490}
491
492// ------------------------------------------------------------------------
493//
494// Paint the y-axis title
495//
496void MHCamera::PaintAxisTitle()
497{
498 const Float_t range = fGeomCam->GetMaxRadius()*1.05;
499 const Float_t w = (1 + 1.5/sqrt((float)(fNcells-2)))*range;
500
501 TLatex *ptitle = new TLatex(w, -.90*range, GetYaxis()->GetTitle());
502
503 ptitle->SetTextSize(0.05);
504 ptitle->SetTextAlign(21);
505
506 // box with the histogram title
507 ptitle->SetTextColor(gStyle->GetTitleTextColor());
508#if ROOT_VERSION_CODE > ROOT_VERSION(3,05,01)
509 ptitle->SetTextFont(gStyle->GetTitleFont(""));
510#endif
511 ptitle->Paint();
512}
513
514// ------------------------------------------------------------------------
515//
516// Paints the camera.
517//
518void MHCamera::Paint(Option_t *o)
519{
520 if (fNcells<=1)
521 return;
522
523 TString opt(o);
524 opt.ToLower();
525
526 if (opt.Contains("hist"))
527 {
528 opt.ReplaceAll("hist", "");
529 TH1D::Paint(opt);
530 return;
531 }
532
533 // Maintain aspect ratio
534 SetRange();
535
536 Bool_t isbox = opt.Contains("box");
537 Bool_t iscol = isbox ? !opt.Contains("nocol") : 1;
538
539 GetPainter();
540 if (fPainter)
541 {
542 if (!TestBit(TH1::kNoStats))
543 {
544 fPainter->SetHistogram(this);
545 fPainter->PaintStat(gStyle->GetOptStat(), NULL);
546 }
547
548 // Paint primitives (pixels, color legend, photons, ...)
549 if (fPainter->InheritsFrom(THistPainter::Class()))
550 ((THistPainter*)fPainter)->PaintTitle();
551 }
552
553 // Update Contents of the pixels and paint legend
554 Update(gPad->GetLogy(), isbox, iscol);
555 PaintAxisTitle();
556}
557
558// ------------------------------------------------------------------------
559//
560// With this function you can change the color palette. For more
561// information see TStyle::SetPalette. Only palettes with 50 colors
562// are allowed.
563// In addition you can use SetPalette(52, 0) to create an inverse
564// deep blue sea palette
565//
566void MHCamera::SetPalette(Int_t ncolors, Int_t *colors)
567{
568 //
569 // If not enough colors are specified skip this.
570 //
571 if (ncolors>1 && ncolors<50)
572 {
573 cout << "MHCamera::SetPalette: Only default palettes with 50 colors are allowed... ignored." << endl;
574 return;
575 }
576
577 //
578 // If ncolors==52 create a reversed deep blue sea palette
579 //
580 if (ncolors==52)
581 {
582 gStyle->SetPalette(51, NULL);
583 TArrayI c(kItemsLegend);
584 for (int i=0; i<kItemsLegend; i++)
585 c[kItemsLegend-i-1] = gStyle->GetColorPalette(i);
586 gStyle->SetPalette(kItemsLegend, c.GetArray());
587 }
588 else
589 gStyle->SetPalette(ncolors, colors);
590
591 fColors.Set(kItemsLegend);
592 for (int i=0; i<kItemsLegend; i++)
593 fColors[i] = gStyle->GetColorPalette(i);
594}
595
596
597void MHCamera::SetPrettyPalette()
598{
599 if (!TString(GetDrawOption()).Contains("hist", TString::kIgnoreCase))
600 SetPalette(1, 0);
601}
602
603void MHCamera::SetDeepBlueSeaPalette()
604{
605 if (!TString(GetDrawOption()).Contains("hist", TString::kIgnoreCase))
606 SetPalette(51, 0);
607}
608
609void MHCamera::SetInvDeepBlueSeaPalette()
610{
611 if (!TString(GetDrawOption()).Contains("hist", TString::kIgnoreCase))
612 SetPalette(52, 0);
613}
614
615void MHCamera::DrawPixelIndices()
616{
617 if (fNcells<=1)
618 return;
619
620 // FIXME: Is this correct?
621 for (int i=0; i<kItemsLegend; i++)
622 fColors[i] = 16;
623
624 if (!gPad)
625 Draw();
626
627 TText txt;
628 txt.SetTextFont(122);
629 txt.SetTextAlign(22); // centered/centered
630
631 for (Int_t i=0; i<fNcells-2; i++)
632 {
633 TString num;
634 num += i;
635
636 const MGeomPix &h = (*fGeomCam)[i];
637 TText *nt = txt.DrawText(h.GetX(), h.GetY(), num);
638 nt->SetTextSize(0.3*h.GetD()/fGeomCam->GetMaxRadius()/1.05);
639 }
640}
641
642void MHCamera::DrawSectorIndices()
643{
644 if (fNcells<=1)
645 return;
646
647 for (int i=0; i<kItemsLegend; i++)
648 fColors[i] = 16;
649
650 if (!gPad)
651 Draw();
652
653 TText txt;
654 txt.SetTextFont(122);
655 txt.SetTextAlign(22); // centered/centered
656
657 for (Int_t i=0; i<fNcells-2; i++)
658 {
659 TString num;
660 num += (*fGeomCam)[i].GetSector();
661
662 const MGeomPix &h = (*fGeomCam)[i];
663 TText *nt = txt.DrawText(h.GetX(), h.GetY(), num);
664 nt->SetTextSize(0.3*h.GetD()/fGeomCam->GetMaxRadius()/1.05);
665 }
666}
667
668// ------------------------------------------------------------------------
669//
670// Call this function to add a MCamEvent on top of the present contents.
671// Only 'used' pixels are added.
672//
673void MHCamera::AddCamContent(const MCamEvent &event, Int_t type)
674{
675 if (fNcells<=1)
676 return;
677
678 // FIXME: Security check missing!
679 for (Int_t idx=0; idx<fNcells-2; idx++)
680 {
681 Double_t val=0;
682 if (event.GetPixelContent(val, idx, *fGeomCam, type) && !IsUsed(idx))
683 SetUsed(idx);
684
685 Fill(idx, val); // FIXME: Slow!
686 }
687 fEntries++;
688}
689
690// ------------------------------------------------------------------------
691//
692// Call this function to add a MHCamera on top of the present contents.
693// Only 'used' pixels are added.
694// Type:
695// 0) bin content
696// 1) errors
697// 2) rel. errors
698//
699void MHCamera::AddCamContent(const MHCamera &d, Int_t type)
700{
701 if (fNcells!=d.fNcells)
702 return;
703
704 // FIXME: Security check missing!
705 for (Int_t idx=0; idx<fNcells-2; idx++)
706 if (d.IsUsed(idx))
707 SetUsed(idx);
708
709 switch (type)
710 {
711 case 1:
712 for (Int_t idx=0; idx<fNcells-2; idx++)
713 Fill(idx, d.GetBinError(idx+1));
714 break;
715 case 2:
716 for (Int_t idx=0; idx<fNcells-2; idx++)
717 if (d.GetBinContent(idx+1)!=0)
718 Fill(idx, TMath::Abs(d.GetBinError(idx+1)/d.GetBinContent(idx+1)));
719 break;
720 default:
721 for (Int_t idx=0; idx<fNcells-2; idx++)
722 Fill(idx, d.GetBinContent(idx+1));
723 break;
724 }
725 fEntries++;
726}
727
728// ------------------------------------------------------------------------
729//
730// Call this function to add a TArrayD on top of the present contents.
731// Only 'used' pixels are added.
732//
733void MHCamera::AddCamContent(const TArrayD &event, const TArrayC *used)
734{
735 if (event.GetSize()!=fNcells-2)
736 return;
737
738 if (used && used->GetSize()!=fNcells-2)
739 return;
740
741 for (Int_t idx=0; idx<fNcells-2; idx++)
742 {
743 Fill(idx, const_cast<TArrayD&>(event)[idx]); // FIXME: Slow!
744
745 if (used && (*const_cast<TArrayC*>(used))[idx])
746 SetUsed(idx);
747 }
748 fEntries++;
749}
750
751// ------------------------------------------------------------------------
752//
753// Call this function to add a MCamEvent on top of the present contents.
754// 1 is added to each pixel if the contents of MCamEvent>threshold
755//
756void MHCamera::CntCamContent(const MCamEvent &event, Double_t threshold, Int_t type)
757{
758 if (fNcells<=1)
759 return;
760
761 // FIXME: Security check missing!
762 for (Int_t idx=0; idx<fNcells-2; idx++)
763 {
764 Double_t val=0;
765 if (event.GetPixelContent(val, idx, *fGeomCam, type) && !IsUsed(idx))
766 SetUsed(idx);
767
768 if (val>threshold)
769 Fill(idx);
770 }
771 fEntries++;
772}
773
774// ------------------------------------------------------------------------
775//
776// Call this function to add a TArrayD on top of the present contents.
777// 1 is added to each pixel if the contents of MCamEvent>threshold
778//
779void MHCamera::CntCamContent(const TArrayD &event, Double_t threshold, Bool_t ispos)
780{
781 if (event.GetSize()!=fNcells-2)
782 return;
783
784 for (Int_t idx=0; idx<fNcells-2; idx++)
785 {
786 if (const_cast<TArrayD&>(event)[idx]>threshold)
787 Fill(idx);
788
789 if (!ispos || fArray[idx+1]>0)
790 SetUsed(idx);
791 }
792 fEntries++;
793}
794
795// ------------------------------------------------------------------------
796//
797// Fill the pixels with random contents.
798//
799void MHCamera::FillRandom()
800{
801 if (fNcells<=1)
802 return;
803
804 Reset();
805
806 // FIXME: Security check missing!
807 for (Int_t idx=0; idx<fNcells-2; idx++)
808 {
809 Fill(idx, gRandom->Uniform()*fGeomCam->GetPixRatio(idx));
810 SetUsed(idx);
811 }
812 fEntries=1;
813}
814
815
816// ------------------------------------------------------------------------
817//
818// Fill the colors in respect to the cleaning levels
819//
820void MHCamera::FillLevels(const MCerPhotEvt &event, Float_t lvl1, Float_t lvl2)
821{
822 if (fNcells<=1)
823 return;
824
825 SetCamContent(event, 2);
826
827 for (Int_t i=0; i<fNcells-2; i++)
828 {
829 if (!IsUsed(i))
830 continue;
831
832 if (fArray[i+1]>lvl1)
833 fArray[i+1] = 0;
834 else
835 if (fArray[i+1]>lvl2)
836 fArray[i+1] = 1;
837 else
838 fArray[i+1] = 2;
839 }
840}
841
842// ------------------------------------------------------------------------
843//
844// Fill the colors in respect to the cleaning levels
845//
846void MHCamera::FillLevels(const MCerPhotEvt &event, const MImgCleanStd &clean)
847{
848 FillLevels(event, clean.GetCleanLvl1(), clean.GetCleanLvl2());
849}
850
851// ------------------------------------------------------------------------
852//
853// Reset the all pixel colors to a default value
854//
855void MHCamera::Reset(Option_t *opt)
856{
857 if (fNcells<=1)
858 return;
859
860 TH1::Reset(opt);
861
862 for (Int_t i=0; i<fNcells-2; i++)
863 {
864 fArray[i+1]=0;
865 ResetUsed(i);
866 }
867 fArray[0] = 0;
868 fArray[fNcells-1] = 0;
869}
870
871// ------------------------------------------------------------------------
872//
873// Here we calculate the color index for the current value.
874// The color index is defined with the class TStyle and the
875// Color palette inside. We use the command gStyle->SetPalette(1,0)
876// for the display. So we have to convert the value "wert" into
877// a color index that fits the color palette.
878// The range of the color palette is defined by the values fMinPhe
879// and fMaxRange. Between this values we have 50 color index, starting
880// with 0 up to 49.
881//
882Int_t MHCamera::GetColor(Float_t val, Float_t min, Float_t max, Bool_t islog)
883{
884 if (TMath::IsNaN(val)) // FIXME: gLog!
885 return 10;
886
887 //
888 // first treat the over- and under-flows
889 //
890 const Int_t maxcolidx = kItemsLegend-1;
891
892 if (val >= max)
893 return fColors[maxcolidx];
894
895 if (val <= min)
896 return fColors[0];
897
898 //
899 // calculate the color index
900 //
901 Float_t ratio;
902 if (islog && min>0)
903 ratio = log10(val/min) / log10(max/min);
904 else
905 ratio = (val-min) / (max-min);
906
907 const Int_t colidx = (Int_t)(ratio*maxcolidx + .5);
908 return fColors[colidx];
909}
910
911TPaveStats *MHCamera::GetStatisticBox()
912{
913 TObject *obj = 0;
914
915 TIter Next(fFunctions);
916 while ((obj = Next()))
917 if (obj->InheritsFrom(TPaveStats::Class()))
918 return static_cast<TPaveStats*>(obj);
919
920 return NULL;
921}
922
923// ------------------------------------------------------------------------
924//
925// Change the text on the legend according to the range of the Display
926//
927void MHCamera::UpdateLegend(Float_t min, Float_t max, Bool_t islog)
928{
929 TPaveStats *stats = GetStatisticBox();
930
931 const Float_t hndc = 0.92 - (stats ? stats->GetY1NDC() : 1);
932 const Float_t range = fGeomCam->GetMaxRadius()*1.05;
933 const Float_t H = (0.75-hndc)*range;
934 const Float_t offset = hndc*range;
935
936 const Float_t h = 2./kItemsLegend;
937 const Float_t w = range/sqrt((float)(fNcells-2));
938
939 TBox newbox;
940 TText newtxt;
941 newtxt.SetTextSize(0.03);
942 newtxt.SetTextAlign(12);
943#if ROOT_VERSION_CODE > ROOT_VERSION(3,01,06)
944 newtxt.SetBit(/*kNoContextMenu|*/kCannotPick);
945 newbox.SetBit(/*kNoContextMenu|*/kCannotPick);
946#endif
947
948 const Float_t step = (islog && min>0 ? log10(max/min) : max-min) / kItemsLegend;
949 const Int_t firsts = step*3 < 1e-8 ? 8 : (Int_t)floor(log10(step*3));
950 const TString opt = Form("%%.%if", firsts>0 ? 0 : TMath::Abs(firsts));
951
952 for (Int_t i=0; i<kItemsLegend+1; i+=3)
953 {
954 Float_t val;
955 if (islog && min>0)
956 val = pow(10, step*i) * min;
957 else
958 val = min + step*i;
959
960 //const bool dispexp = max-min>1.5 && fabs(val)>0.1 && fabs(val)<1e6;
961 newtxt.PaintText(range+1.5*w, H*(i*h-1)-offset, Form(opt, val));
962 }
963
964 for (Int_t i=0; i<kItemsLegend; i++)
965 {
966 newbox.SetFillColor(fColors[i]);
967 newbox.PaintBox(range, H*(i*h-1)-offset, range+w, H*((i+1)*h-1)-offset);
968 }
969
970 TArrow arr;
971 arr.PaintArrow(-range*.9, -range*.9, -range*.6, -range*.9, 0.025);
972 arr.PaintArrow(-range*.9, -range*.9, -range*.9, -range*.6, 0.025);
973
974 TString text;
975 text += (int)(range*.3);
976 text += "mm";
977
978 TText newtxt2;
979 newtxt2.SetTextSize(0.04);
980 newtxt2.PaintText(-range*.85, -range*.85, text);
981
982 text = "";
983 text += (float)((int)(range*.3*fGeomCam->GetConvMm2Deg()*10))/10;
984 text += "\\circ";
985 text = text.Strip(TString::kLeading);
986
987 TLatex latex;
988 latex.PaintLatex(-range*.85, -range*.75, 0, 0.04, text);
989}
990
991// ------------------------------------------------------------------------
992//
993// Save primitive as a C++ statement(s) on output stream out
994//
995void MHCamera::SavePrimitive(ofstream &out, Option_t *opt)
996{
997 cout << "MHCamera::SavePrimitive: Must be rewritten!" << endl;
998 /*
999 if (!gROOT->ClassSaved(TCanvas::Class()))
1000 fDrawingPad->SavePrimitive(out, opt);
1001
1002 out << " " << fDrawingPad->GetName() << "->SetWindowSize(";
1003 out << fDrawingPad->GetWw() << "," << fDrawingPad->GetWh() << ");" << endl;
1004 */
1005}
1006
1007// ------------------------------------------------------------------------
1008//
1009// compute the distance of a point (px,py) to the Camera
1010// this functions needed for graphical primitives, that
1011// means without this function you are not able to interact
1012// with the graphical primitive with the mouse!!!
1013//
1014// All calcutations are done in pixel coordinates
1015//
1016Int_t MHCamera::DistancetoPrimitive(Int_t px, Int_t py)
1017{
1018 if (fNcells<=1)
1019 return 999999;
1020
1021 const Int_t kMaxDiff = 7;
1022
1023 TPaveStats *box = (TPaveStats*)gPad->GetPrimitive("stats");
1024 if (box)
1025 {
1026 const Double_t w = box->GetY2NDC()-box->GetY1NDC();
1027 box->SetX1NDC(gStyle->GetStatX()-gStyle->GetStatW());
1028 box->SetY1NDC(gStyle->GetStatY()-w);
1029 box->SetX2NDC(gStyle->GetStatX());
1030 box->SetY2NDC(gStyle->GetStatY());
1031 }
1032
1033 if (TString(GetDrawOption()).Contains("hist", TString::kIgnoreCase))
1034 return TH1D::DistancetoPrimitive(px, py);
1035
1036 for (Int_t i=0; i<fNcells-2; i++)
1037 {
1038 MHexagon hex((*fGeomCam)[i]);
1039 if (hex.DistancetoPrimitive(px, py)==0)
1040 return 0;
1041 }
1042
1043 if (!box)
1044 return 999999;
1045
1046 const Int_t dist = box->DistancetoPrimitive(px, py);
1047 if (dist > kMaxDiff)
1048 return 999999;
1049
1050 gPad->SetSelected(box);
1051 return dist;
1052}
1053
1054// ------------------------------------------------------------------------
1055//
1056// Function introduced (31-01-03) WILL BE REMOVED IN THE FUTURE! DON'T
1057// USE IT!
1058//
1059void MHCamera::SetPix(const Int_t idx, const Int_t color, Float_t min, Float_t max)
1060{
1061 fArray[idx+1] = color;
1062 SetUsed(idx);
1063}
1064
1065// ------------------------------------------------------------------------
1066//
1067//
1068Int_t MHCamera::GetPixelIndex(Int_t px, Int_t py) const
1069{
1070 if (fNcells<=1)
1071 return -1;
1072
1073 Int_t i;
1074 for (i=0; i<fNcells-2; i++)
1075 {
1076 MHexagon hex((*fGeomCam)[i]);
1077 if (hex.DistancetoPrimitive(px, py)>0)
1078 continue;
1079
1080 return i;
1081 }
1082 return -1;
1083}
1084
1085// ------------------------------------------------------------------------
1086//
1087// Returns string containing info about the object at position (px,py).
1088// Returned string will be re-used (lock in MT environment).
1089//
1090char *MHCamera::GetObjectInfo(Int_t px, Int_t py) const
1091{
1092 if (TString(GetDrawOption()).Contains("hist", TString::kIgnoreCase))
1093 return TH1D::GetObjectInfo(px, py);
1094
1095 static char info[128];
1096
1097 const Int_t idx=GetPixelIndex(px, py);
1098
1099 if (idx<0)
1100 return TObject::GetObjectInfo(px, py);
1101
1102 sprintf(info, "Software Pixel Index: %d (Hardware Id=%d)", idx, idx+1);
1103 return info;
1104}
1105
1106// ------------------------------------------------------------------------
1107//
1108// Execute a mouse event on the camera
1109//
1110void MHCamera::ExecuteEvent(Int_t event, Int_t px, Int_t py)
1111{
1112 if (TString(GetDrawOption()).Contains("hist", TString::kIgnoreCase))
1113 {
1114 TH1D::ExecuteEvent(event, px, py);
1115 return;
1116 }
1117 //if (event==kMouseMotion && fStatusBar)
1118 // fStatusBar->SetText(GetObjectInfo(px, py), 0);
1119 if (event!=kButton1Down)
1120 return;
1121
1122 const Int_t idx = GetPixelIndex(px, py);
1123 if (idx<0)
1124 return;
1125
1126 cout << GetTitle() << " <" << GetName() << ">" << endl;
1127 cout << "Software Pixel Index: " << idx << endl;
1128 cout << "Hardware Pixel Id: " << idx+1 << endl;
1129 cout << "Contents: " << fArray[idx+1] << " <";
1130 cout << (IsUsed(idx)?"on":"off");
1131 cout << ">" << endl;
1132
1133 if (fNotify && fNotify->GetSize()>0)
1134 new TCanvas;
1135 fNotify->ForEach(MCamEvent, DrawPixelContent)(idx);
1136}
1137
1138UInt_t MHCamera::GetNumPixels() const
1139{
1140 return fGeomCam->GetNumPixels();
1141}
Note: See TracBrowser for help on using the repository browser.