83445e4e35f0b107e6e5a07c26bf60d3bd97f1fe
[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                                 AliESDEvent* esd = reinterpret_cast<AliESDEvent*>(fMessage->ReadObject( fMessage->GetClass() ));
220                                 esd->GetStdContent();
221                                 event.Add(esd);
222                         }
223                         fMessage->Reset();
224                 }
225                 else if (block->fDataType == AliHLTMUONConstants::RecHitsBlockDataType())
226                 {
227                         specification |= block->fSpecification;
228                         AliHLTMUONRecHitsBlockReader inblock(block->fPtr, block->fSize);
229                         if (not BlockStructureOk(inblock))
230                         {
231                                 if (DumpDataOnError()) DumpEvent(evtData, trigData);
232                                 continue;
233                         }
234                         
235                         // Decode the source DDL from the specification bits.
236                         Int_t sourceDDL = -1;
237                         bool ddl[22];
238                         AliHLTMUONUtils::UnpackSpecBits(block->fSpecification, ddl);
239                         for (int k = 0; k < 22; k++)
240                         {
241                                 if (ddl[k])
242                                 {
243                                         if (sourceDDL == -1)
244                                         {
245                                                 sourceDDL = k+1;
246                                         }
247                                         else
248                                         {
249                                                 HLTWarning("The input data block %d contains"
250                                                         " data from multiple DDL sources.", i
251                                                 );
252                                         }
253                                 }
254                         }
255                         if (sourceDDL > 20)
256                         {
257                                 HLTWarning("The source DDL for input data block %d is %d."
258                                         " The expected range for the DDL is [1..20].",
259                                         i, sourceDDL
260                                 );
261                         }
262                         
263                         for (AliHLTUInt32_t n = 0; n < inblock.Nentries(); n++)
264                         {
265                                 const AliHLTMUONRecHitStruct& h = inblock[n];
266                                 AliHLTUInt8_t chamber;
267                                 AliHLTUInt16_t detElemId;
268                                 AliHLTMUONUtils::UnpackRecHitFlags(h.fFlags, chamber, detElemId);
269                                 event.Add(new AliHLTMUONRecHit(h.fX, h.fY, h.fZ, sourceDDL, detElemId));
270                         }
271                 }
272                 else if (block->fDataType == AliHLTMUONConstants::TriggerRecordsBlockDataType())
273                 {
274                         specification |= block->fSpecification;
275                         AliHLTMUONTriggerRecordsBlockReader inblock(block->fPtr, block->fSize);
276                         if (not BlockStructureOk(inblock))
277                         {
278                                 if (DumpDataOnError()) DumpEvent(evtData, trigData);
279                                 continue;
280                         }
281                         
282                         // Decode the source DDL from the specification bits.
283                         Int_t sourceDDL = -1;
284                         bool ddl[22];
285                         AliHLTMUONUtils::UnpackSpecBits(block->fSpecification, ddl);
286                         for (int k = 0; k < 22; k++)
287                         {
288                                 if (ddl[k])
289                                 {
290                                         if (sourceDDL == -1)
291                                         {
292                                                 sourceDDL = k+1;
293                                         }
294                                         else
295                                         {
296                                                 HLTWarning("The input data block %d contains"
297                                                         " data from multiple DDL sources.", i
298                                                 );
299                                         }
300                                 }
301                         }
302                         if (sourceDDL != -1 and (sourceDDL < 21 or sourceDDL > 22))
303                         {
304                                 HLTWarning("The source DDL for input data block %d is %d."
305                                         " The expected range for the DDL is [21..22].",
306                                         i, sourceDDL
307                                 );
308                         }
309                         
310                         for (AliHLTUInt32_t n = 0; n < inblock.Nentries(); n++)
311                         {
312                                 const AliHLTMUONTriggerRecordStruct& t = inblock[n];
313                                 
314                                 AliHLTMUONParticleSign sign;
315                                 bool hitset[4];
316                                 AliHLTMUONUtils::UnpackTriggerRecordFlags(
317                                                 t.fFlags, sign, hitset
318                                         );
319                         
320                                 AliHLTMUONTriggerRecord* tr = new AliHLTMUONTriggerRecord(
321                                                 t.fId, sign, t.fPx, t.fPy, t.fPz, sourceDDL
322                                         );
323                                 for (int k = 0; k < 4; k++)
324                                 {
325                                         if (not hitset[k]) continue;
326                                         Int_t detElemId = AliHLTMUONUtils::GetDetElemIdFromFlags(t.fHit[k].fFlags);
327                                         tr->SetHit(k+11, t.fHit[k].fX, t.fHit[k].fY, t.fHit[k].fZ, detElemId);
328                                 }
329                                 event.Add(tr);
330                                 triggerMap[t.fId] = tr;
331                         }
332                 }
333                 else
334                 {
335                         if (block->fDataType != AliHLTMUONConstants::TrigRecsDebugBlockDataType() and
336                             block->fDataType != AliHLTMUONConstants::ClusterBlockDataType() and
337                             block->fDataType != AliHLTMUONConstants::ChannelBlockDataType() and
338                             block->fDataType != AliHLTMUONConstants::MansoTracksBlockDataType() and
339                             block->fDataType != AliHLTMUONConstants::MansoCandidatesBlockDataType() and
340                             block->fDataType != AliHLTMUONConstants::SinglesDecisionBlockDataType() and
341                             block->fDataType != AliHLTMUONConstants::PairsDecisionBlockDataType()
342                            )
343                         {
344                                 // Log a message indicating that we got a data block that we
345                                 // do not know how to handle.
346                                 if (fWarnForUnexpecedBlock)
347                                         HLTWarning("Received a data block of a type we cannot handle: '%s', spec: 0x%X",
348                                                 DataType2Text(block->fDataType).c_str(), block->fSpecification
349                                         );
350 #ifdef __DEBUG
351                                 else
352                                         HLTDebug("Received a data block of a type we cannot handle: '%s', spec: 0x%X",
353                                                 DataType2Text(block->fDataType).c_str(), block->fSpecification
354                                         );
355 #endif
356                         }
357                 }
358         }
359         
360         // We need to check if there are any trigger record debug data blocks
361         // and add their information to the AliHLTMUONTriggerRecord objects.
362         for (block = GetFirstInputBlock(AliHLTMUONConstants::TrigRecsDebugBlockDataType());
363              block != NULL;
364              block = GetNextInputBlock()
365             )
366         {
367                 specification |= block->fSpecification;
368                 AliHLTMUONTrigRecsDebugBlockReader inblock(block->fPtr, block->fSize);
369                 if (not BlockStructureOk(inblock))
370                 {
371                         if (DumpDataOnError()) DumpEvent(evtData, trigData);
372                         continue;
373                 }
374                 
375                 for (AliHLTUInt32_t n = 0; n < inblock.Nentries(); n++)
376                 {
377                         const AliHLTMUONTrigRecInfoStruct& triginfo = inblock[n];
378                         
379                         AliHLTMUONTriggerRecord* trigrec = triggerMap[triginfo.fTrigRecId];
380                         if (trigrec == NULL)
381                         {
382                                 // Decode the source DDL from the specification bits.
383                                 Int_t sourceDDL = -1;
384                                 bool ddl[22];
385                                 AliHLTMUONUtils::UnpackSpecBits(block->fSpecification, ddl);
386                                 for (int k = 0; k < 22; k++)
387                                 {
388                                         if (ddl[k])
389                                         {
390                                                 if (sourceDDL == -1)
391                                                 {
392                                                         sourceDDL = k+1;
393                                                 }
394                                                 else
395                                                 {
396                                                         HLTWarning("An trigger debug information data block"
397                                                                 " contains data from multiple DDL sources."
398                                                         );
399                                                 }
400                                         }
401                                 }
402                                 if (sourceDDL != -1 and (sourceDDL < 21 or sourceDDL > 22))
403                                 {
404                                         HLTWarning("The source DDL for a trigger debug information data"
405                                                 " block is %d. The expected range for the DDL is [21..22].",
406                                                 sourceDDL
407                                         );
408                                 }
409                                 
410                                 // Add an new empty trigger record since none was found.
411                                 trigrec = new AliHLTMUONTriggerRecord(
412                                                 0, 0, 0, 0, 0, sourceDDL
413                                         );
414                                 triggerMap[triginfo.fTrigRecId] = trigrec;
415                                 event.Add(trigrec);
416                         }
417                         else
418                         {
419                                 for (Int_t j = 0; j < 4; ++j)
420                                 {
421                                         if (trigrec->DetElemId(j+11) != -1 and triginfo.fDetElemId[j] != trigrec->DetElemId(j+11))
422                                         {
423                                                 HLTWarning("Found a trigger record with a hit on chamber %d with a different"
424                                                         " detector element ID %d than the debug information %d.",
425                                                         j, trigrec->DetElemId(j+11), triginfo.fDetElemId[j]
426                                                 );
427                                         }
428                                 }
429                         }
430                         
431                         typedef AliMUONTriggerDDLDecoderEventHandler Handler;
432                         
433                         trigrec->SetDebugInfo(triginfo.fZmiddle, triginfo.fBl);
434                         
435                         UShort_t patternX[4][3] = {
436                                 {
437                                         Handler::GetLocalX1(&triginfo.fL0StructPrev),
438                                         Handler::GetLocalX1(&triginfo.fL0Struct),
439                                         Handler::GetLocalX1(&triginfo.fL0StructNext)
440                                 },{
441                                         Handler::GetLocalX2(&triginfo.fL0StructPrev),
442                                         Handler::GetLocalX2(&triginfo.fL0Struct),
443                                         Handler::GetLocalX2(&triginfo.fL0StructNext)
444                                 },{
445                                         Handler::GetLocalX3(&triginfo.fL0StructPrev),
446                                         Handler::GetLocalX3(&triginfo.fL0Struct),
447                                         Handler::GetLocalX3(&triginfo.fL0StructNext)
448                                 },{
449                                         Handler::GetLocalX4(&triginfo.fL0StructPrev),
450                                         Handler::GetLocalX4(&triginfo.fL0Struct),
451                                         Handler::GetLocalX4(&triginfo.fL0StructNext)
452                                 }
453                         };
454                         UShort_t patternY[4][3] = {
455                                 {
456                                         Handler::GetLocalY1(&triginfo.fL0StructPrev),
457                                         Handler::GetLocalY1(&triginfo.fL0Struct),
458                                         Handler::GetLocalY1(&triginfo.fL0StructNext)
459                                 },{
460                                         Handler::GetLocalY2(&triginfo.fL0StructPrev),
461                                         Handler::GetLocalY2(&triginfo.fL0Struct),
462                                         Handler::GetLocalY2(&triginfo.fL0StructNext)
463                                 },{
464                                         Handler::GetLocalY3(&triginfo.fL0StructPrev),
465                                         Handler::GetLocalY3(&triginfo.fL0Struct),
466                                         Handler::GetLocalY3(&triginfo.fL0StructNext)
467                                 },{
468                                         Handler::GetLocalY4(&triginfo.fL0StructPrev),
469                                         Handler::GetLocalY4(&triginfo.fL0Struct),
470                                         Handler::GetLocalY4(&triginfo.fL0StructNext)
471                                 }
472                         };
473                         
474                         for (Int_t j = 0; j < 4; ++j)
475                         {
476                                 trigrec->SetHitDebugInfo(j+11, patternX[j], patternY[j]);
477                         }
478                 }
479         }
480         
481         std::map<AliHLTInt32_t, AliHLTMUONRecHit*> clusterMap;
482         
483         // We need to check if there are any cluster data blocks and add their
484         // information to the AliHLTMUONRecHit objects.
485         for (block = GetFirstInputBlock(AliHLTMUONConstants::ClusterBlockDataType());
486              block != NULL;
487              block = GetNextInputBlock()
488             )
489         {
490                 specification |= block->fSpecification;
491                 AliHLTMUONClustersBlockReader inblock(block->fPtr, block->fSize);
492                 if (not BlockStructureOk(inblock))
493                 {
494                         if (DumpDataOnError()) DumpEvent(evtData, trigData);
495                         continue;
496                 }
497                 
498                 for (AliHLTUInt32_t n = 0; n < inblock.Nentries(); n++)
499                 {
500                         const AliHLTMUONClusterStruct& clust = inblock[n];
501                         
502                         AliHLTUInt8_t chamber;
503                         AliHLTUInt16_t detElemId;
504                         AliHLTMUONUtils::UnpackRecHitFlags(clust.fHit.fFlags, chamber, detElemId);
505                         if (clust.fDetElemId != detElemId)
506                         {
507                                 HLTWarning("Found a cluster with a different detector element ID (%d)"
508                                         " from its corresponding hit (x,y,z = %f,%f,%f and detElemId = %d).",
509                                         clust.fDetElemId,
510                                         clust.fHit.fX, clust.fHit.fY, clust.fHit.fZ,
511                                         detElemId
512                                 );
513                         }
514                         
515                         // Try find the corresponding reconstructed hit in 'event'.
516                         AliHLTMUONRecHit* hit = NULL;
517                         for (Int_t k = 0; k < event.Array().GetEntriesFast(); k++)
518                         {
519                                 if (event.Array()[k]->IsA() != AliHLTMUONRecHit::Class())
520                                         continue;
521                                 AliHLTMUONRecHit* h = static_cast<AliHLTMUONRecHit*>(event.Array()[k]);
522                                 if (h->DetElemId() == detElemId and h->X() == clust.fHit.fX
523                                     and h->Y() == clust.fHit.fY and h->Z() == clust.fHit.fZ)
524                                 {
525                                         hit = h;
526                                         break;
527                                 }
528                         }
529                         
530                         // If we could not find the corresponding hit then we need to create
531                         // a new hit object, otherwise we can just append the information.
532                         if (hit == NULL)
533                         {
534                                 // Decode the source DDL from the specification bits.
535                                 Int_t sourceDDL = -1;
536                                 bool ddl[22];
537                                 AliHLTMUONUtils::UnpackSpecBits(block->fSpecification, ddl);
538                                 for (int k = 0; k < 22; k++)
539                                 {
540                                         if (ddl[k])
541                                         {
542                                                 if (sourceDDL == -1)
543                                                 {
544                                                         sourceDDL = k+1;
545                                                 }
546                                                 else
547                                                 {
548                                                         HLTWarning("An input block of cluster data contains"
549                                                                 " data from multiple DDL sources."
550                                                         );
551                                                 }
552                                         }
553                                 }
554                                 if (sourceDDL > 20)
555                                 {
556                                         HLTWarning("The source DDL of a cluster data input block is %d."
557                                                 " The expected range for the DDL is [1..20].",
558                                                 sourceDDL
559                                         );
560                                 }
561                                 hit = new AliHLTMUONRecHit(
562                                                 clust.fHit.fX, clust.fHit.fY, clust.fHit.fZ,
563                                                 sourceDDL, detElemId
564                                         );
565                                 event.Add(hit);
566                         }
567                         else
568                         {
569                                 hit->SetDebugInfo(
570                                                   detElemId, clust.fId,
571                                                   clust.fNchannelsB, clust.fNchannelsNB,
572                                                   clust.fChargeB, clust.fChargeNB,
573                                                   hit->SourceDDL()
574                                 );
575                         }
576                         
577                         clusterMap[clust.fId] = hit;
578                 }
579         }
580         
581         // We need to check if there are any channel data blocks and add their
582         // information to the AliHLTMUONRecHit objects.
583         for (block = GetFirstInputBlock(AliHLTMUONConstants::ChannelBlockDataType());
584              block != NULL;
585              block = GetNextInputBlock()
586             )
587         {
588                 specification |= block->fSpecification;
589                 AliHLTMUONChannelsBlockReader inblock(block->fPtr, block->fSize);
590                 if (not BlockStructureOk(inblock))
591                 {
592                         if (DumpDataOnError()) DumpEvent(evtData, trigData);
593                         continue;
594                 }
595                 
596                 for (AliHLTUInt32_t n = 0; n < inblock.Nentries(); n++)
597                 {
598                         const AliHLTMUONChannelStruct& channel = inblock[n];
599                         
600                         AliHLTMUONRecHit* hit = clusterMap[channel.fClusterId];
601                         if (hit == NULL)
602                         {
603                                 // Decode the source DDL from the specification bits.
604                                 Int_t sourceDDL = -1;
605                                 bool ddl[22];
606                                 AliHLTMUONUtils::UnpackSpecBits(block->fSpecification, ddl);
607                                 for (int k = 0; k < 22; k++)
608                                 {
609                                         if (ddl[k])
610                                         {
611                                                 if (sourceDDL == -1)
612                                                 {
613                                                         sourceDDL = k+1;
614                                                 }
615                                                 else
616                                                 {
617                                                         HLTWarning("An input block of cluster data contains"
618                                                                 " data from multiple DDL sources."
619                                                         );
620                                                 }
621                                         }
622                                 }
623                                 if (sourceDDL > 20)
624                                 {
625                                         HLTWarning("The source DDL of a cluster data input block is %d."
626                                                 " The expected range for the DDL is [1..20].",
627                                                 sourceDDL
628                                         );
629                                 }
630                                 hit = new AliHLTMUONRecHit(0, 0, 0, sourceDDL, -1);
631                                 event.Add(hit);
632                         }
633                         
634                         hit->AddChannel(
635                                         channel.fBusPatch, channel.fManu,
636                                         channel.fChannelAddress, channel.fSignal,
637                                         channel.fRawDataWord
638                                 );
639                 }
640         }
641         
642         // Now we can look for tracks to add. We needed the ROOT trigger records
643         // and reco hits created before we can create track objects.
644         
645         std::map<AliHLTInt32_t, AliHLTMUONTrack*> trackMap;
646         
647         for (block = GetFirstInputBlock(AliHLTMUONConstants::TracksBlockDataType());
648              block != NULL;
649              block = GetNextInputBlock()
650             )
651         {
652                 specification |= block->fSpecification;
653                 AliHLTMUONTracksBlockReader inblock(block->fPtr, block->fSize);
654                 if (not BlockStructureOk(inblock))
655                 {
656                         if (DumpDataOnError()) DumpEvent(evtData, trigData);
657                         continue;
658                 }
659                 
660                 for (AliHLTUInt32_t n = 0; n < inblock.Nentries(); n++)
661                 {
662                         const AliHLTMUONTrackStruct& t = inblock[n];
663                         trackMap[t.fId] = AddTrack(event, t);
664                 }
665         }
666
667         std::map<AliHLTInt32_t, AliHLTMUONMansoTrack*> mansoTrackMap;
668         
669         for (block = GetFirstInputBlock(AliHLTMUONConstants::MansoTracksBlockDataType());
670              block != NULL;
671              block = GetNextInputBlock()
672             )
673         {
674                 specification |= block->fSpecification;
675                 AliHLTMUONMansoTracksBlockReader inblock(block->fPtr, block->fSize);
676                 if (not BlockStructureOk(inblock))
677                 {
678                         if (DumpDataOnError()) DumpEvent(evtData, trigData);
679                         continue;
680                 }
681                 
682                 for (AliHLTUInt32_t n = 0; n < inblock.Nentries(); n++)
683                 {
684                         const AliHLTMUONMansoTrackStruct& t = inblock[n];
685                         mansoTrackMap[t.fId] = AddTrack(event, t);
686                 }
687         }
688         
689         // Look for Manso track candidates to add the debug info to the tracks.
690         for (block = GetFirstInputBlock(AliHLTMUONConstants::MansoCandidatesBlockDataType());
691              block != NULL;
692              block = GetNextInputBlock()
693             )
694         {
695                 specification |= block->fSpecification;
696                 AliHLTMUONMansoCandidatesBlockReader inblock(block->fPtr, block->fSize);
697                 if (not BlockStructureOk(inblock))
698                 {
699                         if (DumpDataOnError()) DumpEvent(evtData, trigData);
700                         continue;
701                 }
702                 
703                 for (AliHLTUInt32_t n = 0; n < inblock.Nentries(); n++)
704                 {
705                         const AliHLTMUONMansoCandidateStruct& tc = inblock[n];
706                         AliHLTMUONMansoTrack* mtrack = mansoTrackMap[tc.fTrack.fId];
707                         if (mtrack == NULL)
708                         {
709                                 // If we got here then we could not find the corresponding Manso
710                                 // track. So we need to create and add a new track object.
711                                 mtrack = AddTrack(event, tc.fTrack);
712                         }
713                         mtrack->SetDebugData(tc.fZmiddle, tc.fBl);
714                         for (AliHLTUInt32_t i = 0; i < 4; ++i)
715                         {
716                                 if (tc.fRoI[i] == AliHLTMUONConstants::NilMansoRoIStruct()) continue;
717                                 mtrack->SetRoI(i+7, tc.fRoI[i].fX, tc.fRoI[i].fY, tc.fRoI[i].fZ, tc.fRoI[i].fRadius);
718                         }
719                 }
720         }
721         
722         bool decisionBlockFound = false;
723         UInt_t numLowPt = 0;
724         UInt_t numHighPt = 0;
725         TClonesArray singlesDecisions("AliHLTMUONDecision::AliTrackDecision");
726         
727         // Find the single tracks decision blocks and add their information.
728         // We just sum the trigger scalars and single decisions.
729         for (block = GetFirstInputBlock(AliHLTMUONConstants::SinglesDecisionBlockDataType());
730              block != NULL;
731              block = GetNextInputBlock()
732             )
733         {
734                 decisionBlockFound = true;
735                 specification |= block->fSpecification;
736                 AliHLTMUONSinglesDecisionBlockReader inblock(block->fPtr, block->fSize);
737                 if (not BlockStructureOk(inblock))
738                 {
739                         if (DumpDataOnError()) DumpEvent(evtData, trigData);
740                         continue;
741                 }
742                 
743                 numLowPt += inblock.BlockHeader().fNlowPt;
744                 numHighPt += inblock.BlockHeader().fNhighPt;
745                 
746                 for (AliHLTUInt32_t n = 0; n < inblock.Nentries(); n++)
747                 {
748                         const AliHLTMUONTrackDecisionStruct& t = inblock[n];
749                         
750                         bool highPt, lowPt;
751                         AliHLTMUONUtils::UnpackTrackDecisionBits(t.fTriggerBits, highPt, lowPt);
752                         
753                         // Try find the corresponding track.
754                         const TObject* track = trackMap[t.fTrackId];
755                         if (track == NULL) track = mansoTrackMap[t.fTrackId];
756                         
757                         // If the track was not found then create a dummy one.
758                         if (track == NULL)
759                         {
760                                 AliHLTMUONMansoTrack* tr = new AliHLTMUONMansoTrack(t.fTrackId);
761                                 event.Add(tr);
762                                 track = tr;
763                                 mansoTrackMap[t.fTrackId] = tr;
764                         }
765                         
766                         new (singlesDecisions[singlesDecisions.GetEntriesFast()])
767                                 AliHLTMUONDecision::AliTrackDecision(t.fPt, lowPt, highPt, track);
768                 }
769         }
770         
771         UInt_t numUnlikeAnyPt = 0;
772         UInt_t numUnlikeLowPt = 0;
773         UInt_t numUnlikeHighPt = 0;
774         UInt_t numLikeAnyPt = 0;
775         UInt_t numLikeLowPt = 0;
776         UInt_t numLikeHighPt = 0;
777         UInt_t numAnyMass = 0;
778         UInt_t numLowMass = 0;
779         UInt_t numHighMass = 0;
780         TClonesArray pairsDecisions("AliHLTMUONDecision::AliPairDecision");
781         
782         // Find the track pairs decision blocks and add their information.
783         // We just sum the trigger scalars and track pair decisions.
784         for (block = GetFirstInputBlock(AliHLTMUONConstants::PairsDecisionBlockDataType());
785              block != NULL;
786              block = GetNextInputBlock()
787             )
788         {
789                 decisionBlockFound = true;
790                 specification |= block->fSpecification;
791                 AliHLTMUONPairsDecisionBlockReader inblock(block->fPtr, block->fSize);
792                 if (not BlockStructureOk(inblock))
793                 {
794                         if (DumpDataOnError()) DumpEvent(evtData, trigData);
795                         continue;
796                 }
797                 
798                 numUnlikeAnyPt += inblock.BlockHeader().fNunlikeAnyPt;
799                 numUnlikeLowPt += inblock.BlockHeader().fNunlikeLowPt;
800                 numUnlikeHighPt += inblock.BlockHeader().fNunlikeHighPt;
801                 numLikeAnyPt += inblock.BlockHeader().fNlikeAnyPt;
802                 numLikeLowPt += inblock.BlockHeader().fNlikeLowPt;
803                 numLikeHighPt += inblock.BlockHeader().fNlikeHighPt;
804                 numAnyMass += inblock.BlockHeader().fNmassAny;
805                 numLowMass += inblock.BlockHeader().fNmassLow;
806                 numHighMass += inblock.BlockHeader().fNmassHigh;
807                 
808                 for (AliHLTUInt32_t n = 0; n < inblock.Nentries(); n++)
809                 {
810                         const AliHLTMUONPairDecisionStruct& t = inblock[n];
811                         
812                         bool highMass, lowMass, unlike;
813                         AliHLTUInt8_t highPtCount, lowPtCount;
814                         AliHLTMUONUtils::UnpackPairDecisionBits(
815                                         t.fTriggerBits, highMass, lowMass, unlike,
816                                         highPtCount, lowPtCount
817                                 );
818                         
819                         // Try find the corresponding tracks.
820                         const TObject* trackA = trackMap[t.fTrackAId];
821                         if (trackA == NULL) trackA = mansoTrackMap[t.fTrackAId];
822                         const TObject* trackB = trackMap[t.fTrackBId];
823                         if (trackB == NULL) trackB = mansoTrackMap[t.fTrackBId];
824                         
825                         // If either of the tracks was not found then create a dummy one.
826                         if (trackA == NULL)
827                         {
828                                 AliHLTMUONMansoTrack* tr = new AliHLTMUONMansoTrack(t.fTrackAId);
829                                 event.Add(tr);
830                                 trackA = tr;
831                                 mansoTrackMap[t.fTrackAId] = tr;
832                         }
833                         if (trackB == NULL)
834                         {
835                                 AliHLTMUONMansoTrack* tr = new AliHLTMUONMansoTrack(t.fTrackBId);
836                                 event.Add(tr);
837                                 trackB = tr;
838                                 mansoTrackMap[t.fTrackBId] = tr;
839                         }
840                         
841                         new (pairsDecisions[pairsDecisions.GetEntriesFast()])
842                                 AliHLTMUONDecision::AliPairDecision(
843                                         t.fInvMass, lowMass, highMass, unlike,
844                                         lowPtCount, highPtCount, trackA, trackB
845                                 );
846                 }
847         }
848         
849         // Do not add the decision if no decision blocks were found.
850         if (decisionBlockFound)
851         {
852                 AliHLTMUONDecision* triggerDecision = new AliHLTMUONDecision(
853                                 numLowPt, numHighPt, numUnlikeAnyPt, numUnlikeLowPt,
854                                 numUnlikeHighPt, numLikeAnyPt, numLikeLowPt,
855                                 numLikeHighPt, numAnyMass, numLowMass, numHighMass
856                         );
857                 for (Int_t i = 0; i < singlesDecisions.GetEntriesFast(); i++)
858                 {
859                         AliHLTMUONDecision::AliTrackDecision* decision =
860                                 static_cast<AliHLTMUONDecision::AliTrackDecision*>( singlesDecisions[i] );
861                         triggerDecision->AddDecision(decision);
862                 }
863                 for (Int_t j = 0; j < pairsDecisions.GetEntriesFast(); j++)
864                 {
865                         AliHLTMUONDecision::AliPairDecision* decision =
866                                 static_cast<AliHLTMUONDecision::AliPairDecision*>( pairsDecisions[j] );
867                         triggerDecision->AddDecision(decision);
868                 }
869                 
870                 event.Add(triggerDecision);
871         }
872         
873         PushBack(&event, AliHLTMUONConstants::RootifiedEventDataType(), specification);
874         
875         return 0;
876 }
877
878
879 AliHLTMUONMansoTrack* AliHLTMUONRootifierComponent::AddTrack(
880                 AliHLTMUONEvent& event, const AliHLTMUONMansoTrackStruct& track
881         )
882 {
883         // Converts the track structure and adds it to the event object.
884         
885         AliHLTMUONParticleSign sign;
886         bool hitset[4];
887         AliHLTMUONUtils::UnpackMansoTrackFlags(
888                         track.fFlags, sign, hitset
889                 );
890         
891         // Try find the trigger record in 'event'.
892         const AliHLTMUONTriggerRecord* trigrec = NULL;
893         for (Int_t k = 0; k < event.Array().GetEntriesFast(); k++)
894         {
895                 if (event.Array()[k]->IsA() != AliHLTMUONTriggerRecord::Class())
896                         continue;
897                 const AliHLTMUONTriggerRecord* tk =
898                         static_cast<const AliHLTMUONTriggerRecord*>(event.Array()[k]);
899                 if (tk->Id() == track.fTrigRec)
900                 {
901                         trigrec = tk;
902                         break;
903                 }
904         }
905         
906         // Now try find the hits in 'event'.
907         // If they cannot be found then create new ones.
908         const AliHLTMUONRecHit* hit7 = NULL;
909         const AliHLTMUONRecHit* hit8 = NULL;
910         const AliHLTMUONRecHit* hit9 = NULL;
911         const AliHLTMUONRecHit* hit10 = NULL;
912         for (Int_t k = 0; k < event.Array().GetEntriesFast(); k++)
913         {
914                 if (event.Array()[k]->IsA() != AliHLTMUONRecHit::Class())
915                         continue;
916                 const AliHLTMUONRecHit* h =
917                         static_cast<const AliHLTMUONRecHit*>(event.Array()[k]);
918                 
919                 if (hitset[0] and h->X() == track.fHit[0].fX and h->Y() == track.fHit[0].fY
920                         and h->Z() == track.fHit[0].fZ)
921                 {
922                         hit7 = h;
923                 }
924                 if (hitset[1] and h->X() == track.fHit[1].fX and h->Y() == track.fHit[1].fY
925                         and h->Z() == track.fHit[1].fZ)
926                 {
927                         hit8 = h;
928                 }
929                 if (hitset[2] and h->X() == track.fHit[2].fX and h->Y() == track.fHit[2].fY
930                         and h->Z() == track.fHit[2].fZ)
931                 {
932                         hit9 = h;
933                 }
934                 if (hitset[3] and h->X() == track.fHit[3].fX and h->Y() == track.fHit[3].fY
935                         and h->Z() == track.fHit[3].fZ)
936                 {
937                         hit10 = h;
938                 }
939         }
940         AliHLTMUONRecHit* newhit;
941         if (hitset[0] and hit7 == NULL)
942         {
943                 newhit = new AliHLTMUONRecHit(track.fHit[0].fX, track.fHit[0].fY, track.fHit[0].fZ);
944                 event.Add(newhit);
945                 hit7 = newhit;
946         }
947         if (hitset[1] and hit8 == NULL)
948         {
949                 newhit = new AliHLTMUONRecHit(track.fHit[1].fX, track.fHit[1].fY, track.fHit[1].fZ);
950                 event.Add(newhit);
951                 hit8 = newhit;
952         }
953         if (hitset[2] and hit9 == NULL)
954         {
955                 newhit = new AliHLTMUONRecHit(track.fHit[2].fX, track.fHit[2].fY, track.fHit[2].fZ);
956                 event.Add(newhit);
957                 hit9 = newhit;
958         }
959         if (hitset[3] and hit10 == NULL)
960         {
961                 newhit = new AliHLTMUONRecHit(track.fHit[3].fX, track.fHit[3].fY, track.fHit[3].fZ);
962                 event.Add(newhit);
963                 hit10 = newhit;
964         }
965
966         AliHLTMUONMansoTrack* tr = new AliHLTMUONMansoTrack(
967                         track.fId, sign, track.fPx, track.fPy, track.fPz, track.fChi2,
968                         trigrec, hit7, hit8, hit9, hit10
969                 );
970         event.Add(tr);
971         return tr;
972 }
973
974
975 AliHLTMUONTrack* AliHLTMUONRootifierComponent::AddTrack(
976                 AliHLTMUONEvent& event, const AliHLTMUONTrackStruct& track
977         )
978 {
979         // Converts the track structure and adds it to the event object.
980         
981         AliHLTMUONParticleSign sign;
982         bool hitset[16];
983         AliHLTMUONUtils::UnpackTrackFlags(
984                         track.fFlags, sign, hitset
985                 );
986         
987         // Try find the trigger record in 'event'.
988         const AliHLTMUONTriggerRecord* trigrec = NULL;
989         for (Int_t k = 0; k < event.Array().GetEntriesFast(); k++)
990         {
991                 if (event.Array()[k]->IsA() != AliHLTMUONTriggerRecord::Class())
992                         continue;
993                 const AliHLTMUONTriggerRecord* tk =
994                         static_cast<const AliHLTMUONTriggerRecord*>(event.Array()[k]);
995                 if (tk->Id() == track.fTrigRec)
996                 {
997                         trigrec = tk;
998                         break;
999                 }
1000         }
1001         
1002         // Now try find the hits in 'event'.
1003         // If they cannot be found then create new ones.
1004         const AliHLTMUONRecHit* hits[16];
1005         for (int i = 0; i < 16; ++i) hits[i] = NULL;
1006         for (Int_t k = 0; k < event.Array().GetEntriesFast(); k++)
1007         {
1008                 if (event.Array()[k]->IsA() != AliHLTMUONRecHit::Class())
1009                         continue;
1010                 const AliHLTMUONRecHit* h =
1011                         static_cast<const AliHLTMUONRecHit*>(event.Array()[k]);
1012                 for (int i = 0; i < 16; ++i)
1013                 {
1014                         if (hitset[i] and h->X() == track.fHit[i].fX and h->Y() == track.fHit[i].fY
1015                             and h->Z() == track.fHit[i].fZ)
1016                         {
1017                                 hits[i] = h;
1018                         }
1019                 }
1020         }
1021         AliHLTMUONRecHit* newhit;
1022         for (int i = 0; i < 16; ++i)
1023         {
1024                 if (hitset[i] and hits[i] == NULL)
1025                 {
1026                         newhit = new AliHLTMUONRecHit(track.fHit[i].fX, track.fHit[i].fY, track.fHit[i].fZ);
1027                         event.Add(newhit);
1028                         hits[i] = newhit;
1029                 }
1030         }
1031
1032         AliHLTMUONTrack* tr = new AliHLTMUONTrack(
1033                         track.fId, sign, track.fPx, track.fPy, track.fPz,
1034                         track.fInverseBendingMomentum, track.fThetaX, track.fThetaY,
1035                         track.fX, track.fY, track.fZ, track.fChi2,
1036                         trigrec, hits
1037                 );
1038         event.Add(tr);
1039         return tr;
1040 }