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);
214 AliHLTSystem* pSystem=fpPluginBase->GetInstance();
217 // clean up the HLTOUT instance if still existing, currently FinishEvent
218 // is not called at the end of the event processing and the cleanup
219 // needs to be done here to avoid a warning message. Later it can be
220 // declared a malfunction if the HLTOUT instance is still existing at
222 AliHLTOUT* pHLTOUT=NULL;
223 pSystem->InvalidateHLTOUT(&pHLTOUT);
230 AliDebug(0, Form("terminate HLT system: status %#x", pSystem->GetStatusFlags()));
231 if (pSystem->CheckStatus(AliHLTSystem::kStarted)) {
232 // send specific 'event' to execute the stop sequence
233 pSystem->Reconstruct(0, NULL, NULL);
239 void AliHLTReconstructor::FinishEvent()
241 /// overloaded from AliReconstructor: finish current event
242 if (!fpPluginBase) return;
244 // indicate step 'FinishEvent'
245 SetProcessingStep(kProcessingStepFinishEvent);
247 AliInfo("finishing event");
248 AliHLTSystem* pSystem=fpPluginBase->GetInstance();
250 // this is the end of the lifetime of the HLTOUT instance
251 // called after all other modules have been reconstructed
252 AliHLTOUT* pHLTOUT=NULL;
253 pSystem->InvalidateHLTOUT(&pHLTOUT);
262 const char* AliHLTReconstructor::fgkCalibStreamerInfoEntry="HLT/Calib/StreamerInfo";
264 void AliHLTReconstructor::Reconstruct(AliRawReader* rawReader, TTree* /*clustersTree*/) const
266 // reconstruction of real data without writing of ESD
267 // For each event, HLT reconstruction chains can be executed and
268 // added to the existing HLTOUT data
269 // The HLTOUT data is finally processed in FillESD
272 AliError("internal memory error: can not get AliHLTSystem instance from plugin");
277 AliHLTSystem* pSystem=fpPluginBase->GetInstance();
280 AliHLTOUT* pHLTOUT=NULL;
281 pSystem->InvalidateHLTOUT(&pHLTOUT);
283 // at this stage we always have a new event, regardless state of
284 // fProcessingStep; build the HLTOUT instance from scratch
289 if (pSystem->CheckStatus(AliHLTSystem::kError)) {
290 // this is the highest level where an error can be detected, no error
291 // codes can be returned
292 AliFatal("HLT system in error state");
295 if (!pSystem->CheckStatus(AliHLTSystem::kReady)) {
296 AliError("HLT system in wrong state");
300 // indicate the local reconstruction step
301 SetProcessingStep(kProcessingStepLocal);
303 // init the HLTOUT instance for the current event
304 // not nice. Have to query the global run loader to get the current event no.
306 AliRunLoader* runloader = AliRunLoader::Instance();
308 eventNo=runloader->GetEventNumber();
311 AliRawReader* input=NULL;
312 if ((fFlags&kAliHLTReconstructorIgnoreHLTOUT) == 0 ) {
315 pHLTOUT=new AliHLTOUTRawReader(input, eventNo, fpEsdManager);
317 if (pHLTOUT->Init()>=0) {
318 pSystem->InitHLTOUT(pHLTOUT);
320 AliError("error : initialization of HLTOUT handler failed");
323 AliError("memory allocation failed: can not create AliHLTOUT object");
326 AliError("can not get event number");
329 if ((iResult=pSystem->Reconstruct(1, NULL, rawReader))>=0) {
334 void AliHLTReconstructor::FillESD(AliRawReader* rawReader, TTree* /*clustersTree*/,
335 AliESDEvent* esd) const
337 // reconstruct real data and fill ESD
338 if (!rawReader || !esd) {
339 AliError("missing raw reader or esd object");
344 AliError("internal memory error: can not get AliHLTSystem instance from plugin");
348 AliHLTSystem* pSystem=fpPluginBase->GetInstance();
351 if (pSystem->CheckStatus(AliHLTSystem::kError)) {
352 // this is the highest level where an error can be detected, no error
353 // codes can be returned
354 AliFatal("HLT system in error state");
357 if (!pSystem->CheckStatus(AliHLTSystem::kReady)) {
358 AliError("HLT system in wrong state");
361 pSystem->FillESD(-1, NULL, esd);
363 // the HLTOUT handler has either been created in the AliHLTReconstructor::Reconstruct
364 // step of this event or is created now. In either case the instance is deleted after
366 AliHLTOUT* pHLTOUT=NULL;
367 pSystem->InvalidateHLTOUT(&pHLTOUT);
368 if (pHLTOUT && fProcessingStep!=kProcessingStepLocal) {
369 // this is a new event, if local reconstruction would have been executed
370 // the HLTOUT instance would have been created for the current event already,
371 // in all other cases one has to create the HLTOUT instance here
377 AliRawReader* input=NULL;
378 if ((fFlags&kAliHLTReconstructorIgnoreHLTOUT) == 0 ) {
381 pHLTOUT=new AliHLTOUTRawReader(input, esd->GetEventNumberInFile(), fpEsdManager);
384 // indicate step 'ESD filling'
385 SetProcessingStep(kProcessingStepESD);
388 ProcessHLTOUT(pHLTOUT, esd, (pSystem->GetGlobalLoggingLevel()&kHLTLogDebug)!=0);
389 // 2012-03-30: a change in the module sequence of AliReconstruction is soon
390 // going to be applied: HLT reconstruction is executed fully (i.e. both local
391 // reconstruction and FillESD) before all the other modules. In order to make the
392 // HLTOUT data available for other modules it is kept here and released in the method
394 pSystem->InitHLTOUT(pHLTOUT);
396 AliError("error creating HLTOUT handler");
401 void AliHLTReconstructor::Reconstruct(TTree* /*digitsTree*/, TTree* /*clustersTree*/) const
403 // reconstruct simulated data
405 AliHLTSystem* pSystem=fpPluginBase->GetInstance();
408 // create the HLTOUT instance in order to be available for other detector reconstruction
409 // first cleanup any existing instance
410 AliHLTOUT* pHLTOUT=NULL;
411 pSystem->InvalidateHLTOUT(&pHLTOUT);
413 // at this stage we always have a new event, regardless state of
414 // fProcessingStep; build the HLTOUT instance from scratch
420 // indicate the local reconstruction step
421 SetProcessingStep(kProcessingStepLocal);
423 // not nice. Have to query the global run loader to get the current event no.
424 // This is related to the missing AliLoader for HLT.
425 // Since AliReconstruction can not provide a digits tree, the file needs to be accessed
426 // explicitely, and the corresponding event needs to be selected.
428 AliRunLoader* runloader = AliRunLoader::Instance();
430 eventNo=runloader->GetEventNumber();
433 const char* digitfile=NULL;
434 if ((fFlags&kAliHLTReconstructorIgnoreHLTOUT) == 0 ) {
435 digitfile="HLT.Digits.root";
438 pHLTOUT=new AliHLTOUTDigitReader(eventNo, fpEsdManager, digitfile);
440 if (pHLTOUT->Init()>=0) {
441 pSystem->InitHLTOUT(pHLTOUT);
443 AliError("error : initialization of HLTOUT handler failed");
446 AliError("memory allocation failed: can not create AliHLTOUT object");
449 AliError("can not get event number");
452 // all data processing happens in FillESD
456 void AliHLTReconstructor::FillESD(TTree* /*digitsTree*/, TTree* /*clustersTree*/, AliESDEvent* esd) const
458 // reconstruct simulated data and fill ESD
460 // later this is the place to extract the simulated HLT data
461 // for now it's only an user failure condition as he tries to run HLT reconstruction
463 TString option = GetOption();
464 if (!option.IsNull() &&
465 (option.Contains("config=") || option.Contains("chains="))) {
466 AliWarning(Form("You are trying to run a custom HLT chain on digits data.\n\n"
467 "HLT reconstruction can be run embedded into AliReconstruction from\n"
468 "raw data (real or simulated)). Reconstruction of digit data takes\n"
469 "place in AliSimulation, appropriate input conversion is needed to\n"
470 "feed data from the detector digits into the HLT chain.\n"
471 "Consider running embedded into AliSimulation.\n"
472 " /*** run macro *****************************************/\n"
473 " AliSimulation sim;\n"
474 " sim.SetRunHLT(\"%s\");\n"
475 " sim.SetRunGeneration(kFALSE);\n"
476 " sim.SetMakeDigits(\"\");\n"
477 " sim.SetMakeSDigits(\"\");\n"
478 " sim.SetMakeDigitsFromHits(\"\");\n"
480 " /*********************************************************/\n\n",
484 AliError("internal memory error: can not get AliHLTSystem instance from plugin");
488 AliHLTSystem* pSystem=fpPluginBase->GetInstance();
490 if (pSystem->CheckStatus(AliHLTSystem::kError)) {
491 // this is the highest level where an error can be detected, no error
492 // codes can be returned
493 AliFatal("HLT system in error state");
496 if (!pSystem->CheckStatus(AliHLTSystem::kReady)) {
497 AliError("HLT system in wrong state");
501 // the HLTOUT handler has either been created in the AliHLTReconstructor::Reconstruct
502 // step of this event or is created now. In either case the instance is deleted after
504 AliHLTOUT* pHLTOUT=NULL;
505 pSystem->InvalidateHLTOUT(&pHLTOUT);
506 if (pHLTOUT && fProcessingStep!=kProcessingStepLocal) {
507 // this is a new event, if local reconstruction would have been executed
508 // the HLTOUT instance would have been created for the current event already,
509 // in all other cases one has to create the HLTOUT instance here
515 const char* digitfile=NULL;
516 if ((fFlags&kAliHLTReconstructorIgnoreHLTOUT) == 0 ) {
517 digitfile="HLT.Digits.root";
519 pHLTOUT=new AliHLTOUTDigitReader(esd->GetEventNumberInFile(), fpEsdManager, digitfile);
522 // indicate step 'ESD filling'
523 SetProcessingStep(kProcessingStepESD);
526 ProcessHLTOUT(pHLTOUT, esd, (pSystem->GetGlobalLoggingLevel()&kHLTLogDebug)!=0);
527 // 2012-03-30: a change in the module sequence of AliReconstruction is soon
528 // going to be applied: HLT reconstruction is executed fully (i.e. both local
529 // reconstruction and FillESD) before all the other modules. In order to make the
530 // HLTOUT data available for other modules it is kept here and released in the method
532 pSystem->InitHLTOUT(pHLTOUT);
534 AliError("error creating HLTOUT handler");
539 void AliHLTReconstructor::ProcessHLTOUT(AliHLTOUT* pHLTOUT, AliESDEvent* esd, bool bVerbose) const
541 // treatment of simulated or real HLTOUT data
542 if (!pHLTOUT) return;
544 AliError("internal memory error: can not get AliHLTSystem instance from plugin");
548 AliHLTSystem* pSystem=fpPluginBase->GetInstance();
550 AliError("error getting HLT system instance");
554 if (pHLTOUT->Init()<0) {
555 AliError("error : initialization of HLTOUT handler failed");
560 PrintHLTOUTContent(pHLTOUT);
562 int blockindex=pHLTOUT->SelectFirstDataBlock(kAliHLTDataTypeStreamerInfo);
564 const AliHLTUInt8_t* pBuffer=NULL;
565 AliHLTUInt32_t size=0;
566 if (pHLTOUT->GetDataBuffer(pBuffer, size)>=0) {
567 TObject* pObject=AliHLTMessage::Extract(pBuffer, size);
569 TObjArray* pArray=dynamic_cast<TObjArray*>(pObject);
571 AliHLTMisc::Instance().InitStreamerInfos(pArray);
573 AliError(Form("wrong class type of streamer info list: expected TObjArray, but object is of type %s", pObject->Class()->GetName()));
576 AliError(Form("failed to extract object from data block of type %s", AliHLTComponent::DataType2Text(kAliHLTDataTypeStreamerInfo).c_str()));
579 AliError(Form("failed to get data buffer for block of type %s", AliHLTComponent::DataType2Text(kAliHLTDataTypeStreamerInfo).c_str()));
583 if (pSystem->ProcessHLTOUT(pHLTOUT, esd)<0) {
584 AliError("error processing HLTOUT");
587 if (bVerbose && esd) {
588 AliInfo("HLT ESD content:");
593 void AliHLTReconstructor::ProcessHLTOUT(const char* digitFile, AliESDEvent* pEsd) const
595 // debugging/helper function to examine simulated data
596 if (!digitFile) return;
598 // read the number of events
600 if (f.IsZombie()) return;
602 f.GetObject("rawhltout", pTree);
604 AliWarning(Form("can not find tree rawhltout in file %s", digitFile));
607 int nofEvents=pTree->GetEntries();
609 //delete pTree; OF COURSE NOT! its an object in the file
612 for (int event=0; event<nofEvents; event++) {
613 AliHLTOUTDigitReader* pHLTOUT=new AliHLTOUTDigitReader(event, fpEsdManager, digitFile);
615 AliInfo(Form("event %d", event));
616 ProcessHLTOUT(pHLTOUT, pEsd, true);
619 AliError("error creating HLTOUT handler");
624 void AliHLTReconstructor::ProcessHLTOUT(AliRawReader* pRawReader, AliESDEvent* pEsd) const
626 // debugging/helper function to examine simulated or real HLTOUT data
627 if (!pRawReader) return;
629 pRawReader->RewindEvents();
630 for (int event=0; pRawReader->NextEvent(); event++) {
631 AliHLTOUTRawReader* pHLTOUT=new AliHLTOUTRawReader(pRawReader, event, fpEsdManager);
633 AliInfo(Form("event %d", event));
634 // the two event fields contain: period - orbit - bunch crossing counter
638 // | 28 bit | 24 bit | 12|
640 AliHLTUInt64_t eventId=0;
641 const UInt_t* rawreaderEventId=pRawReader->GetEventId();
642 if (rawreaderEventId) {
643 eventId=rawreaderEventId[0];
645 eventId|=rawreaderEventId[1];
647 AliInfo(Form("Event Id from rawreader:\t 0x%016llx", eventId));
648 ProcessHLTOUT(pHLTOUT, pEsd, true);
651 AliError("error creating HLTOUT handler");
656 void AliHLTReconstructor::PrintHLTOUTContent(AliHLTOUT* pHLTOUT) const
658 // print the block specifications of the HLTOUT data blocks
659 if (!pHLTOUT) return;
662 AliInfo(Form("Event Id from hltout:\t 0x%016llx", pHLTOUT->EventId()));
663 for (iResult=pHLTOUT->SelectFirstDataBlock();
665 iResult=pHLTOUT->SelectNextDataBlock()) {
666 AliHLTComponentDataType dt=kAliHLTVoidDataType;
667 AliHLTUInt32_t spec=kAliHLTVoidDataSpec;
668 pHLTOUT->GetDataBlockDescription(dt, spec);
669 const AliHLTUInt8_t* pBuffer=NULL;
670 AliHLTUInt32_t size=0;
671 if (pHLTOUT->GetDataBuffer(pBuffer, size)>=0) {
672 pHLTOUT->ReleaseDataBuffer(pBuffer);
673 pBuffer=NULL; // just a dummy
675 AliInfo(Form(" %s 0x%x: size %d", AliHLTComponent::DataType2Text(dt).c_str(), spec, size));
679 int AliHLTReconstructor::BuildCTPTriggerClassString(TString& triggerclasses) const
681 // build the CTP trigger class string from the OCDB entry of the CTP trigger
684 triggerclasses.Clear();
685 AliCentralTrigger* pCTP = new AliCentralTrigger();
686 AliTriggerConfiguration *config=NULL;
687 TString configstr("");
688 if (pCTP->LoadConfiguration(configstr) &&
689 (config = pCTP->GetConfiguration())!=NULL) {
690 const TObjArray& classesArray = config->GetClasses();
691 int nclasses = classesArray.GetEntriesFast();
692 for( int iclass=0; iclass < nclasses; iclass++ ) {
693 AliTriggerClass* trclass = NULL;
694 if (classesArray.At(iclass) && (trclass=dynamic_cast<AliTriggerClass*>(classesArray.At(iclass)))!=NULL) {
696 int trindex = TMath::Nint(TMath::Log2(trclass->GetMask()));
697 entry.Form("%02d:%s:", trindex, trclass->GetName());
698 AliTriggerCluster* cluster=NULL;
699 TObject* clusterobj=config->GetClusters().FindObject(trclass->GetCluster());
700 if (clusterobj && (cluster=dynamic_cast<AliTriggerCluster*>(clusterobj))!=NULL) {
701 TString detectors=cluster->GetDetectorsInCluster();
702 TObjArray* pTokens=detectors.Tokenize(" ");
704 for (int dix=0; dix<pTokens->GetEntriesFast(); dix++) {
705 int id=AliDAQ::DetectorID(((TObjString*)pTokens->At(dix))->GetString());
707 TString detstr; detstr.Form("%s%02d", dix>0?"-":"", id);
710 AliError(Form("invalid detector name extracted from trigger cluster: %s (%s)", ((TObjString*)pTokens->At(dix))->GetString().Data(), detectors.Data()));
718 AliError(Form("can not find trigger cluster %s in config", trclass->GetCluster()?trclass->GetCluster()->GetName():"NULL"));
722 if (!triggerclasses.IsNull()) triggerclasses+=",";
723 triggerclasses+=entry;