]> git.uio.no Git - u/mrichter/AliRoot.git/blob - HLT/MUON/OnlineAnalysis/AliHLTMUONMansoTrackerFSMComponent.cxx
Merge remote-tracking branch 'origin/flatdev' into mergeFlat2Master
[u/mrichter/AliRoot.git] / HLT / MUON / OnlineAnalysis / AliHLTMUONMansoTrackerFSMComponent.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  *   Indranil Das <indra.das@saha.ac.in>                                  *
8  *                                                                        *
9  * Permission to use, copy, modify and distribute this software and its   *
10  * documentation strictly for non-commercial purposes is hereby granted   *
11  * without fee, provided that the above copyright notice appears in all   *
12  * copies and that both the copyright notice and this permission notice   *
13  * appear in the supporting documentation. The authors make no claims     *
14  * about the suitability of this software for any purpose. It is          *
15  * provided "as is" without express or implied warranty.                  *
16  **************************************************************************/
17
18 // $Id$
19
20 ///
21 ///  @file   AliHLTMUONMansoTrackerFSMComponent.cxx
22 ///  @author Artur Szostak <artursz@iafrica.com>,
23 ///          Indranil Das <indra.das@saha.ac.in>
24 ///  @date   18 Sep 2007
25 ///  @brief  Implementation of AliHLTMUONMansoTrackerFSMComponent class.
26 ///
27
28 #include "AliHLTMUONMansoTrackerFSMComponent.h"
29 #include "AliHLTMUONConstants.h"
30 #include "AliHLTMUONCalculations.h"
31 #include "AliHLTMUONUtils.h"
32 #include "AliHLTMUONMansoTrackerFSM.h"
33 #include "AliHLTMUONDataBlockReader.h"
34 #include "AliHLTMUONDataBlockWriter.h"
35 #include <cstdlib>
36 #include <cstring>
37 #include <cerrno>
38 #include <new>
39
40 ClassImp(AliHLTMUONMansoTrackerFSMComponent);
41
42
43 AliHLTMUONMansoTrackerFSMComponent::AliHLTMUONMansoTrackerFSMComponent() :
44         AliHLTMUONProcessor(),
45         AliHLTMUONMansoTrackerFSMCallback(),
46         fTracker(NULL),
47         fTrackCount(0),
48         fBlock(NULL),
49         fRecHitBlockArraySize(0),
50         fWarnForUnexpecedBlock(false),
51         fCanLoadZmiddle(true),
52         fCanLoadBL(true)
53 {
54         ///
55         /// Default constructor.
56         ///
57         
58         for (int i = 0; i < 4; i++)
59         {
60                 fRecHitBlockCount[i] = 0;
61                 fRecHitBlock[i] = NULL;
62         }
63         
64         ResetCanLoadFlags();
65 }
66
67
68 AliHLTMUONMansoTrackerFSMComponent::~AliHLTMUONMansoTrackerFSMComponent()
69 {
70         ///
71         /// Default destructor.
72         ///
73         
74         // Should never have the following 2 pointers non-NULL since DoDeinit
75         // should have been called before, but handle this case anyway.
76         if (fTracker != NULL) delete fTracker;
77         
78         // Remember that only fRecHitBlock[0] stores the pointer to the allocated
79         // memory. The other pointers are just reletive to this.
80         if (fRecHitBlock[0] != NULL) delete [] fRecHitBlock[0];
81 }
82
83
84 const char* AliHLTMUONMansoTrackerFSMComponent::GetComponentID()
85 {
86         ///
87         /// Inherited from AliHLTComponent. Returns the component ID.
88         ///
89         
90         return AliHLTMUONConstants::MansoTrackerFSMId();
91 }
92
93
94 void AliHLTMUONMansoTrackerFSMComponent::GetInputDataTypes(
95                 AliHLTComponentDataTypeList& list
96         )
97 {
98         ///
99         /// Inherited from AliHLTProcessor. Returns the list of expected input data types.
100         ///
101         
102         assert( list.empty() );
103         list.push_back( AliHLTMUONConstants::TriggerRecordsBlockDataType() );
104         list.push_back( AliHLTMUONConstants::RecHitsBlockDataType() );
105 }
106
107
108 AliHLTComponentDataType AliHLTMUONMansoTrackerFSMComponent::GetOutputDataType()
109 {
110         ///
111         /// Inherited from AliHLTComponent. Returns the output data type.
112         ///
113         
114         return kAliHLTMultipleDataType;
115 }
116
117
118 int AliHLTMUONMansoTrackerFSMComponent::GetOutputDataTypes(AliHLTComponentDataTypeList& list)
119 {
120         /// Inherited from AliHLTComponent. Returns the output data types.
121         
122         assert( list.empty() );
123         list.push_back( AliHLTMUONConstants::MansoTracksBlockDataType() );
124         list.push_back( AliHLTMUONConstants::MansoCandidatesBlockDataType() );
125         return list.size();
126 }
127
128
129 void AliHLTMUONMansoTrackerFSMComponent::GetOutputDataSize(
130                 unsigned long& constBase, double& inputMultiplier
131         )
132 {
133         ///
134         /// Inherited from AliHLTComponent. Returns an estimate of the expected output data size.
135         ///
136         
137         constBase = sizeof(AliHLTMUONMansoTracksBlockStruct) + 1024*1024;
138         inputMultiplier = 1;
139 }
140
141
142 AliHLTComponent* AliHLTMUONMansoTrackerFSMComponent::Spawn()
143 {
144         ///
145         /// Inherited from AliHLTComponent. Creates a new object instance.
146         ///
147         
148         return new AliHLTMUONMansoTrackerFSMComponent;
149 }
150
151
152 int AliHLTMUONMansoTrackerFSMComponent::DoInit(int argc, const char** argv)
153 {
154         ///
155         /// Inherited from AliHLTComponent.
156         /// Parses the command line parameters and initialises the component.
157         ///
158         
159         HLTInfo("Initialising dHLT manso tracker FSM component.");
160         
161         // Inherit the parents functionality.
162         int result = AliHLTMUONProcessor::DoInit(argc, argv);
163         if (result != 0) return result;
164
165         // Just in case for whatever reason we still have some of the internal
166         // object allocated previously still hanging around delete them now.
167         FreeMemory();
168         
169         fWarnForUnexpecedBlock = false;
170         bool makeCandidates = false;
171         ResetCanLoadFlags();
172         double zmiddle = 0;
173         double bfieldintegral = 0;
174         double roiA[4] = {0, 0, 0, 0};
175         double roiB[4] = {0, 0, 0, 0};
176         double chamberZ[6] = {0, 0, 0, 0, 0, 0};
177         
178         for (int i = 0; i < argc; i++)
179         {
180                 if (ArgumentAlreadyHandled(i, argv[i])) continue;
181
182                 if (strcmp( argv[i], "-zmiddle" ) == 0)
183                 {
184                         if (not fCanLoadZmiddle)
185                         {
186                                 HLTWarning("The Z coordinate for the middle of the dipole was already specified."
187                                         " Will replace previous value given by -zmiddle."
188                                 );
189                         }
190                         
191                         if ( argc <= i+1 )
192                         {
193                                 HLTError("The Z coordinate for the middle of the dipole was not specified." );
194                                 return -EINVAL;
195                         }
196                         
197                         char* cpErr = NULL;
198                         zmiddle = strtod(argv[i+1], &cpErr);
199                         if (cpErr == NULL or *cpErr != '\0')
200                         {
201                                 HLTError("Cannot convert '%s' to a valid floating point number.",
202                                         argv[i+1]
203                                 );
204                                 return -EINVAL;
205                         }
206                         
207                         fCanLoadZmiddle = false;  // Prevent loading from CDB.
208                         i++;
209                         continue;
210                 }
211         
212                 if (strcmp( argv[i], "-bfieldintegral" ) == 0)
213                 {
214                         if (not fCanLoadBL)
215                         {
216                                 HLTWarning("The magnetic field integral was already specified."
217                                         " Will replace previous value given by -bfieldintegral."
218                                 );
219                         }
220                         
221                         if ( argc <= i+1 )
222                         {
223                                 HLTError("The magnetic field integral was not specified." );
224                                 return -EINVAL;
225                         }
226                         
227                         char* cpErr = NULL;
228                         bfieldintegral = strtod(argv[i+1], &cpErr);
229                         if (cpErr == NULL or *cpErr != '\0')
230                         {
231                                 HLTError("Cannot convert '%s' to a valid floating point number.",
232                                         argv[i+1]
233                                 );
234                                 return -EINVAL;
235                         }
236                         
237                         fCanLoadBL = false;  // Prevent loading from CDB.
238                         i++;
239                         continue;
240                 }
241         
242                 if (strcmp(argv[i], "-a7") == 0 or strcmp(argv[i], "-a8") == 0 or
243                     strcmp(argv[i], "-a9") == 0 or strcmp(argv[i], "-a10") == 0
244                    )
245                 {
246                         int chamber = 7; int chamberIndex = 0;
247                         switch (argv[i][2])
248                         {
249                         case '7': chamber = 7; chamberIndex = 0; break;
250                         case '8': chamber = 8; chamberIndex = 1; break;
251                         case '9': chamber = 9; chamberIndex = 2; break;
252                         case '1': chamber = 10; chamberIndex = 3; break;
253                         }
254                         
255                         if (not fCanLoadA[chamberIndex])
256                         {
257                                 HLTWarning("The region of interest parameter 'A' for chamber %d was"
258                                         " already specified. Will replace previous value given by -a%d.",
259                                         chamber, chamber
260                                 );
261                         }
262                         
263                         if ( argc <= i+1 )
264                         {
265                                 HLTError("The region of interest parameter was not specified." );
266                                 return -EINVAL;
267                         }
268                         
269                         char* cpErr = NULL;
270                         roiA[chamberIndex] = strtod(argv[i+1], &cpErr);
271                         if (cpErr == NULL or *cpErr != '\0')
272                         {
273                                 HLTError("Cannot convert '%s' to a valid floating point number.",
274                                         argv[i+1]
275                                 );
276                                 return -EINVAL;
277                         }
278                         
279                         fCanLoadA[chamberIndex] = false;  // Prevent loading from CDB.
280                         i++;
281                         continue;
282                 }
283         
284                 if (strcmp(argv[i], "-b7") == 0 or strcmp(argv[i], "-b8") == 0 or
285                     strcmp(argv[i], "-b9") == 0 or strcmp(argv[i], "-b10") == 0
286                    )
287                 {
288                         int chamber = 7; int chamberIndex = 0;
289                         switch (argv[i][2])
290                         {
291                         case '7': chamber = 7; chamberIndex = 0; break;
292                         case '8': chamber = 8; chamberIndex = 1; break;
293                         case '9': chamber = 9; chamberIndex = 2; break;
294                         case '1': chamber = 10; chamberIndex = 3; break;
295                         }
296                         
297                         if (not fCanLoadB[chamberIndex])
298                         {
299                                 HLTWarning("The region of interest parameter 'B' for chamber %d was"
300                                         " already specified. Will replace previous value given by -b%d.",
301                                         chamber, chamber
302                                 );
303                         }
304                         
305                         if ( argc <= i+1 )
306                         {
307                                 HLTError("The region of interest parameter was not specified." );
308                                 return -EINVAL;
309                         }
310                         
311                         char* cpErr = NULL;
312                         roiB[chamberIndex] = strtod(argv[i+1], &cpErr);
313                         if (cpErr == NULL or *cpErr != '\0')
314                         {
315                                 HLTError("Cannot convert '%s' to a valid floating point number.",
316                                         argv[i+1]
317                                 );
318                                 return -EINVAL;
319                         }
320                         
321                         fCanLoadB[chamberIndex] = false;  // Prevent loading from CDB.
322                         i++;
323                         continue;
324                 }
325                 
326                 if (strcmp(argv[i], "-z7") == 0 or strcmp(argv[i], "-z8") == 0 or
327                     strcmp(argv[i], "-z9") == 0 or strcmp(argv[i], "-z10") == 0 or
328                     strcmp(argv[i], "-z11") == 0 or strcmp(argv[i], "-z13") == 0
329                    )
330                 {
331                         int chamber = 7; int chamberIndex = 0;
332                         switch (argv[i][2])
333                         {
334                         case '7': chamber = 7; chamberIndex = 0; break;
335                         case '8': chamber = 8; chamberIndex = 1; break;
336                         case '9': chamber = 9; chamberIndex = 2; break;
337                         case '1':
338                                 switch (argv[i][3])
339                                 {
340                                 case '0': chamber = 10; chamberIndex = 3; break;
341                                 case '1': chamber = 11; chamberIndex = 4; break;
342                                 case '3': chamber = 13; chamberIndex = 5; break;
343                                 }
344                                 break;
345                         }
346                         
347                         if (not fCanLoadZ[chamberIndex])
348                         {
349                                 HLTWarning("The nominal Z coordinate of chamber %d was already"
350                                         " specified. Will replace previous value given by -z%d.",
351                                         chamber, chamber
352                                 );
353                         }
354                         
355                         if ( argc <= i+1 )
356                         {
357                                 HLTError("The region of interest parameter was not specified." );
358                                 return -EINVAL;
359                         }
360                         
361                         char* cpErr = NULL;
362                         chamberZ[chamberIndex] = strtod(argv[i+1], &cpErr);
363                         if (cpErr == NULL or *cpErr != '\0')
364                         {
365                                 HLTError("Cannot convert '%s' to a valid floating point number.",
366                                         argv[i+1]
367                                 );
368                                 return -EINVAL;
369                         }
370                         
371                         fCanLoadZ[chamberIndex] = false;  // Prevent loading from CDB.
372                         i++;
373                         continue;
374                 }
375                 
376                 if (strcmp(argv[i], "-warn_on_unexpected_block") == 0)
377                 {
378                         fWarnForUnexpecedBlock = true;
379                         continue;
380                 }
381                 
382                 if (strcmp(argv[i], "-makecandidates") == 0)
383                 {
384                         makeCandidates = true;
385                         continue;
386                 }
387                 
388                 HLTError("Unknown option '%s'.", argv[i]);
389                 return -EINVAL;
390         }
391         
392         try
393         {
394                 fTracker = new AliHLTMUONMansoTrackerFSM();
395         }
396         catch (const std::bad_alloc&)
397         {
398                 HLTError("Could not allocate more memory for the tracker component.");
399                 return -ENOMEM;
400         }
401         fTracker->SetCallback(this);
402         fTracker->MakeCandidates(makeCandidates);
403         
404         // Set all the parameters that were found on the command line.
405         if (not fCanLoadZmiddle) AliHLTMUONCalculations::Zf(zmiddle);
406         if (not fCanLoadBL) AliHLTMUONCalculations::QBL(bfieldintegral);
407         if (not fCanLoadA[0]) fTracker->SetA7(roiA[0]);
408         if (not fCanLoadA[1]) fTracker->SetA8(roiA[1]);
409         if (not fCanLoadA[2]) fTracker->SetA9(roiA[2]);
410         if (not fCanLoadA[3]) fTracker->SetA10(roiA[3]);
411         if (not fCanLoadB[0]) fTracker->SetB7(roiB[0]);
412         if (not fCanLoadB[1]) fTracker->SetB8(roiB[1]);
413         if (not fCanLoadB[2]) fTracker->SetB9(roiB[2]);
414         if (not fCanLoadB[3]) fTracker->SetB10(roiB[3]);
415         if (not fCanLoadZ[0]) fTracker->SetZ7(chamberZ[0]);
416         if (not fCanLoadZ[1]) fTracker->SetZ8(chamberZ[1]);
417         if (not fCanLoadZ[2]) fTracker->SetZ9(chamberZ[2]);
418         if (not fCanLoadZ[3]) fTracker->SetZ10(chamberZ[3]);
419         if (not fCanLoadZ[4]) fTracker->SetZ11(chamberZ[4]);
420         if (not fCanLoadZ[5]) fTracker->SetZ13(chamberZ[5]);
421         
422         if (not DelaySetup())
423         {
424                 if (AtLeastOneCanLoadFlagsIsSet())
425                 {
426                         HLTInfo("Loading configuration parameters from CDB.");
427                         
428                         result = ReadConfigFromCDB();
429                         if (result != 0)
430                         {
431                                 // Error messages already generated in ReadConfigFromCDB.
432                                 FreeMemory(); // Make sure we cleanup to avoid partial initialisation.
433                                 return result;
434                         }
435                 }
436                 else
437                 {
438                         // Print the debug messages here since ReadConfigFromCDB does not get called,
439                         // in-which the debug messages would have been printed.
440                         HLTDebug("Using the following configuration parameters:");
441                         HLTDebug("                    Middle of dipole Z coordinate = %f cm", AliHLTMUONCalculations::Zf());
442                         HLTDebug("                          Magnetic field integral = %f T.m", AliHLTMUONCalculations::QBL());
443                         HLTDebug("   Region of interest parameter 'A' for chamber 7 = %f",    fTracker->GetA7());
444                         HLTDebug("   Region of interest parameter 'B' for chamber 7 = %f cm", fTracker->GetB7());
445                         HLTDebug("   Region of interest parameter 'A' for chamber 8 = %f",    fTracker->GetA8());
446                         HLTDebug("   Region of interest parameter 'B' for chamber 8 = %f cm", fTracker->GetB8());
447                         HLTDebug("   Region of interest parameter 'A' for chamber 9 = %f",    fTracker->GetA9());
448                         HLTDebug("   Region of interest parameter 'B' for chamber 9 = %f cm", fTracker->GetB9());
449                         HLTDebug("  Region of interest parameter 'A' for chamber 10 = %f",    fTracker->GetA10());
450                         HLTDebug("  Region of interest parameter 'B' for chamber 10 = %f cm", fTracker->GetB10());
451                         HLTDebug("               Nominal Z coordinate for chamber 7 = %f cm", fTracker->GetZ7());
452                         HLTDebug("               Nominal Z coordinate for chamber 8 = %f cm", fTracker->GetZ8());
453                         HLTDebug("               Nominal Z coordinate for chamber 9 = %f cm", fTracker->GetZ9());
454                         HLTDebug("              Nominal Z coordinate for chamber 10 = %f cm", fTracker->GetZ10());
455                         HLTDebug("              Nominal Z coordinate for chamber 11 = %f cm", fTracker->GetZ11());
456                         HLTDebug("              Nominal Z coordinate for chamber 13 = %f cm", fTracker->GetZ13());
457                 }
458                 
459                 ResetCanLoadFlags();  // From this point read all parameters from CDB.
460         }
461         
462         const int initArraySize = 10;
463         // Allocate some initial memory for the reconstructed hit arrays.
464         try
465         {
466                 fRecHitBlock[0] = new AliRecHitBlockInfo[initArraySize*4];
467         }
468         catch (const std::bad_alloc&)
469         {
470                 HLTError("Could not allocate more memory for the reconstructed hit arrays.");
471                 FreeMemory(); // Make sure we cleanup to avoid partial initialisation.
472                 return -ENOMEM;
473         }
474         // Only set the arrays' size once we have successfully allocated the memory for the arrays.
475         fRecHitBlockArraySize = initArraySize;
476         // Now we need to set the pointers fRecHitBlock[i] {i>0} relative to fRecHitBlock[0].
477         for (Int_t i = 1; i < 4; i++)
478         {
479                 fRecHitBlock[i] = fRecHitBlock[i-1] + fRecHitBlockArraySize;
480         }
481         // And reset the number of records actually stored in the arrays.
482         for (Int_t i = 0; i < 4; i++)
483         {
484                 fRecHitBlockCount[i] = 0;
485         }
486         
487         return 0;
488 }
489
490
491 int AliHLTMUONMansoTrackerFSMComponent::Reconfigure(
492                 const char* cdbEntry, const char* componentId
493         )
494 {
495         /// Inherited from AliHLTComponent. This method will reload CDB configuration
496         /// entries for this component from the CDB.
497         /// \param cdbEntry If this is NULL or equals "HLT/ConfigMUON/MansoTrackerFSM"
498         ///     then new configuration parameters are loaded, otherwise nothing is done.
499         /// \param componentId  The name of the component in the current chain.
500         
501         TString path = cdbEntry;
502         bool givenConfigPath = (path == AliHLTMUONConstants::MansoTrackerFSMCDBPath());
503         
504         if (cdbEntry == NULL or givenConfigPath)
505         {
506                 HLTInfo("Reading new configuration entries from CDB for component '%s'.", componentId);
507                 ResetCanLoadFlags();  // Make sure to allow reading all values from CDB.
508                 int result = ReadConfigFromCDB();
509                 if (result != 0) return result;
510         }
511         
512         return 0;
513 }
514
515
516 int AliHLTMUONMansoTrackerFSMComponent::ReadPreprocessorValues(const char* modules)
517 {
518         /// Inherited from AliHLTComponent. 
519         /// Updates the configuration of this component if HLT or ALL has been
520         /// specified in the 'modules' list.
521
522         TString mods = modules;
523         if (mods.Contains("ALL"))
524         {
525                 return Reconfigure(NULL, GetComponentID());
526         }
527         if (mods.Contains("HLT"))
528         {
529                 return Reconfigure(AliHLTMUONConstants::MansoTrackerFSMCDBPath(), GetComponentID());
530         }
531         return 0;
532 }
533
534
535 int AliHLTMUONMansoTrackerFSMComponent::ReadConfigFromCDB()
536 {
537         /// Reads this component's configuration parameters from the CDB.
538         /// These include the middle of the dipole Z coordinate (zmiddle), the
539         /// integrated magnetic field of the dipole, Z coordinates of the chambers
540         /// and the region of interest parameters used during the tracking.
541         /// \param setZmiddle Indicates if the zmiddle parameter should be set
542         ///       (default true).
543         /// \param setBL Indicates if the integrated magnetic field parameter should
544         ///       be set (default true).
545         /// \return 0 if no errors occured and negative error code compatible with
546         ///       the HLT framework on errors.
547
548         const char* pathToEntry = AliHLTMUONConstants::MansoTrackerFSMCDBPath();
549         
550         TMap* map = NULL;
551         int result = FetchTMapFromCDB(pathToEntry, map);
552         if (result != 0) return result;
553         
554         Double_t value = 0;
555         if (fCanLoadZmiddle)
556         {
557                 result = GetFloatFromTMap(map, "zmiddle", value, pathToEntry, "dipole middle Z coordinate");
558                 if (result != 0) return result;
559                 AliHLTMUONCalculations::Zf(value);
560         }
561         
562         if (fCanLoadBL)
563         {
564                 Double_t bfieldintegral;
565                 result = FetchFieldIntegral(bfieldintegral);
566                 if (result == 0)
567                 {
568                         AliHLTMUONCalculations::QBL(bfieldintegral);
569                 }
570                 else
571                 {
572                         HLTWarning("Failed to load the magnetic field integral from GRP information.");
573                         result = GetFloatFromTMap(map, "bfieldintegral", value, pathToEntry, "integrated magnetic field");
574                         if (result != 0) return result;
575                         HLTWarning(Form("Using deprecated magnetic field integral value of %f T.m.", value));
576                         AliHLTMUONCalculations::QBL(value);
577                 }
578         }
579         
580         if (fCanLoadA[0])
581         {
582                 result = GetFloatFromTMap(map, "roi_paramA_chamber7", value, pathToEntry, "chamber 7 region of interest 'A'");
583                 if (result != 0) return result;
584                 fTracker->SetA7(value);
585         }
586         if (fCanLoadA[1])
587         {
588                 result = GetFloatFromTMap(map, "roi_paramA_chamber8", value, pathToEntry, "chamber 8 region of interest 'A'");
589                 if (result != 0) return result;
590                 fTracker->SetA8(value);
591         }
592         if (fCanLoadA[2])
593         {
594                 result = GetFloatFromTMap(map, "roi_paramA_chamber9", value, pathToEntry, "chamber 9 region of interest 'A'");
595                 if (result != 0) return result;
596                 fTracker->SetA9(value);
597         }
598         if (fCanLoadA[3])
599         {
600                 result = GetFloatFromTMap(map, "roi_paramA_chamber10", value, pathToEntry, "chamber 10 region of interest 'A'");
601                 if (result != 0) return result;
602                 fTracker->SetA10(value);
603         }
604         
605         if (fCanLoadB[0])
606         {
607                 result = GetFloatFromTMap(map, "roi_paramB_chamber7", value, pathToEntry, "chamber 7 region of interest 'B'");
608                 if (result != 0) return result;
609                 fTracker->SetB7(value);
610         }
611         if (fCanLoadB[1])
612         {
613                 result = GetFloatFromTMap(map, "roi_paramB_chamber8", value, pathToEntry, "chamber 8 region of interest 'B'");
614                 if (result != 0) return result;
615                 fTracker->SetB8(value);
616         }
617         if (fCanLoadB[2])
618         {
619                 result = GetFloatFromTMap(map, "roi_paramB_chamber9", value, pathToEntry, "chamber 9 region of interest 'B'");
620                 if (result != 0) return result;
621                 fTracker->SetB9(value);
622         }
623         if (fCanLoadB[3])
624         {
625                 result = GetFloatFromTMap(map, "roi_paramB_chamber10", value, pathToEntry, "chamber 10 region of interest 'B'");
626                 if (result != 0) return result;
627                 fTracker->SetB10(value);
628         }
629         
630         if (fCanLoadZ[0])
631         {
632                 result = GetFloatFromTMap(map, "chamber7postion", value, pathToEntry, "nominal chamber 7 Z coordinate");
633                 if (result != 0) return result;
634                 fTracker->SetZ7(value);
635         }
636         if (fCanLoadZ[1])
637         {
638                 result = GetFloatFromTMap(map, "chamber8postion", value, pathToEntry, "nominal chamber 8 Z coordinate");
639                 if (result != 0) return result;
640                 fTracker->SetZ8(value);
641         }
642         if (fCanLoadZ[2])
643         {
644                 result = GetFloatFromTMap(map, "chamber9postion", value, pathToEntry, "nominal chamber 9 Z coordinate");
645                 if (result != 0) return result;
646                 fTracker->SetZ9(value);
647         }
648         if (fCanLoadZ[3])
649         {
650                 result = GetFloatFromTMap(map, "chamber10postion", value, pathToEntry, "nominal chamber 10 Z coordinate");
651                 if (result != 0) return result;
652                 fTracker->SetZ10(value);
653         }
654         if (fCanLoadZ[4])
655         {
656                 result = GetFloatFromTMap(map, "chamber11postion", value, pathToEntry, "nominal chamber 11 Z coordinate");
657                 if (result != 0) return result;
658                 fTracker->SetZ11(value);
659         }
660         if (fCanLoadZ[5])
661         {
662                 result = GetFloatFromTMap(map, "chamber13postion", value, pathToEntry, "nominal chamber 13 Z coordinate");
663                 if (result != 0) return result;
664                 fTracker->SetZ13(value);
665         }
666         
667         HLTDebug("Using the following configuration parameters:");
668         HLTDebug("                    Middle of dipole Z coordinate = %f cm", AliHLTMUONCalculations::Zf());
669         HLTDebug("                          Magnetic field integral = %f T.m", AliHLTMUONCalculations::QBL());
670         HLTDebug("   Region of interest parameter 'A' for chamber 7 = %f",    fTracker->GetA7());
671         HLTDebug("   Region of interest parameter 'B' for chamber 7 = %f cm", fTracker->GetB7());
672         HLTDebug("   Region of interest parameter 'A' for chamber 8 = %f",    fTracker->GetA8());
673         HLTDebug("   Region of interest parameter 'B' for chamber 8 = %f cm", fTracker->GetB8());
674         HLTDebug("   Region of interest parameter 'A' for chamber 9 = %f",    fTracker->GetA9());
675         HLTDebug("   Region of interest parameter 'B' for chamber 9 = %f cm", fTracker->GetB9());
676         HLTDebug("  Region of interest parameter 'A' for chamber 10 = %f",    fTracker->GetA10());
677         HLTDebug("  Region of interest parameter 'B' for chamber 10 = %f cm", fTracker->GetB10());
678         HLTDebug("               Nominal Z coordinate for chamber 7 = %f cm", fTracker->GetZ7());
679         HLTDebug("               Nominal Z coordinate for chamber 8 = %f cm", fTracker->GetZ8());
680         HLTDebug("               Nominal Z coordinate for chamber 9 = %f cm", fTracker->GetZ9());
681         HLTDebug("              Nominal Z coordinate for chamber 10 = %f cm", fTracker->GetZ10());
682         HLTDebug("              Nominal Z coordinate for chamber 11 = %f cm", fTracker->GetZ11());
683         HLTDebug("              Nominal Z coordinate for chamber 13 = %f cm", fTracker->GetZ13());
684         
685         return 0;
686 }
687
688
689 int AliHLTMUONMansoTrackerFSMComponent::DoDeinit()
690 {
691         ///
692         /// Inherited from AliHLTComponent. Performs a cleanup of the component.
693         ///
694         
695         HLTInfo("Deinitialising dHLT manso tracker FSM component.");
696         FreeMemory();
697         return 0;
698 }
699
700
701 int AliHLTMUONMansoTrackerFSMComponent::DoEvent(
702                 const AliHLTComponentEventData& evtData,
703                 const AliHLTComponentBlockData* blocks,
704                 AliHLTComponentTriggerData& trigData,
705                 AliHLTUInt8_t* outputPtr,
706                 AliHLTUInt32_t& size,
707                 AliHLTComponentBlockDataList& outputBlocks
708         )
709 {
710         ///
711         /// Inherited from AliHLTProcessor. Processes the new event data.
712         ///
713         
714         // Initialise the configuration parameters from CDB if we were
715         // requested to initialise only when the first event was received.
716         if (DelaySetup())
717         {
718                 // Load the configuration paramters from CDB if they have not
719                 // been given on the command line.
720                 if (AtLeastOneCanLoadFlagsIsSet())
721                 {
722                         HLTInfo("Loading configuration parameters from CDB.");
723                         int result = ReadConfigFromCDB();
724                         if (result != 0) return result;
725                 }
726                 
727                 DoneDelayedSetup();
728                 ResetCanLoadFlags();  // From this point read all parameters from CDB.
729         }
730         
731         Reset();
732         AliHLTUInt32_t specification = 0;  // Contains the output data block spec bits.
733         
734         // Resize the rec hit arrays if we possibly will need more space.
735         // To guarantee that they will not overflow we need to make sure each
736         // array is at least as big as the number of input data blocks.
737         if (fRecHitBlockArraySize < evtData.fBlockCnt)
738         {
739                 // Release the old memory block and allocate more memory.
740                 if (fRecHitBlock[0] != NULL)
741                 {
742                         delete [] fRecHitBlock[0];
743                 }
744                 
745                 // Reset the number of records actually stored in the arrays.
746                 for (Int_t i = 0; i < 4; i++)
747                 {
748                         fRecHitBlockCount[i] = 0;
749                 }
750                 
751                 try
752                 {
753                         fRecHitBlock[0] = new AliRecHitBlockInfo[evtData.fBlockCnt*4];
754                 }
755                 catch (const std::bad_alloc&)
756                 {
757                         HLTError("Could not allocate more memory for the reconstructed hit arrays.");
758                         // Ok so now we need to clear all the pointers because we actually
759                         // deleted the memory.
760                         fRecHitBlockArraySize = 0;
761                         for (Int_t i = 0; i < 4; i++)
762                         {
763                                 fRecHitBlock[i] = NULL;
764                         }
765                         if (DumpDataOnError()) DumpEvent(evtData, blocks, trigData, outputPtr, size, outputBlocks);
766                         return -ENOMEM;
767                 }
768                 // Only set the arrays' size once we have successfully allocated the memory for the arrays.
769                 fRecHitBlockArraySize = evtData.fBlockCnt;
770                 // Now we need to set the pointers fRecHitBlock[i] {i>0} relative to fRecHitBlock[0].
771                 for (Int_t i = 1; i < 4; i++)
772                 {
773                         fRecHitBlock[i] = fRecHitBlock[i-1] + fRecHitBlockArraySize;
774                 }
775         }
776         
777         AliHLTMUONMansoTracksBlockWriter block(outputPtr, size);
778         fBlock = &block;
779         
780         if (not block.InitCommonHeader())
781         {
782                 Logging(kHLTLogError,
783                         "AliHLTMUONMansoTrackerFSMComponent::DoEvent",
784                         "Buffer overflow",
785                         "The buffer is only %d bytes in size. We need a minimum of %d bytes.",
786                         size, sizeof(AliHLTMUONMansoTracksBlockWriter::HeaderType)
787                 );
788                 if (DumpDataOnError()) DumpEvent(evtData, blocks, trigData, outputPtr, size, outputBlocks);
789                 size = 0; // Important to tell framework that nothing was generated.
790                 return -ENOBUFS;
791         }
792
793         // Loop over all input blocks in the event and add the ones that contain
794         // reconstructed hits into the hit buffers. The blocks containing trigger
795         // records are ignored for now and will be processed later.
796         for (AliHLTUInt32_t n = 0; n < evtData.fBlockCnt; n++)
797         {
798                 HLTDebug("Handling block: %u, with fDataType = '%s', fPtr = %p and fSize = %u bytes.",
799                         n, DataType2Text(blocks[n].fDataType).c_str(), blocks[n].fPtr, blocks[n].fSize
800                 );
801                 
802                 if (blocks[n].fDataType == AliHLTMUONConstants::RecHitsBlockDataType())
803                 {
804                         specification |= blocks[n].fSpecification;
805                         
806                         AliHLTMUONRecHitsBlockReader inblock(blocks[n].fPtr, blocks[n].fSize);
807                         if (not BlockStructureOk(inblock))
808                         {
809                                 if (DumpDataOnError()) DumpEvent(evtData, blocks, trigData, outputPtr, size, outputBlocks);
810                                 continue;
811                         }
812                         
813                         if (inblock.Nentries() != 0)
814                                 AddRecHits(blocks[n].fSpecification, inblock.GetArray(), inblock.Nentries());
815                         else
816                         {
817                                 Logging(kHLTLogDebug,
818                                         "AliHLTMUONMansoTrackerFSMComponent::DoEvent",
819                                         "Block empty",
820                                         "Received a reconstructed hits data block which contains no entries."
821                                 );
822                         }
823                 }
824                 else if (blocks[n].fDataType != AliHLTMUONConstants::TriggerRecordsBlockDataType())
825                 {
826                         // Log a message indicating that we got a data block that we
827                         // do not know how to handle.
828                         if (fWarnForUnexpecedBlock)
829                                 HLTWarning("Received a data block of a type we cannot handle: '%s', spec: 0x%X",
830                                         DataType2Text(blocks[n].fDataType).c_str(), blocks[n].fSpecification
831                                 );
832 #ifdef __DEBUG
833                         else
834                                 HLTDebug("Received a data block of a type we cannot handle: '%s', spec: 0x%X",
835                                         DataType2Text(blocks[n].fDataType).c_str(), blocks[n].fSpecification
836                                 );
837 #endif
838                 }
839         }
840   
841         // Again loop over all input blocks in the event, but this time look for
842         // the trigger record blocks and process these.
843         for (AliHLTUInt32_t n = 0; n < evtData.fBlockCnt; n++)
844         {
845                 if (blocks[n].fDataType != AliHLTMUONConstants::TriggerRecordsBlockDataType())
846                         continue;
847                 
848                 AliHLTMUONTriggerRecordsBlockReader inblock(blocks[n].fPtr, blocks[n].fSize);
849                 if (not BlockStructureOk(inblock))
850                 {
851                         if (DumpDataOnError()) DumpEvent(evtData, blocks, trigData, outputPtr, size, outputBlocks);
852                         continue;
853                 }
854                 
855                 DebugTrace("Processing a trigger block with "
856                         << inblock.Nentries() << " entries."
857                 );
858                 
859                 specification |= blocks[n].fSpecification;
860                 
861                 for (AliHLTUInt32_t i = 0; i < inblock.Nentries(); i++)
862                 {
863                         fTracker->FindTrack(inblock[i]);
864                         
865                         // Reset the tracker so that we do not double count tracks.
866                         fTracker->Reset();
867                 }
868         }
869         
870         AliHLTComponentBlockData bd;
871         FillBlockData(bd);
872         bd.fPtr = outputPtr;
873         bd.fOffset = 0;
874         bd.fSize = block.BytesUsed();
875         bd.fDataType = AliHLTMUONConstants::MansoTracksBlockDataType();
876         bd.fSpecification = specification;
877         outputBlocks.push_back(bd);
878         AliHLTUInt32_t totalSize = block.BytesUsed();
879         
880         if (fTracker->MakeCandidates())
881         {
882                 AliHLTMUONMansoCandidatesBlockWriter candidatesBlock(outputPtr+totalSize, size-totalSize);
883                 if (not candidatesBlock.InitCommonHeader())
884                 {
885                         HLTError("Buffer overflowed. There are only %d bytes left in the buffer,"
886                                 " but we need a minimum of %d bytes.",
887                                 size, sizeof(AliHLTMUONMansoCandidatesBlockWriter::HeaderType)
888                         );
889                         if (DumpDataOnError()) DumpEvent(evtData, blocks, trigData, outputPtr, size, outputBlocks);
890                         size = 0; // Important to tell framework that nothing was generated.
891                         return -ENOBUFS;
892                 }
893                 
894                 // Fill in the output block buffer.
895                 candidatesBlock.SetNumberOfEntries(fTracker->TrackCandidatesCount());
896                 for (AliHLTUInt32_t i = 0; i < fTracker->TrackCandidatesCount(); ++i)
897                 {
898                         candidatesBlock[i] = fTracker->TrackCandidates()[i];
899                 }
900                 
901                 fTracker->ZeroTrackCandidatesList();
902                 
903                 AliHLTComponentBlockData bdc;
904                 FillBlockData(bdc);
905                 bdc.fPtr = outputPtr;
906                 bdc.fOffset = totalSize;
907                 bdc.fSize = candidatesBlock.BytesUsed();
908                 bdc.fDataType = AliHLTMUONConstants::MansoCandidatesBlockDataType();
909                 bdc.fSpecification = specification;
910                 outputBlocks.push_back(bdc);
911                 totalSize += candidatesBlock.BytesUsed();
912         }
913         
914         size = totalSize;
915         return 0;
916 }
917
918
919 void AliHLTMUONMansoTrackerFSMComponent::Reset()
920 {
921         ///
922         /// Reset the track count and reconstructed hit data block arrays.
923         ///
924         
925         DebugTrace("Resetting AliHLTMUONMansoTrackerFSMComponent.");
926
927         //fTracker->Reset();  // Not necessary here because it is done after every FindTrack call.
928         fTrackCount = 0;
929         fBlock = NULL;  // Do not delete. Already done implicitly at the end of DoEvent.
930         for (int i = 0; i < 4; i++)
931         {
932                 fRecHitBlockCount[i] = 0;
933         }
934 }
935
936
937 void AliHLTMUONMansoTrackerFSMComponent::FreeMemory()
938 {
939         /// Deletes any objects and arrays allocated by this component and releases
940         /// the memory used. This is called as a helper routine by the init and deinit
941         /// methods. If some or all of the object pointers are already NULL then
942         /// nothing is done for those. This method guarantees that all the relevant
943         /// pointers will be NULL after returning from this method.
944
945         if (fTracker != NULL)
946         {
947                 delete fTracker;
948                 fTracker = NULL;
949         }
950         
951         // Remember that only fRecHitBlock[0] stores the pointer to the allocated memory.
952         // The other pointers are just reletive to this.
953         if (fRecHitBlock[0] != NULL)
954                 delete [] fRecHitBlock[0];
955         
956         fRecHitBlockArraySize = 0;
957         for (Int_t i = 0; i < 4; i++)
958         {
959                 fRecHitBlockCount[i] = 0;
960                 fRecHitBlock[i] = NULL;
961         }
962 }
963
964
965 void AliHLTMUONMansoTrackerFSMComponent::AddRecHits(
966                 AliHLTUInt32_t specification,
967                 const AliHLTMUONRecHitStruct* recHits,
968                 AliHLTUInt32_t count
969         )
970 {
971         ///
972         /// Adds a new reconstructed hit data block to the internal list of blocks
973         /// for the tracker to process.
974         /// These lists will later be used when the tracker requests them through
975         /// the callback method 'RequestClusters'.
976         ///
977         
978         DebugTrace("AliHLTMUONMansoTrackerFSMComponent::AddRecHits called with specification = 0x"
979                  << std::hex << specification << std::dec << " and count = "
980                  << count << " rec hits."
981         );
982         
983         AliHLTUInt8_t chamberMap[20] = {
984                 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10
985         };
986         
987         // Identify the chamber the rec hits came from using the specifications field.
988         bool gotDataFromDDL[22];
989         AliHLTMUONUtils::UnpackSpecBits(specification, gotDataFromDDL);
990                 
991         AliHLTInt8_t chamber = -1;
992         for (int i = 0; i < 20; i++)
993         {
994                 if (not gotDataFromDDL[i]) continue;
995                 if (7 <= chamberMap[i] and chamberMap[i] <= 10)
996                 {
997                         if (chamber != -1 and chamber != chamberMap[i])
998                         {
999                                 Logging(kHLTLogError,
1000                                         "AliHLTMUONMansoTrackerFSMComponent::AddRecHits",
1001                                         "Invalid block",
1002                                         "Received a data block with data from multiple chambers."
1003                                           " This component cannot handle such a case."
1004                                 );
1005                                 return;
1006                         }
1007                         else
1008                                 chamber = chamberMap[i];
1009                 }
1010                 else
1011                 {
1012                         if (fWarnForUnexpecedBlock)
1013                         {
1014                                 Logging(kHLTLogWarning,
1015                                         "AliHLTMUONMansoTrackerFSMComponent::AddRecHits",
1016                                         "Invalid chamber",
1017                                         "Received a data block with data from chamber %d"
1018                                          " which is outside the expected range: [7..10].",
1019                                         chamberMap[i]
1020                                 );
1021                         }
1022                         return;
1023                 }
1024         }
1025         
1026         // Make sure we got one chamber number.
1027         if (chamber < 7 or 10 < chamber)
1028         {
1029                 Logging(kHLTLogError,
1030                         "AliHLTMUONMansoTrackerFSMComponent::AddRecHits",
1031                         "Invalid block",
1032                         "Received a reconstructed hit data block with a null specification."
1033                          " Cannot know which chamber the data comes from."
1034                 );
1035                 return;
1036         }
1037         
1038         DebugTrace("Added " << count << " reconstructed hits from chamber "
1039                 << (int)chamber << " to the internal arrays."
1040         );
1041         
1042         assert( fRecHitBlockCount[chamber-7] < fRecHitBlockArraySize );
1043         AliRecHitBlockInfo info(count, recHits);
1044         fRecHitBlock[chamber-7][fRecHitBlockCount[chamber-7]] = info;
1045         fRecHitBlockCount[chamber-7]++;
1046 }
1047
1048
1049 void AliHLTMUONMansoTrackerFSMComponent::ResetCanLoadFlags()
1050 {
1051         /// Resets all the fCanLoad* flags to true. This enables loading of all
1052         /// those CDB entries in the method ReadConfigFromCDB.
1053         
1054         fCanLoadZmiddle = true;
1055         fCanLoadBL = true;
1056         for (int i = 0; i < 4; i++)
1057         {
1058                 fCanLoadA[i] = true;
1059                 fCanLoadB[i] = true;
1060         }
1061         for (int i = 0; i < 6; i++)
1062         {
1063                 fCanLoadZ[i] = true;
1064         }
1065 }
1066
1067
1068 bool AliHLTMUONMansoTrackerFSMComponent::AtLeastOneCanLoadFlagsIsSet() const
1069 {
1070         /// Returns true if at least one fCanLoad* flag was true and false otherwise.
1071
1072         if (fCanLoadZmiddle or fCanLoadBL) return true;
1073         for (int i = 0; i < 4; i++)
1074         {
1075                 if (fCanLoadA[i]) return true;
1076                 if (fCanLoadB[i]) return true;
1077         }
1078         for (int i = 0; i < 6; i++)
1079         {
1080                 if (fCanLoadZ[i]) return true;
1081         }
1082         return false;
1083 }
1084
1085
1086 void AliHLTMUONMansoTrackerFSMComponent::RequestClusters(
1087                 AliHLTMUONMansoTrackerFSM* tracker,
1088                 AliHLTFloat32_t left, AliHLTFloat32_t right,
1089                 AliHLTFloat32_t bottom, AliHLTFloat32_t top,
1090                 AliHLTMUONChamberName chamber, const void* tag
1091         )
1092 {
1093         ///
1094         /// Inherited from AliHLTMUONMansoTrackerFSMCallback.
1095         /// This is the call back method used by the tracker algorithm to request
1096         /// clusters on a certain chamber.
1097         ///
1098
1099         DebugTrace("AliHLTMUONMansoTracker::RequestClusters(chamber = " << chamber << ")");
1100         void* ctag = const_cast<void*>(tag);
1101         int chNo = -1;
1102         AliHLTUInt32_t recHitsCount = 0;
1103         AliRecHitBlockInfo* recHitsBlock = NULL;
1104         switch (chamber)
1105         {
1106         case kChamber7:
1107                 recHitsCount = fRecHitBlockCount[0];
1108                 recHitsBlock = fRecHitBlock[0];
1109                 chNo = 7;
1110                 break;
1111
1112         case kChamber8:
1113                 recHitsCount = fRecHitBlockCount[1];
1114                 recHitsBlock = fRecHitBlock[1];
1115                 chNo = 8;
1116                 break;
1117
1118         case kChamber9:
1119                 recHitsCount = fRecHitBlockCount[2];
1120                 recHitsBlock = fRecHitBlock[2];
1121                 chNo = 9;
1122                 break;
1123
1124         case kChamber10:
1125                 recHitsCount = fRecHitBlockCount[3];
1126                 recHitsBlock = fRecHitBlock[3];
1127                 chNo = 10;
1128                 break;
1129
1130         default: return;
1131         }
1132         
1133         DebugTrace("Returning requested hits for chamber " << chNo << ":");
1134         for (AliHLTUInt32_t i = 0; i < recHitsCount; i++)
1135         for (AliHLTUInt32_t j = 0; j < recHitsBlock[i].Count(); j++)
1136         {
1137                 const AliHLTMUONRecHitStruct* hit = &(recHitsBlock[i].Data()[j]);
1138                 if (left < hit->fX and hit->fX < right and bottom < hit->fY and hit->fY < top)
1139                         tracker->ReturnClusters(ctag, hit, 1);
1140         }
1141         DebugTrace("Done returning hits from chamber " << chNo << ".");
1142         tracker->EndOfClusters(ctag);
1143 }
1144
1145
1146 void AliHLTMUONMansoTrackerFSMComponent::EndOfClusterRequests(
1147                 AliHLTMUONMansoTrackerFSM* /*tracker*/
1148         )
1149 {
1150         ///
1151         /// Inherited from AliHLTMUONMansoTrackerFSMCallback.
1152         /// Nothing special to do here.
1153         ///
1154         
1155         DebugTrace("End of cluster requests.");
1156 }
1157
1158
1159 void AliHLTMUONMansoTrackerFSMComponent::FoundTrack(AliHLTMUONMansoTrackerFSM* tracker)
1160 {
1161         ///
1162         /// Inherited from AliHLTMUONMansoTrackerFSMCallback.
1163         /// This is the call back method used by the tracker algorithm to declare
1164         /// that a new track has been found.
1165         ///
1166         
1167         DebugTrace("AliHLTMUONMansoTrackerFSMComponent::FoundTrack()");
1168         
1169         AliHLTMUONMansoTracksBlockWriter* block =
1170                 reinterpret_cast<AliHLTMUONMansoTracksBlockWriter*>(fBlock);
1171         
1172         AliHLTMUONMansoTrackStruct newTrack;
1173         tracker->FillTrackData(newTrack);
1174         
1175         // The indicies of the duplicate tracks. If set to block->Nentries() then
1176         // this indicates the index is not used.
1177         AliHLTUInt32_t dup1 = block->Nentries();
1178         AliHLTUInt32_t dup2 = block->Nentries();
1179         
1180         // Check if there are any tracks that use the same hits as the one found.
1181         // If there are, then use the one that has the highest pT.
1182         // There will be at most 2 duplicate tracks.
1183         for (AliHLTUInt32_t i = 0; i < block->Nentries(); i++)
1184         {
1185                 AliHLTMUONMansoTrackStruct& track = (*block)[i];
1186                 bool hasNoDuplicates = true;
1187                 for (AliHLTUInt32_t j = 0; j < 4; j++)
1188                 {
1189                         if (track.fHit[j] == AliHLTMUONConstants::NilRecHitStruct()) continue;
1190                         if (newTrack.fHit[j] == AliHLTMUONConstants::NilRecHitStruct()) continue;
1191                         if (track.fHit[j] == newTrack.fHit[j])
1192                         {
1193                                 hasNoDuplicates = false;
1194                                 break;
1195                         }
1196                 }
1197                 if (hasNoDuplicates) continue;
1198                 
1199                 if (dup1 == block->Nentries())
1200                 {
1201                         dup1 = i;
1202                 }
1203                 else if (dup2 == block->Nentries())
1204                 {
1205                         dup2 = i;
1206                 }
1207                 else
1208                 {
1209                         HLTError("Found more than 2 tracks with duplicate hits. This is completely unexpected. Something is seriously wrong!");
1210                 }
1211         }
1212         
1213         if (dup1 != block->Nentries() and dup2 != block->Nentries())
1214         {
1215                 // In this case we found 2 duplicate entries.
1216                 // Figure out which one has the highest pT and keep only that one.
1217                 AliHLTMUONMansoTrackStruct& track1 = (*block)[dup1];
1218                 AliHLTMUONMansoTrackStruct& track2 = (*block)[dup2];
1219                 double newPt = sqrt(newTrack.fPx * newTrack.fPx + newTrack.fPy * newTrack.fPy);
1220                 double dupPt1 = sqrt(track1.fPx * track1.fPx + track1.fPy * track1.fPy);
1221                 double dupPt2 = sqrt(track2.fPx * track2.fPx + track2.fPy * track2.fPy);
1222                 
1223                 if (newPt >= dupPt1 and newPt >= dupPt2)
1224                 {
1225                         // The new track must replace both existing tracks.
1226                         track1 = newTrack;
1227                         track2 = (*block)[block->Nentries()-1];
1228                 }
1229                 else if (dupPt1 >= newPt and dupPt1 >= dupPt2)
1230                 {
1231                         // track1 has the highest pT so ignore the new track and delete track2.
1232                         track2 = (*block)[block->Nentries()-1];
1233                 }
1234                 else
1235                 {
1236                         // In this case track2 must have the highest pT so ignore the new
1237                         // track and delete track1.
1238                         track1 = (*block)[block->Nentries()-1];
1239                 }
1240                 
1241                 // Decrement the number of entries because we deleted a track.
1242                 assert(fTrackCount > 0);
1243                 assert(block->Nentries() > 0);
1244                 block->SetNumberOfEntries(block->Nentries()-1);
1245                 fTrackCount--;
1246         }
1247         else if (dup1 != block->Nentries())
1248         {
1249                 // Only one track with duplicate hits found.
1250                 // See if the new track has higher pT. If it does then replace the
1251                 // exisiting track, otherwise ignore the new track.
1252                 AliHLTMUONMansoTrackStruct& track1 = (*block)[dup1];
1253                 double newPt = sqrt(newTrack.fPx * newTrack.fPx + newTrack.fPy * newTrack.fPy);
1254                 double dupPt1 = sqrt(track1.fPx * track1.fPx + track1.fPy * track1.fPy);
1255                 if (newPt >= dupPt1)
1256                 {
1257                         track1 = newTrack;
1258                 }
1259         }
1260         else
1261         {
1262                 // No track found with duplicate hits so we can add the new track as it is.
1263                 AliHLTMUONMansoTrackStruct* track = block->AddEntry();
1264                 if (track == NULL)
1265                 {
1266                         Logging(kHLTLogError,
1267                                 "AliHLTMUONMansoTrackerFSMComponent::FoundTrack",
1268                                 "Buffer overflow",
1269                                 "We have overflowed the output buffer for Manso track data."
1270                                 " The output buffer size is only %d bytes.",
1271                                 block->BufferSize()
1272                         );
1273                         return;
1274                 }
1275         
1276                 fTrackCount++;
1277                 *track = newTrack;
1278                 DebugTrace("\tAdded new track: " << *track);
1279         }
1280 }
1281
1282
1283 void AliHLTMUONMansoTrackerFSMComponent::NoTrackFound(AliHLTMUONMansoTrackerFSM* /*tracker*/)
1284 {
1285         ///
1286         /// Inherited from AliHLTMUONMansoTrackerFSMCallback.
1287         /// Nothing special to do here.
1288         ///
1289         
1290         DebugTrace("No track found.");
1291 }
1292