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