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