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