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