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