Line data Source code
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 16 : 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 0 : : TTask("AliMUONPedestalEventGenerator","Generate fake pedestal events"),
86 0 : fCalibrationData(new AliMUONCalibrationData(runNumber)),
87 0 : fDateFileName(filename),
88 0 : fGAliceFileName("galice.root"),
89 0 : fMakeDDL(kTRUE),
90 0 : fLoader(0x0),
91 0 : fPedestals(fCalibrationData->Pedestals()),
92 0 : fDigitStore(0x0),
93 0 : fRawWriter(0x0)
94 0 : {
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 0 : if (!gSystem->IsAbsoluteFileName(fGAliceFileName))
101 : {
102 0 : char* absFileName = gSystem->ConcatFileName(gSystem->WorkingDirectory(),
103 0 : fGAliceFileName);
104 0 : fGAliceFileName = absFileName;
105 0 : delete[] absFileName;
106 0 : }
107 :
108 0 : AliRunLoader* runLoader = LoadRun("recreate");
109 0 : if (!runLoader)
110 : {
111 0 : AliError("Could not create RunLoader");
112 0 : return;
113 : }
114 :
115 0 : runLoader->SetNumberOfEventsPerFile(nevents);
116 :
117 : // Initialize event headers.
118 0 : runLoader->MakeTree("E");
119 :
120 0 : for ( Int_t iEvent = 0; iEvent < nevents; ++iEvent )
121 : {
122 0 : runLoader->SetEventNumber(iEvent);
123 0 : runLoader->GetHeader()->Reset(runNumber,iEvent);
124 0 : runLoader->TreeE()->Fill();
125 : }
126 0 : runLoader->WriteHeader("OVERWRITE");
127 0 : runLoader->CdGAFile();
128 0 : runLoader->Write(0, TObject::kOverwrite);
129 :
130 0 : delete runLoader;
131 0 : fLoader = 0x0;
132 0 : }
133 :
134 :
135 : //_____________________________________________________________________________
136 : AliMUONPedestalEventGenerator::~AliMUONPedestalEventGenerator()
137 0 : {
138 : /// dtor
139 0 : delete fCalibrationData;
140 0 : AliInfo(Form("make a digit counter %d",fgCounter));
141 0 : delete fDigitStore;
142 0 : delete fRawWriter;
143 0 : }
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 0 : AliCodeTimerAuto("",0)
153 :
154 0 : AliInfo("Converting raw to date");
155 :
156 0 : const Int_t kIDet = AliDAQ::DetectorID("MUONTRK");
157 :
158 : const Int_t kNLDCs = 5;//TMath::CeilNint(AliDAQ::NumberOfLdcs(kIDet));
159 :
160 0 : char* path = gSystem->Which(gSystem->Getenv("PATH"), "dateStream");
161 0 : if (!path)
162 : {
163 0 : AliError("the program dateStream was not found");
164 0 : return kFALSE;
165 : }
166 :
167 0 : delete[] path;
168 :
169 0 : AliRunLoader* runLoader = LoadRun("read");
170 0 : if (!runLoader) return kFALSE;
171 :
172 0 : AliInfo(Form("converting raw data DDL files to DATE files %s", fDateFileName.Data()));
173 0 : FILE** pipe = new FILE*[kNLDCs];
174 :
175 0 : for ( Int_t iFile = 0; iFile < kNLDCs; ++iFile)
176 : {
177 0 : char command[256];
178 : // Note the option -s. It is used in order to avoid
179 : // the generation of SOR/EOR events.
180 0 : snprintf(command, 256, "dateStream -c -D -o %s.LDC%d -# %d -C",
181 0 : fDateFileName.Data(), iFile, runLoader->GetNumberOfEvents());
182 0 : pipe[iFile] = gSystem->OpenPipe(command, "w");
183 0 : }
184 :
185 0 : for (Int_t iEvent = 0; iEvent < runLoader->GetNumberOfEvents(); ++iEvent)
186 : {
187 : Float_t ldc = 0;
188 : Int_t prevLDC = -1;
189 :
190 0 : for (Int_t iDDL = 0; iDDL < AliDAQ::NumberOfDdls(kIDet); ++iDDL)
191 : {
192 0 : Int_t ddlID = AliDAQ::DdlID(kIDet,iDDL);
193 0 : Int_t ldcID = Int_t(ldc + 0.0001);
194 0 : ldc += AliDAQ::NumberOfLdcs(kIDet) / AliDAQ::NumberOfDdls(kIDet);
195 :
196 0 : char rawFileName[256];
197 0 : snprintf(rawFileName, 256, "raw%d/%s",
198 0 : iEvent, AliDAQ::DdlFileName(kIDet,iDDL));
199 :
200 : // check existence and size of raw data file
201 0 : FILE* file = fopen(rawFileName, "rb");
202 0 : if (!file) continue;
203 0 : fseek(file, 0, SEEK_END);
204 0 : unsigned long size = ftell(file);
205 0 : fclose(file);
206 0 : if (!size) continue;
207 :
208 0 : if (ldcID != prevLDC) {
209 0 : fprintf(pipe[ldcID], " LDC Id %d\n", ldcID);
210 : prevLDC = ldcID;
211 0 : }
212 0 : fprintf(pipe[ldcID], " Equipment Id %d Payload %s\n", ddlID, rawFileName);
213 0 : }
214 : }
215 :
216 : Int_t result(0);
217 :
218 0 : for ( Int_t iFile = 0; iFile < kNLDCs; ++iFile)
219 : {
220 0 : result += gSystem->ClosePipe(pipe[iFile]);
221 : }
222 :
223 0 : for (Int_t iEvent = 0; iEvent < runLoader->GetNumberOfEvents(); ++iEvent)
224 : {
225 0 : char command[256];
226 0 : snprintf(command, 256, "rm -r raw%d", iEvent);
227 0 : gSystem->Exec(command);
228 0 : }
229 :
230 0 : delete [] pipe;
231 0 : delete runLoader;
232 0 : fLoader=0x0;
233 0 : return (result == 0);
234 0 : }
235 :
236 : //_____________________________________________________________________________
237 : AliMUONVDigitStore*
238 : AliMUONPedestalEventGenerator::DigitStore()
239 : {
240 : /// Return digt container; create it if it does not exist
241 :
242 0 : if (!fDigitStore) fDigitStore = AliMUONVDigitStore::Create("AliMUONDigitStoreV2R");
243 0 : return fDigitStore;
244 : }
245 :
246 : //_____________________________________________________________________________
247 : void
248 : AliMUONPedestalEventGenerator::Exec(Option_t*)
249 : {
250 : /// Main steering method
251 :
252 0 : AliCodeTimerAuto("",0)
253 :
254 0 : if (!fPedestals)
255 : {
256 0 : AliError("No pedestal store. Cannot proceed.");
257 0 : return;
258 : }
259 :
260 0 : AliRunLoader* runLoader = LoadRun("update");
261 :
262 0 : Int_t nevents = runLoader->GetNumberOfEvents();
263 :
264 0 : for ( Int_t i = 0; i < nevents ; ++i )
265 : {
266 0 : runLoader->GetEvent(i);
267 :
268 0 : fLoader->MakeDigitsContainer();
269 0 : TTree* treeD = fLoader->TreeD();
270 0 : if (!treeD)
271 : {
272 0 : AliError(Form("Could not get TreeD for event %d",i));
273 0 : continue;
274 : }
275 :
276 0 : DigitStore()->Connect(*treeD);
277 :
278 0 : GenerateDigits(*(DigitStore()));
279 :
280 : // Fill the output treeD
281 0 : 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 0 : AliCodeTimerStart("WriteDigits")
289 0 : fLoader->WriteDigits("OVERWRITE");
290 0 : AliCodeTimerStop("WriteDigits")
291 :
292 0 : fLoader->UnloadDigits();
293 :
294 0 : if ( fMakeDDL )
295 : {
296 0 : AliCodeTimerAuto("Digits2Raw",1);
297 0 : Digits2Raw(i);
298 0 : }
299 0 : }
300 :
301 0 : runLoader->WriteRunLoader("OVERWRITE");
302 0 : delete runLoader;
303 0 : fLoader = 0x0;
304 :
305 : // Finally, if instructed to do so, convert DDL files to DATE file(s)
306 0 : if ( fMakeDDL && fDateFileName.Length() > 0 )
307 : {
308 0 : AliCodeTimerAuto("ConvertRawFilesToDate",1)
309 0 : Bool_t dateOutput = ConvertRawFilesToDate();
310 0 : if (!dateOutput)
311 : {
312 0 : AliError("DATE output failed. Exiting.");
313 0 : return;
314 : }
315 0 : }
316 0 : }
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 0 : AliCodeTimerAuto("",0)
325 :
326 0 : if (!fRawWriter)
327 : {
328 0 : AliRawDataHeaderSim header;
329 0 : fRawWriter = new AliMUONRawWriter;
330 0 : fRawWriter->SetHeader(header);
331 0 : }
332 :
333 : // Generate RAW data from the digits
334 : // Be carefull to create&change to the correct directory first...
335 :
336 0 : TString baseDir = gSystem->WorkingDirectory();
337 :
338 0 : char dirName[256];
339 0 : snprintf(dirName, 256, "raw%d", event);
340 0 : gSystem->MakeDirectory(dirName);
341 0 : if (!gSystem->ChangeDirectory(dirName))
342 : {
343 0 : AliError(Form("couldn't change to directory %s", dirName));
344 0 : return;
345 : }
346 :
347 0 : fRawWriter->Digits2Raw(DigitStore(),0);
348 :
349 0 : gSystem->ChangeDirectory(baseDir);
350 0 : }
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 0 : AliCodeTimerAuto("",0)
360 :
361 0 : digitStore.Clear();
362 :
363 : Int_t ngenerated(0);
364 : Int_t nmanus(0);
365 0 : TIter next(fPedestals->CreateIterator());
366 : AliMUONVCalibParam* pedestals;
367 :
368 0 : while ( ( pedestals = static_cast<AliMUONVCalibParam*>(next())) )
369 : {
370 0 : Int_t detElemId = pedestals->ID0();
371 0 : Int_t manuId = pedestals->ID1();
372 :
373 0 : AliMpDetElement* de = AliMpDEStore::Instance()->GetDetElement(detElemId);
374 : AliMp::PlaneType planeType = AliMp::kBendingPlane;
375 0 : if ( manuId & AliMpConstants::ManuMask(AliMp::kNonBendingPlane) )
376 : {
377 : planeType = AliMp::kNonBendingPlane;
378 0 : }
379 0 : AliMp::CathodType cathode = de->GetCathodType(planeType);
380 :
381 0 : ++nmanus;
382 :
383 0 : for ( Int_t manuChannel = 0; manuChannel < pedestals->Size(); ++manuChannel )
384 : {
385 0 : Float_t mean = pedestals->ValueAsFloat(manuChannel,0);
386 0 : 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 0 : continue;
392 : }
393 0 : else if ( mean < 1 || mean > 4095 )
394 : {
395 0 : 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 0 : Float_t sigma = pedestals->ValueAsFloat(manuChannel,1);
402 :
403 0 : if ( sigma < 0 )
404 : {
405 0 : 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 0 : }
411 :
412 0 : AliMUONVDigit* d = digitStore.Add(detElemId,manuId,manuChannel,
413 : cathode,
414 : AliMUONVDigitStore::kIgnore);
415 :
416 : Float_t ped = -1;
417 0 : while ( ped <= 0 )
418 : {
419 0 : ped = gRandom->Gaus(mean,sigma);
420 : }
421 0 : Int_t pedADC = TMath::FloorNint(ped);
422 :
423 0 : d->SetADC(pedADC);
424 0 : 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 0 : ++fgCounter;
429 0 : ++ngenerated;
430 : }
431 0 : }
432 : }
433 0 : AliDebug(1,Form("ngenerated=%d nmanus=%d",ngenerated,nmanus));
434 0 : }
435 :
436 : //_____________________________________________________________________________
437 : AliRunLoader*
438 : AliMUONPedestalEventGenerator::LoadRun(const char* mode)
439 : {
440 : /// Get access to AliRunLoader object
441 0 : while (AliRunLoader::Instance())
442 : {
443 0 : AliDebug(1,Form("Deleting AliRunLoader %p",AliRunLoader::Instance()));
444 0 : delete AliRunLoader::Instance();
445 : }
446 :
447 : AliRunLoader* runLoader =
448 0 : AliRunLoader::Open(fGAliceFileName,AliConfig::GetDefaultEventFolderName(),
449 : mode);
450 :
451 0 : AliDebug(1,Form("AliRunLoader(%s)=%p",mode,runLoader));
452 :
453 0 : if (!runLoader)
454 : {
455 0 : AliError("No run loader found in file galice.root");
456 0 : return 0x0;
457 : }
458 :
459 0 : TString smode(mode);
460 0 : smode.ToUpper();
461 :
462 0 : if (smode.Contains("RECREATE"))
463 : {
464 0 : AliInfo("Creating folder structure");
465 0 : AliConfig::Instance()
466 0 : ->CreateDetectorFolders(runLoader->GetEventFolder(),
467 : "MUON", "MUON");
468 0 : fLoader = new AliLoader("MUON",runLoader->GetEventFolder());
469 0 : runLoader->AddLoader(fLoader);
470 : }
471 :
472 0 : fLoader = static_cast<AliLoader*>(runLoader->GetDetectorLoader("MUON"));
473 :
474 : return runLoader;
475 0 : }
|