3 //**************************************************************************
4 //* This file is property of and copyright by the *
5 //* ALICE Experiment at CERN, All rights reserved. *
7 //* Primary Authors: Matthias Richter <Matthias.Richter@ift.uib.no> *
9 //* Permission to use, copy, modify and distribute this software and its *
10 //* documentation strictly for non-commercial purposes is hereby granted *
11 //* without fee, provided that the above copyright notice appears in all *
12 //* copies and that both the copyright notice and this permission notice *
13 //* appear in the supporting documentation. The authors make no claims *
14 //* about the suitability of this software for any purpose. It is *
15 //* provided "as is" without express or implied warranty. *
16 //**************************************************************************
18 // @file AliHLTReconstructor.cxx
19 // @author Matthias Richter
21 // @brief Binding class for HLT reconstruction in AliRoot
22 // Implements bot the interface to run HLT chains embedded into
23 // AliReconstruction and the unpacking and treatment of HLTOUT
26 #include <TObjString.h>
30 #include "TObjArray.h"
32 #include "TStreamerInfo.h"
33 #include "AliHLTReconstructor.h"
35 #include "AliRawReader.h"
36 #include "AliESDEvent.h"
37 #include "AliHLTSystem.h"
38 #include "AliHLTOUTRawReader.h"
39 #include "AliHLTOUTDigitReader.h"
40 #include "AliHLTEsdManager.h"
41 #include "AliHLTPluginBase.h"
42 #include "AliHLTMisc.h"
43 #include "AliCDBManager.h"
44 #include "AliCDBEntry.h"
45 #include "AliHLTMessage.h"
46 #include "AliCentralTrigger.h"
47 #include "AliTriggerConfiguration.h"
48 #include "AliTriggerClass.h"
49 #include "AliTriggerCluster.h"
51 #include "AliRunLoader.h"
55 /** ROOT macro for the implementation of ROOT specific class methods */
56 ClassImp(AliHLTReconstructor)
58 AliHLTReconstructor::AliHLTReconstructor()
61 , fpPluginBase(new AliHLTPluginBase)
63 , fProcessingStep(kProcessingStepUndefined)
68 AliHLTReconstructor::AliHLTReconstructor(const char* options)
71 , fpPluginBase(new AliHLTPluginBase)
73 , fProcessingStep(kProcessingStepUndefined)
76 if (options) Init(options);
79 AliHLTReconstructor::~AliHLTReconstructor()
83 if (fpEsdManager) AliHLTEsdManager::Delete(fpEsdManager);
87 AliHLTSystem* pSystem=fpPluginBase->GetInstance();
89 AliDebug(0, Form("terminate HLT system: status %#x", pSystem->GetStatusFlags()));
90 if (pSystem->CheckStatus(AliHLTSystem::kStarted)) {
91 // send specific 'event' to execute the stop sequence
92 pSystem->Reconstruct(0, NULL, NULL);
101 void AliHLTReconstructor::Init(const char* options)
103 // init the reconstructor
108 void AliHLTReconstructor::Init()
110 // init the reconstructor
112 AliError("internal memory error: can not get AliHLTSystem instance from plugin");
116 AliHLTSystem* pSystem=fpPluginBase->GetInstance();
118 AliError("can not create AliHLTSystem object");
121 if (pSystem->CheckStatus(AliHLTSystem::kError)) {
122 AliError("HLT system in error state");
126 TString esdManagerOptions;
128 // the options scan has been moved to AliHLTSystem, the old code
129 // here is kept to be able to run an older version of the HLT code
130 // with newer AliRoot versions.
131 TString option = GetOption();
132 TObjArray* pTokens=option.Tokenize(" ");
135 int iEntries=pTokens->GetEntries();
136 for (int i=0; i<iEntries; i++) {
137 TString token=(((TObjString*)pTokens->At(i))->GetString());
138 if (token.Contains("loglevel=")) {
139 TString param=token.ReplaceAll("loglevel=", "");
140 if (param.IsDigit()) {
141 pSystem->SetGlobalLoggingLevel((AliHLTComponentLogSeverity)param.Atoi());
142 } else if (param.BeginsWith("0x") &&
143 param.Replace(0,2,"",0).IsHex()) {
145 sscanf(param.Data(),"%x", &severity);
146 pSystem->SetGlobalLoggingLevel((AliHLTComponentLogSeverity)severity);
148 AliWarning("wrong parameter for option \'loglevel=\', (hex) number expected");
150 } else if (token.Contains("alilog=off")) {
151 pSystem->SwitchAliLog(0);
152 } else if (token.CompareTo("ignore-hltout")==0) {
153 fFlags|=kAliHLTReconstructorIgnoreHLTOUT;
154 } else if (token.CompareTo("run-online-config")==0) {
155 fFlags|=kAliHLTReconstructorIgnoreHLTOUT;
156 if (option.Length()>0) option+=" ";
158 } else if (token.CompareTo("ignore-ctp")==0) {
159 fFlags|=kAliHLTReconstructorIgnoreCTP;
160 } else if (token.Contains("esdmanager=")) {
161 token.ReplaceAll("esdmanager=", "");
162 token.ReplaceAll(","," ");
163 token.ReplaceAll("'","");
164 esdManagerOptions=token;
166 if (option.Length()>0) option+=" ";
175 if ((fFlags&kAliHLTReconstructorIgnoreCTP)==0 &&
176 BuildCTPTriggerClassString(ctpParam)>=0) {
177 if (!ecsParam.IsNull()) ecsParam+=";";
178 ecsParam+="CTP_TRIGGER_CLASS=";
182 if (!ecsParam.IsNull()) {
187 if (!pSystem->CheckStatus(AliHLTSystem::kReady)) {
188 if (pSystem->ScanOptions(option.Data())<0) {
189 AliError("error setting options for HLT system");
192 if ((pSystem->Configure())<0) {
193 AliError("error during HLT system configuration");
198 fpEsdManager=AliHLTEsdManager::New();
200 fpEsdManager->SetOption(esdManagerOptions.Data());
203 AliHLTMisc::Instance().InitStreamerInfos(fgkCalibStreamerInfoEntry);
206 void AliHLTReconstructor::Terminate()
208 /// overloaded from AliReconstructor: terminate event processing
210 // indicate step 'Terminate'
211 SetProcessingStep(kProcessingStepTerminate);
213 AliInfo("terminating");
215 AliHLTSystem* pSystem=fpPluginBase->GetInstance();
218 // clean up the HLTOUT instance if still existing, currently FinishEvent
219 // is not called at the end of the event processing and the cleanup
220 // needs to be done here to avoid a warning message. Later it can be
221 // declared a malfunction if the HLTOUT instance is still existing at
223 AliHLTOUT* pHLTOUT=NULL;
224 pSystem->InvalidateHLTOUT(&pHLTOUT);
231 AliDebug(0, Form("terminate HLT system: status %#x", pSystem->GetStatusFlags()));
232 if (pSystem->CheckStatus(AliHLTSystem::kStarted)) {
233 // send specific 'event' to execute the stop sequence
234 pSystem->Reconstruct(0, NULL, NULL);
240 void AliHLTReconstructor::FinishEvent()
242 /// overloaded from AliReconstructor: finish current event
243 if (!fpPluginBase) return;
245 // indicate step 'FinishEvent'
246 SetProcessingStep(kProcessingStepFinishEvent);
248 AliInfo("finishing event");
249 AliHLTSystem* pSystem=fpPluginBase->GetInstance();
251 // this is the end of the lifetime of the HLTOUT instance
252 // called after all other modules have been reconstructed
253 AliHLTOUT* pHLTOUT=NULL;
254 pSystem->InvalidateHLTOUT(&pHLTOUT);
263 const char* AliHLTReconstructor::fgkCalibStreamerInfoEntry="HLT/Calib/StreamerInfo";
265 void AliHLTReconstructor::Reconstruct(AliRawReader* rawReader, TTree* /*clustersTree*/) const
267 // reconstruction of real data without writing of ESD
268 // For each event, HLT reconstruction chains can be executed and
269 // added to the existing HLTOUT data
270 // The HLTOUT data is finally processed in FillESD
273 AliError("internal memory error: can not get AliHLTSystem instance from plugin");
278 AliHLTSystem* pSystem=fpPluginBase->GetInstance();
281 AliHLTOUT* pHLTOUT=NULL;
282 pSystem->InvalidateHLTOUT(&pHLTOUT);
284 // at this stage we always have a new event, regardless state of
285 // fProcessingStep; build the HLTOUT instance from scratch
290 if (pSystem->CheckStatus(AliHLTSystem::kError)) {
291 AliError("HLT system in error state");
294 if (!pSystem->CheckStatus(AliHLTSystem::kReady)) {
295 AliError("HLT system in wrong state");
299 // indicate the local reconstruction step
300 SetProcessingStep(kProcessingStepLocal);
302 // init the HLTOUT instance for the current event
303 // not nice. Have to query the global run loader to get the current event no.
305 AliRunLoader* runloader = AliRunLoader::Instance();
307 eventNo=runloader->GetEventNumber();
310 AliRawReader* input=NULL;
311 if ((fFlags&kAliHLTReconstructorIgnoreHLTOUT) == 0 ) {
314 pHLTOUT=new AliHLTOUTRawReader(input, eventNo, fpEsdManager);
316 if (pHLTOUT->Init()>=0) {
317 pSystem->InitHLTOUT(pHLTOUT);
319 AliError("error : initialization of HLTOUT handler failed");
322 AliError("memory allocation failed: can not create AliHLTOUT object");
325 AliError("can not get event number");
328 if ((iResult=pSystem->Reconstruct(1, NULL, rawReader))>=0) {
333 void AliHLTReconstructor::FillESD(AliRawReader* rawReader, TTree* /*clustersTree*/,
334 AliESDEvent* esd) const
336 // reconstruct real data and fill ESD
337 if (!rawReader || !esd) {
338 AliError("missing raw reader or esd object");
343 AliError("internal memory error: can not get AliHLTSystem instance from plugin");
347 AliHLTSystem* pSystem=fpPluginBase->GetInstance();
350 if (pSystem->CheckStatus(AliHLTSystem::kError)) {
351 AliError("HLT system in error state");
354 if (!pSystem->CheckStatus(AliHLTSystem::kReady)) {
355 AliError("HLT system in wrong state");
358 pSystem->FillESD(-1, NULL, esd);
360 // the HLTOUT handler has either been created in the AliHLTReconstructor::Reconstruct
361 // step of this event or is created now. In either case the instance is deleted after
363 AliHLTOUT* pHLTOUT=NULL;
364 pSystem->InvalidateHLTOUT(&pHLTOUT);
365 if (pHLTOUT && fProcessingStep!=kProcessingStepLocal) {
366 // this is a new event, if local reconstruction would have been executed
367 // the HLTOUT instance would have been created for the current event already,
368 // in all other cases one has to create the HLTOUT instance here
374 AliRawReader* input=NULL;
375 if ((fFlags&kAliHLTReconstructorIgnoreHLTOUT) == 0 ) {
378 pHLTOUT=new AliHLTOUTRawReader(input, esd->GetEventNumberInFile(), fpEsdManager);
381 // indicate step 'ESD filling'
382 SetProcessingStep(kProcessingStepESD);
385 ProcessHLTOUT(pHLTOUT, esd, (pSystem->GetGlobalLoggingLevel()&kHLTLogDebug)!=0);
386 // 2012-03-30: a change in the module sequence of AliReconstruction is soon
387 // going to be applied: HLT reconstruction is executed fully (i.e. both local
388 // reconstruction and FillESD) before all the other modules. In order to make the
389 // HLTOUT data available for other modules it is kept here and released in the method
391 pSystem->InitHLTOUT(pHLTOUT);
393 AliError("error creating HLTOUT handler");
398 void AliHLTReconstructor::Reconstruct(TTree* /*digitsTree*/, TTree* /*clustersTree*/) const
400 // reconstruct simulated data
402 AliHLTSystem* pSystem=fpPluginBase->GetInstance();
405 // create the HLTOUT instance in order to be available for other detector reconstruction
406 // first cleanup any existing instance
407 AliHLTOUT* pHLTOUT=NULL;
408 pSystem->InvalidateHLTOUT(&pHLTOUT);
410 // at this stage we always have a new event, regardless state of
411 // fProcessingStep; build the HLTOUT instance from scratch
417 // indicate the local reconstruction step
418 SetProcessingStep(kProcessingStepLocal);
420 // not nice. Have to query the global run loader to get the current event no.
421 // This is related to the missing AliLoader for HLT.
422 // Since AliReconstruction can not provide a digits tree, the file needs to be accessed
423 // explicitely, and the corresponding event needs to be selected.
425 AliRunLoader* runloader = AliRunLoader::Instance();
427 eventNo=runloader->GetEventNumber();
430 const char* digitfile=NULL;
431 if ((fFlags&kAliHLTReconstructorIgnoreHLTOUT) == 0 ) {
432 digitfile="HLT.Digits.root";
435 pHLTOUT=new AliHLTOUTDigitReader(eventNo, fpEsdManager, digitfile);
437 if (pHLTOUT->Init()>=0) {
438 pSystem->InitHLTOUT(pHLTOUT);
440 AliError("error : initialization of HLTOUT handler failed");
443 AliError("memory allocation failed: can not create AliHLTOUT object");
446 AliError("can not get event number");
449 // all data processing happens in FillESD
453 void AliHLTReconstructor::FillESD(TTree* /*digitsTree*/, TTree* /*clustersTree*/, AliESDEvent* esd) const
455 // reconstruct simulated data and fill ESD
457 // later this is the place to extract the simulated HLT data
458 // for now it's only an user failure condition as he tries to run HLT reconstruction
460 TString option = GetOption();
461 if (!option.IsNull() &&
462 (option.Contains("config=") || option.Contains("chains="))) {
463 AliWarning(Form("You are trying to run a custom HLT chain on digits data.\n\n"
464 "HLT reconstruction can be run embedded into AliReconstruction from\n"
465 "raw data (real or simulated)). Reconstruction of digit data takes\n"
466 "place in AliSimulation, appropriate input conversion is needed to\n"
467 "feed data from the detector digits into the HLT chain.\n"
468 "Consider running embedded into AliSimulation.\n"
469 " /*** run macro *****************************************/\n"
470 " AliSimulation sim;\n"
471 " sim.SetRunHLT(\"%s\");\n"
472 " sim.SetRunGeneration(kFALSE);\n"
473 " sim.SetMakeDigits(\"\");\n"
474 " sim.SetMakeSDigits(\"\");\n"
475 " sim.SetMakeDigitsFromHits(\"\");\n"
477 " /*********************************************************/\n\n",
481 AliError("internal memory error: can not get AliHLTSystem instance from plugin");
485 AliHLTSystem* pSystem=fpPluginBase->GetInstance();
487 if (pSystem->CheckStatus(AliHLTSystem::kError)) {
488 AliError("HLT system in error state");
491 if (!pSystem->CheckStatus(AliHLTSystem::kReady)) {
492 AliError("HLT system in wrong state");
496 // the HLTOUT handler has either been created in the AliHLTReconstructor::Reconstruct
497 // step of this event or is created now. In either case the instance is deleted after
499 AliHLTOUT* pHLTOUT=NULL;
500 pSystem->InvalidateHLTOUT(&pHLTOUT);
501 if (pHLTOUT && fProcessingStep!=kProcessingStepLocal) {
502 // this is a new event, if local reconstruction would have been executed
503 // the HLTOUT instance would have been created for the current event already,
504 // in all other cases one has to create the HLTOUT instance here
510 const char* digitfile=NULL;
511 if ((fFlags&kAliHLTReconstructorIgnoreHLTOUT) == 0 ) {
512 digitfile="HLT.Digits.root";
514 pHLTOUT=new AliHLTOUTDigitReader(esd->GetEventNumberInFile(), fpEsdManager, digitfile);
517 // indicate step 'ESD filling'
518 SetProcessingStep(kProcessingStepESD);
521 ProcessHLTOUT(pHLTOUT, esd, (pSystem->GetGlobalLoggingLevel()&kHLTLogDebug)!=0);
522 // 2012-03-30: a change in the module sequence of AliReconstruction is soon
523 // going to be applied: HLT reconstruction is executed fully (i.e. both local
524 // reconstruction and FillESD) before all the other modules. In order to make the
525 // HLTOUT data available for other modules it is kept here and released in the method
527 pSystem->InitHLTOUT(pHLTOUT);
529 AliError("error creating HLTOUT handler");
534 void AliHLTReconstructor::ProcessHLTOUT(AliHLTOUT* pHLTOUT, AliESDEvent* esd, bool bVerbose) const
536 // treatment of simulated or real HLTOUT data
537 if (!pHLTOUT) return;
539 AliError("internal memory error: can not get AliHLTSystem instance from plugin");
543 AliHLTSystem* pSystem=fpPluginBase->GetInstance();
545 AliError("error getting HLT system instance");
549 if (pHLTOUT->Init()<0) {
550 AliError("error : initialization of HLTOUT handler failed");
555 PrintHLTOUTContent(pHLTOUT);
557 int blockindex=pHLTOUT->SelectFirstDataBlock(kAliHLTDataTypeStreamerInfo);
559 const AliHLTUInt8_t* pBuffer=NULL;
560 AliHLTUInt32_t size=0;
561 if (pHLTOUT->GetDataBuffer(pBuffer, size)>=0) {
562 TObject* pObject=AliHLTMessage::Extract(pBuffer, size);
564 TObjArray* pArray=dynamic_cast<TObjArray*>(pObject);
566 AliHLTMisc::Instance().InitStreamerInfos(pArray);
568 AliError(Form("wrong class type of streamer info list: expected TObjArray, but object is of type %s", pObject->Class()->GetName()));
571 AliError(Form("failed to extract object from data block of type %s", AliHLTComponent::DataType2Text(kAliHLTDataTypeStreamerInfo).c_str()));
574 AliError(Form("failed to get data buffer for block of type %s", AliHLTComponent::DataType2Text(kAliHLTDataTypeStreamerInfo).c_str()));
578 if (pSystem->ProcessHLTOUT(pHLTOUT, esd)<0) {
579 AliError("error processing HLTOUT");
582 if (bVerbose && esd) {
583 AliInfo("HLT ESD content:");
588 void AliHLTReconstructor::ProcessHLTOUT(const char* digitFile, AliESDEvent* pEsd) const
590 // debugging/helper function to examine simulated data
591 if (!digitFile) return;
593 // read the number of events
595 if (f.IsZombie()) return;
597 f.GetObject("rawhltout", pTree);
599 AliWarning(Form("can not find tree rawhltout in file %s", digitFile));
602 int nofEvents=pTree->GetEntries();
604 //delete pTree; OF COURSE NOT! its an object in the file
607 for (int event=0; event<nofEvents; event++) {
608 AliHLTOUTDigitReader* pHLTOUT=new AliHLTOUTDigitReader(event, fpEsdManager, digitFile);
610 AliInfo(Form("event %d", event));
611 ProcessHLTOUT(pHLTOUT, pEsd, true);
614 AliError("error creating HLTOUT handler");
619 void AliHLTReconstructor::ProcessHLTOUT(AliRawReader* pRawReader, AliESDEvent* pEsd) const
621 // debugging/helper function to examine simulated or real HLTOUT data
622 if (!pRawReader) return;
624 pRawReader->RewindEvents();
625 for (int event=0; pRawReader->NextEvent(); event++) {
626 AliHLTOUTRawReader* pHLTOUT=new AliHLTOUTRawReader(pRawReader, event, fpEsdManager);
628 AliInfo(Form("event %d", event));
629 // the two event fields contain: period - orbit - bunch crossing counter
633 // | 28 bit | 24 bit | 12|
635 AliHLTUInt64_t eventId=0;
636 const UInt_t* rawreaderEventId=pRawReader->GetEventId();
637 if (rawreaderEventId) {
638 eventId=rawreaderEventId[0];
640 eventId|=rawreaderEventId[1];
642 AliInfo(Form("Event Id from rawreader:\t 0x%016llx", eventId));
643 ProcessHLTOUT(pHLTOUT, pEsd, true);
646 AliError("error creating HLTOUT handler");
651 void AliHLTReconstructor::PrintHLTOUTContent(AliHLTOUT* pHLTOUT) const
653 // print the block specifications of the HLTOUT data blocks
654 if (!pHLTOUT) return;
657 AliInfo(Form("Event Id from hltout:\t 0x%016llx", pHLTOUT->EventId()));
658 for (iResult=pHLTOUT->SelectFirstDataBlock();
660 iResult=pHLTOUT->SelectNextDataBlock()) {
661 AliHLTComponentDataType dt=kAliHLTVoidDataType;
662 AliHLTUInt32_t spec=kAliHLTVoidDataSpec;
663 pHLTOUT->GetDataBlockDescription(dt, spec);
664 const AliHLTUInt8_t* pBuffer=NULL;
665 AliHLTUInt32_t size=0;
666 if (pHLTOUT->GetDataBuffer(pBuffer, size)>=0) {
667 pHLTOUT->ReleaseDataBuffer(pBuffer);
668 pBuffer=NULL; // just a dummy
670 AliInfo(Form(" %s 0x%x: size %d", AliHLTComponent::DataType2Text(dt).c_str(), spec, size));
674 int AliHLTReconstructor::BuildCTPTriggerClassString(TString& triggerclasses) const
676 // build the CTP trigger class string from the OCDB entry of the CTP trigger
679 triggerclasses.Clear();
680 AliCentralTrigger* pCTP = new AliCentralTrigger();
681 AliTriggerConfiguration *config=NULL;
682 TString configstr("");
683 if (pCTP->LoadConfiguration(configstr) &&
684 (config = pCTP->GetConfiguration())!=NULL) {
685 const TObjArray& classesArray = config->GetClasses();
686 int nclasses = classesArray.GetEntriesFast();
687 for( int iclass=0; iclass < nclasses; iclass++ ) {
688 AliTriggerClass* trclass = NULL;
689 if (classesArray.At(iclass) && (trclass=dynamic_cast<AliTriggerClass*>(classesArray.At(iclass)))!=NULL) {
691 int trindex = TMath::Nint(TMath::Log2(trclass->GetMask()));
692 entry.Form("%02d:%s:", trindex, trclass->GetName());
693 AliTriggerCluster* cluster=NULL;
694 TObject* clusterobj=config->GetClusters().FindObject(trclass->GetCluster());
695 if (clusterobj && (cluster=dynamic_cast<AliTriggerCluster*>(clusterobj))!=NULL) {
696 TString detectors=cluster->GetDetectorsInCluster();
697 TObjArray* pTokens=detectors.Tokenize(" ");
699 for (int dix=0; dix<pTokens->GetEntriesFast(); dix++) {
700 int id=AliDAQ::DetectorID(((TObjString*)pTokens->At(dix))->GetString());
702 TString detstr; detstr.Form("%s%02d", dix>0?"-":"", id);
705 AliError(Form("invalid detector name extracted from trigger cluster: %s (%s)", ((TObjString*)pTokens->At(dix))->GetString().Data(), detectors.Data()));
713 AliError(Form("can not find trigger cluster %s in config", trclass->GetCluster()?trclass->GetCluster()->GetName():"NULL"));
717 if (!triggerclasses.IsNull()) triggerclasses+=",";
718 triggerclasses+=entry;