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