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