]> git.uio.no Git - u/mrichter/AliRoot.git/blob - EVE/EveDet/AliEveFMDLoader.cxx
Update master to aliroot
[u/mrichter/AliRoot.git] / EVE / EveDet / AliEveFMDLoader.cxx
1 /**************************************************************************
2  * Copyright(c) 2008, Christian Holm Christensen                          *
3  *                                                                        *
4  * Author: Christian Holm Christensen.                                    *
5  * Contributors are mentioned in the code where appropriate.              *
6  *                                                                        *
7  * Permission to use, copy, modify and distribute this software and its   *
8  * documentation for any purposes is hereby granted without fee,          * 
9  * provided that the above copyright notice appears in all copies and     *
10  * that both the copyright notice and this permission notice remains      *
11  * intact.  The authors make no claims about the suitability of this      * 
12  * software for any purpose. It is provided "as is" without express or    *
13  * implied warranty.                                                      * 
14  **************************************************************************/
15 /* $Id$ */
16 /** @file    AliEveFMDLoader.cxx
17     @author  Christian Holm Christensen <cholm@nbi.dk>
18     @date    Sun Mar 26 17:59:18 2006
19     @brief   Implementation of AliEveFMDLoader singleton class 
20 */
21 //____________________________________________________________________
22 //                                                                          
23 // Forward Multiplicity Detector based on Silicon wafers. This class
24 // is the loader for the event display. 
25 //
26 // This class is a singleton, meaning that there's only one instance
27 // of this.  This is done to speed up the processing by putting all
28 // things that are needed every time into the constructor. 
29 //
30 #include "AliRunLoader.h"
31 #include "AliEveEventManager.h"
32 #include "AliEveFMDLoader.h"
33 #include "AliFMDUShortMap.h"
34 #include "AliFMDBoolMap.h"
35 #include "AliFMDGeometry.h"
36 #include "AliFMDParameters.h"
37 #include "AliFMDDetector.h"
38 #include "AliFMDRing.h"
39 #include "AliFMDBaseDigit.h"
40 #include "AliFMDDigit.h"
41 #include "AliFMDRawReader.h"
42 #include "AliFMDHit.h"
43 #include "AliESDEvent.h"
44 #include "AliESDFMD.h"
45 #include "AliLog.h"
46 #include "AliRawReader.h"
47 #include <TClonesArray.h>
48 #include <TTree.h>
49 #include <TGeoShape.h>
50 #include <TGeoManager.h>
51 #include <TEveGeoNode.h>
52 #include <TEveBoxSet.h>
53 #include <TEveQuadSet.h>
54 #include <TEveManager.h>
55 #include <TEveUtil.h>
56 #include <TStyle.h>
57 #include <TMath.h>
58 #include <iostream>
59
60 // Some very private variables. 
61 namespace 
62 {
63   const Char_t* kDetector = "FMD%d";
64   const Char_t* kRing     = "FMD%d%c";
65   const Char_t* kModule   = "FMD%d%c[%02d-%02d]";
66   const Char_t* kSector   = "FMD%d%c[%02d] %s";
67
68   const Char_t* kHits     = "Hits";
69   const Char_t* kDigits   = "Digits";
70   const Char_t* kRaw      = "Raw";
71   const Char_t* kESD      = "ESD";
72   
73 }
74
75 //____________________________________________________________________
76 AliEveFMDLoader* AliEveFMDLoader::fgInstance = 0;
77
78 //____________________________________________________________________
79 AliEveFMDLoader* AliEveFMDLoader::Instance()
80 {
81   // Get the singleton instance.  If the instance has not been
82   // instantised yet, it will be after this call.
83   if (!fgInstance) 
84     fgInstance = new AliEveFMDLoader();
85   return fgInstance;
86 }
87
88 //____________________________________________________________________
89 AliEveFMDLoader::AliEveFMDLoader(const char* name, Bool_t useBoxes, 
90                                  Bool_t /* old */)
91   : TEveElementList(name, 0), 
92     fHitPalette(0, 1000),
93     fDigitPalette(0, 1023), 
94     fMultPalette(0, 20),
95     fUseBoxDigits(useBoxes), 
96     fHitCache("AliFMDHit",0),
97     fDigitCache("AliFMDDigit", 0),
98     fRawCache("AliFMDDigit", 0)
99 {
100   // Constructor 
101   // Parameters:
102   // @param name     Name of the folder. 
103   // @param useBoxes Whether to use boxes or Quads for the signals 
104   // @param old      Whether to enable reading old RCU data format
105
106   // increase reference count 
107   IncDenyDestroy();
108   
109   // Increase reference counts on palettes 
110   fHitPalette.IncRefCount();
111   fDigitPalette.IncRefCount();
112   fMultPalette.IncRefCount();
113   
114   
115   // Initialize the FMD geometry manager 
116   TGeoManager* geoMan  = AliEveEventManager::AssertGeometry();
117   if (!geoMan) return;
118   geoMan->GetTopVolume()->cd(0);
119
120   AliFMDGeometry* geom = AliFMDGeometry::Instance();
121   geom->Init();
122   geom->InitTransformations();
123
124   AliFMDParameters* pars = AliFMDParameters::Instance();
125   // pars->UseRcuTrailer(!old);
126   // pars->UseCompleteHeader(old);
127   // pars->SetSampleRate(4);
128   pars->Init(kFALSE, 0);
129
130   // Get shapes
131   TGeoShape* inner = static_cast<TGeoShape*>(gGeoManager->GetListOfShapes()
132                                              ->FindObject("FMDI_physical_sensor"));
133   if (!inner) throw TEveException("Shape of inner type sensors not found");
134   TGeoShape* outer = static_cast<TGeoShape*>(gGeoManager->GetListOfShapes()
135                                              ->FindObject("FMDO_physical_sensor"));
136   if (!outer) throw TEveException("Shape of outer type sensors not found");
137
138   // Emulate reference counting 
139   inner->SetUniqueID(1000);
140   outer->SetUniqueID(1000);
141   
142   // Loop over detectors 
143   for (UShort_t d = 1; d <= 3; d++) { 
144     AliFMDDetector*  detector = geom->GetDetector(d);
145     if (!detector) continue;
146     TEveElementList* ed       = new TEveElementList(Form(kDetector, 
147                                                          detector->GetId()));
148     AddElement(ed);
149     ed->IncDenyDestroy();
150     ed->SetUserData(detector);
151
152     // Loop over rings 
153     Char_t           rings[]  = { 'I', 'O', 0 };
154     Char_t*          pr       = &(rings[0]);
155     while (*pr) { 
156       AliFMDRing* ring = detector->GetRing(*pr);
157       pr++;
158       if (!ring) continue;
159       TEveElementList* er      = new TEveElementList(Form(kRing, 
160                                                           detector->GetId(),
161                                                           ring->GetId()));
162       ed->AddElement(er);
163       er->IncDenyDestroy();
164       er->SetUserData(ring);
165       
166       // UShort_t      nsec    = ring->GetNSectors();
167       // UShort_t      nstr    = ring->GetNStrips();
168       UShort_t         nmod    = ring->GetNModules();
169       // Loop over modules 
170       for (UShort_t m = 0; m < nmod; m++) { 
171         TEveGeoShape* em = new TEveGeoShape(Form(kModule, 
172                                                  detector->GetId(),
173                                                  ring->GetId(), 
174                                                  2*m, 2*m+1));
175         er->AddElement(em);
176         em->SetTransMatrix(*(detector->FindTransform(ring->GetId(), 2*m)));
177         em->SetShape(ring->GetId() == 'I' ? inner : outer);
178         em->SetMainColor(Color_t(kGray));
179         em->SetMainTransparency(32);
180         em->IncDenyDestroy();
181         ModuleData* data = new ModuleData;
182         data->fScaledSum = 0;
183         em->SetUserData(data);
184
185 #if 0
186         for (UShort_t s = 2*m; s < 2*m+2 && s < nsec; s++) { 
187           TEveDigitSet* eb = MakeDigitSet(Form(kSector,
188                                                detector->GetId(), 
189                                                ring->GetId(), s), nstr);
190           em->AddElement(eb);
191           eb->SetEmitSignals(kFALSE);
192           eb->SetPickable(kTRUE);
193           // eb->SetOwnIds(kTRUE);
194         } // for (UShort_t s ...)
195 #endif
196       }  // for (UShort_t m ...)
197     }  // while (pr)
198   }  // for (UShort_t d ...)
199 }
200
201 //____________________________________________________________________
202 AliEveFMDLoader::~AliEveFMDLoader()
203 {
204   // Destructor
205   AliWarning("AliEveFMDLoader being destroyed!");
206 }
207
208 //____________________________________________________________________
209 Int_t
210 AliEveFMDLoader::RemoveFromListTrees(TEveElement* el)
211 {
212   // Called when the element should be removed from the list. We
213   // overload this to allow clearing of signals.
214   // Parameters:
215   // @param el Tree to remove from.
216
217   // Since we're most likely setting up for a new event, we clear all
218   // signals here - a little tricky, but it works(tm). 
219   ClearDigitSets("All");
220   
221   // Do normal TEveElement::RemoveElement
222   return TEveElementList::RemoveFromListTrees(el);
223 }
224 //____________________________________________________________________
225 void
226 AliEveFMDLoader::RemoveParent(TEveElement* el)
227 {
228   // Called when the element should be removed from the list. We
229   // overload this to allow clearing of signals.
230   // Parameters:
231   // @param el Parent to remove from.
232   TEveElementList::RemoveParent(el);
233 }
234
235 //____________________________________________________________________
236 TEveDigitSet* 
237 AliEveFMDLoader::MakeDigitSet(const char* name, UShort_t nstr)
238 {
239   // Make a digit set.  The type of digit set depends on the setting
240   // of fUseBoxDigits.  If this is true, we return a TEveBoxSet,
241   // otherwise a TEveQuadSet   
242   // Parameters: 
243   //    name    The name 
244   //    nstr    The number of strips 
245   // Return 
246   //    newly allocated digit set
247   TEveDigitSet* ret = 0;
248   if (fUseBoxDigits) { 
249     TEveBoxSet* boxes = new TEveBoxSet(name);
250     // boxes->Reset(TEveBoxSet::kBT_AABox, kFALSE, nstr);
251     boxes->Reset(TEveBoxSet::kBT_FreeBox, kFALSE, nstr);
252     ret = boxes;
253   }
254   else { 
255     TEveQuadSet* quads = new TEveQuadSet(name);
256     quads->Reset(TEveQuadSet::kQT_RectangleXY, kFALSE, nstr);
257     ret = quads;
258   }
259   return ret;
260 }
261
262 //____________________________________________________________________
263 void
264 AliEveFMDLoader::ClearDigitSets(const char* type)
265 {
266   // Clear signals of some type.   
267   // Parameters:
268   // @param type Type of signals to clear 
269   //     Type can be one of 
270   //     - All    All signals 
271   //     - Hits   Hits 
272   //     - Digits Digits 
273   //     - Raw    Raw 
274   //     - ESD    ESD 
275   TString stype(type);
276
277   for (TEveElement::List_i di = BeginChildren(); 
278        di != EndChildren(); ++di) { 
279     for (TEveElement::List_i ri = (*di)->BeginChildren(); 
280          ri != (*di)->EndChildren(); ++ri) { 
281       for (TEveElement::List_i mi = (*ri)->BeginChildren();
282            mi != (*ri)->EndChildren(); ++mi) { 
283         ModuleData* data = static_cast<ModuleData*>((*mi)->GetUserData());
284         data->fScaledSum = 0;
285         (*mi)->SetMainColor(Color_t(kGray));
286         if (stype == "All") {
287           (*mi)->RemoveElements();
288           continue;
289         }
290         for (TEveElement::List_i si = (*mi)->BeginChildren(); 
291              si != (*mi)->EndChildren(); ++si) { 
292           TEveDigitSet* signals = static_cast<TEveDigitSet*>((*si));
293           if (!signals) continue;
294           TString s(signals->GetName());
295           if (!s.Contains(type)) continue;
296           (*mi)->RemoveElement(signals);
297         }
298       }
299     }
300   }
301 }
302
303 //____________________________________________________________________
304 TEveDigitSet*
305 AliEveFMDLoader::FindDigitSet(const char* t, UShort_t d, Char_t r, UShort_t s)
306 {
307   // Find a digit set corresponding to the passed parameters.  If it
308   // is not found, one is created
309   // Parameters:
310   // @param type   Type of data 
311   // @param d      Detector 
312   // @param r      Ring 
313   // @param s      Sector 
314   // @return a digit set
315   TEveElement* detector = FindChild(Form(kDetector, d));
316   if (!detector) { 
317     AliError(Form("Detector %s not found", Form(kDetector, d)));
318     return 0;
319   }
320   
321   TEveElement* ring = detector->FindChild(Form(kRing, d, r));
322   if (!ring) { 
323     AliError(Form("Ring %s not found", Form(kRing, d, r)));
324     return 0;
325   }
326   
327   Int_t mod = 2*(s/2);
328   TEveElement* module = ring->FindChild(Form(kModule, d, r, mod, mod+1));
329   if (!module) { 
330     AliError(Form("Module %s not found", Form(kModule, d, r, s, s+1)));
331     return 0;
332   }
333   
334   TEveElement*  sector = module->FindChild(Form(kSector, d, r, s, t));
335   TEveDigitSet* signal = static_cast<TEveDigitSet*>(sector);
336   if (!sector) { 
337     AliFMDRing* rng = AliFMDGeometry::Instance()->GetRing(r);
338     signal = MakeDigitSet(Form(kSector, d, r, s, t), rng->GetNStrips());
339     module->AddElement(signal);
340     signal->SetEmitSignals(kFALSE);
341     signal->SetPickable(kTRUE);
342     TString st(t);
343     if      (t == kHits)   signal->SetPalette(&fHitPalette);
344     else if (t == kDigits) signal->SetPalette(&fDigitPalette);
345     else if (t == kRaw)    signal->SetPalette(&fDigitPalette);
346     else if (t == kESD) {
347       signal->SetPalette(&fMultPalette);
348       signal->SetOwnIds(kTRUE);
349     }    
350   }
351   return signal;
352 }
353
354 //____________________________________________________________________
355 void
356 AliEveFMDLoader::AddSignal(const char* t, 
357                            UShort_t det, Char_t rng, UShort_t sec, 
358                            UShort_t str, Float_t signal, Float_t min, 
359                            Float_t  max, TObject* ref)
360 {
361   // Add a signal to a digit set
362   // Parameters:
363   // @param type   Type of data 
364   // @param det    Detector 
365   // @param rng    Ring 
366   // @param sec    Sector 
367   // @param str    Strip
368   // @param signal Signal value 
369   // @param min    Minimum of this kind of signal 
370   // @param max    Maximum of this kind of signal 
371   // @param ref    Reference object 
372   AliFMDGeometry* geom = AliFMDGeometry::Instance();
373   Double_t x, y, z;
374   geom->Detector2XYZ(det, rng, sec, str, x, y, z);
375   AddSignal(t, det, rng, sec, str, x, y, z, signal, min, max, ref);
376 }
377
378 //____________________________________________________________________
379 void
380 AliEveFMDLoader::AddSignal(const char* t, 
381                            UShort_t det, Char_t rng, UShort_t sec, 
382                            UShort_t str, Double_t x, Double_t y, Double_t z, 
383                            Float_t signal, Float_t min, Float_t  max, 
384                            TObject* ref)
385 {
386   // Add a signal to a digit set, with known (x,y,z) coordinates
387   // (this is for hits)
388   // Parameters:
389   // @param type   Type of data 
390   // @param det    Detector 
391   // @param rng    Ring 
392   // @param sec    Sector 
393   // @param str    Strip
394   // @param x      X coordinate  
395   // @param y      Y coordinate  
396   // @param z      Z coordinate  
397   // @param signal Signal value 
398   // @param min    Minimum of this kind of signal 
399   // @param max    Maximum of this kind of signal 
400   // @param ref    Reference object 
401   AliFMDGeometry* geom = AliFMDGeometry::Instance();
402   AliFMDRing*     ring = geom->GetRing(rng);
403   if (!ring) return;
404
405   TEveDigitSet* signals = FindDigitSet(t, det, rng, sec);
406   if (!signals) { 
407     AliWarning(Form("No signal (%s) found for FMD%d%c[%02d,%03d]", 
408                     t, det, rng, sec, str));
409     return;
410   }
411   
412   Float_t  scaled = TMath::Min((signal - min) / (max - min) * 10., 10.);
413   if ((scaled - min) < 1e-6) { 
414     // Very small (scalled) signals are ignored 
415     AliDebug(10, Form("Skipping small %s signal at FMD%d%c[%02d,%03d]=%f (s-min=%f<1e-6)", 
416                       t, det, rng, sec, str, signal, scaled-min));
417     return;
418   }
419   Double_t w      = 2*ring->GetPitch();
420   Int_t    value  = int(TMath::Nint(signal));
421   AliDebug(5, Form("New %s signal at FMD%d%c[%02d,%03d]=%f (v=%d, s=%f)", 
422                    t, det, rng, sec, str, signal, value, scaled));
423   AddDigit(signals, x, y, z, w, scaled, value, ref);
424 }
425
426 //____________________________________________________________________
427 void
428 AliEveFMDLoader::AddDigit(TEveDigitSet* signals, 
429                           Double_t x, Double_t y, Double_t z, 
430                           Double_t w, Float_t scaled, Int_t value, 
431                           TObject* ref)
432 {
433   // Add a digit to a digit set. 
434   // Parameters:
435   // @param signals Digit set. 
436   // @param x      X coordinate  
437   // @param y      Y coordinate  
438   // @param z      Z coordinate  
439   // @param w      strip pitch 
440   // @param scaled Scaled value 
441   // @param value  Signal value 
442   // @param ref    Reference object
443   if (fUseBoxDigits) { 
444     TEveBoxSet* boxes = static_cast<TEveBoxSet*>(signals);
445     Float_t fw   = w;
446     Float_t zc   = (z > 0 ? -1 : 1) * scaled + z;
447     Float_t vs[] = { -fw, -5*fw, zc-scaled,   // Lower back  left
448                      +fw, -5*fw, zc-scaled,   // Lower back  right
449                      +fw, +5*fw, zc-scaled,   // Lower front right
450                      -fw, +5*fw, zc-scaled,   // Lower front left 
451                      -fw, -5*fw, zc+scaled,   // Upper back  left
452                      +fw, -5*fw, zc+scaled,   // Upper back  right
453                      +fw, +5*fw, zc+scaled,   // Upper front right
454                      -fw, +5*fw, zc+scaled }; // Upper front left
455     Float_t ang  = TMath::ATan2(y,x);
456     for (size_t i = 0; i < 8; i++) { 
457       Float_t bx = vs[3*i+0];
458       Float_t by = vs[3*i+1];
459       Float_t ca = TMath::Cos(ang);
460       Float_t sa = TMath::Sin(ang);
461       vs[3*i+0]  = bx * ca - by * sa + x;
462       vs[3*i+1]  = bx * sa + by * ca + y;
463     }
464     // boxes->AddBox(x, y, (z > 0 ? -scaled : 0) + z , 5*w, w, scaled);
465     boxes->AddBox(vs);
466     boxes->DigitValue(value);
467     if (ref) boxes->DigitId(ref);
468   }
469   else { 
470     TEveQuadSet* quads = static_cast<TEveQuadSet*>(signals);
471     quads->AddQuad(x,y,z,w,w);
472     quads->QuadValue(value);
473     if (ref) quads->QuadId(ref);
474   }
475   TEveElement* par  = *(signals->BeginParents());
476   ModuleData*  data = static_cast<ModuleData*>(par->GetUserData());
477   int          maxD = 0;
478   switch (signals->GetName()[4]) { 
479   case 'I': case 'i': maxD = 2 * 512; break;
480   case 'O': case 'o': maxD = 2 * 256; break;
481   default:  return;
482   }
483   data->fScaledSum += scaled / maxD;
484 }
485 //____________________________________________________________________
486 void
487 AliEveFMDLoader::SummarizeModule(TEveElement* module)
488 {
489   // Modify color of module according to the summed signal
490   ModuleData*  data = static_cast<ModuleData*>(module->GetUserData());
491   Float_t      sum  = data->fScaledSum / module->NumChildren();
492   if (sum <= 1e-6) {
493     module->SetMainColor(Color_t(kGray));
494     module->SetMainAlpha(0);
495     return;
496   }
497
498
499   /* The sum stored is 
500    * 
501    *  1/N 1/M_max   S_i^N S_j^M_i x_ij 
502    *
503    * where i runs over the number (N) of digit sets in the module 
504    * (zero or more of  Hits, Digits, Raw, ESD, i.e., in the range from
505    * 0 to 4), j runs over the number of digits (M_i) in a single digit
506    * set, M_max is the possible number of digits sets in each module 
507    * (2*256 for outer rings, 2*512 for inner rings), and x_ij is the 
508    * scaled signal (according to the colour palette for the signal in 
509    * question) multiplied by 10 i.e., 
510    * 
511    *   x_ij = 10 * (s_ij - s_min,i) / (s_max,i - s_min,i)
512    * 
513    * Here, s_ij is the basic signal (E-loss, ADC, or multiplicity), 
514    * and s_min,i and s_max,i are the corresponding limits. 
515    *
516    * Hence, the scaled sum above is in the range from 0 to 10.  
517    *
518    * To use one of the palettes, we need to scale this number to the 
519    * range set in the palette and cast it to an integer. 
520    */
521   int min  = fMultPalette.GetMinVal();
522   int max  = fMultPalette.GetMaxVal();
523   int cidx = int(sum/10 * (max-min) + min);
524   UChar_t pix[3];
525   fMultPalette.ColorFromValue(cidx, pix, false);
526   module->SetMainColorRGB(pix[0], pix[1], pix[2]);
527   module->SetMainAlpha(0.33);
528 }
529
530 //____________________________________________________________________
531 void
532 AliEveFMDLoader::SummarizeModules()
533 {
534   // Summarize the signals in the all the modules, and modify 
535   // the module colour accordingly 
536   
537   for (TEveElement::List_i di = BeginChildren(); 
538        di != EndChildren(); ++di) { 
539     for (TEveElement::List_i ri = (*di)->BeginChildren(); 
540          ri != (*di)->EndChildren(); ++ri) { 
541       for (TEveElement::List_i mi = (*ri)->BeginChildren();
542            mi != (*ri)->EndChildren(); ++mi) { 
543
544         TEveElement* module = *mi;
545         SummarizeModule(module);
546       }
547     }
548   }
549 }
550 //____________________________________________________________________
551 void
552 AliEveFMDLoader::CheckAdd()
553 {
554   // check if we shoul re-add ourselves to the current event node 
555   TEveElement* event = gEve->GetCurrentEvent();
556   SummarizeModules();
557   if (event && event->FindChild(GetName())) return;
558   gEve->AddElement(this);
559 }
560
561
562 //____________________________________________________________________
563 void
564 AliEveFMDLoader::LoadHits()
565 {
566   // Load and display hits
567   ClearDigitSets(kHits);
568
569   AliRunLoader* rl =  AliEveEventManager::AssertRunLoader();
570   if (!rl) { 
571     AliError("No run loader");
572     return;
573   }
574   
575   rl->LoadHits("FMD");
576   TTree* ht = rl->GetTreeH("FMD", false);
577   if (!ht) { 
578     AliError("No FMD tree");
579     return;
580   }
581   
582   TClonesArray* hits = &fHitCache;
583   fHitCache.Clear();
584   ht->SetBranchAddress("FMD", &hits);
585
586   Float_t min = fHitPalette.GetMinVal();
587   Float_t max = fHitPalette.GetMaxVal();
588
589   Int_t nTracks = ht->GetEntriesFast();
590   for (Int_t i = 0; i < nTracks; i++) {
591     Int_t hitRead  = ht->GetEntry(i);
592     if (hitRead <= 0) continue;
593
594     Int_t nHit = hits->GetEntriesFast();
595     if (nHit <= 0) continue;
596   
597     for (Int_t j = 0; j < nHit; j++) {
598       AliFMDHit* hit = static_cast<AliFMDHit*>(hits->At(j));
599       if (!hit) continue;
600   
601       AddSignal(kHits, 
602                 hit->Detector(), hit->Ring(), hit->Sector(), hit->Strip(),
603                 hit->X(), hit->Y(), hit->Z(), int(hit->Edep()*1000), 
604                 min, max, hit);
605     }
606   }
607   CheckAdd();
608 }
609
610 //____________________________________________________________________
611 void
612 AliEveFMDLoader::DoLoadDigits(const char* t, TClonesArray* digits)
613 {
614   // Do the actual display of digits 
615   // Parameters:
616   // @param type What to show 
617   // @param digits The digits
618   Float_t min = fDigitPalette.GetMinVal();
619   Float_t max = fDigitPalette.GetMaxVal();
620
621   Int_t n = digits->GetEntriesFast();
622   for (Int_t i = 0; i < n; i++) { 
623     AliFMDDigit* digit = static_cast<AliFMDDigit*>(digits->At(i));
624     if (!digit) return;
625     AddSignal(t, digit->Detector(), digit->Ring(), digit->Sector(),
626               digit->Strip(), digit->Counts(), min, max, digit);
627   }
628   CheckAdd();
629 }
630
631 //____________________________________________________________________
632 void
633 AliEveFMDLoader::LoadDigits()
634 {
635   // Load and display simulated digits 
636   ClearDigitSets(kDigits);
637
638   AliRunLoader* rl =  AliEveEventManager::AssertRunLoader();
639   if (!rl) { 
640     AliError("No run-loader");
641     return;
642   }
643   
644   rl->LoadDigits("FMD");
645   TTree* dt = rl->GetTreeD("FMD", false);
646   if (!dt) { 
647     AliError("No FMD tree");
648     return;
649   }
650   
651   TClonesArray* digits = &fDigitCache;
652   fDigitCache.Clear();
653   dt->SetBranchAddress("FMD", &digits);
654
655   Int_t read = dt->GetEntry(0);
656   if (read <= 0) { 
657     AliWarning("Nothing read");
658     return;
659   }
660   DoLoadDigits(kDigits, digits);
661 }
662
663
664 //____________________________________________________________________
665 void
666 AliEveFMDLoader::LoadRaw()
667 {
668   // Load and display raw digits 
669   ClearDigitSets(kRaw);
670
671   AliRawReader* rr =  AliEveEventManager::AssertRawReader();
672   if (!rr) { 
673     AliError("No raw-reader");
674     return;
675   }
676   rr->Reset();
677   AliFMDRawReader* fr = new AliFMDRawReader(rr, 0);
678   TClonesArray* digits = &fRawCache;
679   fRawCache.Clear();
680   
681   fr->ReadAdcs(digits);
682   
683   DoLoadDigits(kRaw, digits);
684 }
685
686 //____________________________________________________________________
687 void
688 AliEveFMDLoader::LoadESD()
689 {
690   // Load and display ESD information 
691   
692   ClearDigitSets(kESD);
693
694   AliESDEvent* esd =  AliEveEventManager::AssertESD();
695   if (!esd) { 
696     AliError("No ESD");
697     return;
698   }
699
700   AliESDFMD* fmd = esd->GetFMDData();
701   if (!fmd) { 
702     AliError("No FMD ESD data");
703     return;
704   }
705
706   Float_t min = fMultPalette.GetMinVal();
707   Float_t max = fMultPalette.GetMaxVal();
708   
709   for (UShort_t det = 1; det <= 3; det++) {
710     Char_t rings[] = { 'I', (det == 1 ? '\0' : 'O'), '\0' };
711     for (Char_t* rng = rings; *rng != '\0'; rng++) {
712       UShort_t nsec = (*rng == 'I' ?  20 :  40);
713       UShort_t nstr = (*rng == 'I' ? 512 : 256);
714       for (UShort_t sec = 0; sec < nsec; sec++) {
715         for (UShort_t str = 0; str < nstr; str++) {
716           Float_t mult = fmd->Multiplicity(det,*rng,sec,str);
717           if (mult == AliESDFMD::kInvalidMult) continue;
718           Float_t eta  = fmd->Eta(det,*rng,sec,str);
719           
720         // As it was before, it causes big memory leak:
721 //        AddSignal(kESD, det, *rng, sec, str, mult, min, max,
722 //                  new TNamed(Form("FMD%d%c[%02d,%03d]", det, *rng, sec, str),
723 //                             Form("Mch=%f, eta=%f", mult, eta)));
724                 
725         // I propose to replace it with:
726         TNamed *tmpNamed = new TNamed(Form("FMD%d%c[%02d,%03d]", det, *rng, sec, str),Form("Mch=%f, eta=%f", mult, eta));
727         AddSignal(kESD, det, *rng, sec, str, mult, min, max,tmpNamed);
728         if(tmpNamed)delete tmpNamed;
729         //
730         
731         }
732       }
733     }
734   }
735   CheckAdd();
736 }
737   
738 //____________________________________________________________________
739 //
740 // EOF
741 //