Important updates for Manso Tracker to use magnetic field integrals based on global...
[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 /// Implements a component to convert dHLT raw data into TObjects.
26
27 #include "AliHLTMUONRootifierComponent.h"
28 #include "AliHLTMUONEvent.h"
29 #include "AliHLTMUONConstants.h"
30 #include "AliHLTMUONUtils.h"
31 #include "AliHLTMUONRecHit.h"
32 #include "AliHLTMUONTriggerRecord.h"
33 #include "AliHLTMUONMansoTrack.h"
34 #include "AliHLTMUONDecision.h"
35 #include "AliMUONTriggerDDLDecoderEventHandler.h"
36 #include "TClonesArray.h"
37 #include <cassert>
38 #include <map>
39
40 ClassImp(AliHLTMUONRootifierComponent);
41
42
43 AliHLTMUONRootifierComponent::AliHLTMUONRootifierComponent() :
44         AliHLTMUONProcessor(),
45         fWarnForUnexpecedBlock(false)
46 {
47         ///
48         /// Default constructor.
49         ///
50 }
51
52
53 AliHLTMUONRootifierComponent::~AliHLTMUONRootifierComponent()
54 {
55         ///
56         /// Default destructor.
57         ///
58 }
59
60
61 bool AliHLTMUONRootifierComponent::IgnoreArgument(const char* arg) const
62 {
63         /// Return true if the argument is one of -cdbpath -run or -delaysetup
64         /// to prevent the parent class from parsing these arguments in DoInit.
65         
66         if (strcmp(arg, "-cdbpath") == 0 or strcmp(arg, "-run") == 0 or
67             strcmp(arg, "-delaysetup") == 0)
68         {
69                 return true;
70         }
71         else
72         {
73                 return false;
74         }
75 }
76
77
78 int AliHLTMUONRootifierComponent::DoInit(int argc, const char** argv)
79 {
80         ///
81         /// Inherited from AliHLTComponent.
82         /// Parses the command line parameters and initialises the component.
83         ///
84         
85         HLTInfo("Initialising dHLT rootifier component.");
86
87         // Inherit the parents functionality.
88         int result = AliHLTMUONProcessor::DoInit(argc, argv);
89         if (result != 0) return result;
90         
91         fWarnForUnexpecedBlock = false;
92         
93         for (int i = 0; i < argc; i++)
94         {
95                 if (ArgumentAlreadyHandled(i, argv[i])) continue;
96
97                 if (strcmp(argv[i], "-warn_on_unexpected_block") == 0)
98                 {
99                         fWarnForUnexpecedBlock = true;
100                         continue;
101                 }
102
103                 HLTError("Unknown option '%s'.", argv[i]);
104                 return -EINVAL;
105         }
106         
107         return 0;
108 }
109
110
111 int AliHLTMUONRootifierComponent::DoDeinit()
112 {
113         ///
114         /// Inherited from AliHLTComponent. Performs a cleanup of the component.
115         ///
116         
117         HLTInfo("Deinitialising dHLT rootifier component.");
118         return 0;
119 }
120
121
122 const char* AliHLTMUONRootifierComponent::GetComponentID()
123 {
124         ///
125         /// Inherited from AliHLTComponent. Returns the component ID.
126         ///
127         
128         return AliHLTMUONConstants::RootifierComponentId();
129 }
130
131
132 AliHLTComponentDataType AliHLTMUONRootifierComponent::GetOutputDataType()
133 {
134         /// Inherited from AliHLTComponent. Returns kAliHLTMultipleDataType
135         /// refer to GetOutputDataTypes for all returned data types.
136         
137         return kAliHLTMultipleDataType;
138 }
139
140
141 int AliHLTMUONRootifierComponent::GetOutputDataTypes(AliHLTComponentDataTypeList& tgtList)
142 {
143         /// Inherited from AliHLTComponent. Returns the output data types.
144         
145         tgtList.push_back(AliHLTMUONConstants::RootifiedEventDataType());
146         return tgtList.size();
147 }
148
149
150 void AliHLTMUONRootifierComponent::GetInputDataTypes(AliHLTComponentDataTypeList& list)
151 {
152         ///
153         /// Inherited from AliHLTProcessor. Returns the list of expected input data types.
154         ///
155         
156         list.push_back(kAliHLTAnyDataType);
157 }
158
159
160 void AliHLTMUONRootifierComponent::GetOutputDataSize(
161                 unsigned long& constBase, double& inputMultiplier
162         )
163 {
164         ///
165         /// Inherited from AliHLTComponent. Returns an estimate of the expected output data size.
166         ///
167         
168         constBase = 1024*1024;
169         inputMultiplier = 100;
170 }
171
172
173 AliHLTComponent* AliHLTMUONRootifierComponent::Spawn()
174 {
175         ///
176         /// Inherited from AliHLTComponent. Creates a new object instance.
177         ///
178         
179         return new AliHLTMUONRootifierComponent();
180 }
181
182
183 int AliHLTMUONRootifierComponent::DoEvent(
184                 const AliHLTComponentEventData& evtData,
185                 AliHLTComponentTriggerData& trigData
186         )
187 {
188         ///
189         /// Inherited from AliHLTProcessor. Processes the new event data.
190         ///
191         
192         if (not IsDataEvent()) return 0;
193         
194         AliHLTMUONEvent event(evtData.fEventID);
195         const AliHLTComponentBlockData* block = NULL;
196         AliHLTUInt32_t specification = 0;  // Contains the output data block spec bits.
197         std::map<AliHLTInt32_t, AliHLTMUONTriggerRecord*> triggerMap;
198
199         // First process the blocks of reconstructed hits and trigger records.
200         for (int i = 0; i < GetNumberOfInputBlocks(); i++)
201         {
202                 block = GetInputBlock(i);
203                 assert( block != NULL );
204                 
205                 HLTDebug("Handling block: %u, with fDataType = '%s', fPtr = %p and fSize = %u bytes.",
206                         i, DataType2Text(block->fDataType).c_str(), block->fPtr, block->fSize
207                 );
208                 
209                 if (block->fDataType == AliHLTMUONConstants::RecHitsBlockDataType())
210                 {
211                         specification |= block->fSpecification;
212                         AliHLTMUONRecHitsBlockReader inblock(block->fPtr, block->fSize);
213                         if (not BlockStructureOk(inblock))
214                         {
215                                 if (DumpDataOnError()) DumpEvent(evtData, trigData);
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                                 AliHLTUInt8_t chamber;
251                                 AliHLTUInt16_t detElemId;
252                                 AliHLTMUONUtils::UnpackRecHitFlags(h.fFlags, chamber, detElemId);
253                                 event.Add(new AliHLTMUONRecHit(h.fX, h.fY, h.fZ, sourceDDL, detElemId));
254                         }
255                 }
256                 else if (block->fDataType == AliHLTMUONConstants::TriggerRecordsBlockDataType())
257                 {
258                         specification |= block->fSpecification;
259                         AliHLTMUONTriggerRecordsBlockReader inblock(block->fPtr, block->fSize);
260                         if (not BlockStructureOk(inblock))
261                         {
262                                 if (DumpDataOnError()) DumpEvent(evtData, trigData);
263                                 continue;
264                         }
265                         
266                         // Decode the source DDL from the specification bits.
267                         Int_t sourceDDL = -1;
268                         bool ddl[22];
269                         AliHLTMUONUtils::UnpackSpecBits(block->fSpecification, ddl);
270                         for (int k = 0; k < 22; k++)
271                         {
272                                 if (ddl[k])
273                                 {
274                                         if (sourceDDL == -1)
275                                         {
276                                                 sourceDDL = k+1;
277                                         }
278                                         else
279                                         {
280                                                 HLTWarning("The input data block %d contains"
281                                                         " data from multiple DDL sources.", i
282                                                 );
283                                         }
284                                 }
285                         }
286                         if (sourceDDL != -1 and (sourceDDL < 21 or sourceDDL > 22))
287                         {
288                                 HLTWarning("The source DDL for input data block %d is %d."
289                                         " The expected range for the DDL is [21..22].",
290                                         i, sourceDDL
291                                 );
292                         }
293                         
294                         for (AliHLTUInt32_t n = 0; n < inblock.Nentries(); n++)
295                         {
296                                 const AliHLTMUONTriggerRecordStruct& t = inblock[n];
297                                 
298                                 AliHLTMUONParticleSign sign;
299                                 bool hitset[4];
300                                 AliHLTMUONUtils::UnpackTriggerRecordFlags(
301                                                 t.fFlags, sign, hitset
302                                         );
303                         
304                                 AliHLTMUONTriggerRecord* tr = new AliHLTMUONTriggerRecord(
305                                                 t.fId, sign, t.fPx, t.fPy, t.fPz, sourceDDL
306                                         );
307                                 for (int k = 0; k < 4; k++)
308                                 {
309                                         if (not hitset[k]) continue;
310                                         Int_t detElemId = AliHLTMUONUtils::GetDetElemIdFromFlags(t.fHit[k].fFlags);
311                                         tr->SetHit(k+11, t.fHit[k].fX, t.fHit[k].fY, t.fHit[k].fZ, detElemId);
312                                 }
313                                 event.Add(tr);
314                                 triggerMap[t.fId] = tr;
315                         }
316                 }
317                 else
318                 {
319                         if (block->fDataType != AliHLTMUONConstants::TrigRecsDebugBlockDataType() and
320                             block->fDataType != AliHLTMUONConstants::ClusterBlockDataType() and
321                             block->fDataType != AliHLTMUONConstants::ChannelBlockDataType() and
322                             block->fDataType != AliHLTMUONConstants::MansoTracksBlockDataType() and
323                             block->fDataType != AliHLTMUONConstants::MansoCandidatesBlockDataType() and
324                             block->fDataType != AliHLTMUONConstants::SinglesDecisionBlockDataType() and
325                             block->fDataType != AliHLTMUONConstants::PairsDecisionBlockDataType()
326                            )
327                         {
328                                 // Log a message indicating that we got a data block that we
329                                 // do not know how to handle.
330                                 if (fWarnForUnexpecedBlock)
331                                         HLTWarning("Received a data block of a type we cannot handle: '%s', spec: 0x%X",
332                                                 DataType2Text(block->fDataType).c_str(), block->fSpecification
333                                         );
334 #ifdef __DEBUG
335                                 else
336                                         HLTDebug("Received a data block of a type we cannot handle: '%s', spec: 0x%X",
337                                                 DataType2Text(block->fDataType).c_str(), block->fSpecification
338                                         );
339 #endif
340                         }
341                 }
342         }
343         
344         // We need to check if there are any trigger record debug data blocks
345         // and add their information to the AliHLTMUONTriggerRecord objects.
346         for (block = GetFirstInputBlock(AliHLTMUONConstants::TrigRecsDebugBlockDataType());
347              block != NULL;
348              block = GetNextInputBlock()
349             )
350         {
351                 specification |= block->fSpecification;
352                 AliHLTMUONTrigRecsDebugBlockReader inblock(block->fPtr, block->fSize);
353                 if (not BlockStructureOk(inblock))
354                 {
355                         if (DumpDataOnError()) DumpEvent(evtData, trigData);
356                         continue;
357                 }
358                 
359                 for (AliHLTUInt32_t n = 0; n < inblock.Nentries(); n++)
360                 {
361                         const AliHLTMUONTrigRecInfoStruct& triginfo = inblock[n];
362                         
363                         AliHLTMUONTriggerRecord* trigrec = triggerMap[triginfo.fTrigRecId];
364                         if (trigrec == NULL)
365                         {
366                                 // Decode the source DDL from the specification bits.
367                                 Int_t sourceDDL = -1;
368                                 bool ddl[22];
369                                 AliHLTMUONUtils::UnpackSpecBits(block->fSpecification, ddl);
370                                 for (int k = 0; k < 22; k++)
371                                 {
372                                         if (ddl[k])
373                                         {
374                                                 if (sourceDDL == -1)
375                                                 {
376                                                         sourceDDL = k+1;
377                                                 }
378                                                 else
379                                                 {
380                                                         HLTWarning("An trigger debug information data block"
381                                                                 " contains data from multiple DDL sources."
382                                                         );
383                                                 }
384                                         }
385                                 }
386                                 if (sourceDDL != -1 and (sourceDDL < 21 or sourceDDL > 22))
387                                 {
388                                         HLTWarning("The source DDL for a trigger debug information data"
389                                                 " block is %d. The expected range for the DDL is [21..22].",
390                                                 sourceDDL
391                                         );
392                                 }
393                                 
394                                 trigrec = new AliHLTMUONTriggerRecord(
395                                                 0, 0, 0, 0, 0, sourceDDL
396                                         );
397                         }
398                         else
399                         {
400                                 for (Int_t j = 0; j < 4; ++j)
401                                 {
402                                         if (trigrec->DetElemId(j+11) != -1 and triginfo.fDetElemId[j] != trigrec->DetElemId(j+11))
403                                         {
404                                                 HLTWarning("Found a trigger record with a hit on chamber %d with a different"
405                                                         " detector element ID %d than the debug information %d.",
406                                                         j, trigrec->DetElemId(j+11), triginfo.fDetElemId[j]
407                                                 );
408                                         }
409                                 }
410                         }
411                         
412                         typedef AliMUONTriggerDDLDecoderEventHandler Handler;
413                         
414                         trigrec->SetDebugInfo(triginfo.fZmiddle, triginfo.fBl);
415                         
416                         UShort_t patternX[4][3] = {
417                                 {
418                                         Handler::GetLocalX1(&triginfo.fL0StructPrev),
419                                         Handler::GetLocalX1(&triginfo.fL0Struct),
420                                         Handler::GetLocalX1(&triginfo.fL0StructNext)
421                                 },{
422                                         Handler::GetLocalX2(&triginfo.fL0StructPrev),
423                                         Handler::GetLocalX2(&triginfo.fL0Struct),
424                                         Handler::GetLocalX2(&triginfo.fL0StructNext)
425                                 },{
426                                         Handler::GetLocalX3(&triginfo.fL0StructPrev),
427                                         Handler::GetLocalX3(&triginfo.fL0Struct),
428                                         Handler::GetLocalX3(&triginfo.fL0StructNext)
429                                 },{
430                                         Handler::GetLocalX4(&triginfo.fL0StructPrev),
431                                         Handler::GetLocalX4(&triginfo.fL0Struct),
432                                         Handler::GetLocalX4(&triginfo.fL0StructNext)
433                                 }
434                         };
435                         UShort_t patternY[4][3] = {
436                                 {
437                                         Handler::GetLocalY1(&triginfo.fL0StructPrev),
438                                         Handler::GetLocalY1(&triginfo.fL0Struct),
439                                         Handler::GetLocalY1(&triginfo.fL0StructNext)
440                                 },{
441                                         Handler::GetLocalY2(&triginfo.fL0StructPrev),
442                                         Handler::GetLocalY2(&triginfo.fL0Struct),
443                                         Handler::GetLocalY2(&triginfo.fL0StructNext)
444                                 },{
445                                         Handler::GetLocalY3(&triginfo.fL0StructPrev),
446                                         Handler::GetLocalY3(&triginfo.fL0Struct),
447                                         Handler::GetLocalY3(&triginfo.fL0StructNext)
448                                 },{
449                                         Handler::GetLocalY4(&triginfo.fL0StructPrev),
450                                         Handler::GetLocalY4(&triginfo.fL0Struct),
451                                         Handler::GetLocalY4(&triginfo.fL0StructNext)
452                                 }
453                         };
454                         
455                         for (Int_t j = 0; j < 4; ++j)
456                         {
457                                 trigrec->SetHitDebugInfo(j+11, patternX[j], patternY[j]);
458                         }
459                 }
460         }
461         
462         std::map<AliHLTInt32_t, AliHLTMUONRecHit*> clusterMap;
463         
464         // We need to check if there are any cluster data blocks and add their
465         // information to the AliHLTMUONRecHit objects.
466         for (block = GetFirstInputBlock(AliHLTMUONConstants::ClusterBlockDataType());
467              block != NULL;
468              block = GetNextInputBlock()
469             )
470         {
471                 specification |= block->fSpecification;
472                 AliHLTMUONClustersBlockReader inblock(block->fPtr, block->fSize);
473                 if (not BlockStructureOk(inblock))
474                 {
475                         if (DumpDataOnError()) DumpEvent(evtData, trigData);
476                         continue;
477                 }
478                 
479                 for (AliHLTUInt32_t n = 0; n < inblock.Nentries(); n++)
480                 {
481                         const AliHLTMUONClusterStruct& clust = inblock[n];
482                         
483                         AliHLTUInt8_t chamber;
484                         AliHLTUInt16_t detElemId;
485                         AliHLTMUONUtils::UnpackRecHitFlags(clust.fHit.fFlags, chamber, detElemId);
486                         if (clust.fDetElemId != detElemId)
487                         {
488                                 HLTWarning("Found a cluster with a different detector element ID (%d)"
489                                         " from its corresponding hit (x,y,z = %f,%f,%f and detElemId = %d).",
490                                         clust.fDetElemId,
491                                         clust.fHit.fX, clust.fHit.fY, clust.fHit.fZ,
492                                         detElemId
493                                 );
494                         }
495                         
496                         // Try find the corresponding reconstructed hit in 'event'.
497                         AliHLTMUONRecHit* hit = NULL;
498                         for (Int_t k = 0; k < event.Array().GetEntriesFast(); k++)
499                         {
500                                 if (event.Array()[k]->IsA() != AliHLTMUONRecHit::Class())
501                                         continue;
502                                 AliHLTMUONRecHit* h = static_cast<AliHLTMUONRecHit*>(event.Array()[k]);
503                                 if (h->DetElemId() == detElemId and h->X() == clust.fHit.fX
504                                     and h->Y() == clust.fHit.fY and h->Z() == clust.fHit.fZ)
505                                 {
506                                         hit = h;
507                                         break;
508                                 }
509                         }
510                         
511                         // If we could not find the corresponding hit then we need to create
512                         // a new hit object, otherwise we can just append the information.
513                         if (hit == NULL)
514                         {
515                                 // Decode the source DDL from the specification bits.
516                                 Int_t sourceDDL = -1;
517                                 bool ddl[22];
518                                 AliHLTMUONUtils::UnpackSpecBits(block->fSpecification, ddl);
519                                 for (int k = 0; k < 22; k++)
520                                 {
521                                         if (ddl[k])
522                                         {
523                                                 if (sourceDDL == -1)
524                                                 {
525                                                         sourceDDL = k+1;
526                                                 }
527                                                 else
528                                                 {
529                                                         HLTWarning("An input block of cluster data contains"
530                                                                 " data from multiple DDL sources."
531                                                         );
532                                                 }
533                                         }
534                                 }
535                                 if (sourceDDL > 20)
536                                 {
537                                         HLTWarning("The source DDL of a cluster data input block is %d."
538                                                 " The expected range for the DDL is [1..20].",
539                                                 sourceDDL
540                                         );
541                                 }
542                                 hit = new AliHLTMUONRecHit(
543                                                 clust.fHit.fX, clust.fHit.fY, clust.fHit.fZ,
544                                                 sourceDDL, detElemId
545                                         );
546                                 event.Add(hit);
547                         }
548                         else
549                         {
550                                 hit->SetDebugInfo(
551                                                   detElemId, clust.fId,
552                                                   clust.fNchannelsB, clust.fNchannelsNB,
553                                                   clust.fChargeB, clust.fChargeNB,
554                                                   hit->SourceDDL()
555                                 );
556                         }
557                         
558                         clusterMap[clust.fId] = hit;
559                 }
560         }
561         
562         // We need to check if there are any channel data blocks and add their
563         // information to the AliHLTMUONRecHit objects.
564         for (block = GetFirstInputBlock(AliHLTMUONConstants::ChannelBlockDataType());
565              block != NULL;
566              block = GetNextInputBlock()
567             )
568         {
569                 specification |= block->fSpecification;
570                 AliHLTMUONChannelsBlockReader inblock(block->fPtr, block->fSize);
571                 if (not BlockStructureOk(inblock))
572                 {
573                         if (DumpDataOnError()) DumpEvent(evtData, trigData);
574                         continue;
575                 }
576                 
577                 for (AliHLTUInt32_t n = 0; n < inblock.Nentries(); n++)
578                 {
579                         const AliHLTMUONChannelStruct& channel = inblock[n];
580                         
581                         AliHLTMUONRecHit* hit = clusterMap[channel.fClusterId];
582                         if (hit == NULL)
583                         {
584                                 // Decode the source DDL from the specification bits.
585                                 Int_t sourceDDL = -1;
586                                 bool ddl[22];
587                                 AliHLTMUONUtils::UnpackSpecBits(block->fSpecification, ddl);
588                                 for (int k = 0; k < 22; k++)
589                                 {
590                                         if (ddl[k])
591                                         {
592                                                 if (sourceDDL == -1)
593                                                 {
594                                                         sourceDDL = k+1;
595                                                 }
596                                                 else
597                                                 {
598                                                         HLTWarning("An input block of cluster data contains"
599                                                                 " data from multiple DDL sources."
600                                                         );
601                                                 }
602                                         }
603                                 }
604                                 if (sourceDDL > 20)
605                                 {
606                                         HLTWarning("The source DDL of a cluster data input block is %d."
607                                                 " The expected range for the DDL is [1..20].",
608                                                 sourceDDL
609                                         );
610                                 }
611                                 hit = new AliHLTMUONRecHit(0, 0, 0, sourceDDL, -1);
612                                 event.Add(hit);
613                         }
614                         
615                         hit->AddChannel(
616                                         channel.fBusPatch, channel.fManu,
617                                         channel.fChannelAddress, channel.fSignal,
618                                         channel.fRawDataWord
619                                 );
620                 }
621         }
622         
623         std::map<AliHLTInt32_t, AliHLTMUONMansoTrack*> trackMap;
624         
625         // Now we can look for tracks to add. We needed the ROOT trigger records
626         // and reco hits created before we can create track objects.
627         for (block = GetFirstInputBlock(AliHLTMUONConstants::MansoTracksBlockDataType());
628              block != NULL;
629              block = GetNextInputBlock()
630             )
631         {
632                 specification |= block->fSpecification;
633                 AliHLTMUONMansoTracksBlockReader inblock(block->fPtr, block->fSize);
634                 if (not BlockStructureOk(inblock))
635                 {
636                         if (DumpDataOnError()) DumpEvent(evtData, trigData);
637                         continue;
638                 }
639                 
640                 for (AliHLTUInt32_t n = 0; n < inblock.Nentries(); n++)
641                 {
642                         const AliHLTMUONMansoTrackStruct& t = inblock[n];
643                         trackMap[t.fId] = AddTrack(event, t);
644                 }
645         }
646         
647         // Look for Manso track candidates to add the debug info to the tracks.
648         for (block = GetFirstInputBlock(AliHLTMUONConstants::MansoCandidatesBlockDataType());
649              block != NULL;
650              block = GetNextInputBlock()
651             )
652         {
653                 specification |= block->fSpecification;
654                 AliHLTMUONMansoCandidatesBlockReader inblock(block->fPtr, block->fSize);
655                 if (not BlockStructureOk(inblock))
656                 {
657                         if (DumpDataOnError()) DumpEvent(evtData, trigData);
658                         continue;
659                 }
660                 
661                 for (AliHLTUInt32_t n = 0; n < inblock.Nentries(); n++)
662                 {
663                         const AliHLTMUONMansoCandidateStruct& tc = inblock[n];
664                         AliHLTMUONMansoTrack* mtrack = trackMap[tc.fTrack.fId];
665                         if (mtrack == NULL)
666                         {
667                                 // If we got here then we could not find the corresponding Manso
668                                 // track. So we need to create and add a new track object.
669                                 mtrack = AddTrack(event, tc.fTrack);
670                         }
671                         mtrack->SetDebugData(tc.fZmiddle, tc.fBl);
672                         for (AliHLTUInt32_t i = 0; i < 4; ++i)
673                         {
674                                 if (tc.fRoI[i] == AliHLTMUONConstants::NilMansoRoIStruct()) continue;
675                                 mtrack->SetRoI(i+7, tc.fRoI[i].fX, tc.fRoI[i].fY, tc.fRoI[i].fZ, tc.fRoI[i].fRadius);
676                         }
677                 }
678         }
679         
680         bool decisionBlockFound = false;
681         UInt_t numLowPt = 0;
682         UInt_t numHighPt = 0;
683         TClonesArray singlesDecisions("AliHLTMUONDecision::AliTrackDecision");
684         
685         // Find the single tracks decision blocks and add their information.
686         // We just sum the trigger scalars and single decisions.
687         for (block = GetFirstInputBlock(AliHLTMUONConstants::SinglesDecisionBlockDataType());
688              block != NULL;
689              block = GetNextInputBlock()
690             )
691         {
692                 decisionBlockFound = true;
693                 specification |= block->fSpecification;
694                 AliHLTMUONSinglesDecisionBlockReader inblock(block->fPtr, block->fSize);
695                 if (not BlockStructureOk(inblock))
696                 {
697                         if (DumpDataOnError()) DumpEvent(evtData, trigData);
698                         continue;
699                 }
700                 
701                 numLowPt += inblock.BlockHeader().fNlowPt;
702                 numHighPt += inblock.BlockHeader().fNhighPt;
703                 
704                 for (AliHLTUInt32_t n = 0; n < inblock.Nentries(); n++)
705                 {
706                         const AliHLTMUONTrackDecisionStruct& t = inblock[n];
707                         
708                         bool highPt, lowPt;
709                         AliHLTMUONUtils::UnpackTrackDecisionBits(t.fTriggerBits, highPt, lowPt);
710                         
711                         // Try find the corresponding track in the 'event'.
712                         const AliHLTMUONMansoTrack* track = NULL;
713                         for (Int_t k = 0; k < event.Array().GetEntriesFast(); k++)
714                         {
715                                 if (event.Array()[k]->IsA() != AliHLTMUONMansoTrack::Class())
716                                         continue;
717                                 const AliHLTMUONMansoTrack* tk =
718                                         static_cast<const AliHLTMUONMansoTrack*>(event.Array()[k]);
719                                 if (tk->Id() == t.fTrackId)
720                                 {
721                                         track = tk;
722                                         break;
723                                 }
724                         }
725                         
726                         // If the track was not found then create a dummy one.
727                         if (track == NULL)
728                         {
729                                 AliHLTMUONMansoTrack* tr = new AliHLTMUONMansoTrack(t.fTrackId);
730                                 event.Add(tr);
731                                 track = tr;
732                         }
733                         
734                         new (singlesDecisions[singlesDecisions.GetEntriesFast()])
735                                 AliHLTMUONDecision::AliTrackDecision(t.fPt, lowPt, highPt, track);
736                 }
737         }
738         
739         UInt_t numUnlikeAnyPt = 0;
740         UInt_t numUnlikeLowPt = 0;
741         UInt_t numUnlikeHighPt = 0;
742         UInt_t numLikeAnyPt = 0;
743         UInt_t numLikeLowPt = 0;
744         UInt_t numLikeHighPt = 0;
745         UInt_t numAnyMass = 0;
746         UInt_t numLowMass = 0;
747         UInt_t numHighMass = 0;
748         TClonesArray pairsDecisions("AliHLTMUONDecision::AliPairDecision");
749         
750         // Find the track pairs decision blocks and add their information.
751         // We just sum the trigger scalars and track pair decisions.
752         for (block = GetFirstInputBlock(AliHLTMUONConstants::PairsDecisionBlockDataType());
753              block != NULL;
754              block = GetNextInputBlock()
755             )
756         {
757                 decisionBlockFound = true;
758                 specification |= block->fSpecification;
759                 AliHLTMUONPairsDecisionBlockReader inblock(block->fPtr, block->fSize);
760                 if (not BlockStructureOk(inblock))
761                 {
762                         if (DumpDataOnError()) DumpEvent(evtData, trigData);
763                         continue;
764                 }
765                 
766                 numUnlikeAnyPt += inblock.BlockHeader().fNunlikeAnyPt;
767                 numUnlikeLowPt += inblock.BlockHeader().fNunlikeLowPt;
768                 numUnlikeHighPt += inblock.BlockHeader().fNunlikeHighPt;
769                 numLikeAnyPt += inblock.BlockHeader().fNlikeAnyPt;
770                 numLikeLowPt += inblock.BlockHeader().fNlikeLowPt;
771                 numLikeHighPt += inblock.BlockHeader().fNlikeHighPt;
772                 numAnyMass += inblock.BlockHeader().fNmassAny;
773                 numLowMass += inblock.BlockHeader().fNmassLow;
774                 numHighMass += inblock.BlockHeader().fNmassHigh;
775                 
776                 for (AliHLTUInt32_t n = 0; n < inblock.Nentries(); n++)
777                 {
778                         const AliHLTMUONPairDecisionStruct& t = inblock[n];
779                         
780                         bool highMass, lowMass, unlike;
781                         AliHLTUInt8_t highPtCount, lowPtCount;
782                         AliHLTMUONUtils::UnpackPairDecisionBits(
783                                         t.fTriggerBits, highMass, lowMass, unlike,
784                                         highPtCount, lowPtCount
785                                 );
786                         
787                         // Try find the corresponding tracks in the 'event'.
788                         const AliHLTMUONMansoTrack* trackA = NULL;
789                         const AliHLTMUONMansoTrack* trackB = NULL;
790                         for (Int_t k = 0; k < event.Array().GetEntriesFast(); k++)
791                         {
792                                 if (event.Array()[k]->IsA() != AliHLTMUONMansoTrack::Class())
793                                         continue;
794                                 const AliHLTMUONMansoTrack* tk =
795                                         static_cast<const AliHLTMUONMansoTrack*>(event.Array()[k]);
796                                 if (tk->Id() == t.fTrackAId) trackA = tk;
797                                 if (tk->Id() == t.fTrackBId) trackB = tk;
798                                 if (trackA != NULL and trackB != NULL) break;
799                         }
800                         
801                         // If either of the tracks was not found then create a dummy one.
802                         if (trackA == NULL)
803                         {
804                                 AliHLTMUONMansoTrack* tr = new AliHLTMUONMansoTrack(t.fTrackAId);
805                                 event.Add(tr);
806                                 trackA = tr;
807                         }
808                         if (trackB == NULL)
809                         {
810                                 AliHLTMUONMansoTrack* tr = new AliHLTMUONMansoTrack(t.fTrackBId);
811                                 event.Add(tr);
812                                 trackB = tr;
813                         }
814                         
815                         new (pairsDecisions[pairsDecisions.GetEntriesFast()])
816                                 AliHLTMUONDecision::AliPairDecision(
817                                         t.fInvMass, lowMass, highMass, unlike,
818                                         lowPtCount, highPtCount, trackA, trackB
819                                 );
820                 }
821         }
822         
823         // Do not add the decision if no decision blocks were found.
824         if (decisionBlockFound)
825         {
826                 AliHLTMUONDecision* triggerDecision = new AliHLTMUONDecision(
827                                 numLowPt, numHighPt, numUnlikeAnyPt, numUnlikeLowPt,
828                                 numUnlikeHighPt, numLikeAnyPt, numLikeLowPt,
829                                 numLikeHighPt, numAnyMass, numLowMass, numHighMass
830                         );
831                 for (Int_t i = 0; i < singlesDecisions.GetEntriesFast(); i++)
832                 {
833                         AliHLTMUONDecision::AliTrackDecision* decision =
834                                 static_cast<AliHLTMUONDecision::AliTrackDecision*>( singlesDecisions[i] );
835                         triggerDecision->AddDecision(decision);
836                 }
837                 for (Int_t j = 0; j < pairsDecisions.GetEntriesFast(); j++)
838                 {
839                         AliHLTMUONDecision::AliPairDecision* decision =
840                                 static_cast<AliHLTMUONDecision::AliPairDecision*>( pairsDecisions[j] );
841                         triggerDecision->AddDecision(decision);
842                 }
843                 
844                 event.Add(triggerDecision);
845         }
846         
847         PushBack(&event, AliHLTMUONConstants::RootifiedEventDataType(), specification);
848         
849         return 0;
850 }
851
852
853 AliHLTMUONMansoTrack* AliHLTMUONRootifierComponent::AddTrack(
854                 AliHLTMUONEvent& event, const AliHLTMUONMansoTrackStruct& track
855         )
856 {
857         // Converts the track structure and adds it to the event object.
858         
859         AliHLTMUONParticleSign sign;
860         bool hitset[4];
861         AliHLTMUONUtils::UnpackMansoTrackFlags(
862                         track.fFlags, sign, hitset
863                 );
864         
865         // Try find the trigger record in 'event'.
866         const AliHLTMUONTriggerRecord* trigrec = NULL;
867         for (Int_t k = 0; k < event.Array().GetEntriesFast(); k++)
868         {
869                 if (event.Array()[k]->IsA() != AliHLTMUONTriggerRecord::Class())
870                         continue;
871                 const AliHLTMUONTriggerRecord* tk =
872                         static_cast<const AliHLTMUONTriggerRecord*>(event.Array()[k]);
873                 if (tk->Id() == track.fTrigRec)
874                 {
875                         trigrec = tk;
876                         break;
877                 }
878         }
879         
880         // Now try find the hits in 'event'.
881         // If they cannot be found then create new ones.
882         const AliHLTMUONRecHit* hit7 = NULL;
883         const AliHLTMUONRecHit* hit8 = NULL;
884         const AliHLTMUONRecHit* hit9 = NULL;
885         const AliHLTMUONRecHit* hit10 = NULL;
886         for (Int_t k = 0; k < event.Array().GetEntriesFast(); k++)
887         {
888                 if (event.Array()[k]->IsA() != AliHLTMUONRecHit::Class())
889                         continue;
890                 const AliHLTMUONRecHit* h =
891                         static_cast<const AliHLTMUONRecHit*>(event.Array()[k]);
892                 
893                 if (hitset[0] and h->X() == track.fHit[0].fX and h->Y() == track.fHit[0].fY
894                         and h->Z() == track.fHit[0].fZ)
895                 {
896                         hit7 = h;
897                 }
898                 if (hitset[1] and h->X() == track.fHit[1].fX and h->Y() == track.fHit[1].fY
899                         and h->Z() == track.fHit[1].fZ)
900                 {
901                         hit8 = h;
902                 }
903                 if (hitset[2] and h->X() == track.fHit[2].fX and h->Y() == track.fHit[2].fY
904                         and h->Z() == track.fHit[2].fZ)
905                 {
906                         hit9 = h;
907                 }
908                 if (hitset[3] and h->X() == track.fHit[3].fX and h->Y() == track.fHit[3].fY
909                         and h->Z() == track.fHit[3].fZ)
910                 {
911                         hit10 = h;
912                 }
913         }
914         AliHLTMUONRecHit* newhit;
915         if (hitset[0] and hit7 == NULL)
916         {
917                 newhit = new AliHLTMUONRecHit(track.fHit[0].fX, track.fHit[0].fY, track.fHit[0].fZ);
918                 event.Add(newhit);
919                 hit7 = newhit;
920         }
921         if (hitset[1] and hit8 == NULL)
922         {
923                 newhit = new AliHLTMUONRecHit(track.fHit[1].fX, track.fHit[1].fY, track.fHit[1].fZ);
924                 event.Add(newhit);
925                 hit8 = newhit;
926         }
927         if (hitset[2] and hit9 == NULL)
928         {
929                 newhit = new AliHLTMUONRecHit(track.fHit[2].fX, track.fHit[2].fY, track.fHit[2].fZ);
930                 event.Add(newhit);
931                 hit9 = newhit;
932         }
933         if (hitset[3] and hit10 == NULL)
934         {
935                 newhit = new AliHLTMUONRecHit(track.fHit[3].fX, track.fHit[3].fY, track.fHit[3].fZ);
936                 event.Add(newhit);
937                 hit10 = newhit;
938         }
939
940         AliHLTMUONMansoTrack* tr = new AliHLTMUONMansoTrack(
941                         track.fId, sign, track.fPx, track.fPy, track.fPz, track.fChi2,
942                         trigrec, hit7, hit8, hit9, hit10
943                 );
944         event.Add(tr);
945         return tr;
946 }