activating individual HLT simulations from digits and raw data
[u/mrichter/AliRoot.git] / HLT / rec / AliHLTReconstructor.cxx
1 // $Id$
2
3 //**************************************************************************
4 //* This file is property of and copyright by the ALICE HLT Project        * 
5 //* ALICE Experiment at CERN, All rights reserved.                         *
6 //*                                                                        *
7 //* Primary Authors: Matthias Richter <Matthias.Richter@ift.uib.no>        *
8 //*                  for The ALICE HLT Project.                            *
9 //*                                                                        *
10 //* Permission to use, copy, modify and distribute this software and its   *
11 //* documentation strictly for non-commercial purposes is hereby granted   *
12 //* without fee, provided that the above copyright notice appears in all   *
13 //* copies and that both the copyright notice and this permission notice   *
14 //* appear in the supporting documentation. The authors make no claims     *
15 //* about the suitability of this software for any purpose. It is          *
16 //* provided "as is" without express or implied warranty.                  *
17 //**************************************************************************
18
19 //  @file   AliHLTReconstructor.cxx
20 //  @author Matthias Richter
21 //  @date   
22 //  @brief  Binding class for HLT reconstruction in AliRoot
23 //          Implements bot the interface to run HLT chains embedded into
24 //          AliReconstruction and the unpacking and treatment of HLTOUT
25
26 #include <TSystem.h>
27 #include <TObjString.h>
28 #include "TFile.h"
29 #include "TTree.h"
30 #include "TObject.h"
31 #include "TObjArray.h"
32 #include "TClass.h"
33 #include "TStreamerInfo.h"
34 #include "AliHLTReconstructor.h"
35 #include "AliLog.h"
36 #include "AliRawReader.h"
37 #include "AliESDEvent.h"
38 #include "AliHLTSystem.h"
39 #include "AliHLTOUTRawReader.h"
40 #include "AliHLTOUTDigitReader.h"
41 #include "AliHLTEsdManager.h"
42 #include "AliHLTPluginBase.h"
43 #include "AliHLTMisc.h"
44 #include "AliCDBManager.h"
45 #include "AliCDBEntry.h"
46 #include "AliHLTMessage.h"
47 #include "AliCentralTrigger.h"
48 #include "AliTriggerConfiguration.h"
49 #include "AliTriggerClass.h"
50 #include "AliTriggerCluster.h"
51 #include "AliDAQ.h"
52
53 class AliCDBEntry;
54
55 /** ROOT macro for the implementation of ROOT specific class methods */
56 ClassImp(AliHLTReconstructor)
57
58 AliHLTReconstructor::AliHLTReconstructor()
59   : AliReconstructor()
60   , fpEsdManager(NULL)
61   , fpPluginBase(new AliHLTPluginBase)
62   , fFlags(0)
63
64   //constructor
65 }
66
67 AliHLTReconstructor::AliHLTReconstructor(const char* options)
68   : AliReconstructor()
69   , fpEsdManager(NULL)
70   , fpPluginBase(new AliHLTPluginBase)
71   , fFlags(0)
72
73   //constructor
74   if (options) Init(options);
75 }
76
77 AliHLTReconstructor::~AliHLTReconstructor()
78
79   //destructor
80
81   if (fpPluginBase) {
82   AliHLTSystem* pSystem=fpPluginBase->GetInstance();
83   if (pSystem) {
84     AliDebug(0, Form("terminate HLT system: status %#x", pSystem->GetStatusFlags()));
85     if (pSystem->CheckStatus(AliHLTSystem::kStarted)) {
86       // send specific 'event' to execute the stop sequence
87       pSystem->Reconstruct(0, NULL, NULL);
88     }
89   }
90   delete fpPluginBase;
91   }
92   fpPluginBase=NULL;
93
94   if (fpEsdManager) AliHLTEsdManager::Delete(fpEsdManager);
95   fpEsdManager=NULL;
96 }
97
98 void AliHLTReconstructor::Init(const char* options)
99 {
100   // init the reconstructor
101   SetOption(options);
102   Init();
103 }
104
105 void AliHLTReconstructor::Init()
106 {
107   // init the reconstructor
108   if (!fpPluginBase) {
109     AliError("internal memory error: can not get AliHLTSystem instance from plugin");
110     return;
111   }
112
113   AliHLTSystem* pSystem=fpPluginBase->GetInstance();
114   if (!pSystem) {
115     AliError("can not create AliHLTSystem object");
116     return;
117   }
118   if (pSystem->CheckStatus(AliHLTSystem::kError)) {
119     AliError("HLT system in error state");
120     return;
121   }
122
123   TString esdManagerOptions;
124
125   // the options scan has been moved to AliHLTSystem, the old code
126   // here is kept to be able to run an older version of the HLT code
127   // with newer AliRoot versions.
128   TString option = GetOption();
129   TObjArray* pTokens=option.Tokenize(" ");
130   option="";
131   if (pTokens) {
132     int iEntries=pTokens->GetEntries();
133     for (int i=0; i<iEntries; i++) {
134       TString token=(((TObjString*)pTokens->At(i))->GetString());
135       if (token.Contains("loglevel=")) {
136         TString param=token.ReplaceAll("loglevel=", "");
137         if (param.IsDigit()) {
138           pSystem->SetGlobalLoggingLevel((AliHLTComponentLogSeverity)param.Atoi());
139         } else if (param.BeginsWith("0x") &&
140                    param.Replace(0,2,"",0).IsHex()) {
141           int severity=0;
142           sscanf(param.Data(),"%x", &severity);
143           pSystem->SetGlobalLoggingLevel((AliHLTComponentLogSeverity)severity);
144         } else {
145           AliWarning("wrong parameter for option \'loglevel=\', (hex) number expected");
146         }
147       } else if (token.Contains("alilog=off")) {
148         pSystem->SwitchAliLog(0);
149       } else if (token.CompareTo("ignore-hltout")==0) {
150         fFlags|=kAliHLTReconstructorIgnoreHLTOUT;
151       } else if (token.CompareTo("ignore-ctp")==0) {
152         fFlags|=kAliHLTReconstructorIgnoreCTP;
153       } else if (token.Contains("esdmanager=")) {
154         token.ReplaceAll("esdmanager=", "");
155         token.ReplaceAll(","," ");
156         token.ReplaceAll("'","");
157         esdManagerOptions=token;
158       } else {
159         if (option.Length()>0) option+=" ";
160         option+=token;
161       }
162     }
163     delete pTokens;
164   }
165
166   TString ecsParam;
167   TString ctpParam;
168   if ((fFlags&kAliHLTReconstructorIgnoreCTP)==0 &&
169       BuildCTPTriggerClassString(ctpParam)>=0) {
170     if (!ecsParam.IsNull()) ecsParam+=";";
171     ecsParam+="CTP_TRIGGER_CLASS=";
172     ecsParam+=ctpParam;
173   }
174
175   if (!ecsParam.IsNull()) {
176     option+=" ECS=";
177     option+=ecsParam;
178   }
179
180   if (!pSystem->CheckStatus(AliHLTSystem::kReady)) {
181     if (pSystem->ScanOptions(option.Data())<0) {
182       AliError("error setting options for HLT system");
183       return;
184     }
185     if ((pSystem->Configure())<0) {
186       AliError("error during HLT system configuration");
187       return;
188     }
189   }
190
191   fpEsdManager=AliHLTEsdManager::New();
192   fpEsdManager->SetOption(esdManagerOptions.Data());
193
194   AliHLTMisc::Instance().InitStreamerInfos(fgkCalibStreamerInfoEntry);
195 }
196
197 const char* AliHLTReconstructor::fgkCalibStreamerInfoEntry="HLT/Calib/StreamerInfo";
198
199 void AliHLTReconstructor::Reconstruct(AliRawReader* rawReader, TTree* /*clustersTree*/) const 
200 {
201   // reconstruction of real data without writing of ESD
202   // For each event, HLT reconstruction chains can be executed and
203   // added to the existing HLTOUT data
204   // The HLTOUT data is finally processed in FillESD
205   if (!fpPluginBase) {
206     AliError("internal memory error: can not get AliHLTSystem instance from plugin");
207     return;
208   }
209
210   int iResult=0;
211   AliHLTSystem* pSystem=fpPluginBase->GetInstance();
212
213   if (pSystem) {
214     if (pSystem->CheckStatus(AliHLTSystem::kError)) {
215       AliError("HLT system in error state");
216       return;
217     }
218     if (!pSystem->CheckStatus(AliHLTSystem::kReady)) {
219       AliError("HLT system in wrong state");
220       return;
221     }
222     if ((iResult=pSystem->Reconstruct(1, NULL, rawReader))>=0) {
223     }
224   }
225 }
226
227 void AliHLTReconstructor::FillESD(AliRawReader* rawReader, TTree* /*clustersTree*/, 
228                                   AliESDEvent* esd) const
229 {
230   // reconstruct real data and fill ESD
231   if (!rawReader || !esd) {
232     AliError("missing raw reader or esd object");
233     return;
234   }
235
236   if (!fpPluginBase) {
237     AliError("internal memory error: can not get AliHLTSystem instance from plugin");
238     return;
239   }
240
241   AliHLTSystem* pSystem=fpPluginBase->GetInstance();
242
243   if (pSystem) {
244     if (pSystem->CheckStatus(AliHLTSystem::kError)) {
245       AliError("HLT system in error state");
246       return;
247     }
248     if (!pSystem->CheckStatus(AliHLTSystem::kReady)) {
249       AliError("HLT system in wrong state");
250       return;
251     }
252     pSystem->FillESD(-1, NULL, esd);
253
254     AliRawReader* input=NULL;
255     if ((fFlags&kAliHLTReconstructorIgnoreHLTOUT) == 0 ) {
256       input=rawReader;
257     }
258     AliHLTOUTRawReader* pHLTOUT=new AliHLTOUTRawReader(input, esd->GetEventNumberInFile(), fpEsdManager);
259     if (pHLTOUT) {
260       ProcessHLTOUT(pHLTOUT, esd, (pSystem->GetGlobalLoggingLevel()&kHLTLogDebug)!=0);
261       delete pHLTOUT;
262     } else {
263       AliError("error creating HLTOUT handler");
264     }
265   }
266 }
267
268 void AliHLTReconstructor::Reconstruct(TTree* /*digitsTree*/, TTree* /*clustersTree*/) const
269 {
270   // reconstruct simulated data
271
272   // all reconstruction has been moved to FillESD
273   //AliReconstructor::Reconstruct(digitsTree,clustersTree);
274   AliInfo("running digit data reconstruction");
275 }
276
277 void AliHLTReconstructor::FillESD(TTree* /*digitsTree*/, TTree* /*clustersTree*/, AliESDEvent* esd) const
278 {
279   // reconstruct simulated data and fill ESD
280
281   // later this is the place to extract the simulated HLT data
282   // for now it's only an user failure condition as he tries to run HLT reconstruction
283   // on simulated data 
284   TString option = GetOption();
285   if (!option.IsNull() && 
286       (option.Contains("config=") || option.Contains("chains="))) {
287     AliWarning(Form("HLT reconstruction can be run embedded into Alireconstruction from\n"
288                     "raw data (real or simulated)). Reconstruction of of digit data takes\n"
289                     "place in AliSimulation, appropriate input conversion is needed.\n"
290                     "Consider running embedded into AliSimulation."
291                     "        /***  run macro *****************************************/\n"
292                     "        AliSimulation sim;\n"
293                     "        sim.SetRunHLT(\"%s\");\n"
294                     "        sim.SetRunGeneration(kFALSE);\n"
295                     "        sim.SetMakeDigits(\"\");\n"
296                     "        sim.SetMakeSDigits(\"\");\n"
297                     "        sim.SetMakeDigitsFromHits(\"\");\n"
298                     "        sim.Run();\n"
299                     "        /*********************************************************/", option.Data()));
300   }
301   if (!fpPluginBase) {
302     AliError("internal memory error: can not get AliHLTSystem instance from plugin");
303     return;
304   }
305
306   AliHLTSystem* pSystem=fpPluginBase->GetInstance();
307   if (pSystem) {
308     if (pSystem->CheckStatus(AliHLTSystem::kError)) {
309       AliError("HLT system in error state");
310       return;
311     }
312     if (!pSystem->CheckStatus(AliHLTSystem::kReady)) {
313       AliError("HLT system in wrong state");
314       return;
315     }
316
317     AliHLTOUTDigitReader* pHLTOUT=new AliHLTOUTDigitReader(esd->GetEventNumberInFile(), fpEsdManager);
318     if (pHLTOUT) {
319       ProcessHLTOUT(pHLTOUT, esd, (pSystem->GetGlobalLoggingLevel()&kHLTLogDebug)!=0);
320       delete pHLTOUT;
321     } else {
322       AliError("error creating HLTOUT handler");
323     }
324   }
325 }
326
327 void AliHLTReconstructor::ProcessHLTOUT(AliHLTOUT* pHLTOUT, AliESDEvent* esd, bool bVerbose) const
328 {
329   // treatment of simulated or real HLTOUT data
330   if (!pHLTOUT) return;
331   if (!fpPluginBase) {
332     AliError("internal memory error: can not get AliHLTSystem instance from plugin");
333     return;
334   }
335
336   AliHLTSystem* pSystem=fpPluginBase->GetInstance();
337   if (!pSystem) {
338     AliError("error getting HLT system instance");
339     return;
340   }
341
342   if (pHLTOUT->Init()<0) {
343     AliError("error : initialization of HLTOUT handler failed");
344     return;
345   }
346
347   if (bVerbose)
348     PrintHLTOUTContent(pHLTOUT);
349
350   int blockindex=pHLTOUT->SelectFirstDataBlock(kAliHLTDataTypeStreamerInfo);
351   if (blockindex>=0) {
352     const AliHLTUInt8_t* pBuffer=NULL;
353     AliHLTUInt32_t size=0;
354     if (pHLTOUT->GetDataBuffer(pBuffer, size)>=0) {
355       TObject* pObject=AliHLTMessage::Extract(pBuffer, size);
356       if (pObject) {
357         TObjArray* pArray=dynamic_cast<TObjArray*>(pObject);
358         if (pArray) {
359           AliHLTMisc::Instance().InitStreamerInfos(pArray);
360         } else {
361           AliError(Form("wrong class type of streamer info list: expected TObjArray, but object is of type %s", pObject->Class()->GetName()));
362         }
363       } else {
364         AliError(Form("failed to extract object from data block of type %s", AliHLTComponent::DataType2Text(kAliHLTDataTypeStreamerInfo).c_str()));
365       }
366     } else {
367       AliError(Form("failed to get data buffer for block of type %s", AliHLTComponent::DataType2Text(kAliHLTDataTypeStreamerInfo).c_str()));
368     }
369   }
370
371   if (pSystem->ProcessHLTOUT(pHLTOUT, esd)<0) {
372     AliError("error processing HLTOUT");
373   }
374
375   if (bVerbose) {
376     AliInfo("HLT ESD content:");
377     esd->Print();
378   }
379   pHLTOUT->Reset();
380 }
381
382 void AliHLTReconstructor::ProcessHLTOUT(const char* digitFile, AliESDEvent* pEsd) const
383 {
384   // debugging/helper function to examine simulated data
385   if (!digitFile) return;
386
387   // read the number of events
388   TFile f(digitFile);
389   if (f.IsZombie()) return;
390   TTree* pTree=NULL;
391   f.GetObject("rawhltout", pTree);
392   if (!pTree) {
393     AliWarning(Form("can not find tree rawhltout in file %s", digitFile));
394     return ;
395   }
396   int nofEvents=pTree->GetEntries();
397   f.Close();
398   //delete pTree; OF COURSE NOT! its an object in the file
399   pTree=NULL;
400
401   for (int event=0; event<nofEvents; event++) {
402     AliHLTOUTDigitReader* pHLTOUT=new AliHLTOUTDigitReader(event, fpEsdManager, digitFile);
403     if (pHLTOUT) {
404       AliInfo(Form("event %d", event));
405       ProcessHLTOUT(pHLTOUT, pEsd, true);
406       delete pHLTOUT;
407     } else {
408       AliError("error creating HLTOUT handler");
409     }
410   }
411 }
412
413 void AliHLTReconstructor::ProcessHLTOUT(AliRawReader* pRawReader, AliESDEvent* pEsd) const
414 {
415   // debugging/helper function to examine simulated or real HLTOUT data
416   if (!pRawReader) return;
417
418   pRawReader->RewindEvents();
419   for (int event=0; pRawReader->NextEvent(); event++) {
420     AliHLTOUTRawReader* pHLTOUT=new AliHLTOUTRawReader(pRawReader, event, fpEsdManager);
421     if (pHLTOUT) {
422       AliInfo(Form("event %d", event));
423       // the two event fields contain: period - orbit - bunch crossing counter
424       //        id[0]               id[1]
425       // |32                0|32                0|
426       //
427       // |      28 bit    |       24 bit     | 12|
428       //        period          orbit         bcc
429       AliHLTUInt64_t eventId=0;
430       const UInt_t* rawreaderEventId=pRawReader->GetEventId();
431       if (rawreaderEventId) {
432         eventId=rawreaderEventId[0];
433         eventId=eventId<<32;
434         eventId|=rawreaderEventId[1];
435       }
436       AliInfo(Form("Event Id from rawreader:\t 0x%016llx", eventId));
437       ProcessHLTOUT(pHLTOUT, pEsd, true);
438       delete pHLTOUT;
439     } else {
440       AliError("error creating HLTOUT handler");
441     }
442   }
443 }
444
445 void AliHLTReconstructor::PrintHLTOUTContent(AliHLTOUT* pHLTOUT) const
446 {
447   // print the block specifications of the HLTOUT data blocks
448   if (!pHLTOUT) return;
449   int iResult=0;
450
451   AliInfo(Form("Event Id from hltout:\t 0x%016llx", pHLTOUT->EventId()));
452   for (iResult=pHLTOUT->SelectFirstDataBlock();
453        iResult>=0;
454        iResult=pHLTOUT->SelectNextDataBlock()) {
455     AliHLTComponentDataType dt=kAliHLTVoidDataType;
456     AliHLTUInt32_t spec=kAliHLTVoidDataSpec;
457     pHLTOUT->GetDataBlockDescription(dt, spec);
458     const AliHLTUInt8_t* pBuffer=NULL;
459     AliHLTUInt32_t size=0;
460     if (pHLTOUT->GetDataBuffer(pBuffer, size)>=0) {
461       pHLTOUT->ReleaseDataBuffer(pBuffer);
462       pBuffer=NULL; // just a dummy
463     }
464     AliInfo(Form("   %s  0x%x: size %d", AliHLTComponent::DataType2Text(dt).c_str(), spec, size));
465   }
466 }
467
468 int AliHLTReconstructor::BuildCTPTriggerClassString(TString& triggerclasses) const
469 {
470   // build the CTP trigger class string from the OCDB entry of the CTP trigger
471   int iResult=0;
472   
473   triggerclasses.Clear();
474   AliCentralTrigger* pCTP = new AliCentralTrigger();
475   AliTriggerConfiguration *config=NULL;
476   TString configstr("");
477   if (pCTP->LoadConfiguration(configstr) && 
478       (config = pCTP->GetConfiguration())!=NULL) {
479     const TObjArray& classesArray = config->GetClasses();
480     int nclasses = classesArray.GetEntriesFast();
481     for( int iclass=0; iclass < nclasses; iclass++ ) {
482       AliTriggerClass* trclass = NULL;
483       if (classesArray.At(iclass) && (trclass=dynamic_cast<AliTriggerClass*>(classesArray.At(iclass)))!=NULL) {
484         TString entry;
485         int trindex = TMath::Nint(TMath::Log2(trclass->GetMask()));
486         entry.Form("%02d:%s:", trindex, trclass->GetName());
487         AliTriggerCluster* cluster=NULL;
488         TObject* clusterobj=config->GetClusters().FindObject(trclass->GetCluster());
489         if (clusterobj && (cluster=dynamic_cast<AliTriggerCluster*>(clusterobj))!=NULL) {
490           TString detectors=cluster->GetDetectorsInCluster();
491           TObjArray* pTokens=detectors.Tokenize(" ");
492           if (pTokens) {
493             for (int dix=0; dix<pTokens->GetEntriesFast(); dix++) {
494               int id=AliDAQ::DetectorID(((TObjString*)pTokens->At(dix))->GetString());
495               if (id>=0) {
496                 TString detstr; detstr.Form("%s%02d", dix>0?"-":"", id);
497                 entry+=detstr;
498               } else {
499                 AliError(Form("invalid detector name extracted from trigger cluster: %s (%s)", ((TObjString*)pTokens->At(dix))->GetString().Data(), detectors.Data()));
500                 iResult=-EPROTO;
501                 break;
502               }
503             }
504             delete pTokens;
505           }
506         } else {
507           AliError(Form("can not find trigger cluster %s in config", trclass->GetCluster()?trclass->GetCluster()->GetName():"NULL"));
508           iResult=-EPROTO;
509           break;
510         }
511         if (!triggerclasses.IsNull()) triggerclasses+=",";
512         triggerclasses+=entry;
513       }
514     }
515   }
516
517   return iResult;
518 }