Merge branch 'master' of https://git.cern.ch/reps/AliRoot
[u/mrichter/AliRoot.git] / MUON / AliMUONTrackerDataMaker.cxx
1 /**************************************************************************
2 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
3 *                                                                        *
4 * Author: The ALICE Off-line Project.                                    *
5 * Contributors are mentioned in the code where appropriate.              *
6 *                                                                        *
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 **************************************************************************/
15
16 // $Id$
17
18 /// \class AliMUONTrackerDataMaker
19 /// 
20 /// Implementation of VTrackerDataMaker to read raw data and 
21 /// calibrate it (if required)
22 /// 
23 /// \author Laurent Aphecetche, Subatech
24
25 #include "AliMUONTrackerDataMaker.h"
26
27 #include "AliCDBManager.h"
28 #include "AliCDBStorage.h"
29 #include "AliCodeTimer.h"
30 #include "AliDAQ.h"
31 #include "AliLog.h"
32 #include "AliMUON2DMap.h"
33 #include "AliMUONCalibParamND.h"
34 #include "AliMUONCalibrationData.h"
35 #include "AliMUONDigitCalibrator.h"
36 #include "AliMUONLogger.h"
37 #include "AliMUONRawStreamTrackerHP.h"
38 #include "AliMUONTrackerData.h"
39 #include "AliMpDDLStore.h"
40 #include "AliRawEventHeaderBase.h"
41 #include "AliRawReader.h"
42 #include "Riostream.h"
43
44 using std::endl;
45 using std::cout;
46 /// \cond CLASSIMP
47 ClassImp(AliMUONTrackerDataMaker)
48 /// \endcond
49
50 Int_t AliMUONTrackerDataMaker::fgkCounter(0);
51
52 //_____________________________________________________________________________
53 AliMUONTrackerDataMaker::AliMUONTrackerDataMaker(TRootIOCtor*) 
54
55 AliMUONVTrackerDataMaker(),
56 fRawReader(0x0),
57 fAccumulatedData(0x0),
58 fIsOwnerOfAccumulatedData(kTRUE),
59 fOneEventData(0x0),
60 fDigitCalibrator(0x0),
61 fCalibrationData(0x0), 
62 fSource(""),
63 fOCDBPath(""),
64 fNumberOfEvents(0),
65 fRunNumber(0),
66 fIsRunning(kFALSE),
67 fIsOwnerOfRawReader(kFALSE),
68 fIsEventByEvent(kFALSE),
69 fLogger(0x0),
70 fLastEventWasEmpty(kFALSE),
71 fNumberOfPhysicsEvents(0),
72 fNumberOfGoodPhysicsEvents(0),
73 fTryRecover(kFALSE),
74 fFirstEvent(-1),
75 fLastEvent(-1)
76 {
77 /// Root IO ctor
78 }
79
80 //_____________________________________________________________________________
81 AliMUONTrackerDataMaker::AliMUONTrackerDataMaker(const AliMUONRecoParam* recoParam,
82                                                  Int_t runNumber,
83                                                  AliRawReader* rawReader,
84                                                  const char* cdbPath,
85                                                  const char* calibMode,
86                                                  Bool_t histogram,
87                                                  Double_t xmin,
88                                                  Double_t xmax)
89 :
90 AliMUONVTrackerDataMaker(),
91 fRawReader(rawReader),
92 fAccumulatedData(0x0),
93 fIsOwnerOfAccumulatedData(kTRUE),
94 fOneEventData(new AliMUON2DMap(true)),
95 fDigitCalibrator(0x0),
96 fCalibrationData(0x0), 
97 fSource(""),
98 fOCDBPath(cdbPath),
99 fNumberOfEvents(0),
100 fRunNumber(runNumber),
101 fIsRunning(kFALSE),
102 fIsOwnerOfRawReader(kFALSE),
103 fIsEventByEvent(kFALSE),
104 fLogger(0x0),
105 fLastEventWasEmpty(kFALSE),
106 fNumberOfPhysicsEvents(0),
107 fNumberOfGoodPhysicsEvents(0),
108 fTryRecover(kFALSE),
109 fFirstEvent(-1),
110 fLastEvent(-1)
111 {
112   /// Ctor in which this object will NOT be the owner of the reader
113   /// and can NOT apply rewind to it, nor use Next on it. 
114   Ctor(recoParam,runNumber,calibMode,histogram,xmin,xmax);
115 }
116
117
118 //_____________________________________________________________________________
119 AliMUONTrackerDataMaker::AliMUONTrackerDataMaker(const AliMUONRecoParam* recoParam,
120                                                  AliRawReader* rawReader,
121                                                  const char* cdbPath,
122                                                  const char* calibMode,
123                                                  Bool_t histogram,
124                                                  Double_t xmin,
125                                                  Double_t xmax)
126 :
127 AliMUONVTrackerDataMaker(),
128 fRawReader(rawReader),
129 fAccumulatedData(0x0),
130 fIsOwnerOfAccumulatedData(kTRUE),
131 fOneEventData(new AliMUON2DMap(true)),
132 fDigitCalibrator(0x0),
133 fCalibrationData(0x0), 
134 fSource(""),
135 fOCDBPath(cdbPath),
136 fNumberOfEvents(0),
137 fRunNumber(0),
138 fIsRunning(kFALSE),
139 fIsOwnerOfRawReader(kTRUE),
140 fIsEventByEvent(kFALSE),
141 fLogger(0x0),
142 fLastEventWasEmpty(kFALSE),
143 fNumberOfPhysicsEvents(0),
144 fNumberOfGoodPhysicsEvents(0),
145 fTryRecover(kFALSE),
146 fFirstEvent(-1),
147 fLastEvent(-1)
148 {
149   /// Ctor in which we take the ownership of the rawReader, so we can rewind
150   /// and advance it as we wish
151   
152   if ( fRawReader && fRawReader->NextEvent() ) 
153   {
154     fRunNumber = fRawReader->GetRunNumber();
155     fRawReader->RewindEvents();
156   }
157   
158   Ctor(recoParam,fRunNumber,calibMode,histogram,xmin,xmax);
159 }
160
161 //_____________________________________________________________________________
162 AliMUONTrackerDataMaker::AliMUONTrackerDataMaker(AliRawReader* rawReader, Bool_t histogram)
163 :
164 AliMUONVTrackerDataMaker(),
165 fRawReader(rawReader),
166 fAccumulatedData(0x0),
167 fIsOwnerOfAccumulatedData(kTRUE),
168 fOneEventData(new AliMUON2DMap(true)),
169 fDigitCalibrator(0x0),
170 fCalibrationData(0x0), 
171 fSource(""),
172 fOCDBPath(""),
173 fNumberOfEvents(0),
174 fRunNumber(0),
175 fIsRunning(kFALSE),
176 fIsOwnerOfRawReader(kTRUE),
177 fIsEventByEvent(kFALSE),
178 fLogger(0x0),
179 fLastEventWasEmpty(kFALSE),
180 fNumberOfPhysicsEvents(0),
181 fNumberOfGoodPhysicsEvents(0),
182 fTryRecover(kFALSE),
183 fFirstEvent(-1),
184 fLastEvent(-1)
185 {
186   /// Ctor from raw data reader
187   if ( fRawReader && fRawReader->NextEvent() ) 
188   {
189     fRunNumber = fRawReader->GetRunNumber();
190     fRawReader->RewindEvents();
191   }
192   
193   Ctor(0x0,fRunNumber,"",histogram);
194   
195 }
196
197 //_____________________________________________________________________________
198 void 
199 AliMUONTrackerDataMaker::Ctor(const AliMUONRecoParam* recoParam,
200                               Int_t runNumber,
201                               const char* calibMode,
202                               Bool_t histogram,
203                               Double_t xmin, Double_t xmax)
204 {
205   /// "designated constructor"
206
207   Bool_t calibrate = ( strlen(calibMode) > 0 );
208   
209   TString name;
210   TString type("RAW");
211   
212   if ( calibrate ) 
213   {
214     TString scalib(calibMode);
215     scalib.ToUpper();
216     if ( scalib == "GAIN" ) type = "CALC";
217     if ( scalib == "NOGAIN" ) type = "CALZ";
218     if ( scalib == "GAINCONSTANTCAPA") type = "CALG";
219     if ( scalib == "INJECTIONGAIN" ) type = "CALE";
220   }
221   
222   if ( !fRunNumber ) 
223   {
224     ++fgkCounter;
225     name = Form("%s%s_%d",(histogram?"H":""),type.Data(),fgkCounter);
226   }
227   else
228   {
229     name = Form("%s%s%d",(histogram?"H":""),type.Data(),fRunNumber);
230   }
231   
232   fAccumulatedData = new AliMUONTrackerData(name.Data(),"charge values",1);
233   fAccumulatedData->SetDimensionName(0,(calibrate ? "Calibrated charge" : "Raw charge"));
234   if (histogram)
235   {
236     fAccumulatedData->MakeHistogramForDimension(0,kTRUE,xmin,xmax);
237   }
238   
239   if ( calibrate ) 
240   {
241     fCalibrationData = new AliMUONCalibrationData(runNumber);
242     
243     // force the reading of calibration NOW
244     // FIXME: not really elegant and error prone (as we have the list of calib data twice, 
245     // once here and once in the digitcalibrator class, hence the change of them getting
246     // out of sync)
247     // But with the current CDBManager implementation, I don't know how to solve
248     // this better (e.g. to avoid clearing cache messages and so on).
249
250     AliCDBStorage* storage(0x0);
251     
252     if ( fOCDBPath.Length() > 0 )
253     {
254       storage = AliCDBManager::Instance()->GetDefaultStorage();
255
256       if ( storage && ( storage->GetURI() != fOCDBPath.Data() ) )
257       {
258         AliCDBManager::Instance()->SetDefaultStorage(fOCDBPath.Data());
259       }
260     }
261     
262     fCalibrationData->Pedestals();
263     fCalibrationData->Gains();
264     fCalibrationData->Neighbours();
265     fCalibrationData->HV();
266     fCalibrationData->Capacitances();
267     
268     if ( storage && ( storage->GetURI() != fOCDBPath.Data() ) )
269     {
270       AliCDBManager::Instance()->SetDefaultStorage(storage);
271     }
272     
273     fDigitCalibrator = new AliMUONDigitCalibrator(*fCalibrationData,recoParam);
274     //FIXME: get the reco param from GUI and/or from OCDB if not used from the QA code ?
275   }
276 }
277
278 //_____________________________________________________________________________
279 AliMUONTrackerDataMaker::~AliMUONTrackerDataMaker()
280 {
281 /// dtor
282
283   delete fOneEventData;
284   if ( fIsOwnerOfAccumulatedData ) delete fAccumulatedData;
285   if ( fIsOwnerOfRawReader ) delete fRawReader;
286   delete fCalibrationData;
287   delete fDigitCalibrator;
288 }
289
290 //_____________________________________________________________________________
291 Bool_t 
292 AliMUONTrackerDataMaker::Add(const AliMUONTrackerDataMaker& other)
293 {
294   /// Adds other to this
295     
296   if (!fAccumulatedData) return kFALSE;
297   
298   if ( fIsEventByEvent )
299   {
300     AliError("Cannot add event by event objects !");
301     return kFALSE;
302   }
303   
304   if ( fRunNumber != other.fRunNumber ) fRunNumber = -1;
305   
306   fSource += "\n";
307   fSource += other.fSource;
308   
309   fNumberOfEvents += other.fNumberOfEvents;
310   fNumberOfPhysicsEvents += other.fNumberOfPhysicsEvents;
311   fNumberOfGoodPhysicsEvents += other.fNumberOfGoodPhysicsEvents;
312
313   TList list;
314   list.Add(other.fAccumulatedData);
315   
316   fAccumulatedData->Merge(&list);
317   
318   return kTRUE;
319 }
320
321 //_____________________________________________________________________________
322 Bool_t 
323 AliMUONTrackerDataMaker::NextEvent()
324 {
325   /// Read and process next event
326   
327   if ( !fIsOwnerOfRawReader ) 
328   {
329     AliError("I'm not the owner of the raw reader. Cannot use NextEvent");
330     return kFALSE;
331   }
332   
333   AliCodeTimerAuto("",0);
334   
335   if ( !IsRunning() ) return kTRUE;
336   
337   Bool_t ok(kTRUE);
338   
339   if ( fLastEvent >= fFirstEvent && fLastEvent > 0 ) // do we have an event range to consider ?
340   {
341     // skip up to first event
342     
343     while ( (fNumberOfEvents-1) < fFirstEvent && ( ok = fRawReader->NextEvent() ) ) 
344     {
345       ++fNumberOfEvents; 
346     }
347     
348     if ( ok && (fNumberOfEvents-1) <= fLastEvent ) 
349     {
350       ok = fRawReader->NextEvent();
351     }
352     else
353     {
354       fNumberOfEvents=fLastEvent+1;
355       return kFALSE;
356     }
357   }
358   else
359   {
360     // no event range, just proceed...
361     ok = fRawReader->NextEvent();
362   }
363   
364   if (!ok) 
365   {
366     return kFALSE;
367   }
368   
369         ProcessEvent();
370         
371         return kTRUE;  
372 }
373
374 //_____________________________________________________________________________
375 Bool_t AliMUONTrackerDataMaker::ProcessEvent()
376 {
377   /// Process current event 
378   /// 
379   /// Note that in case of calibration, we do not simply reuse the 
380   /// AliMUONDigitCalibrator::Calibrate(AliMUONVDigitStore&) method, 
381   /// as this would require filling first a digitStore, and then calibrate it,
382   /// and then convert it into a VStore, all this taking too much time.
383   /// But we *do* reuse the AliMUONDigitCalibrator::CalibrateDigit in order not to 
384   /// duplicate this critical piece of calibration code !
385   ///
386   
387   ++fNumberOfEvents;
388   
389   Int_t eventType = fRawReader->GetType();
390   
391   if (eventType != AliRawEventHeaderBase::kPhysicsEvent ) 
392   {
393     return kTRUE; // for the moment
394   }
395   
396   ++fNumberOfPhysicsEvents;
397   
398   fLastEventWasEmpty = kFALSE;
399   
400   AliCodeTimerAuto("",0);
401   
402   AliMUONRawStreamTrackerHP stream(fRawReader);
403
404   stream.DisableWarnings();
405   stream.DisableRawReaderErrorLogger();
406   stream.DisableMUONErrorLogger();
407
408   if ( fTryRecover ) 
409   {
410     stream.TryRecover(kTRUE);
411   }
412   else
413   {
414     stream.TryRecover(kFALSE);
415   }
416   
417   if (fLogger)
418   {
419     stream.EnableMUONErrorLogger();  
420     stream.SetMUONErrorLogger(fLogger);    
421     stream.SetLoggingDetailLevel(AliMUONRawStreamTrackerHP::kMediumErrorDetail);
422   }
423   
424   const Int_t nddls = AliDAQ::NumberOfDdls("MUONTRK");
425   TArrayI nevents(nddls);
426   
427   for ( Int_t i = 0; i < nddls; ++i ) 
428   {
429     nevents[i] = 0;
430   }
431   
432   fOneEventData->Clear();
433   
434   Int_t buspatchId;
435   UShort_t  manuId;
436   UChar_t manuChannel;
437   UShort_t adc;
438   
439   stream.First();
440   
441   while ( stream.Next(buspatchId,manuId,manuChannel,adc,kTRUE) )
442   {    
443     Int_t detElemId = AliMpDDLStore::Instance()->GetDEfromBus(buspatchId);
444     
445     Int_t ddl = AliMpDDLStore::Instance()->GetDDLfromBus(buspatchId);
446     
447     nevents[ddl] = 1;
448     
449     AliMUONVCalibParam* param = static_cast<AliMUONVCalibParam*>(fOneEventData->FindObject(detElemId,manuId));
450     if (!param)
451     {
452       param = new AliMUONCalibParamND(1,64,detElemId,manuId,
453                                       AliMUONVCalibParam::InvalidFloatValue());
454       fOneEventData->Add(param);
455     }
456     
457     Double_t charge(adc);
458     
459     if ( fDigitCalibrator ) 
460     {
461       if ( fDigitCalibrator->IsValidDigit(detElemId, manuId, manuChannel) )
462       {
463         charge = fDigitCalibrator->CalibrateDigit(detElemId, manuId, manuChannel,adc);
464       }
465       else
466       {
467         charge = 0.0;
468       }
469     }
470     
471     if (charge > 0.0 ) 
472     {
473       param->SetValueAsDouble(manuChannel,0,charge);
474     }
475   }
476   
477         Bool_t badEvent = stream.HasPaddingError() || stream.HasGlitchError();
478
479         if (!badEvent)
480   {
481     fAccumulatedData->Add(*fOneEventData,&nevents);  
482     if ( fOneEventData->GetSize() == 0 ) fLastEventWasEmpty = kTRUE;
483     ++fNumberOfGoodPhysicsEvents;
484   }
485     
486   AliDebug(1,Form("n %10d nphysics %10d ngood %10d",fNumberOfEvents,fNumberOfPhysicsEvents,fNumberOfGoodPhysicsEvents));
487         
488   return !badEvent;
489 }
490
491
492 //_____________________________________________________________________________
493 void 
494 AliMUONTrackerDataMaker::Print(Option_t*) const
495 {
496   /// Printout
497   
498   cout << "Source=" << Source() << " Running=" << ( IsRunning() ? "YES" : "NO")
499   << endl;
500 }
501
502 //_____________________________________________________________________________
503 void AliMUONTrackerDataMaker::Rewind()
504 {
505   /// Rewind events
506   if ( fIsOwnerOfRawReader ) 
507   {
508     fRawReader->RewindEvents();
509     fNumberOfEvents=0;  
510     fNumberOfPhysicsEvents=0;
511     fNumberOfGoodPhysicsEvents=0;
512   }
513   else
514   {
515     AliError("Wrong usage of this class : cannot rewind as I am not owner of the raw reader !");
516   }
517 }
518
519 //_____________________________________________________________________________
520 Long64_t AliMUONTrackerDataMaker::Merge(TCollection* list)
521 {
522   /// Merge objects in collection
523   
524   if (!list) return 0;
525   
526   if ( list->IsEmpty() ) return NumberOfEvents();
527   
528   TIter next(list);
529   const TObject* o(0x0);
530   
531   while ( ( o = next() ) )
532   {
533     const AliMUONTrackerDataMaker* data = dynamic_cast<const AliMUONTrackerDataMaker*>(o);
534     if (!data)
535     {
536       AliError(Form("Object named %s is not an AliMUONTrackerDataMaker ! Skipping it",
537                     o->GetName()));
538     }
539     else
540     {
541       Bool_t ok = Add(*data);
542       if (!ok)
543       {
544         AliError("Got incompatible objects");
545       }
546     }
547   }
548   
549   return NumberOfEvents();
550 }
551
552 //_____________________________________________________________________________
553 void 
554 AliMUONTrackerDataMaker::SetRawReader(AliRawReader* rawReader)
555 {
556   /// Change the rawreader (only works if isowner=true)
557   
558   if ( fIsOwnerOfRawReader ) 
559         {
560     AliFatal("Improper use of this class ! Cannot change raw reader in this case");
561         }
562         
563   fRawReader = rawReader;
564   
565 }