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"
52 #include "AliRunInfo.h"
56 /** ROOT macro for the implementation of ROOT specific class methods */
57 ClassImp(AliHLTReconstructor)
59 AliHLTReconstructor::AliHLTReconstructor()
62 , fpPluginBase(new AliHLTPluginBase)
64 , fProcessingStep(kProcessingStepUndefined)
69 AliHLTReconstructor::AliHLTReconstructor(const char* options)
72 , fpPluginBase(new AliHLTPluginBase)
74 , fProcessingStep(kProcessingStepUndefined)
77 if (options) Init(options);
80 AliHLTReconstructor::~AliHLTReconstructor()
84 if (fpEsdManager) AliHLTEsdManager::Delete(fpEsdManager);
88 AliHLTSystem* pSystem=fpPluginBase->GetInstance();
90 AliDebug(0, Form("terminate HLT system: status %#x", pSystem->GetStatusFlags()));
91 if (pSystem->CheckStatus(AliHLTSystem::kStarted)) {
92 // send specific 'event' to execute the stop sequence
93 pSystem->Reconstruct(0, NULL, NULL);
102 void AliHLTReconstructor::Init(const char* options)
104 // init the reconstructor
109 void AliHLTReconstructor::Init()
111 // init the reconstructor
113 AliError("internal memory error: can not get AliHLTSystem instance from plugin");
117 AliHLTSystem* pSystem=fpPluginBase->GetInstance();
119 AliError("can not create AliHLTSystem object");
122 if (pSystem->CheckStatus(AliHLTSystem::kError)) {
123 AliError("HLT system in error state");
127 TString esdManagerOptions;
129 // the options scan has been moved to AliHLTSystem, the old code
130 // here is kept to be able to run an older version of the HLT code
131 // with newer AliRoot versions.
132 TString option = GetOption();
133 TObjArray* pTokens=option.Tokenize(" ");
136 int iEntries=pTokens->GetEntries();
137 for (int i=0; i<iEntries; i++) {
138 TString token=(((TObjString*)pTokens->At(i))->GetString());
139 if (token.Contains("loglevel=")) {
140 TString param=token.ReplaceAll("loglevel=", "");
141 if (param.IsDigit()) {
142 pSystem->SetGlobalLoggingLevel((AliHLTComponentLogSeverity)param.Atoi());
143 } else if (param.BeginsWith("0x") &&
144 param.Replace(0,2,"",0).IsHex()) {
146 sscanf(param.Data(),"%x", &severity);
147 pSystem->SetGlobalLoggingLevel((AliHLTComponentLogSeverity)severity);
149 AliWarning("wrong parameter for option \'loglevel=\', (hex) number expected");
151 } else if (token.Contains("alilog=off")) {
152 pSystem->SwitchAliLog(0);
153 } else if (token.CompareTo("ignore-hltout")==0) {
154 fFlags|=kAliHLTReconstructorIgnoreHLTOUT;
155 } else if (token.CompareTo("run-online-config")==0) {
156 fFlags|=kAliHLTReconstructorIgnoreHLTOUT;
157 if (option.Length()>0) option+=" ";
159 } else if (token.CompareTo("ignore-ctp")==0) {
160 fFlags|=kAliHLTReconstructorIgnoreCTP;
161 } else if (token.Contains("esdmanager=")) {
162 token.ReplaceAll("esdmanager=", "");
163 token.ReplaceAll(","," ");
164 token.ReplaceAll("'","");
165 esdManagerOptions=token;
167 if (option.Length()>0) option+=" ";
176 if ((fFlags&kAliHLTReconstructorIgnoreCTP)==0 &&
177 BuildCTPTriggerClassString(ctpParam)>=0) {
178 if (!ecsParam.IsNull()) ecsParam+=";";
179 ecsParam+="CTP_TRIGGER_CLASS=";
183 if (!ecsParam.IsNull()) {
188 if (!pSystem->CheckStatus(AliHLTSystem::kReady)) {
189 pSystem->SetDetectorMask(GetRunInfo()->GetDetectorMask());
190 if (pSystem->ScanOptions(option.Data())<0) {
191 AliError("error setting options for HLT system");
194 if ((pSystem->Configure())<0) {
195 AliError("error during HLT system configuration");
200 fpEsdManager=AliHLTEsdManager::New();
202 fpEsdManager->SetOption(esdManagerOptions.Data());
205 AliHLTMisc::Instance().InitStreamerInfos(fgkCalibStreamerInfoEntry);
208 void AliHLTReconstructor::Terminate()
210 /// overloaded from AliReconstructor: terminate event processing
212 // indicate step 'Terminate'
213 SetProcessingStep(kProcessingStepTerminate);
216 AliHLTSystem* pSystem=fpPluginBase->GetInstance();
219 // clean up the HLTOUT instance if still existing, currently FinishEvent
220 // is not called at the end of the event processing and the cleanup
221 // needs to be done here to avoid a warning message. Later it can be
222 // declared a malfunction if the HLTOUT instance is still existing at
224 AliHLTOUT* pHLTOUT=NULL;
225 pSystem->InvalidateHLTOUT(&pHLTOUT);
232 AliDebug(0, Form("terminate HLT system: status %#x", pSystem->GetStatusFlags()));
233 if (pSystem->CheckStatus(AliHLTSystem::kStarted)) {
234 // send specific 'event' to execute the stop sequence
235 pSystem->Reconstruct(0, NULL, NULL);
241 void AliHLTReconstructor::FinishEvent()
243 /// overloaded from AliReconstructor: finish current event
244 if (!fpPluginBase) return;
246 // indicate step 'FinishEvent'
247 SetProcessingStep(kProcessingStepFinishEvent);
249 AliInfo("finishing event");
250 AliHLTSystem* pSystem=fpPluginBase->GetInstance();
252 // this is the end of the lifetime of the HLTOUT instance
253 // called after all other modules have been reconstructed
254 AliHLTOUT* pHLTOUT=NULL;
255 pSystem->InvalidateHLTOUT(&pHLTOUT);
264 const char* AliHLTReconstructor::fgkCalibStreamerInfoEntry="HLT/Calib/StreamerInfo";
266 void AliHLTReconstructor::Reconstruct(AliRawReader* rawReader, TTree* /*clustersTree*/) const
268 // reconstruction of real data without writing of ESD
269 // For each event, HLT reconstruction chains can be executed and
270 // added to the existing HLTOUT data
271 // The HLTOUT data is finally processed in FillESD
274 AliError("internal memory error: can not get AliHLTSystem instance from plugin");
279 AliHLTSystem* pSystem=fpPluginBase->GetInstance();
282 AliHLTOUT* pHLTOUT=NULL;
283 pSystem->InvalidateHLTOUT(&pHLTOUT);
285 // at this stage we always have a new event, regardless state of
286 // fProcessingStep; build the HLTOUT instance from scratch
291 if (pSystem->CheckStatus(AliHLTSystem::kError)) {
292 // this is the highest level where an error can be detected, no error
293 // codes can be returned
294 AliFatal("HLT system in error state");
297 if (!pSystem->CheckStatus(AliHLTSystem::kReady)) {
298 AliError("HLT system in wrong state");
302 // indicate the local reconstruction step
303 SetProcessingStep(kProcessingStepLocal);
305 // init the HLTOUT instance for the current event
306 // not nice. Have to query the global run loader to get the current event no.
308 AliRunLoader* runloader = AliRunLoader::Instance();
310 eventNo=runloader->GetEventNumber();
313 AliRawReader* input=NULL;
314 if ((fFlags&kAliHLTReconstructorIgnoreHLTOUT) == 0 ) {
317 pHLTOUT=new AliHLTOUTRawReader(input, eventNo, fpEsdManager);
319 if (pHLTOUT->Init()>=0) {
320 pSystem->InitHLTOUT(pHLTOUT);
322 AliError("error : initialization of HLTOUT handler failed");
325 AliError("memory allocation failed: can not create AliHLTOUT object");
328 AliError("can not get event number");
331 if ((iResult=pSystem->Reconstruct(1, NULL, rawReader))>=0) {
336 void AliHLTReconstructor::FillESD(AliRawReader* rawReader, TTree* /*clustersTree*/,
337 AliESDEvent* esd) const
339 // reconstruct real data and fill ESD
340 if (!rawReader || !esd) {
341 AliError("missing raw reader or esd object");
346 AliError("internal memory error: can not get AliHLTSystem instance from plugin");
350 AliHLTSystem* pSystem=fpPluginBase->GetInstance();
353 if (pSystem->CheckStatus(AliHLTSystem::kError)) {
354 // this is the highest level where an error can be detected, no error
355 // codes can be returned
356 AliFatal("HLT system in error state");
359 if (!pSystem->CheckStatus(AliHLTSystem::kReady)) {
360 AliError("HLT system in wrong state");
363 pSystem->FillESD(-1, NULL, esd);
365 // the HLTOUT handler has either been created in the AliHLTReconstructor::Reconstruct
366 // step of this event or is created now. In either case the instance is deleted after
368 AliHLTOUT* pHLTOUT=NULL;
369 pSystem->InvalidateHLTOUT(&pHLTOUT);
370 if (pHLTOUT && fProcessingStep!=kProcessingStepLocal) {
371 // this is a new event, if local reconstruction would have been executed
372 // the HLTOUT instance would have been created for the current event already,
373 // in all other cases one has to create the HLTOUT instance here
379 AliRawReader* input=NULL;
380 if ((fFlags&kAliHLTReconstructorIgnoreHLTOUT) == 0 ) {
383 pHLTOUT=new AliHLTOUTRawReader(input, esd->GetEventNumberInFile(), fpEsdManager);
386 // indicate step 'ESD filling'
387 SetProcessingStep(kProcessingStepESD);
390 ProcessHLTOUT(pHLTOUT, esd, (pSystem->GetGlobalLoggingLevel()&kHLTLogDebug)!=0);
391 // 2012-03-30: a change in the module sequence of AliReconstruction is soon
392 // going to be applied: HLT reconstruction is executed fully (i.e. both local
393 // reconstruction and FillESD) before all the other modules. In order to make the
394 // HLTOUT data available for other modules it is kept here and released in the method
396 pSystem->InitHLTOUT(pHLTOUT);
398 AliError("error creating HLTOUT handler");
403 void AliHLTReconstructor::Reconstruct(TTree* /*digitsTree*/, TTree* /*clustersTree*/) const
405 // reconstruct simulated data
407 AliHLTSystem* pSystem=fpPluginBase->GetInstance();
410 // create the HLTOUT instance in order to be available for other detector reconstruction
411 // first cleanup any existing instance
412 AliHLTOUT* pHLTOUT=NULL;
413 pSystem->InvalidateHLTOUT(&pHLTOUT);
415 // at this stage we always have a new event, regardless state of
416 // fProcessingStep; build the HLTOUT instance from scratch
422 // indicate the local reconstruction step
423 SetProcessingStep(kProcessingStepLocal);
425 // not nice. Have to query the global run loader to get the current event no.
426 // This is related to the missing AliLoader for HLT.
427 // Since AliReconstruction can not provide a digits tree, the file needs to be accessed
428 // explicitely, and the corresponding event needs to be selected.
430 AliRunLoader* runloader = AliRunLoader::Instance();
432 eventNo=runloader->GetEventNumber();
435 const char* digitfile=NULL;
436 if ((fFlags&kAliHLTReconstructorIgnoreHLTOUT) == 0 ) {
437 digitfile="HLT.Digits.root";
440 pHLTOUT=new AliHLTOUTDigitReader(eventNo, fpEsdManager, digitfile);
442 if (pHLTOUT->Init()>=0) {
443 pSystem->InitHLTOUT(pHLTOUT);
445 AliError("error : initialization of HLTOUT handler failed");
448 AliError("memory allocation failed: can not create AliHLTOUT object");
451 AliError("can not get event number");
454 // all data processing happens in FillESD
458 void AliHLTReconstructor::FillESD(TTree* /*digitsTree*/, TTree* /*clustersTree*/, AliESDEvent* esd) const
460 // reconstruct simulated data and fill ESD
462 // later this is the place to extract the simulated HLT data
463 // for now it's only an user failure condition as he tries to run HLT reconstruction
465 TString option = GetOption();
466 if (!option.IsNull() &&
467 (option.Contains("config=") || option.Contains("chains="))) {
468 AliWarning(Form("You are trying to run a custom HLT chain on digits data.\n\n"
469 "HLT reconstruction can be run embedded into AliReconstruction from\n"
470 "raw data (real or simulated)). Reconstruction of digit data takes\n"
471 "place in AliSimulation, appropriate input conversion is needed to\n"
472 "feed data from the detector digits into the HLT chain.\n"
473 "Consider running embedded into AliSimulation.\n"
474 " /*** run macro *****************************************/\n"
475 " AliSimulation sim;\n"
476 " sim.SetRunHLT(\"%s\");\n"
477 " sim.SetRunGeneration(kFALSE);\n"
478 " sim.SetMakeDigits(\"\");\n"
479 " sim.SetMakeSDigits(\"\");\n"
480 " sim.SetMakeDigitsFromHits(\"\");\n"
482 " /*********************************************************/\n\n",
486 AliError("internal memory error: can not get AliHLTSystem instance from plugin");
490 AliHLTSystem* pSystem=fpPluginBase->GetInstance();
492 if (pSystem->CheckStatus(AliHLTSystem::kError)) {
493 // this is the highest level where an error can be detected, no error
494 // codes can be returned
495 AliFatal("HLT system in error state");
498 if (!pSystem->CheckStatus(AliHLTSystem::kReady)) {
499 AliError("HLT system in wrong state");
503 // the HLTOUT handler has either been created in the AliHLTReconstructor::Reconstruct
504 // step of this event or is created now. In either case the instance is deleted after
506 AliHLTOUT* pHLTOUT=NULL;
507 pSystem->InvalidateHLTOUT(&pHLTOUT);
508 if (pHLTOUT && fProcessingStep!=kProcessingStepLocal) {
509 // this is a new event, if local reconstruction would have been executed
510 // the HLTOUT instance would have been created for the current event already,
511 // in all other cases one has to create the HLTOUT instance here
517 const char* digitfile=NULL;
518 if ((fFlags&kAliHLTReconstructorIgnoreHLTOUT) == 0 ) {
519 digitfile="HLT.Digits.root";
521 pHLTOUT=new AliHLTOUTDigitReader(esd->GetEventNumberInFile(), fpEsdManager, digitfile);
524 // indicate step 'ESD filling'
525 SetProcessingStep(kProcessingStepESD);
528 ProcessHLTOUT(pHLTOUT, esd, (pSystem->GetGlobalLoggingLevel()&kHLTLogDebug)!=0);
529 // 2012-03-30: a change in the module sequence of AliReconstruction is soon
530 // going to be applied: HLT reconstruction is executed fully (i.e. both local
531 // reconstruction and FillESD) before all the other modules. In order to make the
532 // HLTOUT data available for other modules it is kept here and released in the method
534 pSystem->InitHLTOUT(pHLTOUT);
536 AliError("error creating HLTOUT handler");
541 void AliHLTReconstructor::ProcessHLTOUT(AliHLTOUT* pHLTOUT, AliESDEvent* esd, bool bVerbose) const
543 // treatment of simulated or real HLTOUT data
544 if (!pHLTOUT) return;
546 AliError("internal memory error: can not get AliHLTSystem instance from plugin");
550 AliHLTSystem* pSystem=fpPluginBase->GetInstance();
552 AliError("error getting HLT system instance");
556 if (pHLTOUT->Init()<0) {
557 AliError("error : initialization of HLTOUT handler failed");
562 PrintHLTOUTContent(pHLTOUT);
564 int blockindex=pHLTOUT->SelectFirstDataBlock(kAliHLTDataTypeStreamerInfo);
566 const AliHLTUInt8_t* pBuffer=NULL;
567 AliHLTUInt32_t size=0;
568 if (pHLTOUT->GetDataBuffer(pBuffer, size)>=0) {
569 TObject* pObject=AliHLTMessage::Extract(pBuffer, size);
571 TObjArray* pArray=dynamic_cast<TObjArray*>(pObject);
573 AliHLTMisc::Instance().InitStreamerInfos(pArray);
575 AliError(Form("wrong class type of streamer info list: expected TObjArray, but object is of type %s", pObject->Class()->GetName()));
578 AliError(Form("failed to extract object from data block of type %s", AliHLTComponent::DataType2Text(kAliHLTDataTypeStreamerInfo).c_str()));
581 AliError(Form("failed to get data buffer for block of type %s", AliHLTComponent::DataType2Text(kAliHLTDataTypeStreamerInfo).c_str()));
585 if (pSystem->ProcessHLTOUT(pHLTOUT, esd)<0) {
586 AliError("error processing HLTOUT");
589 if (bVerbose && esd) {
590 AliInfo("HLT ESD content:");
595 void AliHLTReconstructor::ProcessHLTOUT(const char* digitFile, AliESDEvent* pEsd) const
597 // debugging/helper function to examine simulated data
598 if (!digitFile) return;
600 // read the number of events
602 if (f.IsZombie()) return;
604 f.GetObject("rawhltout", pTree);
606 AliWarning(Form("can not find tree rawhltout in file %s", digitFile));
609 int nofEvents=pTree->GetEntries();
611 //delete pTree; OF COURSE NOT! its an object in the file
614 for (int event=0; event<nofEvents; event++) {
615 AliHLTOUTDigitReader* pHLTOUT=new AliHLTOUTDigitReader(event, fpEsdManager, digitFile);
617 AliInfo(Form("event %d", event));
618 ProcessHLTOUT(pHLTOUT, pEsd, true);
621 AliError("error creating HLTOUT handler");
626 void AliHLTReconstructor::ProcessHLTOUT(AliRawReader* pRawReader, AliESDEvent* pEsd) const
628 // debugging/helper function to examine simulated or real HLTOUT data
629 if (!pRawReader) return;
631 pRawReader->RewindEvents();
632 for (int event=0; pRawReader->NextEvent(); event++) {
633 AliHLTOUTRawReader* pHLTOUT=new AliHLTOUTRawReader(pRawReader, event, fpEsdManager);
635 AliInfo(Form("event %d", event));
636 // the two event fields contain: period - orbit - bunch crossing counter
640 // | 28 bit | 24 bit | 12|
642 AliHLTUInt64_t eventId=0;
643 const UInt_t* rawreaderEventId=pRawReader->GetEventId();
644 if (rawreaderEventId) {
645 eventId=rawreaderEventId[0];
647 eventId|=rawreaderEventId[1];
649 AliInfo(Form("Event Id from rawreader:\t 0x%016llx", eventId));
650 ProcessHLTOUT(pHLTOUT, pEsd, true);
653 AliError("error creating HLTOUT handler");
658 void AliHLTReconstructor::PrintHLTOUTContent(AliHLTOUT* pHLTOUT) const
660 // print the block specifications of the HLTOUT data blocks
661 if (!pHLTOUT) return;
664 AliInfo(Form("Event Id from hltout:\t 0x%016llx", pHLTOUT->EventId()));
665 for (iResult=pHLTOUT->SelectFirstDataBlock();
667 iResult=pHLTOUT->SelectNextDataBlock()) {
668 AliHLTComponentDataType dt=kAliHLTVoidDataType;
669 AliHLTUInt32_t spec=kAliHLTVoidDataSpec;
670 pHLTOUT->GetDataBlockDescription(dt, spec);
671 const AliHLTUInt8_t* pBuffer=NULL;
672 AliHLTUInt32_t size=0;
673 if (pHLTOUT->GetDataBuffer(pBuffer, size)>=0) {
674 pHLTOUT->ReleaseDataBuffer(pBuffer);
675 pBuffer=NULL; // just a dummy
677 AliInfo(Form(" %s 0x%x: size %d", AliHLTComponent::DataType2Text(dt).c_str(), spec, size));
681 int AliHLTReconstructor::BuildCTPTriggerClassString(TString& triggerclasses) const
683 // build the CTP trigger class string from the OCDB entry of the CTP trigger
686 triggerclasses.Clear();
687 AliCentralTrigger* pCTP = new AliCentralTrigger();
688 AliTriggerConfiguration *config=NULL;
689 TString configstr("");
690 if (pCTP->LoadConfiguration(configstr) &&
691 (config = pCTP->GetConfiguration())!=NULL) {
692 const TObjArray& classesArray = config->GetClasses();
693 int nclasses = classesArray.GetEntriesFast();
694 for( int iclass=0; iclass < nclasses; iclass++ ) {
695 AliTriggerClass* trclass = NULL;
696 if (classesArray.At(iclass) && (trclass=dynamic_cast<AliTriggerClass*>(classesArray.At(iclass)))!=NULL) {
698 int trindex = TMath::Nint(TMath::Log2(trclass->GetMask()));
699 entry.Form("%02d:%s:", trindex, trclass->GetName());
700 AliTriggerCluster* cluster=NULL;
701 TObject* clusterobj=config->GetClusters().FindObject(trclass->GetCluster());
702 if (clusterobj && (cluster=dynamic_cast<AliTriggerCluster*>(clusterobj))!=NULL) {
703 TString detectors=cluster->GetDetectorsInCluster();
704 TObjArray* pTokens=detectors.Tokenize(" ");
706 for (int dix=0; dix<pTokens->GetEntriesFast(); dix++) {
707 int id=AliDAQ::DetectorID(((TObjString*)pTokens->At(dix))->GetString());
709 TString detstr; detstr.Form("%s%02d", dix>0?"-":"", id);
712 AliError(Form("invalid detector name extracted from trigger cluster: %s (%s)", ((TObjString*)pTokens->At(dix))->GetString().Data(), detectors.Data()));
720 AliError(Form("can not find trigger cluster %s in config", trclass->GetCluster()?trclass->GetCluster()->GetName():"NULL"));
724 if (!triggerclasses.IsNull()) triggerclasses+=",";
725 triggerclasses+=entry;