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