1 /**************************************************************************
2 * Copyright(c) 2004, ALICE Experiment at CERN, All rights reserved. *
4 * Author: The ALICE Off-line Project. *
5 * Contributors are mentioned in the code where appropriate. *
7 * Permission to use, copy, modify and distribute this software and its *
8 * documentation strictly for non-commercial purposes is hereby granted *
9 * without fee, provided that the above copyright notice appears in all *
10 * copies and that both the copyright notice and this permission notice *
11 * appear in the supporting documentation. The authors make no claims *
12 * about the suitability of this software for any purpose. It is *
13 * provided "as is" without express or implied warranty. *
14 **************************************************************************/
16 /** @file AliFMDDisplay.cxx
17 @author Christian Holm Christensen <cholm@nbi.dk>
18 @date Mon Mar 27 12:39:09 2006
19 @brief FMD Event display
21 //___________________________________________________________________
23 // The classes defined here, are utility classes for reading in data
24 // for the FMD. They are put in a seperate library to not polute the
25 // normal libraries. The classes are intended to be used as base
26 // classes for customized class that do some sort of analysis on the
27 // various types of data produced by the FMD.
29 // Latest changes by Christian Holm Christensen
33 #include <TApplication.h>
36 #include <TGeoManager.h>
38 #include <TMarker3DBox.h>
41 #include <TSliderBox.h>
44 #include <TVirtualX.h>
45 #include <TVirtualViewer3D.h>
47 // #include <TArrayF.h>
48 // #include <TParticle.h>
50 #include "AliFMDDisplay.h" // ALIFMDDISPLAY_H
51 #include "AliFMDHit.h" // ALIFMDHIT_H
52 #include "AliFMDDigit.h" // ALIFMDDIGIT_H
53 #include "AliFMDSDigit.h" // ALIFMDSDIGIT_H
54 #include "AliFMDRecPoint.h" // ALIFMDRECPOINT_H
55 #include "AliFMDGeometry.h" // ALIFMDGEOMETRY_H
56 #include "AliFMDParameters.h" // ALIFMDPARAMETERS_H
57 #include <AliESDFMD.h> // ALIESDFMD_H
58 // #include <AliLog.h>
59 #include "AliFMDDebug.h" // Better debug macros
61 //____________________________________________________________________
62 ClassImp(AliFMDDisplay)
64 ; // This is here to keep Emacs for indenting the next line
67 //____________________________________________________________________
68 AliFMDDisplay* AliFMDDisplay::fgInstance = 0;
70 //____________________________________________________________________
71 const AliFMDDisplay::Range_t AliFMDDisplay::fgkEdepRange = { 100, 0., 2. };
72 const AliFMDDisplay::Range_t AliFMDDisplay::fgkAdcRange = { 1024, 0., 1023. };
73 const AliFMDDisplay::Range_t AliFMDDisplay::fgkMultRange = { 500, 0., 20. };
76 //____________________________________________________________________
78 AliFMDDisplay::Instance()
80 // Return static instance
81 // If the instance does not exist
86 //____________________________________________________________________
87 AliFMDDisplay::~AliFMDDisplay()
100 if (fPad) delete fPad;
102 if (fSlider) delete fSlider;
103 if (fCanvas) delete fCanvas;
106 //____________________________________________________________________
107 AliFMDDisplay::AliFMDDisplay(Bool_t onlyFMD, const char* gAliceFile)
108 : AliFMDInput(gAliceFile),
133 // Constructor of an FMD display object.
136 SetName("AliFMDDisplay");
137 SetTitle("3D Display of various kinds of FMD data");
139 if (fgInstance) delete fgInstance;
143 //____________________________________________________________________
145 AliFMDDisplay::MakeCanvas(const char** which)
149 // which Which button to put up.
150 gStyle->SetPalette(1);
151 // gStyle->SetCanvasPreferGL(kTRUE);
154 fCanvas = new TCanvas(Form("gl%s", GetName()),
155 Form("%s - Display", GetTitle()),
156 w, Int_t(w / (1-y1)));
157 fCanvas->SetFillColor(1);
158 fCanvas->ToggleEventStatus();
160 fPad = new TPad("glview", "3DView", 0.0, y1, 1.0, 1.0, 1, 0, 0);
163 const char** p = which;
168 AliInfo(Form("Got %d buttons", n));
174 if (TESTBIT(fTreeMask, kDigits)) {
177 fFactor = new TSlider("pedFactor", "Pedestal Factor", xb+.01, 0, 1, yb);
178 fFactor->SetMethod("AliFMDDisplay::Instance()->ChangeFactor()");
179 fFactor->SetRange(3./10, 1);
182 static_cast<TSliderBox*>(fFactor->GetListOfPrimitives()->
183 FindObject("TSliderBox"));
185 sbox->SetToolTipText("Adjust the noise suppression factor by moving "
189 if (TESTBIT(fTreeMask, kHits) ||
190 TESTBIT(fTreeMask, kESD) ||
191 TESTBIT(fTreeMask, kDigits) ||
192 TESTBIT(fTreeMask, kSDigits) ||
193 TESTBIT(fTreeMask, kRaw)) {
195 fSlider = new TSlider("genCut", "Multiplicity cut", 0, 0, xb, yb);
196 fSlider->SetMethod("AliFMDDisplay::Instance()->ChangeCut()");
197 fSlider->SetRange(0,1);
200 static_cast<TSliderBox*>(fSlider->GetListOfPrimitives()->
201 FindObject("TSliderBox"));
203 sbox->SetToolTipText("Adjust lower and upper limit on data signal");
209 while ((m = *(p++))) {
211 AliInfo(Form("Adding button %s", m));
212 TButton* b = new TButton(m, Form("AliFMDDisplay::Instance()->%s()", m),
213 x0, yb, TMath::Min(x0 + dx,.999F), y1);
221 //____________________________________________________________________
223 AliFMDDisplay::ShowOnlyFMD()
228 if (!fGeoManager) return;
229 static bool once = false;
232 AliInfo("Will only show the FMD");
233 TGeoVolume* top = gGeoManager->GetTopVolume();
234 top->InvisibleAll(kTRUE);
235 TGeoIterator next(top);
238 Bool_t hasFMD1 = kFALSE;
239 Bool_t hasFMD2 = kFALSE;
240 Bool_t hasFMD3 = kFALSE;
241 AliInfo("Getting material FMD_Si$");
242 TGeoMaterial* si = gGeoManager->GetMaterial("FMD_Si$"); // kRed
243 AliInfo("Getting material FMD_Carbon$");
244 TGeoMaterial* c = gGeoManager->GetMaterial("FMD_Carbon$"); // kGray
245 AliInfo("Getting material FMD_Aluminum$");
246 TGeoMaterial* al = gGeoManager->GetMaterial("FMD_Aluminum$");// kGray-2
247 AliInfo("Getting material FMD_Copper$");
248 TGeoMaterial* cu = gGeoManager->GetMaterial("FMD_Copper$"); // kGreen-2
249 AliInfo("Getting material FMD_PCB$");
250 TGeoMaterial* pcb = gGeoManager->GetMaterial("FMD_PCB$"); // kGreen+2
251 AliInfo("Getting material FMD_PCB$");
252 TGeoMaterial* chip = gGeoManager->GetMaterial("FMD_Si Chip$");// kGreen+2
254 while ((node = static_cast<TGeoNode*>(next()))) {
255 const char* name = node->GetName();
257 if (!(v = node->GetVolume())) continue;
259 if (name[0] == 'F') {
260 TGeoMaterial* m = (v->IsAssembly() ? 0 : v->GetMaterial());
262 if (m == si) col = kRed;
263 else if (m == c) col = kGray;
264 else if (m == al) col = kYellow+4;
265 else if (m == cu) col = kRed+6;
266 else if (m == pcb) col = kGreen+2;
267 else if (m == chip) col = kGreen+4;
269 v->SetLineColor(col);
270 v->SetFillColor(col);
272 if (name[2] == 'M' && (name[3] == 'T' || name[3] == 'B')) {
273 // Virtual Master half-ring volume - top-level
274 Int_t det = node->GetNumber();
276 case 1: hasFMD1 = true; break;
277 case 2: hasFMD2 = true; break;
278 case 3: hasFMD3 = true; break;
283 else if (name[3] == 'V' && (name[2] == 'T' || name[2] == 'B'))
284 toshow.Add(v); // Virtual Half-ring, bare detectors
285 else if (name[3] == 'H' && (name[2] == 'F' || name[2] == 'B'))
286 toshow.Add(v); // Virtual Hybrid container
287 else if (name[2] == 'S' && name[3] == 'U')
288 toshow.Add(v); // Virtual support structre
289 // else if (name[3] == 'H' && (name[2] == 'F' || name[2] == 'B'))
290 // toshow.Add(v); // Virtual Hybrid container
292 v->SetVisibility(kFALSE);
293 v->SetVisDaughters(kFALSE);
294 v->InvisibleAll(kTRUE);
297 while ((v = static_cast<TGeoVolume*>(i()))) {
298 if (!v->IsAssembly())
299 v->SetVisibility(kTRUE);
300 v->InvisibleAll(kFALSE);
301 v->SetVisDaughters(kTRUE);
307 //____________________________________________________________________
309 AliFMDDisplay::ExecuteEvent(Int_t event, Int_t px, Int_t py)
311 // Execute an event on canvas
313 // event What happened
314 // px, py Pixel coordinates
315 if (px == 0 && py == 0) return;
316 if (!fZoomMode && fPad->GetView()) {
317 fPad->GetView()->ExecuteRotateView(event, px, py);
320 fPad->SetCursor(kCross);
323 fPad->TAttLine::Modify();
324 fX0 = fPad->AbsPixeltoX(px);
325 fY0 = fPad->AbsPixeltoY(py);
326 fXPixel = fOldXPixel = px;
327 fYPixel = fOldYPixel = py;
332 gVirtualX->DrawBox(fXPixel, fYPixel, fOldXPixel, fOldYPixel,
337 gVirtualX->DrawBox(fXPixel, fYPixel, fOldXPixel, fOldYPixel,
341 fPad->GetCanvas()->FeedbackMode(kFALSE);
342 if (px == fXPixel || py == fYPixel) return;
343 fX1 = fPad->AbsPixeltoX(px);
344 fY1 = fPad->AbsPixeltoY(py);
345 if (fX1 < fX0) std::swap(fX0, fX1);
346 if (fY1 < fY0) std::swap(fY0, fY1);
347 fPad->Range(fX0, fY0, fX1, fY1);
353 //____________________________________________________________________
355 AliFMDDisplay::DistancetoPrimitive(Int_t px, Int_t)
357 // Calculate the distance from point to
358 // something in the canvas.
359 // Depends on the zoom mode.
360 fPad->SetCursor(kCross);
361 Float_t xmin = fPad->GetX1();
362 Float_t xmax = fPad->GetX2();
363 Float_t dx = .02 * (xmax - xmin);
364 Float_t x = fPad->AbsPixeltoX(px);
365 if (x < xmin + dx || x > xmax - dx) return 9999;
366 return (fZoomMode ? 0 : 7);
368 //____________________________________________________________________
370 AliFMDDisplay::Init()
372 // Initialize. GEt transforms and such,
373 // so that we can draw thins properly
374 // Returns true on success
375 if (!AliFMDInput::Init()) return kFALSE;
376 AliFMDGeometry* geom = AliFMDGeometry::Instance();
378 geom->InitTransformations();
379 if (TESTBIT(fTreeMask, kDigits) || TESTBIT(fTreeMask, kRaw))
380 AliFMDParameters::Instance()->Init();
382 fMarkers = new TObjArray;
383 fHits = new TObjArray;
384 fMarkers->SetOwner(kTRUE);
385 fHits->SetOwner(kFALSE);
389 //____________________________________________________________________
391 AliFMDDisplay::MakeAux()
393 // MAke the aux canvas
394 // This is used to display spectra
396 const Range_t* range = 0;
397 if (TESTBIT(fTreeMask, kESD)) range = &fgkMultRange;
398 else if (TESTBIT(fTreeMask, kDigits)) range = &fgkAdcRange;
399 else if (TESTBIT(fTreeMask, kSDigits)) range = &fgkAdcRange;
400 else if (TESTBIT(fTreeMask, kRaw)) range = &fgkAdcRange;
401 else if (TESTBIT(fTreeMask, kHits)) range = &fgkEdepRange;
405 fAux = new TCanvas("aux", "Aux");
407 Float_t dBin = (range->fHigh - range->fLow) / range->fNbins;
408 fSpec = new TH1D("spec", "Spectra", range->fNbins,
409 range->fLow-dBin/2, range->fHigh-dBin/2);
410 fSpecCut = static_cast<TH1*>(fSpec->Clone("specCut"));
411 fSpec->SetFillColor(2);
412 fSpec->SetFillStyle(3001);
413 fSpecCut->SetFillColor(4);
414 fSpecCut->SetFillStyle(3001);
422 //____________________________________________________________________
424 AliFMDDisplay::DrawAux()
426 // Draw in the Aux the canvas
427 // For example draw the spectra
433 fSpecCut->Draw("same");
439 //____________________________________________________________________
441 AliFMDDisplay::Begin(Int_t event)
443 // Begin of event. Make canvas is not already done
445 // event The event number
447 const char* m[] = { "Continue",
459 // AliInfo("Clearing canvas");
462 Warning("End", "No geometry manager");
465 AliInfo("Drawing geometry");
467 fGeoManager->GetTopVolume()->Draw();
468 if (fOnlyFMD) ShowOnlyFMD();
469 AliInfo("Adjusting view");
471 if (fPad->GetView()) {
472 fPad->GetView()->SetView(-200, -40, 80, irep);
473 fPad->GetView()->Zoom();
477 return AliFMDInput::Begin(event);
480 //____________________________________________________________________
482 AliFMDDisplay::AtEnd()
484 // Called at of the event.
495 //____________________________________________________________________
497 AliFMDDisplay::Idle()
500 // Sends the ROOT loop into the idle loop,
501 // so that we can go on.
504 gApplication->StartIdleing();
505 gSystem->InnerLoop();
506 gApplication->StopIdleing();
508 AliInfo("After idle loop");
509 if (fMarkers) fMarkers->Delete();
510 if (fHits) fHits->Clear();
511 AliInfo("After clearing caches");
514 //____________________________________________________________________
518 // End of event. Draw everything
521 if (fReturn) return kFALSE;
522 return AliFMDInput::End();
525 //____________________________________________________________________
527 AliFMDDisplay::LookupColor(Float_t x, Float_t min, Float_t max) const
530 // Get a colour from the current palette depending
531 // on the ratio x/max
532 Float_t range = (max-min);
533 Float_t l = fSlider->GetMinimum();
534 Float_t h = fSlider->GetMaximum();
535 if (l == h) { l = 0; h = 1; }
536 Float_t cmin = range * l;
537 Float_t cmax = range * h;
538 Float_t crange = (cmax-cmin);
539 Int_t idx = Int_t((x-cmin) / crange * gStyle->GetNumberOfColors());
540 return gStyle->GetColorPalette(idx);
543 //____________________________________________________________________
545 AliFMDDisplay::SetCut(Float_t l, Float_t h)
547 // Change the cut on the slider.
548 fSlider->SetMinimum(l);
549 fSlider->SetMaximum(h);
553 //____________________________________________________________________
555 AliFMDDisplay::ChangeCut()
557 // Change the cut on the slider.
558 // The factor depends on what is
559 // drawn in the AUX canvas
560 AliInfo(Form("Range is now %7.5f - %7.5f", fSlider->GetMinimum(),
561 fSlider->GetMaximum()));
562 if ((TESTBIT(fTreeMask, kESD) ||
563 TESTBIT(fTreeMask, kDigits) ||
564 TESTBIT(fTreeMask, kSDigits) ||
565 TESTBIT(fTreeMask, kRaw))) {
566 Float_t l = fSlider->GetMinimum();
567 Float_t h = fSlider->GetMaximum();
570 AliInfo(Form("ADC range is now %4d - %4d", int(l), int(h)));
574 //____________________________________________________________________
576 AliFMDDisplay::ChangeFactor()
578 // Change the cut on the slider.
579 // The factor depends on what is
580 // drawn in the AUX canvas
581 AliInfo(Form("Noise factor is now %4.1f, pedestal factor %3.1f",
582 10*fFactor->GetMinimum(),fFactor->GetMaximum()));
586 //____________________________________________________________________
588 AliFMDDisplay::Redisplay()
591 // Redraw markers, hits,
593 if (fMarkers) fMarkers->Delete();
594 if (fHits) fHits->Clear();
595 if (fSpec) fSpec->Reset();
596 if (fSpecCut) fSpecCut->Reset();
600 //____________________________________________________________________
602 AliFMDDisplay::Break()
605 // Redraw markers, hits,
607 if (fMarkers) fMarkers->Delete();
608 if (fHits) fHits->Clear();
609 if (fSpec) fSpec->Reset();
610 if (fSpecCut) fSpecCut->Reset();
614 //____________________________________________________________________
616 AliFMDDisplay::Render()
619 TVirtualViewer3D* viewer = fPad->GetViewer3D("ogl");
623 //____________________________________________________________________
625 AliFMDDisplay::AddMarker(Float_t x, Float_t y, Float_t z,
626 TObject* o, Float_t s, Float_t min, Float_t max)
628 // Add a marker to the display
634 // o Object to refer to
636 // max Maximum of signal
639 Float_t zsize = (s - min) / (max-min) * 10;
640 Float_t r = TMath::Sqrt(x * x + y * y);
641 Float_t theta = TMath::ATan2(r, z);
642 Float_t phi = TMath::ATan2(y, x);
643 Float_t rz = z + (z < 0 ? 1 : -1) * zsize;
644 TMarker3DBox* marker = new TMarker3DBox(x,y,rz,size,size,zsize,theta,phi);
645 if (o) marker->SetRefObject(o);
646 marker->SetLineColor(LookupColor(s, min, max));
647 fMarkers->Add(marker);
649 //____________________________________________________________________
651 AliFMDDisplay::AddMarker(UShort_t det, Char_t rng, UShort_t sec, UShort_t str,
652 TObject* o, Float_t s, Float_t min, Float_t max)
654 // Add a marker to the display
660 // o Object to refer to
662 // max Maximum of signal
664 AliFMDGeometry* geom = AliFMDGeometry::Instance();
666 geom->Detector2XYZ(det, rng, sec, str, x, y, z);
667 AddMarker(x,y,z,o,s,min,max);
670 //____________________________________________________________________
672 AliFMDDisplay::InsideCut(Float_t val, const Float_t& min,
673 const Float_t& max) const
675 Float_t r = max - min;
676 Float_t l = fSlider->GetMinimum();
677 Float_t h = fSlider->GetMaximum();
678 if (l == h) { l = 0; h = 1; }
679 if (val < r * l + min || val > r * h + min) return kFALSE;
684 //____________________________________________________________________
686 AliFMDDisplay::ProcessHit(AliFMDHit* hit, TParticle* /* p */)
691 static const Float_t rMin = fgkEdepRange.fLow;
692 static const Float_t rMax = fgkEdepRange.fHigh;
694 if (!hit) { AliError("No hit"); return kFALSE; }
695 // if (!p) { AliError("No track"); return kFALSE; }
696 Float_t edep = hit->Edep();
698 if (fHits) fHits->Add(hit);
699 if (fSpec) fSpec->Fill(edep);
700 if (!InsideCut(edep, rMin, rMax)) return kTRUE;
701 if (fSpecCut) fSpecCut->Fill(edep);
703 AddMarker(hit->X(), hit->Y(), hit->Z(), hit, edep, rMin, rMax);
707 //____________________________________________________________________
709 AliFMDDisplay::ProcessDigit(AliFMDDigit* digit)
713 // digit Digit information
714 static const Float_t rMin = fgkAdcRange.fLow;
715 static const Float_t rMax = fgkAdcRange.fHigh;
717 if (!digit) { AliError("No digit"); return kFALSE; }
719 AliFMDParameters* parm = AliFMDParameters::Instance();
720 UShort_t det = digit->Detector();
721 Char_t ring = digit->Ring();
722 UShort_t sec = digit->Sector();
723 UShort_t str = digit->Strip();
724 Double_t ped = parm->GetPedestal(det,ring, sec, str);
725 Double_t pedW = parm->GetPedestalWidth(det,ring, sec, str);
726 Double_t threshold = (ped * fFactor->GetMaximum()
727 + pedW * fFactor->GetMinimum());
728 Float_t counts = digit->Counts();
730 if (fHits) fHits->Add(digit);
731 if (fSpec) fSpec->Fill(counts);
732 if (!InsideCut(counts-threshold, rMin, rMax)) return kTRUE;
733 if (fSpecCut) fSpecCut->Fill(counts);
736 AddMarker(det, ring, sec, str, digit, counts, rMin, rMax);
740 //____________________________________________________________________
742 AliFMDDisplay::ProcessSDigit(AliFMDSDigit* sdigit)
746 // sdigit Digit information
747 static const Float_t rMin = fgkAdcRange.fLow;
748 static const Float_t rMax = fgkAdcRange.fHigh;
750 if (!sdigit) { AliError("No sdigit"); return kFALSE; }
752 UShort_t det = sdigit->Detector();
753 Char_t ring = sdigit->Ring();
754 UShort_t sec = sdigit->Sector();
755 UShort_t str = sdigit->Strip();
756 Float_t counts = sdigit->Counts();
758 if (fHits) fHits->Add(sdigit);
759 if (fSpec) fSpec->Fill(counts);
760 if (!InsideCut(counts, rMin, rMax)) return kTRUE;
761 if (fSpecCut) fSpecCut->Fill(counts);
763 AddMarker(det, ring, sec, str, sdigit, counts, rMin, rMax);
767 //____________________________________________________________________
769 AliFMDDisplay::ProcessRaw(AliFMDDigit* digit)
773 // digit Digit information
774 return ProcessDigit(digit);
777 //____________________________________________________________________
779 AliFMDDisplay::ProcessRecPoint(AliFMDRecPoint* recpoint)
781 // Process reconstructed point
783 // recpoint Reconstructed multiplicity/energy
784 static const Float_t rMin = fgkMultRange.fLow;
785 static const Float_t rMax = fgkMultRange.fHigh;
788 if (!recpoint) { AliError("No recpoint"); return kFALSE; }
790 if (!InsideCut(recpoint->Particles(), rMin, rMax)) return kTRUE;
792 if (fHits) fHits->Add(recpoint);
793 AddMarker(recpoint->Detector(), recpoint->Ring(), recpoint->Sector(),
794 recpoint->Strip(), recpoint, recpoint->Particles(), rMin, rMax);
798 //____________________________________________________________________
800 AliFMDDisplay::ProcessESD(UShort_t det, Char_t rng, UShort_t sec, UShort_t str,
801 Float_t, Float_t mult)
803 // Process data from ESD
805 // det,rng,sec,str Detector coordinates.
806 // mult Multiplicity.
807 static const Float_t rMin = fgkMultRange.fLow;
808 static const Float_t rMax = fgkMultRange.fHigh;
810 Double_t cmult = mult;
811 if (fSpec) fSpec->Fill(cmult);
812 if (!InsideCut(cmult, rMin, rMax) || cmult == AliESDFMD::kInvalidMult)
815 AddMarker(det,rng,sec,str, 0, cmult, rMin, rMax);
817 if (fSpecCut) fSpecCut->Fill(cmult);
822 //____________________________________________________________________