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