remoe duplicate QA initialisation and do ESD QA for same detectors as RecPoint QA
[u/mrichter/AliRoot.git] / MUON / AliMUONPedestalEventGenerator.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 #include "AliMUONPedestalEventGenerator.h"
19
20 #include "AliHeader.h"
21 #include "AliLog.h"
22 #include "AliMUONCalibrationData.h"
23 #include "AliMUONVDigitStore.h"
24 #include "AliMUONRawWriter.h"
25 #include "AliCodeTimer.h"
26 #include "AliMUONVCalibParam.h"
27 #include "AliMUONVDigit.h"
28 #include "AliMUONVStore.h"
29 #include "AliMpCathodType.h"
30 #include "AliMpConstants.h"
31 #include "AliMpDEStore.h"
32 #include "AliMpDetElement.h"
33 #include "AliMpIntPair.h"
34 #include "AliMpPlaneType.h"
35 #include "AliRunLoader.h"
36 #include <TClonesArray.h>
37 #include <TMath.h>
38 #include <TROOT.h>
39 #include <TRandom.h>
40 #include <TStopwatch.h>
41 #include <TSystem.h>
42 #include "AliDAQ.h"
43
44 //-----------------------------------------------------------------------------
45 /// \class AliMUONPedestalEventGenerator
46 ///
47 /// Generate simulated pedestal events for MUON TRK, to be able to e.g. test
48 /// online calibration routines.
49 ///
50 /// The pedestals themselves are taken from the CDB. What we get from the CDB
51 /// is, per channel, the mean and the sigma of the pedestal. We then use
52 /// those informations to randomly get the pedestals for each channel, for
53 /// each event (picking in a gaus(mean,sigma)).
54 ///
55 /// Output can be just digits, or digits + raw (ddl), or digits + raw (ddl)
56 /// + raw (date files, one per LDC), depending of ctor and MakeDDL() method.
57 ///
58 /// \author L. Aphecetche
59 //-----------------------------------------------------------------------------
60
61 /// \cond CLASSIMP
62 ClassImp(AliMUONPedestalEventGenerator)
63 /// \endcond
64
65 Int_t AliMUONPedestalEventGenerator::fgCounter(0);
66
67 //std::streambuf* RedirectTo(std::ostream& what, std::ostream& to)
68 //{
69 //  std::streambuf* old = what.rdbuf();
70 //  
71 //  std::streambuf* psbuf = to.rdbuf();
72 //  what.rdbuf(psbuf);
73 //  
74 //  return old;
75 //}
76
77 //_____________________________________________________________________________
78 AliMUONPedestalEventGenerator::AliMUONPedestalEventGenerator(Int_t runNumber,
79                                                              Int_t nevents,
80                                                              const char* filename)
81 : TTask("AliMUONPedestalEventGenerator","Generate fake pedestal events"), 
82 fCalibrationData(new AliMUONCalibrationData(runNumber)),
83 fDateFileName(filename),
84 fGAliceFileName("galice.root"),
85 fMakeDDL(kTRUE),
86 fLoader(0x0),
87 fPedestals(fCalibrationData->Pedestals()),
88 fDigitStore(0x0),
89 fRawWriter(0x0)
90 {
91   /// Will generate pedestals according to (mean,sigma)s found in CDB
92   /// for run runNumber.
93   /// Will generate nevents events
94   /// If filename is != "", it will be the basename of the output LDC files
95   ///
96   if (!gSystem->IsAbsoluteFileName(fGAliceFileName)) 
97   {
98     char* absFileName = gSystem->ConcatFileName(gSystem->WorkingDirectory(),
99                                                 fGAliceFileName);
100     fGAliceFileName = absFileName;
101     delete[] absFileName;
102   }
103   
104   AliRunLoader* runLoader = LoadRun("recreate");
105   
106   runLoader->SetNumberOfEventsPerFile(nevents);
107   
108   if (!runLoader)
109   {
110     AliError("Could not create RunLoader");
111     return;
112   }
113   
114   // Initialize event headers.
115   runLoader->MakeTree("E");
116
117   for ( Int_t iEvent = 0; iEvent < nevents; ++iEvent )
118   {
119     runLoader->SetEventNumber(iEvent);
120     runLoader->GetHeader()->Reset(runNumber,iEvent);
121     runLoader->TreeE()->Fill();
122   }
123   runLoader->WriteHeader("OVERWRITE");
124   runLoader->CdGAFile();
125   runLoader->Write(0, TObject::kOverwrite);  
126
127   delete runLoader;
128   fLoader = 0x0;
129 }
130
131
132 //_____________________________________________________________________________
133 AliMUONPedestalEventGenerator::~AliMUONPedestalEventGenerator()
134 {
135   /// dtor
136   delete fCalibrationData;
137   AliInfo(Form("make a digit counter %d",fgCounter));
138   delete fDigitStore;
139   delete fRawWriter;
140 }
141
142 //_____________________________________________________________________________
143 Bool_t 
144 AliMUONPedestalEventGenerator::ConvertRawFilesToDate()
145 {
146   /// convert raw data DDL files to DATE files with the program "dateStream".
147   /// we make one file per LDC
148   
149   AliCodeTimerAuto("")
150   
151   AliInfo("Converting raw to date");
152   
153   const Int_t kIDet = AliDAQ::DetectorID("MUONTRK");
154   
155   const Int_t kNLDCs = TMath::CeilNint(AliDAQ::NumberOfLdcs(kIDet));
156   
157   char* path = gSystem->Which(gSystem->Getenv("PATH"), "dateStream");
158   if (!path) 
159   {
160     AliError("the program dateStream was not found");
161     return kFALSE;
162   }
163   
164   delete[] path;
165   
166   AliRunLoader* runLoader = LoadRun("read");
167   if (!runLoader) return kFALSE;
168   
169   AliInfo(Form("converting raw data DDL files to DATE files %s", fDateFileName.Data()));
170   FILE** pipe = new FILE*[kNLDCs];
171   
172   for ( Int_t iFile = 0; iFile < kNLDCs; ++iFile)
173   {
174     char command[256];
175     // Note the option -s. It is used in order to avoid
176     // the generation of SOR/EOR events.
177     sprintf(command, "dateStream -s -D -o %s.LDC%d -# %d -C", 
178             fDateFileName.Data(), iFile, runLoader->GetNumberOfEvents());
179     pipe[iFile] = gSystem->OpenPipe(command, "w");
180   }
181   
182   for (Int_t iEvent = 0; iEvent < runLoader->GetNumberOfEvents(); ++iEvent) 
183   {
184     Float_t ldc = 0;
185     Int_t prevLDC = -1;
186
187     for (Int_t iDDL = 0; iDDL < AliDAQ::NumberOfDdls(kIDet); ++iDDL) 
188     {        
189       Int_t ddlID = AliDAQ::DdlID(kIDet,iDDL);
190       Int_t ldcID = Int_t(ldc + 0.0001);
191       ldc += AliDAQ::NumberOfLdcs(kIDet) / AliDAQ::NumberOfDdls(kIDet);
192       
193       char rawFileName[256];
194       sprintf(rawFileName, "raw%d/%s", 
195               iEvent, AliDAQ::DdlFileName(kIDet,iDDL));
196       
197       // check existence and size of raw data file
198       FILE* file = fopen(rawFileName, "rb");
199       if (!file) continue;
200       fseek(file, 0, SEEK_END);
201       unsigned long size = ftell(file);
202       fclose(file);
203       if (!size) continue;
204       
205       if (ldcID != prevLDC) {
206         fprintf(pipe[ldcID], " LDC Id %d\n", ldcID);
207         prevLDC = ldcID;
208       }
209       fprintf(pipe[ldcID], "  Equipment Id %d Payload %s\n", ddlID, rawFileName);
210     }
211   }
212   
213   Int_t result(0);
214   
215   for ( Int_t iFile = 0; iFile < kNLDCs; ++iFile)
216   {
217     result += gSystem->ClosePipe(pipe[iFile]);
218   }
219   
220   for (Int_t iEvent = 0; iEvent < runLoader->GetNumberOfEvents(); ++iEvent) 
221   {
222     char command[256];
223     sprintf(command, "rm -r raw%d", iEvent);
224     gSystem->Exec(command);
225   }
226   
227   delete [] pipe;
228   delete runLoader;
229   fLoader=0x0;
230   return (result == 0);
231 }
232
233 //_____________________________________________________________________________
234 AliMUONVDigitStore*
235 AliMUONPedestalEventGenerator::DigitStore()
236 {
237 /// Return digt container; create it if it does not exist
238
239   if (!fDigitStore) fDigitStore = AliMUONVDigitStore::Create("AliMUONDigitStoreV2R");
240   return fDigitStore;
241 }
242
243 //_____________________________________________________________________________
244 void
245 AliMUONPedestalEventGenerator::Exec(Option_t*)
246 {  
247   /// Main steering method
248   
249   AliCodeTimerAuto("")
250   
251   if (!fPedestals)
252   {
253     AliError("No pedestal store. Cannot proceed.");
254     return;
255   }
256   
257   AliRunLoader* runLoader = LoadRun("update");
258   
259   Int_t nevents = runLoader->GetNumberOfEvents();
260     
261   for ( Int_t i = 0; i < nevents ; ++i )
262   {
263     runLoader->GetEvent(i);
264     
265     fLoader->MakeDigitsContainer();
266     TTree* treeD = fLoader->TreeD();  
267     if (!treeD)
268     {
269       AliError(Form("Could not get TreeD for event %d",i));
270       continue;
271     }
272     
273     DigitStore()->Connect(*treeD);
274         
275     GenerateDigits(*(DigitStore()));
276
277     // Fill the output treeD
278     treeD->Fill();
279     
280     // Write to the output tree(D).
281     // Please note that as GlobalTrigger, LocalTrigger and Digits are in the same
282     // tree (=TreeD) in different branches, this WriteDigits in fact writes all of 
283     // the 3 branches.
284
285     AliCodeTimerStart("WriteDigits")
286     fLoader->WriteDigits("OVERWRITE");
287     AliCodeTimerStop("WriteDigits")
288     
289     fLoader->UnloadDigits();
290     
291     if ( fMakeDDL )
292     {
293       AliCodeTimerAuto("Digits2Raw");
294       Digits2Raw(i);
295     }
296   }
297     
298   runLoader->WriteRunLoader("OVERWRITE");
299   delete runLoader;
300   fLoader = 0x0;
301     
302   // Finally, if instructed to do so, convert DDL files to DATE file(s)
303   if ( fMakeDDL && fDateFileName.Length() > 0 ) 
304   {
305     AliCodeTimerAuto("ConvertRawFilesToDate")
306     Bool_t dateOutput = ConvertRawFilesToDate();
307     if (!dateOutput) 
308     {
309       AliError("DATE output failed. Aborting.");
310       return;
311     }    
312   }
313 }
314
315 //_____________________________________________________________________________
316 void
317 AliMUONPedestalEventGenerator::Digits2Raw(Int_t event)
318 {
319   /// Converts digits (from MUON.Digits.root file) to Raw DDL ascii files.
320   
321   AliCodeTimerAuto("")
322   
323   if (!fRawWriter) fRawWriter = new AliMUONRawWriter;
324   
325   // Generate RAW data from the digits
326   // Be carefull to create&change to the correct directory first...
327   
328   TString baseDir = gSystem->WorkingDirectory();
329   
330   char dirName[256];
331   sprintf(dirName, "raw%d", event);
332   gSystem->MakeDirectory(dirName);
333   if (!gSystem->ChangeDirectory(dirName)) 
334   {
335     AliError(Form("couldn't change to directory %s", dirName));
336     return;
337   }
338   
339   fRawWriter->Digits2Raw(DigitStore(),0);
340   
341   gSystem->ChangeDirectory(baseDir);
342 }
343
344 //_____________________________________________________________________________
345 void
346 AliMUONPedestalEventGenerator::GenerateDigits(AliMUONVDigitStore& digitStore)
347 {  
348   /// Generate digits (where ADC is set to pedestal value) for all MUON TRK
349   /// and for 1 event.
350   
351   AliCodeTimerAuto("")
352
353   digitStore.Clear();
354   
355   Int_t ngenerated(0);
356   Int_t nmanus(0);
357   TIter next(fPedestals->CreateIterator());
358   AliMUONVCalibParam* pedestals;
359   
360   while ( ( pedestals = static_cast<AliMUONVCalibParam*>(next())) )
361   {
362     Int_t detElemId = pedestals->ID0();
363     Int_t manuId = pedestals->ID1();
364     
365     AliMpDetElement* de = AliMpDEStore::Instance()->GetDetElement(detElemId);
366     AliMp::PlaneType planeType = AliMp::kBendingPlane;
367     if ( manuId & AliMpConstants::ManuMask(AliMp::kNonBendingPlane) ) 
368     {
369       planeType = AliMp::kNonBendingPlane;
370     }
371     AliMp::CathodType cathode = de->GetCathodType(planeType);
372     
373     ++nmanus;
374         
375     for ( Int_t manuChannel = 0; manuChannel < pedestals->Size(); ++manuChannel )
376     {
377       Float_t mean = pedestals->ValueAsFloat(manuChannel,0);
378       if (mean == AliMUONVCalibParam::InvalidFloatValue())
379       {
380         // This is a poor's man way of knowing if that channel really exists.
381         // Better and safer way (but much slower too) would be to check pad existence
382         // using AliMpVSegmentation::PadByLocation(AliMpIntPair(manuId,manuChannel))
383         continue;
384       }
385       else if ( mean < 1 || mean >  4095 ) 
386       {
387         AliFatal(Form("Got an invalid mean pedestal value for DE %d Manu %d"
388                       " channel %d : mean = %e",detElemId,manuId,manuChannel,
389                       mean));
390       }
391       else
392       {
393         Float_t sigma = pedestals->ValueAsFloat(manuChannel,1);
394         
395         if ( sigma < 0 ) 
396         {
397           AliWarning(Form("Got a negative sigma pedestal value for DE %d Manu %d"
398                           " channel %d : sigma = %e, will use Abs()=%e",
399                           detElemId,manuId,manuChannel,
400                           sigma,-sigma));
401           sigma = -sigma;
402         }
403         
404         AliMUONVDigit* d = digitStore.Add(detElemId,manuId,manuChannel,
405                                           cathode,
406                                           AliMUONVDigitStore::kIgnore);
407         
408         Float_t ped = -1;
409         while ( ped <= 0 ) 
410         {
411           ped = gRandom->Gaus(mean,sigma);
412         }
413         Int_t pedADC = TMath::FloorNint(ped);
414
415         d->SetADC(pedADC);
416         d->SetCharge(ped);
417         // we do not set the remaining parts of the digit, as in principle
418         // this is all we need : manuId, manuChannel and ADC, as far as
419         // real data is concerned.
420         ++fgCounter;
421         ++ngenerated;
422       }
423     }
424   }
425   AliDebug(1,Form("ngenerated=%d nmanus=%d",ngenerated,nmanus));
426 }
427
428 //_____________________________________________________________________________
429 AliRunLoader*
430 AliMUONPedestalEventGenerator::LoadRun(const char* mode)
431 {
432   /// Get access to AliRunLoader object
433   while (AliRunLoader::GetRunLoader()) 
434   {
435     AliDebug(1,Form("Deleting AliRunLoader %p",AliRunLoader::GetRunLoader()));
436     delete AliRunLoader::GetRunLoader();
437   }
438   
439   AliRunLoader* runLoader = 
440     AliRunLoader::Open(fGAliceFileName,AliConfig::GetDefaultEventFolderName(), 
441                        mode);
442
443   AliDebug(1,Form("AliRunLoader(%s)=%p",mode,runLoader));
444   
445   if (!runLoader) 
446   {
447     AliError("No run loader found in file galice.root");
448   }
449     
450   TString smode(mode);
451   smode.ToUpper();
452   
453   if (smode.Contains("RECREATE"))
454   {
455     AliInfo("Creating folder structure");
456     AliConfig::Instance()
457     ->CreateDetectorFolders(runLoader->GetEventFolder(), 
458                             "MUON", "MUON");
459     fLoader = new AliLoader("MUON",runLoader->GetEventFolder());
460     runLoader->AddLoader(fLoader);
461   }
462   
463   fLoader = static_cast<AliLoader*>(runLoader->GetDetectorLoader("MUON"));
464     
465   return runLoader;
466 }