Compatibility with ROOT trunk
[u/mrichter/AliRoot.git] / STEER / STEER / AliCentralTrigger.cxx
1 /**************************************************************************
2  * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
3  *                                                                        *
4  * Author: The ALICE Off-line Project.                                    *
5  * Contributors are mentioned in the code where appropriate.              *
6  *                                                                        *
7  * Permission to use, copy, modify and distribute this software and its   *
8  * documentation strictly for non-commercial purposes is hereby granted   *
9  * without fee, provided that the above copyright notice appears in all   *
10  * copies and that both the copyright notice and this permission notice   *
11  * appear in the supporting documentation. The authors make no claims     *
12  * about the suitability of this software for any purpose. It is          *
13  * provided "as is" without express or implied warranty.                  *
14  **************************************************************************/
15
16 /* $Id$ */
17
18 ///////////////////////////////////////////////////////////////////////////////
19 //                                                                           //
20 // This class for running the Central Trigger Processor                      //
21 //                                                                           //
22 //                                                                           //
23 //    Load Configuration                                                     //
24 //    Make a list the trigger detectors involved (from the classes)          //
25 //    For the each event                                                     //
26 //           Run the Trigger for the each detector                           //
27 //           Get the inputs                                                  //
28 //           Check the trigger classes                                       //
29 //           Create the class mask                                           //
30 //           Save result                                                     //
31 //                                                                           //
32 //                                                                           //
33 ///////////////////////////////////////////////////////////////////////////////
34
35 #include <TString.h>
36 #include <TObjString.h>
37 #include <TObjArray.h>
38 #include <TStopwatch.h>
39 #include <TFile.h>
40 #include <TTree.h>
41
42 #include "AliLog.h"
43 #include "AliRun.h"
44 #include "AliRunLoader.h"
45 #include "AliLoader.h"
46 #include "AliModule.h"
47
48 #include "AliTriggerInput.h"
49 #include "AliTriggerDetector.h"
50 #include "AliTriggerConfiguration.h"
51 #include "AliTriggerClass.h"
52 #include "AliTriggerCluster.h"
53 #include "AliCentralTrigger.h"
54 #include "AliDetectorEventHeader.h"
55 #include "AliHeader.h"
56
57 #include "AliCDBManager.h"
58 #include "AliCDBPath.h"
59 #include "AliCDBEntry.h"
60
61 using std::endl;
62 using std::cout;
63 using std::hex;
64 using std::dec;
65 ClassImp( AliCentralTrigger )
66
67 //_____________________________________________________________________________
68 AliCentralTrigger::AliCentralTrigger() :
69    TObject(),
70    fClassMask(0),
71    fClusterMask(0),
72    fL0TriggerInputs(0),
73    fL1TriggerInputs(0),
74    fL2TriggerInputs(0),
75    fConfiguration(NULL)
76 {
77    // Default constructor
78   SetOwner();
79 }
80
81 //_____________________________________________________________________________
82 AliCentralTrigger::AliCentralTrigger( TString & config ) :
83    TObject(),
84    fClassMask(0),
85    fClusterMask(0),
86    fL0TriggerInputs(0),
87    fL1TriggerInputs(0),
88    fL2TriggerInputs(0),
89    fConfiguration(NULL)
90 {
91    // Default constructor
92    LoadConfiguration( config );
93 }
94
95 //_____________________________________________________________________________
96 AliCentralTrigger::~AliCentralTrigger()
97 {
98   // Destructor
99   DeleteConfiguration();
100 }
101
102 //_____________________________________________________________________________
103 void AliCentralTrigger::DeleteConfiguration()
104 {
105   // Delete the active configuration
106   fClassMask = 0;
107   fClusterMask = 0;
108   fL0TriggerInputs = 0;
109   fL1TriggerInputs = 0;
110   fL2TriggerInputs = 0;
111   if (fConfiguration) {
112     if (IsOwner()) delete fConfiguration;
113     fConfiguration = 0x0;
114   }
115 }
116
117 //_____________________________________________________________________________
118 void AliCentralTrigger::Reset()
119 {
120    // Reset Class Mask and classes
121    fClassMask = 0;
122    fClusterMask = 0;
123    fL0TriggerInputs = 0;
124    fL1TriggerInputs = 0;
125    fL2TriggerInputs = 0;
126
127    if (fConfiguration) {
128      const TObjArray& classesArray = fConfiguration->GetClasses();
129      Int_t nclasses = classesArray.GetEntriesFast();
130      for( Int_t j=0; j<nclasses; j++ ) {
131        AliTriggerClass* trclass = (AliTriggerClass*)classesArray.At( j );
132        trclass->Reset();
133      }
134    }
135 }
136
137 //_____________________________________________________________________________
138 void AliCentralTrigger::MakeBranch( TString name, TTree * tree )
139 {
140    // Make a branch to store only trigger class mask event by event
141
142    if( tree )  {
143       AliDebug( 1, "Got Tree from folder." );
144       TBranch* branch = tree->GetBranch( name );
145       if( branch == 0x0 ) {
146          AliDebug( 1, "Creating new branch" );
147          branch = tree->Branch( name, &(this->fClassMask), "fClassMask/l:fClusterMask/i:fL0TriggerInputs/i:fL1TriggerInputs/i:fL2TriggerInputs/s" );
148          branch->SetAutoDelete( kFALSE );
149       }
150       else {
151          AliDebug( 1, "Got Branch from Tree" );
152          branch->SetAddress( &(this->fClassMask) );
153       }
154    }
155 }
156
157 //_____________________________________________________________________________
158 Bool_t AliCentralTrigger::LoadConfiguration( TString & config )
159 {
160    // Load one and only one pre-created COnfiguration from database/file that match
161    // with the input string 'config'
162    // Ej: "p-p", "Pb-Pb" or "p-p-DIMUON CALIBRATION-CENTRAL-BARREL"
163
164    // Delete the active configuration, if any
165   DeleteConfiguration();
166
167    // Load the selected configuration
168    if (!config.IsNull()) {
169      fConfiguration = AliTriggerConfiguration::LoadConfiguration( config );
170      SetOwner();
171      if(fConfiguration)
172        return kTRUE;
173      else {
174        AliError( Form( "Valid TriggerConfiguration (%s) is not found ! Disabling the trigger simulation !", config.Data() ) );
175        return kFALSE;
176      }
177    }
178    else {
179      // Load one and only one trigger descriptor from CDB
180      AliInfo( "Getting trigger configuration from OCDB!" );
181  
182      AliCDBPath path( "GRP", "CTP", "Config" );
183         
184      AliCDBEntry *entry=AliCDBManager::Instance()->Get(path.GetPath());
185      SetOwner(kFALSE);
186      if( !entry ) AliFatal( "Couldn't load trigger description data from CDB!" );
187
188      fConfiguration = (AliTriggerConfiguration *)entry->GetObject();
189      if(fConfiguration)
190        return kTRUE;
191      else {
192        AliError( "No valid configuration is found in the CDB ! Disabling the trigger simulation !" );
193        return kFALSE;
194      }
195    }
196 }
197
198 //_____________________________________________________________________________
199 TString AliCentralTrigger::GetDetectors()
200 {
201    // return TString with the detectors (modules) to be used for triggering
202
203    TString result;
204
205    if (fConfiguration)
206      result = fConfiguration->GetTriggeringModules();
207
208    return result;
209 }
210
211 //_____________________________________________________________________________
212 Bool_t AliCentralTrigger::RunTrigger( AliRunLoader* runLoader, const char *detectors )
213 {
214    // run the trigger
215
216    if( !fConfiguration ) {
217       AliError( "No trigger configuration loaded, skipping trigger" );
218       return kFALSE;
219    }
220
221    TTree *tree = runLoader->TreeCT();
222    if( !tree ) {
223       AliError( "No folder with trigger loaded, skipping trigger" );
224       return kFALSE;
225    }
226
227    TStopwatch stopwatch;
228    stopwatch.Start();
229
230    AliInfo( Form(" Triggering Detectors: %s \n", GetDetectors().Data() ) );
231    AliInfo( Form(" Detectors with digits: %s \n", detectors ) );
232
233    // Process each event
234    for( Int_t iEvent = 0; iEvent < runLoader->GetNumberOfEvents(); iEvent++ ) {
235       runLoader->GetEvent( iEvent );
236       // Get detectors involve
237       TString detStr = GetDetectors();
238       TString detWithDigits = detectors;
239       TObjArray* detArray = runLoader->GetAliRun()->Detectors();
240       // Reset Mask
241       fClassMask = 0;
242       fClusterMask = 0;
243       // Reset configuration object (inputs and classes)
244       fConfiguration->Reset();
245       TObjArray trgdetArray; // use as garbage collector
246       for( Int_t iDet = 0; iDet < detArray->GetEntriesFast(); iDet++ ) {
247          AliModule* det = (AliModule*) detArray->At( iDet );
248          if( !det || !det->IsActive() ) continue;
249          if( IsSelected(det->GetName(), detStr) &&
250              IsSelected(det->GetName(), detWithDigits) ) {
251
252             AliDebug(1,Form("Triggering from digits for %s", det->GetName() ) );
253             AliTriggerDetector* trgdet = det->CreateTriggerDetector();
254             trgdet->AssignInputs(fConfiguration->GetInputs());
255             TStopwatch stopwatchDet;
256             stopwatchDet.Start();
257             trgdet->Trigger();
258             AliDebug(1, Form("Execution time for %s: R:%.2fs C:%.2fs",
259                      det->GetName(), stopwatchDet.RealTime(), stopwatchDet.CpuTime() ) );
260
261             trgdetArray.AddLast( trgdet );
262
263             // Write trigger detector in Event folder in Digits file
264             TString loadername = det->GetName();
265             loadername.Append( "Loader" );
266             AliLoader * loader = runLoader->GetLoader( loadername );
267             if( loader ) {
268                AliDataLoader * dataLoader = loader->GetDigitsDataLoader();
269                if( !dataLoader->IsFileOpen() ) {
270                   if( dataLoader->OpenFile( "UPDATE" ) ) {
271                      AliWarning( Form( "\n\nCan't write trigger for %s\n", det->GetName() ) );
272                   }
273                }
274                dataLoader->Cd();
275                if( gFile && !gFile->IsWritable() ) {
276                   gFile->ReOpen( "UPDATE" );
277                   dataLoader->Cd();
278                }
279                trgdet->Write( "Trigger", TObject::kOverwrite );
280                dataLoader->CloseFile();
281             }
282             else  AliWarning( Form( "Not loader found for %s", det->GetName() ) );
283          }
284       }
285
286       // Check trigger conditions and create the trigger class mask
287       TriggerClasses();
288       // Calculate trigger Input pattern
289       TriggerInputs();
290
291       // Clear trigger detectors
292       trgdetArray.SetOwner();
293       trgdetArray.Delete();
294
295       if( (detStr.CompareTo( "ALL" ) != 0) && !detStr.IsNull() ) {
296          AliError( Form("the following detectors were not found: %s",
297                    detStr.Data()));
298          //JF return kFALSE;
299       }
300
301       // Save trigger mask
302       tree->Fill();
303       AliDebug(1, Form("Event:%d  Class Mask:0x%llX", iEvent,fClassMask ) );
304    } // end event loop
305
306    Reset();
307 //   cout << endl <<  " Print " << endl;
308 //   Print();
309
310    // Write
311    runLoader->WriteTrigger( "OVERWRITE" );
312
313    return kTRUE;
314 }
315 //----------------------------------------------------------------------------
316 void AliCentralTrigger::TriggerInputs()
317 {
318  // Find which inputs are in configuration
319  // and calculate input pattern
320  fL0TriggerInputs=0;
321  fL1TriggerInputs=0;
322  fL2TriggerInputs=0;
323  if(fConfiguration){
324     const TObjArray& inputsArray = fConfiguration->GetInputs();
325     Int_t ninputs = inputsArray.GetEntriesFast();
326     for( Int_t j=0; j<ninputs; j++ ) {
327       AliTriggerInput* input = (AliTriggerInput*)inputsArray.At( j );
328       if(input->GetValue()){
329        UChar_t level=input->GetLevel();
330             if(level == 0) fL0TriggerInputs |= (input->GetMask());
331        else if(level == 1) fL1TriggerInputs |= (input->GetMask());
332        else if(level == 2) fL2TriggerInputs |= (input->GetMask());
333        else{
334          AliError(Form("Unknown input level:%c:",level));
335        }
336       }
337     }
338  }
339 }
340 //_____________________________________________________________________________
341 ULong64_t AliCentralTrigger::TriggerClasses()
342 {
343   // Check trigger conditions and create the trigger class
344   // and trigger cluster masks
345   fClassMask = 0;
346   fClusterMask = 0;
347   if (fConfiguration) {
348     const TObjArray& classesArray = fConfiguration->GetClasses();
349     Int_t nclasses = classesArray.GetEntriesFast();
350     for( Int_t j=0; j<nclasses; j++ ) {
351       AliTriggerClass* trclass = (AliTriggerClass*)classesArray.At( j );
352       trclass->Trigger( fConfiguration->GetInputs(), fConfiguration->GetFunctions() );
353       fClassMask |= trclass->GetValue();
354       if (trclass->GetStatus()) {
355         AliTriggerCluster *trclust = trclass->GetCluster();
356         fClusterMask |= AliDAQ::DetectorPattern(trclust->GetDetectorsInCluster());
357       }
358     }
359   }
360   return fClassMask;
361 }
362 //_____________________________________________________________________________
363 TObjArray* AliCentralTrigger::GetFiredClasses() const
364 {
365    // return only the true conditions
366
367    TObjArray* result = new TObjArray();
368
369    if (fConfiguration) {
370      const TObjArray& classesArray = fConfiguration->GetClasses();
371      Int_t nclasses = classesArray.GetEntriesFast();
372      for( Int_t j=0; j<nclasses; j++ ) {
373        AliTriggerClass* trclass = (AliTriggerClass*)classesArray.At( j );
374        if( trclass->GetStatus() ) result->AddLast( trclass );
375      }
376    }
377
378    return result;
379 }
380
381 //_____________________________________________________________________________
382 void AliCentralTrigger::Print( const Option_t*  ) const
383 {
384    // Print
385    cout << "Central Trigger: " << endl;
386    cout << "  Trigger Class Mask: 0x" << hex << fClassMask << dec << endl;
387    if (fConfiguration) fConfiguration->Print();
388    cout << endl;
389 }
390
391
392 //////////////////////////////////////////////////////////////////////////////
393 // Helper method
394
395 //_____________________________________________________________________________
396 Bool_t AliCentralTrigger::IsSelected( TString detName, TString& detectors ) const
397 {
398    // check whether detName is contained in detectors
399    // if yes, it is removed from detectors
400
401    // check if all detectors are selected
402    if( (detectors.CompareTo("ALL") == 0 ) ||
403         detectors.BeginsWith("ALL ") ||
404         detectors.EndsWith(" ALL") ||
405         detectors.Contains(" ALL ") ) {
406       detectors = "ALL";
407       return kTRUE;
408    }
409
410    // search for the given detector
411    Bool_t result = kFALSE;
412    if( (detectors.CompareTo( detName ) == 0) ||
413         detectors.BeginsWith( detName+" " ) ||
414         detectors.EndsWith( " "+detName ) ||
415         detectors.Contains( " "+detName+" " ) ) {
416       detectors.ReplaceAll( detName, "" );
417       result = kTRUE;
418    }
419
420    // clean up the detectors string
421    while( detectors.Contains("  ") )  detectors.ReplaceAll( "  ", " " );
422    while( detectors.BeginsWith(" ") ) detectors.Remove( 0, 1 );
423    while( detectors.EndsWith(" ") )   detectors.Remove( detectors.Length()-1, 1 );
424
425    return result;
426 }
427
428 //_____________________________________________________________________________
429 Bool_t AliCentralTrigger::CheckTriggeredDetectors() const
430 {
431   // Check the trigger mask, finds which trigger classes
432   // have been fired, load the corresponding trigger clusters and
433   // finally makes a list of the detectors that have been readout
434   // for each particular event. This list is then compared to the
435   // one stored in fClusterMask. Return value:
436   // true = two lists are equal
437   // false = two lists are not equal meaning wrong trigger config
438   // is loaded.
439
440   if (!fConfiguration) {
441     AliError("The trigger confiration has not yet been loaded! Cross-check is not possible!");
442     return kFALSE;
443   }
444   else {
445
446     // Make a cross-check so that to exclude wrong trigger configuration used
447     // Loop over the trigger classes
448     UInt_t clusterMask = 0;
449     const TObjArray& classesArray = fConfiguration->GetClasses();
450     Int_t nclasses = classesArray.GetEntriesFast();
451     for( Int_t j=0; j<nclasses; j++ ) {
452       AliTriggerClass* trclass = (AliTriggerClass*)classesArray.At( j );
453       if (trclass->GetMask() & fClassMask) { // class was fired
454         AliTriggerCluster *trclust = trclass->GetCluster();
455         clusterMask |= AliDAQ::DetectorPattern(trclust->GetDetectorsInCluster());
456       }
457     }
458     // Compare the stored cluster mask with the one
459     // that we get from trigger classes
460     if (clusterMask != fClusterMask) {
461       if ((clusterMask & fClusterMask) == clusterMask) {
462         AliInfo(Form("Cluster mask from trigger classes (%x) and from data (%x) differ. Concurrent DAQ run(s) could be the reason.",
463                      (UInt_t)clusterMask,(UInt_t)fClusterMask));
464         return kTRUE;
465       }
466       else {
467         AliError(Form("Wrong cluster mask from trigger classes (%x), expecting (%x)! Loaded trigger configuration is possibly wrong!",
468                       (UInt_t)clusterMask,(UInt_t)fClusterMask));
469         return kFALSE;
470       }
471     }
472   }
473
474   return kTRUE;
475 }