Cleanup of documentation and code.
[u/mrichter/AliRoot.git] / HLT / MUON / OfflineInterface / AliHLTMUONRootifierComponent.cxx
1 /**************************************************************************
2  * This file is property of and copyright by the ALICE HLT Project        * 
3  * All rights reserved.                                                   *
4  *                                                                        *
5  * Primary Authors:                                                       *
6  *   Artur Szostak <artursz@iafrica.com>                                  *
7  *                                                                        *
8  * Permission to use, copy, modify and distribute this software and its   *
9  * documentation strictly for non-commercial purposes is hereby granted   *
10  * without fee, provided that the above copyright notice appears in all   *
11  * copies and that both the copyright notice and this permission notice   *
12  * appear in the supporting documentation. The authors make no claims     *
13  * about the suitability of this software for any purpose. It is          * 
14  * provided "as is" without express or implied warranty.                  *
15  **************************************************************************/
16
17 /* $Id$ */
18
19 ///
20 /// @file   AliHLTMUONRootifierComponent.cxx
21 /// @author Artur Szostak <artursz@iafrica.com>
22 /// @date   29 Sep 2007
23 /// @brief  Implementation of the AliHLTMUONRootifierComponent component.
24 ///
25
26 #include "AliHLTMUONRootifierComponent.h"
27 #include "AliHLTMUONEvent.h"
28 #include "AliHLTMUONConstants.h"
29 #include "AliHLTMUONUtils.h"
30 #include "AliHLTMUONDataBlockReader.h"
31 #include "AliHLTMUONRecHit.h"
32 #include "AliHLTMUONTriggerRecord.h"
33 #include "AliHLTMUONMansoTrack.h"
34 #include "AliHLTMUONDecision.h"
35 #include "TClonesArray.h"
36 #include <cassert>
37
38 ClassImp(AliHLTMUONRootifierComponent);
39
40
41 AliHLTMUONRootifierComponent::AliHLTMUONRootifierComponent() :
42         AliHLTProcessor(),
43         fWarnForUnexpecedBlock(false)
44 {
45         ///
46         /// Default constructor.
47         ///
48 }
49
50
51 AliHLTMUONRootifierComponent::~AliHLTMUONRootifierComponent()
52 {
53         ///
54         /// Default destructor.
55         ///
56 }
57
58
59 int AliHLTMUONRootifierComponent::DoInit(int argc, const char** argv)
60 {
61         ///
62         /// Inherited from AliHLTComponent.
63         /// Parses the command line parameters and initialises the component.
64         ///
65         
66         HLTInfo("Initialising dHLT rootifier component.");
67         
68         fWarnForUnexpecedBlock = false;
69         
70         for (int i = 0; i < argc; i++)
71         {
72                 if (strcmp(argv[i], "-warn_on_unexpected_block") == 0)
73                 {
74                         fWarnForUnexpecedBlock = true;
75                         continue;
76                 }
77
78                 HLTError("Unknown option '%s'.", argv[i]);
79                 return -EINVAL;
80         }
81         
82         return 0;
83 }
84
85
86 int AliHLTMUONRootifierComponent::DoDeinit()
87 {
88         ///
89         /// Inherited from AliHLTComponent. Performs a cleanup of the component.
90         ///
91         
92         HLTInfo("Deinitialising dHLT rootifier component.");
93         return 0;
94 }
95
96
97 const char* AliHLTMUONRootifierComponent::GetComponentID()
98 {
99         ///
100         /// Inherited from AliHLTComponent. Returns the component ID.
101         ///
102         
103         return AliHLTMUONConstants::RootifierComponentId();
104 }
105
106
107 AliHLTComponentDataType AliHLTMUONRootifierComponent::GetOutputDataType()
108 {
109         /// Inherited from AliHLTComponent. Returns kAliHLTMultipleDataType
110         /// refer to GetOutputDataTypes for all returned data types.
111         
112         return kAliHLTMultipleDataType;
113 }
114
115
116 int AliHLTMUONRootifierComponent::GetOutputDataTypes(AliHLTComponentDataTypeList& tgtList)
117 {
118         /// Inherited from AliHLTComponent. Returns the output data types.
119         
120         tgtList.push_back(kAliHLTAnyDataType);
121         return 1;
122 }
123
124
125 void AliHLTMUONRootifierComponent::GetInputDataTypes(
126                 vector<AliHLTComponentDataType>& list
127         )
128 {
129         ///
130         /// Inherited from AliHLTProcessor. Returns the list of expected input data types.
131         ///
132         
133         list.push_back(kAliHLTAnyDataType);
134 }
135
136
137 void AliHLTMUONRootifierComponent::GetOutputDataSize(
138                 unsigned long& constBase, double& inputMultiplier
139         )
140 {
141         ///
142         /// Inherited from AliHLTComponent. Returns an estimate of the expected output data size.
143         ///
144         
145         constBase = 1024*1024;
146         inputMultiplier = 100;
147 }
148
149
150 AliHLTComponent* AliHLTMUONRootifierComponent::Spawn()
151 {
152         ///
153         /// Inherited from AliHLTComponent. Creates a new object instance.
154         ///
155         
156         return new AliHLTMUONRootifierComponent();
157 }
158
159
160 int AliHLTMUONRootifierComponent::DoEvent(
161                 const AliHLTComponentEventData& evtData,
162                 AliHLTComponentTriggerData& /*trigData*/
163         )
164 {
165         ///
166         /// Inherited from AliHLTProcessor. Processes the new event data.
167         ///
168         
169         AliHLTMUONEvent event(evtData.fEventID);
170         const AliHLTComponentBlockData* block = NULL;
171
172         // First process the blocks of reconstructed hits and trigger records.
173         for (int i = 0; i < GetNumberOfInputBlocks(); i++)
174         {
175                 block = GetInputBlock(i);
176                 assert( block != NULL );
177                 
178                 HLTDebug("Handling block: %u, with fDataType = '%s', fPtr = %p and fSize = %u bytes.",
179                         n, DataType2Text(block->fDataType).c_str(), block->fPtr, block->fSize
180                 );
181                 
182                 if (block->fDataType == AliHLTMUONConstants::RecHitsBlockDataType())
183                 {
184                         AliHLTUInt8_t* ptr = reinterpret_cast<AliHLTUInt8_t*>(block->fPtr);
185                         ptr += block->fOffset;
186                         AliHLTMUONRecHitsBlockReader inblock(ptr, block->fSize);
187                         if (not inblock.BufferSizeOk())
188                         {
189                                 size_t headerSize = sizeof(AliHLTMUONRecHitsBlockReader::HeaderType);
190                                 if (block->fSize < headerSize)
191                                 {
192                                         HLTError("Received a reconstructed hits data block with a size of %d bytes,"
193                                                 " which is smaller than the minimum valid header size of %d bytes."
194                                                 " The block must be corrupt.",
195                                                 block->fSize, headerSize
196                                         );
197                                         continue;
198                                 }
199                                 
200                                 size_t expectedWidth = sizeof(AliHLTMUONRecHitsBlockReader::ElementType);
201                                 if (inblock.CommonBlockHeader().fRecordWidth != expectedWidth)
202                                 {
203                                         HLTError("Received a reconstructed hits data block with a record"
204                                                 " width of %d bytes, but the expected value is %d bytes."
205                                                 " The block might be corrupt.",
206                                                 block->fSize, headerSize
207                                         );
208                                         continue;
209                                 }
210                                 
211                                 HLTError("Received a reconstructed hits data block with a size of %d bytes,"
212                                         " but the block header claims the block should be %d bytes."
213                                         " The block might be corrupt.",
214                                         block->fSize, inblock.BytesUsed()
215                                 );
216                                 continue;
217                         }
218                         
219                         // Decode the source DDL from the specification bits.
220                         Int_t sourceDDL = -1;
221                         bool ddl[22];
222                         AliHLTMUONUtils::UnpackSpecBits(block->fSpecification, ddl);
223                         for (int k = 0; k < 22; k++)
224                         {
225                                 if (ddl[k])
226                                 {
227                                         if (sourceDDL == -1)
228                                         {
229                                                 sourceDDL = k+1;
230                                         }
231                                         else
232                                         {
233                                                 HLTWarning("The input data block %d contains"
234                                                         " data from multiple DDL sources.", i
235                                                 );
236                                         }
237                                 }
238                         }
239                         if (sourceDDL > 20)
240                         {
241                                 HLTWarning("The source DDL for input data block %d is %d."
242                                         " The expected range for the DDL is [1..20].",
243                                         i, sourceDDL
244                                 );
245                         }
246                         
247                         for (AliHLTUInt32_t n = 0; n < inblock.Nentries(); n++)
248                         {
249                                 const AliHLTMUONRecHitStruct& h = inblock[n];
250                                 event.Add(new AliHLTMUONRecHit(h.fX, h.fY, h.fZ, sourceDDL));
251                         }
252                 }
253                 else if (block->fDataType == AliHLTMUONConstants::TriggerRecordsBlockDataType())
254                 {
255                         AliHLTUInt8_t* ptr = reinterpret_cast<AliHLTUInt8_t*>(block->fPtr);
256                         ptr += block->fOffset;
257                         AliHLTMUONTriggerRecordsBlockReader inblock(ptr, block->fSize);
258                         if (not inblock.BufferSizeOk())
259                         {
260                                 size_t headerSize = sizeof(AliHLTMUONTriggerRecordsBlockReader::HeaderType);
261                                 if (block->fSize < headerSize)
262                                 {
263                                         HLTError("Received a trigger records data block with a size of %d bytes,"
264                                                 " which is smaller than the minimum valid header size of %d bytes."
265                                                 " The block must be corrupt.",
266                                                 block->fSize, headerSize
267                                         );
268                                         continue;
269                                 }
270                                 
271                                 size_t expectedWidth = sizeof(AliHLTMUONTriggerRecordsBlockReader::ElementType);
272                                 if (inblock.CommonBlockHeader().fRecordWidth != expectedWidth)
273                                 {
274                                         HLTError("Received a trigger records data block with a record"
275                                                 " width of %d bytes, but the expected value is %d bytes."
276                                                 " The block might be corrupt.",
277                                                 block->fSize, headerSize
278                                         );
279                                         continue;
280                                 }
281                                 
282                                 HLTError("Received a trigger records data block with a size of %d bytes,"
283                                         " but the block header claims the block should be %d bytes."
284                                         " The block might be corrupt.",
285                                         block->fSize, inblock.BytesUsed()
286                                 );
287                                 continue;
288                         }
289                         
290                         // Decode the source DDL from the specification bits.
291                         Int_t sourceDDL = -1;
292                         bool ddl[22];
293                         AliHLTMUONUtils::UnpackSpecBits(block->fSpecification, ddl);
294                         for (int k = 0; k < 22; k++)
295                         {
296                                 if (ddl[k])
297                                 {
298                                         if (sourceDDL == -1)
299                                         {
300                                                 sourceDDL = k+1;
301                                         }
302                                         else
303                                         {
304                                                 HLTWarning("The input data block %d contains"
305                                                         " data from multiple DDL sources.", i
306                                                 );
307                                         }
308                                 }
309                         }
310                         if (sourceDDL != -1 and (sourceDDL < 21 or sourceDDL > 22))
311                         {
312                                 HLTWarning("The source DDL for input data block %d is %d."
313                                         " The expected range for the DDL is [21..22].",
314                                         i, sourceDDL
315                                 );
316                         }
317                         
318                         for (AliHLTUInt32_t n = 0; n < inblock.Nentries(); n++)
319                         {
320                                 const AliHLTMUONTriggerRecordStruct& t = inblock[n];
321                                 
322                                 AliHLTMUONParticleSign sign;
323                                 bool hitset[4];
324                                 AliHLTMUONUtils::UnpackTriggerRecordFlags(
325                                                 t.fFlags, sign, hitset
326                                         );
327                         
328                                 AliHLTMUONTriggerRecord* tr = new AliHLTMUONTriggerRecord(
329                                                 t.fId, sign, t.fPx, t.fPy, t.fPz, sourceDDL
330                                         );
331                                 for (int k = 0; k < 4; k++)
332                                         tr->SetHit(k+11, t.fHit[k].fX, t.fHit[k].fY, t.fHit[k].fZ);
333                                 event.Add(tr);
334                         }
335                 }
336                 else
337                 {
338                         if (block->fDataType != AliHLTMUONConstants::MansoTracksBlockDataType() and
339                             block->fDataType != AliHLTMUONConstants::SinglesDecisionBlockDataType() and
340                             block->fDataType != AliHLTMUONConstants::PairsDecisionBlockDataType()
341                            )
342                         {
343                                 // Log a message indicating that we got a data block that we
344                                 // do not know how to handle.
345                                 if (fWarnForUnexpecedBlock)
346                                         HLTWarning("Received a data block of a type we cannot handle: '%s', spec: 0x%X",
347                                                 DataType2Text(block->fDataType).c_str(), block->fSpecification
348                                         );
349                                 else
350                                         HLTDebug("Received a data block of a type we cannot handle: '%s', spec: 0x%X",
351                                                 DataType2Text(block->fDataType).c_str(), block->fSpecification
352                                         );
353                         }
354                 }
355         }
356         
357         // Now we can look for tracks to add. We needed the ROOT trigger records
358         // and reco hits created before we can create track objects.
359         for (block = GetFirstInputBlock(AliHLTMUONConstants::MansoTracksBlockDataType());
360              block != NULL;
361              block = GetNextInputBlock()
362             )
363         {
364                 AliHLTUInt8_t* ptr = reinterpret_cast<AliHLTUInt8_t*>(block->fPtr);
365                 ptr += block->fOffset;
366                 AliHLTMUONMansoTracksBlockReader inblock(ptr, block->fSize);
367                 if (not inblock.BufferSizeOk())
368                 {
369                         size_t headerSize = sizeof(AliHLTMUONMansoTracksBlockReader::HeaderType);
370                         if (block->fSize < headerSize)
371                         {
372                                 HLTError("Received a Manso tracks data block with a size of %d bytes,"
373                                         " which is smaller than the minimum valid header size of %d bytes."
374                                         " The block must be corrupt.",
375                                         block->fSize, headerSize
376                                 );
377                                 continue;
378                         }
379                         
380                         size_t expectedWidth = sizeof(AliHLTMUONMansoTracksBlockReader::ElementType);
381                         if (inblock.CommonBlockHeader().fRecordWidth != expectedWidth)
382                         {
383                                 HLTError("Received a Manso tracks data block with a record"
384                                         " width of %d bytes, but the expected value is %d bytes."
385                                         " The block might be corrupt.",
386                                         block->fSize, headerSize
387                                 );
388                                 continue;
389                         }
390                         
391                         HLTError("Received a Manso tracks data block with a size of %d bytes,"
392                                 " but the block header claims the block should be %d bytes."
393                                 " The block might be corrupt.",
394                                 block->fSize, inblock.BytesUsed()
395                         );
396                         continue;
397                 }
398                 
399                 for (AliHLTUInt32_t n = 0; n < inblock.Nentries(); n++)
400                 {
401                         const AliHLTMUONMansoTrackStruct& t = inblock[n];
402                         
403                         AliHLTMUONParticleSign sign;
404                         bool hitset[4];
405                         AliHLTMUONUtils::UnpackMansoTrackFlags(
406                                         t.fFlags, sign, hitset
407                                 );
408                         
409                         // Try find the trigger record in 'event'.
410                         const AliHLTMUONTriggerRecord* trigrec = NULL;
411                         for (Int_t k = 0; k < event.Array().GetEntriesFast(); k++)
412                         {
413                                 if (event.Array()[k]->IsA() != AliHLTMUONTriggerRecord::Class())
414                                         continue;
415                                 const AliHLTMUONTriggerRecord* tk =
416                                         static_cast<const AliHLTMUONTriggerRecord*>(event.Array()[k]);
417                                 if (tk->Id() == t.fTrigRec)
418                                 {
419                                         trigrec = tk;
420                                         break;
421                                 }
422                         }
423                         
424                         // Now try find the hits in 'event'.
425                         // If they cannot be found then create new ones.
426                         const AliHLTMUONRecHit* hit7 = NULL;
427                         const AliHLTMUONRecHit* hit8 = NULL;
428                         const AliHLTMUONRecHit* hit9 = NULL;
429                         const AliHLTMUONRecHit* hit10 = NULL;
430                         for (Int_t k = 0; k < event.Array().GetEntriesFast(); k++)
431                         {
432                                 if (event.Array()[k]->IsA() != AliHLTMUONRecHit::Class())
433                                         continue;
434                                 const AliHLTMUONRecHit* h =
435                                         static_cast<const AliHLTMUONRecHit*>(event.Array()[k]);
436                                 
437                                 if (hitset[0] and h->X() == t.fHit[0].fX and h->Y() == t.fHit[0].fY
438                                         and h->Z() == t.fHit[0].fZ)
439                                 {
440                                         hit7 = h;
441                                 }
442                                 if (hitset[1] and h->X() == t.fHit[1].fX and h->Y() == t.fHit[1].fY
443                                         and h->Z() == t.fHit[1].fZ)
444                                 {
445                                         hit8 = h;
446                                 }
447                                 if (hitset[2] and h->X() == t.fHit[2].fX and h->Y() == t.fHit[2].fY
448                                         and h->Z() == t.fHit[2].fZ)
449                                 {
450                                         hit9 = h;
451                                 }
452                                 if (hitset[3] and h->X() == t.fHit[3].fX and h->Y() == t.fHit[3].fY
453                                         and h->Z() == t.fHit[3].fZ)
454                                 {
455                                         hit10 = h;
456                                 }
457                         }
458                         AliHLTMUONRecHit* newhit;
459                         if (hitset[0] and hit7 == NULL)
460                         {
461                                 newhit = new AliHLTMUONRecHit(t.fHit[0].fX, t.fHit[0].fY, t.fHit[0].fZ);
462                                 event.Add(newhit);
463                                 hit7 = newhit;
464                         }
465                         if (hitset[1] and hit8 == NULL)
466                         {
467                                 newhit = new AliHLTMUONRecHit(t.fHit[1].fX, t.fHit[1].fY, t.fHit[1].fZ);
468                                 event.Add(newhit);
469                                 hit8 = newhit;
470                         }
471                         if (hitset[2] and hit9 == NULL)
472                         {
473                                 newhit = new AliHLTMUONRecHit(t.fHit[2].fX, t.fHit[2].fY, t.fHit[2].fZ);
474                                 event.Add(newhit);
475                                 hit9 = newhit;
476                         }
477                         if (hitset[3] and hit10 == NULL)
478                         {
479                                 newhit = new AliHLTMUONRecHit(t.fHit[3].fX, t.fHit[3].fY, t.fHit[3].fZ);
480                                 event.Add(newhit);
481                                 hit10 = newhit;
482                         }
483                 
484                         AliHLTMUONMansoTrack* tr = new AliHLTMUONMansoTrack(
485                                         t.fId, sign, t.fPx, t.fPy, t.fPz, t.fChi2,
486                                         trigrec, hit7, hit8, hit9, hit10
487                                 );
488                         event.Add(tr);
489                 }
490         }
491         
492         UInt_t numLowPt = 0;
493         UInt_t numHighPt = 0;
494         TClonesArray singlesDecisions("AliHLTMUONDecision::AliTrackDecision");
495         
496         // Find the single tracks decision blocks and add their information.
497         // We just sum the trigger scalars and single decisions.
498         for (block = GetFirstInputBlock(AliHLTMUONConstants::SinglesDecisionBlockDataType());
499              block != NULL;
500              block = GetNextInputBlock()
501             )
502         {
503                 AliHLTUInt8_t* ptr = reinterpret_cast<AliHLTUInt8_t*>(block->fPtr);
504                 ptr += block->fOffset;
505                 AliHLTMUONSinglesDecisionBlockReader inblock(ptr, block->fSize);
506                 if (not inblock.BufferSizeOk())
507                 {
508                         size_t headerSize = sizeof(AliHLTMUONSinglesDecisionBlockReader::HeaderType);
509                         if (block->fSize < headerSize)
510                         {
511                                 HLTError("Received a single tracks trigger decision data block with a size of %d bytes,"
512                                         " which is smaller than the minimum valid header size of %d bytes."
513                                         " The block must be corrupt.",
514                                         block->fSize, headerSize
515                                 );
516                                 continue;
517                         }
518                         
519                         size_t expectedWidth = sizeof(AliHLTMUONSinglesDecisionBlockReader::ElementType);
520                         if (inblock.CommonBlockHeader().fRecordWidth != expectedWidth)
521                         {
522                                 HLTError("Received a single tracks trigger decision data block with a record"
523                                         " width of %d bytes, but the expected value is %d bytes."
524                                         " The block might be corrupt.",
525                                         block->fSize, headerSize
526                                 );
527                                 continue;
528                         }
529                         
530                         HLTError("Received a single tracks trigger decision data block with a size of %d bytes,"
531                                 " but the block header claims the block should be %d bytes."
532                                 " The block might be corrupt.",
533                                 block->fSize, inblock.BytesUsed()
534                         );
535                         continue;
536                 }
537                 
538                 numLowPt += inblock.BlockHeader().fNlowPt;
539                 numHighPt += inblock.BlockHeader().fNhighPt;
540                 
541                 for (AliHLTUInt32_t n = 0; n < inblock.Nentries(); n++)
542                 {
543                         const AliHLTMUONTrackDecisionStruct& t = inblock[n];
544                         
545                         bool highPt, lowPt;
546                         AliHLTMUONUtils::UnpackTrackDecisionBits(t.fTriggerBits, highPt, lowPt);
547                         
548                         // Try find the corresponding track in the 'event'.
549                         const AliHLTMUONMansoTrack* track = NULL;
550                         for (Int_t k = 0; k < event.Array().GetEntriesFast(); k++)
551                         {
552                                 if (event.Array()[k]->IsA() != AliHLTMUONMansoTrack::Class())
553                                         continue;
554                                 const AliHLTMUONMansoTrack* tk =
555                                         static_cast<const AliHLTMUONMansoTrack*>(event.Array()[k]);
556                                 if (tk->Id() == t.fTrackId)
557                                 {
558                                         track = tk;
559                                         break;
560                                 }
561                         }
562                         
563                         // If the track was not found then create a dummy one.
564                         if (track == NULL)
565                         {
566                                 AliHLTMUONMansoTrack* tr = new AliHLTMUONMansoTrack(t.fTrackId);
567                                 event.Add(tr);
568                                 track = tr;
569                         }
570                         
571                         new (singlesDecisions[singlesDecisions.GetEntriesFast()])
572                                 AliHLTMUONDecision::AliTrackDecision(t.fPt, lowPt, highPt, track);
573                 }
574         }
575         
576         UInt_t numUnlikeAnyPt = 0;
577         UInt_t numUnlikeLowPt = 0;
578         UInt_t numUnlikeHighPt = 0;
579         UInt_t numLikeAnyPt = 0;
580         UInt_t numLikeLowPt = 0;
581         UInt_t numLikeHighPt = 0;
582         UInt_t numAnyMass = 0;
583         UInt_t numLowMass = 0;
584         UInt_t numHighMass = 0;
585         TClonesArray pairsDecisions("AliHLTMUONDecision::AliPairDecision");
586         
587         // Find the track pairs decision blocks and add their information.
588         // We just sum the trigger scalars and track pair decisions.
589         for (block = GetFirstInputBlock(AliHLTMUONConstants::PairsDecisionBlockDataType());
590              block != NULL;
591              block = GetNextInputBlock()
592             )
593         {
594                 AliHLTUInt8_t* ptr = reinterpret_cast<AliHLTUInt8_t*>(block->fPtr);
595                 ptr += block->fOffset;
596                 AliHLTMUONPairsDecisionBlockReader inblock(ptr, block->fSize);
597                 if (not inblock.BufferSizeOk())
598                 {
599                         size_t headerSize = sizeof(AliHLTMUONPairsDecisionBlockReader::HeaderType);
600                         if (block->fSize < headerSize)
601                         {
602                                 HLTError("Received a track pairs trigger decision data block with a size of %d bytes,"
603                                         " which is smaller than the minimum valid header size of %d bytes."
604                                         " The block must be corrupt.",
605                                         block->fSize, headerSize
606                                 );
607                                 continue;
608                         }
609                         
610                         size_t expectedWidth = sizeof(AliHLTMUONPairsDecisionBlockReader::ElementType);
611                         if (inblock.CommonBlockHeader().fRecordWidth != expectedWidth)
612                         {
613                                 HLTError("Received a track pairs trigger decision data block with a record"
614                                         " width of %d bytes, but the expected value is %d bytes."
615                                         " The block might be corrupt.",
616                                         block->fSize, headerSize
617                                 );
618                                 continue;
619                         }
620                         
621                         HLTError("Received a track pairs trigger decision data block with a size of %d bytes,"
622                                 " but the block header claims the block should be %d bytes."
623                                 " The block might be corrupt.",
624                                 block->fSize, inblock.BytesUsed()
625                         );
626                         continue;
627                 }
628                 
629                 numUnlikeAnyPt += inblock.BlockHeader().fNunlikeAnyPt;
630                 numUnlikeLowPt += inblock.BlockHeader().fNunlikeLowPt;
631                 numUnlikeHighPt += inblock.BlockHeader().fNunlikeHighPt;
632                 numLikeAnyPt += inblock.BlockHeader().fNlikeAnyPt;
633                 numLikeLowPt += inblock.BlockHeader().fNlikeLowPt;
634                 numLikeHighPt += inblock.BlockHeader().fNlikeHighPt;
635                 numAnyMass += inblock.BlockHeader().fNmassAny;
636                 numLowMass += inblock.BlockHeader().fNmassLow;
637                 numHighMass += inblock.BlockHeader().fNmassHigh;
638                 
639                 for (AliHLTUInt32_t n = 0; n < inblock.Nentries(); n++)
640                 {
641                         const AliHLTMUONPairDecisionStruct& t = inblock[n];
642                         
643                         bool highMass, lowMass, unlike;
644                         AliHLTUInt8_t highPtCount, lowPtCount;
645                         AliHLTMUONUtils::UnpackPairDecisionBits(
646                                         t.fTriggerBits, highMass, lowMass, unlike,
647                                         highPtCount, lowPtCount
648                                 );
649                         
650                         // Try find the corresponding tracks in the 'event'.
651                         const AliHLTMUONMansoTrack* trackA = NULL;
652                         const AliHLTMUONMansoTrack* trackB = NULL;
653                         for (Int_t k = 0; k < event.Array().GetEntriesFast(); k++)
654                         {
655                                 if (event.Array()[k]->IsA() != AliHLTMUONMansoTrack::Class())
656                                         continue;
657                                 const AliHLTMUONMansoTrack* tk =
658                                         static_cast<const AliHLTMUONMansoTrack*>(event.Array()[k]);
659                                 if (tk->Id() == t.fTrackAId) trackA = tk;
660                                 if (tk->Id() == t.fTrackBId) trackB = tk;
661                                 if (trackA != NULL and trackB != NULL) break;
662                         }
663                         
664                         // If either of the tracks was not found then create a dummy one.
665                         if (trackA == NULL)
666                         {
667                                 AliHLTMUONMansoTrack* tr = new AliHLTMUONMansoTrack(t.fTrackAId);
668                                 event.Add(tr);
669                                 trackA = tr;
670                         }
671                         if (trackB == NULL)
672                         {
673                                 AliHLTMUONMansoTrack* tr = new AliHLTMUONMansoTrack(t.fTrackBId);
674                                 event.Add(tr);
675                                 trackB = tr;
676                         }
677                         
678                         new (pairsDecisions[pairsDecisions.GetEntriesFast()])
679                                 AliHLTMUONDecision::AliPairDecision(
680                                         t.fInvMass, lowMass, highMass, unlike,
681                                         lowPtCount, highPtCount, trackA, trackB
682                                 );
683                 }
684         }
685         
686         AliHLTMUONDecision* triggerDecision = new AliHLTMUONDecision(
687                         numLowPt, numHighPt, numUnlikeAnyPt, numUnlikeLowPt,
688                         numUnlikeHighPt, numLikeAnyPt, numLikeLowPt,
689                         numLikeHighPt, numAnyMass, numLowMass, numHighMass
690                 );
691         for (Int_t i = 0; i < singlesDecisions.GetEntriesFast(); i++)
692         {
693                 AliHLTMUONDecision::AliTrackDecision* decision =
694                         static_cast<AliHLTMUONDecision::AliTrackDecision*>( singlesDecisions[i] );
695                 triggerDecision->AddDecision(decision);
696         }
697         for (Int_t j = 0; j < pairsDecisions.GetEntriesFast(); j++)
698         {
699                 AliHLTMUONDecision::AliPairDecision* decision =
700                         static_cast<AliHLTMUONDecision::AliPairDecision*>( pairsDecisions[j] );
701                 triggerDecision->AddDecision(decision);
702         }
703         event.Add(triggerDecision);
704         
705         PushBack(&event, "ROOTEVNT", "MUON");
706         
707         return 0;
708 }
709