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