]> git.uio.no Git - u/mrichter/AliRoot.git/blob - HLT/rec/AliHLTReconstructor.cxx
minor bugfix: pointer protection for printout
[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 #include "AliRunLoader.h"
53
54 class AliCDBEntry;
55
56 /** ROOT macro for the implementation of ROOT specific class methods */
57 ClassImp(AliHLTReconstructor)
58
59 AliHLTReconstructor::AliHLTReconstructor()
60   : AliReconstructor()
61   , fpEsdManager(NULL)
62   , fpPluginBase(new AliHLTPluginBase)
63   , fFlags(0)
64
65   //constructor
66 }
67
68 AliHLTReconstructor::AliHLTReconstructor(const char* options)
69   : AliReconstructor()
70   , fpEsdManager(NULL)
71   , fpPluginBase(new AliHLTPluginBase)
72   , fFlags(0)
73
74   //constructor
75   if (options) Init(options);
76 }
77
78 AliHLTReconstructor::~AliHLTReconstructor()
79
80   //destructor
81
82   if (fpEsdManager) AliHLTEsdManager::Delete(fpEsdManager);
83   fpEsdManager=NULL;
84
85   if (fpPluginBase) {
86   AliHLTSystem* pSystem=fpPluginBase->GetInstance();
87   if (pSystem) {
88     AliDebug(0, Form("terminate HLT system: status %#x", pSystem->GetStatusFlags()));
89     if (pSystem->CheckStatus(AliHLTSystem::kStarted)) {
90       // send specific 'event' to execute the stop sequence
91       pSystem->Reconstruct(0, NULL, NULL);
92     }
93   }
94   delete fpPluginBase;
95   }
96   fpPluginBase=NULL;
97
98 }
99
100 void AliHLTReconstructor::Init(const char* options)
101 {
102   // init the reconstructor
103   SetOption(options);
104   Init();
105 }
106
107 void AliHLTReconstructor::Init()
108 {
109   // init the reconstructor
110   if (!fpPluginBase) {
111     AliError("internal memory error: can not get AliHLTSystem instance from plugin");
112     return;
113   }
114
115   AliHLTSystem* pSystem=fpPluginBase->GetInstance();
116   if (!pSystem) {
117     AliError("can not create AliHLTSystem object");
118     return;
119   }
120   if (pSystem->CheckStatus(AliHLTSystem::kError)) {
121     AliError("HLT system in error state");
122     return;
123   }
124
125   TString esdManagerOptions;
126
127   // the options scan has been moved to AliHLTSystem, the old code
128   // here is kept to be able to run an older version of the HLT code
129   // with newer AliRoot versions.
130   TString option = GetOption();
131   TObjArray* pTokens=option.Tokenize(" ");
132   option="";
133   if (pTokens) {
134     int iEntries=pTokens->GetEntries();
135     for (int i=0; i<iEntries; i++) {
136       TString token=(((TObjString*)pTokens->At(i))->GetString());
137       if (token.Contains("loglevel=")) {
138         TString param=token.ReplaceAll("loglevel=", "");
139         if (param.IsDigit()) {
140           pSystem->SetGlobalLoggingLevel((AliHLTComponentLogSeverity)param.Atoi());
141         } else if (param.BeginsWith("0x") &&
142                    param.Replace(0,2,"",0).IsHex()) {
143           int severity=0;
144           sscanf(param.Data(),"%x", &severity);
145           pSystem->SetGlobalLoggingLevel((AliHLTComponentLogSeverity)severity);
146         } else {
147           AliWarning("wrong parameter for option \'loglevel=\', (hex) number expected");
148         }
149       } else if (token.Contains("alilog=off")) {
150         pSystem->SwitchAliLog(0);
151       } else if (token.CompareTo("ignore-hltout")==0) {
152         fFlags|=kAliHLTReconstructorIgnoreHLTOUT;
153       } else if (token.CompareTo("run-online-config")==0) {
154         fFlags|=kAliHLTReconstructorIgnoreHLTOUT;
155         if (option.Length()>0) option+=" ";
156         option+=token;
157       } else if (token.CompareTo("ignore-ctp")==0) {
158         fFlags|=kAliHLTReconstructorIgnoreCTP;
159       } else if (token.Contains("esdmanager=")) {
160         token.ReplaceAll("esdmanager=", "");
161         token.ReplaceAll(","," ");
162         token.ReplaceAll("'","");
163         esdManagerOptions=token;
164       } else {
165         if (option.Length()>0) option+=" ";
166         option+=token;
167       }
168     }
169     delete pTokens;
170   }
171
172   TString ecsParam;
173   TString ctpParam;
174   if ((fFlags&kAliHLTReconstructorIgnoreCTP)==0 &&
175       BuildCTPTriggerClassString(ctpParam)>=0) {
176     if (!ecsParam.IsNull()) ecsParam+=";";
177     ecsParam+="CTP_TRIGGER_CLASS=";
178     ecsParam+=ctpParam;
179   }
180
181   if (!ecsParam.IsNull()) {
182     option+=" ECS=";
183     option+=ecsParam;
184   }
185
186   if (!pSystem->CheckStatus(AliHLTSystem::kReady)) {
187     if (pSystem->ScanOptions(option.Data())<0) {
188       AliError("error setting options for HLT system");
189       return;
190     }
191     if ((pSystem->Configure())<0) {
192       AliError("error during HLT system configuration");
193       return;
194     }
195   }
196
197   fpEsdManager=AliHLTEsdManager::New();
198   if (fpEsdManager) {
199     fpEsdManager->SetOption(esdManagerOptions.Data());
200   }
201
202   AliHLTMisc::Instance().InitStreamerInfos(fgkCalibStreamerInfoEntry);
203 }
204
205 void AliHLTReconstructor::Terminate() const
206 {
207   AliInfo("terminating");
208   if (fpPluginBase) {
209   AliHLTSystem* pSystem=fpPluginBase->GetInstance();
210   if (pSystem) {
211     AliDebug(0, Form("terminate HLT system: status %#x", pSystem->GetStatusFlags()));
212     if (pSystem->CheckStatus(AliHLTSystem::kStarted)) {
213       // send specific 'event' to execute the stop sequence
214       pSystem->Reconstruct(0, NULL, NULL);
215     }
216   }
217   }
218 }
219
220 const char* AliHLTReconstructor::fgkCalibStreamerInfoEntry="HLT/Calib/StreamerInfo";
221
222 void AliHLTReconstructor::Reconstruct(AliRawReader* rawReader, TTree* /*clustersTree*/) const 
223 {
224   // reconstruction of real data without writing of ESD
225   // For each event, HLT reconstruction chains can be executed and
226   // added to the existing HLTOUT data
227   // The HLTOUT data is finally processed in FillESD
228
229   if (!fpPluginBase) {
230     AliError("internal memory error: can not get AliHLTSystem instance from plugin");
231     return;
232   }
233
234   int iResult=0;
235   AliHLTSystem* pSystem=fpPluginBase->GetInstance();
236
237   if (pSystem) {
238     AliHLTOUT* pHLTOUT=NULL;
239     pSystem->InvalidateHLTOUT(&pHLTOUT);
240     if (pHLTOUT) {
241       delete pHLTOUT;
242       pHLTOUT=NULL;
243     }
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
253     // init the HLTOUT instance for the current event
254     // not nice. Have to query the global run loader to get the current event no.
255     Int_t eventNo=-1;
256     AliRunLoader* runloader = AliRunLoader::Instance();
257     if (runloader) {
258       eventNo=runloader->GetEventNumber();
259     }
260     if (eventNo>=0) {
261       AliRawReader* input=NULL;
262       if ((fFlags&kAliHLTReconstructorIgnoreHLTOUT) == 0 ) {
263         input=rawReader;
264       }
265       pHLTOUT=new AliHLTOUTRawReader(input, eventNo, fpEsdManager);
266       if (pHLTOUT) {
267         if (pHLTOUT->Init()>=0) {
268           pSystem->InitHLTOUT(pHLTOUT);
269         } else {
270           AliError("error : initialization of HLTOUT handler failed");
271         }
272       } else {
273         AliError("memory allocation failed: can not create AliHLTOUT object");
274       }
275     } else {
276       AliError("can not get event number");
277     }
278
279     if ((iResult=pSystem->Reconstruct(1, NULL, rawReader))>=0) {
280     }
281   }
282 }
283
284 void AliHLTReconstructor::FillESD(AliRawReader* rawReader, TTree* /*clustersTree*/, 
285                                   AliESDEvent* esd) const
286 {
287   // reconstruct real data and fill ESD
288   if (!rawReader || !esd) {
289     AliError("missing raw reader or esd object");
290     return;
291   }
292
293   if (!fpPluginBase) {
294     AliError("internal memory error: can not get AliHLTSystem instance from plugin");
295     return;
296   }
297
298   AliHLTSystem* pSystem=fpPluginBase->GetInstance();
299
300   if (pSystem) {
301     if (pSystem->CheckStatus(AliHLTSystem::kError)) {
302       AliError("HLT system in error state");
303       return;
304     }
305     if (!pSystem->CheckStatus(AliHLTSystem::kReady)) {
306       AliError("HLT system in wrong state");
307       return;
308     }
309     pSystem->FillESD(-1, NULL, esd);
310
311     // the HLTOUT handler has either been created in the AliHLTReconstructor::Reconstruct
312     // step of this event or is created now. In either case the instance is deleted after
313     // the processing
314     AliHLTOUT* pHLTOUT=NULL;
315     pSystem->InvalidateHLTOUT(&pHLTOUT);
316     if (!pHLTOUT) {
317       AliRawReader* input=NULL;
318       if ((fFlags&kAliHLTReconstructorIgnoreHLTOUT) == 0 ) {
319         input=rawReader;
320       }
321       pHLTOUT=new AliHLTOUTRawReader(input, esd->GetEventNumberInFile(), fpEsdManager);
322     }
323     if (pHLTOUT) {
324       ProcessHLTOUT(pHLTOUT, esd, (pSystem->GetGlobalLoggingLevel()&kHLTLogDebug)!=0);
325       delete pHLTOUT;
326     } else {
327       AliError("error creating HLTOUT handler");
328     }
329   }
330 }
331
332 void AliHLTReconstructor::Reconstruct(TTree* /*digitsTree*/, TTree* /*clustersTree*/) const
333 {
334   // reconstruct simulated data
335
336   AliHLTSystem* pSystem=fpPluginBase->GetInstance();
337
338   if (pSystem) {
339     // create the HLTOUT instance in order to be available for other detector reconstruction
340     // first cleanup any existing instance
341     AliHLTOUT* pHLTOUT=NULL;
342     pSystem->InvalidateHLTOUT(&pHLTOUT);
343     if (pHLTOUT) {
344       delete pHLTOUT;
345       pHLTOUT=NULL;
346     }
347
348     // not nice. Have to query the global run loader to get the current event no.
349     // This is related to the missing AliLoader for HLT.
350     // Since AliReconstruction can not provide a digits tree, the file needs to be accessed
351     // explicitely, and the corresponding event needs to be selected.
352     Int_t eventNo=-1;
353     AliRunLoader* runloader = AliRunLoader::Instance();
354     if (runloader) {
355       eventNo=runloader->GetEventNumber();
356     }
357     if (eventNo>=0) {
358       const char* digitfile=NULL;
359       if ((fFlags&kAliHLTReconstructorIgnoreHLTOUT) == 0 ) {
360         digitfile="HLT.Digits.root";
361       }
362
363       pHLTOUT=new AliHLTOUTDigitReader(eventNo, fpEsdManager, digitfile);
364       if (pHLTOUT) {
365         if (pHLTOUT->Init()>=0) {
366           pSystem->InitHLTOUT(pHLTOUT);
367         } else {
368           AliError("error : initialization of HLTOUT handler failed");
369         }
370       } else {
371         AliError("memory allocation failed: can not create AliHLTOUT object");
372       }
373     } else {
374       AliError("can not get event number");
375     }
376
377     // all data processing happens in FillESD
378   }
379 }
380
381 void AliHLTReconstructor::FillESD(TTree* /*digitsTree*/, TTree* /*clustersTree*/, AliESDEvent* esd) const
382 {
383   // reconstruct simulated data and fill ESD
384
385   // later this is the place to extract the simulated HLT data
386   // for now it's only an user failure condition as he tries to run HLT reconstruction
387   // on simulated data 
388   TString option = GetOption();
389   if (!option.IsNull() && 
390       (option.Contains("config=") || option.Contains("chains="))) {
391     AliWarning(Form("You are trying to run a custom HLT chain on digits data.\n\n"
392                     "HLT reconstruction can be run embedded into AliReconstruction from\n"
393                     "raw data (real or simulated)). Reconstruction of digit data takes\n"
394                     "place in AliSimulation, appropriate input conversion is needed to\n"
395                     "feed data from the detector digits into the HLT chain.\n"
396                     "Consider running embedded into AliSimulation.\n"
397                     "        /***  run macro *****************************************/\n"
398                     "        AliSimulation sim;\n"
399                     "        sim.SetRunHLT(\"%s\");\n"
400                     "        sim.SetRunGeneration(kFALSE);\n"
401                     "        sim.SetMakeDigits(\"\");\n"
402                     "        sim.SetMakeSDigits(\"\");\n"
403                     "        sim.SetMakeDigitsFromHits(\"\");\n"
404                     "        sim.Run();\n"
405                     "        /*********************************************************/\n\n",
406                     option.Data()));
407   }
408   if (!fpPluginBase) {
409     AliError("internal memory error: can not get AliHLTSystem instance from plugin");
410     return;
411   }
412
413   AliHLTSystem* pSystem=fpPluginBase->GetInstance();
414   if (pSystem) {
415     if (pSystem->CheckStatus(AliHLTSystem::kError)) {
416       AliError("HLT system in error state");
417       return;
418     }
419     if (!pSystem->CheckStatus(AliHLTSystem::kReady)) {
420       AliError("HLT system in wrong state");
421       return;
422     }
423
424     // the HLTOUT handler has either been created in the AliHLTReconstructor::Reconstruct
425     // step of this event or is created now. In either case the instance is deleted after
426     // the processing
427     AliHLTOUT* pHLTOUT=NULL;
428     pSystem->InvalidateHLTOUT(&pHLTOUT);
429     if (!pHLTOUT) {
430       const char* digitfile=NULL;
431       if ((fFlags&kAliHLTReconstructorIgnoreHLTOUT) == 0 ) {
432         digitfile="HLT.Digits.root";
433       }
434       pHLTOUT=new AliHLTOUTDigitReader(esd->GetEventNumberInFile(), fpEsdManager, digitfile);
435     }
436
437     if (pHLTOUT) {
438       ProcessHLTOUT(pHLTOUT, esd, (pSystem->GetGlobalLoggingLevel()&kHLTLogDebug)!=0);
439       delete pHLTOUT;
440     } else {
441       AliError("error creating HLTOUT handler");
442     }
443   }
444 }
445
446 void AliHLTReconstructor::ProcessHLTOUT(AliHLTOUT* pHLTOUT, AliESDEvent* esd, bool bVerbose) const
447 {
448   // treatment of simulated or real HLTOUT data
449   if (!pHLTOUT) return;
450   if (!fpPluginBase) {
451     AliError("internal memory error: can not get AliHLTSystem instance from plugin");
452     return;
453   }
454
455   AliHLTSystem* pSystem=fpPluginBase->GetInstance();
456   if (!pSystem) {
457     AliError("error getting HLT system instance");
458     return;
459   }
460
461   if (pHLTOUT->Init()<0) {
462     AliError("error : initialization of HLTOUT handler failed");
463     return;
464   }
465
466   if (bVerbose)
467     PrintHLTOUTContent(pHLTOUT);
468
469   int blockindex=pHLTOUT->SelectFirstDataBlock(kAliHLTDataTypeStreamerInfo);
470   if (blockindex>=0) {
471     const AliHLTUInt8_t* pBuffer=NULL;
472     AliHLTUInt32_t size=0;
473     if (pHLTOUT->GetDataBuffer(pBuffer, size)>=0) {
474       TObject* pObject=AliHLTMessage::Extract(pBuffer, size);
475       if (pObject) {
476         TObjArray* pArray=dynamic_cast<TObjArray*>(pObject);
477         if (pArray) {
478           AliHLTMisc::Instance().InitStreamerInfos(pArray);
479         } else {
480           AliError(Form("wrong class type of streamer info list: expected TObjArray, but object is of type %s", pObject->Class()->GetName()));
481         }
482       } else {
483         AliError(Form("failed to extract object from data block of type %s", AliHLTComponent::DataType2Text(kAliHLTDataTypeStreamerInfo).c_str()));
484       }
485     } else {
486       AliError(Form("failed to get data buffer for block of type %s", AliHLTComponent::DataType2Text(kAliHLTDataTypeStreamerInfo).c_str()));
487     }
488   }
489
490   if (pSystem->ProcessHLTOUT(pHLTOUT, esd)<0) {
491     AliError("error processing HLTOUT");
492   }
493
494   if (bVerbose && esd) {
495     AliInfo("HLT ESD content:");
496     esd->Print();
497   }
498   pHLTOUT->Reset();
499 }
500
501 void AliHLTReconstructor::ProcessHLTOUT(const char* digitFile, AliESDEvent* pEsd) const
502 {
503   // debugging/helper function to examine simulated data
504   if (!digitFile) return;
505
506   // read the number of events
507   TFile f(digitFile);
508   if (f.IsZombie()) return;
509   TTree* pTree=NULL;
510   f.GetObject("rawhltout", pTree);
511   if (!pTree) {
512     AliWarning(Form("can not find tree rawhltout in file %s", digitFile));
513     return ;
514   }
515   int nofEvents=pTree->GetEntries();
516   f.Close();
517   //delete pTree; OF COURSE NOT! its an object in the file
518   pTree=NULL;
519
520   for (int event=0; event<nofEvents; event++) {
521     AliHLTOUTDigitReader* pHLTOUT=new AliHLTOUTDigitReader(event, fpEsdManager, digitFile);
522     if (pHLTOUT) {
523       AliInfo(Form("event %d", event));
524       ProcessHLTOUT(pHLTOUT, pEsd, true);
525       delete pHLTOUT;
526     } else {
527       AliError("error creating HLTOUT handler");
528     }
529   }
530 }
531
532 void AliHLTReconstructor::ProcessHLTOUT(AliRawReader* pRawReader, AliESDEvent* pEsd) const
533 {
534   // debugging/helper function to examine simulated or real HLTOUT data
535   if (!pRawReader) return;
536
537   pRawReader->RewindEvents();
538   for (int event=0; pRawReader->NextEvent(); event++) {
539     AliHLTOUTRawReader* pHLTOUT=new AliHLTOUTRawReader(pRawReader, event, fpEsdManager);
540     if (pHLTOUT) {
541       AliInfo(Form("event %d", event));
542       // the two event fields contain: period - orbit - bunch crossing counter
543       //        id[0]               id[1]
544       // |32                0|32                0|
545       //
546       // |      28 bit    |       24 bit     | 12|
547       //        period          orbit         bcc
548       AliHLTUInt64_t eventId=0;
549       const UInt_t* rawreaderEventId=pRawReader->GetEventId();
550       if (rawreaderEventId) {
551         eventId=rawreaderEventId[0];
552         eventId=eventId<<32;
553         eventId|=rawreaderEventId[1];
554       }
555       AliInfo(Form("Event Id from rawreader:\t 0x%016llx", eventId));
556       ProcessHLTOUT(pHLTOUT, pEsd, true);
557       delete pHLTOUT;
558     } else {
559       AliError("error creating HLTOUT handler");
560     }
561   }
562 }
563
564 void AliHLTReconstructor::PrintHLTOUTContent(AliHLTOUT* pHLTOUT) const
565 {
566   // print the block specifications of the HLTOUT data blocks
567   if (!pHLTOUT) return;
568   int iResult=0;
569
570   AliInfo(Form("Event Id from hltout:\t 0x%016llx", pHLTOUT->EventId()));
571   for (iResult=pHLTOUT->SelectFirstDataBlock();
572        iResult>=0;
573        iResult=pHLTOUT->SelectNextDataBlock()) {
574     AliHLTComponentDataType dt=kAliHLTVoidDataType;
575     AliHLTUInt32_t spec=kAliHLTVoidDataSpec;
576     pHLTOUT->GetDataBlockDescription(dt, spec);
577     const AliHLTUInt8_t* pBuffer=NULL;
578     AliHLTUInt32_t size=0;
579     if (pHLTOUT->GetDataBuffer(pBuffer, size)>=0) {
580       pHLTOUT->ReleaseDataBuffer(pBuffer);
581       pBuffer=NULL; // just a dummy
582     }
583     AliInfo(Form("   %s  0x%x: size %d", AliHLTComponent::DataType2Text(dt).c_str(), spec, size));
584   }
585 }
586
587 int AliHLTReconstructor::BuildCTPTriggerClassString(TString& triggerclasses) const
588 {
589   // build the CTP trigger class string from the OCDB entry of the CTP trigger
590   int iResult=0;
591   
592   triggerclasses.Clear();
593   AliCentralTrigger* pCTP = new AliCentralTrigger();
594   AliTriggerConfiguration *config=NULL;
595   TString configstr("");
596   if (pCTP->LoadConfiguration(configstr) && 
597       (config = pCTP->GetConfiguration())!=NULL) {
598     const TObjArray& classesArray = config->GetClasses();
599     int nclasses = classesArray.GetEntriesFast();
600     for( int iclass=0; iclass < nclasses; iclass++ ) {
601       AliTriggerClass* trclass = NULL;
602       if (classesArray.At(iclass) && (trclass=dynamic_cast<AliTriggerClass*>(classesArray.At(iclass)))!=NULL) {
603         TString entry;
604         int trindex = TMath::Nint(TMath::Log2(trclass->GetMask()));
605         entry.Form("%02d:%s:", trindex, trclass->GetName());
606         AliTriggerCluster* cluster=NULL;
607         TObject* clusterobj=config->GetClusters().FindObject(trclass->GetCluster());
608         if (clusterobj && (cluster=dynamic_cast<AliTriggerCluster*>(clusterobj))!=NULL) {
609           TString detectors=cluster->GetDetectorsInCluster();
610           TObjArray* pTokens=detectors.Tokenize(" ");
611           if (pTokens) {
612             for (int dix=0; dix<pTokens->GetEntriesFast(); dix++) {
613               int id=AliDAQ::DetectorID(((TObjString*)pTokens->At(dix))->GetString());
614               if (id>=0) {
615                 TString detstr; detstr.Form("%s%02d", dix>0?"-":"", id);
616                 entry+=detstr;
617               } else {
618                 AliError(Form("invalid detector name extracted from trigger cluster: %s (%s)", ((TObjString*)pTokens->At(dix))->GetString().Data(), detectors.Data()));
619                 iResult=-EPROTO;
620                 break;
621               }
622             }
623             delete pTokens;
624           }
625         } else {
626           AliError(Form("can not find trigger cluster %s in config", trclass->GetCluster()?trclass->GetCluster()->GetName():"NULL"));
627           iResult=-EPROTO;
628           break;
629         }
630         if (!triggerclasses.IsNull()) triggerclasses+=",";
631         triggerclasses+=entry;
632       }
633     }
634   }
635
636   return iResult;
637 }