AliMUONStopwatchGroup replaced with AliCodeTimer (Laurent)
[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 "AliMUONDigitStoreV1.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   delete [] pipe;
221   delete runLoader;
222   fLoader=0x0;
223   return (result == 0);
224 }
225
226 //_____________________________________________________________________________
227 AliMUONVDigitStore*
228 AliMUONPedestalEventGenerator::DigitStore()
229 {
230 /// Return digt container; create it if it does not exist
231
232   if (!fDigitStore) fDigitStore = new AliMUONDigitStoreV1;
233   return fDigitStore;
234 }
235
236 //_____________________________________________________________________________
237 void
238 AliMUONPedestalEventGenerator::Exec(Option_t*)
239 {  
240   /// Main steering method
241   
242   AliCodeTimerAuto("")
243   
244   if (!fPedestals)
245   {
246     AliError("No pedestal store. Cannot proceed.");
247     return;
248   }
249   
250   AliRunLoader* runLoader = LoadRun("update");
251   
252   Int_t nevents = runLoader->GetNumberOfEvents();
253     
254   for ( Int_t i = 0; i < nevents ; ++i )
255   {
256     runLoader->GetEvent(i);
257     
258     fLoader->MakeDigitsContainer();
259     TTree* treeD = fLoader->TreeD();  
260     if (!treeD)
261     {
262       AliError(Form("Could not get TreeD for event %d",i));
263       continue;
264     }
265     
266     DigitStore()->Connect(*treeD);
267         
268     GenerateDigits(*(DigitStore()));
269
270     // Fill the output treeD
271     treeD->Fill();
272     
273     // Write to the output tree(D).
274     // Please note that as GlobalTrigger, LocalTrigger and Digits are in the same
275     // tree (=TreeD) in different branches, this WriteDigits in fact writes all of 
276     // the 3 branches.
277
278     AliCodeTimerStart("WriteDigits")
279     fLoader->WriteDigits("OVERWRITE");
280     AliCodeTimerStop("WriteDigits")
281     
282     fLoader->UnloadDigits();
283     
284     if ( fMakeDDL )
285     {
286       Digits2Raw(i);
287     }
288     
289 //    gROOT->ProcessLine(Form("gObjectTable->Print(); > generate.txt.%d",i));
290   }
291     
292   runLoader->WriteRunLoader("OVERWRITE");
293   delete runLoader;
294   fLoader = 0x0;
295     
296   // Finally, if instructed to do so, convert DDL files to DATE file(s)
297   if ( fMakeDDL && fDateFileName.Length() > 0 ) 
298   {
299     Bool_t dateOutput = ConvertRawFilesToDate();
300     if (!dateOutput) 
301     {
302       AliError("DATE output failed. Aborting.");
303       return;
304     }    
305   }
306 }
307
308 //_____________________________________________________________________________
309 void
310 AliMUONPedestalEventGenerator::Digits2Raw(Int_t event)
311 {
312   /// Converts digits (from MUON.Digits.root file) to Raw DDL ascii files.
313   
314   AliCodeTimerAuto("")
315   
316   if (!fRawWriter) fRawWriter = new AliMUONRawWriter;
317   
318   // Generate RAW data from the digits
319   // Be carefull to create&change to the correct directory first...
320   
321   TString baseDir = gSystem->WorkingDirectory();
322   
323   char dirName[256];
324   sprintf(dirName, "raw%d", event);
325   gSystem->MakeDirectory(dirName);
326   if (!gSystem->ChangeDirectory(dirName)) 
327   {
328     AliError(Form("couldn't change to directory %s", dirName));
329     return;
330   }
331   
332   fRawWriter->Digits2Raw(DigitStore(),0);
333   
334   gSystem->ChangeDirectory(baseDir);
335 }
336
337 //_____________________________________________________________________________
338 void
339 AliMUONPedestalEventGenerator::GenerateDigits(AliMUONVDigitStore& digitStore)
340 {  
341   /// Generate digits (where ADC is set to pedestal value) for all MUON TRK
342   /// and for 1 event.
343   
344   AliCodeTimerAuto("")
345
346   digitStore.Clear();
347   
348   Int_t ngenerated(0);
349   Int_t nmanus(0);
350   TIter next(fPedestals->CreateIterator());
351   AliMUONVCalibParam* pedestals;
352   
353   while ( ( pedestals = static_cast<AliMUONVCalibParam*>(next())) )
354   {
355     Int_t detElemId = pedestals->ID0();
356     Int_t manuId = pedestals->ID1();
357     
358     AliMpDetElement* de = AliMpDEStore::Instance()->GetDetElement(detElemId);
359     AliMp::PlaneType planeType = AliMp::kBendingPlane;
360     if ( manuId & AliMpConstants::ManuMask(AliMp::kNonBendingPlane) ) 
361     {
362       planeType = AliMp::kNonBendingPlane;
363     }
364     AliMp::CathodType cathode = de->GetCathodType(planeType);
365     
366     ++nmanus;
367         
368     for ( Int_t manuChannel = 0; manuChannel < pedestals->Size(); ++manuChannel )
369     {
370       Float_t mean = pedestals->ValueAsFloat(manuChannel,0);
371       if (mean == AliMUONVCalibParam::InvalidFloatValue())
372       {
373         // This is a poor's man way of knowing if that channel really exists.
374         // Better and safer way (but much slower too) would be to check pad existence
375         // using AliMpVSegmentation::PadByLocation(AliMpIntPair(manuId,manuChannel))
376         continue;
377       }
378       else
379       {
380         Float_t sigma = pedestals->ValueAsFloat(manuChannel,1);
381         
382
383         AliMUONVDigit* d = digitStore.Add(detElemId,manuId,manuChannel,
384                                           cathode,
385                                           AliMUONVDigitStore::kIgnore);
386         
387         Float_t ped = gRandom->Gaus(mean,sigma);
388         Int_t pedADC = TMath::FloorNint(ped);
389
390         d->SetADC(pedADC);
391         d->SetCharge(ped);
392         // we do not set the remaining parts of the digit, as in principle
393         // this is all we need : manuId, manuChannel and ADC, as far as
394         // real data is concerned.
395         ++fgCounter;
396         ++ngenerated;
397       }
398     }
399   }
400   AliDebug(1,Form("ngenerated=%d nmanus=%d",ngenerated,nmanus));
401 }
402
403 //_____________________________________________________________________________
404 AliRunLoader*
405 AliMUONPedestalEventGenerator::LoadRun(const char* mode)
406 {
407   /// Get access to AliRunLoader object
408   while (AliRunLoader::GetRunLoader()) 
409   {
410     AliDebug(1,Form("Deleting AliRunLoader %p",AliRunLoader::GetRunLoader()));
411     delete AliRunLoader::GetRunLoader();
412   }
413   
414   AliRunLoader* runLoader = 
415     AliRunLoader::Open(fGAliceFileName,AliConfig::GetDefaultEventFolderName(), 
416                        mode);
417
418   AliDebug(1,Form("AliRunLoader(%s)=%p",mode,runLoader));
419   
420   if (!runLoader) 
421   {
422     AliError("No run loader found in file galice.root");
423   }
424     
425   TString smode(mode);
426   smode.ToUpper();
427   
428   if (smode.Contains("RECREATE"))
429   {
430     AliInfo("Creating folder structure");
431     AliConfig::Instance()
432     ->CreateDetectorFolders(runLoader->GetEventFolder(), 
433                             "MUON", "MUON");
434     fLoader = new AliLoader("MUON",runLoader->GetEventFolder());
435     runLoader->AddLoader(fLoader);
436   }
437   
438   fLoader = static_cast<AliLoader*>(runLoader->GetDetectorLoader("MUON"));
439     
440   return runLoader;
441 }