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