Dropping references to AliMUONLocalTrigger which are depricated. This is a temporary...
[u/mrichter/AliRoot.git] / HLT / MUON / src / AliRoot / TriggerSource.cxx
1 ////////////////////////////////////////////////////////////////////////////////
2 //
3 // Author: Artur Szostak
4 // Email:  artur@alice.phy.uct.ac.za | artursz@iafrica.com
5 //
6 ////////////////////////////////////////////////////////////////////////////////
7
8 /* AliHLTMUONTriggerSource is used to extract L0 trigger information for
9    the muon spectrometer from a simulated event stored in .root files by AliRoot.
10    It is used by the AliHLTMUONMicrodHLT class as a input data set for the
11    dHLT algorithm.
12  */
13  
14 #include "AliRoot/TriggerSource.hpp"
15 #include "AliRoot/Base.hpp"
16 #include "Tracking/Calculations.hpp"
17 #include "AliRun.h"
18 #include "AliRunLoader.h"
19 #include "AliModule.h"
20 #include "AliMUON.h"
21 #include "AliMUONConstants.h"
22 #include "AliMUONHit.h"
23 //#include "AliMUONLocalTrigger.h"
24 #include "AliMUONTriggerCircuit.h"
25 #include "AliMUONDataInterface.h"
26 #include "TDatabasePDG.h"
27 #ifndef __alpha
28 #include <math.h>
29 #else
30 #include <float.h>
31 #endif
32
33 ClassImp(AliHLTMUONTriggerSource)
34 ClassImp(AliHLTMUONTriggerSource::AliEventData)
35
36
37 AliHLTMUONTriggerSource::AliHLTMUONTriggerSource()
38         : TObject(),
39           fAreaToUse(kFromWholePlane), fDataToUse(kFromLocalTriggers),
40           fMaxBlockSize(0xFFFFFFFF), fUseLookupTable(kTRUE),
41           fFilename(""), fFoldername(""),
42           fEventIndex(-1), fCurrentEvent(NULL),
43           fBlockIndex(-1), fCurrentBlock(NULL),
44           fTriggerIndex(-1), fCurrentTrigger(NULL),
45           fEventList(AliHLTMUONTriggerSource::AliEventData::Class()),
46           fHadToLoadgAlice(kFALSE)
47 {
48 // Default constructor.
49
50         fAreaToUse = kFromWholePlane;
51         fDataToUse = kFromLocalTriggers;
52         fMaxBlockSize = 0xFFFFFFFF;
53         fUseLookupTable = kTRUE;
54         fFilename = "";
55         fFoldername = "";
56         ResetAllPointers();
57         fHadToLoadgAlice = kFALSE;
58 }
59
60
61 AliHLTMUONTriggerSource::AliHLTMUONTriggerSource(AliMUONDataInterface* data)
62         : TObject(),
63           fAreaToUse(kFromWholePlane), fDataToUse(kFromLocalTriggers),
64           fMaxBlockSize(0xFFFFFFFF), fUseLookupTable(kTRUE),
65           fFilename(""), fFoldername(""),
66           fEventIndex(-1), fCurrentEvent(NULL),
67           fBlockIndex(-1), fCurrentBlock(NULL),
68           fTriggerIndex(-1), fCurrentTrigger(NULL),
69           fEventList(AliHLTMUONTriggerSource::AliEventData::Class()),
70           fHadToLoadgAlice(kFALSE)
71 {
72 // Creates a new trigger source object by filling data from the data interface.
73
74         fAreaToUse = kFromWholePlane;
75         fDataToUse = kFromLocalTriggers;
76         fMaxBlockSize = 0xFFFFFFFF;
77         fUseLookupTable = kTRUE;
78         fFilename = "";
79         fFoldername = "";
80         ResetAllPointers();
81         fHadToLoadgAlice = kFALSE;
82         FillFrom(data);
83 }
84
85
86 AliHLTMUONTriggerSource::~AliHLTMUONTriggerSource()
87 {
88         fEventList.Delete();
89 }
90
91
92 void AliHLTMUONTriggerSource::FillFrom(AliMUONDataInterface* data)
93 {
94 // Fills the internal data structures from the specified data interface
95 // for all the events found in AliMUONDataInterface.
96            
97         DebugMsg(1, "FillFrom(AliMUONDataInterface*)");
98         
99         if (FileAndFolderOk(data))
100         {
101                 AliMUON* module = NULL;
102                 if ( ! FetchAliMUON(module) ) return;
103                 
104                 for (Int_t i = 0; i < data->NumberOfEvents(); i++)
105                 {
106                         AddEventFrom(data, module, i);
107                 }
108                 
109                 FinishedWithAliMUON();
110         }
111 }
112
113
114 void AliHLTMUONTriggerSource::FillFrom(AliMUONDataInterface* data, Int_t event)
115 {
116 // Fills the internal data structures from the specified data interface
117 // for the given event.
118
119         DebugMsg(1, "FillFrom(AliMUONDataInterface*, Int_t)");
120         
121         if (FileAndFolderOk(data))
122         {
123                 AliMUON* module = NULL;
124                 if ( ! FetchAliMUON(module) ) return;
125                 AddEventFrom(data, module, event);
126                 FinishedWithAliMUON();
127         }
128 }
129
130
131 void AliHLTMUONTriggerSource::FillFrom(
132                 AliMUONDataInterface* data,
133                 Int_t event, Int_t trigger, Bool_t newblock
134         )
135 {
136 // Fills the internal data structures from the specified data interface
137 // for the given event and trigger number.
138 // If 'newblock' is set to true then the new trigger record is added to 
139 // a new block. Otherwise the point is added to the current block.
140 // Note: This method ignores the fAreaToUse and fMaxBlockSize flags.
141 // This is very usefull for custom trigger source filling.
142 // For the case of adding data from AliMUONHit objects the 'trigger'
143 // parameter becomes the track number in TreeH and not the index of the
144 // AliMUONLocalTrigger object.
145
146         DebugMsg(1, "FillFrom(AliMUONDataInterface*, Int_t, Int_t, Bool_t)");
147         
148         if (FileAndFolderOk(data))
149         {
150                 data->GetEvent(event);
151                 AliMUON* module = NULL;
152                 if ( ! FetchAliMUON(module) ) return;
153
154                 // Check if the current event corresponds to the event number we are
155                 // attempting to add to. If they do not or no event is selected then
156                 // try find the event or create a new one.
157                 if ( fCurrentEvent == NULL )
158                 {
159                         Bool_t found = GetEvent(event);
160                         if ( ! found) AddEvent(event);
161                 }
162                 else
163                 {
164                         if (fCurrentEvent->EventNumber() != event)
165                         {
166                                 Bool_t found = GetEvent(event);
167                                 if ( ! found) AddEvent(event);
168                         }
169                 }
170                 
171                 if ( fCurrentBlock != NULL )
172                 {
173                         Assert( fCurrentEvent != NULL );
174                         // If the newblock flag is set then force a new block.
175                         if (newblock) AddBlock();
176                 }
177                 else
178                         AddBlock();  // No block selected so we need to create a new block.
179
180                 AddTriggerFrom(data, module, trigger);
181                 FinishedWithAliMUON();
182         }
183 }
184
185
186 void AliHLTMUONTriggerSource::Clear(Option_t* /*option*/)
187 {
188 // Clears all the internal arrays.
189
190         fFilename = "";
191         fFoldername = "";
192         ResetAllPointers();
193         fEventList.Clear("C");
194 }
195
196
197 Bool_t AliHLTMUONTriggerSource::GetEvent(Int_t eventnumber) const
198 {
199 // Fetches the specified event number stored in this AliHLTMUONTriggerSource.
200 // Sets the current block and trigger to the first block and trigger record in
201 // the event. If there are no blocks or trigger records then these pointers are
202 // set to NULL. kTRUE is returned if the event was found, kFALSE otherwise.
203
204         DebugMsg(1, "AliHLTMUONTriggerSource::GetEvent(" << eventnumber << ")" );
205         
206         // Try find the corresponding event in the list of events.
207         for (Int_t i = 0; i < fEventList.GetEntriesFast(); i++)
208         {
209                 AliEventData* current = (AliEventData*) fEventList[i];
210                 if (current->EventNumber() == eventnumber)
211                 {
212                         fEventIndex = i;
213                         fCurrentEvent = current;
214                         GetFirstBlock();
215                         DebugMsg(2, "\tfEventIndex = " << fEventIndex << " , fBlockIndex = " << fBlockIndex
216                                 << " , fTriggerIndex = " << fTriggerIndex
217                         );
218                         return kTRUE;
219                 }
220         }
221         return kFALSE;
222 }
223
224
225 Bool_t AliHLTMUONTriggerSource::GetFirstEvent() const
226 {
227 // Fetches the first event stored in this AliHLTMUONTriggerSource.
228 // Sets the current block and trigger record to the first block and trigger
229 // in the event. If there are no blocks or trigger records then these pointers
230 // are set to NULL. kTRUE is returned if the event was found, kFALSE otherwise.
231
232         DebugMsg(1, "AliHLTMUONTriggerSource::GetFirstEvent()");
233         if (fEventList.GetEntriesFast() > 0)
234         {
235                 fEventIndex = 0;
236                 fCurrentEvent = (AliEventData*) fEventList[0];
237                 GetFirstBlock();
238                 DebugMsg(2, "\tfEventIndex = " << fEventIndex << " , fBlockIndex = " << fBlockIndex
239                         << " , fTriggerIndex = " << fTriggerIndex
240                 );
241                 return kTRUE;
242         }
243         else
244         {
245                 DebugMsg(2, "\tfEventIndex = " << fEventIndex << " , fBlockIndex = " << fBlockIndex
246                         << " , fTriggerIndex = " << fTriggerIndex
247                 );
248                 return kFALSE;
249         }
250 }
251
252
253 Bool_t AliHLTMUONTriggerSource::MoreEvents() const
254 {
255 // Returns kTRUE if there are more events to iterate over.
256
257         return 0 <= fEventIndex && fEventIndex < fEventList.GetEntriesFast();
258 }
259
260
261 Bool_t AliHLTMUONTriggerSource::GetNextEvent() const
262 {
263 // Fetches the next event stored following the currently selected one.
264 // kTRUE is returned if the event was found, kFALSE otherwise.
265 // The internal pointers are reset if we reached the last event.
266            
267         DebugMsg(1, "AliHLTMUONTriggerSource::GetNextEvent()");
268         if (fEventIndex < fEventList.GetEntriesFast() - 1)
269         {
270                 fCurrentEvent = (AliEventData*) fEventList[ ++fEventIndex ];
271                 GetFirstBlock();
272                 DebugMsg(2, "\tfEventIndex = " << fEventIndex << " , fBlockIndex = " << fBlockIndex
273                         << " , fTriggerIndex = " << fTriggerIndex
274                 );
275                 return kTRUE;
276         }
277         else
278         {
279                 ResetAllPointers();
280                 return kFALSE;
281         }
282 }
283
284
285 Int_t AliHLTMUONTriggerSource::CurrentEvent() const
286 {
287 // Returns the corresponding AliRoot event number for the current event.
288 // -1 is returned if no event is selected.
289            
290         if (fCurrentEvent != NULL)
291                 return fCurrentEvent->EventNumber();
292         else
293                 return -1;
294 }
295
296
297 Int_t AliHLTMUONTriggerSource::NumberOfBlocks() const
298 {
299 // Returns the number of trigger record blocks in the current event.
300 // -1 is returned if no event is selected.
301            
302         DebugMsg(1, "AliHLTMUONTriggerSource::NumberOfBlocks()");
303         if (fCurrentEvent == NULL)
304         {
305                 Error("NumberOfBlocks", "No event selected.");
306                 return -1;
307         }
308         else
309                 return fCurrentEvent->Blocks().GetEntriesFast();
310 }
311
312
313 Bool_t AliHLTMUONTriggerSource::GetBlock(Int_t index) const
314 {
315 // Fetches the index'th block in the current event.
316 // Sets the current trigger record to the first trigger in the block.
317 // If there are no trigger records then this pointer is set to NULL.
318 // kTRUE is returned if the block was found, kFALSE otherwise.
319
320         DebugMsg(1, "AliHLTMUONTriggerSource::GetBlock(" << index << ")");
321         
322         // Note NumberOfBlocks() also checks if the event was selected.
323         Int_t numberofblocks = NumberOfBlocks();
324         if (numberofblocks < 0) return kFALSE;
325
326         if ( 0 <= index && index < numberofblocks )
327         {
328                 fBlockIndex = index;
329                 fCurrentBlock = (TClonesArray*) fCurrentEvent->Blocks()[index];
330                 GetFirstTrigger();
331                 DebugMsg(2, "\tfEventIndex = " << fEventIndex << " , fBlockIndex = " << fBlockIndex
332                         << " , fTriggerIndex = " << fTriggerIndex
333                 );
334                 return kTRUE;
335         }
336         else
337         {
338                 // The index is out of bounds so inform the user.
339                 if (numberofblocks > 0)
340                         Error(  "GetBlock",
341                                 "The block index (%d) is out of bounds. Valid range is [0, %d]",
342                                 index, numberofblocks - 1
343                         );
344                 else
345                         Error(  "GetBlock",
346                                 "The block index (%d) is out of bounds. No blocks found.",
347                                 index
348                         );
349                 return kFALSE;
350         }
351 }
352
353
354 Bool_t AliHLTMUONTriggerSource::GetFirstBlock() const
355 {
356 // Fetches the first block in the current event.
357 // Sets the current trigger record to the first trigger in the block.
358 // If there are no trigger records then this pointer is set to NULL.
359 // kTRUE is returned if the block was found, kFALSE otherwise.
360            
361         DebugMsg(1, "AliHLTMUONTriggerSource::GetFirstBlock()");
362         // Note: NumberOfBlocks() also checks if fCurrentEvent != NULL.
363         if (NumberOfBlocks() > 0)
364         {
365                 fBlockIndex = 0;
366                 fCurrentBlock = (TClonesArray*) fCurrentEvent->Blocks()[fBlockIndex];
367                 GetFirstTrigger();
368                 DebugMsg(2, "\tfEventIndex = " << fEventIndex << " , fBlockIndex = " << fBlockIndex
369                         << " , fTriggerIndex = " << fTriggerIndex
370                 );
371                 return kTRUE;
372         }
373         else
374                 return kFALSE;
375 }
376
377
378 Bool_t AliHLTMUONTriggerSource::MoreBlocks() const
379 {
380 // Returns kTRUE if there are more blocks to be traversed.
381
382         return 0 <= fBlockIndex && fBlockIndex < NumberOfBlocks();
383 }
384
385
386 Bool_t AliHLTMUONTriggerSource::GetNextBlock() const
387 {
388 // Fetches the next block in the current event.
389 // kTRUE is returned if the block was found, kFALSE otherwise.
390            
391         DebugMsg(1, "AliHLTMUONTriggerSource::GetNextBlock()");
392
393         // Note: NumberOfBlocks() checks if fCurrentEvent != NULL. If it is then it returns -1
394         // and since fBlockIndex is always >= -1 the if statement must go to the else part.
395         if (fBlockIndex < NumberOfBlocks() - 1)
396         {
397                 fCurrentBlock = (TClonesArray*) fCurrentEvent->Blocks()[ ++fBlockIndex ];
398                 GetFirstTrigger();
399                 DebugMsg(2, "\tfEventIndex = " << fEventIndex << " , fBlockIndex = " << fBlockIndex
400                         << " , fTriggerIndex = " << fTriggerIndex
401                 );
402                 return kTRUE;
403         }
404         else
405         {
406                 ResetBlockPointers();
407                 return kFALSE;
408         }
409 }
410
411
412 Int_t AliHLTMUONTriggerSource::NumberOfTriggers() const
413 {
414 // Returns the number of trigger records in the current block.
415 // -1 is returned if no block is selected.
416
417         DebugMsg(1, "AliHLTMUONTriggerSource::NumberOfTriggers()");
418         if (fCurrentBlock == NULL)
419         {
420                 Error("NumberOfTriggers", "No block selected.");
421                 return -1;
422         }
423         else
424                 return fCurrentBlock->GetEntriesFast();
425 }
426
427
428 const AliHLTMUONTriggerRecord* AliHLTMUONTriggerSource::GetTrigger(Int_t triggernumber) const
429 {
430 // Fetches the trigger record with the specified trigger number from
431 // the current block.
432 // NULL is returned if the record was not found.
433
434         DebugMsg(1, "AliHLTMUONTriggerSource::GetTrigger(" << triggernumber << ")");
435
436         if (fCurrentBlock == NULL)
437         {
438                 Error("GetTrigger", "No block selected.");
439                 return NULL;
440         }
441         
442         // Try find the corresponding trigger record in the list of events.
443         for (Int_t i = 0; i < fCurrentBlock->GetEntriesFast(); i++)
444         {
445                 AliHLTMUONTriggerRecord* current = (AliHLTMUONTriggerRecord*) fCurrentBlock->At(i);
446                 if (current->TriggerNumber() == triggernumber)
447                 {
448                         fTriggerIndex = i;
449                         fCurrentTrigger = current;
450                         DebugMsg(2, "\tfEventIndex = " << fEventIndex << " , fBlockIndex = " << fBlockIndex
451                                 << " , fTriggerIndex = " << fTriggerIndex
452                         );
453                         return current;
454                 }
455         }
456         return NULL;
457 }
458
459
460 const AliHLTMUONTriggerRecord* AliHLTMUONTriggerSource::GetFirstTrigger() const
461 {
462 // Fetches the first trigger record in the current block.
463 // NULL is returned if the record was not found.
464
465         DebugMsg(1, "AliHLTMUONTriggerSource::GetFirstTrigger()");
466         // Note: NumberOfTriggers() also checks if fCurrentBlock != NULL.
467         if (NumberOfTriggers() > 0)
468         {
469                 fTriggerIndex = 0;
470                 fCurrentTrigger = (AliHLTMUONTriggerRecord*) fCurrentBlock->At(0);
471                 DebugMsg(2, "\tfEventIndex = " << fEventIndex << " , fBlockIndex = " << fBlockIndex
472                         << " , fTriggerIndex = " << fTriggerIndex
473                 );
474                 return fCurrentTrigger;
475         }
476         else
477                 return NULL;
478 }
479
480
481 Bool_t AliHLTMUONTriggerSource::MoreTriggers() const
482 {
483 // Returns kTRUE if there are more triggers to iterate over.
484
485         return 0 <= fTriggerIndex && fTriggerIndex < NumberOfTriggers();
486 }
487
488
489 const AliHLTMUONTriggerRecord* AliHLTMUONTriggerSource::GetNextTrigger() const
490 {
491 // Fetches the next trigger record in the current block.
492 // NULL is returned if the record was not found.
493
494         DebugMsg(1, "AliHLTMUONTriggerSource::GetNextTrigger()");
495         
496         // Note: NumberOfTriggers() checks if fCurrentBlock != NULL. If it is then it returns -1
497         // and since fTriggerIndex is always >= -1 the if statement must go to the else part.
498         if (fTriggerIndex < NumberOfTriggers() - 1)
499         {
500                 fCurrentTrigger = (AliHLTMUONTriggerRecord*) fCurrentBlock->At( ++fTriggerIndex );
501                 DebugMsg(2, "\tfEventIndex = " << fEventIndex << " , fBlockIndex = " << fBlockIndex
502                         << " , fTriggerIndex = " << fTriggerIndex
503                 );
504                 return fCurrentTrigger;
505         }
506         else
507         {
508                 ResetTriggerPointers();
509                 return NULL;
510         }
511 }
512
513
514 Int_t AliHLTMUONTriggerSource::CurrentTrigger() const
515 {
516 // Returns the trigger record number for the currently selected trigger record.
517 // This number corresponds to the index'th AliMUONLocalTrigger object for the
518 // current event.
519 // -1 is returned if no trigger record is selected.
520
521         if (fCurrentTrigger != NULL)
522         {
523                 return fCurrentTrigger->TriggerNumber();
524         }
525         else
526         {
527                 Error("CurrentTrigger", "No trigger record selected.");
528                 return -1;
529         }
530 }
531
532
533 void AliHLTMUONTriggerSource::AddEvent(Int_t eventnumber)
534 {
535 // Adds a new AliEventData block to the fEventList and updates the fCurrentEvent,
536 // fCurrentBlock and fCurrentTrigger pointers.
537
538         DebugMsg(1, "AliHLTMUONTriggerSource::AddEvent(" << eventnumber << ")");
539         Assert( eventnumber >= 0 );
540
541         // Assume the eventnumber does not already exist in the event list.
542         fEventIndex = fEventList.GetEntriesFast();
543         new ( fEventList[fEventIndex] ) AliEventData(eventnumber);
544         fCurrentEvent = (AliEventData*) fEventList[fEventIndex];
545         
546         // Remember to reset the other pointers because the new event is empty.
547         ResetBlockPointers();
548         
549         DebugMsg(2, "\tfEventIndex = " << fEventIndex << " , fBlockIndex = " << fBlockIndex
550                 << " , fTriggerIndex = " << fTriggerIndex
551         );
552 }
553
554
555 void AliHLTMUONTriggerSource::AddBlock()
556 {
557 // Adds a new block to the current event and updates fCurrentBlock and fCurrentTrigger.
558
559         DebugMsg(1, "AliHLTMUONTriggerSource::AddBlock()");
560         
561         if (fCurrentEvent == NULL)
562         {
563                 Error("AddBlock", "No event selected.");
564                 return;
565         }
566         
567         fBlockIndex = fCurrentEvent->Blocks().GetEntriesFast();
568         new ( fCurrentEvent->Blocks()[fBlockIndex] ) TClonesArray(AliHLTMUONTriggerRecord::Class());
569         fCurrentBlock = (TClonesArray*) fCurrentEvent->Blocks()[fBlockIndex];
570         
571         // Remember to reset the trigger pointer because the new block is empty.
572         ResetTriggerPointers();
573
574         DebugMsg(2, "\tfEventIndex = " << fEventIndex << " , fBlockIndex = " << fBlockIndex
575                 << " , fTriggerIndex = " << fTriggerIndex
576         );
577 }
578
579
580 void AliHLTMUONTriggerSource::AddTrigger(const AliHLTMUONTriggerRecord& data)
581 {
582 // Adds a new trigger record to the current event and block.
583 // The fCurrentTrigger is updated appropriately.
584
585         DebugMsg(1, "AliHLTMUONTriggerSource::AddTrigger(" << (void*)&data << ")");
586
587         if (fCurrentBlock == NULL)
588         {
589                 Error("AddTrigger", "No block selected.");
590                 return;
591         }
592         
593         fTriggerIndex = fCurrentBlock->GetEntriesFast();
594         new ( (*fCurrentBlock)[fTriggerIndex] ) AliHLTMUONTriggerRecord(data);
595         fCurrentTrigger = (AliHLTMUONTriggerRecord*) (*fCurrentBlock)[fTriggerIndex];
596         
597         DebugMsg(2, "\tfEventIndex = " << fEventIndex << " , fBlockIndex = " << fBlockIndex
598                 << " , fTriggerIndex = " << fTriggerIndex
599         );
600 }
601
602
603 Bool_t AliHLTMUONTriggerSource::FileAndFolderOk(AliMUONDataInterface* data)
604 {
605 // Checks if the file and folder names correspond to this AliHLTMUONTriggerSource's 
606 // file and folder names. kTRUE is returned if they do.
607 // If the file and folder names are empty then they are assigned the names
608 // as found in the data interface and kTRUE is returned.
609
610         if (fFilename == "")
611         {
612                 // Nothing filled yet so set the file and folder names.
613                 fFilename = data->CurrentFile();
614                 fFoldername = data->CurrentFolder();
615                 return kTRUE;
616         }
617
618         if ( fFilename != data->CurrentFile() )
619         {
620                 Error(  "FileAndFolderOk",
621                         "The Trigger source already contains data from file '%s', cannot add data from file '%s'",
622                         fFilename.Data(), data->CurrentFile().Data()
623                 );
624                 return kFALSE;
625         }
626         
627         if ( fFoldername != data->CurrentFolder() )
628         {
629                 Error(  "FileAndFolderOk",
630                         "The Trigger source already contains data from folder '%s', cannot add data from folder '%s'",
631                         fFoldername.Data(), data->CurrentFolder().Data()
632                 );
633                 return kFALSE;
634         }
635         
636         return kTRUE;
637 }
638
639
640 void AliHLTMUONTriggerSource::AddEventFrom(AliMUONDataInterface* data, AliMUON* module, Int_t event)
641 {
642 // Adds the whole event from the data interface to the internal data structures.
643 // It is assumed that FileAndFolderOk(data) returns true just before calling
644 // this method.
645
646         if ( data->GetEvent(event) )
647         {
648                 AddEvent(event);
649
650                 AddBlock();
651                 UInt_t currentblocksize = 0;
652                 AliHLTMUONTriggerRecord trigdata;
653
654                 switch (fDataToUse)
655                 {
656                 case kFromHits:
657                         for (Int_t track = 0; track < data->NumberOfTracks(); track++)
658                         {
659                                 if ( ! FillTriggerFromHits(data, track, trigdata) )
660                                         continue;  // Continue if unable to find hits.
661
662                                 if (InFillRegion(trigdata))
663                                 {
664                                         AddTrigger(trigdata);
665
666                                         // Create a new block if we reached the maximum block size.
667                                         if ( ++currentblocksize == fMaxBlockSize )
668                                         {
669                                                 AddBlock();
670                                                 currentblocksize = 0;
671                                         }
672                                 }
673                         }
674                         break;
675
676                 case kFromLocalTriggers:
677                         Assert( module != NULL );
678                         DebugMsg(4, "THIS OPTION IS DEPRICATED!!!");
679 /* THIS CODE IS DEPRICATED (to be removed)
680                         for (Int_t i = 0; i < data->NumberOfLocalTriggers(); i++)
681                         {
682                                 DebugMsg(4, "for loop: i = " << i);
683                                 AliMUONLocalTrigger* lt = data->LocalTrigger(i);
684                                 FillTriggerFromLocalTrigger(lt, module, trigdata);
685                                 trigdata.TriggerNumber(i);
686
687                                 if (InFillRegion(trigdata))
688                                 {
689                                         AddTrigger(trigdata);
690
691                                         // Create a new block if we reached the maximum block size.
692                                         if ( ++currentblocksize == fMaxBlockSize )
693                                         {
694                                                 AddBlock();
695                                                 currentblocksize = 0;
696                                         }
697                                 }
698                         }
699 */
700                         break;
701
702                 default:
703                         Error("AddChamberFrom", "fDataToUse is not set to a valid value.");
704                 }
705         }  // Loop on events.
706 }
707
708
709 void AliHLTMUONTriggerSource::AddTriggerFrom(AliMUONDataInterface* data, AliMUON* module, Int_t trigger)
710 {
711 // Adds the specified trigger record from the given data interface.
712 // The data interface should be initialised correctly, that is the event
713 // should already be selected before calling this method.
714
715         DebugMsg(1, "Entering AddTriggerFrom");
716
717         AliHLTMUONTriggerRecord trigdata;
718
719         switch (fDataToUse)
720         {
721         case kFromHits:
722                 {
723                 // Note: in this case we treat the trigger parameter as a track number.
724                 if ( ! FillTriggerFromHits(data, trigger, trigdata) )
725                         return;  // Continue if unable to find hits.
726                 }
727                 break;
728
729         case kFromLocalTriggers:
730                 {
731 /* THIS CODE IS DEPRICATED (to be removed)
732                 Assert( module != NULL );
733                 AliMUONLocalTrigger* lt = data->LocalTrigger(trigger);
734                 FillTriggerFromLocalTrigger(lt, module, trigdata);
735                 trigdata.TriggerNumber(trigger);
736 */
737                 }
738                 break;
739
740         default:
741                 Error("AddTriggerFrom", "fDataToUse is not set to a valid value.");
742                 return;
743         }
744         
745         AddTrigger(trigdata);
746         
747         DebugMsg(1, "Leaving AddTriggerFrom");
748 }
749
750
751 Bool_t AliHLTMUONTriggerSource::InFillRegion(const AliHLTMUONTriggerRecord& data) const
752 {
753 // Checks to see if the specified trigger record is in the chamber region
754 // we want to fill from.
755 // kTRUE is returned if (x, y) is in the region, and kFALSE otherwise.
756
757         switch (fAreaToUse)
758         {
759         case kFromWholePlane:     return kTRUE;
760         case kFromLeftHalfPlane:  return data.Station1Point().X() <= 0;
761         case kFromRightHalfPlane: return data.Station1Point().X() > 0;
762
763         default:
764                 Error("InFillRegion", "fAreaToUse is not set to a valid value.");
765                 return kFALSE;
766         }
767 }
768
769
770 /* THIS CODE IS DEPRICATED (to be removed)
771
772 void AliHLTMUONTriggerSource::FillTriggerFromLocalTrigger(
773                 AliMUONLocalTrigger* trigger, AliMUON* module, AliHLTMUONTriggerRecord& record
774         )
775 {
776 // Fills the trigger data from the AliMUONLocalTrigger object.
777 // if the fUseLookupTable is set to true then we use the L0 lookup table to
778 // fill the Pt value otherwise we use the PtCal method in AliMUONTriggerCircuit.
779 // Note the fTriggerNumber parameter is not filled in to 'record'.
780
781         DebugMsg(2, "Creating TriggerRecord from AliMUONLocalTrigger object: " << (void*)trigger );
782         AliMUONTriggerCircuit& circuit = module->TriggerCircuit(trigger->LoCircuit());
783
784         // Get the sign of the particle the sign of the muon.
785         if (trigger->LoLpt() == 1 || trigger->LoHpt() == 1 || trigger->LoApt() == 1)
786         {
787                 record.ParticleSign(-1);
788         }
789         else
790         if (trigger->LoLpt() == 2 || trigger->LoHpt() == 2 || trigger->LoApt() == 2)
791         {
792                 record.ParticleSign(+1);
793         }
794         else
795         {
796                 record.ParticleSign(0);
797         }
798         DebugMsg(2, "Particle sign = " << record.ParticleSign() );
799
800         // Compute the transverse momentum.
801         if (fUseLookupTable)
802         {
803                 // TODO: implement use of the L0 lookup table.
804                 Error("FillTriggerFromLocalTrigger", "Use of L0 lookup table is not yet implemented!");
805         }
806         else
807         {
808                 Float_t pt = circuit.PtCal( trigger->LoStripX(), trigger->LoDev(), trigger->LoStripY() );
809                 record.Pt(pt);
810         }
811         DebugMsg(2, "Pt = " << record.Pt() );
812
813         // Build the impact points.
814         record.Station1Point().X() = circuit.GetX11Pos(trigger->LoStripY());
815         record.Station1Point().Y() = circuit.GetY11Pos(trigger->LoStripX());
816         record.Station2Point().Y() = circuit.GetY21Pos(trigger->LoStripX() + trigger->LoDev() + 1);  // Why + 1?
817         record.Station2Point().X() = AliMUONConstants::DefaultChamberZ(12) * record.Station1Point().X() / AliMUONConstants::DefaultChamberZ(10);
818         DebugMsg(2, "fStation1x = " << record.Station1Point().X());
819         DebugMsg(2, "fStation1y = " << record.Station1Point().Y());
820         DebugMsg(2, "fStation2x = " << record.Station2Point().X());
821         DebugMsg(2, "fStation2y = " << record.Station2Point().Y());
822 }
823 */
824
825
826 Bool_t AliHLTMUONTriggerSource::FillTriggerFromHits(
827                 AliMUONDataInterface* data, Int_t track, AliHLTMUONTriggerRecord& record
828         )
829 {
830 // Fills the TriggerRecord structure from AliMUONHit objects.
831 // The hits on the last 4 chambers are used (i.e. chambers 11 to 14).
832 // kTRUE is returned if the structure was filled successfully.
833
834         DebugMsg(2, "Creating TriggerRecord from hits on track: " << track );
835         
836         Float_t x1, y1, z1, x2, y2, z2, x3, y3, z3, x4, y4, z4;
837 #ifndef __alpha
838 #ifndef __sun
839         x1 = y1 = z1 = x2 = y2 = z2 = x3 = y3 = z3 = x4 = y4 = z4 = nanf("");
840 #else
841         x1 = y1 = z1 = x2 = y2 = z2 = x3 = y3 = z3 = x4 = y4 = z4 = 0;
842 #endif
843 #else
844         x1 = y1 = z1 = x2 = y2 = z2 = x3 = y3 = z3 = x4 = y4 = z4 = FLT_QNAN;
845 #endif
846         // Find the hit that corresponds to chambers. 11 to 14. We can ignore any
847         // hits above the first 14. If there are that many it means the particle
848         // is cycling in the detector.
849         for (Int_t i = 0; i < data->NumberOfHits(track) && i < 14; i++)
850         {
851                 AliMUONHit* h = data->Hit(track, i);
852
853                 // Note AliMUONHit::Chamber() returns a value in the range 1..14
854                 // It is also important to have positive Z coordinates and under the
855                 // new version of Aliroot we use GEANT coordinates which return 
856                 // negatives. So we use the fabs routine.
857                 switch ( h->Chamber() )
858                 {
859                 case 11: x1 = h->X(); y1 = h->Y(); z1 = (Float_t)fabs(h->Z()); break;
860                 case 12: x2 = h->X(); y2 = h->Y(); z2 = (Float_t)fabs(h->Z()); break;
861                 case 13: x3 = h->X(); y3 = h->Y(); z3 = (Float_t)fabs(h->Z()); break;
862                 case 14: x4 = h->X(); y4 = h->Y(); z4 = (Float_t)fabs(h->Z()); break;
863                 }
864         }
865         DebugMsg(4, "Found: x1 = " << x1 << ", y1 = " << y1 << ", z1 = " << z1);
866         DebugMsg(4, "Found: x2 = " << x2 << ", y2 = " << y2 << ", z2 = " << z2);
867         DebugMsg(4, "Found: x3 = " << x3 << ", y3 = " << y3 << ", z3 = " << z3);
868         DebugMsg(4, "Found: x4 = " << x4 << ", y4 = " << y4 << ", z4 = " << z4);
869
870         // Get a coordinate for station 1, perferably from chamber 11 otherwise
871         // use hits from chamber 12.
872         if ( ! TMath::IsNaN(x1))
873         {
874                 record.Station1Point().X() = x1;
875                 record.Station1Point().Y() = y1;
876                 DebugMsg(3, "Using value from chamber 11: x1 = " << x1 << ", y1 = " << y1 << ", z1 = " << z1 );
877         }
878         else if ( ! TMath::IsNaN(x2))
879         {
880                 record.Station1Point().X() = x2;
881                 record.Station1Point().Y() = y2;
882                 z1 = z2;
883                 DebugMsg(3, "Using value from chamber 12: x2 = " << x2 << ", y2 = " << y2 << ", z2 = " << z2 );
884         }
885         else
886         {
887                 // Return false if we could not find any hits on chambers 11 or 12.
888                 Warning("FillTriggerFromHits", "Could not find any hits on chambers 11 and 12.");
889                 return kFALSE;
890         }
891
892         // Get a coordinate for station 2, perferably from chamber 13 otherwise
893         // use hits from chamber 14.
894         if ( ! TMath::IsNaN(x3))
895         {
896                 record.Station2Point().X() = x3;
897                 record.Station2Point().Y() = y3;
898                 z2 = z3;
899                 DebugMsg(3, "Using value from chamber 13: x3 = " << x3 << ", y3 = " << y3 << ", z3 = " << z3 );
900         }
901         else if ( ! TMath::IsNaN(x4))
902         {
903                 record.Station2Point().X() = x4;
904                 record.Station2Point().Y() = y4;
905                 z2 = z4;
906                 DebugMsg(3, "Using value from chamber 14: x4 = " << x4 << ", y4 = " << y4 << ", z4 = " << z4 );
907         }
908         else
909         {
910                 // Return false if we could not find any hits on chambers 13 or 14.
911                 Warning("FillTriggerFromHits", "Could not find any hits on chambers 13 and 14.");
912                 return kFALSE;
913         }
914         
915         record.TriggerNumber(track);
916         
917         // Get the sign of the particle.
918         Int_t particlecode = (Int_t) data->Hit(track, 0)->Particle();
919         DebugMsg(3, "particle code = " << particlecode);
920         TDatabasePDG* pdb = TDatabasePDG::Instance();
921         TParticlePDG* pdata = pdb->GetParticle(particlecode);
922         if (pdata->Charge() < 0)
923                 record.ParticleSign(-1);
924         else if (pdata->Charge() > 0)
925                 record.ParticleSign(+1);
926         else
927                 record.ParticleSign(0);
928         DebugMsg(3, "Particle sign = " << record.ParticleSign());
929         
930         DebugMsg(3, "Calculating Pt: x1 = " << record.Station1Point().X()
931                         << ", y1 = " << record.Station1Point().Y()
932                         << ", y2 = " << record.Station2Point().Y()
933                         << ", z1 = " << z1
934                         << ", z2 = " << z2
935                 );
936         // Calculate and assign the transverse momentum.
937         Float_t pt = AliHLTMUONCoreCalculatePt(
938                                 record.Station1Point().X(),
939                                 record.Station1Point().Y(), record.Station2Point().Y(),
940                                 z1, z2
941                         );
942         record.Pt(pt);
943         
944         DebugMsg(3, "Pt = " << record.Pt());
945         
946         return kTRUE;
947 }
948
949
950 Bool_t AliHLTMUONTriggerSource::FetchAliMUON(AliMUON*& module)
951 {
952 // Fetches the AliMUON module from the AliRun global object. AliRun will be loaded
953 // by the runloader if it has not yet been loaded. In such a case the AliRun object
954 // will also we unloaded when we are done with it.
955 // kTRUE is returned if no error occured and kFALSE otherwise.
956 // Note that if fDataToUse is set to kFromHits then gAlice is not loaded and 'module'
957 // will be left untouched. The method will still return kTRUE however since this is
958 // not an error. We do not need the AliMUON module when filling from hits.
959
960         // Check if we even need the MUON module. Not having to load it will
961         // save a lot of loading time for AliRoot.
962         if (fDataToUse == kFromHits)
963         {
964                 // Make sure we do not attempt to unload gAlice in FinishedWithAliMUON,
965                 // by setting the fHadToLoadgAlice to false.
966                 fHadToLoadgAlice = kFALSE;
967                 return kTRUE;
968         }
969         
970         AliRunLoader* runloader = AliRunLoader::GetRunLoader();
971         if ( runloader == NULL )
972         {
973                 Error("FetchAliMUON", "AliRunLoader not initialised!");
974                 return kFALSE;
975         }
976
977         // Try fetch the AliRun object. If it is not found then try load it using
978         // the runloader.
979         AliRun* alirun = runloader->GetAliRun();
980         if (alirun == NULL)
981         {
982                 if (runloader->LoadgAlice() != 0)
983                 {
984                         // Error.
985                         DebugMsg(1, "Leaving FillFrom(AliMUONDataInterface*)");
986                         return kFALSE;
987                 }
988                 fHadToLoadgAlice = kTRUE;
989                 alirun = runloader->GetAliRun();
990         }
991         else
992                 fHadToLoadgAlice = kFALSE;
993
994         // Get the MUON module pointer and return it.
995         module = dynamic_cast<AliMUON*>( alirun->GetModule("MUON") );
996         return kTRUE;
997 }
998
999
1000 void AliHLTMUONTriggerSource::FinishedWithAliMUON()
1001 {
1002 // After one is finished with the AliMUON object returned by GetAliMUON, one
1003 // should call this method.
1004 // If the gAlice object was loaded by GetAliMUON then it will be unloaded at
1005 // this point, otherwise nothing is done.
1006
1007         // Only unload the gAlice object if we had to load it ourselves.
1008         if (fHadToLoadgAlice)
1009                 AliRunLoader::GetRunLoader()->UnloadgAlice();
1010 }
1011
1012
1013 void AliHLTMUONTriggerSource::ResetAllPointers() const
1014 {
1015 // Sets all the current pointers to NULL and indices to -1.
1016
1017         fEventIndex = -1;
1018         fCurrentEvent = NULL;
1019         fBlockIndex = -1;
1020         fCurrentBlock = NULL;
1021         fTriggerIndex = -1;
1022         fCurrentTrigger = NULL;
1023         DebugMsg(2, "\tfEventIndex = " << fEventIndex << " , fBlockIndex = " << fBlockIndex
1024                 << " , fTriggerIndex = " << fTriggerIndex
1025         );
1026 }
1027
1028
1029 void AliHLTMUONTriggerSource::ResetBlockPointers() const
1030 {
1031 // Sets the block and trigger pointers to NULL and indices to -1.
1032
1033         fBlockIndex = -1;
1034         fCurrentBlock = NULL;
1035         fTriggerIndex = -1;
1036         fCurrentTrigger = NULL;
1037         DebugMsg(2, "\tfEventIndex = " << fEventIndex << " , fBlockIndex = " << fBlockIndex
1038                 << " , fTriggerIndex = " << fTriggerIndex
1039         );
1040 }
1041
1042
1043 void AliHLTMUONTriggerSource::ResetTriggerPointers() const
1044 {
1045 // Sets just the current trigger record pointer to NULL and index to -1.
1046
1047         fTriggerIndex = -1;
1048         fCurrentTrigger = NULL;
1049         DebugMsg(2, "\tfEventIndex = " << fEventIndex << " , fBlockIndex = " << fBlockIndex
1050                 << " , fTriggerIndex = " << fTriggerIndex
1051         );
1052 }
1053
1054
1055 AliHLTMUONTriggerSource::AliEventData::AliEventData() :
1056         fEventNumber(-1), fBlocks(TClonesArray::Class())
1057 {
1058         fEventNumber = -1;
1059 }
1060
1061
1062 AliHLTMUONTriggerSource::AliEventData::AliEventData(Int_t eventnumber)
1063         : fEventNumber(eventnumber), fBlocks(TClonesArray::Class())
1064 {
1065 // Create a new event data block with specified event number.
1066
1067         fEventNumber = eventnumber;
1068
1069         // If the following is not set then we do not write the fBlocks properly.
1070         fBlocks.BypassStreamer(kFALSE);
1071 }
1072
1073
1074 AliHLTMUONTriggerSource::AliEventData::~AliEventData()
1075 {
1076         //fBlocks.Clear("C");  // Done in fBlocks destructor 
1077 }
1078